aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/htmlroff/input.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2006-02-21 18:37:05 +0000
committerrsc <devnull@localhost>2006-02-21 18:37:05 +0000
commitc42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4 (patch)
tree400f263e56681842ba1e6e1fdd8be453856474ef /src/cmd/htmlroff/input.c
parent49a1496cbbb871bc623cfd0925566628e246c9ba (diff)
downloadplan9port-c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4.tar.gz
plan9port-c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4.tar.bz2
plan9port-c42a1d3d6168df56f966ea1f3ba3ef39ebbff4e4.zip
add
Diffstat (limited to 'src/cmd/htmlroff/input.c')
-rw-r--r--src/cmd/htmlroff/input.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/cmd/htmlroff/input.c b/src/cmd/htmlroff/input.c
new file mode 100644
index 00000000..99e0d56e
--- /dev/null
+++ b/src/cmd/htmlroff/input.c
@@ -0,0 +1,241 @@
+/*
+ * Read input files.
+ */
+#include "a.h"
+
+typedef struct Istack Istack;
+struct Istack
+{
+ Rune unget[3];
+ int nunget;
+ Biobuf *b;
+ Rune *p;
+ Rune *ep;
+ Rune *s;
+ int lineno;
+ Rune *name;
+ Istack *next;
+ void (*fn)(void);
+};
+
+Istack *istack;
+Istack *ibottom;
+
+static void
+setname(void)
+{
+ Rune *r, *p;
+
+ if(istack == nil || istack->name == nil)
+ return;
+ _nr(L(".F"), istack->name);
+ r = erunestrdup(istack->name);
+ p = runestrchr(r, '.');
+ if(p)
+ *p = 0;
+ _nr(L(".B"), r);
+ free(r);
+}
+
+static void
+ipush(Istack *is)
+{
+ if(istack == nil)
+ ibottom = is;
+ else
+ is->next = istack;
+ istack = is;
+ setname();
+}
+
+static void
+iqueue(Istack *is)
+{
+ if(ibottom == nil){
+ istack = is;
+ setname();
+ }else
+ ibottom->next = is;
+ ibottom = is;
+}
+
+int
+_inputfile(Rune *s, void (*push)(Istack*))
+{
+ Istack *is;
+ Biobuf *b;
+ char *t;
+
+ t = esmprint("%S", s);
+ if((b = Bopen(t, OREAD)) == nil){
+ free(t);
+ fprint(2, "%s: open %S: %r\n", argv0, s);
+ return -1;
+ }
+ free(t);
+ is = emalloc(sizeof *is);
+ is->b = b;
+ is->name = erunestrdup(s);
+ is->lineno = 1;
+ push(is);
+ return 0;
+}
+
+int
+pushinputfile(Rune *s)
+{
+ return _inputfile(s, ipush);
+}
+
+int
+queueinputfile(Rune *s)
+{
+ return _inputfile(s, iqueue);
+}
+
+int
+_inputstdin(void (*push)(Istack*))
+{
+ Biobuf *b;
+ Istack *is;
+
+ if((b = Bopen("/dev/null", OREAD)) == nil){
+ fprint(2, "%s: open /dev/null: %r\n", argv0);
+ return -1;
+ }
+ dup(0, b->fid);
+ is = emalloc(sizeof *is);
+ is->b = b;
+ is->name = erunestrdup(L("stdin"));
+ is->lineno = 1;
+ push(is);
+ return 0;
+}
+
+int
+pushstdin(void)
+{
+ return _inputstdin(ipush);
+}
+
+int
+queuestdin(void)
+{
+ return _inputstdin(iqueue);
+}
+
+void
+_inputstring(Rune *s, void (*push)(Istack*))
+{
+ Istack *is;
+
+ is = emalloc(sizeof *is);
+ is->s = erunestrdup(s);
+ is->p = is->s;
+ is->ep = is->p+runestrlen(is->p);
+ push(is);
+}
+
+void
+pushinputstring(Rune *s)
+{
+ _inputstring(s, ipush);
+}
+
+
+void
+inputnotify(void (*fn)(void))
+{
+ if(istack)
+ istack->fn = fn;
+}
+
+int
+popinput(void)
+{
+ Istack *is;
+
+ is = istack;
+ if(is == nil)
+ return 0;
+
+ istack = istack->next;
+ if(is->b)
+ Bterm(is->b);
+ free(is->s);
+ free(is->name);
+ if(is->fn)
+ is->fn();
+ free(is);
+ setname();
+ return 1;
+}
+
+int
+getrune(void)
+{
+ Rune r;
+ int c;
+
+top:
+ if(istack == nil)
+ return -1;
+ if(istack->nunget)
+ return istack->unget[--istack->nunget];
+ else if(istack->p){
+ if(istack->p >= istack->ep){
+ popinput();
+ goto top;
+ }
+ r = *istack->p++;
+ }else if(istack->b){
+ if((c = Bgetrune(istack->b)) < 0){
+ popinput();
+ goto top;
+ }
+ r = c;
+ }else{
+ r = 0;
+ sysfatal("getrune - can't happen");
+ }
+ if(r == '\n')
+ istack->lineno++;
+ return r;
+}
+
+void
+ungetrune(Rune r)
+{
+ if(istack == nil || istack->nunget >= nelem(istack->unget))
+ pushinputstring(L(""));
+ istack->unget[istack->nunget++] = r;
+}
+
+int
+linefmt(Fmt *f)
+{
+ Istack *is;
+
+ for(is=istack; is && !is->b; is=is->next)
+ ;
+ if(is)
+ return fmtprint(f, "%S:%d", is->name, is->lineno);
+ else
+ return fmtprint(f, "<no input>");
+}
+
+void
+setlinenumber(Rune *s, int n)
+{
+ Istack *is;
+
+ for(is=istack; is && !is->name; is=is->next)
+ ;
+ if(is){
+ if(s){
+ free(is->name);
+ is->name = erunestrdup(s);
+ }
+ is->lineno = n;
+ }
+}