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
2 2
3PORT?=80803PORT?=8080
4WIKI_PATH=sndkit4WIKI_PATH=sndkit
5WORGLE=worgle5WORGLE=$(abspath worgle/worglite)
6WORGLE_FLAGS=-g -Werror6WORGLE_FLAGS=-g -Werror
7 7
8TANGLED=\8TANGLED=\
@@ -61,6 +61,10 @@ transfer: · 52 unmodified lines
61 rsync -rvt _site/$(WIKI_PATH)/* _live/$(WIKI_PATH)61 rsync -rvt _site/$(WIKI_PATH)/* _live/$(WIKI_PATH)
62 rsync -rvt _img _live/$(WIKI_PATH)/62 rsync -rvt _img _live/$(WIKI_PATH)/
63 63
64
65worgle/worglite: worgle/worgle.c worgle/parg.c
66 $(CC) -std=c89 -Wall -pedantic -O3 -DWORGLITE $^ -o $@
67
64server:68server:
65 weewiki server - $(PORT)69 weewiki server - $(PORT)
66 70
@@ -74,7 +78,8 @@ keys.txt: · 7 unmodified lines
74keys.db: keys.txt78keys.db: keys.txt
75 ./keys2db < keys.txt | sqlite3 $@79 ./keys2db < keys.txt | sqlite3 $@
76 80
77tangle: $(TANGLED)81tangle: worgle/worglite $(TANGLED)
78 82
79clean:83clean:
80 $(RM) $(TANGLED)84 $(RM) $(TANGLED)
85 $(RM) worgle/worglite
worgle/LICENSE+3−0
@@ -0,0 +1,3 @@
1This software is dual-licensed to the public domain and under the following
2license: you are granted a perpetual, irrevocable license to copy, modify,
3publish, and distribute this file as you see fit.
worgle/README.org+7−0
@@ -0,0 +1,7 @@
1Contained here is a pre-tangled version of Worgle,
2a highly portable (and highly limited) tangler for
3noweb-style literate programs written in org and org-mode.
4
5Compiling with -DWORGLITE produces worglite, a lightweight
6version of worgle good enough to tangle the documents here
7in 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 */
21static int
22is_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 */
30static int
31match_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 */
72static int
73match_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
141void
142parg_init(struct parg_state *ps)
143{
144 ps->optarg = NULL;
145 ps->optind = 1;
146 ps->optopt = '?';
147 ps->nextchar = NULL;
148}
149
150int
151parg_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
157int
158parg_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 */
212static void
213reverse(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 */
233static int
234parg_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
312int
313parg_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
16extern "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 */
29struct 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 */
41struct 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 */
53typedef 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 */
68void
69parg_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 */
114int
115parg_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 */
164int
165parg_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 */
183int
184parg_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
14static int use_debug = 0;
15static int use_warnings = 0;
16static int map_source_code = 0;
17static char *map_filename = NULL;
18#ifndef WORGLITE
19static int generate_db = 0;
20static char *db_filename = NULL;
21#endif
22static int tangle_code = 1;
23enum {
24MODE_ORG,
25MODE_BEGINCODE,
26MODE_CODE
27};
28enum {
29ORGLET_HEADER,
30ORGLET_CONTENT,
31ORGLET_BLKREF,
32ORGLET_UNKNOWN
33};
34static int loadfile(worgle_d *worg, int file);
35static int parse_name(char *line, size_t len, worgle_string *str);
36#ifndef WORGLITE
37static int parse_header(worgle_d *worg,
38 char *line,
39 size_t len);
40#endif
41static int parse_begin(char *line, size_t len, worgle_string *str);
42static int check_for_reference(char *line , size_t size, worgle_string *str);
43static int worgle_getline(char *fullbuf,
44 char **line,
45 size_t *pos,
46 size_t *line_size,
47 size_t buf_size);
48static void append_filename(worgle_d *worg, char *filename);
49#ifndef WORGLITE
50static void tangle_to_db(worgle_d *worg);
51#endif
52static 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}
76int 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}
212static 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}
254void 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
266static 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
315static 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}
380void 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}
386void 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}
398void 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}
409static 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}
450static 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}
473int worgle_generate(worgle_d *worg)
474{
475 return worgle_filelist_write(&worg->flist, &worg->dict);
476}
477void worgle_init(worgle_d *worg)
478{
479worgle_string_init(&worg->block);
480#ifndef WORGLITE
481worgle_string_init(&worg->segblock);
482#endif
483worg->curline = -1;
484worg->block_started = 0;
485#ifndef WORGLITE
486worg->new_content = 1;
487#endif
488worgle_hashmap_init(&worg->dict);
489worgle_filelist_init(&worg->flist);
490worg->curbuf = NULL;
491worg->buffers = NULL;
492worg->nbuffers = 0;
493worg->curblock = NULL;
494worg->linum = 0;
495worg->orgs = NULL;
496worg->curorg = NULL;
497worg->prog = 0;
498worg->UUID_count = 1;
499}
500void 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}
516void worgle_string_reset(worgle_string *str)
517{
518 str->str = NULL;
519 str->size = 0;
520}
521void worgle_string_init(worgle_string *str)
522{
523 worgle_string_reset(str);
524}
525int worgle_string_write(FILE *fp, worgle_string *str)
526{
527 return fwrite(str->str, 1, str->size, fp);
528}
529void 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}
542int 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}
568int worgle_segment_is_text(worgle_segment *s)
569{
570 return s->type == SEGTYPE_TEXT;
571}
572
573int worgle_segment_is_reference(worgle_segment *s)
574{
575 return s->type == SEGTYPE_REFERENCE;
576}
577void 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}
589void 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}
601worgle_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}
621worgle_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}
628worgle_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}
636int 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}
649void worgle_blocklist_init(worgle_blocklist *lst)
650{
651 lst->head = NULL;
652 lst->tail = NULL;
653 lst->nblocks = 0;
654}
655void 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}
668void 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}
678void 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}
686void 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}
693static 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}
705int 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}
726worgle_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}
742int 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}
762void worgle_filelist_init(worgle_filelist *flist)
763{
764 flist->head = NULL;
765 flist->tail = NULL;
766 flist->nfiles = 0;
767}
768void 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}
780worgle_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}
800int 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}
813void worgle_textbuf_zero(worgle_textbuf *txt)
814{
815 txt->buf = NULL;
816 worgle_string_init(&txt->filename);
817 txt->size = 0;
818}
819void worgle_textbuf_init(worgle_textbuf *txt,
820 char *buf,
821 size_t bufsize)
822{
823 txt->buf = buf;
824 txt->size = bufsize;
825}
826void worgle_textbuf_free(worgle_textbuf *txt)
827{
828 if(txt->buf != NULL) free(txt->buf);
829 worgle_textbuf_zero(txt);
830}
831worgle_long worgle_uuid_new(worgle_d *worg)
832{
833 return worg->UUID_count++;
834}
835worgle_long worgle_segment_id_get(worgle_segment *s)
836{
837 return s->id;
838}
839
840void worgle_segment_id_set(worgle_segment *s, worgle_long id)
841{
842 s->id = id;
843}
844worgle_long worgle_block_id_get(worgle_block *b)
845{
846 return b->id;
847}
848
849void worgle_block_id_set(worgle_block *b, worgle_long id)
850{
851 b->id = id;
852}
853void worgle_file_id_set(worgle_file *f, worgle_long id)
854{
855 f->id = id;
856}
857void worgle_orglet_id_set(worgle_orglet *orglet,
858 worgle_long id)
859{
860 orglet->id = id;
861}
862void worgle_orgfile_init(worgle_orgfile *org)
863{
864 org->head = NULL;
865 org->tail = NULL;
866 org->size = 0;
867 org->prev = NULL;
868}
869void 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}
883void 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}
900void 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}
924void 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}
954void 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}
979void 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}
987void worgle_orglet_free(worgle_orglet *orglet)
988{
989 free(orglet->ud);
990 free(orglet);
991}
992int 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}
1024static 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
1054static 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
1075void 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}
1115void 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
1135void 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
1143int 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
3typedef struct worgle_d worgle_d;
4typedef struct worgle_string worgle_string;
5typedef struct worgle_segment worgle_segment;
6typedef struct worgle_block worgle_block;
7typedef struct worgle_blocklist worgle_blocklist;
8typedef struct worgle_hashmap worgle_hashmap;
9typedef struct worgle_file worgle_file;
10typedef struct worgle_filelist worgle_filelist;
11typedef struct worgle_textbuf worgle_textbuf;
12typedef unsigned long worgle_long;
13typedef struct worgle_orgfile worgle_orgfile;
14typedef struct worgle_orglet worgle_orglet;
15typedef struct worgle_orglet_header worgle_orglet_header;
16typedef struct worgle_orglet_content worgle_orglet_content;
17typedef struct worgle_orglet_blkref worgle_orglet_blkref;
18int parse_file(worgle_d *worg, int file);
19void worgle_begin_block(worgle_d *worg, worgle_string *name);
20void worgle_append_file(worgle_d *worg, worgle_string *filename);
21void worgle_append_string(worgle_d *worg);
22void worgle_append_reference(worgle_d *worg, worgle_string *ref);
23int worgle_generate(worgle_d *worg);
24void worgle_init(worgle_d *worg);
25void worgle_free(worgle_d *worg);
26void worgle_string_reset(worgle_string *str);
27void worgle_string_init(worgle_string *str);
28int worgle_string_write(FILE *fp, worgle_string *str);
29void worgle_segment_init(worgle_segment *s,
30 int type,
31 worgle_string *str,
32 worgle_string *filename,
33 size_t linum);
34int worgle_segment_write(worgle_segment *s, worgle_hashmap *h, FILE *fp);
35int worgle_segment_is_text(worgle_segment *s);
36int worgle_segment_is_reference(worgle_segment *s);
37void worgle_block_init(worgle_block *b);
38void worgle_block_free(worgle_block *lst);
39worgle_segment* worgle_block_append_segment(worgle_block *b,
40 worgle_string *str,
41 int type,
42 size_t linum,
43 worgle_string *filename);
44worgle_segment* worgle_block_append_string(worgle_block *b,
45 worgle_string *str,
46 size_t linum,
47 worgle_string *filename);
48worgle_segment* worgle_block_append_reference(worgle_block *b,
49 worgle_string *str,
50 size_t linum,
51 worgle_string *filename);
52int worgle_block_write(worgle_block *b, worgle_hashmap *h, FILE *fp);
53void worgle_blocklist_init(worgle_blocklist *lst);
54void worgle_blocklist_free(worgle_blocklist *lst);
55void worgle_blocklist_append(worgle_blocklist *lst, worgle_block *b);
56void worgle_hashmap_init(worgle_hashmap *h);
57void worgle_hashmap_free(worgle_hashmap *h);
58int worgle_hashmap_find(worgle_hashmap *h, worgle_string *name, worgle_block **b);
59worgle_block * worgle_hashmap_get(worgle_hashmap *h, worgle_string *name);
60int worgle_file_write(worgle_file *f, worgle_hashmap *h);
61void worgle_filelist_init(worgle_filelist *flist);
62void worgle_filelist_free(worgle_filelist *flist);
63worgle_file* worgle_filelist_append(worgle_filelist *flist,
64 worgle_string *name,
65 worgle_block *top);
66int worgle_filelist_write(worgle_filelist *flist, worgle_hashmap *h);
67void worgle_textbuf_zero(worgle_textbuf *txt);
68void worgle_textbuf_init(worgle_textbuf *txt,
69 char *buf,
70 size_t bufsize);
71void worgle_textbuf_free(worgle_textbuf *txt);
72worgle_long worgle_uuid_new(worgle_d *worg);
73worgle_long worgle_segment_id_get(worgle_segment *s);
74void worgle_segment_id_set(worgle_segment *s, worgle_long id);
75worgle_long worgle_block_id_get(worgle_block *b);
76void worgle_block_id_set(worgle_block *b, worgle_long id);
77void worgle_file_id_set(worgle_file *f, worgle_long id);
78void worgle_orglet_id_set(worgle_orglet *orglet,
79 worgle_long id);
80void worgle_orgfile_init(worgle_orgfile *org);
81void worgle_orgfile_free(worgle_orgfile *org);
82void worgle_orgfile_append(worgle_d *worg,
83 worgle_orgfile *file,
84 worgle_orglet *orglet);
85void worgle_orgfile_append_header(worgle_d *worg,
86 worgle_string *header,
87 int lvl);
88void worgle_orgfile_append_content(worgle_d *worg,
89 worgle_string *text);
90void worgle_orgfile_append_reference(worgle_d *worg,
91 worgle_block *blk);
92void worgle_orglet_init(worgle_orglet *orglet);
93void worgle_orglet_free(worgle_orglet *orglet);
94int worgle_warn_unused(worgle_d *worg);
95void worgle_map(worgle_d *worg, worgle_block *b, int lvl, FILE *out);
96void worgle_map_files(worgle_d *worg, char *filename);
97void 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
2struct worgle_string {
3 char *str;
4 size_t size;
5};
6enum {
7SEGTYPE_TEXT,
8SEGTYPE_REFERENCE
9};
10struct 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};
18struct 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};
29struct worgle_blocklist {
30 int nblocks;
31 worgle_block *head;
32 worgle_block *tail;
33};
34#define HASH_SIZE 256
35struct worgle_hashmap {
36 worgle_blocklist blk[HASH_SIZE];
37 int nwords;
38};
39struct worgle_file {
40 worgle_string filename;
41 worgle_block *top;
42 worgle_file *nxt;
43 worgle_long id;
44};
45struct worgle_filelist {
46 worgle_file *head;
47 worgle_file *tail;
48 int nfiles;
49};
50struct worgle_textbuf {
51 char *buf;
52 size_t size;
53 worgle_string filename;
54};
55struct worgle_orglet_header {
56 worgle_string str;
57 int lvl;
58};
59struct worgle_orglet_content {
60 worgle_string text;
61};
62struct worgle_orglet_blkref {
63 worgle_block *blk;
64 int pos;
65 int prev_lastseg;
66 int segoff;
67};
68struct worgle_orglet {
69 int type;
70 void *ud;
71 worgle_orglet *next;
72 size_t linum;
73 worgle_long id;
74};
75struct worgle_orgfile {
76 worgle_orglet *head;
77 worgle_orglet *tail;
78 worgle_orgfile *prev;
79 int size;
80};
81struct 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