summaryrefslogtreecommitdiff
path: root/buttress.h
blob: c4f90c8153774be54562027fbbdc3611651ca2dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#ifndef BUTTRESS_BUTTRESS_H
#define BUTTRESS_BUTTRESS_H

#include <stdio.h>
#include <wchar.h>
#include <time.h>

#ifdef __GNUC__
#define NORETURN __attribute__((__noreturn__))
#endif

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

/* For suppressing unused-parameter warnings */
#define IGNORE(x) ( (x) = (x) )

/*
 * Structure tags
 */
typedef struct input_Tag input;
typedef struct filepos_Tag filepos;
typedef struct paragraph_Tag paragraph;
typedef struct word_Tag word;
typedef struct keywordlist_Tag keywordlist;
typedef struct keyword_Tag keyword;
typedef struct userstyle_Tag userstyle;
typedef struct numberstate_Tag numberstate;
typedef struct index_Tag index;
typedef struct macrostack_Tag macrostack;

/*
 * Data structure to hold a file name and index, a line and a
 * column number, for reporting errors
 */
struct filepos_Tag {
    char *filename;
    int line, col;
};

/*
 * Data structure to hold all the file names etc for input
 */
typedef struct pushback_Tag {
    int chr;
    filepos pos;
} pushback;
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 */
    pushback *pushback;		       /* pushed-back input characters */
    int npushback, pushbacksize;
    filepos pos;
    int reportcols;		       /* report column numbers in errors */
    macrostack *stack;		       /* macro expansions in force */
};

/*
 * Data structure to hold the input form of the source, ie a linked
 * list of paragraphs
 */
struct paragraph_Tag {
    paragraph *next;
    int type;
    wchar_t *keyword;		       /* for most special paragraphs */
    word *words;		       /* list of words in paragraph */
    int aux;			       /* number, in a numbered paragraph */
    word *kwtext;		       /* chapter/section indication */
    word *kwtext2;		       /* numeric-only form of kwtext */
    filepos fpos;
};
enum {
    para_IM,			       /* index merge */
    para_BR,			       /* bibliography rewrite */
    para_Rule,			       /* random horizontal rule */
    para_Chapter,
    para_Appendix,
    para_UnnumberedChapter,
    para_Heading,
    para_Subsect,
    para_Normal,
    para_Biblio,		       /* causes no output unless turned ... */
    para_BiblioCited,		       /*  ... into this paragraph type */
    para_Bullet,
    para_NumberedList,
    para_Code,
    para_Copyright,
    para_Preamble,
    para_NoCite,
    para_Title,
    para_VersionID,
    para_NotParaType		       /* placeholder value */
};

/*
 * Data structure to hold an individual word
 */
struct word_Tag {
    word *next, *alt;
    int type;
    int aux;
    int breaks;			       /* can a line break after it? */
    wchar_t *text;
    filepos fpos;
};
enum {
    /* ORDERING CONSTRAINT: these normal-word types ... */
    word_Normal,
    word_Emph,
    word_Code,			       /* monospaced; `quoted' in text */
    word_WeakCode,		       /* monospaced, normal in text */
    /* ... must be in the same order as these space types ... */
    word_WhiteSpace,		       /* text is NULL or ignorable */
    word_EmphSpace,		       /* WhiteSpace when emphasised */
    word_CodeSpace,		       /* WhiteSpace when code */
    word_WkCodeSpace,		       /* WhiteSpace when weak code */
    /* END ORDERING CONSTRAINT */
    word_internal_endattrs,
    word_UpperXref,		       /* \K */
    word_LowerXref,		       /* \k */
    word_XrefEnd,		       /* (invisible; no text) */
    word_IndexRef,		       /* (always an invisible one) */
    word_HyperLink,		       /* (invisible) */
    word_HyperEnd		       /* (also invisible; no text) */
};
/* aux values for attributed words */
enum {
    attr_Only,			       /* a lone word with the attribute */
    attr_First,			       /* the first of a series */
    attr_Last,			       /* the last of a series */
    attr_Always			       /* any other part of a series */
};
#define isattr(x) ( ( (x) > word_Normal && (x) < word_WhiteSpace ) || \
                    ( (x) > word_WhiteSpace && (x) < word_internal_endattrs ) )
#define sameattr(x,y) ( (x)-(y) == 0 || (x)-(y) == 4 || (x)-(y) == -4 )
#define tospacestyle(x) ( (x) + 4 )

/*
 * 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 */
    err_cantopen,		       /* unable to open input file `%s' */
    err_nodata,			       /* no data in input files */
    err_brokencodepara,		       /* line in codepara didn't begin `\c' */
    err_kwunclosed,		       /* expected `}' after keyword */
    err_kwillegal,		       /* paragraph type expects no keyword */
    err_kwexpected,		       /* paragraph type expects a keyword */
    err_kwtoomany,		       /* paragraph type expects only 1 */
    err_bodyillegal,		       /* paragraph type expects only kws! */
    err_badparatype,		       /* invalid command at start of para */
    err_badmidcmd,		       /* invalid command in mid-para */
    err_unexbrace,		       /* unexpected brace */
    err_explbr,			       /* expected `{' after command */
    err_commenteof,		       /* EOF inside braced comment */
    err_kwexprbr,		       /* expected `}' after cross-ref */
    err_missingrbrace,		       /* unclosed braces at end of para */
    err_nestedstyles,		       /* unable to nest text styles */
    err_nestedindex,		       /* unable to nest `\i' thingys */
    err_nosuchkw,		       /* unresolved cross-reference */
    err_multiBR,		       /* multiple \BRs on same keyword */
    err_nosuchidxtag,		       /* \IM on unknown index tag (warning) */
    err_cantopenw,		       /* can't open output file for write */
    err_macroexists		       /* this macro already exists */
};

