summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>1999-01-30 21:35:36 +0000
committerSimon Tatham <anakin@pobox.com>1999-01-30 21:35:36 +0000
commitf91811f57de0561cc7c8efb5897a6b62f5c0e0b2 (patch)
tree0f942e70bd4936e5806874193d17ba90693cd313
downloadhalibut-f91811f57de0561cc7c8efb5897a6b62f5c0e0b2.zip
halibut-f91811f57de0561cc7c8efb5897a6b62f5c0e0b2.tar.gz
halibut-f91811f57de0561cc7c8efb5897a6b62f5c0e0b2.tar.bz2
halibut-f91811f57de0561cc7c8efb5897a6b62f5c0e0b2.tar.xz
Initial checkin of skeleton application. About to start reading files
[originally from svn r22]
-rw-r--r--Makefile55
-rw-r--r--buttress.h113
-rw-r--r--error.c60
-rw-r--r--help.c32
-rw-r--r--input.c33
-rw-r--r--licence.c16
-rw-r--r--main.c187
-rw-r--r--malloc.c39
-rw-r--r--version.c13
9 files changed, 548 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#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 <stdio.h>
+#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 <stdio.h>
+#include <assert.h>
+#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 <stdio.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+#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 <stdlib.h>
+#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 <stdio.h>
+
+#ifndef VERSION
+#define VER "anonymous build (" __DATE__ " " __TIME__ ")"
+#else
+#define VER "version " VERSION
+#endif
+
+const char *const version = VER;