From: Robert Pengelly Date: Mon, 3 Jun 2024 03:36:56 +0000 (+0100) Subject: New server X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=0dc7366b10e5a160d153305dfe6c80c34e3ac10b;p=xar.git New server --- 0dc7366b10e5a160d153305dfe6c80c34e3ac10b diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/Makefile.pdw b/Makefile.pdw new file mode 100644 index 0000000..6dbb921 --- /dev/null +++ b/Makefile.pdw @@ -0,0 +1,22 @@ +#****************************************************************************** +# @file Makefile.pdw +#****************************************************************************** +AS=aswin +CC=gccwin +LD=ldwin + +COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib -D__WIN32__ -D__NOBIVA__ -D__PDOS__ +COBJ=append.o ar.o conv.o delete.o display.o extract.o lib.o ranlib.o replace.o report.o + +all: clean xar.exe + +xar.exe: $(COBJ) + $(LD) -s -o xar.exe ../pdos/pdpclib/w32start.o $(COBJ) ../pdos/pdpclib/msvcrt.a + +.c.o: + $(CC) $(COPTS) $< + $(AS) -o $@ $*.s + rm -f $*.s + +clean: + rm -f *.o xar.exe diff --git a/Makefile.s64 b/Makefile.s64 new file mode 100644 index 0000000..0ccc969 --- /dev/null +++ b/Makefile.s64 @@ -0,0 +1,24 @@ +CPP=pdcc +CC=cc64 +CFLAGS= +LD=pdld +LDFLAGS=-s -nostdlib --no-insert-timestamp --image-base 0x400000 +AS=pdas --oformat coff --64 +COPTS=-I. -I../pdos/pdpclib -D__WIN32__ -D__NOBIVA__ -D__64BIT__ -D__CC64__ + +OBJS=append.obj ar.obj conv.obj delete.obj display.obj extract.obj lib.obj ranlib.obj replace.obj report.obj + +TARGET=xar.exe + +all: clean $(TARGET) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $(TARGET) ../pdos/pdpclib/w32start.obj $(OBJS) ../pdos/pdpclib/msvcrt.lib + +.c.obj: + $(CPP) -E $(COPTS) -o $*.i $< + $(CC) -c -out:$@ $*.i + rm -f $*.i + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Makefile.std b/Makefile.std new file mode 100644 index 0000000..a7f73c5 --- /dev/null +++ b/Makefile.std @@ -0,0 +1,19 @@ +AS=pdas --oformat coff +CC=gccwin +LD=pdld + +COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib -D__WIN32__ -D__NOBIVA__ -D__PDOS__ +COBJ=append.o ar.o conv.o delete.o display.o extract.o lib.o ranlib.o replace.o report.o + +all: clean xar.exe + +xar.exe: $(COBJ) + $(LD) -s -nostdlib --no-insert-timestamp -o xar.exe ../pdos/pdpclib/w32start.o $(COBJ) ../pdos/pdpclib/msvcrt.a + +.c.o: + $(CC) $(COPTS) $< + $(AS) -o $@ $*.s + rm -f $*.s + +clean: + rm -f *.o xar.exe diff --git a/Makefile.unix b/Makefile.unix new file mode 100644 index 0000000..f4f5b54 --- /dev/null +++ b/Makefile.unix @@ -0,0 +1,30 @@ +#****************************************************************************** +# @file Makefile.unix +#****************************************************************************** +SRCDIR ?= $(CURDIR) +VPATH := $(SRCDIR) + +CC := gcc +CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90 + +ifneq ($(shell uname -s),Darwin) +CFLAGS += -m32 +endif + +CSRC := append.c ar.c conv.c delete.c display.c extract.c lib.c ranlib.c replace.c report.c + +ifeq ($(OS), Windows_NT) +all: xar.exe + +xar.exe: $(CSRC) + $(CC) $(CFLAGS) -o $@ $^ +else +all: xar + +xar: $(CSRC) + $(CC) $(CFLAGS) -o $@ $^ +endif + +clean: + if [ -f xar.exe ]; then rm -rf xar.exe; fi + if [ -f xar ]; then rm -rf xar; fi diff --git a/Makefile.vsc b/Makefile.vsc new file mode 100644 index 0000000..b9fe4d6 --- /dev/null +++ b/Makefile.vsc @@ -0,0 +1,17 @@ +CC=cl +LD=cl + +COPTS=-c -nologo -O2 -I. +COBJ=append.obj ar.obj conv.obj delete.obj display.obj \ + extract.obj lib.obj ranlib.obj replace.obj report.obj + +all: clean xar.exe + +xar.exe: $(COBJ) + $(LD) -nologo -Fexar.exe $(COBJ) + +.c.obj: + $(CC) $(COPTS) -Fo$@ $< + +clean: + rm -f *.obj xar.exe diff --git a/Makefile.w32 b/Makefile.w32 new file mode 100644 index 0000000..ad0e650 --- /dev/null +++ b/Makefile.w32 @@ -0,0 +1,19 @@ +#****************************************************************************** +# @file Makefile.w32 +#****************************************************************************** +SRCDIR ?= $(CURDIR) +VPATH := $(SRCDIR) + +CC := gcc +CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -m32 -pedantic -std=c90 + +CSRC := append.c ar.c conv.c delete.c display.c extract.c lib.c ranlib.c replace.c report.c + +all: xar.exe + +clean: + if exist xar.exe ( del /q xar.exe ) + if exist xar ( del /q xar ) + +xar.exe: $(CSRC) + $(CC) $(CFLAGS) -o $@ $^ diff --git a/Makefile.wcd b/Makefile.wcd new file mode 100644 index 0000000..8d1c0ca --- /dev/null +++ b/Makefile.wcd @@ -0,0 +1,21 @@ +#****************************************************************************** +# @file Makefile.wcd +# +# Produce MSDOS executables links with PDPCLIB created by makefile.wcd +#****************************************************************************** +CC=wcl +COPTS=-ecc -q -w -c -ml -zl -D__MSDOS__ -D__PDOS__ -fpi87 -s -zdp -zu -I. -I..\pdos\pdpclib + +all: clean xar.exe + +xar.exe: append.obj ar.obj conv.obj delete.obj display.obj extract.obj lib.obj ranlib,obj replace.obj report.obj + wlink File ar.obj Name xar.exe Form dos Library temp.lib,..\pdos\pdpclib\watcom.lib Option quiet,map + +.c.obj: + $(CC) $(COPTS) $< + wlib -b -q temp +$*.obj + +clean: + rm -f *.obj + rm -f xar.exe + rm -f temp.lib diff --git a/README.md b/README.md new file mode 100644 index 0000000..9433d5b --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +All source code is Public Domain. + +## Obtain the source code + + git clone https://git.candlhat.org/xar.git + +## Building + + BSD: + + Make sure you have gcc and gmake installed then run gmake -f Makefile.unix. + + Linux: + + Make sure you have gcc and make installed then run make -f Makefile.unix. + + macOS: + + Make sure you have xcode command line tools installed then run make -f Makefile.unix. + + Windows: + + Make sure you have mingw installed and the location within your PATH variable then run mingw32-make.exe -f Makefile.w32. diff --git a/append.c b/append.c new file mode 100644 index 0000000..bab69e9 --- /dev/null +++ b/append.c @@ -0,0 +1,153 @@ +/****************************************************************************** + * @file append.c + *****************************************************************************/ +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" + +void append (FILE *ofp, char *fname) { + + unsigned char aout_magic[2]; + FILE *tfp; + + struct ar_header header; + char temp[17]; + + char *p, *name = fname, *contents; + long bytes, len, read; + + int need_newline = 0; + int valid = 0; + + if ((tfp = fopen (fname, "r+b")) == NULL) { + + report_at (program_name, 0, REPORT_ERROR, "failed to open %s", fname); + return; + + } + + if (fread (aout_magic, 2, 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading %s", fname); + return; + + } + + valid = ((aout_magic[0] == 0x07 && aout_magic[1] == 0x01) || (aout_magic[0] == 0x4C && aout_magic[1] == 0x01) || (aout_magic[0] == 0x64 && aout_magic[1] == 0x86)); + + if (!valid) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "%s is not a valid a.out or coff object", fname); + return; + + } + + memset (temp, 0x20, 16); + temp[0] = '0'; + + if ((p = strrchr (fname, '/'))) { + name = (p + 1); + } + + len = strlen (name); + + if (len > 16) { + len = 16; + } + + memcpy (header.name, name, len); + + while (len < 16) { + header.name[len++] = 0x20; + } + + memcpy (header.mtime, temp, 12); + memcpy (header.owner, temp, 6); + memcpy (header.group, temp, 6); + memcpy (header.mode, temp, 8); + + fseek (tfp, 0, SEEK_END); + bytes = ftell (tfp); + + len = sprintf (temp, "%ld", bytes); + temp[len] = 0x20; + + memcpy (header.size, temp, 10); + + header.endsig[0] = 0x60; + header.endsig[1] = 0x0A; + + need_newline = (bytes % 2); + + if (fwrite (&header, sizeof (header), 1, ofp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header"); + return; + + } + + contents = xmalloc (512); + fseek (tfp, 0, SEEK_SET); + + for (;;) { + + if (bytes == 0 || feof (tfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, tfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading %s", fname); + return; + + } + + bytes -= read; + + if (fwrite (contents, read, 1, ofp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing %s to archive", fname); + return; + + } + + } + + free (contents); + + if (need_newline) { + + temp[0] = 0x0A; + + if (fwrite (temp, 1, 1, ofp) != 1) { + + fclose (tfp); + exit (EXIT_FAILURE); + + } + + } + + fclose (tfp); + +} diff --git a/ar.c b/ar.c new file mode 100644 index 0000000..65b823e --- /dev/null +++ b/ar.c @@ -0,0 +1,129 @@ +/****************************************************************************** + * @file ar.c + *****************************************************************************/ +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" +#include "stdint.h" + +struct ar_state *state = 0; +const char *program_name = 0; + +FILE *arfp = NULL; + +int main (int argc, char **argv) { + + char ar_magic[8]; + long i; + + if (argc && *argv) { + + char *p; + program_name = *argv; + + if ((p = strrchr (program_name, '/'))) { + program_name = (p + 1); + } + + } + + state = xmalloc (sizeof (*state)); + parse_args (&argc, &argv, 1); + + if (state->append || state->replace) { + + if ((arfp = fopen (state->outfile, "r+b")) == NULL) { + + if ((arfp = fopen (state->outfile, "w+b")) == NULL) { + + report_at (program_name, 0, REPORT_ERROR, "failed to create %s", state->outfile); + return EXIT_FAILURE; + + } + + if (fwrite ("!\n", 8, 1, arfp) != 1) { + + fclose (arfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing to %s", state->outfile); + return EXIT_FAILURE; + + } + + } + + fclose (arfp); + + } + + if ((arfp = fopen (state->outfile, "r+b")) == NULL) { + + report_at (program_name, 0, REPORT_ERROR, "failed to open %s", state->outfile); + return EXIT_FAILURE; + + } + + if (fread (ar_magic, 8, 1, arfp) != 1) { + + fclose (arfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading %s", state->outfile); + return EXIT_FAILURE; + + } + + if (memcmp ("!\n", ar_magic, 8)) { + + fclose (arfp); + + report_at (program_name, 0, REPORT_ERROR, "%s is not a valid archive file", state->outfile); + return EXIT_FAILURE; + + } + + for (i = 0; i < state->nb_files; ++i) { + + if (state->append) { + + fseek (arfp, 0, SEEK_END); + append (arfp, state->files[i]); + + } else if (state->replace) { + + fseek (arfp, 8, SEEK_SET); + replace (state->files[i]); + + } else if (state->del) { + + fseek (arfp, 8, SEEK_SET); + delete (state->files[i]); + + } else if (state->extract) { + + fseek (arfp, 8, SEEK_SET); + extract (state->files[0]); + + } + + } + + if (state->display) { + + fseek (arfp, 8, SEEK_SET); + display (); + + } else if (state->ranlib) { + + fseek (arfp, 8, SEEK_SET); + ranlib (); + + } + + fclose (arfp); + return EXIT_SUCCESS; + +} diff --git a/ar.h b/ar.h new file mode 100644 index 0000000..2831f3b --- /dev/null +++ b/ar.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * @file ar.h + *****************************************************************************/ +#ifndef _AR_H +#define _AR_H + +struct ar_state { + + char **files; + long nb_files; + + const char *outfile; + + int del, move, print; + int append, replace, ranlib; + int display, extract; + +}; + +extern struct ar_state *state; +extern const char *program_name; + +struct ar_header { + + char name[16]; + char mtime[12]; + char owner[6]; + char group[6]; + char mode[8]; + char size[10]; + char endsig[2]; + +}; + +#include + +#include "stdint.h" + +extern FILE *arfp; +uint32_t conv_dec (char *str, int32_t max); + +void append (FILE *ofp, char *fname); +void delete (char *fname); +void display (void); +void extract (char *fname); +void ranlib (void); +void replace (char *fname); + +#endif /* _AR_H */ diff --git a/conv.c b/conv.c new file mode 100644 index 0000000..f8267ab --- /dev/null +++ b/conv.c @@ -0,0 +1,19 @@ +/****************************************************************************** + * @file conv.c + *****************************************************************************/ +#include "stdint.h" + +uint32_t conv_dec (char *str, int32_t max) { + + uint32_t value = 0; + + while (*str != ' ' && max-- > 0) { + + value *= 10; + value += *str++ - '0'; + + } + + return value; + +} diff --git a/delete.c b/delete.c new file mode 100644 index 0000000..e190ce0 --- /dev/null +++ b/delete.c @@ -0,0 +1,182 @@ +/****************************************************************************** + * @file delete.c + *****************************************************************************/ +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" + +void delete (char *fname) { + + FILE *tfp = tmpfile (); + + char temp[17], *name, *p, *contents; + long bytes, len, read; + + if (fwrite ("!\x0A", 8, 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whist writing ar header"); + return; + + } + + name = fname; + + if ((p = strrchr (fname, '/'))) { + name = (p + 1); + } + + len = strlen (name); + + if (len > 16) { + len = 16; + } + + memcpy (temp, name, len); + temp[len] = '\0'; + + for (;;) { + + struct ar_header hdr; + + if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { + + if (feof (arfp)) { + break; + } + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading '%s'", state->outfile); + return; + + } + + bytes = conv_dec (hdr.size, 10); + + if (bytes % 2) { + bytes++; + } + + if (memcmp (hdr.name, "/", 1) == 0) { + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (memcmp (hdr.name, temp, len) == 0) { + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (fwrite (&hdr, sizeof (hdr), 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header"); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + + for (;;) { + + if (bytes == 0 || feof (arfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, arfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (NULL, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile); + exit (EXIT_FAILURE); + + } + + bytes -= read; + + if (fwrite (contents, read, 1, tfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (NULL, 0, REPORT_ERROR, "failed to write temp file"); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + + } + + fclose (arfp); + remove (state->outfile); + + if ((arfp = fopen (state->outfile, "w+b")) == NULL) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed to open %s for writing", state->outfile); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + bytes = ftell (tfp); + + fseek (arfp, 0, SEEK_SET); + fseek (tfp, 0, SEEK_SET); + + for (;;) { + + if (bytes == 0 || feof (tfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, tfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file"); + return; + + } + + bytes -= read; + + if (fwrite (contents, read, 1, arfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whist writing %s", state->outfile); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + fclose (tfp); + +} diff --git a/display.c b/display.c new file mode 100644 index 0000000..7038961 --- /dev/null +++ b/display.c @@ -0,0 +1,57 @@ +/****************************************************************************** + * @file display.c + *****************************************************************************/ +#include +#include + +#include "ar.h" +#include "report.h" + +void display (void) { + + char temp[17] = { 0 }; + int i; + + for (;;) { + + struct ar_header hdr; + long bytes; + + if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { + + if (feof (arfp)) { + break; + } + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading '%s'", state->outfile); + return; + + } + + bytes = conv_dec (hdr.size, 10); + + if (bytes % 2) { + bytes++; + } + + fseek (arfp, bytes, SEEK_CUR); + + if (memcmp (hdr.name, "/", 1) == 0) { + continue; + } + + memcpy (temp, hdr.name, 16); + + for (i = 16; i >= 0; --i) { + + if (temp[i] == 0x20) { + temp[i] = '\0'; + } + + } + + printf ("%s\n", temp); + + } + +} diff --git a/extract.c b/extract.c new file mode 100644 index 0000000..18fd2c6 --- /dev/null +++ b/extract.c @@ -0,0 +1,120 @@ +/****************************************************************************** + * @file extract.c + *****************************************************************************/ +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" + +void extract (char *fname) { + + FILE *ofp; + + char temp[17], *name, *p, *contents; + long bytes, len, read; + + name = fname; + + if ((p = strrchr (fname, '/'))) { + name = (p + 1); + } + + len = strlen (name); + + if (len > 16) { + len = 16; + } + + memcpy (temp, name, len); + temp[len] = '\0'; + + for (;;) { + + struct ar_header hdr; + + if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { + + if (feof (arfp)) { + break; + } + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading '%s'", state->outfile); + return; + + } + + bytes = conv_dec (hdr.size, 10); + + if (memcmp (hdr.name, "/", 1) == 0) { + + if (bytes % 2) { + bytes++; + } + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (memcmp (hdr.name, temp, len) != 0) { + + if (bytes % 2) { + bytes++; + } + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if ((ofp = fopen (temp, "w+b")) == NULL) { + + report_at (program_name, 0, REPORT_ERROR, "failed to open %s for writing", temp); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + + for (;;) { + + if (bytes == 0 || feof (arfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, arfp) != 1) { + + free (contents); + fclose (ofp); + + report_at (NULL, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile); + exit (EXIT_FAILURE); + + } + + bytes -= read; + + if (fwrite (contents, read, 1, ofp) != 1) { + + free (contents); + fclose (ofp); + + report_at (NULL, 0, REPORT_ERROR, "failed to write %s file", temp); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + + } + +} diff --git a/lib.c b/lib.c new file mode 100644 index 0000000..aa774d8 --- /dev/null +++ b/lib.c @@ -0,0 +1,200 @@ +/****************************************************************************** + * @file lib.c + *****************************************************************************/ +#include +#include +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" +#include "stdint.h" + +static void print_help (void) { + + if (!program_name) { + goto _exit; + } + + fprintf (stderr, "Usage: %s command archive-file file...\n", program_name); + fprintf (stderr, "Commands:\n\n"); + + fprintf (stderr, " d delete file(s) from the archive\n"); + fprintf (stderr, " q quick append file(s) to the archive\n"); + fprintf (stderr, " r replace existing or insert new file(s) into the archive\n"); + fprintf (stderr, " s act as ranlib\n"); + fprintf (stderr, " t display contents of the archive\n"); + fprintf (stderr, " x extract file(s) from the archive\n"); + + fprintf (stderr, "\n"); + +_exit: + + exit (EXIT_SUCCESS); + +} + +char *xstrdup (const char *str) { + + char *ptr = xmalloc (strlen (str) + 1); + strcpy (ptr, str); + + return ptr; + +} + +void *xmalloc (unsigned long size) { + + void *ptr = malloc (size); + + if (ptr == NULL && size) { + + report_at (program_name, 0, REPORT_ERROR, "memory full (malloc)"); + exit (EXIT_FAILURE); + + } + + memset (ptr, 0, size); + return ptr; + +} + +void *xrealloc (void *ptr, unsigned long size) { + + void *new_ptr = realloc (ptr, size); + + if (new_ptr == NULL && size) { + + report_at (program_name, 0, REPORT_ERROR, "memory full (realloc)"); + exit (EXIT_FAILURE); + + } + + return new_ptr; + +} + +void dynarray_add (void *ptab, long *nb_ptr, void *data) { + + int32_t nb, nb_alloc; + void **pp; + + nb = *nb_ptr; + pp = *(void ***) ptab; + + if ((nb & (nb - 1)) == 0) { + + if (!nb) { + nb_alloc = 1; + } else { + nb_alloc = nb * 2; + } + + pp = xrealloc (pp, nb_alloc * sizeof (void *)); + *(void ***) ptab = pp; + + } + + pp[nb++] = data; + *nb_ptr = nb; + +} + +void parse_args (int *pargc, char ***pargv, int optind) { + + char **argv = *pargv; + int argc = *pargc; + + const char *r; + + if (argc < 3) { + print_help (); + } + + r = argv[optind++]; + +check_options: + + if (r[0] == '-') { + ++r; + } + + while (*r != '\0') { + + char ch = *r++; + + if (ch == 'd') { + + state->del++; + continue; + + } + + if (ch == 'm') { + + state->move++; + continue; + + } + + if (ch == 'p') { + + state->print++; + continue; + + } + + if (ch == 'q') { + + state->append++; + continue; + + } + + if (ch == 'r') { + + state->replace++; + continue; + + } + + if (ch == 's') { + + state->ranlib++; + continue; + + } + + if (ch == 't') { + + state->display++; + continue; + + } + + if (ch == 'x') { + + state->extract++; + continue; + + } + + print_help (); + + } + + if (*(r = argv[optind++]) == '-') { goto check_options; } + + if (state->append + state->del + state->display + state->extract + state->move + state->print + state->ranlib + state->replace != 1) { + print_help (); + } + + state->outfile = xstrdup (r); + + while (optind < argc) { + dynarray_add (&state->files, &state->nb_files, xstrdup (argv[optind++])); + } + +} diff --git a/lib.h b/lib.h new file mode 100644 index 0000000..d1adb09 --- /dev/null +++ b/lib.h @@ -0,0 +1,15 @@ +/****************************************************************************** + * @file lib.h + *****************************************************************************/ +#ifndef _LIB_H +#define _LIB_H + +char *xstrdup (const char *str); + +void *xmalloc (unsigned long size); +void *xrealloc (void *ptr, unsigned long size); + +void dynarray_add (void *ptab, long *nb_ptr, void *data); +void parse_args (int *pargc, char ***pargv, int optind); + +#endif /* _LIB_H */ diff --git a/makefile.slp b/makefile.slp new file mode 100644 index 0000000..1749ae7 --- /dev/null +++ b/makefile.slp @@ -0,0 +1,26 @@ +# This builds the Linux 32-bit ELF executable + +AS=pdas --oformat coff +CC=gccwin +LD=pdld + +COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib \ + -U__WIN32__ -D__NOBIVA__ -D__PDOS__ \ + -D__gnu_linux__ +LDFLAGS=-s --no-insert-timestamp -nostdlib --oformat elf --emit-relocs + +COBJ=append.obj ar.obj conv.obj delete.obj display.obj extract.obj \ + lib.obj ranlib.obj replace.obj report.obj + +all: clean xar.exe + +xar.exe: $(COBJ) + $(LD) $(LDFLAGS) -o xar.exe ../pdos/pdpclib/linstart.o $(COBJ) ../pdos/pdpclib/pdplinux.a + +.c.obj: + $(CC) $(COPTS) $< + $(AS) -o $@ $*.s + rm -f $*.s + +clean: + rm -f *.obj xar.exe diff --git a/makefile.sos b/makefile.sos new file mode 100644 index 0000000..18ae6f6 --- /dev/null +++ b/makefile.sos @@ -0,0 +1,29 @@ +# This builds the OS/2 32-bit version +# You will need to build PDPCLIB with the USE_MEMMGR +# option because this program does lots of small memory allocations + +AS=pdas --oformat coff +CC=gccwin +LD=pdld + +COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib \ + -U__WIN32__ -D__NOBIVA__ -D__PDOS__ \ + -D__HAVESYS__=_System -D__OS2__ -D__32BIT__ +LDFLAGS=-s --no-insert-timestamp -nostdlib --oformat lx \ + --stub ../pdos/pdpclib/needpdos.exe + +COBJ=append.obj ar.obj conv.obj delete.obj display.obj extract.obj \ + lib.obj ranlib.obj replace.obj report.obj + +all: clean xar.exe + +xar.exe: $(COBJ) + $(LD) $(LDFLAGS) -o xar.exe ../pdos/pdpclib/os2strt.obj $(COBJ) ../pdos/pdpclib/pdpos2.lib ../pdos/pdpclib/os2.lib + +.c.obj: + $(CC) $(COPTS) $< + $(AS) -o $@ $*.s + rm -f $*.s + +clean: + rm -f *.obj xar.exe diff --git a/makefile.std b/makefile.std new file mode 100644 index 0000000..ddfb016 --- /dev/null +++ b/makefile.std @@ -0,0 +1,20 @@ +AS=pdas --oformat coff +CC=gccwin +LD=pdld + +COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib -D__WIN32__ -D__NOBIVA__ -D__PDOS__ +COBJ=append.obj ar.obj conv.obj delete.obj display.obj extract.obj \ + lib.obj ranlib.obj replace.obj report.obj + +all: clean xar.exe + +xar.exe: $(COBJ) + $(LD) -s -nostdlib --no-insert-timestamp -o xar.exe ../pdos/pdpclib/w32start.obj $(COBJ) ../pdos/pdpclib/msvcrt.lib + +.c.obj: + $(CC) $(COPTS) $< + $(AS) -o $@ $*.s + rm -f $*.s + +clean: + rm -f *.o xar.exe diff --git a/ranlib.c b/ranlib.c new file mode 100644 index 0000000..3a88817 --- /dev/null +++ b/ranlib.c @@ -0,0 +1,541 @@ +/****************************************************************************** + * @file ranlib.c + *****************************************************************************/ +#include +#include +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" + +#define GET_INT32(arr) ((int32_t) arr[0] | (((int32_t) arr[1]) << 8) | (((int32_t) arr[2]) << 16) | (((int32_t) arr[3]) << 24)) + +#define GET_UINT16(arr) ((uint32_t) arr[0] | (((uint32_t) arr[1]) << 8)) +#define GET_UINT32(arr) ((uint32_t) arr[0] | (((uint32_t) arr[1]) << 8) | (((uint32_t) arr[2]) << 16) | (((uint32_t) arr[3]) << 24)) + +struct aout_exec { + + unsigned char a_info[4]; + unsigned char a_text[4]; + unsigned char a_data[4]; + unsigned char a_bss[4]; + unsigned char a_syms[4]; + unsigned char a_entry[4]; + unsigned char a_trsize[4]; + unsigned char a_drsize[4]; + +}; + +struct aout_nlist { + + unsigned char n_strx[4]; + unsigned char n_type; + + unsigned char n_other; + unsigned char n_desc[2]; + + unsigned char n_value[4]; + +}; + +struct coff_exec { + + unsigned char Machine[2]; + unsigned char NumberOfSections[2]; + + unsigned char TimeDateStamp[4]; + unsigned char PointerToSymbolTable[4]; + unsigned char NumberOfSymbols[4]; + + unsigned char SizeOfOptionalHeader[2]; + unsigned char Characteristics[2]; + +}; + +struct coff_symbol { + + char Name[8]; + unsigned char Value[4]; + + unsigned char SectionNumber[2]; + unsigned char Type[2]; + + unsigned char StorageClass[1]; + unsigned char NumberOfAuxSymbols[1]; + +}; + +struct strtab { + + const char *name; + long length, offset; + +}; + +struct gstrtab { + + long count, max; + struct strtab *strtabs; + +}; + +static struct gstrtab gstrtab = { 0, 64, NULL }; + +static int add_strtab (struct gstrtab *gstrtab, struct strtab *strtab) { + + if (gstrtab->strtabs == NULL) { + + if ((gstrtab->strtabs = malloc (gstrtab->max * sizeof (*strtab))) == NULL) { + return 1; + } + + } + + if (gstrtab->count >= gstrtab->max) { + + void *tmp; + + gstrtab->max *= 2; + + if ((tmp = realloc (gstrtab->strtabs, gstrtab->max * sizeof (*strtab))) == NULL) { + return 1; + } + + gstrtab->strtabs = tmp; + + } + + gstrtab->strtabs[gstrtab->count] = *strtab; + gstrtab->count++; + + return 0; + +} + +static void aout_get_symbols (void *object, long offset) { + + struct aout_exec *hdr = (struct aout_exec *) object; + + long sym_start = sizeof (*hdr) + GET_UINT32 (hdr->a_text) + GET_UINT32 (hdr->a_data) + GET_UINT32 (hdr->a_trsize) + GET_UINT32 (hdr->a_drsize); + long strtab_start = sym_start + GET_UINT32 (hdr->a_syms); + + while (sym_start < strtab_start) { + + struct aout_nlist nlist; + memcpy (&nlist, (char *) object + sym_start, sizeof (nlist)); + + if (nlist.n_type == 5 || nlist.n_type == 7 || nlist.n_type == 9) { + + struct strtab *strtab; + char *symname = (char *) object + strtab_start + GET_INT32 (nlist.n_strx); + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = strlen (symname); + + strtab->name = xstrdup (symname); + strtab->offset = offset; + + add_strtab (&gstrtab, strtab); + + } + + sym_start += sizeof (nlist); + + } + +} + +static void coff_get_symbols (void *object, long offset) { + + struct coff_exec *hdr = (struct coff_exec *) object; + + long sym_start = GET_UINT32 (hdr->PointerToSymbolTable); + long sym_cnt = GET_UINT32 (hdr->NumberOfSymbols); + long string_table_start = sym_start + (sizeof (struct coff_symbol) * sym_cnt); + + while (sym_cnt--) { + + struct coff_symbol sym; + memcpy (&sym, (char *) object + sym_start, sizeof (sym)); + + if (sym.StorageClass[0] == 2 && GET_UINT16 (sym.SectionNumber) != 0) { + + struct strtab *strtab; + + if (sym.Name[0] != 0) { + + int i, len; + + for (i = 0, len = 0; i < 8; i++) { + + if (sym.Name[i] == '\0') { + break; + } + + len++; + + } + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = len; + + strtab->name = xstrdup (sym.Name); + strtab->offset = offset; + + add_strtab (&gstrtab, strtab); + + } else { + + unsigned char offset1 = (unsigned char) sym.Name[4]; + unsigned char offset2 = (unsigned char) sym.Name[5]; + unsigned char offset3 = (unsigned char) sym.Name[6]; + unsigned char offset4 = (unsigned char) sym.Name[7]; + + long final_offset = ((uint32_t) offset1 | (((uint32_t) offset2) << 8) | (((uint32_t) offset3) << 16) | (((uint32_t) offset4) << 24)); + final_offset += string_table_start; + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = strlen ((char *) object + final_offset); + + strtab->name = xstrdup ((char *) object + final_offset); + strtab->offset = offset; + + add_strtab (&gstrtab, strtab); + + } + + } + + sym_start += sizeof (sym); + + } + +} + +void ranlib (void) { + + FILE *tfp = tmpfile (); + long offset = 0; + + struct ar_header header; + long bytes, i, j, len, read, val; + + unsigned char *object; + void *contents; + + char temp[16]; + int valid = 0; + + for (;;) { + + struct ar_header hdr; + long bytes; + + if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { + + if (feof (arfp)) { + break; + } + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading '%s'", state->outfile); + return; + + } + + bytes = conv_dec (hdr.size, 10); + + if (bytes % 2) { + bytes++; + } + + if (memcmp (hdr.name, "/", 1) == 0) { + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + object = xmalloc (bytes); + + if (fread (object, bytes, 1, arfp) != 1) { + + free (object); + + report_at (program_name, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile); + exit (EXIT_FAILURE); + + + } + + valid = ((object[0] == 0x07 && object[1] == 0x01) || (object[0] == 0x4C && object[1] == 0x01) || (object[0] == 0x64 && object[1] == 0x86)); + + if (!valid) { + + free (object); + + offset += sizeof (hdr); + offset += bytes; + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (object[0] == 0x07 && object[1] == 0x01) { + aout_get_symbols (object, offset + 8); + } else { + coff_get_symbols (object, offset + 8); + } + + free (object); + + offset += sizeof (hdr); + offset += bytes; + + } + + fseek (arfp, 8, SEEK_SET); + bytes = 0; + + for (i = 0; i < gstrtab.count; ++i) { + bytes += gstrtab.strtabs[i].length + 5; + } + + for (i = 0; i < gstrtab.count; ++i) { + + gstrtab.strtabs[i].offset += bytes; + + if (bytes % 2) { + gstrtab.strtabs[i].offset++; + } + + } + + if (fwrite ("!\x0A", 8, 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whist writing ar header"); + return; + + } + + memset (temp, 0x20, 16); + temp[0] = '0'; + + len = 1; + memcpy (header.name, "/", len); + + while (len < 16) { + header.name[len++] = 0x20; + } + + memcpy (header.mtime, temp, 12); + memcpy (header.owner, temp, 6); + memcpy (header.group, temp, 6); + memcpy (header.mode, temp, 8); + + len = sprintf (temp, "%ld", bytes + 4); + temp[len] = 0x20; + + memcpy (header.size, temp, 10); + + header.endsig[0] = 0x60; + header.endsig[1] = 0x0A; + + if (fwrite (&header, sizeof (header), 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header"); + return; + + } + + val = gstrtab.count; + + for (i = 0; i < 4; ++i) { + temp[4 - 1 - i] = (val >> (CHAR_BIT * i)) & UCHAR_MAX; + } + + if (fwrite (temp, 4, 1, tfp) != 1) { + exit (EXIT_FAILURE); + } + + for (i = 0; i < gstrtab.count; ++i) { + + val = gstrtab.strtabs[i].offset + 4 + sizeof (header); + + for (j = 0; j < 4; ++j) { + temp[4 - 1 - j] = (val >> (CHAR_BIT * j)) & UCHAR_MAX; + } + + if (fwrite (temp, 4, 1, tfp) != 1) { + exit (EXIT_FAILURE); + } + + } + + for (i = 0; i < gstrtab.count; ++i) { + + const char *name = gstrtab.strtabs[i].name; + long length = gstrtab.strtabs[i].length; + + if (fwrite (name, length, 1, tfp) != 1) { + exit (EXIT_FAILURE); + } + + temp[0] = '\0'; + + if (fwrite (temp, 1, 1, tfp) != 1) { + exit (EXIT_FAILURE); + } + + } + + if (bytes % 2) { + + temp[0] = '\0'; + + if (fwrite (temp, 1, 1, tfp) != 1) { + exit (EXIT_FAILURE); + } + + } + + for (;;) { + + struct ar_header hdr; + + if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { + + if (feof (arfp)) { + break; + } + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading '%s'", state->outfile); + return; + + } + + bytes = conv_dec (hdr.size, 10); + + if (bytes % 2) { + bytes++; + } + + if (memcmp (hdr.name, "/", 1) == 0) { + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (fwrite (&hdr, sizeof (hdr), 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header"); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + + for (;;) { + + if (bytes == 0 || feof (arfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, arfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (NULL, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile); + exit (EXIT_FAILURE); + + } + + bytes -= read; + + if (fwrite (contents, read, 1, tfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (NULL, 0, REPORT_ERROR, "failed to write temp file"); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + + } + + fclose (arfp); + remove (state->outfile); + + if ((arfp = fopen (state->outfile, "w+b")) == NULL) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed to open %s for writing", state->outfile); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + bytes = ftell (tfp); + + fseek (arfp, 0, SEEK_SET); + fseek (tfp, 0, SEEK_SET); + + for (;;) { + + if (bytes == 0 || feof (tfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, tfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file"); + return; + + } + + bytes -= read; + + if (fwrite (contents, read, 1, arfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whist writing %s", state->outfile); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + fclose (tfp); + +} diff --git a/replace.c b/replace.c new file mode 100644 index 0000000..3df068c --- /dev/null +++ b/replace.c @@ -0,0 +1,192 @@ +/****************************************************************************** + * @file replace.c + *****************************************************************************/ +#include +#include +#include + +#include "ar.h" +#include "lib.h" +#include "report.h" + +void replace (char *fname) { + + FILE *tfp = tmpfile (); + + char temp[17], *name, *p, *contents; + long bytes, len, read; + + if (fwrite ("!\x0A", 8, 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whist writing ar header"); + return; + + } + + name = fname; + + if ((p = strrchr (fname, '/'))) { + name = (p + 1); + } + + len = strlen (name); + + if (len > 16) { + len = 16; + } + + memcpy (temp, name, len); + temp[len] = '\0'; + + state->append = 1; + + for (;;) { + + struct ar_header hdr; + + if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { + + if (feof (arfp)) { + break; + } + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading '%s'", state->outfile); + return; + + } + + bytes = conv_dec (hdr.size, 10); + + if (bytes % 2) { + bytes++; + } + + if (memcmp (hdr.name, "/", 1) == 0) { + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (memcmp (hdr.name, temp, len) == 0) { + + state->append = 0; + append (tfp, fname); + + fseek (arfp, bytes, SEEK_CUR); + continue; + + } + + if (fwrite (&hdr, sizeof (hdr), 1, tfp) != 1) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst writing header"); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + + for (;;) { + + if (bytes == 0 || feof (arfp)) { + break; + } else if (bytes >= 512) { + read = 512;; + } else { + read = bytes; + } + + if (fread (contents, read, 1, arfp) != 1) { + + free (contents); + + report_at (NULL, 0, REPORT_ERROR, "failed to read %ld bytes from %s", bytes, state->outfile); + exit (EXIT_FAILURE); + + } + + bytes -= read; + + if (fwrite (contents, read, 1, tfp) != 1) { + + free (contents); + + report_at (NULL, 0, REPORT_ERROR, "failed to write temp file"); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + + } + + if (state->append) { + + state->append = 0; + append (tfp, fname); + + } + + fclose (arfp); + remove (state->outfile); + + if ((arfp = fopen (state->outfile, "w+b")) == NULL) { + + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed to open %s", state->outfile); + exit (EXIT_FAILURE); + + } + + contents = xmalloc (512); + bytes = ftell (tfp); + + fseek (arfp, 0, SEEK_SET); + fseek (tfp, 0, SEEK_SET); + + for (;;) { + + if (bytes == 0 || feof (tfp)) { + break; + } else if (bytes >= 512) { + read = 512; + } else { + read = bytes; + } + + if (fread (contents, read, 1, tfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whilst reading temp file"); + return; + + } + + bytes -= read; + + if (fwrite (contents, read, 1, arfp) != 1) { + + free (contents); + fclose (tfp); + + report_at (program_name, 0, REPORT_ERROR, "failed whist writing %s", state->outfile); + exit (EXIT_FAILURE); + + } + + } + + free (contents); + fclose (tfp); + +} diff --git a/report.c b/report.c new file mode 100644 index 0000000..14ad2f6 --- /dev/null +++ b/report.c @@ -0,0 +1,125 @@ +/****************************************************************************** + * @file report.c + *****************************************************************************/ +#include +#include + +#include "report.h" + +#ifndef __PDOS__ +#if defined (_WIN32) +# include +static int OriginalConsoleColor = -1; +#endif + +static void reset_console_color (void) { + +#if defined (_WIN32) + + HANDLE hStdError = GetStdHandle (STD_ERROR_HANDLE); + + if (OriginalConsoleColor == -1) { return; } + + SetConsoleTextAttribute (hStdError, OriginalConsoleColor); + OriginalConsoleColor = -1; + +#else + + fprintf (stderr, "\033[0m"); + +#endif + +} + +static void set_console_color (int color) { + +#if defined (_WIN32) + + HANDLE hStdError = GetStdHandle (STD_ERROR_HANDLE); + WORD wColor; + + if (OriginalConsoleColor == -1) { + + CONSOLE_SCREEN_BUFFER_INFO csbi; + + if (!GetConsoleScreenBufferInfo (hStdError, &csbi)) { + return; + } + + OriginalConsoleColor = csbi.wAttributes; + + } + + wColor = (OriginalConsoleColor & 0xF0) + (color & 0xF); + SetConsoleTextAttribute (hStdError, wColor); + +#else + + fprintf (stderr, "\033[%dm", color); + +#endif + +} +#endif + +void report_at (const char *filename, unsigned long line_number, int type, const char *fmt, ...) { + + va_list ap; + + if (filename) { + + if (line_number == 0) { + fprintf (stderr, "%s: ", filename); + } else { + fprintf (stderr, "%s:", filename); + } + + } + + if (line_number > 0) { + fprintf (stderr, "%lu: ", line_number); + } + + if (type == REPORT_ERROR || type == REPORT_FATAL_ERROR) { + +#ifndef __PDOS__ + set_console_color (COLOR_ERROR); +#endif + + if (type == REPORT_ERROR) { + fprintf (stderr, "error:"); + } else { + fprintf (stderr, "fatal error:"); + } + + } else if (type == REPORT_INTERNAL_ERROR) { + +#ifndef __PDOS__ + set_console_color (COLOR_INTERNAL_ERROR); +#endif + + fprintf (stderr, "internal error:"); + + } else if (type == REPORT_WARNING) { + +#ifndef __PDOS__ + set_console_color (COLOR_WARNING); +#endif + + fprintf (stderr, "warning:"); + + } + +#ifndef __PDOS__ + reset_console_color (); +#endif + + fprintf (stderr, " "); + + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + + fprintf (stderr, "\n"); + +} diff --git a/report.h b/report.h new file mode 100644 index 0000000..bdd121e --- /dev/null +++ b/report.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * @file report.h + *****************************************************************************/ +#ifndef _REPORT_H +#define _REPORT_H + +enum { + + REPORT_ERROR = 0, + REPORT_FATAL_ERROR, + REPORT_INTERNAL_ERROR, + REPORT_WARNING + +}; + +#if defined (_WIN32) +# define COLOR_ERROR 12 +# define COLOR_WARNING 13 +# define COLOR_INTERNAL_ERROR 19 +#else +# define COLOR_ERROR 91 +# define COLOR_INTERNAL_ERROR 94 +# define COLOR_WARNING 95 +#endif + +void report_at (const char *filename, unsigned long line_number, int type, const char *fmt, ...); + +#endif /* _REPORT_H */ diff --git a/stdint.h b/stdint.h new file mode 100644 index 0000000..f4b18c0 --- /dev/null +++ b/stdint.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * @file stdint.h + *****************************************************************************/ +#ifndef _STDINT_H +#define _STDINT_H + +#include + +typedef signed char int8_t; +typedef unsigned char uint8_t; + +typedef signed short int16_t; +typedef unsigned short uint16_t; + +#if INT_MAX == 32767 +typedef signed long int32_t; +typedef unsigned long uint32_t; +#else +typedef signed int int32_t; +typedef unsigned int uint32_t; +#endif + +#endif /* _STDINT_H */