+/* --- Eof scanner operations --- */
+
+static scansrc_ops eof_ops = { eof_scan, eof_destroy };
+
+/* --- The end of file marker --- */
+
+static scansrc scan_eof = { &scan_eof, &eof_ops, "<eof>", 0, DSTR_INIT };
+
+/*----- General scanner handling ------------------------------------------*/
+
+/* --- @scan@ --- *
+ *
+ * Arguments: @scanner *sc@ = pointer to main scanner context
+ *
+ * Returns: Character read, or end-of-file.
+ *
+ * Use: Scans a character from a source of characters.
+ */
+
+int scan(scanner *sc)
+{
+ int ch;
+ if (sc->head->pushback.len)
+ ch = sc->head->pushback.buf[--sc->head->pushback.len];
+ else {
+ scansrc *ss = sc->head;
+ if (ss == &scan_eof)
+ ch = EOF;
+ else if ((ch = ss->ops->scan(ss)) == EOF) {
+ sc->head = ss->next;
+ if (sc->head == &scan_eof)
+ sc->tail = &sc->head;
+ ss->ops->destroy(ss);
+ ch = '\n';
+ }
+ }
+ return (ch);
+}
+
+/* --- @unscan@ --- *
+ *
+ * Arguments: @scanner *sc@ = pointer to main scanner context
+ * @int ch@ = character to unscan
+ *
+ * Returns: ---
+ *
+ * Use: Scans a character from a source of characters.
+ */
+
+void unscan(scanner *sc, int ch)
+{
+ DPUTC(&sc->head->pushback, ch);
+}
+
+/* --- @scan_push@ --- *
+ *
+ * Arguments: @scanner *sc@ = pointer to main scanner context
+ * @scansrc *ss@ = souorce to push
+ *
+ * Returns: ---
+ *
+ * Use: Pushes a scanner source onto the front of the queue.
+ */
+
+void scan_push(scanner *sc, scansrc *ss)
+{
+ ss->next = sc->head;
+ if (sc->head == &scan_eof)
+ sc->tail = &ss->next;
+ sc->head = ss;
+ dstr_create(&ss->pushback);
+ ss->tok = 0;
+ ss->t = 0;
+}
+
+/* --- @scan_add@ --- *
+ *
+ * Arguments: @scanner *sc@ = pointer to main scanner context
+ * @scansrc *ss@ = souorce to push
+ *
+ * Returns: ---
+ *
+ * Use: Adds a scanner source onto the end of the queue.
+ */
+
+void scan_add(scanner *sc, scansrc *ss)
+{
+ ss->next = &scan_eof;
+ *sc->tail = ss;
+ sc->tail = &ss->next;
+ dstr_create(&ss->pushback);
+ ss->tok = 0;
+ ss->t = 0;
+}
+
+/* --- @scan_create@ --- *
+ *
+ * Arguments: @scanner *sc@ = scanner context to initialize
+ *
+ * Returns: ---
+ *
+ * Use: Initializes a scanner block ready for use.
+ */
+
+void scan_create(scanner *sc)