diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /web/schemeweb |
Initial commit
Diffstat (limited to 'web/schemeweb')
-rw-r--r-- | web/schemeweb/Makefile | 41 | ||||
-rw-r--r-- | web/schemeweb/README | 123 | ||||
-rw-r--r-- | web/schemeweb/reader.sw | 44 | ||||
-rw-r--r-- | web/schemeweb/sweb.1 | 73 | ||||
-rw-r--r-- | web/schemeweb/sweb.c | 420 |
5 files changed, 701 insertions, 0 deletions
diff --git a/web/schemeweb/Makefile b/web/schemeweb/Makefile new file mode 100644 index 0000000000..3b88e4f570 --- /dev/null +++ b/web/schemeweb/Makefile @@ -0,0 +1,41 @@ +# SchemeWEB Makefile +# $Id: Makefile,v 2.0 1994/02/25 13:50:51 ramsdell Exp $ + +CFLAGS = -O +srcdir = . +VPATH = . +INSTALL = cp +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) + +prefix = /usr/local +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +mandir = $(prefix)/man +manext = 1 + +SHELL=/bin/sh +DISTFILES=Makefile README sweb.c sweb.1 reader.sw + +all: sweb + +sweb: sweb.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(srcdir)/sweb.c + +install: sweb sweb.1 + $(INSTALL_PROGRAM) sweb $(bindir)/sweb + $(INSTALL_DATA) sweb.1 $(mandir)/man$(manext)/sweb.$(manext) + +uninstall: + rm $(bindir)/sweb + rm $(mandir)/man$(manext)/sweb.$(manext) + +dist: schemeweb.sh + +schemeweb.sh: $(DISTFILES) + shar $(DISTFILES) > $@ + +clean: + -rm sweb + +.PHONY: all install uninstall dist clean diff --git a/web/schemeweb/README b/web/schemeweb/README new file mode 100644 index 0000000000..9222df1789 --- /dev/null +++ b/web/schemeweb/README @@ -0,0 +1,123 @@ +$Id: README,v 2.1 94/07/22 07:00:10 ramsdell Exp $ + +SchemeWEB---Simple support for literate programming in Lisp. + +SchemeWEB is a Unix filter that allows you to generate both Lisp and +LaTeX code from one source file. The generated LaTeX code formats +Lisp programs in typewriter font obeying the spacing in the source +file. Comments can include arbitrary LaTeX commands. SchemeWEB was +originally developed for the Scheme dialect of Lisp, but it can easily +be used with most other dialects. + +Version 2.1 implements several improvements over the version 1.2 which +was released in 1990. + +* The LaTeX source generated from a SchemeWEB file no longer requires +the use of a style option, such as the astyped option required by the +previous version. The output is similar to that produced by c2latex. + +* By default, Lisp source generated from a SchemeWEB file includes all +comments. As a result, the filter can translate the Lisp source +generated from a SchemeWEB file directly into LaTeX source. + +* The filter can translate the Lisp source generated from a SchemeWEB +file into the original SchemeWEB file. + +As a result of these changes, a SchemeWEB file can be stored and +distributed as a standard Lisp file by tangling the SchemeWEB file. +For the purposes of editing comments, the SchemeWEB file can be +recovered by untangling the Lisp file. LaTeX documentation can be +generated from both the Lisp file or the SchemeWEB file. + +Version 2.1 patches version 2.0 so it now correctly formats strings +which span more than one line of text. + +Installation: + +1) Create the executable by typing: + + make + +2) Install the executable and the manual page by typing: + + make install + +By default the makefile will install the executable in $(prefix)/bin +and the manual page in $(prefix)/man/man1, where prefix=/usr/local. +You can change the prefix by typing: + + make prefix=<Your path> install + +You can also change the installation targets by editing the makefile. + +3) You can modify the reader used by your Lisp system's standard LOAD +so that it can read SchemeWEB files directly. To make this change, +follow the model given in "reader.sw", a reader of SchemeWEB source +for the R4RS dialect of Scheme. + +A formatted version of the manual page follows. + +----------------------------------------------------------------- + +sweb(1) USER COMMANDS sweb(1) + + + +NAME + sweb - Simple support for literate programming in Lisp. + +SYNOPSIS + sweb [-stuvwx] [input_file [output_file]] + +DESCRIPTION + A SchemeWEB file is a Lisp source file which contains code + sections and comment sections, but each section is identi- + fied in a novel way. A code section begins with a line + whose first character is a left parenthesis. It continues + until a line is found which contains the parenthesis that + matches the one which started the code section. The remain- + ing lines of text in the source file are treated as com- + ments. + + Several operations involving SchemeWEB files are provided by + the sweb program. + + The -t option translates a SchemeWEB file into a standard + Lisp file. It simply adds an initial semicolon to comment + lines that lack them, and passes code sections through + unchanged. This process is called tangling the SchemeWEB + file. + + The -w option translates a SchemeWEB file into a LaTeX + source file. Text is added to code sections so that LaTeX + will print the code verbatim. Comment sections are passed + through unchanged except that if the first character of a + line is a semicolon, it is excised. This makes it possible + to process a SchemeWEB file which has been tangled. This + process is called weaving the SchemeWEB file. This is the + default action of sweb. + + The -x option weaves a SchemeWEB file as above, except the + LaTeX source produced inhibits page breaks in code sections. + + The -u option translates a Lisp file which has been produced + from a SchemeWEB file back into a SchemeWEB file. It simply + removes the first semicolon in every line that starts with + one as its first character. This process is called untan- + gling a sweb produced Lisp file. + + The -s option tangles a SchemeWEB file and strips all com- + ments from the file. + + The -v option prints version information. + + A SchemeWEB file can be stored and distributed as a standard + Lisp file by tangling the SchemeWEB file. For the purposes + of editing comments, the SchemeWEB file can be recovered by + untangling the Lisp file. LaTeX documentation can be + generated from both the Lisp file or the SchemeWEB file. + + SchemeWEB was originally developed for the Scheme dialect of + Lisp; however, it became obvious that no changes were + required to support most other dialects. SchemeWEB's name + reflects its heritage. diff --git a/web/schemeweb/reader.sw b/web/schemeweb/reader.sw new file mode 100644 index 0000000000..fee7e1f6ec --- /dev/null +++ b/web/schemeweb/reader.sw @@ -0,0 +1,44 @@ +\documentstyle{article} +% $Id: reader.sw,v 2.0 1994/02/25 14:03:14 ramsdell Exp $ +\title{{\tt read-sw}} +\author{John D. Ramsdell} +\date{\verb$Date: 1994/02/25 14:03:14 $} + +\newcommand{\schemeweb}{Scheme{\tt WEB}} + +\begin{document} + +\maketitle + +\verb|read-sw| reads a {\schemeweb} source file +much as \verb|read| reads a Scheme source file. +(define (read-sw . rest) ; Returns what \verb|read| returns. + (let ((port (if (pair? rest) ; \verb|read-sw| arguments are + (car rest) ; the same as \verb|read|'s. + (current-input-port)))) + (letrec + ((text-mode-and-saw-newline ; Lines of a {\schemeweb} file + (lambda () ; beginning with ``{\tt(}'', + (let ((ch (peek-char port))) ; start a code section. + (cond ((eof-object? ch) ch) + ((char=? ch #\() ; If code section, then use + (got-code (read port))) ; \verb|read| to get code, + (else ; else skip this line as it + (text-mode-within-a-line)))))) ; is a comment. + (text-mode-within-a-line + (lambda () ; Ignore comments. + (let ((ch (read-char port))) + (cond ((eof-object? ch) ch) + ((char=? ch #\newline) + (text-mode-and-saw-newline)) + (else (text-mode-within-a-line)))))) + (got-code + (lambda (code) ; Ignore the remainder of the + (let ((ch (read-char port))) ; last code line and return + (cond ((eof-object? ch) code) ; the results of \verb|read|. + ((char=? ch #\newline) + code) + (else (got-code code))))))) + (text-mode-and-saw-newline) ; Start by looking + ))) ; for a code line. +\end{document} diff --git a/web/schemeweb/sweb.1 b/web/schemeweb/sweb.1 new file mode 100644 index 0000000000..7c5d617e98 --- /dev/null +++ b/web/schemeweb/sweb.1 @@ -0,0 +1,73 @@ +.TH sweb 1 +.\" $Id: sweb.1,v 2.0 1994/02/25 13:43:28 ramsdell Exp $ +.SH NAME +sweb \- Simple support for literate programming in Lisp. +.SH SYNOPSIS +.B sweb +[-stuvwx] [input_file [output_file]] +.SH DESCRIPTION +A SchemeWEB file is a Lisp source file which contains code sections +and comment sections, but each section is identified in a novel way. +A code section begins with a line whose first character is a left +parenthesis. +It continues until a line is found which contains the +parenthesis that matches the one which started the code section. +The remaining lines of text in the source file are treated as comments. + +Several operations involving SchemeWEB files are provided by the +.B sweb +program. +.PP +The +.B \-t +option translates a SchemeWEB file into a standard Lisp file. +It simply adds an initial semicolon to comment lines that lack them, and +passes code sections through unchanged. +This process is called tangling the SchemeWEB file. +.PP +The +.B \-w +option translates a SchemeWEB file into a LaTeX source file. +Text is added to code sections so that LaTeX will print the code verbatim. +Comment sections are passed through unchanged except that if the first +character of a line is a semicolon, it is excised. +This makes it possible to process a SchemeWEB file which has been tangled. +This process is called weaving the SchemeWEB file. +This is the default action of +.B sweb. +.PP +The +.B \-x +option weaves a SchemeWEB file as above, except the LaTeX source +produced inhibits page breaks in code sections. +.PP +The +.B \-u +option translates a Lisp file which has been produced from a +SchemeWEB file back into a SchemeWEB file. +It simply removes the first semicolon in every line that starts with +one as its first character. +This process is called untangling a +.B sweb +produced Lisp file. +.PP +The +.B \-s +option tangles a SchemeWEB file and strips all comments from the file. +.PP +The +.B \-v +option prints version information. +.PP +A SchemeWEB file can be stored and distributed as a standard Lisp +file by tangling the SchemeWEB file. +For the purposes of editing comments, the SchemeWEB file can be +recovered by untangling the Lisp file. +LaTeX documentation can be generated from both the Lisp file or the +SchemeWEB file. +.PP +SchemeWEB was originally developed for the Scheme dialect of Lisp; +however, it became obvious that no changes were required to support +most other dialects. +SchemeWEB's name reflects its heritage. + diff --git a/web/schemeweb/sweb.c b/web/schemeweb/sweb.c new file mode 100644 index 0000000000..fa882e9182 --- /dev/null +++ b/web/schemeweb/sweb.c @@ -0,0 +1,420 @@ +/* SchemeWEB -- WEB for Lisp. John D. Ramsdell. + * Simple support for literate programming in Lisp. + */ + +/* $Id: sweb.c,v 2.1 94/07/21 11:30:36 ramsdell Exp $ */ + +#ifndef lint +static char vcid[] = "$Id: sweb.c,v 2.1 94/07/21 11:30:36 ramsdell Exp $"; +static char copyright[] = "Copyright 1994 by The MITRE Corporation."; +#endif /* lint */ + +#define VERSION "2.1" + +/* + * Copyright 1994 by The MITRE Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a copy of the GNU General Public License, write to the + * Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + */ + +/* +This program processes SchemeWEB files. A SchemeWEB file is a Lisp +source file which contains code sections and comment sections, but +each section is identified in a novel way. A code section begins with +a line whose first character is a left parenthesis. It continues +until a line is found which contains the parenthesis that matches the +one which started the code section. The remaining lines of text in +the source file are treated as comments. Several operations involving +SchemeWEB files are provided by the this program. See the manual +page for a complete description of the various operations. +*/ + +/* SchemeWEB is currently set up for use with LaTeX. */ + +/* Define TANGLE to make a program which translates SchemeWEB source +into Scheme source by default. */ + +/* Define SAVE_LEADING_SEMICOLON if you want text lines to be copied +with any leading semicolon while weaving. */ + +#include <stdio.h> + +typedef enum {FALSE, TRUE} bool; + +/* Runtime flags */ +bool weaving; /* Weaving or tangling? */ +bool strip_comments; /* Strip comments while tangling. */ + +/* Formatting commands added into weaved documents. */ +char *begin_comment = "\\mbox{"; /* This pair is used */ +char *end_comment = "}"; /* to surround comments in code. */ +char *begin_code = "\\begin{flushleft}\n"; /* This pair is used */ +char *end_code = "\\end{flushleft}\n"; /* to surround code. */ +char *code_line_separator = "\\\\ "; +char *begin_code_line = "\\verb|"; /* This pair is used */ +char *end_code_line = "|"; /* to surround code lines. */ + +/* Information for error messages. */ +char *prog = NULL; /* Name of program. */ +char *src = NULL; /* Name of input file. */ +int lineno = 1; /* Line number. */ + +/* Output occurs through putchar, putstring, and code_putchar. */ + +#define putstring(s) (fputs(s, stdout)) + +int /* Used while printing */ +code_putchar(c) /* a code section. */ + int c; +{ + if (c == '|' && weaving) return putstring("|\\verb-|-\\verb|"); + else return putchar(c); +} + +/* All input occurs in the following routines so that TAB characters +can be expanded while weaving. TeX treats TAB characters as a +space--not what is wanted. */ + +int ch_buf; /* Used to implement */ +bool buf_used = FALSE; /* one character push back. */ + +int +getchr() +{ + int c; + static int spaces = 0; /* Spaces left to print a TAB. */ + static int column = 0; /* Current input column. */ + if (buf_used) { + buf_used = FALSE; + return ch_buf; + } + if (spaces > 0) { + spaces--; + return ' '; + } + switch (c = getc(stdin)) { + case '\t': + if (!weaving) return c; + spaces = 7 - (7&column); /* Maybe this should be 7&(~column). */ + column += spaces + 1; + return ' '; + case '\n': + lineno++; + column = 0; + return c; + default: + column++; + return c; + } +} + +void +ungetchr(c) + int c; +{ + buf_used = TRUE; + ch_buf = c; +} + +/* Error message for end of file found in code. */ +bool +report_eof_in_code() +{ + fprintf(stderr, "End of file within a code section.\n"); + return TRUE; +} + +bool +copy_text_saw_eof() /* Copies a line of text out. */ +{ /* Used while printing */ + int c; /* a text section. */ + while (1) { + c = getchr(); + if (c == EOF) return TRUE; + if (c == '\n') return FALSE; + putchar(c); + } +} + +bool +strip_text_saw_eof() /* Gobbles up a line of input. */ +{ + int c; + while (1) { + c = getchr(); + if (c == EOF) return TRUE; + if (c == '\n') return FALSE; + } +} + +bool /* This copies comments */ +copy_comment_saw_eof() /* within code sections. */ +{ + if (weaving) putstring(begin_comment); + putchar(';'); + if (copy_text_saw_eof()) return TRUE; + if (weaving) putstring(end_comment); + return FALSE; +} + +bool /* Copies a string found */ +copy_string_saw_eof() /* within a code section. */ +{ + int c; + while (1) { + c = getchr(); + if (c == EOF) return TRUE; + if (c == '\n') { /* Found a string which continues on */ + putstring(end_code_line); /* a new line. */ + putchar(c); /* Close existing line, and then */ + putstring(code_line_separator); /* begin copying the rest of */ + putstring(begin_code_line); /* on the next line. */ + continue; + } + code_putchar(c); + switch (c) { + case '"': return FALSE; + case '\\': + c = getchr(); + if (c == EOF) return TRUE; + code_putchar(c); + } + } +} + +bool +maybe_char_syntax_saw_eof() +{ /* Makes sure that the character */ + int c; /* #\( does not get counted in */ + c = getchr(); /* balancing parentheses. */ + if (c == EOF) return TRUE; + if (c != '\\') { + ungetchr(c); + return FALSE; + } + code_putchar(c); + c = getchr(); + if (c == EOF) return TRUE; + code_putchar(c); + return FALSE; +} + +bool /* Copies a code section */ +copy_code_failed() /* containing S-exprs. */ +{ + int parens = 1; /* Used to balance parentheses. */ + int c; + while (1) { /* While parens are not balanced, */ + c = getchr(); + if (c == EOF) /* Report failure on EOF. */ + return report_eof_in_code(); + if (c == '\n' && weaving) + putstring(end_code_line); + if (c == ';') { /* Report failure on EOF in a comment. */ + if (weaving) putstring(end_code_line); + if (strip_comments + ? strip_text_saw_eof() + : copy_comment_saw_eof()) + return report_eof_in_code(); + else + c = '\n'; + } + code_putchar(c); /* Write the character and then see */ + switch (c) { /* if it requires special handling. */ + case '(': + parens++; + break; + case ')': + parens--; + if (parens < 0) { + fprintf(stderr, "Too many right parentheses found.\n"); + return TRUE; + } + break; + case '"': /* Report failure on EOF in a string. */ + if (copy_string_saw_eof()) { + fprintf(stderr, "End of file found within a string.\n"); + return TRUE; + } + break; + case '#': /* Report failure on EOF in a character. */ + if (maybe_char_syntax_saw_eof()) + return report_eof_in_code(); + break; + case '\n': + if (parens == 0) return FALSE; + if (weaving) { + putstring(code_line_separator); + putstring(begin_code_line); + } + } + } +} + +int +schemeweb() +{ + int c; + while (1) { /* At loop start it's in text mode */ + c = getchr(); /* and at the begining of a line. */ + if (c == '(') { /* text mode changed to code mode. */ + if (weaving) putstring(begin_code); + do { /* Copy code. */ + if (weaving) putstring(begin_code_line); + putchar(c); + if (copy_code_failed()) { + fputs(prog, stderr); + if (src != NULL) + fprintf(stderr, ":%s:", src); + else + fputs(":<stdin>:", stderr); + fprintf(stderr, + "%d: Error in a code section.\n", + lineno); + return 1; + } + c = getchr(); /* Repeat when there is code */ + } while (c == '('); /* immediately after some code. */ + if (weaving) putstring(end_code); + } + /* Found a text line--now in text mode. */ +#if !defined SAVE_LEADING_SEMICOLON + if (c == ';' && weaving) + c = getchr(); +#endif + if (c == EOF) return 0; /* Files that do not end with */ + ungetchr(c); /* a newline are okay. */ + + if (strip_comments) { + if (strip_text_saw_eof()) return 0; + } + else { + if (c != '\n' && !weaving) putchar(';'); + if (copy_text_saw_eof()) return 0; /* Copy a text line. */ + putchar('\n'); + } + } +} + +int /* Removes any semicolons */ +untangle() /* than start a line of text. */ +{ + int c; + + while (1) { /* At a beginning of a line of text */ + c = getchar(); /* when at this point in the code. */ + if (c == EOF) return 0; + if (c != ';') putchar(c); + while (c != '\n') { + c = getchar(); + if (c == EOF) return 0; + putchar(c); + } + } +} + +bool /* Open the file arguments */ +open_file_args_failed(argc, argv) + int argc; + char *argv[]; +{ + switch (argc) { + case 2: + case 1: + src = argv[0]; /* Save for error messages. */ + if (NULL == freopen(argv[0], "r", stdin)) { + fprintf(stderr, "Cannot open %s for reading.\n", argv[0]); + break; + } + if (argc == 2 && NULL == freopen(argv[1], "w", stdout)) { + fprintf(stderr, "Cannot open %s for writing.\n", argv[1]); + break; + } + case 0: + return FALSE; + } + return TRUE; +} + +int +usage() +{ + fprintf(stderr, + "Usage: %s [-stuvwx] [input_file [output_file]]\n%s%s%s%s%s%s", + prog, + "\t-s: tangle input stripping comments\n", + "\t-t: tangle input retaining comments\n", + "\t-u: untangle input\n", + "\t-v: print version information\n", + "\t-w: weave input\n", + "\t-x: weave input and exclude line breaks in code sections\n"); + fprintf(stderr, "The default option is %s.\n", +#if defined TANGLE + "-t" +#else + "-w" +#endif + ); + return 1; +} + +int +main (argc, argv) + int argc; + char *argv[]; +{ + bool untangling = FALSE; +#if defined TANGLE + weaving = FALSE; +#else + weaving = TRUE; +#endif + strip_comments = FALSE; + + prog = argv[0]; /* Save program name for error messages. */ + + /* Option processing. Note only one option can be requested at a time. */ + /* -s: tangle input stripping comments. */ + /* -t: tangle input retaining comments. */ + /* -u: untangle input. */ + /* -v: print version information. */ + /* -w: weave input. */ + /* -x: weave input and exclude line breaks in code sections. */ + if (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + case 's': weaving = FALSE; strip_comments = TRUE; break; + case 't': weaving = FALSE; break; + case 'u': untangling = TRUE; break; + case 'v': + fprintf(stderr, "This is SchemeWEB version %s.\n", VERSION); + return 0; + case 'w': weaving = TRUE; break; + case 'x': weaving = TRUE; code_line_separator = "\\\\* "; break; + default: + fprintf(stderr, "Bad option: -%c.\n", argv[1][1]); + return usage(); + } + if (argv[1][2] != '\0') { + fprintf(stderr, "Only one option allowed.\n"); + return usage(); + } + argc--; argv++; + } + + if (open_file_args_failed(argc - 1, argv + 1)) return usage(); + + if (untangling) return untangle(); + return schemeweb(); +} |