Discount

Sample programs

The Discount distribution includes a few sample programs, which are woefully undocumented, but give a good idea of how to call the library.

They are:

Theme
processes a markdown document and wraps the rest of a html document around it using a template file
mkd2html
processes a markdown document and wraps it with the rest of a html document. Unlike theme, it doesn’t use a template file.
makepage
like mkd2html, but it generates a xhtml document.

An annotated sample program

This program is about as simple as you can get for rendering a markdown document. I’ve annotated it to try and describe it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mkdio.h>


int
main(argc, argv)
char **argv;
{

I need a flag structure pointer (mkd_flag_t*) and a document pointer (MMIOT*). flag_arg and flag_err are used here to handle setting option flags

    mkd_flag_t *flags;
    char *flag_arg;
    char *flag_err;
    MMIOT *doc;

Before using a flag blob, it needs to be initialized. mkd_flags() is the initializer (with mkd_free_flags() as the corresponding cleanup function.)

    if ( (flags = mkd_flags()) == NULL ) {
        fprintf(stderr, "out of memory initializing flag blob?\n");
        exit(1);
    }

Here I’ll process options using mkd_set_flag_string() – this function munches the flag string I pass it, so if I want to preserve the original option string I need to copy it and pass the copy to mkd_set_flag_string().

    while ( (argc > 1) && (strncmp(argv[1], "-f", 2) == 0) ) {
        flag_arg = strdup(2+argv[1]);
        argc--;
        argv++;

You can see the options by calling show_flags() show_flags() is not exposed in the API, so you’d need to define before calling it.

        if ( strcmp(argv[0], "-f?") == 0 ) {
            extern void show_flags(int, int, mkd_flag_t*);
            show_flags(1, 1, NULL);
            exit(0);
        }

Here’s where we parse a single option string; mkd_set_flag_string() splits the option string apart at each comma (so -fhtml5,strict is identical to the two options -fhtml5 -fstrict) and returns NULL if everything is valid, or a pointer to the first unknown flag if not.

        if ( (flag_err = mkd_set_flag_string(flags, flag_arg)) != NULL ) {
            fprintf(stderr, "unknown argument %s\n", flag_err);
            exit(1);
        }

Since I used strdup() to duplicate the flag option string, I need to free()` it when I’m done using it.

        free(flag_arg);
    }

Standard unix here; if an input file is given on the command line, use freopen() to associate it to stdin

    if ( (argc > 1) && (freopen(argv[1], "r", stdin) == NULL) ) {
        fprintf(stderr, "cannot open %s for input\n", argv[1]);
        exit(1);
    }

Here we read our input; if it is successful, it returns a MMIOT pointer that we can use to further process the document.

    if ( (doc=mkd_in(stdin, flags)) == NULL ) {
        fprintf(stderr, "unable to load %s\n", (argc>1) ? argv[1] : "markdown source");
        exit(1);
    }

With the document in hand we call mkd_compile to convert the markdown to HTML, then mkd_generatehtml() to write it to standard output.

    if ( mkd_compile(doc, flags) )
        mkd_generatehtml(doc, stdout);
    else
        fprintf(stderr, "unable to compile %s\n", (argc>1) ? argv[1] : "markdown source");

And when we’re done we need to call mkd_cleanup() to deallocate the MMIOT that the document is stored in & mkd_free_flags() to deallocate our previously allocated flag blob.

    mkd_cleanup(doc);
    mkd_free_flags(flags);

And that’s it

    exit(0);
}