History

imported local copy of worgle

Paul Batchelor committed 5 years ago

Commit bb90c2f1 parent 5788b5f8 files · +1995 −2Browse files

Unified · Split

8 files
  1. Makefile +7 −2
  2. worgle/LICENSE +3 −0
  3. worgle/README.org +7 −0
  4. worgle/parg.c +354 −0
  5. worgle/parg.h +192 −0
  6. worgle/worgle.c +1230 −0
  7. worgle/worgle.h +98 −0
  8. worgle/worgle_private.h +104 −0
Makefile+7−2
@@ -2,7 +2,7 @@ · 1 unmodified line
22
33 PORT?=8080
44 WIKI_PATH=sndkit
5−WORGLE=worgle
5+WORGLE=$(abspath worgle/worglite)
66 WORGLE_FLAGS=-g -Werror
77
88 TANGLED=\
@@ -61,6 +61,10 @@ transfer: · 52 unmodified lines
6161 rsync -rvt _site/$(WIKI_PATH)/* _live/$(WIKI_PATH)
6262 rsync -rvt _img _live/$(WIKI_PATH)/
6363
64+
65+worgle/worglite: worgle/worgle.c worgle/parg.c
66+ $(CC) -std=c89 -Wall -pedantic -O3 -DWORGLITE $^ -o $@
67+
6468 server:
6569 weewiki server - $(PORT)
6670
@@ -74,7 +78,8 @@ keys.txt: · 7 unmodified lines
7478 keys.db: keys.txt
7579 ./keys2db < keys.txt | sqlite3 $@
7680
77−tangle: $(TANGLED)
81+tangle: worgle/worglite $(TANGLED)
7882
7983 clean:
8084 $(RM) $(TANGLED)
85+ $(RM) worgle/worglite
worgle/LICENSE+3−0
@@ -0,0 +1,3 @@
1+This software is dual-licensed to the public domain and under the following
2+license: you are granted a perpetual, irrevocable license to copy, modify,
3+publish, and distribute this file as you see fit.
worgle/README.org+7−0
@@ -0,0 +1,7 @@
1+Contained here is a pre-tangled version of Worgle,
2+a highly portable (and highly limited) tangler for
3+noweb-style literate programs written in org and org-mode.
4+
5+Compiling with -DWORGLITE produces worglite, a lightweight
6+version of worgle good enough to tangle the documents here
7+in sndkit.
worgle/parg.c+354−0
@@ -0,0 +1,354 @@
1+/*
2+ * parg - parse argv
3+ *
4+ * Written in 2015-2016 by Joergen Ibsen
5+ *
6+ * To the extent possible under law, the author(s) have dedicated all
7+ * copyright and related and neighboring rights to this software to the
8+ * public domain worldwide. This software is distributed without any
9+ * warranty. <http://creativecommons.org/publicdomain/zero/1.0/>
10+ */
11+
12+#include "parg.h"
13+
14+#include <assert.h>
15+#include <stdlib.h>
16+#include <string.h>
17+
18+/*
19+ * Check if state is at end of argv.
20+ */
21+static int
22+is_argv_end(const struct parg_state *ps, int argc, char *const argv[])
23+{
24+ return ps->optind >= argc || argv[ps->optind] == NULL;
25+}
26+
27+/*
28+ * Match nextchar against optstring.
29+ */
30+static int
31+match_short(struct parg_state *ps, int argc, char *const argv[],
32+ const char *optstring)
33+{
34+ const char *p = strchr(optstring, *ps->nextchar);
35+
36+ if (p == NULL) {
37+ ps->optopt = *ps->nextchar++;
38+ return '?';
39+ }
40+
41+ /* If no option argument, return option */
42+ if (p[1] != ':') {
43+ return *ps->nextchar++;
44+ }
45+
46+ /* If more characters, return as option argument */
47+ if (ps->nextchar[1] != '\0') {
48+ ps->optarg = &ps->nextchar[1];
49+ ps->nextchar = NULL;
50+ return *p;
51+ }
52+
53+ /* If option argument is optional, return option */
54+ if (p[2] == ':') {
55+ return *ps->nextchar++;
56+ }
57+
58+ /* Option argument required, so return next argv element */
59+ if (is_argv_end(ps, argc, argv)) {
60+ ps->optopt = *ps->nextchar++;
61+ return optstring[0] == ':' ? ':' : '?';
62+ }
63+
64+ ps->optarg = argv[ps->optind++];
65+ ps->nextchar = NULL;
66+ return *p;
67+}
68+
69+/*
70+ * Match string at nextchar against longopts.
71+ */
72+static int
73+match_long(struct parg_state *ps, int argc, char *const argv[],
74+ const char *optstring,
75+ const struct parg_option *longopts, int *longindex)
76+{
77+ size_t len;
78+ int num_match = 0;
79+ int match = -1;
80+ int i;
81+
82+ len = strcspn(ps->nextchar, "=");
83+
84+ for (i = 0; longopts[i].name; ++i) {
85+ if (strncmp(ps->nextchar, longopts[i].name, len) == 0) {
86+ match = i;
87+ num_match++;
88+ /* Take if exact match */
89+ if (longopts[i].name[len] == '\0') {
90+ num_match = 1;
91+ break;
92+ }
93+ }
94+ }
95+
96+ /* Return '?' on no or ambiguous match */
97+ if (num_match != 1) {
98+ ps->optopt = 0;
99+ ps->nextchar = NULL;
100+ return '?';
101+ }
102+
103+ assert(match != -1);
104+
105+ if (longindex) {
106+ *longindex = match;
107+ }
108+
109+ if (ps->nextchar[len] == '=') {
110+ /* Option argument present, check if extraneous */
111+ if (longopts[match].has_arg == PARG_NOARG) {
112+ ps->optopt = longopts[match].flag ? 0 : longopts[match].val;
113+ ps->nextchar = NULL;
114+ return optstring[0] == ':' ? ':' : '?';
115+ }
116+ else {
117+ ps->optarg = &ps->nextchar[len + 1];
118+ }
119+ }
120+ else if (longopts[match].has_arg == PARG_REQARG) {
121+ /* Option argument required, so return next argv element */
122+ if (is_argv_end(ps, argc, argv)) {
123+ ps->optopt = longopts[match].flag ? 0 : longopts[match].val;
124+ ps->nextchar = NULL;
125+ return optstring[0] == ':' ? ':' : '?';
126+ }
127+
128+ ps->optarg = argv[ps->optind++];
129+ }
130+
131+ ps->nextchar = NULL;
132+
133+ if (longopts[match].flag != NULL) {
134+ *longopts[match].flag = longopts[match].val;
135+ return 0;
136+ }
137+
138+ return longopts[match].val;
139+}
140+
141+void
142+parg_init(struct parg_state *ps)
143+{
144+ ps->optarg = NULL;
145+ ps->optind = 1;
146+ ps->optopt = '?';
147+ ps->nextchar = NULL;
148+}
149+
150+int
151+parg_getopt(struct parg_state *ps, int argc, char *const argv[],
152+ const char *optstring)
153+{
154+ return parg_getopt_long(ps, argc, argv, optstring, NULL, NULL);
155+}
156+
157+int
158+parg_getopt_long(struct parg_state *ps, int argc, char *const argv[],
159+ const char *optstring,
160+ const struct parg_option *longopts, int *longindex)
161+{
162+ assert(ps != NULL);
163+ assert(argv != NULL);
164+ assert(optstring != NULL);
165+
166+ ps->optarg = NULL;
167+
168+ if (argc < 2) {
169+ return -1;
170+ }
171+
172+ /* Advance to next element if needed */
173+ if (ps->nextchar == NULL || *ps->nextchar == '\0') {
174+ if (is_argv_end(ps, argc, argv)) {
175+ return -1;
176+ }
177+
178+ ps->nextchar = argv[ps->optind++];
179+
180+ /* Check for nonoption element (including '-') */
181+ if (ps->nextchar[0] != '-' || ps->nextchar[1] == '\0') {
182+ ps->optarg = ps->nextchar;
183+ ps->nextchar = NULL;
184+ return 1;
185+ }
186+
187+ /* Check for '--' */
188+ if (ps->nextchar[1] == '-') {
189+ if (ps->nextchar[2] == '\0') {
190+ ps->nextchar = NULL;
191+ return -1;
192+ }
193+
194+ if (longopts != NULL) {
195+ ps->nextchar += 2;
196+
197+ return match_long(ps, argc, argv, optstring,
198+ longopts, longindex);
199+ }
200+ }
201+
202+ ps->nextchar++;
203+ }
204+
205+ /* Match nextchar */
206+ return match_short(ps, argc, argv, optstring);
207+}
208+
209+/*
210+ * Reverse elements of `v` from `i` to `j`.
211+ */
212+static void
213+reverse(char *v[], int i, int j)
214+{
215+ while (j - i > 1) {
216+ char *tmp = v[i];
217+ v[i] = v[j - 1];
218+ v[j - 1] = tmp;
219+ ++i;
220+ --j;
221+ }
222+}
223+
224+/*
225+ * Reorder elements of `argv` with no special cases.
226+ *
227+ * This function assumes there is no `--` element, and the last element
228+ * is not an option missing a required argument.
229+ *
230+ * The algorithm is described here:
231+ * http://hardtoc.com/2016/11/07/reordering-arguments.html
232+ */
233+static int
234+parg_reorder_simple(int argc, char *argv[],
235+ const char *optstring,
236+ const struct parg_option *longopts)
237+{
238+ struct parg_state ps;
239+ int change;
240+ int l = 0;
241+ int m = 0;
242+ int r = 0;
243+
244+ if (argc < 2) {
245+ return argc;
246+ }
247+
248+ do {
249+ int nextind;
250+ int c;
251+
252+ parg_init(&ps);
253+
254+ nextind = ps.optind;
255+
256+ /* Parse until end of argument */
257+ do {
258+ c = parg_getopt_long(&ps, argc, argv, optstring, longopts, NULL);
259+ } while (ps.nextchar != NULL && *ps.nextchar != '\0');
260+
261+ change = 0;
262+
263+ do {
264+ /* Find next non-option */
265+ for (l = nextind; c != 1 && c != -1;) {
266+ l = ps.optind;
267+
268+ do {
269+ c = parg_getopt_long(&ps, argc, argv, optstring, longopts, NULL);
270+ } while (ps.nextchar != NULL && *ps.nextchar != '\0');
271+ }
272+
273+ /* Find next option */
274+ for (m = l; c == 1;) {
275+ m = ps.optind;
276+
277+ do {
278+ c = parg_getopt_long(&ps, argc, argv, optstring, longopts, NULL);
279+ } while (ps.nextchar != NULL && *ps.nextchar != '\0');
280+ }
281+
282+ /* Find next non-option */
283+ for (r = m; c != 1 && c != -1;) {
284+ r = ps.optind;
285+
286+ do {
287+ c = parg_getopt_long(&ps, argc, argv, optstring, longopts, NULL);
288+ } while (ps.nextchar != NULL && *ps.nextchar != '\0');
289+ }
290+
291+ /* Find next option */
292+ for (nextind = r; c == 1;) {
293+ nextind = ps.optind;
294+
295+ do {
296+ c = parg_getopt_long(&ps, argc, argv, optstring, longopts, NULL);
297+ } while (ps.nextchar != NULL && *ps.nextchar != '\0');
298+ }
299+
300+ if (m < r) {
301+ change = 1;
302+ reverse(argv, l, m);
303+ reverse(argv, m, r);
304+ reverse(argv, l, r);
305+ }
306+ } while (c != -1);
307+ } while (change != 0);
308+
309+ return l + (r - m);
310+}
311+
312+int
313+parg_reorder(int argc, char *argv[],
314+ const char *optstring,
315+ const struct parg_option *longopts)
316+{
317+ struct parg_state ps;
318+ int lastind;
319+ int optend;
320+ int c;
321+
322+ assert(argv != NULL);
323+ assert(optstring != NULL);
324+
325+ if (argc < 2) {
326+ return argc;
327+ }
328+
329+ parg_init(&ps);
330+
331+ /* Find end of normal arguments */
332+ do {
333+ lastind = ps.optind;
334+
335+ c = parg_getopt_long(&ps, argc, argv, optstring, longopts, NULL);
336+
337+ /* Check for trailing option with error */
338+ if ((c == '?' || c == ':') && is_argv_end(&ps, argc, argv)) {
339+ lastind = ps.optind - 1;
340+ break;
341+ }
342+ } while (c != -1);
343+
344+ optend = parg_reorder_simple(lastind, argv, optstring, longopts);
345+
346+ /* Rotate `--` or trailing option with error into position */
347+ if (lastind < argc) {
348+ reverse(argv, optend, lastind);
349+ reverse(argv, optend, lastind + 1);
350+ ++optend;
351+ }
352+
353+ return optend;
354+}
worgle/parg.h+192−0
@@ -0,0 +1,192 @@
1+/*
2+ * parg - parse argv
3+ *
4+ * Written in 2015-2016 by Joergen Ibsen
5+ *
6+ * To the extent possible under law, the author(s) have dedicated all
7+ * copyright and related and neighboring rights to this software to the
8+ * public domain worldwide. This software is distributed without any
9+ * warranty. <http://creativecommons.org/publicdomain/zero/1.0/>
10+ */
11+
12+#ifndef PARG_H_INCLUDED
13+#define PARG_H_INCLUDED
14+
15+#ifdef __cplusplus
16+extern "C" {
17+#endif
18+
19+#define PARG_VER_MAJOR 1 /**< Major version number */
20+#define PARG_VER_MINOR 0 /**< Minor version number */
21+#define PARG_VER_PATCH 2 /**< Patch version number */
22+#define PARG_VER_STRING "1.0.2" /**< Version number as a string */
23+
24+/**
25+ * Structure containing state between calls to parser.
26+ *
27+ * @see parg_init
28+ */
29+struct parg_state {
30+ const char *optarg; /**< Pointer to option argument, if any */
31+ int optind; /**< Next index in argv to process */
32+ int optopt; /**< Option value resulting in error, if any */
33+ const char *nextchar; /**< Next character to process */
34+};
35+
36+/**
37+ * Structure for supplying long options to `parg_getopt_long()`.
38+ *
39+ * @see parg_getopt_long
40+ */
41+struct parg_option {
42+ const char *name; /**< Name of option */
43+ int has_arg; /**< Option argument status */
44+ int *flag; /**< Pointer to flag variable */
45+ int val; /**< Value of option */
46+};
47+
48+/**
49+ * Values for `has_arg` flag in `parg_option`.
50+ *
51+ * @see parg_option
52+ */
53+typedef enum {
54+ PARG_NOARG, /**< No argument */
55+ PARG_REQARG, /**< Required argument */
56+ PARG_OPTARG /**< Optional argument */
57+} parg_arg_num;
58+
59+/**
60+ * Initialize `ps`.
61+ *
62+ * Must be called before using state with a parser.
63+ *
64+ * @see parg_state
65+ *
66+ * @param ps pointer to state
67+ */
68+void
69+parg_init(struct parg_state *ps);
70+
71+/**
72+ * Parse next short option in `argv`.
73+ *
74+ * Elements in `argv` that contain short options start with a single dash
75+ * followed by one or more option characters, and optionally an option
76+ * argument for the last option character. Examples are '`-d`', '`-ofile`',
77+ * and '`-dofile`'.
78+ *
79+ * Consecutive calls to this function match the command-line arguments in
80+ * `argv` against the short option characters in `optstring`.
81+ *
82+ * If an option character in `optstring` is followed by a colon, '`:`', the
83+ * option requires an argument. If it is followed by two colons, the option
84+ * may take an optional argument.
85+ *
86+ * If a match is found, `optarg` points to the option argument, if any, and
87+ * the value of the option character is returned.
88+ *
89+ * If a match is found, but is missing a required option argument, `optopt`
90+ * is set to the option character. If the first character in `optstring` is
91+ * '`:`', then '`:`' is returned, otherwise '`?`' is returned.
92+ *
93+ * If no option character in `optstring` matches a short option, `optopt`
94+ * is set to the option character, and '`?`' is returned.
95+ *
96+ * If an element of argv does not contain options (a nonoption element),
97+ * `optarg` points to the element, and `1` is returned.
98+ *
99+ * An element consisting of a single dash, '`-`', is returned as a nonoption.
100+ *
101+ * Parsing stops and `-1` is returned, when the end of `argv` is reached, or
102+ * if an element contains '`--`'.
103+ *
104+ * Works similarly to `getopt`, if `optstring` were prefixed by '`-`'.
105+ *
106+ * @param ps pointer to state
107+ * @param argc number of elements in `argv`
108+ * @param argv array of pointers to command-line arguments
109+ * @param optstring string containing option characters
110+ * @return option value on match, `1` on nonoption element, `-1` on end of
111+ * arguments, '`?`' on unmatched option, '`?`' or '`:`' on option argument
112+ * error
113+ */
114+int
115+parg_getopt(struct parg_state *ps, int argc, char *const argv[],
116+ const char *optstring);
117+
118+/**
119+ * Parse next long or short option in `argv`.
120+ *
121+ * Elements in `argv` that contain a long option start with two dashes
122+ * followed by a string, and optionally an equal sign and an option argument.
123+ * Examples are '`--help`' and '`--size=5`'.
124+ *
125+ * If no exact match is found, an unambiguous prefix of a long option will
126+ * match. For example, if '`foo`' and '`foobar`' are valid long options, then
127+ * '`--fo`' is ambiguous and will not match, '`--foo`' matches exactly, and
128+ * '`--foob`' is an unambiguous prefix and will match.
129+ *
130+ * If a long option match is found, and `flag` is `NULL`, `val` is returned.
131+ *
132+ * If a long option match is found, and `flag` is not `NULL`, `val` is stored
133+ * in the variable `flag` points to, and `0` is returned.
134+ *
135+ * If a long option match is found, but is missing a required option argument,
136+ * or has an option argument even though it takes none, `optopt` is set to
137+ * `val` if `flag` is `NULL`, and `0` otherwise. If the first character in
138+ * `optstring` is '`:`', then '`:`' is returned, otherwise '`?`' is returned.
139+ *
140+ * If `longindex` is not `NULL`, the index of the entry in `longopts` that
141+ * matched is stored there.
142+ *
143+ * If no long option in `longopts` matches a long option, '`?`' is returned.
144+ *
145+ * Handling of nonoptions and short options is like `parg_getopt()`.
146+ *
147+ * If no short options are required, an empty string, `""`, should be passed
148+ * as `optstring`.
149+ *
150+ * Works similarly to `getopt_long`, if `optstring` were prefixed by '`-`'.
151+ *
152+ * @see parg_getopt
153+ *
154+ * @param ps pointer to state
155+ * @param argc number of elements in `argv`
156+ * @param argv array of pointers to command-line arguments
157+ * @param optstring string containing option characters
158+ * @param longopts array of `parg_option` structures
159+ * @param longindex pointer to variable to store index of matching option in
160+ * @return option value on match, `0` for flag option, `1` on nonoption
161+ * element, `-1` on end of arguments, '`?`' on unmatched or ambiguous option,
162+ * '`?`' or '`:`' on option argument error
163+ */
164+int
165+parg_getopt_long(struct parg_state *ps, int argc, char *const argv[],
166+ const char *optstring,
167+ const struct parg_option *longopts, int *longindex);
168+
169+/**
170+ * Reorder elements of `argv` so options appear first.
171+ *
172+ * If there are no long options, `longopts` may be `NULL`.
173+ *
174+ * The return value can be used as `argc` parameter for `parg_getopt()` and
175+ * `parg_getopt_long()`.
176+ *
177+ * @param argc number of elements in `argv`
178+ * @param argv array of pointers to command-line arguments
179+ * @param optstring string containing option characters
180+ * @param longopts array of `parg_option` structures
181+ * @return index of first nonoption in `argv` on success, `-1` on error
182+ */
183+int
184+parg_reorder(int argc, char *argv[],
185+ const char *optstring,
186+ const struct parg_option *longopts);
187+
188+#ifdef __cplusplus
189+} /* extern "C" */
190+#endif
191+
192+#endif /* PARG_H_INCLUDED */
worgle/worgle.c+1230−0
@@ -0,0 +1,1230 @@
1+#include <stdio.h>
2+#include <stdlib.h>
3+#include <string.h>
4+#ifndef WORGLITE
5+#include <sqlite3.h>
6+#endif
7+#include "parg.h"
8+#include "worgle.h"
9+#include "worgle_private.h"
10+#ifndef WORGLITE
11+#include "db.h"
12+#endif
13+
14+static int use_debug = 0;
15+static int use_warnings = 0;
16+static int map_source_code = 0;
17+static char *map_filename = NULL;
18+#ifndef WORGLITE
19+static int generate_db = 0;
20+static char *db_filename = NULL;
21+#endif
22+static int tangle_code = 1;
23+enum {
24+MODE_ORG,
25+MODE_BEGINCODE,
26+MODE_CODE
27+};
28+enum {
29+ORGLET_HEADER,
30+ORGLET_CONTENT,
31+ORGLET_BLKREF,
32+ORGLET_UNKNOWN
33+};
34+static int loadfile(worgle_d *worg, int file);
35+static int parse_name(char *line, size_t len, worgle_string *str);
36+#ifndef WORGLITE
37+static int parse_header(worgle_d *worg,
38+ char *line,
39+ size_t len);
40+#endif
41+static int parse_begin(char *line, size_t len, worgle_string *str);
42+static int check_for_reference(char *line , size_t size, worgle_string *str);
43+static int worgle_getline(char *fullbuf,
44+ char **line,
45+ size_t *pos,
46+ size_t *line_size,
47+ size_t buf_size);
48+static void append_filename(worgle_d *worg, char *filename);
49+#ifndef WORGLITE
50+static void tangle_to_db(worgle_d *worg);
51+#endif
52+static int loadfile(worgle_d *worg, int file)
53+{
54+ FILE *fp;
55+ char *filename;
56+ worgle_textbuf *txt;
57+ size_t size;
58+ char *buf;
59+ txt = &worg->buffers[file];
60+ filename = txt->filename.str;
61+ fp = fopen(filename, "r");
62+
63+ if(fp == NULL) {
64+ fprintf(stderr, "Could not find file %s\n", filename);
65+ return 1;
66+ }
67+ fseek(fp, 0, SEEK_END);
68+ size = ftell(fp);
69+ buf = calloc(1, size);
70+ worgle_textbuf_init(&worg->buffers[file], buf, size);
71+ fseek(fp, 0, SEEK_SET);
72+ fread(buf, size, 1, fp);
73+ fclose(fp);
74+ return 1;
75+}
76+int parse_file(worgle_d *worg, int file)
77+{
78+ char *buf;
79+ size_t size;
80+ worgle_textbuf *curbuf;
81+ worgle_string str;
82+ char *line;
83+ size_t pos;
84+ size_t read;
85+ int mode;
86+ int rc;
87+ int status;
88+
89+ curbuf = &worg->buffers[file];
90+ buf = curbuf->buf;
91+ size = curbuf->size;
92+ worg->curbuf = curbuf;
93+#ifndef WORGLITE
94+ worg->curorg = &worg->orgs[file];
95+ if (file > 0) {
96+ worg->curorg->prev = &worg->orgs[file - 1];
97+ } else {
98+ worg->curorg->prev = NULL;
99+ }
100+#endif
101+ worgle_string_init(&str);
102+ line = NULL;
103+ pos = 0;
104+ mode = MODE_ORG;
105+ rc = 0;
106+ status = 0;
107+ worg->linum = 0;
108+ while (1) {
109+ worg->linum++;
110+ status = worgle_getline(buf, &line, &pos, &read, size);
111+ if(!status) break;
112+ if(mode == MODE_ORG) {
113+ #ifndef WORGLITE
114+ if (generate_db) {
115+ if (read >= 2) {
116+ if (parse_header(worg, line, read)) {
117+ continue;
118+ }
119+ }
120+ }
121+ #endif
122+ if(read >= 7) {
123+ if(!strncmp(line, "#+NAME", 6)) {
124+ #ifndef WORGLITE
125+ if (generate_db) {
126+ worgle_orgfile_append_content(worg, &worg->segblock);
127+ worgle_string_reset(&worg->segblock);
128+ }
129+ #endif
130+ if(line[6] != ':') {
131+ fprintf(stderr,
132+ "line %lu: expected ':'\n",
133+ worg->linum);
134+ rc = 1;
135+ break;
136+ }
137+ mode = MODE_BEGINCODE;
138+ parse_name(line, read, &str);
139+ worgle_begin_block(worg, &str);
140+ #ifndef WORGLITE
141+ continue;
142+ #endif
143+ }
144+ }
145+ #ifndef WORGLITE
146+ if (generate_db) {
147+ #ifndef WORGLITE
148+ if (worg->new_content) {
149+ worg->new_content = 0;
150+ worgle_string_reset(&worg->segblock);
151+ worg->segblock.str = line;
152+ }
153+ worg->segblock.size += read;
154+ #endif
155+ }
156+ #endif
157+ } else if(mode == MODE_CODE) {
158+ if(read >= 9) {
159+ if(!strncmp(line, "#+END_SRC", 9)) {
160+ mode = MODE_ORG;
161+ worg->block_started = 0;
162+ worgle_append_string(worg);
163+ #ifndef WORGLITE
164+ worg->new_content = 1;
165+ #endif
166+ continue;
167+ }
168+ }
169+
170+ if(check_for_reference(line, read, &str)) {
171+ worgle_append_string(worg);
172+ worgle_append_reference(worg, &str);
173+ worg->block_started = 1;
174+ worgle_string_reset(&worg->block);
175+ continue;
176+ }
177+
178+ worg->block.size += read;
179+
180+ if(worg->block_started) {
181+ worg->block.str = line;
182+ worg->block_started = 0;
183+ worg->curline = worg->linum;
184+ }
185+ } else if(mode == MODE_BEGINCODE) {
186+ if (read >= 11) {
187+ if(!strncmp (line, "#+BEGIN_SRC",11)) {
188+ mode = MODE_CODE;
189+ worg->block_started = 1;
190+ worgle_string_reset(&worg->block);
191+ if (parse_begin(line, read, &str) == 2) {
192+ worgle_append_file(worg, &str);
193+ }
194+ continue;
195+ } else {
196+ fwrite(line, read, 1, stderr);
197+ fprintf(stderr,
198+ "line %lu: Expected #+BEGIN_SRC\n",
199+ worg->linum);
200+ rc = 1;
201+ break;
202+ }
203+ }
204+ fprintf(stderr,
205+ "line %lu: Expected #+BEGIN_SRC\n",
206+ worg->linum);
207+ rc = 1;
208+ }
209+ }
210+ return rc;
211+}
212+static int parse_name(char *line, size_t len, worgle_string *str)
213+{
214+ size_t n;
215+ size_t pos;
216+ int mode;
217+
218+ line+=7;
219+ len-=7;
220+ /* *namelen = 0; */
221+ str->size = 0;
222+ str->str = NULL;
223+ if(len <= 0) return 1;
224+ pos = 0;
225+ mode = 0;
226+ for(n = 0; n < len; n++) {
227+ if(mode == 2) break;
228+ switch(mode) {
229+ case 0:
230+ if(line[n] == ' ') {
231+
232+ } else {
233+ str->str = &line[n];
234+ str->size++;
235+ pos++;
236+ mode = 1;
237+ }
238+ break;
239+ case 1:
240+ if(line[n] == 0xa) {
241+ mode = 2;
242+ break;
243+ }
244+ pos++;
245+ str->size++;
246+ break;
247+ default:
248+ break;
249+ }
250+ }
251+ /* *namelen = pos; */
252+ return 1;
253+}
254+void worgle_begin_block(worgle_d *worg, worgle_string *name)
255+{
256+ worg->curblock = worgle_hashmap_get(&worg->dict, name);
257+ if (worgle_block_id_get(worg->curblock) == 0) {
258+ worgle_block_id_set(worg->curblock, worgle_uuid_new(worg));
259+ }
260+ worg->curblock->nblocks++;
261+#ifndef WORGLITE
262+ worgle_orgfile_append_reference(worg, worg->curblock);
263+#endif
264+}
265+#ifndef WORGLITE
266+static int parse_header(worgle_d *worg,
267+ char *line,
268+ size_t len)
269+{
270+ int mode;
271+ int rc;
272+ size_t s;
273+ char *header;
274+ worgle_string str;
275+ int lvl;
276+ mode = 0;
277+
278+ if(line[0] != '*') return 0;
279+
280+ rc = 0;
281+ worgle_string_init(&str);
282+ lvl = 1;
283+ for (s = 1; s < len; s++) {
284+ if (mode == 2) break;
285+ switch (mode) {
286+ case 0:
287+ if (line[s] == '*') {
288+ lvl++;
289+ } else if (line[s] == ' '){
290+ mode = 1;
291+ } else {
292+ mode = 2;
293+ rc = 0;
294+ }
295+ break;
296+ case 1:
297+ rc = 1;
298+ mode = 2;
299+ header = &line[s];
300+ str.str = header;
301+ str.size = len - s;
302+ str.size -= line[len - 1] == '\n';
303+ worgle_orgfile_append_content(worg, &worg->segblock);
304+ worgle_string_reset(&worg->segblock);
305+ worgle_orgfile_append_header(worg,
306+ &str,
307+ lvl);
308+ worg->new_content = 1;
309+ break;
310+ }
311+ }
312+ return rc;
313+}
314+#endif
315+static int parse_begin(char *line, size_t len, worgle_string *str)
316+{
317+ size_t n;
318+ int mode;
319+ int rc;
320+
321+ line += 11;
322+ len -= 11;
323+
324+ if(len <= 0) return 0;
325+
326+
327+ mode = 0;
328+ n = 0;
329+ rc = 1;
330+ str->str = NULL;
331+ str->size = 0;
332+ while(n < len) {
333+ switch(mode) {
334+ case 0: /* initial spaces after BEGIN_SRC */
335+ if(line[n] == ' ') {
336+ n++;
337+ } else {
338+ mode = 1;
339+ }
340+ break;
341+ case 1: /* look for :tangle */
342+ if(line[n] == ' ') {
343+ mode = 0;
344+ n++;
345+ } else {
346+ if(line[n] == ':') {
347+ if(!strncmp(line + n + 1, "tangle", 6)) {
348+ n+=7;
349+ mode = 2;
350+ rc = 2;
351+ }
352+ }
353+ n++;
354+ }
355+ break;
356+ case 2: /* save file name, spaces after tangle */
357+ if(line[n] != ' ') {
358+ str->str = &line[n];
359+ str->size++;
360+ mode = 3;
361+ }
362+ n++;
363+ break;
364+ case 3: /* read up to next space or line break */
365+ if(line[n] == ' ' || line[n] == '\n') {
366+ mode = 4;
367+ } else {
368+ str->size++;
369+ }
370+ n++;
371+ break;
372+ case 4: /* countdown til end */
373+ n++;
374+ break;
375+ }
376+ }
377+
378+ return rc;
379+}
380+void worgle_append_file(worgle_d *worg, worgle_string *filename)
381+{
382+ worgle_file *f;
383+ f = worgle_filelist_append(&worg->flist, filename, worg->curblock);
384+ worgle_file_id_set(f, worgle_uuid_new(worg));
385+}
386+void worgle_append_string(worgle_d *worg)
387+{
388+ worgle_segment *seg;
389+ if(worg->curblock == NULL) return;
390+ if(worg->curline < 0) return;
391+ seg = worgle_block_append_string(worg->curblock,
392+ &worg->block,
393+ worg->curline,
394+ &worg->curbuf->filename);
395+ worgle_segment_id_set(seg, worgle_uuid_new(worg));
396+ worg->curblock->last_seg = seg->id;
397+}
398+void worgle_append_reference(worgle_d *worg, worgle_string *ref)
399+{
400+ worgle_segment *seg;
401+ if(worg->curblock == NULL) return;
402+ seg = worgle_block_append_reference(worg->curblock,
403+ ref,
404+ worg->linum,
405+ &worg->curbuf->filename);
406+ worgle_segment_id_set(seg, worgle_uuid_new(worg));
407+ worg->curblock->last_seg = seg->id;
408+}
409+static int check_for_reference(char *line , size_t size, worgle_string *str)
410+{
411+ int mode;
412+ size_t n;
413+ mode = 0;
414+
415+ str->size = 0;
416+ str->str = NULL;
417+ for(n = 0; n < size; n++) {
418+ if(mode < 0) break;
419+ switch(mode) {
420+ case 0: /* spaces */
421+ if(line[n] == ' ') continue;
422+ else if(line[n] == '<') mode = 1;
423+ else mode = -1;
424+ break;
425+ case 1: /* second < */
426+ if(line[n] == '<') mode = 2;
427+ else mode = -1;
428+ break;
429+ case 2: /* word setup */
430+ str->str = &line[n];
431+ str->size++;
432+ mode = 3;
433+ break;
434+ case 3: /* the word */
435+ if(line[n] == '>') {
436+ mode = 4;
437+ break;
438+ }
439+ str->size++;
440+ break;
441+ case 4: /* last > */
442+ if(line[n] == '>') mode = 5;
443+ else mode = -1;
444+ break;
445+ }
446+ }
447+
448+ return (mode == 5);
449+}
450+static int worgle_getline(char *fullbuf,
451+ char **line,
452+ size_t *pos,
453+ size_t *line_size,
454+ size_t buf_size)
455+{
456+ size_t p;
457+ size_t s;
458+ *line_size = 0;
459+ p = *pos;
460+ *line = &fullbuf[p];
461+ s = 0;
462+ while(1) {
463+ s++;
464+ if(p >= buf_size) return 0;
465+ if(fullbuf[p] == '\n') {
466+ *pos = p + 1;
467+ *line_size = s;
468+ return 1;
469+ }
470+ p++;
471+ }
472+}
473+int worgle_generate(worgle_d *worg)
474+{
475+ return worgle_filelist_write(&worg->flist, &worg->dict);
476+}
477+void worgle_init(worgle_d *worg)
478+{
479+worgle_string_init(&worg->block);
480+#ifndef WORGLITE
481+worgle_string_init(&worg->segblock);
482+#endif
483+worg->curline = -1;
484+worg->block_started = 0;
485+#ifndef WORGLITE
486+worg->new_content = 1;
487+#endif
488+worgle_hashmap_init(&worg->dict);
489+worgle_filelist_init(&worg->flist);
490+worg->curbuf = NULL;
491+worg->buffers = NULL;
492+worg->nbuffers = 0;
493+worg->curblock = NULL;
494+worg->linum = 0;
495+worg->orgs = NULL;
496+worg->curorg = NULL;
497+worg->prog = 0;
498+worg->UUID_count = 1;
499+}
500+void worgle_free(worgle_d *worg)
501+{
502+ int i;
503+ worgle_hashmap_free(&worg->dict);
504+ worgle_filelist_free(&worg->flist);
505+ for(i = 0; i < worg->nbuffers; i++) {
506+ worgle_textbuf_free(&worg->buffers[i]);
507+ }
508+ if(worg->nbuffers > 0) free(worg->buffers);
509+ if(worg->orgs != NULL && worg->nbuffers > 0) {
510+ for(i = 0; i < worg->nbuffers; i++) {
511+ worgle_orgfile_free(&worg->orgs[i]);
512+ }
513+ free(worg->orgs);
514+ }
515+}
516+void worgle_string_reset(worgle_string *str)
517+{
518+ str->str = NULL;
519+ str->size = 0;
520+}
521+void worgle_string_init(worgle_string *str)
522+{
523+ worgle_string_reset(str);
524+}
525+int worgle_string_write(FILE *fp, worgle_string *str)
526+{
527+ return fwrite(str->str, 1, str->size, fp);
528+}
529+void worgle_segment_init(worgle_segment *s,
530+ int type,
531+ worgle_string *str,
532+ worgle_string *filename,
533+ size_t linum)
534+{
535+ s->type = type;
536+ s->str = *str;
537+ s->filename = filename;
538+ s->linum = linum;
539+ s->nxt = NULL;
540+ s->id = 0;
541+}
542+int worgle_segment_write(worgle_segment *s, worgle_hashmap *h, FILE *fp)
543+{
544+ worgle_block *b;
545+ if(s->type == SEGTYPE_TEXT) {
546+ if(use_debug) {
547+ fprintf(fp, "#line %lu \"", s->linum);
548+ worgle_string_write(fp, s->filename);
549+ fprintf(fp, "\"\n");
550+ }
551+ worgle_string_write(fp, &s->str);
552+ } else {
553+ if(!worgle_hashmap_find(h, &s->str, &b)) {
554+ fprintf(stderr, "Warning: could not find reference segment '");
555+ worgle_string_write(stderr, &s->str);
556+ fprintf(stderr, "'\n");
557+ if(use_warnings == 2) {
558+ return 0;
559+ } else {
560+ return 1;
561+ }
562+ }
563+ return worgle_block_write(b, h, fp);
564+ }
565+
566+ return 1;
567+}
568+int worgle_segment_is_text(worgle_segment *s)
569+{
570+ return s->type == SEGTYPE_TEXT;
571+}
572+
573+int worgle_segment_is_reference(worgle_segment *s)
574+{
575+ return s->type == SEGTYPE_REFERENCE;
576+}
577+void worgle_block_init(worgle_block *b)
578+{
579+ b->nsegs = 0;
580+ b->head = NULL;
581+ b->tail = NULL;
582+ b->nxt = NULL;
583+ b->am_i_used = 0;
584+ worgle_string_init(&b->name);
585+ b->nblocks = 0;
586+ b->last_seg = -1;
587+ b->id = 0;
588+}
589+void worgle_block_free(worgle_block *lst)
590+{
591+ worgle_segment *s;
592+ worgle_segment *nxt;
593+ int n;
594+ s = lst->head;
595+ for(n = 0; n < lst->nsegs; n++) {
596+ nxt = s->nxt;
597+ free(s);
598+ s = nxt;
599+ }
600+}
601+worgle_segment* worgle_block_append_segment(worgle_block *b,
602+ worgle_string *str,
603+ int type,
604+ size_t linum,
605+ worgle_string *filename)
606+{
607+ worgle_segment *s;
608+ s = malloc(sizeof(worgle_segment));
609+ if(b->nsegs == 0) {
610+ b->head = s;
611+ b->tail = s;
612+ }
613+ worgle_segment_init(s, type, str, filename, linum);
614+ b->tail->nxt = s;
615+ b->tail = s;
616+ b->nsegs++;
617+ /* TODO: remove this */
618+ /* b->last_seg = s->id; */
619+ return s;
620+}
621+worgle_segment* worgle_block_append_string(worgle_block *b,
622+ worgle_string *str,
623+ size_t linum,
624+ worgle_string *filename)
625+{
626+ return worgle_block_append_segment(b, str, SEGTYPE_TEXT, linum, filename);
627+}
628+worgle_segment* worgle_block_append_reference(worgle_block *b,
629+ worgle_string *str,
630+ size_t linum,
631+ worgle_string *filename)
632+{
633+ return worgle_block_append_segment(b, str, SEGTYPE_REFERENCE,
634+ linum, filename);
635+}
636+int worgle_block_write(worgle_block *b, worgle_hashmap *h, FILE *fp)
637+{
638+ worgle_segment *s;
639+ int n;
640+ s = b->head;
641+ b->am_i_used = 1;
642+ for(n = 0; n < b->nsegs; n++) {
643+ if(!worgle_segment_write(s, h, fp)) return 0;
644+ s = s->nxt;
645+ }
646+
647+ return 1;
648+}
649+void worgle_blocklist_init(worgle_blocklist *lst)
650+{
651+ lst->head = NULL;
652+ lst->tail = NULL;
653+ lst->nblocks = 0;
654+}
655+void worgle_blocklist_free(worgle_blocklist *lst)
656+{
657+ worgle_block *b;
658+ worgle_block *nxt;
659+ int n;
660+ b = lst->head;
661+ for(n = 0; n < lst->nblocks; n++) {
662+ nxt = b->nxt;
663+ worgle_block_free(b);
664+ free(b);
665+ b = nxt;
666+ }
667+}
668+void worgle_blocklist_append(worgle_blocklist *lst, worgle_block *b)
669+{
670+ if(lst->nblocks == 0) {
671+ lst->head = b;
672+ lst->tail = b;
673+ }
674+ lst->tail->nxt = b;
675+ lst->tail = b;
676+ lst->nblocks++;
677+}
678+void worgle_hashmap_init(worgle_hashmap *h)
679+{
680+ int n;
681+ h->nwords = 0;
682+ for(n = 0; n < HASH_SIZE; n++) {
683+ worgle_blocklist_init(&h->blk[n]);
684+ }
685+}
686+void worgle_hashmap_free(worgle_hashmap *h)
687+{
688+ int n;
689+ for(n = 0; n < HASH_SIZE; n++) {
690+ worgle_blocklist_free(&h->blk[n]);
691+ }
692+}
693+static int hash(const char *str, size_t size)
694+{
695+ unsigned int h = 5381;
696+ size_t i = 0;
697+
698+ for(i = 0; i < size; i++) {
699+ h = ((h << 5) + h) ^ str[i];
700+ h %= 0x7FFFFFFF;
701+ }
702+
703+ return h % HASH_SIZE;
704+}
705+int worgle_hashmap_find(worgle_hashmap *h, worgle_string *name, worgle_block **b)
706+{
707+ int pos;
708+ worgle_blocklist *lst;
709+ int n;
710+ worgle_block *blk;
711+ pos = hash(name->str, name->size);
712+ lst = &h->blk[pos];
713+
714+ blk = lst->head;
715+ for(n = 0; n < lst->nblocks; n++) {
716+ if(name->size == blk->name.size) {
717+ if(!strncmp(name->str, blk->name.str, name->size)) {
718+ *b = blk;
719+ return 1;
720+ }
721+ }
722+ blk = blk->nxt;
723+ }
724+ return 0;
725+}
726+worgle_block * worgle_hashmap_get(worgle_hashmap *h, worgle_string *name)
727+{
728+ worgle_block *b;
729+ worgle_blocklist *lst;
730+ int pos;
731+
732+ if(worgle_hashmap_find(h, name, &b)) return b;
733+ pos = hash(name->str, name->size);
734+ b = NULL;
735+ b = malloc(sizeof(worgle_block));
736+ worgle_block_init(b);
737+ b->name = *name;
738+ lst = &h->blk[pos];
739+ worgle_blocklist_append(lst, b);
740+ return b;
741+}
742+int worgle_file_write(worgle_file *f, worgle_hashmap *h)
743+{
744+ FILE *fp;
745+ char tmp[128];
746+ size_t n;
747+ size_t size;
748+ int rc;
749+
750+ if(f->filename.size > 128) size = 127;
751+ else size = f->filename.size;
752+ for(n = 0; n < size; n++) tmp[n] = f->filename.str[n];
753+ tmp[size] = 0;
754+
755+ fp = fopen(tmp, "w");
756+
757+ rc = worgle_block_write(f->top, h, fp);
758+
759+ fclose(fp);
760+ return rc;
761+}
762+void worgle_filelist_init(worgle_filelist *flist)
763+{
764+ flist->head = NULL;
765+ flist->tail = NULL;
766+ flist->nfiles = 0;
767+}
768+void worgle_filelist_free(worgle_filelist *flist)
769+{
770+ worgle_file *f;
771+ worgle_file *nxt;
772+ int n;
773+ f = flist->head;
774+ for(n = 0; n < flist->nfiles; n++) {
775+ nxt = f->nxt;
776+ free(f);
777+ f = nxt;
778+ }
779+}
780+worgle_file* worgle_filelist_append(worgle_filelist *flist,
781+ worgle_string *name,
782+ worgle_block *top)
783+{
784+ worgle_file *f;
785+ f = malloc(sizeof(worgle_file));
786+ f->filename = *name;
787+ f->top = top;
788+ f->nxt = NULL;
789+ f->id = 0;
790+
791+ if(flist->nfiles == 0) {
792+ flist->head = f;
793+ flist->tail = f;
794+ }
795+ flist->tail->nxt = f;
796+ flist->tail = f;
797+ flist->nfiles++;
798+ return f;
799+}
800+int worgle_filelist_write(worgle_filelist *flist, worgle_hashmap *h)
801+{
802+ worgle_file *f;
803+ int n;
804+
805+ f = flist->head;
806+ for(n = 0; n < flist->nfiles; n++) {
807+ if(!worgle_file_write(f, h)) return 0;
808+ f = f->nxt;
809+ }
810+
811+ return 1;
812+}
813+void worgle_textbuf_zero(worgle_textbuf *txt)
814+{
815+ txt->buf = NULL;
816+ worgle_string_init(&txt->filename);
817+ txt->size = 0;
818+}
819+void worgle_textbuf_init(worgle_textbuf *txt,
820+ char *buf,
821+ size_t bufsize)
822+{
823+ txt->buf = buf;
824+ txt->size = bufsize;
825+}
826+void worgle_textbuf_free(worgle_textbuf *txt)
827+{
828+ if(txt->buf != NULL) free(txt->buf);
829+ worgle_textbuf_zero(txt);
830+}
831+worgle_long worgle_uuid_new(worgle_d *worg)
832+{
833+ return worg->UUID_count++;
834+}
835+worgle_long worgle_segment_id_get(worgle_segment *s)
836+{
837+ return s->id;
838+}
839+
840+void worgle_segment_id_set(worgle_segment *s, worgle_long id)
841+{
842+ s->id = id;
843+}
844+worgle_long worgle_block_id_get(worgle_block *b)
845+{
846+ return b->id;
847+}
848+
849+void worgle_block_id_set(worgle_block *b, worgle_long id)
850+{
851+ b->id = id;
852+}
853+void worgle_file_id_set(worgle_file *f, worgle_long id)
854+{
855+ f->id = id;
856+}
857+void worgle_orglet_id_set(worgle_orglet *orglet,
858+ worgle_long id)
859+{
860+ orglet->id = id;
861+}
862+void worgle_orgfile_init(worgle_orgfile *org)
863+{
864+ org->head = NULL;
865+ org->tail = NULL;
866+ org->size = 0;
867+ org->prev = NULL;
868+}
869+void worgle_orgfile_free(worgle_orgfile *org)
870+{
871+ worgle_orglet *ent;
872+ worgle_orglet *nxt;
873+ int n;
874+ if (org->size > 0) {
875+ ent = org->head;
876+ for (n = 0; n < org->size; n++) {
877+ nxt = ent->next;
878+ worgle_orglet_free(ent);
879+ ent = nxt;
880+ }
881+ }
882+}
883+void worgle_orgfile_append(worgle_d *worg,
884+ worgle_orgfile *file,
885+ worgle_orglet *orglet)
886+{
887+ if (file->size <= 0) {
888+ file->head = orglet;
889+ if (file->prev != NULL) {
890+ file->prev->tail->next = file->head;
891+ }
892+ file->tail = orglet;
893+ }
894+
895+ file->tail->next = orglet;
896+ file->tail = orglet;
897+ file->size++;
898+ worgle_orglet_id_set(orglet, worgle_uuid_new(worg));
899+}
900+void worgle_orgfile_append_header(worgle_d *worg,
901+ worgle_string *header,
902+ int lvl)
903+{
904+ worgle_orglet *orglet;
905+ worgle_orglet_header *h;
906+ worgle_orgfile *f;
907+ size_t linum;
908+
909+ f = worg->curorg;
910+ linum = worg->linum;
911+
912+ orglet = calloc(1, sizeof(worgle_orglet));
913+ h = calloc(1, sizeof(worgle_orglet_header));
914+
915+ h->str = *header;
916+ h->lvl = lvl;
917+ worgle_orglet_init(orglet);
918+
919+ orglet->type = ORGLET_HEADER;
920+ orglet->ud = h;
921+ orglet->linum = linum;
922+ worgle_orgfile_append(worg, f, orglet);
923+}
924+void worgle_orgfile_append_content(worgle_d *worg,
925+ worgle_string *text)
926+{
927+ worgle_orglet *orglet;
928+ worgle_orglet_content *c;
929+ worgle_orgfile *f;
930+ size_t linum;
931+
932+ if (text->size == 0) return;
933+ if (text->size == 1) return;
934+
935+ f = worg->curorg;
936+ linum = worg->linum;
937+
938+ orglet = calloc(1, sizeof(worgle_orglet));
939+ c = calloc(1, sizeof(worgle_orglet_content));
940+
941+ c->text = *text;
942+
943+ /* printf("CONTENT(%d): '", c->text.size); */
944+ /* fwrite(c->text.str, 1, c->text.size, stdout); */
945+ /* printf("'\n"); */
946+
947+ worgle_orglet_init(orglet);
948+
949+ orglet->type = ORGLET_CONTENT;
950+ orglet->ud = c;
951+ orglet->linum = linum;
952+ worgle_orgfile_append(worg, f, orglet);
953+}
954+void worgle_orgfile_append_reference(worgle_d *worg,
955+ worgle_block *blk)
956+{
957+ worgle_orglet *orglet;
958+ worgle_orglet_blkref *br;
959+ worgle_orgfile *f;
960+ size_t linum;
961+
962+ f = worg->curorg;
963+ linum = worg->linum;
964+
965+ orglet = calloc(1, sizeof(worgle_orglet));
966+ br = calloc(1, sizeof(worgle_orglet_blkref));
967+
968+ br->blk = blk;
969+ br->pos = blk->nblocks;
970+ br->prev_lastseg = blk->last_seg;
971+ br->segoff = blk->nsegs;
972+ worgle_orglet_init(orglet);
973+
974+ orglet->type = ORGLET_BLKREF;
975+ orglet->ud = br;
976+ orglet->linum = linum;
977+ worgle_orgfile_append(worg, f, orglet);
978+}
979+void worgle_orglet_init(worgle_orglet *orglet)
980+{
981+ orglet->type = ORGLET_UNKNOWN;
982+ orglet->ud = NULL;
983+ orglet->next = NULL;
984+ orglet->linum = 0;
985+ orglet->id = 0;
986+}
987+void worgle_orglet_free(worgle_orglet *orglet)
988+{
989+ free(orglet->ud);
990+ free(orglet);
991+}
992+int worgle_warn_unused(worgle_d *worg)
993+{
994+ worgle_hashmap *dict;
995+ worgle_block *blk;
996+ worgle_blocklist *lst;
997+ int n;
998+ int b;
999+ int rc;
1000+
1001+ dict = &worg->dict;
1002+ rc = 0;
1003+
1004+ for(n = 0; n < HASH_SIZE; n++) {
1005+ lst = &dict->blk[n];
1006+ blk = lst->head;
1007+ for(b = 0; b < lst->nblocks; b++) {
1008+ if(blk->am_i_used == 0) {
1009+ fprintf(stderr, "Warning: block '");
1010+ worgle_string_write(stderr, &blk->name);
1011+ fprintf(stderr, "' unused.\n");
1012+ fprintf(stderr, "First declared in ");
1013+ worgle_string_write(stderr,
1014+ blk->head->filename);
1015+ fprintf(stderr, ", line %lu\n",
1016+ blk->head->linum);
1017+ if(use_warnings == 2) rc = 1;
1018+ }
1019+ blk = blk->nxt;
1020+ }
1021+ }
1022+ return rc;
1023+}
1024+static void append_filename(worgle_d *worg, char *filename)
1025+{
1026+ worgle_string *str;
1027+ int pos;
1028+ pos = worg->nbuffers;
1029+ worg->nbuffers++;
1030+ if(worg->nbuffers == 1) {
1031+ worg->buffers = calloc(1, sizeof(worgle_textbuf));
1032+ } else {
1033+ worg->buffers = realloc(worg->buffers,
1034+ sizeof(worgle_textbuf) *
1035+ worg->nbuffers);
1036+ }
1037+ str = &worg->buffers[pos].filename;
1038+ str->str = filename;
1039+ str->size = strlen(filename);
1040+#ifndef WORGLITE
1041+ if(worg->nbuffers == 1) {
1042+ worg->orgs = calloc(1, sizeof(worgle_orgfile));
1043+ } else {
1044+ worg->orgs = realloc(worg->orgs,
1045+ sizeof(worgle_orgfile) *
1046+ worg->nbuffers);
1047+ }
1048+ if(worg->nbuffers > 0) {
1049+ worgle_orgfile_init(&worg->orgs[worg->nbuffers - 1]);
1050+ }
1051+#endif
1052+}
1053+#ifndef WORGLITE
1054+static void tangle_to_db(worgle_d *worg)
1055+{
1056+ sqlite3 *db;
1057+ int rc;
1058+
1059+ if(db_filename == NULL) return;
1060+
1061+ rc = sqlite3_open(db_filename, &db);
1062+ if(rc) {
1063+ fprintf(stderr,
1064+ "Could not open database: %s",
1065+ sqlite3_errmsg(db));
1066+ sqlite3_close(db);
1067+ return;
1068+ }
1069+ worgle_db_clear(db, worg->prog);
1070+ worgle_db_schemas(worg, db);
1071+ worgle_db_generate(worg, db);
1072+ sqlite3_close(db);
1073+}
1074+#endif
1075+void worgle_map(worgle_d *worg, worgle_block *b, int lvl, FILE *out)
1076+{
1077+ int i;
1078+ worgle_segment *s;
1079+ worgle_block *newblk;
1080+ worgle_hashmap *h;
1081+
1082+ h = &worg->dict;
1083+ if(lvl != 0) {
1084+ for(i = 0; i <= lvl; i++) {
1085+ fputc('*', out);
1086+ }
1087+ fputc(' ', out);
1088+ worgle_string_write(out, &b->name);
1089+ fputc('\n', out);
1090+ }
1091+
1092+ s = b->head;
1093+
1094+ newblk = NULL;
1095+
1096+ for(i = 0; i < b->nsegs; i++) {
1097+ if(s->type == SEGTYPE_TEXT) {
1098+ if(s->str.size > 0) {
1099+ worgle_string_write(out, s->filename);
1100+ fprintf(out, ":%lu\n", s->linum);
1101+ fprintf(out, "#+NAME: ");
1102+ worgle_string_write(out, &b->name);
1103+ fprintf(out, "_%d\n", i);
1104+ fprintf(out, "#+BEGIN_SRC\n");
1105+ worgle_string_write(out, &s->str);
1106+ fprintf(out, "#+END_SRC");
1107+ }
1108+ fprintf(out, "\n");
1109+ } else if(worgle_hashmap_find(h, &s->str, &newblk)) {
1110+ worgle_map(worg, newblk, lvl + 1, out);
1111+ }
1112+ s = s->nxt;
1113+ }
1114+}
1115+void worgle_map_files(worgle_d *worg, char *filename)
1116+{
1117+ int n;
1118+ worgle_file *f;
1119+ FILE *fp;
1120+
1121+ fp = fopen(filename, "w");
1122+ if(fp == NULL) return;
1123+
1124+ f = worg->flist.head;
1125+
1126+ fprintf(fp, "#+TITLE: Code Map\n");
1127+ for(n = 0; n < worg->flist.nfiles; n++) {
1128+ worgle_map_a_file(worg, f, fp);
1129+ f = f->nxt;
1130+ }
1131+
1132+ fclose(fp);
1133+}
1134+
1135+void worgle_map_a_file(worgle_d *worg, worgle_file *file, FILE *out)
1136+{
1137+ fprintf(out, "* ");
1138+ worgle_string_write(out, &file->filename);
1139+ fprintf(out, "\n");
1140+ worgle_map(worg, file->top, 0, out);
1141+}
1142+
1143+int main(int argc, char *argv[])
1144+{
1145+ worgle_d worg;
1146+ char *filename;
1147+ int rc;
1148+ int i;
1149+ struct parg_state ps;
1150+ int c;
1151+ worgle_init(&worg);
1152+ filename = NULL;
1153+ if(argc < 2) {
1154+ fprintf(stderr, "Usage: %s filename.org\n", argv[0]);
1155+ return 1;
1156+ }
1157+ parg_init(&ps);
1158+ while ((c = parg_getopt(&ps, argc, argv, "gW:m:d:p:n")) != -1) {
1159+ switch(c) {
1160+ case 1:
1161+ filename = (char *)ps.optarg;
1162+ append_filename(&worg, (char *)ps.optarg);
1163+ break;
1164+ case 'g':
1165+ use_debug = 1;
1166+ break;
1167+ case 'W':
1168+ if(!strncmp(ps.optarg, "soft", 4)) {
1169+ use_warnings = 1;
1170+ } else if(!strncmp(ps.optarg, "error", 5)) {
1171+ use_warnings = 2;
1172+ } else {
1173+ fprintf(stderr, "Unidentified warning mode '%s'\n", ps.optarg);
1174+ return 1;
1175+ }
1176+ break;
1177+ case 'm':
1178+ map_source_code = 1;
1179+ map_filename = (char *)ps.optarg;
1180+ break;
1181+ case 'd':
1182+ #ifndef WORGLITE
1183+ generate_db = 1;
1184+ db_filename = (char *)ps.optarg;
1185+ #else
1186+ fprintf(stderr, "Database flag (-d) is not enabled\n");
1187+ return 1;
1188+ #endif
1189+ break;
1190+ case 'p':
1191+ worg.prog = atoi(ps.optarg);
1192+ break;
1193+ case 'n':
1194+ tangle_code = 0;
1195+ break;
1196+ default:
1197+ fprintf(stderr, "Unknown option -%c\n", c);
1198+ return 1;
1199+ }
1200+ }
1201+ if(filename == NULL) {
1202+ fprintf(stderr, "No filename specified\n");
1203+ return 1;
1204+ }
1205+ rc = 0;
1206+ for(i = 0; i < worg.nbuffers; i++) {
1207+ rc = loadfile(&worg, i);
1208+ if(!rc) goto cleanup;
1209+ }
1210+ for (i = 0; i < worg.nbuffers; i++) {
1211+ rc = parse_file(&worg, i);
1212+ if (rc) goto cleanup;
1213+ }
1214+ #ifndef WORGLITE
1215+ if (generate_db) {
1216+ worgle_orgfile_append_content(&worg, &worg.segblock);
1217+ }
1218+ #endif
1219+ if(!rc && tangle_code) if(!worgle_generate(&worg)) rc = 1;
1220+ if(!rc && use_warnings) rc = worgle_warn_unused(&worg);
1221+ if(map_source_code && map_filename != NULL) {
1222+ worgle_map_files(&worg, map_filename);
1223+ }
1224+ #ifndef WORGLITE
1225+ if(generate_db) tangle_to_db(&worg);
1226+ #endif
1227+ cleanup:
1228+ worgle_free(&worg);
1229+ return rc;
1230+}
worgle/worgle.h+98−0
@@ -0,0 +1,98 @@
1+#ifndef WORGLE_H
2+#define WORGLE_H
3+typedef struct worgle_d worgle_d;
4+typedef struct worgle_string worgle_string;
5+typedef struct worgle_segment worgle_segment;
6+typedef struct worgle_block worgle_block;
7+typedef struct worgle_blocklist worgle_blocklist;
8+typedef struct worgle_hashmap worgle_hashmap;
9+typedef struct worgle_file worgle_file;
10+typedef struct worgle_filelist worgle_filelist;
11+typedef struct worgle_textbuf worgle_textbuf;
12+typedef unsigned long worgle_long;
13+typedef struct worgle_orgfile worgle_orgfile;
14+typedef struct worgle_orglet worgle_orglet;
15+typedef struct worgle_orglet_header worgle_orglet_header;
16+typedef struct worgle_orglet_content worgle_orglet_content;
17+typedef struct worgle_orglet_blkref worgle_orglet_blkref;
18+int parse_file(worgle_d *worg, int file);
19+void worgle_begin_block(worgle_d *worg, worgle_string *name);
20+void worgle_append_file(worgle_d *worg, worgle_string *filename);
21+void worgle_append_string(worgle_d *worg);
22+void worgle_append_reference(worgle_d *worg, worgle_string *ref);
23+int worgle_generate(worgle_d *worg);
24+void worgle_init(worgle_d *worg);
25+void worgle_free(worgle_d *worg);
26+void worgle_string_reset(worgle_string *str);
27+void worgle_string_init(worgle_string *str);
28+int worgle_string_write(FILE *fp, worgle_string *str);
29+void worgle_segment_init(worgle_segment *s,
30+ int type,
31+ worgle_string *str,
32+ worgle_string *filename,
33+ size_t linum);
34+int worgle_segment_write(worgle_segment *s, worgle_hashmap *h, FILE *fp);
35+int worgle_segment_is_text(worgle_segment *s);
36+int worgle_segment_is_reference(worgle_segment *s);
37+void worgle_block_init(worgle_block *b);
38+void worgle_block_free(worgle_block *lst);
39+worgle_segment* worgle_block_append_segment(worgle_block *b,
40+ worgle_string *str,
41+ int type,
42+ size_t linum,
43+ worgle_string *filename);
44+worgle_segment* worgle_block_append_string(worgle_block *b,
45+ worgle_string *str,
46+ size_t linum,
47+ worgle_string *filename);
48+worgle_segment* worgle_block_append_reference(worgle_block *b,
49+ worgle_string *str,
50+ size_t linum,
51+ worgle_string *filename);
52+int worgle_block_write(worgle_block *b, worgle_hashmap *h, FILE *fp);
53+void worgle_blocklist_init(worgle_blocklist *lst);
54+void worgle_blocklist_free(worgle_blocklist *lst);
55+void worgle_blocklist_append(worgle_blocklist *lst, worgle_block *b);
56+void worgle_hashmap_init(worgle_hashmap *h);
57+void worgle_hashmap_free(worgle_hashmap *h);
58+int worgle_hashmap_find(worgle_hashmap *h, worgle_string *name, worgle_block **b);
59+worgle_block * worgle_hashmap_get(worgle_hashmap *h, worgle_string *name);
60+int worgle_file_write(worgle_file *f, worgle_hashmap *h);
61+void worgle_filelist_init(worgle_filelist *flist);
62+void worgle_filelist_free(worgle_filelist *flist);
63+worgle_file* worgle_filelist_append(worgle_filelist *flist,
64+ worgle_string *name,
65+ worgle_block *top);
66+int worgle_filelist_write(worgle_filelist *flist, worgle_hashmap *h);
67+void worgle_textbuf_zero(worgle_textbuf *txt);
68+void worgle_textbuf_init(worgle_textbuf *txt,
69+ char *buf,
70+ size_t bufsize);
71+void worgle_textbuf_free(worgle_textbuf *txt);
72+worgle_long worgle_uuid_new(worgle_d *worg);
73+worgle_long worgle_segment_id_get(worgle_segment *s);
74+void worgle_segment_id_set(worgle_segment *s, worgle_long id);
75+worgle_long worgle_block_id_get(worgle_block *b);
76+void worgle_block_id_set(worgle_block *b, worgle_long id);
77+void worgle_file_id_set(worgle_file *f, worgle_long id);
78+void worgle_orglet_id_set(worgle_orglet *orglet,
79+ worgle_long id);
80+void worgle_orgfile_init(worgle_orgfile *org);
81+void worgle_orgfile_free(worgle_orgfile *org);
82+void worgle_orgfile_append(worgle_d *worg,
83+ worgle_orgfile *file,
84+ worgle_orglet *orglet);
85+void worgle_orgfile_append_header(worgle_d *worg,
86+ worgle_string *header,
87+ int lvl);
88+void worgle_orgfile_append_content(worgle_d *worg,
89+ worgle_string *text);
90+void worgle_orgfile_append_reference(worgle_d *worg,
91+ worgle_block *blk);
92+void worgle_orglet_init(worgle_orglet *orglet);
93+void worgle_orglet_free(worgle_orglet *orglet);
94+int worgle_warn_unused(worgle_d *worg);
95+void worgle_map(worgle_d *worg, worgle_block *b, int lvl, FILE *out);
96+void worgle_map_files(worgle_d *worg, char *filename);
97+void worgle_map_a_file(worgle_d *worg, worgle_file *file, FILE *out);
98+#endif
worgle/worgle_private.h+104−0
@@ -0,0 +1,104 @@
1+#ifndef WORGLE_PRIVATE_H
2+struct worgle_string {
3+ char *str;
4+ size_t size;
5+};
6+enum {
7+SEGTYPE_TEXT,
8+SEGTYPE_REFERENCE
9+};
10+struct worgle_segment {
11+ int type;
12+ worgle_string str;
13+ size_t linum;
14+ worgle_string *filename;
15+ worgle_segment *nxt;
16+ worgle_long id;
17+};
18+struct worgle_block {
19+ int nsegs;
20+ worgle_segment *head;
21+ worgle_segment *tail;
22+ worgle_string name;
23+ int am_i_used;
24+ worgle_block *nxt;
25+ int nblocks;
26+ int last_seg;
27+ worgle_long id;
28+};
29+struct worgle_blocklist {
30+ int nblocks;
31+ worgle_block *head;
32+ worgle_block *tail;
33+};
34+#define HASH_SIZE 256
35+struct worgle_hashmap {
36+ worgle_blocklist blk[HASH_SIZE];
37+ int nwords;
38+};
39+struct worgle_file {
40+ worgle_string filename;
41+ worgle_block *top;
42+ worgle_file *nxt;
43+ worgle_long id;
44+};
45+struct worgle_filelist {
46+ worgle_file *head;
47+ worgle_file *tail;
48+ int nfiles;
49+};
50+struct worgle_textbuf {
51+ char *buf;
52+ size_t size;
53+ worgle_string filename;
54+};
55+struct worgle_orglet_header {
56+ worgle_string str;
57+ int lvl;
58+};
59+struct worgle_orglet_content {
60+ worgle_string text;
61+};
62+struct worgle_orglet_blkref {
63+ worgle_block *blk;
64+ int pos;
65+ int prev_lastseg;
66+ int segoff;
67+};
68+struct worgle_orglet {
69+ int type;
70+ void *ud;
71+ worgle_orglet *next;
72+ size_t linum;
73+ worgle_long id;
74+};
75+struct worgle_orgfile {
76+ worgle_orglet *head;
77+ worgle_orglet *tail;
78+ worgle_orgfile *prev;
79+ int size;
80+};
81+struct worgle_d {
82+ worgle_string block;
83+ #ifndef WORGLITE
84+ worgle_string segblock;
85+ #endif
86+ long curline;
87+ int block_started;
88+ #ifndef WORGLITE
89+ int new_content;
90+ #endif
91+ worgle_hashmap dict;
92+ worgle_filelist flist;
93+ worgle_textbuf *curbuf;
94+ worgle_textbuf *buffers;
95+ int nbuffers;
96+ worgle_block *curblock;
97+ size_t linum;
98+ worgle_orgfile *orgs;
99+ worgle_orgfile *curorg;
100+ int prog;
101+ worgle_long UUID_count;
102+};
103+#define WORGLE_PRIVATE_H
104+#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t