mistake, and prohibiting it make some of the code a bit cleaner.
Equally, every section of code should be interpolated at least once -
-with two exceptions. These exceptions are imposed by the tool, not
-the library. A different client could impose different rules on the
-names of top-level code sections.
-
-The first exception we have already seen. A section name starting
-__Example:__ indicates code that is not to be included in the final product.
-
-The second exception is for the top level code sections which will be
-written to files. Again these are identified by their section name.
-This must start with __File:__ the following text (after optional
-spaces) will be used as a file name.
-
-Any section containing code that does not start __Example:__ or
-__File:__ must be included in some other section exactly once.
+with one exception. This exception is imposed by the
+tool, not the library. A different client could impose different
+rules on the names of top-level code sections.
+
+One example of the exception we have already seen. A section name
+starting __Example:__ indicates code that is not to be included in the
+final product. Any leading word will do, providing there is a space,
+and the first space is preceded by a colon, that section name will be
+ignored.
+
+A special case of this exception exists for the leading word
+__File__. These sections are the top level code sections and they
+will be written to the named file. Thus a section named
+__File: foo__ should not be referenced by another section, and its
+contents after all references are expanded will be written to the file
+__foo__.
+
+Any section containing code that does not start __Word:__
+must be included in some other section exactly once.
### Multiple files
### File: mdcode.h
+ #include <stdio.h>
## exported types
## exported functions
#include <unistd.h>
#include <stdlib.h>
+ #include <stdio.h>
#include "mdcode.h"
Now we need a lookup table to be able to find sections by name.
Something that provides an `n*log(N)` search time is probably
justified, but for now I want a minimal stand-alone program so a
-linked list managed by insertion-sort will do. As a comparison
-function it is easiest to sort based on length before content. So
-sections won't be in standard lexical order, but that isn't important.
+linked list managed by insertion-sort will do.
+
+The text compare function will likely be useful for any clients of our
+library, so we may as well export it.
If we cannot find a section, we simply want to create it. This allows
sections and references to be created in any order. Sections with
no references or no content will cause a warning eventually.
+#### exported functions
+
+ int text_cmp(struct text a, struct text b);
+
#### internal functions
- static int text_cmp(struct text a, struct text b)
+ int text_cmp(struct text a, struct text b)
{
- if (a.len != b.len)
+ int len = a.len;
+ if (len > b.len)
+ len = b.len;
+ int cmp = strncmp(a.txt, b.txt, len);
+ if (cmp)
+ return cmp;
+ else
return a.len - b.len;
- return strncmp(a.txt, b.txt, a.len);
}
static struct psection *section_find(struct psection **list, struct text name)
The indents we insert will all be spaces. This might not work well
for `Makefiles`.
-##### client functions
+##### internal functions
- static void code_print(FILE *out, struct code_node *node,
- char *fname)
+ void code_node_print(FILE *out, struct code_node *node,
+ char *fname)
{
for (; node; node = node->next) {
char *c = node->code.txt;
}
}
+###### exported functions
+ void code_node_print(FILE *out, struct code_node *node, char *fname);
+
### Bringing it all together
We are just about ready for the `main` function of the tool which will
#include <errno.h>
#include <sys/mman.h>
#include <string.h>
- #include <stdio.h>
##### client functions
fprintf(stderr, "%s\n", msg);
}
+ static char *strnchr(char *haystack, int len, char needle)
+ {
+ while (len > 0 && *haystack && *haystack != needle) {
+ haystack++;
+ len--;
+ }
+ return len > 0 && *haystack == needle ? haystack : NULL;
+ }
+
int main(int argc, char *argv[])
{
int fd;
(code_free(s->code), prev = s, s = s->next, free(prev))) {
FILE *fl;
char fname[1024];
- if (strncmp(s->section.txt, "Example:", 8) == 0)
+ char *spc = strnchr(s->section.txt, s->section.len, ' ');
+
+ if (spc > s->section.txt && spc[-1] == ':' &&
+ strncmp(s->section.txt, "File: ", 6) != 0)
+ /* Ignore this section */
continue;
- if (strncmp(s->section.txt, "File:", 5) != 0) {
- fprintf(stderr, "Unreferenced section is not a file name: %.*s\n",
+ if (strncmp(s->section.txt, "File: ", 6) != 0) {
+ fprintf(stderr, "Code in unreferenced section that is not ignored or a file name: %.*s\n",
s->section.len, s->section.txt);
errs++;
continue;
errs++;
continue;
}
- code_print(fl, s->code, argv[1]);
+ code_node_print(fl, s->code, argv[1]);
fclose(fl);
}
exit(!!errs);