/*
 * malloc.c
 */
#ifdef LOGALLOC
void *smalloc(char *file, int line, int size);
void *srealloc(char *file, int line, void *p, int size);
void sfree(char *file, int line, void *p);
#define smalloc(x) smalloc(__FILE__, __LINE__, x)
#define srealloc(x, y) srealloc(__FILE__, __LINE__, x, y)
#define sfree(x) sfree(__FILE__, __LINE__, x)
#else
void *smalloc(int size);
void *srealloc(void *p, int size);
void sfree(void *p);
#endif
void free_word_list(word *w);
void free_para_list(paragraph *p);
word *dup_word_list(word *w);

#define mknew(type) ( (type *) smalloc (sizeof (type)) )
#define mknewa(type, number) ( (type *) smalloc ((number) * sizeof (type)) )
#define resize(array, len) ( srealloc ((array), (len) * sizeof (*(array))) )
#define lenof(array) ( sizeof(array) / sizeof(*(array)) )

/*
 * ustring.c
 */
wchar_t *ustrdup(wchar_t *s);
char *ustrtoa(wchar_t *s, char *outbuf, int size);
int ustrlen(wchar_t *s);
wchar_t *ustrcpy(wchar_t *dest, wchar_t *source);
wchar_t utolower(wchar_t);
int ustrcmp(wchar_t *lhs, wchar_t *rhs);
int ustricmp(wchar_t *lhs, wchar_t *rhs);
wchar_t *ustrlow(wchar_t *s);
wchar_t *ustrftime(wchar_t *fmt, struct tm *timespec);

/*
 * help.c
 */
void help(void);
void usage(void);
void showversion(void);

/*
 * licence.c
 */
void licence(void);

/*
 * version.c
 */
const char *const version;

/*
 * misc.c
 */
typedef struct stackTag *stack;
stack stk_new(void);
void stk_free(stack);
void stk_push(stack, void *);
void *stk_pop(stack);

typedef struct tagRdstring rdstring;
struct tagRdstring {
    int pos, size;
    wchar_t *text;
};
typedef struct tagRdstringc rdstringc;
struct tagRdstringc {
    int pos, size;
    char *text;
};
void rdadd(rdstring *rs, wchar_t c);
void rdadds(rdstring *rs, wchar_t *p);
wchar_t *rdtrim(rdstring *rs);
void rdaddc(rdstringc *rs, char c);
void rdaddsc(rdstringc *rs, char *p);
char *rdtrimc(rdstringc *rs);

int compare_wordlists(word *a, word *b);

void mark_attr_ends(paragraph *sourceform);

typedef struct tagWrappedLine wrappedline;
struct tagWrappedLine {
    wrappedline *next;
    word *begin, *end;		       /* first & last words of line */
    int nspaces;		       /* number of whitespaces in line */
    int shortfall;		       /* how much shorter than max width */
};
wrappedline *wrap_para(word *, int, int, int (*)(word *));
void wrap_free(wrappedline *);

/*
 * input.c
 */
paragraph *read_input(input *in, index *idx);

/*
 * keywords.c
 */
struct keywordlist_Tag {
    int nkeywords;
    int size;
    keyword **keys;
    word **looseends;		       /* non-keyword list element numbers */
    int nlooseends;
    int looseendssize;
};
struct keyword_Tag {
    wchar_t *key;		       /* the keyword itself */
    word *text;			       /* "Chapter 2", "Appendix Q"... */
    				       /* (NB: filepos are not set) */
    paragraph *para;		       /* the paragraph referenced */
};
keyword *kw_lookup(keywordlist *, wchar_t *);
keywordlist *get_keywords(paragraph *);
void free_keywords(keywordlist *);
void subst_keywords(paragraph *, keywordlist *);

/*
 * index.c
 */
index *make_index(void);
void cleanup_index(index *);
/* index_merge takes responsibility for freeing arg 3 iff implicit; never
 * takes responsibility for arg 2 */
void index_merge(index *, int is_explicit, wchar_t *, word *);
void build_index(index *);
void index_debug(index *);

/*
 * contents.c
 */
numberstate *number_init(void);
word *number_mktext(numberstate *, int, int, int, word **);
void number_free(numberstate *);

/*
 * biblio.c
 */
void gen_citations(paragraph *, keywordlist *);

/*
 * style.c
 */
struct userstyle_Tag {
};

/*
 * tree23.c
 */
typedef struct tree23_Tag tree23;
typedef struct enum23_Tag {
    void *node;
    int posn;
} enum23;
tree23 *newtree23(void);
void freetree23(tree23 *);
void *add23(tree23 *, void *, int (*cmp)(void *, void *));
void *find23(tree23 *, void *, int (*cmp)(void *, void *));
void *first23(tree23 *, enum23 *);
void *next23(enum23 *);

/*
 * bk_text.c
 */
void text_backend(paragraph *, keywordlist *, index *);

#endif