From f91811f57de0561cc7c8efb5897a6b62f5c0e0b2 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 30 Jan 1999 21:35:36 +0000 Subject: Initial checkin of skeleton application. About to start reading files [originally from svn r22] --- Makefile | 55 ++++++++++++++++++ buttress.h | 113 +++++++++++++++++++++++++++++++++++++ error.c | 60 ++++++++++++++++++++ help.c | 32 +++++++++++ input.c | 33 +++++++++++ licence.c | 16 ++++++ main.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ malloc.c | 39 +++++++++++++ version.c | 13 +++++ 9 files changed, 548 insertions(+) create mode 100644 Makefile create mode 100644 buttress.h create mode 100644 error.c create mode 100644 help.c create mode 100644 input.c create mode 100644 licence.c create mode 100644 main.c create mode 100644 malloc.c create mode 100644 version.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..23eb91e --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +# Buttress master makefile + +# Requires a compiler with -MD support, currently + +# `make' from top level will build in buttress.b +# `make BUILDDIR=foo' from top level will build in directory foo +ifndef REALBUILD +ifndef BUILDDIR +BUILDDIR := build +endif +all: + @test -d $(BUILDDIR) || mkdir $(BUILDDIR) + @make -C $(BUILDDIR) -f ../Makefile REALBUILD=yes +else + +# The `real' makefile part. + +ifdef RELEASE +ifndef VERSION +VERSION := $(RELEASE) +endif +else +CFLAGS += -g +endif + +ifndef VER +ifdef VERSION +VER := $(VERSION) +endif +endif +ifdef VER +VDEF := -DVERSION=\"$(VER)\" +endif + +SRC := ../ + +MODULES := main malloc error help licence version + +OBJECTS := $(addsuffix .o,$(MODULES)) +DEPS := $(addsuffix .d,$(MODULES)) + +buttress: $(OBJECTS) + $(CC) $(LFLAGS) -o buttress $(OBJECTS) + +%.o: $(SRC)%.c + $(CC) $(CFLAGS) -MD -c $< + +version.o: FORCE + $(CC) $(VDEF) -MD -c $(SRC)version.c + +FORCE: # phony target to force version.o to be rebuilt every time + +-include $(DEPS) + +endif diff --git a/buttress.h b/buttress.h new file mode 100644 index 0000000..afb38ae --- /dev/null +++ b/buttress.h @@ -0,0 +1,113 @@ +#ifndef BUTTRESS_BUTTRESS_H +#define BUTTRESS_BUTTRESS_H + +#ifdef __GNUC__ +#define NORETURN __attribute__((__noreturn__)) +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* + * Structure tags + */ +typedef struct input_Tag input; +typedef struct paragraph_Tag paragraph; +typedef struct word_Tag word; + +/* + * Data structure to hold all the file names etc for input + */ +#define INPUT_PUSHBACK_MAX 16 +struct input_Tag { + char **filenames; /* complete list of input files */ + int nfiles; /* how many in the list */ + FILE *currfp; /* the currently open one */ + int currindex; /* which one is that in the list */ + char pushback[INPUT_PUSHBACK_MAX]; /* pushed-back input characters */ + int npushback; +}; + +/* + * Data structure to hold the input form of the source, ie a linked + * list of paragraphs + */ +struct paragraph_Tag { + paragraph *next; + int type; + char *keyword; /* for IR, IA, and heading paras */ + word *words; /* list of words in paragraph */ +} paragraph; +enum { + para_IA, /* index alias */ + para_IR, /* index rewrite */ + para_Chapter, + para_Appendix, + para_Heading, + para_Subsect, + para_Normal, + para_Bullet, + para_Code +}; + +/* + * Data structure to hold an individual word + */ +struct word_Tag { + word *next; + int type; + char *text; +} +enum { + word_Normal, + word_Emph, + word_Code, + word_IndexRef /* always invisible */ +} + +/* + * error.c + */ +void fatal(int code, ...) NORETURN; +void error(int code, ...); +enum { + err_nomemory, /* out of memory */ + err_optnoarg, /* option `-%s' requires an argument */ + err_nosuchopt, /* unrecognised option `-%s' */ + err_noinput, /* no input files */ +}; + +/* + * malloc.c + */ +void *smalloc(int size); +void *srealloc(void *p, int size); +void sfree(void *p); + +/* + * help.c + */ +void help(void); +void usage(void); +void showversion(void); + +/* + * licence.c + */ +void licence(void); + +/* + * version.c + */ +const char *const version; + +/* + * input.c + */ +paragraph *read_input(input *in); + +#endif diff --git a/error.c b/error.c new file mode 100644 index 0000000..2c6e6fb --- /dev/null +++ b/error.c @@ -0,0 +1,60 @@ +/* + * error.c: buttress error handling + */ + +#include +#include +#include +#include "buttress.h" + +/* + * Error flags + */ +#define PREFIX 0x0001 /* give `buttress:' prefix */ + +static void do_error(int code, va_list ap) { + char error[1024]; + char *sp; + int flags; + + switch(code) { + case err_nomemory: /* no arguments */ + sprintf(error, "out of memory"); + flags = PREFIX; + break; + case err_optnoarg: + sp = va_arg(ap, char *); + sprintf(error, "option `-%.200s' requires an argument", sp); + flags = PREFIX; + break; + case err_nosuchopt: + sp = va_arg(ap, char *); + sprintf(error, "unrecognised option `-%.200s'", sp); + flags = PREFIX; + break; + case err_noinput: /* no arguments */ + sprintf(error, "no input files"); + flags = PREFIX; + break; + } + + if (flags & PREFIX) + fputs("buttress: ", stderr); + fputs(error, stderr); + fputc('\n', stderr); +} + +void fatal(int code, ...) { + va_list ap; + va_start(ap, code); + do_error(code, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + +void error(int code, ...) { + va_list ap; + va_start(ap, code); + do_error(code, ap); + va_end(ap); +} diff --git a/help.c b/help.c new file mode 100644 index 0000000..c1e2e42 --- /dev/null +++ b/help.c @@ -0,0 +1,32 @@ +/* + * help.c: usage instructions + */ + +#include +#include "buttress.h" + +static char *helptext[] = { + "FIXME: help text goes here", + NULL +}; + +static char *usagetext[] = { + "FIXME: usage text goes here", + NULL +}; + +void help(void) { + char **p; + for (p = helptext; *p; p++) + puts(*p); +} + +void usage(void) { + char **p; + for (p = usagetext; *p; p++) + puts(*p); +} + +void showversion(void) { + printf("Buttress, %s\n", version); +} diff --git a/input.c b/input.c new file mode 100644 index 0000000..dc745f1 --- /dev/null +++ b/input.c @@ -0,0 +1,33 @@ +/* + * input.c: read the source form + */ + +#include +#include +#include "buttress.h" + +static void unget(input *in, char c) { + assert(in->npushback < INPUT_PUSHBACK_MAX); + in->pushback[in->npushback++] = c; +} + +/* + * Can return EOF + */ +static int get(input *in) { + if (in->npushback) + return (unsigned char)in->pushback[--in->npushback]; + else if (in->currfp) { + int c = getc(in->currfp); + if (c == EOF) { + fclose(in->currfp); + in->currfp = NULL; + in->currindex++; + } + return c; + } +} + +paragraph *read_input(input *in) { + /* FIXME: do some reading */ +} diff --git a/licence.c b/licence.c new file mode 100644 index 0000000..0c4338a --- /dev/null +++ b/licence.c @@ -0,0 +1,16 @@ +/* + * licence.c: licence text + */ + +#include + +static char *licencetext[] = { + "FIXME: licence text goes here", + NULL +}; + +void licence(void) { + char **p; + for (p = licencetext; *p; p++) + puts(*p); +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..ad77b46 --- /dev/null +++ b/main.c @@ -0,0 +1,187 @@ +/* + * main.c: command line parsing and top level + */ + +#include +#include +#include "buttress.h" + +int main(int argc, char **argv) { + char **infiles; + char *outfile; + int nfiles; + int nogo; + int errs; + + /* + * Set up initial (default) parameters. + */ + infiles = smalloc(argc*sizeof(char *)); + outfile = NULL; + nfiles = 0; + nogo = errs = FALSE; + + if (argc == 1) { + usage(); + exit(EXIT_SUCCESS); + } + + /* + * Parse command line arguments. + */ + while (--argc) { + char *p = *++argv; + if (*p == '-') { + /* + * An option. + */ + while (p && *++p) { + char c = *p; + switch (c) { + case '-': + /* + * Long option. + */ + { + char *opt, *val; + opt = p++; /* opt will have _one_ leading - */ + while (*p && *p != '=') + p++; /* find end of option */ + if (*p == '=') { + *p++ = '\0'; + val = p; + } else + val = NULL; + if (!strcmp(opt, "-help")) { + help(); + nogo = TRUE; + } else if (!strcmp(opt, "-version")) { + showversion(); + nogo = TRUE; + } else if (!strcmp(opt, "-licence") || + !strcmp(opt, "-license")) { + licence(); + nogo = TRUE; + } else if (!strcmp(opt, "-output")) { + if (!val) + errs = TRUE, error(err_optnoarg, opt); + else + outfile = val; + } else { + errs = TRUE, error(err_nosuchopt, opt); + } + } + p = NULL; + break; + case 'h': + case 'V': + case 'L': + /* + * Option requiring no parameter. + */ + switch (c) { + case 'h': + help(); + nogo = TRUE; + break; + case 'V': + showversion(); + nogo = TRUE; + break; + case 'L': + licence(); + nogo = TRUE; + break; + } + break; + case 'o': + /* + * Option requiring parameter. + */ + p++; + if (!*p && argc > 1) + --argc, p = *++argv; + else if (!*p) { + char opt[2]; + opt[0] = c; + opt[1] = '\0'; + errs = TRUE, error(err_optnoarg, opt); + } + /* + * Now c is the option and p is the parameter. + */ + switch (c) { + case 'o': + ofile = p; + break; + } + p = NULL; /* prevent continued processing */ + break; + default: + /* + * Unrecognised option. + */ + { + char opt[2]; + opt[0] = c; + opt[1] = '\0'; + errs = TRUE, error(err_nosuchopt, opt); + } + } + } + } else { + /* + * A non-option argument. + */ + infiles[nfiles++] = p; + } + } + + if (errs) + exit(EXIT_FAILURE); + if (nogo) + exit(EXIT_SUCCESS); + + /* + * Do the work. + */ + if (nfiles == 0) { + error(err_noinput); + usage(); + exit(EXIT_FAILURE); + } + + { + input in; + paragraph sourceform; + + in.filenames = infiles; + in.nfiles = nfiles; + in.currfp = NULL; + in.currindex = 0; + in.npushback = 0; + + sourceform = read_input(&in); + if (!sourceform) + exit(EXIT_FAILURE); + + sfree(infiles); + + /* + * FIXME: having read it, do something with it! + */ + { + paragraph *p; + word *w; + for (p = sourceform; p; p = p->next) { + printf("para %d \"%s\" {\n", p->type, p->keyword); + for (w = p->words; w; w = w->next) { + printf(" word %d \"%s\"\n", w->type, w->text); + } + printf("}\n"); + } + } + } + + return 0; +} diff --git a/malloc.c b/malloc.c new file mode 100644 index 0000000..cf0f2e0 --- /dev/null +++ b/malloc.c @@ -0,0 +1,39 @@ +/* + * malloc.c: safe wrappers around malloc, realloc, free, strdup + */ + +#include +#include "buttress.h" + +/* + * smalloc should guarantee to return a useful pointer - buttress + * can do nothing except die when it's out of memory anyway + */ +void *smalloc(int size) { + void *p = malloc(size); + if (!p) + fatal(err_nomemory); + return p; +} + +/* + * sfree should guaranteeably deal gracefully with freeing NULL + */ +void sfree(void *p) { + if (p) + free(p); +} + +/* + * srealloc should guaranteeably be able to realloc NULL + */ +void *srealloc(void *p, int size) { + void *q; + if (p) + q = realloc(p, size); + else + q = malloc(size); + if (!q) + fatal(err_nomemory); + return p; +} diff --git a/version.c b/version.c new file mode 100644 index 0000000..38fbca1 --- /dev/null +++ b/version.c @@ -0,0 +1,13 @@ +/* + * version.c: version string + */ + +#include + +#ifndef VERSION +#define VER "anonymous build (" __DATE__ " " __TIME__ ")" +#else +#define VER "version " VERSION +#endif + +const char *const version = VER; -- cgit v1.1