commit 835be231c45eb36e19a2c23f6f5fb719424ca1c1
parent 16147bfd6a08ac6e19fe4450d778035156c3faa2
Author: Pavel Renev <an2qzavok@gmail.com>
Date: Sat, 9 Apr 2022 22:21:56 +0000
Markdown: new implementation
Diffstat:
3 files changed, 598 insertions(+), 423 deletions(-)
diff --git a/extra/Handler b/extra/Handler
@@ -30,7 +30,7 @@ fn lmarkdown {
history = (`{pwd}^/$fname $history)
forward = ()
clear
- cat $fname
+ Markdown $fname > $rroot/text
}
fn lgopher {
@@ -49,7 +49,7 @@ fn tryfile {
type=`{file -m $1}
switch ($type) {
case 'text/plain';
- lmarkdown $1
+ cat $1
case *;
plumb $1
}
diff --git a/extra/Markdown.c b/extra/Markdown.c
@@ -1,535 +1,705 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
-#include <String.h>
+#include <thread.h>
-char *data;
-long count;
+#include "config.h"
-/* Lexer */
+#define ATTACH(array, size, new) \
+ { \
+ array = realloc(array, sizeof(*array) * (size + 1)); \
+ array[size] = new; \
+ size++; \
+ }
-enum {
- TEOF = 0,
- TH0, TH1, TH2, TH3, TH4, TH5, TH6,
- TWORD, TWBRK, TPBRK,
- TLINK,
- TCODEBLOCK,
- TUNDEF = -1,
-};
+#define APPEND(t1, t2) \
+ { \
+ ATTACH(t1->tokens, t1->count, t2) \
+ t2 = t1; \
+ t1 = nil; \
+ }
typedef struct Token Token;
+
struct Token {
int type;
- String *s;
- String *a;
+ union {
+ Rune rune;
+ struct {
+ int count;
+ Token **tokens;
+ };
+ };
};
-void (*lex)(void);
-long p, tokn;
-Token tok, *tokens;
-int oldtype;
-
-void lnewline(void);
+enum {
+ TNil,
+
+ TRune,
+
+ TSpace,
+ TNewline,
+ TTab,
+ TBraceOpen,
+ TBraceClose,
+ TSqrBraceOpen,
+ TSqrBraceClose,
+ THash,
+ TQuote,
+
+ TWhiteSpace,
+ THMarker,
+ TWord,
+ TWords,
+ TQuoted,
+ TBraced,
+ TSqrBraced,
+ TLink,
+ TText,
+ THeader,
+ TLine,
+ TEmptyLine,
+ TParagraph,
+
+ TMax,
+};
-void lheader(void);
-void lhspace(void);
-void lhword(void);
-void lhline(void);
-void lsubhline(void);
+char *names[] = {
+ [TNil] "nil",
+ [TRune] "rune",
+
+ [TSpace] "sp",
+ [TNewline] "nl",
+ [TTab] "tab",
+ [TBraceOpen] "(",
+ [TBraceClose] ")",
+ [TSqrBraceOpen] "[",
+ [TSqrBraceClose] "]",
+ [THash] "#",
+ [TQuote] "\"",
+
+ [TWhiteSpace] "ws",
+ [THMarker] "h_marker",
+ [TWord] "word",
+ [TWords] "words",
+ [TQuoted] "quoted",
+ [TBraced] "()",
+ [TSqrBraced] "[]",
+ [TLink] "link",
+ [TText] "text",
+ [THeader] "h",
+ [TLine] "line",
+ [TEmptyLine] "pb",
+ [TParagraph] "p",
+};
-void lword(void);
-void lspace(void);
+Biobuf *bfdin;
+
+Token* twrap(int, int, Token **);
+Token** token1(Token *);
+
+void input(void *);
+void header(void *);
+void pass1(void *);
+void quote(void *);
+void pass2(void *);
+void words(void *);
+void pass3(void *);
+void link(void *);
+void line(void *);
+void debug(void *);
+void output(void *);
+void clear(void *);
+
+void freetoken(Token *t);
+void dbgprinttoken(Biobuf *, Token *, int);
+void printtoken(Biobuf *, Token *);
+void printlink(Biobuf *, Token *);
+char * tokentotext(Token *, int);
+
+Rune trune(Token *);
+int ttype(Token *);
+Token ** findtype(Token **, int, int);
-void llink(void);
-void lladdr(void);
-void lltitle(void);
+void
+usage(void)
+{
+ fprint(2, "usage: %s [file]", argv0);
+ threadexitsall("usage");
+}
-void lcodeblock(void);
+void
+threadmain(int argc, char **argv)
+{
+ ARGBEGIN {
+ default:
+ usage();
+ }ARGEND
+
+ if (argc > 0) {
+ bfdin = Bopen(argv[0], OREAD);
+ if (bfdin == nil) sysfatal("%r");
+ } else bfdin = Bfdopen(0, OREAD);
+
+ int n;
+ Channel **c;
+ void (*pipeline[])(void *) = {
+ input,
+ pass1,
+ quote,
+ pass2,
+ words,
+ pass3,
+ link,
+ header,
+ line,
+// debug,
+ output,
+ clear,
+ };
-char consume(void);
-char peek(int);
-void emit(void);
+ n = sizeof(pipeline) / sizeof(*pipeline);
-void emitwbrk(void);
-void emitpbrk(void);
+ c = mallocz(sizeof(Channel *) * (n + 1), 1);
-/* Rich */
+ int i;
+ for (i = 1; i < n; i ++) c[i] = chancreate(sizeof(Token *), 64);
+ for (i = 0; i < n; i++) threadcreate(pipeline[i], (void *)(c + i), 64 * 1024);
+}
-char * newobj(void);
-int setfield(char *, char *, char *);
+Token *
+twrap(int type, int count, Token **tokens)
+{
+ Token *nt = mallocz(sizeof(Token), 1);
+ nt->type = type;
+ nt->count = count;
+ nt->tokens = tokens;
+ return nt;
+}
-void printtoken(Token);
+Token **
+token1(Token *t)
+{
+ Token **tt;
+ tt = malloc(sizeof(Token *));
+ tt[0] = t;
+ return tt;
+}
-char *root = "/mnt/richterm";
+void
+input(void *v)
+{
+ Channel **c = v;
+
+ Rune r;
+ while ((r = Bgetrune(bfdin)) != Beof) {
+ Token *t = mallocz(sizeof(Token), 1);
+ t->type = TRune;
+ t->rune = r;
+ send(c[1], &t);
+ }
+ chanclose(c[1]);
+}
void
-main(int argc, char **argv)
+header(void *v)
{
- int fd;
- char buf[1024];
- long i, n;
-
- if (argc > 1) {
- if ((fd = open(argv[1], OREAD)) < 0)
- sysfatal("can't open %s, %r", argv[1]);
- } else fd = 0;
- count = 0;
- data = nil;
- while ((n = read(fd, buf, sizeof(buf))) > 0) {
- data = realloc(data, count + n);
- memcpy(data + count, buf, n);
- count += n;
+ Channel **c = v;
+ Token *t, *nt, **tt;
+ tt = nil;
+ int h = 0;
+ int count = 0;
+ while (recv(c[0], &t) > 0) {
+ if (h == 0) {
+ if (t->type == THMarker) h = 1;
+ else send(c[1], &t);
+ }
+ if (h != 0) {
+
+ if ((t->type == TNewline) || (t->type == TEmptyLine)) {
+ h = 0;
+ nt = twrap(THeader, count, tt);
+ send(c[1], &nt);
+ send(c[1], &t);
+ tt = nil;
+ count = 0;
+ } else ATTACH(tt, count, t)
+ }
}
- if (n < 0) sysfatal("%r");
-
- tokens = nil;
- tokn = 0;
- tok.s = s_new();
- tok.a = s_new();
- tok.type = TUNDEF;
- oldtype = TUNDEF;
- lex = lnewline;
- while(lex != nil) {
- lex();
+ if (tt != nil) {
+ nt = twrap(THeader, count, tt);
+ send(c[1], &nt);
}
- emitpbrk();
- tok.type = TEOF;
- emit();
+ chanclose(c[1]);
+}
- for (i = 0; i < tokn; i++) {
- if (tokens[i].type == TEOF) break;
- printtoken(tokens[i]);
+void
+pass1(void *v)
+{
+ Channel **c = v;
+ Token *t;
+ while (recv(c[0], &t) > 0) {
+ if (ttype(t) == TRune) {
+ switch (trune(t)) {
+ case L'[':
+ t = twrap(TSqrBraceOpen, 1, token1(t));
+ break;
+ case L']':
+ t = twrap(TSqrBraceClose, 1, token1(t));
+ break;
+ case L'(':
+ t = twrap(TBraceOpen, 1, token1(t));
+ break;
+ case L')':
+ t = twrap(TBraceClose, 1, token1(t));
+ break;
+ case L'\n':
+ t = twrap(TNewline, 1, token1(t));
+ break;
+ case L' ':
+ t = twrap(TSpace, 1, token1(t));
+ break;
+ case L'\t':
+ t = twrap(TTab, 1, token1(t));
+ break;
+ case L'\#':
+ t = twrap(THash, 1, token1(t));
+ break;
+ case L'\"':
+ t = twrap(TQuote, 1, token1(t));
+ break;
+ }
+ send(c[1], &t);
+ }
}
+ chanclose(c[1]);
}
void
-lnewline(void)
+quote(void *v)
{
- char c;
- c = peek(0);
- switch (c){
- case 0:
- lex = nil;
- break;
- // case '\n':
- // consume();
- // emitpbrk();
- // tok.type = TUNDEF;
- // break;
- case '#':
- lex = lheader;
- consume();
- tok.type = TH0;
- break;
- case '=':
- lex = lhline;
- consume();
- break;
- case '-':
- lex =lsubhline;
- consume();
- break;
- case '[':
- lex = llink;
- consume();
- // emitwbrk();
- break;
- case '\t':
- lex = lcodeblock;
- consume();
- break;
- default:
- lex = lword;
- // emitwbrk();
+ Channel **c = v;
+ Token *t, *q = nil;
+ while (recv(c[0], &t) > 0) {
+ if (q == nil) {
+ if (ttype(t) == TQuote) {
+ q = twrap(TQuoted, 1, token1(t));
+ } else send(c[1], &t);
+ } else {
+ if (ttype(t) == TQuote) {
+ ATTACH(q->tokens, q->count, t)
+ send(c[1], &q);
+ q = nil;
+ } else ATTACH(q->tokens, q->count, t)
+ }
}
+ if (q != nil) {
+ fprint(2, "missing end quote\n");
+ send(c[1], &q);
+ }
+ chanclose(c[1]);
}
void
-lword(void)
+pass2(void *v)
{
- char c;
- c = peek(0);
- switch (c) {
- case 0:
- lex = nil;
- emit();
- break;
- case '\n':
- lex = lnewline;
- s_putc(tok.s, c);
- consume();
- tok.type = TWORD;
- emit();
- tok.type = TUNDEF;
- break;
- // case ' ':
- // lex = lspace;
- // s_putc(tok.s, c);
- // consume();
- // break;
- case '[':
- lex = llink;
- tok.type = TWORD;
- emit();
- consume();
- break;
- default:
- s_putc(tok.s, c);
- consume();
+ Channel **c = v;
+ Token *t[2] = {nil, nil};
+ while (recv(c[0], &t[0]) > 0) {
+ switch(ttype(t[1])) {
+ case TTab:
+ case TSpace:
+ t[1] = twrap(TWhiteSpace, 1, token1(t[1]));
+ break;
+ case THash:
+ t[1] = twrap(THMarker, 1, token1(t[1]));
+ break;
+ case TRune:
+ t[1] = twrap(TWord, 1, token1(t[1]));
+ break;
+ }
+
+ switch(ttype(t[1])) {
+ case TNewline:
+ if (ttype(t[0]) == TNewline) {
+ t[1] = twrap(TEmptyLine, 1, token1(t[1]));
+ APPEND(t[1], t[0])
+ }
+ break;
+ case TWhiteSpace:
+ if ((ttype(t[0]) == TSpace) || (ttype(t[0]) == TTab)) {
+ APPEND(t[1], t[0])
+ }
+ break;
+ case THMarker:
+ if (ttype(t[0]) == THash) {
+ APPEND(t[1], t[0])
+ }
+ break;
+ case TWord:
+ if (ttype(t[0]) == TRune) {
+ APPEND(t[1], t[0])
+ }
+ break;
+ }
+
+ if (t[1] != nil) send(c[1], &t[1]);
+ t[1] = t[0];
+ t[0] = nil;
}
+ if (t[1] != nil) send(c[1], &t[1]);
+ chanclose(c[1]);
}
void
-lspace(void)
+words(void *v)
{
- char c;
- c = peek(0);
- switch (c) {
- case ' ':
- consume();
- break;
- case '\n':
- tok.type = TWORD;
- lex = lnewline;
- consume();
- emit();
- tok.type = TUNDEF;
- break;
- default:
- lex = lword;
+ Channel **c = v;
+ Token *t, **buf;
+ char bf = 0xff;
+ buf = mallocz(sizeof(Token *) * 8, 1);
+ int r = 1;
+ while (bf != 0) {
+ t = nil;
+ if (r > 0) {
+ recv(c[0], &t);
+ }
+ memcpy(buf, buf + 1, 7 * sizeof(Token *));
+ buf[7] = t;
+ bf = (bf << 1) | (1 & (t != nil));
+
+ if (ttype(buf[4]) == TWord) {
+ buf[4] = twrap(TWords, 1, token1(buf[4]));
+ }
+
+ if ((ttype(buf[4]) == TWords) &&
+ (ttype(buf[5]) == TWhiteSpace) &&
+ (ttype(buf[6]) == TWord)) {
+ APPEND(buf[4], buf[5])
+ APPEND(buf[5], buf[6])
+ }
+
+ if (buf[0] != nil) {
+ send(c[1], &buf[0]);
+ }
}
+ chanclose(c[1]);
}
void
-lheader(void)
+pass3(void *v)
{
- char c;
- if ((tok.type >= TH0) && (tok.type < TH6)) tok.type++;
- else {
- /* an error */
- lex = nil;
- return;
+ Channel **c = v;
+ Token *t, *b = nil;
+ while(recv(c[0], &t) > 0) {
+ if (b == nil) {
+ if (ttype(t) == TBraceOpen) {
+ b = twrap(TBraced, 1, token1(t));
+ } else if (ttype(t) == TSqrBraceOpen) {
+ b = twrap(TSqrBraced, 1, token1(t));
+ } else send(c[1], &t);
+ } else if (ttype(b) == TBraced) {
+ if (ttype(t) == TBraceClose) {
+ ATTACH(b->tokens, b->count, t)
+ send(c[1], &b);
+ b = nil;
+
+ } else ATTACH(b->tokens, b->count, t)
+ } else /* if (ttype(b) == TSqrBtaced) */ {
+ if (ttype(t) == TSqrBraceClose) {
+ ATTACH(b->tokens, b->count, t)
+ send(c[1], &b);
+ b = nil;
+ } else ATTACH(b->tokens, b->count, t)
+ }
}
- c = peek(0);
- switch (c){
- case '#':
- consume();
- lex = lheader;
- break;
- case '\n':
- /* an error */
- lex = nil;
- break;
- case ' ':
- consume();
- lex = lhspace;
- break;
- default:
- /* an error */
- lex = nil;
+ if (b != nil) {
+ fprint(2, "unclosed (square? ) brace\n");
+ send(c[1], &b);
}
+ chanclose(c[1]);
}
void
-lhspace(void)
+link(void *v)
{
- char c;
- c = peek(0);
- switch(c) {
- case 0:
- case '\n':
- lex = nil;
- case ' ':
- consume();
- break;
- default:
- lex = lhword;
+ Channel **c = v;
+ Token *t, *l = nil;
+ while(recv(c[0], &t) > 0) {
+ if (l == nil) {
+ if (ttype(t) == TSqrBraced) {
+ l = t;
+ } else send(c[1], &t);
+ } else {
+ if (ttype(t) == TBraced) {
+ l = twrap(TLink, 1, token1(l));
+ ATTACH(l->tokens, l->count, t)
+ send(c[1], &l);
+ l = nil;
+ } else {
+ send(c[1], &l);
+ send(c[1], &t);
+ l = nil;
+ }
+ }
}
+ if (l != nil) send(c[1], &l);
+ chanclose(c[1]);
}
void
-lhword(void)
+line(void *v)
{
- char c;
- c = peek(0);
- switch(c) {
- case 0:
- lex = nil;
- break;
- case ' ':
- s_putc(tok.s, c);
- consume();
- lex = lhspace;
- break;
- case '\n':
- consume();
- emit();
- emitpbrk();
- lex = lnewline;
- break;
- default:
- s_putc(tok.s, c);
- consume();
+ Channel **c = v;
+ Token *t, *l = nil;
+ while(recv(c[0], &t) > 0) {
+ switch(ttype(t)) {
+ case TWords:
+ case TLink:
+ case TWhiteSpace:
+ if (l == nil) {
+ l = twrap(TLine, 1, token1(t));
+ } else {
+ ATTACH(l->tokens, l->count, t)
+ }
+ break;
+ default:
+ if (l != nil) {
+ send(c[1], &l);
+ l = nil;
+ }
+ send(c[1], &t);
+ }
}
+ chanclose(c[1]);
}
void
-lhline(void)
+debug(void *v)
{
- char c;
- c = peek(0);
- switch (c) {
- case 0:
- lex = nil;
- break;
- case '=':
- consume();
- s_putc(tok.s, c);
- break;
- case '\n':
- lex = lnewline;
- consume();
- tokens[tokn - 1].type = TH1;
- break;
- default:
- lex = lword;
- consume();
- tok.type = TWORD;
- emit();
- };
+ Channel **c = v;
+ Token *t;
+ Biobuf *b;
+ b = Bfdopen(2, OWRITE);
+ if (b == nil) sysfatal("debug: %r");
+ while (recv(c[0], &t) > 0) {
+ dbgprinttoken(b, t, 0);
+ send(c[1], &t);
+ }
+ chanclose(c[1]);
+ Bflush(b);
}
void
-lsubhline(void)
+output(void *v)
{
- char c;
- c = peek(0);
- switch (c){
- case 0:
- lex = nil;
- break;
- case '-':
- consume();
- s_putc(tok.s, c);
- break;
- case '\n':
- lex = lnewline;
- tokens[tokn - 1].type = TH2;
- consume();
- break;
- default:
- lex = lword;
- tok.type = TWORD;
- consume();
- emit();
+ Channel **c = v;
+ Token *t;
+ Biobuf *b;
+ b = Bfdopen(1, OWRITE);
+ while (recv(c[0], &t) > 0) {
+ printtoken(b, t);
+ send(c[1], &t);
}
+ chanclose(c[1]);
+ Bflush(b);
}
void
-llink(void)
+clear(void *v)
{
- switch (peek(0)){
- case 0:
- lex = nil;
- break;
- case ']':
- consume();
- if (peek(0) == '(') {
- consume();
- lex = lladdr;
- } else lex = lword;
- break;
- default:
- s_putc(tok.s, consume());
+ Channel **c = v;
+ Token *t;
+ while (recv(c[0], &t) > 0) {
+ freetoken(t);
}
}
void
-lladdr(void)
+freetoken(Token *t)
{
- switch (peek(0)){
- case 0:
- lex = nil;
- break;
- case ')':
- lex = lword;
- s_terminate(tok.a);
- consume();
- tok.type = TLINK;
- emit();
- tok.type = TUNDEF;
- break;
- case ' ':
- lex = lltitle;
- consume();
- break;
- default:
- s_putc(tok.a, consume());
- }
+ if (ttype(t) != TRune)
+ for (; t->count > 0; t->count--) freetoken(t->tokens[t->count - 1]);
+ free(t);
}
void
-lltitle(void)
+dbgprinttoken(Biobuf *b, Token *t, int ind)
{
- /* richterm has no support for link titles,
- * so we're skipping it
- */
-
- switch (peek(0)){
- case 0:
- lex = nil;
- break;
- case ')':
- lex = lladdr;
+ int i;
+ char *s;
+ static neednl;
+
+ for (i = 0; i < ind; i++) Bprint(b, " ");
+
+ neednl = 1;
+ switch (t->type) {
+ case TRune:
+ s = tokentotext(t, 1);
+ Bprint(b, "'%s'", s);
+ free(s);
+ break;
+ case TText:
+ s = tokentotext(t, 1);
+ Bprint(b, "text \"%s\"", s);
+ free(s);
+ break;
+ case THMarker:
+ Bprint(b, "h_marker %d", t->count);
+ break;
+ case TQuoted:
+ Bprint(b, "%s ", names[t->type]);
+ case TWord:
+ s = tokentotext(t, 1);
+ Bprint(b, "\"%s\"", s);
+ free(s);
+ break;
+ case TLine:
+ case TLink:
+ case TBraced:
+ case TSqrBraced:
+ case TWords:
+ Bprint(b, "%s\n", names[t->type]);
+ for (i = 0; i < t->count; i++) {
+ dbgprinttoken(b, t->tokens[i], ind + 1);
+ }
break;
- case ' ':
default:
- consume();
+ Bprint(b, "%s", names[t->type]);
+ }
+
+ if (neednl > 0) {
+ neednl = 0;
+ Bprint(b, "\n");
}
}
void
-lcodeblock(void)
+printtoken(Biobuf *b, Token *t)
{
- switch (peek(0)){
- case 0:
- lex = nil;
+ int i;
+ switch(ttype(t)) {
+ case TWord:
+ Bprint(b, ".");
+ for (i = 0; i < t->count; i++) {
+ Bprint(b, "%C", trune(t->tokens[i]));
+ }
+ Bprint(b, "\n");
+ break;
+ case TLink:
+ printlink(b, t);
+ break;
+ case TLine:
+ for (i = 0; i < t->count; i++) printtoken(b, t->tokens[i]);
+ Bprint(b, "n\n");
+ break;
+ case THeader:
+ i = t->tokens[0]->count;
+ if (i > 6) i = 6;
+ i--;
+
+ Bprint(b, "f%s\n", fonts[Fheader1 + i]);
+ for (i = 2; i < t->count; i++) printtoken(b, t->tokens[i]);
+ Bprint(b, "n\n" "f\n");
+ break;
+ case TEmptyLine:
+ Bprint(b, "n\n");
+ break;
+ case TWhiteSpace:
+ Bprint(b, "s\n");
break;
- case '\n':
- lex = lnewline;
- s_putc(tok.s, consume());
- s_terminate(tok.s);
- tok.type = TCODEBLOCK;
- emit();
- tok.type = TUNDEF;
+ case TRune:
+ Bprint(b, ".%C\n", t->rune);
+ break;
+ case TNewline:
break;
default:
- s_putc(tok.s, consume());
+ for (i = 0; i < t->count; i++) printtoken(b, t->tokens[i]);
}
}
-char
-consume(void)
-{
- if (p < count) return data[p++];
- else return 0;
-}
-
-char
-peek(int k)
-{
- if (p + k < count) return data[p + k];
- else return 0;
-}
-
void
-emit(void)
+printlink(Biobuf *b, Token *t)
{
- s_terminate(tok.s);
+ char *text, *url;
+ Token *tlink, *ttext, **tt;
+ ttext = t->tokens[0];
+ tlink = t->tokens[1];
+
+ tt = findtype(ttext->tokens, ttext->count, TWords);
+ if (tt == nil) {
+ fprint(2, "malformed link\n");
+ return;
+ }
+ text = tokentotext(*tt, 0);
- tokens = realloc(tokens, (tokn + 1) * sizeof(Token));
- tokens[tokn] = tok;
- tokn++;
+ tt = findtype(tlink->tokens, tlink->count, TWords);
+ if (tt == nil) {
+ fprint(2, "malformed link\n");
+ free(text);
+ return;
+ }
+ url = tokentotext(*tt, 0);
- tok.s = s_new();
- tok.a = s_new();
- oldtype = tok.type;
- tok.type = TUNDEF;
+ Bprint(b, "l%s\n", url);
+ Bprint(b, ".%s\n", text);
+ Bprint(b, "l\n");
+ free(url);
+ free(text);
}
-void
-emitwbrk(void)
+Token **
+findtype(Token **tt, int count, int type)
{
- if (oldtype == TWORD) {
- tok.type = TWBRK;
- emit();
+ int i;
+ for (i = 0; i < count; i++) {
+ if (ttype(tt[i]) == type) return tt + i;
}
+ return nil;
}
-void
-emitpbrk(void)
+char *
+tokentotext(Token *t, int escape)
{
- if (oldtype != TPBRK) {
- tok.type = TPBRK;
- emit();
+ char *r, *s;
+ int i;
+ switch (t->type) {
+ case TRune:
+ if (escape != 0) {
+ if (t->rune == L'\n') return smprint("\\n");
+ if (t->rune == L'\t') return smprint("\\t");
+ if (t->rune == L'"') return smprint("\\%c", '"');
+ }
+ return smprint("%C", t->rune);
+ case TWhiteSpace:
+ return smprint(" ");
+ default:
+ r = malloc(128);
+ r[0] = '\0';
+ for (i = 0; i < t->count; i++) {
+ s = tokentotext(t->tokens[i], escape);
+ strncat(r, s, 128);
+ free(s);
+ }
+ return r;
}
}
-int
-setfield(char *id, char *field, char *value)
+Rune
+trune(Token *t)
{
- char *path;
- int fd;
- usize n;
- path = smprint("%s/%s/%s", root, id, field);
- fd = open(path, OWRITE);
- if (fd < 0) sysfatal("%r");
- n = write(fd, value, strlen(value));
- if (n != strlen(value)) sysfatal("write failed: %r");
- close(fd);
- free(path);
- return 0;
-}
-
-char *
-newobj(void)
-{
- char *buf;
- int fd;
- fd = open("/mnt/richterm/new", OREAD);
- if (fd < 0) sysfatal("%r");
- buf = mallocz(256, 1);
- read(fd, buf, 256);
- close(fd);
- return buf;
+ if (t == nil) return Runeerror;
+ switch (t->type) {
+ case TRune:
+ return t->rune;
+ default:
+ return Runeerror;
+ }
}
-void
-printtoken(Token tok)
+int
+ttype(Token *t)
{
- char *font, *text, *link, *id;
- font = nil;
- link = nil;
- text = s_to_c(tok.s);
- switch(tok.type) {
- case TH1:
- font = "/lib/font/bit/lucida/unicode.32.font";
- break;
- case TH2:
- font = "/lib/font/bit/lucida/unicode.28.font";
- break;
- case TH3:
- font = "/lib/font/bit/lucida/unicode.24.font";
- break;
- case TH4:
- font = "/lib/font/bit/lucida/unicode.20.font";
- break;
- case TH5:
- font = "/lib/font/bit/lucida/unicode.18.font";
- break;
- case TH6:
- font = "/lib/font/bit/lucida/unicode.16.font";
- break;
- case TWORD:
- break;
- case TWBRK:
- text = " ";
- break;
- case TPBRK:
- text = "\n\n";
- break;
- case TLINK:
- link = s_to_c(tok.a);
- break;
- case TCODEBLOCK:
- text = smprint("\t%s", s_to_c(tok.s));
- font = "/lib/font/bit/terminus/unicode.16.font";
- break;
- default:
- sysfatal("unknown token type %d for text \"%s\"", tok.type, text);
- }
- id = newobj();
- if (text != nil) setfield(id, "text", text);
- if (font != nil) setfield(id, "font", font);
- if (link != nil) setfield(id, "link", link);
+ if (t == nil) return 0;
+ return t->type;
}
diff --git a/extra/mkfile b/extra/mkfile
@@ -6,6 +6,8 @@ TARG=\
Gopher\
Gemini\
+HFILES=config.h
+
SYSLIB=/sys/lib/richterm
BIN=$SYSLIB/bin/$objtype
@@ -19,6 +21,9 @@ install:V: bindir $RC
bindir:V:
mkdir -p $BIN
+config.h:
+ cp config.def.h config.h
+
$RC:V:
mkdir -p $SYSLIB/bin/rc
for (i in $RC) @{