From 9ad2ccb9489996b0877667686e64f519ed1eae2f Mon Sep 17 00:00:00 2001 From: Andrea Pappacoda Date: Tue, 23 Aug 2022 12:47:52 +0200 Subject: [PATCH] Wo wo something is working --- mdoc_thoughts.md | 6 +-- miniman.c | 137 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 114 insertions(+), 29 deletions(-) diff --git a/mdoc_thoughts.md b/mdoc_thoughts.md index cf0dcaf..a8ffeba 100644 --- a/mdoc_thoughts.md +++ b/mdoc_thoughts.md @@ -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 diff --git a/miniman.c b/miniman.c index 4043df7..0af16bc 100644 --- a/miniman.c +++ b/miniman.c @@ -1,6 +1,7 @@ #include /* fprintf, fopen, fgets */ #include /* exit, EXIT_FAILURE */ #include /* strlen */ +#include /* 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; } -- 2.45.2