[net.sources] ALG program sources

sdc@uvacs.UUCP (10/25/83)

This file contains the sources for "alg".  To use, delete the
header portion of this file, then write it out.  Use ar
(ar.c 4.1 10/1/80 from 4.1aBSD or equiv) to extract the files like
this (assuming you wrote this file out as alg.ar):

	ar xv alg.ar

Report problems or bugs to Scott Carson, Univ. of Virginia

	...mcnc!ncsu!uvacs!sdc - usenet
	sdc@uvacs              - csnet
	sdc.uvacs@udel-relay   - arpanet

Delete the header up to and including this line.
!<arch>
Keywords        435608003   503   10    100644  308       `
Keywords for while foreach repeat until if then else
Keywords integer boolean real array set record
Keywords type var const program function procedure
Keywords begin end in do
Keywords cobegin coend task body package elsif
Keywords import export pointer qualified from to
Keywords dif mod exit and or not is
Makefile        435875810   503   10    100644  260       `
LIB=/usr/lib/alg
BIN=/usr/local
MAN=/usr/man/manl

alg:	alg.lex
	lex alg.lex ; cc -O -o alg lex.yy.c -ll

install: alg
	cp alg ${BIN}

setup:	install
	mkdir ${LIB}
	chmod 755 ${LIB}
	cp alg.l ${MAN}
	cp alg.me Keywords example ${LIB}

clean:
	rm -f lex.yy.c

README          435887790   503   10    100644  597       `
The files in this directory are:

	Keywords  - some sample keywords
	Makefile  - the Makefile, of course
	alg.l     - the man page, goes in /usr/man/manl/alg1.l
	alg.lex   - the source code for alg
	alg.me    - macro definitions to be used with -me macros
	example   - a simple example of the use of alg

Starting from the distribution, to the following to install alg:

1.  edit the Makefile, making appropriate definitions for
	the LIB, MAN, and BIN directories.

2.  type "make setup"

3.  check out the alg program by running the file "example" through it:
	type "alg <example | nroff -me"


alg.l           435888518   503   10    100644  2752      `
.TH ALG l UVa
.UC 4
.SH NAME
alg - filter for typesetting algorithms
.SH SYNOPSIS
.B alg <infile >outfile
.SH DESCRIPTION
.I Alg
is a filter which, like
.I eqn
and
.I tbl,
is a preprocessor for
.I "troff (sroff, nroff)."
.I Alg's
specialty is typesetting algorithms or fragments of code which
appear in documents.
.PP
Algorithms are entered between the macros
.I ".AL"
and
.I ".AE",
which are analogous to the
.I ".EQ"
and
.I ".EN"
macros of
.I eqn.
You can use any format you want for the algorithms.
Keywords are set in boldface, and ada-style comments are
italicized.
.PP
.I Alg
starts out with a null list of keywords.
To define your favorite ones, include the line

	Keywords function procedure program

(with your keywords substituted for those above) as the first
line of text between your first
.I ".AL"
-
.I ".AE"
pair.
These keywords stay in effect forever (until the program terminates).
.PP
When using proportional fonts, line-by-line
comments do not normally line up the way you might want.
To surmount this problem, there are two special ada-style
comments which perform the "mark" and "lineup" functions
of
.I eqn.
To make a mark, enter the comment --+ followed by the text
that goes with it.
>From then on, all comments that begin with --- will line up
with it.
For example, you might do this:

	x := x + 1     --+ this comment makes the "mark"

	y := y - xnew  --- this comment lines up with the last

