@@ 97,10 97,10 @@ _look like_ and that's explicit markup is exactly what we want to avoid, so the
`Fl()` function will automatically prefix long options with two hyphens, so that
`Fl(v)` produces `-v`, but `Fl(version)` produces `--version`. Of course this is
not always desired, because some tools like pretty much every C compiler have
-long options that start with a single hiphen, so there will be a `Flm()`
+long options that start with a single hiphen, so there will be a `Fm()`
(flag manual) function that allows you to be explicit about the number of
-hyphens a specific flag will have (so `Fl(v)` becomes `Flm(-v)` and
-`Fl(version)` becomes `Flm(--version)`, but please don't do this, I really like
+hyphens a specific flag will have (so `Fl(v)` becomes `Fm(-v)` and
+`Fl(version)` becomes `Fm(--version)`, but please don't do this, I really like
stacking short options like `grep -Eiv`).
Here are a few parts of cloudflare-ddns' manpage in mdoc format
@@ 1,6 1,7 @@
#include <stdio.h> /* fprintf, fopen, fgets */
#include <stdlib.h> /* exit, EXIT_FAILURE */
#include <string.h> /* strlen */
+#include <ctype.h> /* islower, isupper */
/*
* lines must be hard-wrapped at 80 characters, so the maximum length of a C
@@ 8,28 9,7 @@
*/
#define LINE_STRLEN 82
-int main(const int argc, const char* argv[]) {
- FILE* file;
- char line[LINE_STRLEN];
- int found = 0; /* _Bool is not available in C89 */
- int i = 10;
- char buffer[LINE_STRLEN];
- size_t length;
-
- (void)argc;
-
- fprintf(stderr,
- "Usage: %s [file] [-o output]\n"
- "If no file is given, or if file is -, reads from stdin\n"
- "Currently only reading from a file is supported\n\n",
- argv[0]
- );
-
- file = fopen(argv[1], "rb");
- if (file == NULL) {
- return EXIT_FAILURE;
- }
-
+static void parse_header(FILE* file) {
/*
* I could do this with several loops.
*
@@ 38,6 18,12 @@ int main(const int argc, const char* argv[]) {
* manpage title and the date, respectively.
*/
+ char line[LINE_STRLEN];
+ char buffer[LINE_STRLEN];
+ size_t length;
+
+ int found = 0; /* _Bool is not available in C89 */
+
while (!found) {
fgets(line, LINE_STRLEN, file);
switch (line[0]) {
@@ 79,21 65,120 @@ int main(const int argc, const char* argv[]) {
found = 1;
}
}
+}
- while (i --> 0) {
+static void parse_trivial(FILE* file) {
+ char line[LINE_STRLEN];
+ fpos_t fpos;
+
+ while (1) {
+ fgetpos(file, &fpos);
fgets(line, LINE_STRLEN, file);
+ /* Handle comments, section headers and empty lines */
switch (line[0]) {
case ';':
printf(".\\\"%s", line + 1);
- break;
+ continue;
+ /* FIXME: what about subsections? i.e. ## */
case '#':
printf(".Sh%s", line + 1);
- break;
+ continue;
+ case '\n':
+ puts(".");
+ continue;
}
+ /*
+ * "complex line" found, i.e. a line that is not directly translatable
+ * to an mdoc macro line.
+ * Rewinds the file cursor by one line as I didn't print it.
+ */
+ fsetpos(file, &fpos);
+ break;
+ }
+}
+
+int main(const int argc, const char* argv[]) {
+ FILE* file;
+ int i = 100;
+ int c1, c2, c3; /* character + EOF */
+ int is_top_level; /* _Bool */
+
+ (void)argc;
+
+ fprintf(stderr,
+ "Usage: %s [file] [-o output]\n"
+ "If no file is given, or if file is -, reads from stdin\n"
+ "Currently only reading from a file is supported\n\n",
+ argv[0]
+ );
- /*fprintf(stderr, "line: %s\n", line);*/
+ file = fopen(argv[1], "rb");
+ if (file == NULL) {
+ return EXIT_FAILURE;
}
+
+ parse_header(file);
+ parse_trivial(file);
+
+ /*
+ * How can I handle "complex lines"?
+ *
+ * I could loop over all the text, char by char, and keep track of when I
+ * encounter an uppercase character. If in the next iteration I encounter
+ * a lowercase character, I keep track of that too. If I then encounter
+ * an opening parenthesys, it means that I've encountered a function.
+ *
+ * Now, how I handle the functions? As I need to translate to mdoc, I have
+ * to follow the rules of the MACRO SYNTAX section of OpenBSD's mdoc(7)
+ * manual. If a macro is callable, I can simply translate it in place (?),
+ * if it is not callable I have a problem: to make the cloudflare-ddns(1)
+ * example work I need to insert the macro on a new line when it is not
+ * callable, while mdoc allows you to write non-callable macros inside
+ * other macros, and they'll be simply written out as simple text.
+ * One way I could handle this is that if the non-callable function is not
+ * inside any other function I can write it on a new line, otherwise I just
+ * copy its text. Anyway I think that this will not happen as much as it
+ * happens in mdoc, as miniman is a bit more explicit.
+ * Wait, maybe I'm wrong. Maybe I should insert a new macro line (\n + .)
+ * everytime a top-level function is opened.
+ */
+
+ is_top_level = 1;
+
+ /* recursion? */
+ while(i --> 0) {
+ parse_trivial(file);
+ c1 = getc(file);
+ if (isupper(c1)) {
+ c2 = getc(file);
+ if (islower(c2)) {
+ c3 = getc(file);
+ if (c3 == '(') { /* this is an opening function */
+ if (is_top_level) {
+ fputs("\n.", stdout);
+ is_top_level = 0;
+ }
+ putchar(c1);
+ putchar(c2);
+ putchar(' ');
+ while ((c1 = getc(file)) != ')') {
+ if (c1 == '(') {
+ c1 = ' ';
+ }
+ putchar(c1);
+ }
+ putchar(' ');
+ is_top_level = 1;
+ }
+ }
+ }
+
+ /*if (!isupper(c1)) {
+ putchar(c1);
+ }*/
+ }
+
fclose(file);
return 0;
}