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:
M | blag.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("<"); 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;
}