The mark lasts until the program terminates, unless you
replace it by doing another --+.
These two special comments appear normally in the output,
that is, without the extra "+" or "-".
.PP
.I Alg
recognizes quoted strings, using the same conventions as
.I cc,
with one exception.
If you forget to close a quote,
.I alg
considers the rest of the line (up to the newline) a quoted
string, and does not complain.
The usual backslash mechanism works, so the following string
is correctly interpreted:

	printf(" this is a quote \\" inside a quoted string\\n");

No processing (emboldening, italicizing) is done inside quoted
strings.
.PP
To use
.I alg,
you have to include the line

 .so /usr/lib/alg/alg.me

in your
.I "*roff"
input before you invoke the
.I ".AL"
macro.
If you want to redefine
.I ".AL"
and
.I ".AE",
to add features like a "list of algorithms", you can; they're very simple.
.PP
The file /usr/lib/alg/Keywords has a number of sample
keywords definitions.
You can tailor the list to suit your own style.
There is an example in /usr/lib/alg/example.
.SH "FILES"
/usr/lib/alg/alg.me
/usr/lib/alg/Keywords
/usr/lib/alg/example
.SH "BUGS"
You can't use the autodecrement operator "--" in your algorithms
because it looks like an ada-style comment.
.SH "AUTHOR"
Scott D. Carson, uvacs!sdc (USENET) sdc@uvacs (CSNET)


alg.lex         435894671   503   10    100644  1558      `
%%
	/* $Compile:  lex %f ; cc -O lex.yy.c -o alg -ll
	 */

#define MAXKWD 200   /*keywords*/
#define MAXKWDLEN 50 /*characters*/
 int inalg=0;
 int getkwds=0;
 char kwds[MAXKWD][MAXKWDLEN];
 int nkwds=0, found, i;
 char *addbs();

^\.AL {ECHO; inalg=1; }		/* start processing when we see one of these */
^\.AE {ECHO; inalg=0; }		/* stop processing when we see one of these */

[a-zA-Z][a-zA-Z0-9_]* {			/* identifier */
		if (getkwds) {
				strcpy(kwds[nkwds++],yytext);
		}
		else if (inalg) {
			if (strcmp(yytext,"Keywords")==0) { /* add new kwds */
				getkwds=1;
			}
			else {
				for(i=found=0; i<nkwds && !found; i++) {
						found = (strcmp(yytext,kwds[i]) == 0);
				}
				if (found) {
					printf("\\fB%s\\fP",yytext);
				}
				else ECHO;
			}
		}
		else ECHO;
	}

[\n] {if (!getkwds)  printf("%s",yytext); getkwds=0;}

[ ] {if (!getkwds) printf(" ");}


--[^+-].*$ {				/* ada-style comment */
		getkwds=0;
		if (inalg) printf("\\fI%s\\fP",yytext);
		else ECHO;
	}

--[+].*$ {				/* mark */
		getkwds=0;
		if (inalg) {
			printf("\\fI\\k(AP--%s\\fP",&yytext[3]);
		}
		else ECHO;
	}

---.*$ {				/* lineup */
		getkwds=0;
		if (inalg) {
			printf("\\fI\\h'|\\n(APu'--%s\\fP",&yytext[3]);
		}
		else ECHO;
	}

["]([^"\n\\]|"\\".)*["\n] printf("%s",addbs(yytext)); 	/* quoted string */
%%
/*
 *  add enough backslashes to s to fool nroff - used for quoted strings
 */
char *
addbs(s)
	char *s;
{
	char *t;
	static char tmpstr[200];

	for (t=tmpstr; *s ; s++,t++) {
		if (*s == '\\') {
			*t++ = *s;
		}
		*t = *s;
	}
	*t = *s;
	return tmpstr;
}
alg.me          435856896   503   10    100644  31        `
..
.de AL
.(l
..
.de AE
.)l
..

example         435887357   503   10    100644  1614      `
.so /usr/lib/alg/alg.me
.pp
This is a test of the new algorithm formatting macros.
Here is text to take up space and force the paragraph to
be large enough to look like a paragraph.
The following is a sample Pascal program, neatly done:
.sp
.AL
Keywords program procedure function
Keywords const var type for begin end while do
Keywords integer real array record file set of
program nifty (input, output)
--
--  this routine exemplifies the use of "alg" to format
--  algorithms in nroff/sroff.
--
--  notice that all Ada-style comments are in italics, and
--  that all keywords are emboldened
--
const
   n = 100;
type
   shortint = 0 .. 12;
var
   i: integer;
   x: shortint;

   procedure subnifty (var x: shortint; i: integer);
   --+
   ---  this routine does something totally worthless,
   ---  and the algorithm is inefficient at that.
   ---
   var
      y, kloop: shortint;
      xbar, zbar: integer;
   begin { subnifty }
      y := i - i * x;
      xbar := x;
      while xbar < y do begin
         zbar := xbar * zbar + kloop;
         xbar := pred(xbar);
         kloop := succ(kloop);
      end { while };
      x := zbar;
   end { subnifty };

begin { nifty }
   for i := 1 to n do begin     --+ witty observation here
      x := i * 5;               --- a classic calculation
      subnifty(x,i);
      if x <= 12 then begin
	 subnifty (x+x, i);     --- in line comment
	 x := x - i;            --- another inline comment
      end { if };
      x := x + i;
   end { for };
   writeln (output,"the answer is ", x);        --+ reset the line up column
end { nifty }.  --- did it work right ???
.AE