nihdoc

WIP markup parser (txt -> html)
git clone git://git.alexkarle.com.com/blag
Log | Files | Refs | README | LICENSE

commit d6eb447ca4c50e4ad9628ec9b7ed74dc513f4ee5 (patch)
parent 262f0252386c62ef7fe27f0cf52f39b5b198adde
Author: Alex Karle <alex@alexkarle.com>
Date:   Thu, 23 Dec 2021 21:51:54 -0500

refactor: Convert from singleton state struct -> globals

On one hand, globals are considered bad practice. On the other.. using a
singleton struct is basically the same thing. Might as well save the
argument passing!

Diffstat:
Mblag.c | 227+++++++++++++++++++++++++++++++++++++------------------------------------------
1 file changed, 106 insertions(+), 121 deletions(-)

diff --git a/blag.c b/blag.c @@ -10,6 +10,8 @@ #include <unistd.h> #include <stdbool.h> + +/* Global Constants and Enums */ char *FMT_STRS[] = { ['_'] = "em", ['*'] = "strong", @@ -33,23 +35,25 @@ enum Link { DESC_PARSE, }; -typedef struct State { - int c; - enum Block in; - enum Link in_link; - int hlvl; - bool fmts[256]; /* indexed by _ * ` */ - bool escape; - char lnkbuf[2048]; - int lnkidx; - int indent; - int previndent; - int listdepth; - int lastc; - bool ol; - bool linestarted; -} state; +/* Start Global State */ +int c = '0'; +enum Block in = NONE; +enum Link in_link = NOL; +int hlvl = 0; +bool fmts[256] = {false}; /* indexed by _ * ` */ +bool escape = false; +char lnkbuf[2048] = {0}; +int lnkidx = 0; +int indent = 0; +int previndent = 0; +int listdepth = 0; +int lastc = '0'; +bool ol = false; +bool linestarted = false; + + +/* Helper functions */ void putesc(int c) { switch (c) { case '<': printf("&lt;"); break; @@ -59,159 +63,140 @@ void putesc(int c) { } } -void newlist(state *s) { - s->in = LIST; - s->previndent = s->indent; - printf("<%s>\n<li>\n", s->ol ? "ol" : "ul"); - s->listdepth++; +void newlist() { + in = LIST; + previndent = indent; + printf("<%s>\n<li>\n", ol ? "ol" : "ul"); + listdepth++; } -int endlist(state *s) { - s->in = LIST; - s->previndent = s->indent; - printf("</li>\n</%s>\n", s->ol ? "ol" : "ul"); - return --s->listdepth; +int endlist() { + in = LIST; + previndent = indent; + printf("</li>\n</%s>\n", ol ? "ol" : "ul"); + return --listdepth; } -void maybe_startp(state *s) { +void maybe_startp() { /* All inline types should start the paragraph if no other major type present*/ - if (s->in == NONE) { - s->in = PARAGRAPH; + if (in == NONE) { + in = PARAGRAPH; printf("<p>\n"); } } -void handle_lf(state *s) { - s->indent = 0; - s->linestarted = false; +void handle_lf() { + indent = 0; + linestarted = false; /* single line types (one lf to close) */ - if (s->in == HEADER) { - s->in = NONE; - printf("</h%d>\n", s->hlvl); + if (in == HEADER) { + in = NONE; + printf("</h%d>\n", hlvl); } /* terminate url parsing in links */ - if (s->in_link == URL_PARSE) { - s->in_link = DESC_PARSE; + if (in_link == URL_PARSE) { + in_link = DESC_PARSE; printf("\">"); } /* multi-line types (two lf to close) */ - if (s->lastc == '\n') { - switch (s->in) { + if (lastc == '\n') { + switch (in) { case PARAGRAPH: printf("</p>\n"); break; case CODE: printf("</code></pre>\n"); break; case QUOTE: printf("</blockquote>\n"); break; case LIST: - s->previndent = 0; - while (endlist(s)) + previndent = 0; + while (endlist()) ; break; default: break; /* no op */ } - s->in = NONE; + in = NONE; } } -bool fmt_disabled(state *s) { +bool fmt_disabled() { /* `` blocks disable all but the next `, likewise CODE makes all disabled */ - if (s->in == CODE || s->in_link == URL_PARSE) { + if (in == CODE || in_link == URL_PARSE) { return true; } else { - return s->fmts['`'] && s->c != '`'; + return fmts['`'] && c != '`'; } } -void toggle_format(state *s) { - if (!fmt_disabled(s)) { - maybe_startp(s); - printf("<%s%s>", s->fmts[s->c] ? "/" : "", FMT_STRS[s->c]); - s->fmts[s->c] ^= true; +void toggle_format() { + if (!fmt_disabled()) { + maybe_startp(); + printf("<%s%s>", fmts[c] ? "/" : "", FMT_STRS[c]); + fmts[c] ^= true; } else { - putesc(s->c); + putesc(c); } } int parse() { /* Mini state machine (home grown spaghetti code) */ - int c; - state s = { - .c = '0', - .in = NONE, - .in_link = NOL, - .hlvl = 0, - .escape = false, - .lnkbuf = {0}, - .lnkidx = 0, - .indent = 0, - .previndent = 0, - .listdepth = 0, - .lastc = '0', - .linestarted = false, - .ol = false, - }; - while ((c = getchar()) != EOF) { - s.c = c; /* store for helpers */ - /* Handle Escapes before all else */ - if (s.escape) { - if (s.in == NONE) { - s.in = PARAGRAPH; + if (escape) { + if (in == NONE) { + in = PARAGRAPH; printf("<p>\n"); } putesc(c); - s.escape = false; + escape = false; continue; } /* Store links as we go */ - if (s.in_link == URL_PARSE && c != ']') { - s.lnkbuf[s.lnkidx++] = c; + if (in_link == URL_PARSE && c != ']') { + lnkbuf[lnkidx++] = c; } /* Store the indentation */ - if (!s.linestarted && c == ' ') { - s.indent++; + if (!linestarted && c == ' ') { + indent++; continue; /* don't print leading indents */ } /* Handle unique state changes by char */ switch (c) { case '\\': - s.escape = true; + escape = true; break; case '#': - if (s.in == NONE) { - s.in = HEADER_PARSE; - s.hlvl = 1; - } else if (s.in == HEADER_PARSE) { - s.hlvl++; + if (in == NONE) { + in = HEADER_PARSE; + hlvl = 1; + } else if (in == HEADER_PARSE) { + hlvl++; } else { /* not a special # */ putesc(c); } break; case ' ': - if (s.in == HEADER_PARSE) { - printf("<h%d>", s.hlvl); - s.in = HEADER; - } else if (s.in_link == URL_PARSE) { - s.in_link = DESC_PARSE; + if (in == HEADER_PARSE) { + printf("<h%d>", hlvl); + in = HEADER; + } else if (in_link == URL_PARSE) { + in_link = DESC_PARSE; printf("\">"); - } else if (s.in == LIST_PARSE) { - if (!s.listdepth) { - newlist(&s); + } else if (in == LIST_PARSE) { + if (!listdepth) { + newlist(); } else { - if (s.previndent < s.indent) { - newlist(&s); - } else if (s.previndent > s.indent) { - endlist(&s); + if (previndent < indent) { + newlist(); + } else if (previndent > indent) { + endlist(); printf("</li>\n<li>\n"); } else { - s.in = LIST; + in = LIST; printf("</li>\n<li>\n"); } } @@ -222,37 +207,37 @@ int parse() { case '*': case '`': case '_': - toggle_format(&s); + toggle_format(); break; case '\t': case '>': - if (s.in == NONE) { - s.in = c == '>' ? QUOTE : CODE; + if (in == NONE) { + in = c == '>' ? QUOTE : CODE; printf("%s", c == '>' ? "<blockquote>" : "<pre><code>"); - } else if (s.lastc == '\n' && c == (s.in == CODE ? '\t' : '>')) { + } else if (lastc == '\n' && c == (in == CODE ? '\t' : '>')) { /* no op */ } else { putesc(c); } break; case '[': - if (s.in_link == NOL && !fmt_disabled(&s)) { - maybe_startp(&s); - s.in_link = URL_PARSE; - s.lnkidx = 0; + if (in_link == NOL && !fmt_disabled()) { + maybe_startp(); + in_link = URL_PARSE; + lnkidx = 0; printf("<a href=\""); } else { putesc(c); } break; case ']': - if (s.in_link == URL_PARSE) { + if (in_link == URL_PARSE) { /* no description */ - s.in_link = NOL; - s.lnkbuf[s.lnkidx] = '\0'; - printf("\">%s</a>", s.lnkbuf); - } else if (s.in_link == DESC_PARSE) { - s.in_link = NOL; + in_link = NOL; + lnkbuf[lnkidx] = '\0'; + printf("\">%s</a>", lnkbuf); + } else if (in_link == DESC_PARSE) { + in_link = NOL; printf("</a>"); } else { putesc(c); @@ -269,33 +254,33 @@ int parse() { case '9': case '.': case '-': - if (s.in == NONE || !s.linestarted) { - s.ol = c != '-'; - s.in = LIST_PARSE; - } else if (s.in == LIST_PARSE) { + if (in == NONE || !linestarted) { + ol = c != '-'; + in = LIST_PARSE; + } else if (in == LIST_PARSE) { /* no op */ } else { putesc(c); } break; case '\n': - handle_lf(&s); - if (s.in != NONE) { + handle_lf(); + if (in != NONE) { putesc(c); } break; default: - maybe_startp(&s); + maybe_startp(); putesc(c); break; } - s.lastc = c; + lastc = c; if (c != '\n') { - s.linestarted = true; + linestarted = true; } } /* pretend there's a final LF to close any blocks */ - handle_lf(&s); + handle_lf(); return 0; }