~tachi/miniman

9ad2ccb9489996b0877667686e64f519ed1eae2f — Andrea Pappacoda 2 years ago 0cebedf
Wo wo something is working
2 files changed, 114 insertions(+), 29 deletions(-)

M mdoc_thoughts.md
M miniman.c
M mdoc_thoughts.md => mdoc_thoughts.md +3 -3
@@ 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

M miniman.c => miniman.c +111 -26
@@ 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;
}