initial checkin

This commit is contained in:
gdr 1997-03-14 06:22:29 +00:00
parent e5b9329e55
commit 50a93eb0a9
28 changed files with 9446 additions and 0 deletions

39
usr.bin/nroff/ChangeLog Normal file
View File

@ -0,0 +1,39 @@
CHANGES
-------
2.0
- Maintenance of nroff has been taken over by Devin Reade,
<gdr@myrias.com>
- Fixed a significant number of memory trashing bugs with the
help of Insight.
- Optimized for speed, mainly by translating some functions
into inline code via macros.
- Prototyped, indented and otherwise cleaned up code. Made use
of some GNO v2.0.6 libc routines to reduce source code size.
- Indented source.
=== The remaining versions listed below were by Mike Horwath, ===
=== <mfrankow@seq.hamline.edu> and Jawaid Bazyar <bazyar@hypermall.com> ===
1.1p3.4
Well, guess what? I caused a hell of an error in the last
version of this, and now it is fixed. The problem stemmed
from a library error and has been fixed. All thanks to Jawaid
for creating and fixing the error all by himself. (no flame
to ya Jawaid...heh)
1.1p3.3
Fixed the problem with nroffing the LESS manpage. I don't
really know how the hell I fixed it, but that bug is now gone.
I also optimized the source to a great extent. There is no real
speed increase in output, but the executable is MUCH smaller
than the original posted version. Enjoy.
4/21/92 jb
Fixed double-line problem when redirecting and piping the output
of nroff. (It sticks \r's in the output text all over the place.
I simply filter them out in prchar.)
[previous versions]
Well, first release. The versions suck for now till I can
figure out a better way to do it. It worked, but had bugs.

38
usr.bin/nroff/README Normal file
View File

@ -0,0 +1,38 @@
nroff - Text Processing Typesetter
----------------------------------
This is 'nroff 1.2' for GNO/ME 1.0. This is fairly close to
the real Unix nroff, although there are still some things that
this one doesn't do that it should.
This software was ported by Mike Horwath and Jawaid Bazyar for
the GNO Multitasking Environment. Various bug fixes were applied
by Devin Reade.
Installation
------------
Type 'dmake install' in this directory, or copy the following
files:
nroff --> /usr/bin/nroff
tmac.an --> /usr/lib/tmac/tmac.an
tmac.s --> /usr/lib/tmac/tmac.s
nroff.1 --> /usr/man/man1/nroff.1
man.7 --> /usr/man/man7/man.7
ms.7 --> /usr/man/man7/ms.7
If you want to put the macro files somewhere other than in
/usr/lib/tmac, then set your TMACDIR environment variable to
point to the directory in which they reside.
Compatibility
-------------
This software works with any GNO-compatible shell (Orca suffices,
but pipes don't work very well under Orca, and according to
dozens of GNO users, GNO is "simply superior".)
Bugs
----
This program uses recursion, Not A Good Thing on the IIgs.
It really needs a rewrite.

1672
usr.bin/nroff/command.c Normal file

File diff suppressed because it is too large Load Diff

100
usr.bin/nroff/config.h Normal file
View File

@ -0,0 +1,100 @@
/*
* for diffent os, define tos, unix, or minix. for gemdos, pick
* a compiler (alcyon, mwc, etc). see makefile for VERSFLAGS.
*
* for atari TOS, do: cc -Dtos -Dalcyon ...
*
* for minix, do: cc -D_MINIX -D_ST ... (ST minix)
* cc -D_MINIX ... (PC minix)
*
* for unix, do: cc -Dunix ... (generic)
* cc -Dunix -DBSD... (BSD)
*
* note: so far there is no specific ST minix version. -D_ST is ignored.
*
* nroff uses index/rindex. you may need -Dindex=strchr -Drindex=strrchr
* as well. this file is included in "nroff.h" which gets included in all
* sources so any definitions you need should be added here.
*
* all os-dependent code is #ifdef'ed with GEMDOS, MINIX_ST, MINIX_PC,
* MINIX, or UNIX. most of the differences deal with i/o only.
*/
#ifndef CONFIG_H
#define CONFIG_H
#ifdef __GNO__
#define unix
#define NEWLINE '\r'
#endif
#ifdef ALCYON
# ifndef tos
# define tos
# endif
# ifndef alcyon
# define alcyon
# endif
#endif
#ifdef tos
# define GEMDOS
# undef minix
# undef unix
# undef MINIX
# undef MINIX_ST
# undef MINIX_PC
# undef UNIX
/*#define register*/
#endif
#ifdef alcyon
# ifndef ALCYON
# define ALCYON /* for gemdos version, alcyon C */
# endif
# ifndef GEMDOS
# define GEMDOS
# endif
#endif
#ifdef minix
# ifndef _MINIX
# define _MINIX
# endif
#endif
#ifdef _MINIX
# define MINIX
# undef tos
# undef unix
# undef GEMDOS
# undef MINIX_ST
# undef MINIX_PC
# undef UNIX
# ifdef _ST
# ifndef atariST
# define atariST
# endif
# endif
# ifdef atariST
# define MINIX_ST
# else
# define MINIX_PC
# endif
#endif
#ifdef unix
/* just in case <ctype.h> does not define it (slightly different anyway) */
/*#define tolower(x) (isupper(x)?((x)-'A'+'a'):(x))*/
# undef tos
# undef minix
# undef _MINIX
# undef GEMDOS
# undef _ST
# undef MINIX_ST
# undef MINIX_PC
# ifndef UNIX
# define UNIX
# endif
#endif
#endif /*CONFIG_H*/

759
usr.bin/nroff/escape.c Normal file
View File

@ -0,0 +1,759 @@
/*
* escape.c - Escape and special character input processing portion of
* nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: escape.c,v 1.1 1997/03/14 06:22:27 gdr Exp $
*/
#ifdef __ORCAC__
segment "escape____";
#endif
#define INVERSE '\xF'
#define NORMAL '\xE'
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __GNO__
#include <err.h>
#else
#include "err.h"
#endif
#ifdef sparc
#include "sunos.h"
#endif
#include "nroff.h"
#include "escape.h"
#include "macros.h"
static int specialchar (char *s, char *c);
/*
* expesc
*
* Expand escape sequences in the buffer <src>, placing the results
* in buffer <dest>. If the number of characters written into <dest>
* would be more than <len-1> characters, then abort with an error
* message.
*/
void
expesc (char *src, char *dest, size_t len) {
register char *s;
register char *t;
register char *pstr;
register int i;
register int val;
register int autoinc;
char c;
char fs[5]; /* for font change */
char nrstr[20];
char fmt[20];
char name[10];
int nreg;
char *pfs;
int inc;
int tmp;
char delim;
const char *percent = "%";
char *scratch;
s = src;
t = dest;
/*
* if escape parsing is not on, just copy string
*/
if (dc.escon == NO) {
if (strlen(src) > len-1) {
errx(-1, "buffer overflow at %s:%d", __FILE__, __LINE__);
}
strcpy (dest, src);
return;
}
/*
* do it...
*/
while (*s != EOS) {
if (*s != dc.escchr) {
/*
* not esc, continue...
*/
*t++ = *s++;
} else if (*(s + 1) == dc.escchr) {
/*
* \\ escape escape
*/
*t++ = *s++;
++s;
} else {
switch(*(s+1)) {
case 'n':
/*
* \nx, \n(xx register
*
* first check for \n+... or \n-... (either form)
*/
s += 2;
autoinc = 0;
if (*s == '+') {
autoinc = 1;
s += 1;
}
if (*s == '-') {
autoinc = -1;
s += 1;
}
/*
* was this \nx or \n(xx form?
*/
if (isalpha (*s)) {
/*
* \nx form. find reg (a-z)
*/
nreg = tolower (*s) - 'a';
/*
* was this \n+x or \n-x? if so, do the
* auto incr
*/
if (autoinc > 0) {
dc.nr[nreg] += dc.nrauto[nreg];
} else if (autoinc < 0) {
dc.nr[nreg] -= dc.nrauto[nreg];
}
/*
* display format
*/
if (dc.nrfmt[nreg] == '1') {
/*
* normal decimal digits
*/
t += itoda (dc.nr[nreg], t, 6) - 1;
} else if (dc.nrfmt[nreg] == 'i') {
/*
* lower roman
*/
t += itoroman (dc.nr[nreg], t, 24) - 1;
} else if (dc.nrfmt[nreg] == 'I') {
/*
* upper roman
*/
t += itoROMAN (dc.nr[nreg], t, 24) - 1;
} else if (dc.nrfmt[nreg] == 'a') {
/*
* lower letters
*/
t += itoletter (dc.nr[nreg], t, 12) - 1;
} else if (dc.nrfmt[nreg] == 'A') {
/*
* upper letters
*/
t += itoLETTER (dc.nr[nreg], t, 12) - 1;
} else if (dc.nrfmt[nreg] & 0x80) {
/*
* zero-filled decimal
*/
sprintf (fmt, "%%0%dld", (int)(dc.nrfmt[nreg] & 0x7F));
fmt[5] = '\0';
sprintf (nrstr, fmt, (long) dc.nr[nreg]);
tmp = dc.nrfmt[nreg] & 0x7F;
nrstr[tmp] = '\0';
strcpy (t, nrstr);
t += strlen (nrstr);
} else {
/*
* normal (default)
*/
t += itoda (dc.nr[nreg], t, 6) - 1;
}
++s;
} else if (*s == '%') {
/*
* \n% form. find index into reg struct
*/
FINDREG(percent, nreg, scratch);
if (nreg < 0) {
errx(-1, "no register match");
}
/*
* was this \n+% or \n-%? if so, do the
* auto incr
*/
if (autoinc > 0) {
rg[nreg].rval += rg[nreg].rauto;
} else if (autoinc < 0) {
rg[nreg].rval -= rg[nreg].rauto;
}
/*
* display format
*/
if (rg[nreg].rfmt == '1') {
/*
* normal decimal digits
*/
t += itoda (rg[nreg].rval, t, 6) - 1;
} else if (rg[nreg].rfmt == 'i') {
/*
* lower roman
*/
t += itoroman (rg[nreg].rval, t, 24) - 1;
} else if (rg[nreg].rfmt == 'I') {
/*
* upper roman
*/
t += itoROMAN (rg[nreg].rval, t, 24) - 1;
} else if (rg[nreg].rfmt == 'a') {
/*
* lower letters
*/
t += itoletter (rg[nreg].rval, t, 12) - 1;
} else if (rg[nreg].rfmt == 'A') {
/*
* upper letters
*/
t += itoLETTER (rg[nreg].rval, t, 12) - 1;
} else if (rg[nreg].rfmt & 0x80) {
/*
* zero-filled decimal
*/
sprintf (fmt, "%%0%dld",
(int)(rg[nreg].rfmt & 0x7F));
fmt[5] = '\0';
sprintf (nrstr, fmt, (long) rg[nreg].rval);
tmp = rg[nreg].rfmt & 0x7F;
nrstr[tmp] = '\0';
strcpy (t, nrstr);
t += strlen (nrstr);
} else {
/*
* normal (default)
*/
t += itoda (rg[nreg].rval, t, 6) - 1;
}
s += 1;
} else if (*s == '(') {
/*
* \n(xx form. find index into reg struct
*/
s += 1;
name[0] = *s;
name[1] = *(s + 1);
if (name[1] == ' ' || name[1] == '\t'
|| name[1] == '\n' || name[1] == '\r') {
name[1] = '\0';
}
name[2] = '\0';
FINDREG(name, nreg, scratch);
if (nreg < 0) {
errx(-1, "no register match");
}
/*
* was this \n+(xx or \n-(xx? if so, do the
* auto incr
*/
if (rg[nreg].rflag & RF_WRITE) {
if (autoinc > 0) {
rg[nreg].rval += rg[nreg].rauto;
} else if (autoinc < 0) {
rg[nreg].rval -= rg[nreg].rauto;
}
}
/*
* display format
*/
if (rg[nreg].rfmt == '1') {
/*
* normal decimal digits
*/
t += itoda (rg[nreg].rval, t, 6) - 1;
} else if (rg[nreg].rfmt == 'i') {
/*
* lower roman
*/
t += itoroman (rg[nreg].rval, t, 24) - 1;
} else if (rg[nreg].rfmt == 'I') {
/*
* upper roman
*/
t += itoROMAN (rg[nreg].rval, t, 24) - 1;
} else if (rg[nreg].rfmt == 'a') {
/*
* lower letters
*/
t += itoletter (rg[nreg].rval, t, 12) - 1;
} else if (rg[nreg].rfmt == 'A') {
/*
* upper letters
*/
t += itoLETTER (rg[nreg].rval, t, 12) - 1;
} else if (rg[nreg].rfmt & 0x80) {
/*
* zero-filled decimal
*/
sprintf (fmt, "%%0%dld",
(int)(rg[nreg].rfmt & 0x7F));
fmt[5] = '\0';
sprintf (nrstr, fmt, (long) rg[nreg].rval);
tmp = rg[nreg].rfmt & 0x7F;
nrstr[tmp] = '\0';
strcpy (t, nrstr);
t += strlen (nrstr);
} else {
/*
* normal (default)
*/
t += itoda (rg[nreg].rval, t, 6) - 1;
}
s += 2;
}
break;
case '"': /* \" comment */
*s = EOS;
*t = *s;
return;
case '*': /* \*x, \*(xx string */
/*
*/
s += 2;
if (*s == '(') {
/*
* \*(xx form
*/
s += 1;
name[0] = *s;
name[1] = *(s + 1);
name[2] = '\0';
pstr = getstr (name);
if (!pstr) {
errx(-1,"string not found");
}
while (*pstr) {
*t++ = *pstr++;
}
s += 2;
} else {
/*
* \*x form
*/
name[0] = *s;
name[1] = '\0';
pstr = getstr (name);
if (!pstr) {
errx(-1, "string not found");
}
while (*pstr) {
*t++ = *pstr++;
}
s += 1;
}
break;
case 'f': /* \fx font */
s += 2;
pfs = fs; /* set up ret string */
fs[0] = '\0';
/*
* it parses 1-2 char of s and returns esc seq for
* \fB and \fR (\fI is same as \fB)
*/
fontchange (*s, pfs);
/*
* imbed the atari (vt52) escape seq
*/
while (*pfs) {
*t++ = *pfs++;
}
++s; /* skip B,I,R,S,P */
break;
case '(': /* \(xx special char */
s += 2;
/*
* it returns num char to skip and sets c to
* the ascii value of the char
*/
inc = specialchar (s, &c);
/*
* skip proper num char in s and add c to target
*/
if (inc) {
s += inc;
*t++ = c;
}
break;
case 'e': /* \e printable version of escape */
*t++ = dc.escchr;
s += 2;
break;
case '-': /* \- minus */
case '`': /* \` grave, like \(ga */
case '\'': /* \' accute, like \(aa */
case '.': /* \. period */
case ' ': /* \(space) space */
/* verbatim */
*t++ = *(s+1);
s += 2;
break;
case '0': /* \0 digital width space */
*t++ = ' ';
s += 2;
break;
case '|': /* \| narrow width char (0 in nroff) */
case '^': /* \^ narrow width char (0 in nroff) */
case '&': /* \& non-printing zero width */
case '!': /* \! transparent copy line */
case '$': /* \$N interpolate arg 1<=N<=9 */
case 'a': /* \a */
case 'b': /* \b'abc...' */
case 'c': /* \c */
case 'd': /* \d */
case 'k': /* \kx */
case 'l': /* \l'Nc' */
case 'L': /* \L'Nc' */
case 'p': /* \p */
case 'r': /* \r */
case 's': /* \sN,\s+-N */
case 'u': /* \u */
case 'w': /* \w'str' */
case 'x': /* \x'N' */
case '{': /* \{ */
case '}': /* \} */
case '\n': /* \(newline) ignore newline */
case '\r': /* \(newline) ignore newline */
s += 2; /* currently ignored */
break;
case '%': /* \% hyphen */
*t++ = '-';
*t++ = '-';
s += 2;
break;
case 'h': /* \h'N' horiz motion*/
s += 2;
delim = *s++;
val = atoi (s);
for (i = 0; i < val; i++) {
*t++ = ' ';
}
while (*s != delim) {
if (*s == 0) {
break;
}
s++;
}
if (*s) {
s++;
}
break;
case 'o': /* \o'abc...' overstrike*/
s += 2;
delim = *s++;
while (*s != EOS && *s != delim) {
*t++ = *s++;
*t++ = 0x08;
}
s++;
break;
case 't': /* \t horizontal tab*/
*t++ = '\t';
s += 2;
break;
case 'v': /* \v'N' vert tab*/
s += 2;
delim = *s++;
val = atoi (s);
for (i = 0; i < val; i++) {
*t++ = 0x0A;
}
while (*s != delim) {
if (*s == 0) {
break;
}
s++;
}
if (*s) {
s++;
}
break;
case 'z': /* \zc print c w/o spacing*/
s += 2;
*t++ = *s++;
*t++ = 0x08;
break;
default: /* \X any other character not above*/
s += 1;
*t++ = *s++;
break;
}
}
}
/*
* end the string and return it in original buf
*/
*t = EOS;
/* gdr: this seems to defeat the expansion we just did. */
strcpy (src, dest);
}
/*
* specialchar
* handles \(xx escape sequences for special characters (atari-specific)
*/
static int
specialchar (register char *s, register char *c) {
register char c1;
register char c2;
c1 = *s;
c2 = *(s+1);
/*
* symbols (std font)
*/
if (c1 == 'e' && c2 == 'm') {*c = 0x2D; return 2;} /* dash */
if (c1 == 'h' && c2 == 'y') {*c = 0x2D; return 2;} /* hyphen */
if (c1 == 'b' && c2 == 'u') {*c = 0xF9; return 2;} /* bullet */
if (c1 == 's' && c2 == 'q') {*c = 0xF9; return 2;} /* square */
if (c1 == 'r' && c2 == 'u') {*c = 0x5F; return 2;} /* rule */
if (c1 == '1' && c2 == '2') {*c = 0xAB; return 2;} /* 1/2 */
if (c1 == '1' && c2 == '4') {*c = 0xAC; return 2;} /* 1/4 */
if (c1 == 'd' && c2 == 'e') {*c = 0xF8; return 2;} /* degree */
if (c1 == 'd' && c2 == 'g') {*c = 0xBB; return 2;} /* dagger */
if (c1 == 'f' && c2 == 'm') {*c = 0xBA; return 2;} /* dagger */
if (c1 == 'c' && c2 == 't') {*c = 0x9B; return 2;} /* cent */
if (c1 == 'c' && c2 == 'o') {*c = 0xBD; return 2;} /* copyrite */
if (c1 == 'r' && c2 == 'g') {*c = 0xBE; return 2;} /* registered */
if (c1 == 't' && c2 == 'm') {*c = 0xBF; return 2;} /* trademark */
if (c1 == 'p' && c2 == '2') {*c = 0xFD; return 2;} /* ^2 */
if (c1 == 'p' && c2 == '3') {*c = 0xFE; return 2;} /* ^3 */
if (c1 == 'p' && c2 == 'n') {*c = 0xFC; return 2;} /* ^n */
if (c1 == 'a' && c2 == 'a') {*c = 0xBA; return 2;} /* acute */
if (c1 == 'g' && c2 == 'a') {*c = 0x60; return 2;} /* grave */
if (c1 == 'd' && c2 == 't') {*c = 0xFA; return 2;} /* dot */
if (c1 == 'p' && c2 == 'p') {*c = 0xBC; return 2;} /* paragraph */
if (c1 == '^' && c2 == 'g') {*c = 0x07; return 2;} /* ring bell */
if (c1 == 'u' && c2 == 'a') {*c = 0x01; return 2;} /* up arrow */
if (c1 == 'd' && c2 == 'a') {*c = 0x02; return 2;} /* dn arrow */
if (c1 == '-' && c2 == '>') {*c = 0x03; return 2;} /* rt arrow */
if (c1 == '<' && c2 == '-') {*c = 0x04; return 2;} /* lf arrow */
if (c1 == 'd' && c2 == 'i') {*c = 0xF6; return 2;} /* divide */
if (c1 == 's' && c2 == 'r') {*c = 0xFB; return 2;} /* sq root */
if (c1 == '=' && c2 == '=') {*c = 0xF0; return 2;} /* == */
if (c1 == '>' && c2 == '=') {*c = 0xF2; return 2;} /* >= */
if (c1 == '<' && c2 == '=') {*c = 0xF3; return 2;} /* <= */
if (c1 == '+' && c2 == '-') {*c = 0xF1; return 2;} /* +- */
if (c1 == '~' && c2 == '=') {*c = 0xF7; return 2;} /* ~= */
if (c1 == 'a' && c2 == 'p') {*c = 0x7E; return 2;} /* approx */
if (c1 == 'n' && c2 == 'o') {*c = 0xAA; return 2;} /* not */
if (c1 == 'm' && c2 == 'o') {*c = 0xEE; return 2;} /* member */
if (c1 == 'c' && c2 == 'a') {*c = 0xEF; return 2;} /* intersect */
if (c1 == 'c' && c2 == 'u') {*c = 0x55; return 2;} /* union */
if (c1 == 'i' && c2 == '1') {*c = 0xF4; return 2;} /* integral1 */
if (c1 == 'i' && c2 == '2') {*c = 0xF5; return 2;} /* integral2 */
if (c1 == 'b' && c2 == 'r') {*c = 0x7C; return 2;} /* box v rule */
if (c1 == 'b' && c2 == 'v') {*c = 0x7C; return 2;} /* bold vert */
if (c1 == 'p' && c2 == 'l') {*c = 0x2B; return 2;} /* math plus */
if (c1 == 'm' && c2 == 'i') {*c = 0x2D; return 2;} /* math minus */
if (c1 == 'e' && c2 == 'q') {*c = 0x3D; return 2;} /* math equal */
if (c1 == '*' && c2 == '*') {*c = 0x2A; return 2;} /* math star */
if (c1 == 's' && c2 == 'l') {*c = 0x2F; return 2;} /* slash */
if (c1 == 'u' && c2 == 'l') {*c = 0x5F; return 2;} /* underrule */
if (c1 == 's' && c2 == 'c') {*c = 0xDD; return 2;} /* section */
/*
* greek
*/
if (c1 == '*' && c2 == 'a') {*c = 0xE0; return 2;} /* alpha */
if (c1 == '*' && c2 == 'b') {*c = 0xE1; return 2;} /* beta */
if (c1 == '*' && c2 == 'g') {*c = 0xE2; return 2;} /* gamma */
if (c1 == '*' && c2 == 'd') {*c = 0x7F; return 2;} /* delta */
if (c1 == '*' && c2 == 's') {*c = 0xE4; return 2;} /* sigma */
if (c1 == '*' && c2 == 'p') {*c = 0xE3; return 2;} /* pi */
if (c1 == '*' && c2 == 'm') {*c = 0xE6; return 2;} /* mu */
*c = ' ';
return 0;
}
/*
* fontchange
* handles \fx font change escapes for R,B,I,S,P (atari-specific)
* resets current and last font in dc struct (last used for .ft
* with no args)
*/
#undef SHORT_STANDOUT
void
fontchange (char fnt, char *s) {
int tmp;
*s = '\0';
switch (fnt) {
case 'R': /* Times Roman */
if (dc.dofnt == YES) {
#ifdef SHORT_STANDOUT
s[0] = E_STANDOUT; s[1] = 0;
#else
strcpy (s, e_standout);
#endif
}
dc.lastfnt = dc.thisfnt;
dc.thisfnt = 1;
break;
case 'I': /* Times italic */
if (dc.dofnt == YES) {
#ifdef SHORT_STANDOUT
s[0] = S_STANDOUT; s[1] = 0;
#else
strcpy (s, s_standout);
#endif
}
dc.lastfnt = dc.thisfnt;
dc.thisfnt = 2;
break;
case 'B': /* Times bold */
if (dc.dofnt == YES) {
#ifdef SHORT_STANDOUT
s[0] = S_STANDOUT; s[1] = 0;
#else
strcpy (s, s_standout);
#endif
}
dc.lastfnt = dc.thisfnt;
dc.thisfnt = 3;
break;
case 'S': /* math/special */
*s = '\0';
dc.lastfnt = dc.thisfnt;
dc.thisfnt = 4;
break;
case 'P': /* previous (exchange) */
if (dc.dofnt == YES) {
if (dc.lastfnt == 1) {
#ifdef SHORT_STANDOUT
s[0] = E_STANDOUT; s[1] = 0;
#else
strcpy (s, e_standout); /* to R */
#endif
} else if (dc.lastfnt == 2) {
#ifdef SHORT_STANDOUT
s[0] = S_STANDOUT; s[1] = 0;
#else
strcpy (s, s_standout); /* to I */
#endif
} else if (dc.lastfnt == 3) {
#ifdef SHORT_STANDOUT
s[0] = S_STANDOUT; s[1] = 0;
#else
strcpy (s, s_standout); /* to B */
#endif
} else {
*s = '\0'; /* nothing */
}
}
tmp = dc.thisfnt; /* swap this/last */
dc.thisfnt = dc.lastfnt;
dc.lastfnt = tmp;
break;
default:
*s = '\0';
break;
}
set_ireg (".f", dc.thisfnt, 0);
}
#if 0 /* using macro version */
/*
* findreg
*
* find register named 'name' in pool. return index into array or -1
* if not found.
*/
int
findreg (register char *name) {
register int i;
register char *prname;
for (i = 0; i < MAXREGS; i++) {
prname = rg[i].rname;
if (*prname == *name && *(prname + 1) == *(name + 1)) {
break;
}
}
return ((i < MAXREGS) ? i : -1);
}
#endif

25
usr.bin/nroff/escape.h Normal file
View File

@ -0,0 +1,25 @@
/*
* $Id: escape.h,v 1.1 1997/03/14 06:22:27 gdr Exp $
*
* FINDREG -- macro version of findreg().
* <name> is the register name to find
* <result> is the returned index (-1 iff <name> was not found)
* <scratch_i> is a scratch integer variable
* <scratch_p> is a scratch char * variable
*/
#define FINDREG(name,result,scratch_p) \
{ \
for (result = 0; result < MAXREGS; result++) { \
scratch_p = rg[result].rname; \
if (*scratch_p == *name && *(scratch_p + 1) == *(name + 1)) { \
break; \
} \
} \
if (result >= MAXREGS) { \
result = -1; \
} \
}
void expesc (char *src, char *dest, size_t len);
void fontchange (char fnt, char *s);

325
usr.bin/nroff/io.c Normal file
View File

@ -0,0 +1,325 @@
/*
* io.c - low level I/O processing portion of nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: io.c,v 1.1 1997/03/14 06:22:27 gdr Exp $
*/
#ifdef __ORCAC__
segment "io________";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef __GNO__
#include <err.h>
#include <termcap.h>
#else
#include "err.h"
#include "termcap.h"
#endif
#ifdef sparc
#include "sunos.h"
#endif
#include "nroff.h"
#include "macros.h"
#include "io.h"
#include "escape.h"
char __i;
char *__s;
FILE *fpGLOB;
int
tprchar(char c)
{
return putc( c, fpGLOB );
}
/*
* getlin
*
* retrieve one line of input text from the push-back buffer or
* in_buf, place it in out_buf
*/
int
getlin (char *out_buf, FILE *in_buf) {
#if 0
/*
* gdr: these optimizations should work, but don't as yet ...
*/
register char *q;
register int i;
int c;
int nreg;
const char *dotc = ".c";
i = 0;
/* get characters from the push-back buffer */
q = out_buf;
while ((i < MAXLINE - 1) && (mac.ppb >= mac.pbb)) {
#if 1 /* doesn't happen */
c = *mac.ppb--;
if (c == EOF) {
*q = EOS;
return (i == 0) ? EOF : i;
}
*q++ = c;
#else
*q++ = c = *mac.ppb--;
#endif
if (c == '\n') {
break;
}
i++;
}
*q = EOS;
/* get characters from stream */
c = MAXLINE - i;
if (c > 0) {
fgets(q, c, in_buf);
}
FINDREG(dotc, nreg, q);
if (nreg > 0) {
set_ireg (dotc, rg[nreg].rval + 1, 0);
}
i = strlen(out_buf);
assert(i || feof(in_buf));
return (i == 0) ? EOF : i;
#else /* gdr: old way */
register char *q;
register int i;
int c;
int nreg;
const char *dotc = ".c";
q = out_buf;
for (i = 0; i < MAXLINE - 1; ++i) {
c = NGETC (in_buf);
if (c == EOF) {
*q = EOS;
c = strlen (out_buf);
return (c == 0 ? EOF : c);
}
*q++ = c;
if (c == '\n') {
break;
}
}
*q = EOS;
FINDREG(dotc, nreg, q);
if (nreg > 0) {
set_ireg (dotc, rg[nreg].rval + 1, 0);
}
return (strlen (out_buf));
#endif
}
/*
* pbstr
* Push back string into input stream
*/
void
pbstr (char *str) {
char *p;
if (str == NULL) {
return;
}
p = str + strlen(str) - 1;
while (p >= str) {
PUTBAK(*p);
--p;
}
return;
}
/*
* put
* put out line with proper spacing and indenting
*/
void
put (char *p) {
register int j;
char os[MAXLINE];
if (pg.lineno == 0 || pg.lineno > pg.bottom) {
phead ();
}
if (dc.prflg == TRUE) {
if (!dc.bsflg) {
if (strkovr (p, os) == TRUE) {
for (j = 0; j < pg.offset; ++j) {
PRCHAR2(' ', out_stream);
}
for (j = 0; j < dc.tival; ++j) {
PRCHAR2(' ', out_stream);
}
putlin (os, out_stream);
}
}
for (j = 0; j < pg.offset; ++j) {
PRCHAR2(' ', out_stream);
}
for (j = 0; j < dc.tival; ++j) {
PRCHAR2(' ', out_stream);
}
putlin (p, out_stream);
}
dc.tival = dc.inval;
skip (MIN(dc.lsval - 1, pg.bottom - pg.lineno));
pg.lineno = pg.lineno + dc.lsval;
set_ireg ("ln", pg.lineno, 0);
if (pg.lineno > pg.bottom) {
pfoot ();
#ifdef GEMDOS
if (stepping) {
wait_for_char();
}
#endif
}
}
/*
* putlin
* output a null terminated string to the file
* specified by pbuf.
*/
void
putlin (char *p, FILE *pbuf)
{
while (*p != EOS) {
PRCHAR(*p, pbuf);
p++;
}
}
#ifdef NOT_USED
/*
* prchar
* print character with test for printer
*/
void
prchar (char __c, FILE *fp)
{
#if 0
/* this really slows things down. it should be fixed. for now, ignore
* line printer...
*/
if (fp == stdout) {
putc (c, fp);
} else {
putc_lpr (c, fp);
}
#endif
#if 0
switch(c) {
case S_STANDOUT:
fpGLOB = fp;
tputs(s_standout,1,tprchar);
break;
case E_STANDOUT:
fpGLOB = fp;
tputs(e_standout,1,tprchar);
break;
case S_BOLD:
fpGLOB = fp;
tputs(s_bold,1,tprchar);
break;
case E_BOLD:
fpGLOB = fp;
tputs(e_bold,1,tprchar);
break;
case S_ITALIC:
fpGLOB = fp;
tputs(s_italic,1,tprchar);
break;
case E_ITALIC:
fpGLOB = fp;
tputs(e_italic,1,tprchar);
break;
case 13:
break;
default:
putc(c, fp);
}
#else
/*
* Don't use a case statement here; the macros are out of range
* for some compilers.
*/
if (__c == S_STANDOUT) {
fpGLOB = fp;
tputs(s_standout,1,tprchar);
} else if (__c == E_STANDOUT) {
fpGLOB = fp;
tputs(e_standout,1,tprchar);
} else if (__c == S_BOLD) {
fpGLOB = fp;
tputs(s_bold,1,tprchar);
} else if (__c == E_BOLD) {
fpGLOB = fp;
tputs(e_bold,1,tprchar);
} else if (__c == S_ITALIC) {
fpGLOB = fp;
tputs(s_italic,1,tprchar);
} else if (__c == E_ITALIC) {
fpGLOB = fp;
tputs(e_italic,1,tprchar);
} else if (__c == 13) {
;
} else {
putc(c, fp);
}
#endif
}
/*
* putc_lpr
* write char to printer
*/
void
putc_lpr (char c, FILE *fp)
{
putc (c, fp);
}
#endif /* NOT_USED */

75
usr.bin/nroff/io.h Normal file
View File

@ -0,0 +1,75 @@
/*
* $Id: io.h,v 1.1 1997/03/14 06:22:27 gdr Exp $
*
* prchar
* print character with test for printer -- macro version
*
* profiling has shown that this is where we spend most of our time
* Don't use a case statement here; the macros are out of range
* for some compilers.
*/
#if 0
#define PRCHAR(__c, fp) \
{ \
if (__c == S_STANDOUT) { \
fpGLOB = fp; \
tputs(s_standout,1,tprchar); \
} else if (__c == E_STANDOUT) { \
fpGLOB = fp; \
tputs(e_standout,1,tprchar); \
} else if (__c == S_BOLD) { \
fpGLOB = fp; \
tputs(s_bold,1,tprchar); \
} else if (__c == E_BOLD) { \
fpGLOB = fp; \
tputs(e_bold,1,tprchar); \
} else if (__c == S_ITALIC) { \
fpGLOB = fp; \
tputs(s_italic,1,tprchar); \
} else if (__c == E_ITALIC) { \
fpGLOB = fp; \
tputs(e_italic,1,tprchar); \
} else if (__c == 13) { \
; \
} else { \
putc(c, fp); \
} \
}
#else
#define PRCHAR(c, fp) \
{ \
__i = c; \
switch(__i) { \
case S_STANDOUT: __s = s_standout; break; \
case E_STANDOUT: __s = e_standout; break; \
case S_BOLD: __s = s_bold; break; \
case E_BOLD: __s = e_bold; break; \
case S_ITALIC: __s = s_italic; break; \
case E_ITALIC: __s = e_italic; break; \
case 13: __s = (char *)0x01L; break; \
default: __s = NULL; \
} \
switch((unsigned long)__s) { \
case 0L: putc(c, fp); break; \
case 1L: ; break; \
default: fpGLOB = fp; tputs(__s, 1, tprchar); \
} \
}
#define PRCHAR2(c,fp) putc(c,fp)
extern char __i;
extern char *__s;
extern FILE *fpGLOB;
int getlin (char *p, FILE *in_buf);
void pbstr (char *str);
void put (char *p);
void putlin (char *p, FILE *pbuf);
int tprchar(char c);
#endif

928
usr.bin/nroff/low.c Normal file
View File

@ -0,0 +1,928 @@
/*
* low.c - misc low-level functions for nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: low.c,v 1.1 1997/03/14 06:22:27 gdr Exp $
*/
#ifdef __ORCAC__
segment "low_______";
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef __GNO__
#include <err.h>
#else
#include "err.h"
#endif
#ifdef sparc
#include "sunos.h"
#endif
#include "nroff.h"
/* convert ascii character to decimal */
#define ATOD(c) (((c) < '0') || ((c) > '9')) ? -1 : ((c) - '0')
#if 0 /* not currently used */
static void inptobu (char *); /* convert input units to b.u. */
static void butochar (char *); /* convert b.u. to char spaces */
#endif
/*
* ctod
*
* convert string to decimal. processes only positive values.
* this takes a constant like "1", "1.0i", etc.
*
* Returns converted value (including zero) on success, zero on failure.
*/
int
ctod (char *p) {
long val;
int d;
char *pp = p;
char *ptmp;
int rside = 0;
int lside = 0;
int has_rside = 0;
int has_lside = 0;
if (*p == EOS) {
return 0;
}
ptmp = skipwd (pp);
pp = --ptmp;
switch (*pp) {
case 'i':
case 'c':
val = 0L;
while (*p != EOS && isdigit (*p)) {
has_lside++;
lside = ATOD(*p);
p++;
if (lside == -1) {
break;
}
val = 10L * val + (long) lside;
}
lside = (int) val;
if (*p == '.') {
p++;
val = 0L;
while (*p != EOS && isdigit (*p)) {
has_rside++;
rside = ATOD(*p);
p++;
if (rside == -1) {
break;
}
val = 10L * val + (long) rside;
if (has_rside > 2) { /* more than enough */
break;
}
}
rside = (int) val;
}
/*
* now put it together. 1.0i -> 240, 1.50i -> 360, etc.
*/
val = 0L;
if (has_lside) {
val = (long) lside * BU_INCH;
}
switch (has_rside) {
case 1:
val = val + ((long) rside * BU_INCH / 10L);
break;
case 2:
val = val + ((long) rside * BU_INCH / 100L);
break;
case 3:
val = val + ((long) rside * BU_INCH / 1000L);
break;
default:
break;
}
if (*pp == 'c') {
val = (val * BU_CM) / BU_INCH;
}
/*
* for now we convert to basic char size, 1 em...
*/
val = val / BU_EM;
break;
case 'P':
case 'm':
case 'n':
case 'p':
case 'u':
case 'v':
val = 0L;
while (*p != EOS) {
d = ATOD(*p);
p++;
if (d == -1)
break;
val = 10L * val + (long) d;
}
switch (*pp) {
case 'P':
val = val * BU_PICA;
break;
case 'p':
val = val * BU_POINT;
break;
case 'u':
val = val * BU_BU;
break;
case 'm':
val = val * BU_EM;
break;
case 'n':
val = val * BU_EN;
break;
case 'v':
val = val * BU_EM;
break;
}
/*
* for now we convert to basic char size, 1 em...
*/
val = val / BU_EM;
break;
default:
/*
* this is the default behavior. it SHOULD make things
* compatible with the old way...
*/
val = 0L;
while (*p != EOS) {
d = ATOD(*p);
p++;
if (d == -1) {
break;
}
val = 10L * val + (long) d;
}
break;
}
return (int) val;
}
#if 0 /* not currently used */
/*
* inptobu
*
* convert input units to b.u.
*/
static void
inptobu (char *ps)
{
return;
}
/*
* butochar
*
* convert b.u. to char spaces
*/
static void
butochar (char *ps)
{
return;
}
#endif /* 0 */
/*
* skipbl
*
* skip blanks and tabs in character buffer. return ptr to first
* non-space or non-tab char. this could mean EOS or \r or \n.
*/
char *
skipbl (register char *p)
{
while ((*p != EOS) && (*p == ' ' || *p == '\t')) {
p++;
}
return (p);
}
/*
* skipwd
*
* skip over word and punctuation. anything but space,\t,\r,\n, and EOS
* is skipped. return ptr to the first of these found.
*/
char *
skipwd (register char *p) {
while (*p != EOS && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n') {
p++;
}
return (p);
}
/*
* nroffSpace
*
* space vertically n lines. this does header and footer also.
*/
void
nroffSpace (int n) {
robrk ();
if (pg.lineno > pg.bottom) {
return;
}
if (pg.lineno == 0) {
phead ();
}
skip (MIN(n, pg.bottom + 1 - pg.lineno));
pg.lineno += n;
set_ireg ("ln", pg.lineno, 0);
if (pg.lineno > pg.bottom) {
pfoot ();
}
}
/*
* getfield
* get field from title
*/
char *
getfield (register char *p, register char *q, char delim) {
while (*p != delim && *p != '\r' && *p != '\n' && *p != EOS) {
*q++ = *p++;
}
*q = EOS;
if (*p == delim) {
++p;
}
return p;
}
/*
* getwrd
*
* get non-blank word from p0 into p1.
* return number of characters processed.
*/
int
getwrd (register char *src, register char *dest) {
#if 0 /* gdr changes */
char *orgsrc, *orgdest;
orgsrc = src;
orgdest = dest;
/*
* skip leading whitespace
*/
while (*src == ' ' || *src == '\t') {
src++;
}
/* find end of word */
while (*src != '\0' && !isspace(*src)) {
*dest++ = *src++;
}
/* I don't understand what this is supposed to achieve */
#ifdef WHATTHEFUCK
assert (dest - orgdest >= 1); /* gdr */
c = *(dest - 1);
if (c == '"') {
asssert(dest - orgdest >= 2); /* gdr */
c = *(dest - 2);
}
if (c == '?' || c == '!') {
*dest++ = ' ';
}
if (c == '.' && (*src == '\n' || *src == '\r' || islower (*p))) {
*dest++ = ' ';
}
#endif /* WHATTHEFUCK */
*dest = EOS;
return src - orgsrc;
#elif 1
char c;
register int i;
register char *p;
char *orgsrc, *orgdest;
orgsrc = src;
orgdest = dest;
/*
* init counter...
*/
i = 0;
/*
* skip leading whitespace
*/
while (*src == ' ' || *src == '\t') {
++i;
++src;
}
/*
* set ptr and start to look for end of word
*/
p = src;
while (*src != ' ' && *src != EOS && *src != '\t') {
if (*src == '\n' || *src == '\r') {
break;
}
*dest = *src++;
++dest;
++i;
}
if (dest > orgdest) {
c = *(dest - 1);
if (c == '"' && (dest > orgdest + 1)) {
c = *(dest - 2);
}
if (c == '?' || c == '!') {
*dest++ = ' ';
++i;
}
if (c == '.' && (*src == '\n' || *src == '\r' || islower (*p))) {
*dest++ = ' ';
++i;
}
}
*dest = EOS;
return (i);
#else
char c;
register int i;
register char *p;
char *orgsrc, *orgdest;
orgsrc = src;
orgdest = dest;
/*
* init counter...
*/
i = 0;
/*
* skip leading whitespace
*/
while (*src == ' ' || *src == '\t') {
++i;
++src;
}
/*
* set ptr and start to look for end of word
*/
p = src;
while (*src != ' ' && *src != EOS && *src != '\t') {
if (*src == '\n' || *src == '\r') {
break;
}
*dest = *src++;
++dest;
++i;
}
if (dest > orgdest) {
c = *(dest - 1);
if (c == '"') {
ASSERT(dest > orgdest + 1,
("%s:%d: array indexing error", __FILE__, __LINE__));
c = *(dest - 2);
}
if (c == '?' || c == '!') {
*dest++ = ' ';
++i;
}
if (c == '.' && (*src == '\n' || *src == '\r' || islower (*p))) {
*dest++ = ' ';
++i;
}
}
*dest = EOS;
return (i);
#endif
}
/*
* countesc
* count atari escape sequence characters in given null-terminated
* string
*/
#define ESC 27
int
countesc (register char *p) {
register char *pp;
register int num;
pp = p;
num = 0;
while (*pp != EOS) {
if (*pp == ESC) {
/*
* count escape char (atari-specific, vt52)
* generally only p,q,b,and c will show up...
*/
switch (*(pp+1)) {
case 'A': /* ESC-a */
case 'B':
case 'C':
case 'D':
case 'E':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'd':
case 'e':
case 'f':
case 'j':
case 'k':
case 'l':
case 'o':
case 'p':
case 'q':
case 'v':
case 'w':
num += 2;
break;
case 'b': /* ESC-a-b */
case 'c':
num += 3;
break;
case 'Y': /* ESC-a-b-c */
case '[': /* Esc [ 7 m */
num += 4;
break;
default:
num += 1;
break;
}
}
pp++;
}
return num;
}
/*
* itoda
* convert integer to decimal ascii string
*
* Pre: <value> is the number to convert
* <p> is the output buffer
* <size> is the number of bytes in the output buffer
*
* Post: <p> contains an ascii representation of <value>
*
* Returns:
*/
int
itoda (int value, register char *p, register int size) {
#if 0
int len;
/*
* buffer must be big enough for representation of largest integer,
* plus 1 byte for sign, plus 1 byte for terminator. On a 32-bit
* machine this is 10+1+1 == 12 bytes.
*/
#define MAX_INT_LENGTH 15
char buffer[MAX_INT_LENGTH];
len = sprintf(buffer, "%d", value);
if (len == EOF) {
errx(1, "itoda failed with EOF");
}
if (len >= size) {
errx(1, "%s:%d: buffer overflow", __FILE__, __LINE__);
}
strncpy(p, buffer, len);
return len;
#else
int i, j, aval;
char c[20];
aval = abs (value);
c[0] = EOS;
i = 1;
do {
c[i++] = (aval % 10) + '0';
aval /= 10;
} while (aval > 0 && i <= size);
if (value < 0 && i <= size) {
c[i++] = '-';
}
for (j = 0; j < i; ++j) {
*p++ = c[i - j - 1];
}
return i;
#endif
}
/*
* itoROMAN
* convert integer to upper roman. must be positive
*/
int
itoROMAN (int value, register char *p, register int size) {
register int i;
register int j;
register int aval;
char c[100];
int rem;
aval = abs (value);
c[0] = EOS;
i = 1;
/*
* trivial case:
*/
if (aval == 0) {
c[i++] = '0';
goto done_100;
}
/*
* temporarily mod 100...
*/
aval = aval % 100;
if (aval > 0) {
/*
* build backward
*
* | I| 1
* | II| 2
* | III| 3
* | VI| 4
* | V| 5
* | IV| 6
* | IIV| 7
* | IIIV| 8
* | XI| 9
* | X| 0
* | IX| 11
* | IIX| 12
*/
if ((aval % 5 == 0) && (aval % 10 != 0)) { /* 5 */
c[i++] = 'V';
} else {
rem = aval % 10;
if (rem == 9) { /* 9 */
c[i++] = 'X';
c[i++] = 'I';
}else if (rem == 8) { /* 8 */
c[i++] = 'I';
c[i++] = 'I';
c[i++] = 'I';
c[i++] = 'V';
} else if (rem == 7) { /* 7 */
c[i++] = 'I';
c[i++] = 'I';
c[i++] = 'V';
} else if (rem == 6) { /* 6 */
c[i++] = 'I';
c[i++] = 'V';
} else if (rem == 4) { /* 4 */
c[i++] = 'V';
c[i++] = 'I';
} else { /* 3,2,1 */
for (j = 0; j < rem; j++) {
c[i++] = 'I';
}
}
}
aval /= 10;
if (aval == 0) {
goto done_100;
}
rem = aval % 10;
if (rem == 4) {
c[i++] = 'L';
c[i++] = 'X';
} else if (rem == 5) {
c[i++] = 'L';
} else if (rem < 4) {
for (j = 0; j < rem; j++) {
c[i++] = 'X';
}
} else {
for (j = 0; j < rem - 5; j++) {
c[i++] = 'X';
}
c[i++] = 'L';
}
}
done_100:
/*
* divide by 100 (they are done) and temp mod by another 10
*/
aval = abs (value);
aval /= 100;
if (aval > 0) {
rem = aval % 10;
if (rem == 4) {
c[i++] = 'D';
c[i++] = 'C';
}
if (rem == 5) {
c[i++] = 'D';
} else if (rem < 4) {
for (j = 0; j < rem; j++) {
c[i++] = 'C';
}
} else if (rem == 9) {
c[i++] = 'M';
c[i++] = 'C';
} else if (rem < 9) {
for (j = 0; j < rem - 5; j++) {
c[i++] = 'C';
}
c[i++] = 'D';
}
}
aval /= 10;
if (aval > 0) {
rem = aval % 10;
if (rem < 4) {
for (j = 0; j < rem; j++) {
c[i++] = 'M';
}
}
}
if (value < 0) {
c[i++] = '-';
}
for (j = 0; j < i; ++j) {
*p++ = c[i - j - 1];
}
return i;
}
/*
* itoroman
* convert integer to lower roman
*/
int
itoroman (int value, char *p, int size)
{
register int i;
register int len;
char c[100];
c[0] = EOS;
len = itoROMAN (value, c, size);
for (i = 0; i < len; i++) {
p[i] = c[i];
if (isalpha (p[i])) {
p[i] = tolower (c[i]);
}
}
return len;
}
/*
* itoLETTER
* convert integer to upper letter value: 0,A,B,C,...,AA,AB,AC,...
*/
int
itoLETTER (int value, register char *p, register int size) {
register int i;
register int j;
register int aval;
char c[20];
aval = abs (value);
c[0] = EOS;
i = 1;
/*
* 1 based:
*
* 0 0
* 1 A
* 25 Z
* 26 AA
* 51 AZ
* 52 AAA
* ...
*/
if (aval == 0) {
c[i++] = '0';
} else if (aval < 27) {
c[i++] = aval - 1 + 'A';
} else {
do {
c[i++] = ((aval - 1) % 26) + 'A';
aval = (aval - 1) / 26;
} while (aval > 0 && i <= size);
}
if (value < 0 && i <= size) {
c[i++] = '-';
}
for (j = 0; j < i; ++j) {
*p++ = c[i - j - 1];
}
return i;
}
/*
* itoletter
* convert integer to upper letter value: 0,a,b,c,...,aa,ab,ac,...
*/
int
itoletter (int value, register char *p, register int size) {
register int i;
register int j;
register int aval;
char c[20];
aval = abs (value);
c[0] = EOS;
i = 1;
/*
* 1 based:
*
* 0 0
* 1 A
* 25 Z
* 26 AA
* 51 AZ
* 52 AAA
* ...
*/
if (aval == 0) {
c[i++] = '0';
} else if (aval < 27) {
c[i++] = aval - 1 + 'a';
} else {
do {
c[i++] = ((aval - 1) % 26) + 'a';
aval = (aval - 1) / 26;
} while (aval > 0 && i <= size);
}
if (value < 0 && i <= size) {
c[i++] = '-';
}
for (j = 0; j < i; ++j) {
*p++ = c[i - j - 1];
}
return i;
}
#if 0 /* min, max not needed */
/*
* min
* find minimum of two integer ONLY
*/
#ifdef min
#undef min
#endif
int
min (register int v1, register int v2) {
return ((v1 < v2) ? v1 : v2);
}
/*
* max
* find maximum of two integers ONLY
*/
#ifdef max
#undef max
#endif
int
max (register int v1, register int v2) {
return ((v1 > v2) ? v1 : v2);
}
#endif /* 0 */
/*
* err_exit
* exit cleanly on fatal error (close files, etc). also handles normal
* exit.
*/
void
err_exit (int code) {
if (err_stream != stderr && err_stream != (FILE *) 0) {
/*
* not going to stderr (-o file)
*/
fflush (err_stream);
fclose (err_stream);
}
if (debugging && dbg_stream != stderr && dbg_stream != (FILE *) 0) {
fflush (dbg_stream);
fclose (dbg_stream);
}
if (out_stream != stdout && out_stream != (FILE *) 0) {
/*
* not going to stdout (-l)
*/
fflush (out_stream);
fclose (out_stream);
}
#ifdef GEMDOS
if (hold_screen) {
wait_for_char();
}
#endif
exit(code);
}
#ifdef GEMDOS
#include <osbind.h>
/*
* Wait for a character
*/
void
wait_for_char (void) {
printf ("enter any key..."); fflush (stdout);
Cconin ();
}
#endif

692
usr.bin/nroff/macros.c Normal file
View File

@ -0,0 +1,692 @@
/*
* macros.c - macro input/output processing for nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: macros.c,v 1.1 1997/03/14 06:22:27 gdr Exp $
*/
#ifdef __ORCAC__
segment "macros____";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "err.h"
#ifdef sparc
#include "sunos.h"
#endif
#include "nroff.h"
#include "macros.h"
#include "io.h"
static int colmac (char *p, char *d, int i);
static int putmac (char *name, char *p);
void
initMacros (void) {
memset(mac.mnames, 0, MXMDEF * sizeof(char*));
memset(mac.mb, 0, MACBUF);
memset(mac.pbb, 0, MAXLINE);
#if 0
for (i = 0; i < MXMDEF; ++i) {
mac.mnames[i] = NULL_CPTR;
}
for (i = 0; i < MACBUF; ++i) {
mac.mb[i] = EOS;
}
for (i = 0; i < MAXPBB; ++i) {
mac.pbb[i] = EOS;
}
#endif
mac.lastp = 0;
mac.emb = &mac.mb[0];
mac.ppb = NULL_CPTR;
}
/*
* defmac
*
* Define a macro. top level, read from stream.
*
* we should read macro without interpretation EXCEPT:
*
* 1) number registers are interpolated
* 2) strings indicated by \* are interpolated
* 3) arguments indicated by \$ are interpolated
* 4) concealed newlines indicated by \(newline) are eliminated
* 5) comments indicated by \" are eliminated
* 6) \t and \a are interpreted as ASCII h tab and SOH.
* 7) \\ is interpreted as backslash and \. is interpreted as a period.
*
* currently, we do only 3. a good place to do it would be here before
* putmac, after colmac...
*/
void
defmac (char *line, FILE *infp)
{
register char *q;
register int i;
char name[MNLEN];
char defn[MXMLEN];
char newend[10];
#ifdef BORK
fprintf(stderr, "DEBUG: defmac: \"%s\"\n", line);
#endif
/*
* terminate defn; if it's still this way when we're ready to putmac(),
* then the macro definition was empty and we're going to ignore it.
*/
defn[0] = '\0';
/*
* skip the .de and get to the name...
*/
q = skipwd (line);
q = skipbl (q);
/*
* q now points to the name. Copy it into the "name" buffer.
* Make sure it is valid (i.e. first char is alpha...). The
* getwrd function returns the length of the word.
*/
i = getwrd (q, name);
if (!isprint (*name)) {
errx(-1, "missing or illegal macro definition name");
}
/*
* truncate to 2 char max name.
*/
if (i > 2) {
name[2] = EOS;
}
/*
* skip the name and see if we have a new end defined...
*/
q = skipwd (line);
q = skipbl (q);
for (i = 0; i < 10; i++) {
newend[i] = EOS;
}
for (i = 0; (i < 10) && ( isalpha (q[i]) || isdigit (q[i]) ); i++) {
newend[i] = q[i];
}
/*
* read a line from input stream until we get the end of macro
* command (.en or ..). actually. we should have read the next
* field just above here to get the .de NA . or .de NA en string
* to be new end of macro.
*/
i = 0;
while (getlin (line, infp) != EOF) {
#ifdef BORK
fprintf(stderr,"DEBUG: %s:%d line is \"%s\"\n", __FILE__, __LINE__,
line);
#endif
if (line[0] == dc.cmdchr && line[1] == '\\' && line[2] == '\"') {
/*
* comment, ignore it
*/
continue;
}
if (line[0] == dc.cmdchr && newend[0] != EOS
&& line[1] == newend[0] && line[2] == newend[1]) {
/*
* replacement end found
*/
break;
}
if (line[0] == dc.cmdchr && line[1] == 'e' && line[2] == 'n') {
/*
* .en found
*/
break;
}
if (line[0] == dc.cmdchr && line[1] == dc.cmdchr) {
/*
* .. found
*/
#ifdef BORK
fprintf(stderr,"DEBUG: %s:%d: dot-dot found\n",__FILE__,__LINE__);
#endif
break;
}
/*
* collect macro from the line we just read. all this does
* is put it in the string defn.
*/
#ifdef BORK
fprintf(stderr,"DEBUG: %s:%d: collecting macro\n",__FILE__,__LINE__);
#endif
if ((i = colmac (line, defn, i)) == ERR) {
errx(1, "macro definition too long");
}
}
/*
* store the macro
*/
if (!ignoring && defn[0] != '\0') {
if (putmac (name, defn) == ERR) {
errx(-1, "macro definition table full");
}
}
}
/*
* colmac
*
* Collect macro definition from input stream
*/
static int
colmac (char *p, char *d, int i) {
char *pstart;
int istart;
pstart = p;
istart = i;
while (*p != EOS) {
/*
* are we over the length limit for a single macro?
*/
if (i >= MXMLEN - 1) {
d[i - 1] = EOS;
return (ERR);
}
/*
* "i break for comments..."
*/
if (*p == '\\' && *(p+1) == '\"') {
/*
* first back over any whitespace between comment
* start and last character in line. remember to
* decrement counter i, too...
*/
p--;
while (isspace (*p) && p > pstart && i > istart) {
p--;
i--;
}
/*
* now skip over the comment until we reach the
* trailing newline
*/
while (*p != EOS) {
if (*p == '\n' || *p == '\r') {
break;
}
p++;
}
}
/*
* skip quoted things
*/
if (*p == '\\' && *(p+1) == '\\') {
p++;
}
/*
* copy it
*/
d[i++] = *p++;
}
d[i] = EOS;
return (i);
}
/*
* putmac
*
* Put macro definition into table
*
* NOTE: any expansions of things like number registers SHOULD
* have been done already.
*/
static int
putmac (char *name, char *p) {
/*
* any room left? (did we exceed max number of possible macros)
*/
if (mac.lastp >= MXMDEF) {
return (ERR);
}
/*
* will new one fit in big buffer?
*/
#ifdef DEBUG
strlen(name);
strlen(p);
#endif
if (mac.emb + strlen (name) + strlen (p) + 1 > &mac.mb[MACBUF]) {
return (ERR);
}
/*
* add it...
*
* bump counter, set ptr to name, copy name, copy def.
* finally increment end of macro buffer ptr (emb).
*
* macro looks like this in mb:
*
* mac.mb[MACBUF] size of total buf
* lastp < MXMDEF number of macros possible
* *mnames[MXMDEF] -> names, each max length
* ..._____________________________...____________________...
* / / /|X|X|0|macro definition |0| / / / / / / /
* .../_/_/_|_|_|_|________________...___|_|/_/_/_/_/_/_/_...
* ^
* |
* \----- mac.mnames[mac.lastp] points here
*
* both the 2 char name (XX) and the descripton are null term and
* follow one after the other.
*/
++mac.lastp;
mac.mnames[mac.lastp] = mac.emb;
strcpy (mac.emb, name);
strcpy (mac.emb + strlen (name) + 1, p);
mac.emb += strlen (name) + strlen (p) + 2;
return (OK);
}
/*
* getmac
*
* Get (lookup) macro definition from namespace
*/
char *
getmac (char *name) {
int i;
/*
* loop for all macros, starting with last one
*/
for (i = mac.lastp; i >= 0; --i) {
/*
* is this REALLY a macro?
*/
if (mac.mnames[i]) {
/*
* if it compares, return a ptr to it
*/
if (!strcmp (name, mac.mnames[i])) {
#if 0 /* !!!debug */
puts (mac.mnames[i]);
#endif
if (mac.mnames[i][1] == EOS) {
return (mac.mnames[i] + 2);
} else {
return (mac.mnames[i] + 3);
}
/*NOTREACHED*/
}
}
}
/*
* none found, return null
*/
return (NULL_CPTR);
}
/*
* maceval
*
* Evaluate macro expansion from p into m
*/
void
maceval (char *p, char *m) {
register int i;
char *argp[15];
char c;
int xc;
/*
* replace command char with EOS
*/
*p++ = EOS;
/*
* initialize argp array to substitute command
* string for any undefined argument
*
* NO!!! this is fixed...
*/
#if 0
for (i = 0; i < 10; ++i) {
argp[i] = p;
}
#endif
/*
* skip the command name
*/
p = skipwd (p);
*p++ = EOS;
/*
* loop for all $n variables...
*/
for (i = 0; i < 10; ++i) {
/*
* get to substituted param and if no more, reset remaining
* args to NULL and stop. using "i" here IS ok...
*/
p = skipbl (p);
if (*p == '\r' || *p == '\n' || *p == EOS) {
DEBUGGING(("maceval: set_ireg(.$, %d, 0)", i));
set_ireg (".$", i, 0);
for ( ; i < 10; i++) {
argp[i] = NULL_CPTR;
}
break;
}
/*
* ...otherwise, see if this param is quoted. if it is,
* it is all one parameter, even with blanks (but not
* newlines...). look for another "c" (which is the quote).
*
* if no quote, just read the arg as a single word and null
* terminate it.
*/
if (*p == '\'' || *p == '"') {
c = *p++;
argp[i] = p;
while (*p != c && *p != '\r' && *p != '\n' && *p != EOS) {
++p;
}
*p++ = EOS;
} else {
argp[i] = p;
p = skipwd (p);
*p++ = EOS;
}
}
/*
* m contains text of the macro. p contained the input line.
* here we start at the end of the macro def and see if there
* are any $n thingies. go backwards.
*/
for (i = strlen (m) - 1; i >= 0; --i) {
/*
* found a $.
*/
if (i > 0 && m[i - 1] == '$') {
if (!isdigit (m[i])) {
/*
* it wasn't a numeric replacement arg so
* push this char back onto input stream
*/
PUTBAK(m[i]);
} else {
/*
* it WAS a numeric replacement arg. so we
* want to push back the appropriate macro
* invocation arg. m[i]-'0' is the numerical
* value of the $1 thru $9. if the arg is
* not there, argp[n] will be (char *) 0
* and pbstr will do nothing.
*/
xc = m[i] - '1';
if (argp[xc]) {
pbstr (argp[xc]);
}
--i;
}
} else {
/*
* no $ so push back the char...
*/
PUTBAK(m[i]);
}
}
/*
* at this point, the iobuf will hold the new macro command, full
* expanded for $n things. the return gets us right back to the
* main loop in main() and we parse the (new) command just as if
* it were read from a file.
*/
}
/*
* printmac
* print macro data:
* opt print
* === =====
* 0 name and size
* 1 total size
* 2 full information
*/
void
printmac (int opt) {
register int i; /* was long, minix needs int */
register long localSpace;
register long totalspace;
register char *pname;
register char *pdef;
localSpace = 0L;
totalspace = 0L;
fflush (out_stream);
fflush (err_stream);
for (i = mac.lastp; i >= 0; --i) {
/*
* is this REALLY a macro?
*/
if (mac.mnames[i]) {
pname = (char *) (mac.mnames[i]);
pdef = pname + 3;
if (*(pname + 1) == '\0') {
pdef = pname + 2;
}
localSpace = (long) strlen (pdef);
totalspace += localSpace;
switch (opt) {
case 0:
fprintf (err_stream, "%s %ld\n", pname, localSpace);
break;
case 2:
fprintf (err_stream, "%s %ld\n", pname, localSpace);
fprintf (err_stream, "%s\n", pdef);
break;
case 1:
default:
break;
}
}
}
fprintf (err_stream, "Total space: %ld\n", totalspace);
}
/*
* putstr
*
* Put string definition into (macro) table
*
* NOTE: any expansions of things like number registers SHOULD
* have been done already. strings and macros share mb buffer
*/
int
putstr (const char *name, const char *p) {
/*
* any room left? (did we exceed max number of possible macros)
*/
if (mac.lastp >= MXMDEF) {
return (ERR);
}
/*
* will new one fit in big buffer?
*/
if (mac.emb + strlen (name) + strlen (p) + 1 > &mac.mb[MACBUF]) {
return (ERR);
}
/*
* add it...
*
* bump counter, set ptr to name, copy name, copy def.
* finally increment end of macro buffer ptr (emb).
*
* string looks like this in mb:
*
* mac.mb[MACBUF] size of total buf
* lastp < MXMDEF number of macros/strings possible
* *mnames[MXMDEF] -> names, each max length
* ...______________________________...____________________...
* / / /|X|X|0|string definition |0| / / / / / / /
* .../_/_/_|_|_|_|_________________...___|_|/_/_/_/_/_/_/_...
* ^
* |
* \----- mac.mnames[mac.lastp] points here
*
* both the 2 char name (XX) and the descripton are null term and
* follow one after the other.
*/
++mac.lastp;
mac.mnames[mac.lastp] = mac.emb;
strcpy (mac.emb, name);
strcpy (mac.emb + strlen (name) + 1, p);
mac.emb += strlen (name) + strlen (p) + 2;
return (OK);
}
/*
* getstr
* Get (lookup) string definition from namespace
*/
char *
getstr (char *name) {
int i;
/*
* loop for all macros, starting with last one
*/
for (i = mac.lastp; i >= 0; --i) {
/*
* is this REALLY a macro?
*/
if (mac.mnames[i]) {
/*
* if it compares, return a ptr to it
*/
if (!strcmp (name, mac.mnames[i])) {
#if 0 /* !!!debug */
puts (mac.mnames[i]);
#endif
if (mac.mnames[i][1] == EOS) {
return (mac.mnames[i] + 2);
} else {
return (mac.mnames[i] + 3);
}
}
}
}
/*
* none found, return null
*/
return NULL;
}
#ifdef NOT_USED
/*
* putbak
*
* Push character back into input stream. we use the push-back buffer
* stored with macros.
*/
void
putbak (char c)
{
if (mac.ppb == NULL) { /* first time executing this code */
mac.ppb = mac.pbb;
*mac.ppb = c;
} else if (mac.ppb < mac.pbb + MAXPBB) {
mac.ppb++;
*(mac.ppb) = c;
} else {
errx(-1, "push back buffer overflow (%d chars)", MAXPBB);
}
}
/*
* ngetc
* get a character from the putback buffer or from <infp>
*/
int ngetc (FILE *infp)
{
register int c;
if (mac.ppb >= mac.pbb) {
c = *mac.ppb--;
} else {
c = getc (infp);
}
return (c);
}
#endif /* NOT_USED */

43
usr.bin/nroff/macros.h Normal file
View File

@ -0,0 +1,43 @@
/*
* $Id: macros.h,v 1.1 1997/03/14 06:22:27 gdr Exp $
*
* PUTBAK
*
* Push character back into input stream. we use the push-back buffer
* stored with macros.
*/
#define PUTBAK(c) \
{ \
if (mac.ppb == NULL) { /* first time executing this code */ \
mac.ppb = mac.pbb; \
*mac.ppb = c; \
} else if (mac.ppb < mac.pbb + MAXPBB) { \
mac.ppb++; \
*(mac.ppb) = c; \
} else { \
errx(-1, "push back buffer overflow (%d chars)", MAXPBB); \
} \
}
/* NGETC -- get character from input file or push back buffer */
#define NGETC(infp) ((mac.ppb >= mac.pbb) ? *mac.ppb-- : getc(infp))
typedef struct macros_t {
char *mnames[MXMDEF]; /* table of ptrs to macro names */
int lastp; /* index to last mname */
char *emb; /* next char avail in macro defn buf */
char mb[MACBUF]; /* table of macro definitions */
char *ppb; /* pointer into push back buffer */
char pbb[MAXPBB]; /* push back buffer */
} macros_t;
extern macros_t mac;
void initMacros (void);
void defmac (char *line, FILE *infp);
char *getmac (char *name);
void maceval (char *p, char *m);
void printmac (int opt);
int putstr (const char *name, const char *p);
char *getstr (char *name);

100
usr.bin/nroff/makefile.mk Normal file
View File

@ -0,0 +1,100 @@
#
# Makefile for nroff(1).
#
# $Id: makefile.mk,v 1.1 1997/03/14 06:22:28 gdr Exp $
#
IIGS = FALSE # TRUE or FALSE
USE_INSIGHT = FALSE # TRUE or FALSE
BINDIR = /usr/bin
TMACDIR = /usr/lib/tmac
MANDIR = /usr/man
#
###### end of configuration
#
PROFILE = # -pg
.IF $(IIGS) == TRUE
DEFINES =
OPTIMIZE =
LDLIBS =
.ELIF $(USE_INSIGHT) == TRUE
CC = insight
DEFINES =
OPTIMIZE = -g
LDLIBS = int.tqs -ltermcap
.ELSE
CC = gcc
DEFINES = # -DDEBUG
OPTIMIZE = $(PROFILE) -g
LDLIBS = $(PROFILE) -ltermcap
.END
.IF $(IIGS) == TRUE
UX_SRC =
UX_OBJ =
.ELSE
UX_SRC = err.c
UX_OBJ = err.o
.END
GCC_PARANOIA = \
-Wstrict-prototypes \
-Wmissing-prototypes \
-Waggregate-return \
-Wnested-externs \
-fno-asm -fno-builtin -fno-inline
.IF $(CC) == gcc
GCC_FLAGS = -Wall -funsigned-char $(GCC_PARANOIA)
.ELSE
GCC_FLAGS =
.END
CFLAGS = $(OPTIMIZE) $(GCC_FLAGS) $(DEFINES)
SUNOS_H = sunos.h
OBJS = main.o command.o escape.o io.o low.o macros.o strings.o \
text.o $(UX_OBJ)
SRCS = main.c command.c escape.c io.c low.c macros.c strings.c \
text.c $(UX_SRC)
default: nroff
nroff: $(OBJS)
$(CC) -o $@ $(LDFLAGS) $(OBJS) $(LDLIBS)
clobber:
$(RM) -f nroff $(OBJS)
# $(RM) -f nroff $(OBJS) *~ core tca.* *.tqs insight.log
dep:
gcc -MM $(CFLAGS) *.c > depend
callchart:
cflow $(SRCS) > $@
install:
$(INSTALL) -d $(BINDIR) $(TMACDIR) $(MANDIR)/man1 $(MANDIR)/man7
$(INSTALL) -m755 nroff $(BINDIR)
$(INSTALL) -m644 tmac.an $(TMACDIR)
$(INSTALL) -m644 tmac.s $(TMACDIR)
$(INSTALL) -m644 nroff.1 $(TMACDIR)/man1
$(INSTALL) -m644 man.7 $(TMACDIR)/man7
$(INSTALL) -m644 ms.7 $(TMACDIR)/man7
#
# additional dependancies
#
command.o:: $(SUNOS_H) nroff.h config.h
escape.o:: $(SUNOS_H) nroff.h config.h
io.o:: $(SUNOS_H) nroff.h config.h macros.h io.h
low.o:: $(SUNOS_H) nroff.h config.h
macros.o:: $(SUNOS_H) nroff.h config.h macros.h
main.o:: $(SUNOS_H) nroff.h config.h macros.h
strings.o:: $(SUNOS_H) nroff.h config.h
text.o:: $(SUNOS_H) nroff.h config.h io.h

248
usr.bin/nroff/man.7 Normal file
View File

@ -0,0 +1,248 @@
.\" man(7) manpage by rosenkra@convex.com (Bill Rosenkranz, 7/22/90)
.\"
.TH MAN 7
.SH NAME
man - nroff macro package for manual pages
.SH SYNOPSIS
nroff -man file ...
.SH DESCRIPTION
These macros are used to lay out reference pages for manuals.
.PP
Any text argument
t
may be zero to six words.
Quotes may be used to include blanks in a 'word'.
Text
can be empty, but unlike normal Unix macros, the next line is not used.
.PP
A prevailing indent distance is remembered between successive
indented paragraphs, and is reset to default value upon
reaching a non-indented paragraph (i.e. at .SH or .SS).
In contrast with normal Unix procedure, all indents (tabs) are 8 spaces
instead of 5.
This can be changed by modifying tmac.an.
.SH FILES
.ec |
\lib\tmac\tmac.an the macro library
.ec \
.SH SEE ALSO
nroff(1), man(1)
.SH "REQUEST SUMMARY"
.nf
.cc +
Request Cause Explanation
Break?
.B t no Text t is bold. Quote to imbed blanks.
.I t no Text t is italic. Quote to imbed blanks.
.IP x yes Set prevailing indent to 8. Begin
indented paragraph with hanging tag
given by first argument. Tag x is
always placed on a separate line.
.LP yes Same as .PP.
.PP yes Begin paragraph. Set prevailing
indent to 8.
.RE yes End of relative indent. Set prevailing
indent to amount of starting .RS.
.RP x yes Like .IP, but use relative indent. Must
end the section with .RE.
.RS yes Start relative indent, move left margin
in distance 8.
.SH t yes Subhead. Quote to imbed blanks.
.SS t yes Subsection. Quote to imbed blanks. No
indent for t.
.TH n s c v d yes Begin page named n of chapter s; c is
the chapter name; d is the date of the
most recent change; v is version number.
Sets prevailing indent and tabs to 8.
+cc .
.fi
.ne 8
.SH EXAMPLE
The following illustrates some of the requests available
with this macro package:
.RS
.nf
.cc +
.\\\|" this is a comment
.TH DEMO 1 "Commands Manual" "Version 1.0" "\\\|*\|(DA"
.SH NAME
demo - show how to use -man package \\\|" this is a comment
.SH SYNOPSIS
demo [options] file [...]
.SH DESCRIPTION
This is a test for showing how to use the
.I nroff(1)
man package.
It shows how to use .TH, .SH, .PP, .I, and .IP commands.
.PP
This will be a new paragraph.
You can also use normal
.I nroff(1)
commands in the text.
.SS NROFF COMMANDS:
.IP '\\\\\|"'
This is the comment command.
Note how you have to quote this sucker!
You'll probably never have to write an
.I nroff(1)
manpage, so don't worry about it.
.IP nf
No fill mode (the normal mode is fill mode where things
get justified right and left).
.IP fi
Re-enter fill mode.
.IP br
Break line here no matter what.
.IP sp
Vertical space (also causes a break to occur).
.sp
Note that to continue an indent and make a new paragraph (as
is the case here), just put in a space (.sp).
.PP
Now we should be at a new paragraph.
+cc .
.fi
.RE
.ne 8
Executing 'nroff -man demo.man' results in the following output:
.RS
.nf
.cc +
DEMO (1) Commands Manual DEMO (1)
NAME
demo - show how to use -man package
SYNOPSIS
demo [options] file [...]
DESCRIPTION
This is a test for showing how to use the nroff(1)
man package. It shows how to use .TH, .SH, .PP, .I,
and .IP commands.
This will be a new paragraph. You can also use normal
nroff(1) commands in the text.
NROFF COMMANDS:
\\\|"
This is the comment command. Note how you have to
quote this sucker! You'll probably never have to
write an nroff(1) manpage, so don't worry about
it.
nf
No fill mode (the normal mode is fill mode where
things get justified right and left).
fi
Re-enter fill mode.
br
Break line here no matter what.
sp
Vertical space (also causes a break to occur).
Note that to continue an indent and make a new
paragraph (as is the case here), just put in a
space (.sp).
Now we should be at a new paragraph.
Version 1.0 23:33:57 2/25/90 1
+cc .
.fi
.RE
.ne 8
.SH CONVENTIONS
A typical manual page for a command or function is laid out as follows:
.sp
.RS
.SS ".TH TITLE [1-8]"
The name of the command or function in upper-case,
which serves as the title of the manual page.
This is followed by the number of the section in which it appears.
.SS ".SH NAME"
name - one-line summary
.PP
The name, or list of names, by which the command is called, followed by
a dash and then a one-line summary of the action performed.
All in roman font, this section contains no troff(1) commands or escapes,
and no macro requests.
It is used to generate the whatis(1) database.
.SS ".SH SYNOPSIS"
Commands:
.sp
.RS
The syntax of the command and its arguments as typed on the command line.
When in boldface, a word must be typed exactly as printed.
When in italics, a word can be replaced with text that you supply.
Syntactic symbols appear in roman face:
.RP "[ ]"
An argument, when surrounded by brackets is optional.
.RE
.RP |
Arguments separated by a vertical bar are exclusive.
You can supply only item from such a list.
.RE
.RP ...
Arguments followed by an elipsis can be repeated.
When an elipsis follows a bracketed set, the expression within the
brackets can be repeated.
.RE
.RE
.sp
Functions:
.sp
.RS
If required, the data declaration, or #include directive, is shown first,
followed by the function declaration.
Otherwise, the function declaration is shown.
.RE
.SS ".SH DESCRIPTION"
A narrative description of the command or function in detail, including
how it interacts with files or data, and how it handles the standard
input, standard output and standard error.
.PP
Filenames, and references to commands or functions described elswhere
in the manual, are italicised.
The names of options, variables and other literal terms are
in boldface.
.SS ".SH OPTIONS"
The list of options along with a description of how each affects the
commands operation.
.SS ".SH FILES"
A list of files associated with the command or function.
.SS '.SH "SEE ALSO"'
A comma-separated list of related manual pages, followed by references
to other published materials.
This section contains no troff(1) escapes or commands, and no macro requests.
.SS ".SH DIAGNOSTICS"
A list of diagnostic messages and an explanation of each.
.SS ".SH NOTES"
Any additional notes such as installation-dependent functionality.
.SS ".SH BUGS"
A description of limitations, known defects, and possible problems
associated with the command or function.
.SS ".SH AUTHOR"
The program's author and any pertinent release info.
.SS ".SH VERSION"
The program's current version number and release date.
.RE
.SH AUTHOR
.nf
Adapted for Atari ST (TOS) and Minix by Bill Rosenkranz
net: rosenkra@convex.com
CIS: 71460,17
GENIE: W.ROSENKRANZ
.fi

105
usr.bin/nroff/ms.7 Normal file
View File

@ -0,0 +1,105 @@
.\" ms(7) manpage by rosenkra@convex.com (Bill Rosenkranz, 7/22/90)
.\"
.TH MS 7
.SH NAME
ms - text formatting macros
.SH SYNOPSIS
nroff -ms [ options ] file ...
.SH DESCRIPTION
This package of nroff macro definitions provides a
formatting facility for various styles of articles, theses, and books.
All external -ms macros are defined below.
.PP
Note that this -ms macro package is a subset of the complete ms package
since nroff(1) is not quite up to it yet.
Still, it supports most of what is normally used, including the table
of contents macros.
.PP
Some nroff requests may be unsafe in conjunction with this package.
However, the first four requests below may be used with impunity after
initialization, and the last two may be used even before initialization:
.nf
.bp begin new page
.br break output line
.sp n insert n spacing lines
.ce n center next n lines
.ls n line spacing: n=1 single, n=2 double space
.na no alignment of right margin
.fi
Font changes with \f are also allowed;
for example, '\\fIword\\fR' will italicize word.
.SH FILES
.ec |
\lib\tmac\tmac.s
.ec \
.SH REQUESTS
.nf
.cc +
Macro Initial Break? Explanation
Name Value Reset?
.AB x - y begin abstract; if x=no don't label abstract
.AE - y end abstract
.AI - y author's institution, centered
.AU - y author's name, centered
.B x - n embolden x; if no x, switch to boldface
.I x - n italicize x; if no x, switch to italics
.IP x - y,y indented paragraph, with hanging tag x
.LP - y,y left (block) paragraph.
.NH x - y,y numbered header; x=level, x=0 resets
.PP - y,y paragraph with first line indented
.QP - y,y quoted paragraph (indented, shorter)
.R on n return to Roman font
.RE - y,y end level of relative indentation
.RS 5n y,y right shift: start level of relative indent
.SH - y,y section header, no numbering
.TL - y title, centered
.XP - y,y extended paragraph (biblio entry)
.XS p - y begin index entry, p = page
.XA p - y another index entry, p = page
.XE - y end index entry
.PX - y print index (ignored)
+cc .
.fi
.SH REGISTERS
There are currently no user controlled registers in this implementation.
.PP
Here is a list of string registers available in -ms; they
may be used anywhere in the text:
.nf
.ec |
Name String's Function
\*(DW weekday
\*(MO month (month of the year)
\*(DY day (current date)
\*Q quote (" in nroff)
\*U unquote (" in nroff)
\*- dash (-- in nroff)
.ec \
.fi
.SH EXAMPLES
For an example, see the test files (*.ms) included in the distribution.
.SH BUGS
Probably zillions, especially considering it is so incomplete.
However, it is useful (better than nothing at all).
I have used this package extensively at home to write reports for work.
The results were nearly 100% compatible with Unix (BSD).
No support for displays and keeps, tables, boxed text, multicolumn, other
modes (e.g. thesis mode), footnotes, and beginning/end page traps.
Indented paragraph with tag puts the tag on its own line regardless how
long it is.
.SH AUTHOR
.nf
Adapted for Atari ST (TOS) and Minix by Bill Rosenkranz
net: rosenkra@convex.com
CIS: 71460,17
GENIE: W.ROSENKRANZ
.fi

766
usr.bin/nroff/nroff.1 Normal file
View File

@ -0,0 +1,766 @@
.\" nroff(1) manpage by rosenkra@convex.com (Bill Rosenkranz, 7/22/90)
.\"
.TH NROFF 1
.SH NAME
nroff - text processor (Version 1.10)
.SH SYNOPSIS
nroff [options] file [...]
.SH DESCRIPTION
Nroff is a text processor and formatter based on the design
provided in "Software Tools" by Kernighan and Plauger.
It has been modified to closely resemble the Unix(tm) nroff command.
The text and commands found in the file(s)
are processed to generate formatted text.
Note that one (and only one) of the files can be "-" which reads
input from stdin at that point.
The output always goes to stdout which can be redirected by the shell.
.\" Using the command line option -l will cause the output to
.\" be sent to the printer instead.
The -o option lets you redirect error output to the specified
file rather than stderr.
Debugging information always goes to the file "nroff.dbg" and is
generally used only for program development.
.SH OPTIONS
The following command line options are available:
.IP -d
Set debug mode.
.IP -h
Hold before exit (Atari TOS only).
.IP -m<name>
Process macro file tmac.<name>.
Thus -man would cause the file tmac.an to be loaded.
Note that files processed in this way should contain only macro definitions,
no immediate output should be generated from this file (see ENVIRONMENT).
.IP -o<file>
Set error log file (default is stderr).
.IP -raN
Preset number register 'a' (single character) to N (decimal integer only).
.IP -po<n>
Shift output right n spaces (like .po).
.IP -pn<n>
Initial page number (like .pn).
.IP -v
Prints the version information to stdout.
.IP +<n>
Causes output to start with page n.
.IP -<n>
Causes output to stop after page n.
.IP -
Input from stdin.
.sp
.SH ENVIRONMENT
Nroff recognizes the following environment variables from the shell:
.IP TMACDIR
An alternate directory to find the files tmac.* ("." for example).
The default is c:\\lib\\tmac under TOS and /usr/lib/tmac under
Minix or Unix(tm).
.IP TMPDIR
An alternate directory to place any temporary files.
The default is the current directory.
Note that nroff does not currently use any temporary files.
.SH COMMANDS
Commands typically are distinguished by a period in column one
of the input
followed by a two character abbreviation for the command funtion.
The abbreviation may then be followed by an optional numeric or
character argument.
The numeric argument may be an absolute value such as setting
the right margin to a particular column, or the argument may be
preceded by a plus sign or a minus sign to indicate that the
parameter should be modified relative to a previous setting.
The following commands are recognized (those marked "extension"
are requests added to the basic set provided by Unix(tm) nroff):
.\"
.IP .ad
Begin line adjustment.
If fill mode is not on, adjustment is defered until it is back on.
If a type indicator is present, the adjustment type is changed as follows:
.nf
Indicator Type
l adjust left margin only
r adjust right margin only
c center
b or n adjust both margins (default)
absent unchanged
.fi
.\"
.IP .af
Assign format to number register.
The available formats are:
.nf
Format Numbering Sequence
1 0,1,2,3,4,...
001 000,001,002,...
i 0,i,ii,iii,iv,v,...
I 0,I,II,III,IV,V,...
a 0,a,b,...,z,aa,ab,...zz,aaa,...
A 0,A,B,...,Z,AA,AB,...ZZ,AAA,...
.fi
The second format above indicates that the field width, i.e. number
of digits, is specified by the number of digits in the format type.
.\"
.IP .bd
Ignored by nroff.
.\"
.IP .bo (extension)
Causes the following lines of text to appear in boldface.
The optional argument specifies the number of lines to be typed in boldface.
Boldface and underlining are mutually exclusive features.
The appearance of a boldface command will cause any underlining to cease.
.\"
.IP .bp (extension)
Causes succeeding text to appear at the top of a new page.
The optional argument specifies the page number for the new page.
The initial value is one and the default value is one more than
the previous page number.
.\"
.IP .br
Causes succeeding text to start on a new line at the current left margin.
There is no numeric argument for this command.
.\"
.IP .bs (extension)
Enables or disables the appearance of backspaces in the output text.
Underlining and boldface options are implemented by inserting
character - backspace - character combinations into the output buffer.
This is fine for devices which properly recognize the backspace character.
Some printers, however, do not recognize backspaces, so the option is
provided to overprint one line buffer with another.
The first line buffer is terminated with just a carriage return
rather than the carriage return - linefeed combination.
A zero argument or no argument to the backspace command removes
backspaces from the output.
A non-zero argument leaves them in the output.
The default is to remove backspaces.
.\"
.IP .cc
Changes the nroff command character to that specified by the
character argument.
If no argument is provided, the default is a period (\.).
.\"
.IP .ce
Causes the next line of text to appear centered on the output.
The optional argument specifies if more than one line is to be centered.
.\"
.IP .cs
Ignored by nroff.
.\"
.IP .cu
Causes the next line(s) of text to be continuously underlined.
Unlike the underline command (see \.ul) which underlines only
alphanumerics, continuous underlining underlines all printable characters.
The optional argument specifies the number of lines of text to underlined.
Any normal underlining or boldface commands currently in effect will be
terminated.
.\"
.IP .c2
Changes the nroff no break character to that specified by the
character argument.
If no argument is provided, the default is a single quote.
.\"
.IP .de
Causes all text and commands following to be used to define a macro.
The definition is terminated by a \.en command or the
default \.\. terminator.
The first two characters of the argument following the \.de
command become the name of the new command.
It should be noted that upper and lower case arguments are considered different.
Thus, the commands \.PP and \.pp could define two different macros.
Care should be exercised since existing commands may be redefined.
.sp
A macro may contain up to nine arguments.
In the macro definition, the placement of arguments is designated by the
two character sequences, $1, $2, ... $9.
When the macro is invoked, each argument of the macro command line is
substituted for its corresponding designator in the expansion.
The first argument of the macro command is substituted for the $1
in the expansion, the second argument for the $2, and so forth.
Arguments are typically strings which do not contain blanks or tabs.
If an argument is to contain blanks, then it should be surrounded by
either single or double quotes.
.\"
.IP .ds
Define a string.
To initiate the string with a blank or include blanks
in the string, start it with a single or double quite.
The string
can contain other defined strings or number registers as well as normal
text.
Strings are stored on the macro name space.
.\"
.IP .ec
Changes the nroff escape character to that specified by the
character argument.
If no argument is provided, the default is a backslash.
.\"
.IP .ef (extension)
Specifies the text for the footer on even numbered pages.
The format is the same as for the footer command (see \.fo).
.\"
.IP .eh (extension)
Specifies the text for the header on even numbered pages.
The format is the same as for the footer command (see \.fo).
.\"
.IP .en (extension)
Designates the end of a macro definition.
.\"
.IP .eo
Turn the escape mechanism off.
.\"
.IP .ex
Exit nroff at this point in the processing.
Ex forces all files closed and flushes the output.
.\"
.IP .fi
Causes the input text to be rearranged or filled to obtain the maximum
word count possible between the previously set left and right margins.
No argument is expected.
.\"
.IP .fl
Causes the output buffer to be flushed immediately.
.\"
.IP .fo (extension)
Specifies text to be used for a footer.
The footer text contains three strings seperated by a delimiter character.
The first non-blank character following the command is designated
as the delimiter.
The first text string is left justified to the current indentation
value (specified by \.in).
The second string is centered between the current indentation value
and the current right margin value (specified by \.rm).
The third string is right justified to the current right margin value.
The absence of footer text will result in the footer being printed as
one blank line.
The presence of the page number character (set by \.pc) in the footer
text results in the current page number being inserted at that position.
Multiple occurrances of the page number character are allowed.
.\"
.IP .ft
Changes the current font.
The choices are R (Times Roman), I (Times Italic), B (Times Bold),
S (math special), and P used to request the previous font.
P resets the next previous font to be the one just changed, amounting to a swap.
.\"
.IP .he (extension)
Specifies text to be used for a header.
The format is the same as for the footer (see \.fo).
.\"
.IP .if
Execute a command if the condition is true.
Format is:
.nf
.if c command
.if !c command
.if N command
.if !N command
.if "str1"str2" command
.if !"str1"str2" command
.fi
Here c is a single letter: n (true if nroff), t (true if troff), e (true
if even page), or o (true if odd page).
N is a numerical experssion and can include operators +, -, *, /, % (mod),
>, <, >=, <=, = (or ==), & (and), or : (or).
If the result is greater than 0, the condition evaluates true.
Numbers in the expression can be either constants or contents of number
registers.
Strings are tested using delimeter / or " only at this time.
Note that "block" conditionals like:
.nf
.if c \\{\\
...
...
... \\}
.fi
are not yet supported.
Also the .ie/.el conditional is not yet supported.
.\"
.IP .in
Indents the left margin to the column value specified by the argument.
The default left margin is set to zero.
.\"
.IP .ju (extension)
Causes blanks to be inserted between words in a line of
output in order to align or justify the right margin.
The default is to justify.
.\"
.IP .lg
Ignored by nroff.
.\"
.IP .ll
Sets the current line length.
The default is eighty.
.\"
.IP .ls
Sets the line spacing to the value specified by the argument.
The default is for single spacing.
.\"
.IP .lt
Set length of three-part titles.
Line length and title length
are independent.
Indents do not apply to titles but page offsets do.
.\"
.IP .m1 (extension)
Specifies the number of lines in the header margin.
This is the space from the physical top of page to and including
the header text.
A value of zero causes the header to not be printed.
A value of one causes the header to appear at the physical top of page.
Larger argument values cause the appropriate number of blank
lines to appear before the header is printed.
.\"
.IP .m2 (extension)
Specifies the number of blank lines to be printed between
the header line and the first line of the processed text.
.\"
.IP .m3 (extension)
Specifies the number of blank lines to be printed between
the last line of processed text and the footer line.
.\"
.IP .m4 (extension)
Specifies the number of lines in the footer margin.
This command affects the footer the same way the \.m1
command affects the header.
.\"
.IP .mc
Margin character. The first argument is the character to use,
the second is the distance to the right of the right margin
to place the margin character. Useful for change bars.
No arguments turns the capability off. Note that with this
nroff, the margin character is always a single character only
and this distance is prefered to be in inches (e.g. 0.2i).
The default space is 0.2i (2 spaces).
.\"
.IP .na
Noadjust.
Ajdustment is turned off; the right margin is ragged.
The adjustment type for \.ad is not changed.
Output line filling still occurs if fill mode is on.
.\"
.IP .ne
Specifies a number of lines which should not be broken across a page boundary.
If the number of lines remaining on a page is less than the
value needed, then a new output page is started.
.\"
.IP .nf
Specifies that succeeding text should be printed without
rearrangement, or with no fill.
No argument is expected.
.\"
.IP .nj (extension)
Specifies that no attempt should be made to align or justify the right margin.
No argument is expected.
.\"
.IP .nr
Causes the value of a number register to be set or modified.
A total of twenty-six number registers are available designated
\\na through \\nz (either upper or lower case is allowed).
When the sequence \\nc is imbedded in the text, the current value
of number register c replaces the sequence, thus, such things as
paragraph numbering can be accomplished with relative ease.
.\"
.IP .of (extension)
Specifies the text for the footer on odd numbered pages.
The format is the same as the footer command (see \.fo).
.\"
.IP .oh (extension)
Specifies the text for the header on odd numbered pages.
The format is the same as the footer command (see \.fo).
.\"
.IP .pc
Specifies the page number character to be used in headers and footers.
The occurrance of this character in the header or footer text
results in the current page number being printed.
The default for this character is the percent sign (%).
.\"
.IP .pl
Specifies the page length or the number of lines per output page.
The default is sixty-six.
.\"
.IP .pm
Print macros.
The names and sizes of the macros are printed to stdout.
This is useful when building a macro package to see how much of the
total namespace is consumed by the package.
.\"
.IP .pn
Changes the page number of the current page and all
subsequent pages to its argument.
If no argument is given, the command is ignored.
.\"
.IP .po
Specifies a page offset value.
This allows the formatted text to be shifted to the right by
the number of spaces specified.
This feature may also be invoked by a switch on the command line.
.\"
.IP .ps
Ignored by nroff.
.\"
.IP .rr
Removes a number register.
.\"
.IP .so
Causes input to be retrieved from the file specified
by the command's character string argument.
The contents of the new file are inserted into the output
stream until an EOF is detected.
Processing of the original file is then resumed.
Command nesting is allowed.
.\"
.IP .sp
Specifies a number of blank lines to be output before
printing the next line of text.
.\"
.IP .ss
Ignored by nroff.
.\"
.IP .ti
Temporarily alters the indentation or left margin value for a single
succeeding input line.
.\"
.IP .tl
Specifies text to be used for a page title.
The format is the same as for the header (see \.he).
.\"
.IP .ul
Causes the next line(s) of text to be underlined.
Unlike the \.cu command, this command causes only alphanumerics
to be underlined, skipping punctuation and white space.
Underline and boldface are mutually exclusive.
.PP
The following nroff commands, normally available, are currently
not implemented in this version:
.cc +
\.fp, \.mk, \.rt, \.vs, \.sv, \.os, \.ns, \.rs, \.am, \.as, \.rm, \.rn,
\.di, \.da, \.wh, \.ch, \.dt, \.it, \.em, \.ta, \.tc, \.lc, \.fc, \.lg,
\.uf, \.tr, \.nh, \.hy, \.hc, \.hw, \.nm, \.nn, \.ie, \.el, \.ev, \.rd,
\.ex, \.nx, \.pi, \.tm, and \.ig.
+cc .
.\"
.SH ESCAPE SEQUENCES
Escape sequences are used to access special characters (such as Greek
letters) which may be outside the normal printable ASCII character set.
The are also used to toggle certain actions such as font selection.
.PP
.ne 5
The escape sequences include:
.sp
.eo
.\" .ec -
.nf
\\ backslash character
\e printable version of escape character
\' accute accent (equivalent to \\(aa)
\` grave accent (equivalent to \\(ga)
\- minus sign
\. period
\<space> a single, unpaddable space
\0 digit-width space
\| 1\6em space (zero space in nroff)
\^ 1\12em space (zero space in nroff)
\& non-printing zero-width character
\" beginning of comment
\% default hyphenation character
\(xx special character named xx
\*x,\*(xx interpolate string x or xx
\fc font change (c = R,I,B,S,P)
\nx interpolate number register x
\t horizontal tab
.fi
.sp
.ne 5
The Atari ST (TOS) version of nroff includes the following special
characters. NOTE: THESE ARE NOT AVAILABLE UNDER Minix OR Unix(tm)!
.sp
.nf
\(co copyright
\(rg registered
\(tm trademark
\(12 1/2
\(14 1/4
\(p2 exponent 2
\(p3 exponent 3
\(pn exponent n
\(aa acute
\(ga grave
\(de degree
\(dg dagger
\(ct cent
\(bu bullet
\(pp paragraph
\(^g ring bell
\(ua up arrow
\(da dn arrow
\(-> rt arrow
\(<- lf arrow
\(di divide
\(sr sq root
\(== ==
\(>= >=
\(<= <=
\(+- +-
\(~= ~=
\(ap approx
\(no not
\(mo memeber
\(ca intersect
\(cu union
\(*a alpha
\(*b beta
\(*g gamma
\(*d delta
\(*s sigma
\(*p pi
\(*m mu
.fi
.ec
.SH PREDEFINED GENERAL NUMBER REGISTERS
The following number registers are available for both reading and writing.
They are accessed with the \\n(xx and \\nx escape and can be set with .nr:
.nf
.ne 5
% current page number
dw current day of the week (1-7)
dy current day of the month (1-31)
hh current hours (0-23)
ln current line number
mm current minutes (0-59)
mo current month (1-12)
ss current seconds (0-59)
yr last 2 digits of current year
.fi
.sp
The following number registers are available for reading only:
.nf
.cc +
.$ number of args available in current macro
.A always 1 in nroff
.H available horizontal resolution
.T always 0 in nroff
.V available vertical resolution
.c number of lines read from current file
.f current font (1-4)
.i current indent
.l current line length
.o current page offset
.p current page length
.v current vertical spacing
+cc .
.fi
.SH NOTES
There are several missing features, notably diversions, traps,
conditionals, all the hard stuff.
This means you can't use some existing macro packages (yet, I hope).
There is no complete -ms and -me packages as a result.
The goal is to make this nroff work with all the SunOS macro packages
sometime before Unix becomes obsolete!
.PP
If you make additions to this code, please mail the changes to me so I
can make formal distributions.
.SH BUGS
Undoubtedly more than I know about.
Here are a few:
.PP
The ability to perform numerical calculations on registers is not
implemented.
.PP
All dimensional units are in em's or inches only.
.PP
Lines with multiple string instances (i.e. \\*(xx) don't seem to work.
.PP
Lines with font changes (e.g. for italics) use vt52 escape sequences
to go to highlight mode.
This should read termcap/terminfo to do it right.
.PP
Some interpolations don't work properly.
.PP
The code uses statically allocated arrays for macros, strings, and registers.
This should be changed to dynamically allocated buffers or
write to intermediate files on small memory systems (i.e. Minix).
.SH FILES
.nf
.ec |
\lib\tmac\tmac.* predefined macros (see ENVIRONMENT)
nroff.dbg debugging output
stderr default error output stream
stdout output stream
.ec \
.fi
.SH AUTHOR
.nf
Adapted for Atari ST (TOS) and Minix by Bill Rosenkranz 11/89
net: rosenkra@convex.com
CIS: 71460,17
GENIE: W.ROSENKRANZ
Original author:
Stephen L. Browning
5723 North Parker Avenue
Indianapolis, Indiana 46220
.fi
.SH HISTORY
.nf
Originally written in BDS C (by Stephen L. Browning?)
Adapted for standard C by W. N. Paul
Heavily hacked up to conform to the "real" nroff with numerous
additions by Bill Rosenkranz 11/89
Bug fixes (termcap) and Minix 1.5.5 compatibility by
Wim 'Blue Baron' van Dorst (wsincc@tuerc3.urc.tue.nl)
.fi
.SH RECOMMENDATIONS
I envisioned this rather limited version as a way of formatting
man pages for my Atari ST system.
It works just fine for that.
The man macro package is certainly adequate for that purpose.
However, it would be nice to have more.
I suggest you limit
yourself to things which would port easily to other environments.
All the man macros available here should port without effort
to a more complete Unix(tm) environment.
.PP
Nroff as it stands can certainly be useful.
I recommend you don't
use the commands marked "extension".
Study the source for the man pages here (nroff(1), ms(7), and man(7)) as
well as the macro packages (tmac.an and tmac.s) and the examples to find
out the quirks.
Some things may not quite work like they do under Unix(tm), but it is
fairly close for what is here.
.SH REFERENCES
This document briefly describes the workings of nroff.
It is certainly not the definitive work on text processing.
I suggest you go out and get a good book (there are several on the market)
or refer to the Unix(tm) manuals for more help.
Nroff is just like a compiler and is much more complicated than (say) the C
language which only has a handful of rules and is much more thoroughly
documented.
Good luck!
.SH REQUEST SUMMARY
The following table summarizes the nroff requests currently available:
.nf
.ne 8
.cc +
Request Form Initial Default Notes Explanation
-------------- ------- ------- ------- ----------------------
Font and Character Size Control
.ps +-N 10pt prev E point size (ignored)
.ss N 12/36em ignored E space size (ignored)
.cs F N M off - P constant space mode (ign)
.bd F N off - P embolden font F (ignored)
.bd S F N off - P embolden special font
.ft F Roman prev E change to font F
+ne 4
Page Control
.pl +-N 11in 11in v page length
.bp +-N N=1 - B,v eject page
.pn +-N N=1 ignored - next page number N
.po +-N 0 prev v page offset
.ne N - N=1V D,v need N vertical space
+ne 4
Text Filling, Adjusting, and Centering
.br - - B break
.fi fill - B,E fill mode
.nf fill - B,E no fill or adjust
.ad c adj,both adjust E adjust output, mode c
.na adjust - E no adjust
.ce N off N=1 B,E center N lines
+ne 4
Vertical Spacing
.ls N N=1 prev E output N-1 Vs
.sp N - N=1V B,v space vertical
+ne 4
Line Length and Indenting
.ll +-N 6.5i prev E,m line length
.in +-N N=0 prev B,E,m indent
.ti +-N - ignored B,E,m temporary indent
+ne 4
Macros, Strings, Diversions, and Position Traps
.de xx yy - .yy=.. - define macro xx
.ds xx str - ignored - define string xx
+ne 4
Number Registers
.nr R +-N M - u define and set num reg
.af R c arabic - - assign format to reg
.rr R - - - remove register
+ne 4
I/O Conventions and Character Translation
.ec c \ \ - set escape char
.eo on - - turn off escape mech
.lg N - - - ligature mode (ignored)
.ul N off N=1 E underline N lines
.cu N off N=1 E cont. underline
.cc c . . E set control char
.c2 c ' ' E set nobreak control char
+ne 4
Three-part Titles
.tl 'l'c'r' - - three-part title
.pc c % off - page number char
.lt +-N 6.5in prev E,m length of title
+ne 4
Conditional Acceptence of Input
.if c cmd - - if c true, accept cmd
.if !c cmd - - if c false, accept cmd
.if N cmd - - if N > 0, accept cmd
.if !N cmd - - if N <= 0, accept cmd
.if "s1"s2" cmd - - if strings same, accept cmd
.if !"s1"s2" cmd - - if strings differ, accept cmd
+ne 4
Input/Output File Switching
.so filename - - switch source file
+ne 4
Miscellaneous
.mc c N - off E,m margin char c, seperation N
.pm t - all - print macro names
.fl - - B flush output buffer
+ne 4
Notes
B causes a break
D mode or parameters associated with current diversion level
E relevant parameters are a part of the current environment
O must stay in effect until logical output
P mode must be still or again in effect at time of physical output
v,p,m,u default scale indicators
+cc
.fi

991
usr.bin/nroff/nroff.c Normal file
View File

@ -0,0 +1,991 @@
/*
* main.c - main for nroff word processor
*
* similar to Unix(tm) nroff or RSX-11M RNO. adaptation of text processor
* given in "Software Tools", Kernighan and Plauger.
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: nroff.c,v 1.1 1997/03/14 06:22:27 gdr Exp $
*/
#ifdef __ORCAC__
segment "main______";
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#ifdef __GNO__
#include <err.h>
#include <termcap.h>
#else
#include "err.h"
#include "termcap.h"
#endif
#ifdef sparc
#include <memory.h>
#include "sunos.h"
#endif
#include "nroff.h"
#include "macros.h"
#include "io.h"
static void init (void);
static void processFile (void);
static int pswitch (char *p, int *q);
static void usage (void);
/*************************************************************************
*
* Global variables block. Keep them in main.c so that the IIgs'
* debuggers can find them.
*/
struct docctl dc;
struct page pg;
struct macros_t mac;
struct regs rg[MAXREGS];
FILE *out_stream;
FILE *err_stream;
FILE *dbg_stream;
FILE *sofile[Nfiles+1];
int ignoring; /* .ig vs .de */
int hold_screen;
int debugging;
int stepping; /* paging */
int mc_ing = 0; /* turned off */
int mc_space = 2;
char mc_char = '|';
char tmpdir[256];
char s_standout[20];
char e_standout[20];
char s_bold[20];
char e_bold[20];
char s_italic[20];
char e_italic[20];
char *dbgfile = "nroff.dbg";
#ifdef GEMDOS
char *printer = "prn:"; /* this WON'T work!!! */
#else
char *printer = ".ttyb"; /* this probably won't */
#endif
static char termcap[1024]; /* _must_ be 1024 */
static char *progname;
static char *version = "(GNO) v1.2, 5 Mar 97 gdr";
/*
* End of global variable definitions.
*
*************************************************************************/
int
main (int argc, char *argv[]) {
register int i;
int swflg;
int ifp = 0;
char *ptmp;
char *pterm;
char capability[100];
char *pcap;
char *ps;
#ifdef __GNO__
if (argc > 0) {
progname = __prognameGS();
} else {
exit(1); /* not running from a shell? */
}
#else
if (argc > 0) {
progname = basename(argv[0]);
} else {
progname = "nroff";
}
#endif
/*
* set up initial flags and file descriptors
*/
swflg = FALSE;
ignoring = FALSE;
hold_screen = FALSE;
debugging = FALSE;
stepping = FALSE;
mc_ing = FALSE;
out_stream = stdout;
err_stream = stderr;
dbg_stream = stderr;
/*
* this is for tmp files, if ever needed. it SHOULD start
* out without the trailing slash. if not in env, use default
*/
if ((ptmp = getenv ("TMPDIR")) != NULL) {
strcpy (tmpdir, ptmp);
} else {
strcpy (tmpdir, ".");
}
/*
* handle terminal for \fB, \fI
*/
s_standout[0] = '\0';
e_standout[0] = '\0';
s_bold[0] = '\0';
e_bold[0] = '\0';
s_italic[0] = '\0';
e_italic[0] = '\0';
/*
* get termcap information
*/
if ((pterm = getenv("TERM")) == NULL) {
errx(1, "TERM environment variable not set");
}
switch (tgetent(termcap, pterm)) {
case -1:
errx(1, "couldn't open termcap database");
/*NOTREACHED*/
case 0:
errx(1, "terminal type %s not found in termcap database", pterm);
/*NOTREACHED*/
}
/*
* we currently use standout mode for all weirdness
* like BOLD, italic, etc.
*/
pcap = capability;
if ((ps = tgetstr ("so", &pcap)) != NULL) {
/*
* sun has padding in here. this is NOT portable.
* better to use tputs() to strip it...
*/
/* while (*ps && *ps != 0x1b) ps++; */
strcpy (s_standout, ps);
strcpy (s_bold, ps);
strcpy (s_italic, ps);
} else {
err(1, "couldn't get standout mode");
/*NOTREACHED*/
}
if ((ps = tgetstr ("se", &pcap)) != NULL) {
/* while (*ps && *ps != 0x1b) ps++; */
strcpy (e_standout, ps);
strcpy (e_bold, ps);
strcpy (e_italic, ps);
}
/*
* initialize structures (defaults)
*/
init ();
/*
* parse cmdline flags
*/
for (i = 1; i < argc; ++i) {
if (*argv[i] == '-' || *argv[i] == '+') {
if (pswitch (argv[i], &swflg) == ERR) {
err_exit (-1);
}
}
}
/*
* loop on files
*/
for (i = 1; i < argc; ++i) {
if (*argv[i] != '-' && *argv[i] != '+') {
/*
* open this file...
*/
if ((sofile[0] = fopen (argv[i], "r")) == NULL_FPTR) {
err(-1, "unable to open file %s", argv[i]);
} else {
/*
* do it for this file...
*/
ifp = 1;
processFile ();
fclose (sofile[0]);
}
} else if (*argv[i] == '-' && *(argv[i]+1) == 0) {
/*
* - means read stdin (anywhere in file list)
*/
sofile[0] = stdin;
ifp = 1;
sleep(1);
processFile ();
}
}
/*
* if no files, usage (should really use stdin...)
*/
if ((ifp == 0 && swflg == FALSE) || argc <= 1) {
usage ();
err_exit (-1);
}
/*
* normal exit. this will fflush/fclose streams...
*/
err_exit (0);
#if defined(__GNUC__) || defined(__INSIGHT__)
return 0;
#endif
}
/*------------------------------*/
/* usage */
/*------------------------------*/
static void
usage (void) {
/*
* note: -l may not work correctly
*/
fprintf(stderr, "Usage: %s [options] file [...]\n", progname);
fputs("\t-a\tno font changes\n", stderr);
fputs("\t-b\t\tbackspace\n", stderr);
fputs("\t-d\t\tdebug mode (file: nroff.dbg)\n", stderr);
#ifdef GEMDOS
fputs("\t-h\t\thold screen before desktop\n", stderr);
#endif
#if 0
fputs("\t-l\t\toutput to printer\n", stderr);
#endif
fputs("\t-m<name>\tmacro file (e.g. -man)\n", stderr);
fputs("\t-o<file>\terror log file (stderr is default)\n", stderr);
fputs("\t-po<n>\t\tpage offset\n", stderr);
fputs("\t-pn<n>\t\tinitial page number\n", stderr);
fputs("\t-pl<n>\t\tpage length\n", stderr);
fputs("\t-s\t\tstep through pages\n", stderr);
fputs("\t-v\t\tprint version only\n", stderr);
fputs("\t+<n>\t\tfirst page to do\n", stderr);
fputs("\t-<n>\t\tlast page to do\n", stderr);
fputs("\t-\t\tuse stdin (in file list)\n", stderr);
}
/*
* init
* initialize parameters for nro word processor
*/
static void
init (void) {
#ifdef MINIX
register int i;
#else
register long i;
#endif
time_t tval;
char *ctim;
/*
* misc global flags, etc...
*/
mc_space = 2;
mc_char = '|';
tval = time (0L);
ctim = ctime (&tval);
/*
* basic document controls...
*/
dc.fill = YES;
dc.dofnt = YES;
dc.lsval = 1;
dc.inval = 0;
dc.rmval = PAGEWIDTH - 1;
dc.llval = PAGEWIDTH - 1;
dc.ltval = PAGEWIDTH - 1;
dc.tival = 0;
dc.ceval = 0;
dc.ulval = 0;
dc.cuval = 0;
dc.juval = YES;
dc.adjval = ADJ_BOTH;
dc.boval = 0;
dc.bsflg = FALSE;
dc.prflg = TRUE;
dc.sprdir = 0;
dc.flevel = 0;
dc.lastfnt = 1;
dc.thisfnt = 1;
dc.escon = YES;
dc.pgchr = '%';
dc.cmdchr = '.';
dc.escchr = '\\';
dc.nobrchr = '\'';
for (i = 0; i < 26; ++i) {
dc.nr[i] = 0;
}
for (i = 0; i < 26; ++i) {
dc.nrauto[i] = 1;
}
for (i = 0; i < 26; ++i) {
dc.nrfmt[i] = '1';
}
/*
* initialize internal regs. first zero out...
*/
for (i = 0; i < MAXREGS; i++) {
rg[i].rname[0] = EOS;
rg[i].rname[1] = EOS;
rg[i].rname[2] = EOS;
rg[i].rname[3] = EOS;
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
}
/*
* predefined regs. these are read/write:
*/
i = 0;
strcpy (rg[i].rname, "%"); /* current page */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "ct"); /* character type */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dl"); /* width of last complete di */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dn"); /* height of last complete di */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dw"); /* day of week (1-7) */
rg[i].rval = 0;
if (!strncmp (&ctim[0], "Sun", 3)) rg[i].rval = 1;
else if (!strncmp (&ctim[0], "Mon", 3)) rg[i].rval = 2;
else if (!strncmp (&ctim[0], "Tue", 3)) rg[i].rval = 3;
else if (!strncmp (&ctim[0], "Wed", 3)) rg[i].rval = 4;
else if (!strncmp (&ctim[0], "Thu", 3)) rg[i].rval = 5;
else if (!strncmp (&ctim[0], "Fri", 3)) rg[i].rval = 6;
else if (!strncmp (&ctim[0], "Sat", 3)) rg[i].rval = 7;
rg[i].rauto = 1;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "dy"); /* day of month (1-31) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[8]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "hp"); /* current h pos on input */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "ln"); /* output line num */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "mo"); /* current month (1-12) */
rg[i].rval = 0;
if (!strncmp (&ctim[4], "Jan", 3)) rg[i].rval = 1;
else if (!strncmp (&ctim[4], "Feb", 3)) rg[i].rval = 2;
else if (!strncmp (&ctim[4], "Mar", 3)) rg[i].rval = 3;
else if (!strncmp (&ctim[4], "Apr", 3)) rg[i].rval = 4;
else if (!strncmp (&ctim[4], "May", 3)) rg[i].rval = 5;
else if (!strncmp (&ctim[4], "Jun", 3)) rg[i].rval = 6;
else if (!strncmp (&ctim[4], "Jul", 3)) rg[i].rval = 7;
else if (!strncmp (&ctim[4], "Aug", 3)) rg[i].rval = 8;
else if (!strncmp (&ctim[4], "Sep", 3)) rg[i].rval = 9;
else if (!strncmp (&ctim[4], "Oct", 3)) rg[i].rval = 10;
else if (!strncmp (&ctim[4], "Nov", 3)) rg[i].rval = 11;
else if (!strncmp (&ctim[4], "Dec", 3)) rg[i].rval = 12;
rg[i].rauto = 1;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "nl"); /* v pos of last base-line */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "sb"); /* depth of str below base */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "st"); /* height of str above base */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "yr"); /* last 2 dig of current year*/
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[22]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, "hh"); /* current hour (0-23) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[11]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = 2 | 0x80;
i++;
strcpy (rg[i].rname, "mm"); /* current minute (0-59) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[14]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = 2 | 0x80;
i++;
strcpy (rg[i].rname, "ss"); /* current second (0-59) */
rg[i].rauto = 1;
rg[i].rval = atoi (&ctim[17]);
rg[i].rflag = RF_READ | RF_WRITE;
rg[i].rfmt = 2 | 0x80;
i++;
/*
* these are read only (by user):
*/
strcpy (rg[i].rname, ".$"); /* num args at current macro*/
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".A"); /* 1 for nroff */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".H"); /* hor resolution */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".T"); /* 1 for troff */
rg[i].rauto = 0;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".V"); /* vert resolution */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".a");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".c");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".d");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".f"); /* current font (1-4) */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".h");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".i"); /* current indent */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".l"); /* current line length */
rg[i].rauto = 1;
rg[i].rval = PAGEWIDTH - 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".n");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".o"); /* current offset */
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".p"); /* current page len */
rg[i].rauto = 1;
rg[i].rval = PAGELEN;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".s"); /* current point size */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".t");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".u");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".v"); /* current v line spacing */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".w"); /* width of prev char */
rg[i].rauto = 1;
rg[i].rval = 1;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".x");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".y");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
i++;
strcpy (rg[i].rname, ".z");
rg[i].rauto = 1;
rg[i].rval = 0;
rg[i].rflag = RF_READ;
rg[i].rfmt = '1';
/*
* page controls...
*/
pg.curpag = 0;
pg.newpag = 1;
pg.lineno = 0;
pg.plval = PAGELEN;
pg.m1val = 2;
pg.m2val = 2;
pg.m3val = 2;
pg.m4val = 2;
pg.bottom = pg.plval - pg.m4val - pg.m3val;
pg.offset = 0;
pg.frstpg = 0;
pg.lastpg = 30000;
pg.ehead[0] = pg.ohead[0] = '\n';
pg.efoot[0] = pg.ofoot[0] = '\n';
memset(pg.ehead + 1, EOS, MAXLINE -1);
memset(pg.ohead + 1, EOS, MAXLINE -1);
memset(pg.efoot + 1, EOS, MAXLINE -1);
memset(pg.ofoot + 1, EOS, MAXLINE -1);
#if 0
for (i = 1; i < MAXLINE; ++i) {
pg.ehead[i] = pg.ohead[i] = EOS;
pg.efoot[i] = pg.ofoot[i] = EOS;
}
#endif
pg.ehlim[LEFT] = pg.ohlim[LEFT] = dc.inval;
pg.eflim[LEFT] = pg.oflim[LEFT] = dc.inval;
pg.ehlim[RIGHT] = pg.ohlim[RIGHT] = dc.rmval;
pg.eflim[RIGHT] = pg.oflim[RIGHT] = dc.rmval;
/*
* output buffer controls...
*/
initOutbuf();
/*
* macros...
*/
initMacros();
/*
* file descriptors (for sourced files)
*/
for (i = 0; i < Nfiles+1; ++i) {
sofile[i] = NULL_FPTR;
}
}
/*
* pswitch
*
* process switch values from command line
*/
static int
pswitch (char *p, int *q) {
int swgood;
char mfile[256];
char *ptmac;
int indx;
int val;
swgood = TRUE;
if (*p == '-') {
/*
* since is STILL use the goofy atari/dri xmain code, i
* look for both upper and lower case. if you use dLibs
* (and if its startup code does not ucase the cmd line),
* you can probably look for just lower case. gulam and
* other shells typically don't change case of cmd line.
*/
switch (*++p) {
case 0: /* stdin */
break;
case 'a': /* font changes */
case 'A':
dc.dofnt = NO;
break;
case 'b': /* backspace */
case 'B':
dc.bsflg = TRUE;
break;
case 'd': /* debug mode */
case 'D':
if ((dbg_stream = fopen (dbgfile, "w")) == NULL) {
warn ("unable to open debug file %s, using stderr", dbgfile);
dbg_stream = stderr;
}
debugging = TRUE;
break;
case 'h': /* hold screen */
case 'H':
hold_screen = TRUE;
break;
case 'l': /* to lpr (was P) */
case 'L':
#ifdef GEMDOS
out_stream = (FILE *) 0;
#else
out_stream = fopen (printer, "w");
#endif
setPrinting(TRUE);
break;
case 'm': /* macro file */
case 'M':
/*
* build macro file name. start with lib
*
* put c:\lib\tmac in environment so we can
* read it here. else use default. if you want
* file from cwd, "setenv TMACDIR ." from shell.
*
* we want file names like "tmac.an" (for -man)
*/
if ((ptmac = getenv ("TMACDIR")) != NULL) {
/*
* this is the lib path (e.g. "c:\lib\tmac")
*/
strcpy (mfile, ptmac);
/*
* this is the prefix (i.e. "\tmac.")
*/
strcat (mfile, TMACPRE);
} else {
/*
* use default lib/prefix (i.e.
* "c:\lib\tmac\tmac.")
*/
strcpy (mfile, TMACFULL);
}
/*
* finally, add extension (e.g. "an")
*/
strcat (mfile, ++p);
/*
* open file and read it
*/
if ((sofile[0] = fopen (mfile, "r")) == NULL_FPTR) {
err(-1, "unable to open macro file %s", mfile);
/*NOTREACHED*/
}
processFile ();
fclose (sofile[0]);
break;
case 'o': /* output error log */
case 'O':
if (!*(p+1)) {
err(-1, "no error file specified");
/*NOTREACHED*/
}
if ((err_stream = fopen (p+1, "w")) == NULL) {
err(-1, "unable to open error file %s", p+1);
/*NOTREACHED*/
}
err_set_file(err_stream);
break;
case 'p': /* .po, .pn */
case 'P':
if (*(p+1) == 'o' || *(p+1) == 'O') { /* -po___ */
p += 2;
set (&pg.offset, ctod (p), '1', 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
} else if (*(p+1) == 'n' || *(p+1) == 'N') { /* -pn___ */
p += 2;
set (&pg.curpag, ctod (p) - 1, '1', 0, -HUGE, HUGE);
pg.newpag = pg.curpag + 1;
set_ireg ("%", pg.newpag, 0);
} else if (*(p+1) == 'l' || *(p+1) == 'L') { /* -pl___ */
p += 2;
set (&pg.plval, ctod (p) - 1, '1', 0,
pg.m1val + pg.m2val + pg.m3val + pg.m4val + 1,
HUGE);
set_ireg (".p", pg.plval, 0);
pg.bottom = pg.plval - pg.m3val - pg.m4val;
} else { /* -p___ */
p++;
set (&pg.offset, ctod (p), '1', 0, 0, HUGE);
set_ireg (".o", pg.offset, 0);
}
break;
case 'r': /* set number reg */
case 'R':
if (!isalpha (*(p+1))) {
warnx("invalid number register name (%c)", *(p+1));
} else {
/*
* indx is the user num register and val
* is the final value.
*/
indx = tolower (*(p+1)) - 'a';
val = atoi (p+2);
set (&dc.nr[indx], val, '1', 0, -INFINITE, INFINITE);
}
break;
case 's': /* page step mode */
case 'S':
stepping = TRUE;
break;
case 'v': /* version */
case 'V':
printf ("%s %s\n", progname, version);
*q = TRUE;
break;
case '0': /* last page */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
pg.lastpg = ctod (p);
break;
default: /* illegal */
swgood = FALSE;
break;
}
} else if (*p == '+') { /* first page */
pg.frstpg = ctod (++p);
} else { /* illegal */
swgood = FALSE;
}
if (swgood == FALSE) {
warnx("illegal option: %s", p);
return (ERR);
}
return (OK);
}
/*
* processFile
*
* process input files from command line
*/
static void
processFile (void) {
static char ibuf[MAXLINE];
int i;
/*
* handle nesting of includes (.so). note that .so causes dc.flevel
* to be increased...
*/
for (dc.flevel = 0; dc.flevel >= 0; dc.flevel -= 1) {
while ((i = getlin (ibuf, sofile[dc.flevel])) != EOF) {
/*
* if line is a command or text
*/
if (ibuf[0] == dc.cmdchr) {
comand (ibuf);
} else {
/*
* this is a text line. first see if
* first char is space. if it is, break
* line.
*/
if (ibuf[0] == ' ') {
robrk ();
}
text (ibuf);
}
}
/*
* close included file
*/
if (dc.flevel > 0) {
fclose (sofile[dc.flevel]);
}
}
if (pg.lineno > 0) {
nroffSpace (HUGE);
}
}
#pragma optimize 8
#pragma debug 0
void
debugMessage (const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
fprintf(err_stream, "%s: ", progname);
vfprintf(err_stream, fmt, ap);
va_end(ap);
return;
}

9
usr.bin/nroff/nroff.desc Normal file
View File

@ -0,0 +1,9 @@
Name: nroff
Version: 1.2 (17 Mar 97)
Shell: ORCA/Shell, GNO/ME
Author: Various. Maintained by Devin Reade.
Contact: gdr@myrias.com
Where: /usr/bin
FTP: apple2.caltech.edu, ground.isca.uiowa.edu
Text Processing Typesetter

483
usr.bin/nroff/nroff.h Normal file
View File

@ -0,0 +1,483 @@
#ifndef NRO_H
#define NRO_H
#include "config.h" /* os/compiler options */
#ifndef NEWLINE
#define NEWLINE '\n'
#endif
/*
* nroff.h - stuff for nroff
*
* adapted for atariST/TOS by Bill Rosenkranz 10/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* things to look for here:
* 1) TMAC definition for default macro package lib
* 2) configuration sizes (see _STKSIZ below if alcyon/dri)
* 3) libc should have getenv(), time(), and ctime()
* 4) look in version.h for *printer file name (included below)
*
* all data is currently allocated in static arrays. the biggest
* chunks are the parameters which control number registers and the
* macro name space area. these are defined below: MAXREGS, MACBUF.
* MACBUF is the larger. it holds all macros, strings, etc. if you
* find yourself running out of macro space, increase MACBUF.
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
*/
#include <ctype.h>
/*
* default prefix of macro files. files will be of the form "tmac.an"
* (for -man), "tmac.s" (for -ms), "tmac.e" (for -me), etc. first
* checks environment for TMACDIR which would be path (e.g. "c:\lib\tmac"
* or ".", no trailing slash char!).
*/
#ifdef tmacfull
# define TMACFULL tmacfull
#endif
#ifdef tmacpre
# define TMACPRE tmacpre
#endif
#ifdef GEMDOS
# ifndef TMACFULL
# define TMACFULL "c:\\lib\\tmac\\tmac."
# endif
# ifndef TMACPRE
# define TMACPRE "\\tmac."
# endif
#endif
#ifdef MINIX
# ifndef TMACFULL
# define TMACFULL "/usr/lib/tmac/tmac."
# endif
# ifndef TMACPRE
# define TMACPRE "/tmac."
# endif
#endif
#ifdef UNIX
# ifndef TMACFULL
# define TMACFULL "/usr/lib/tmac/tmac."
# endif
# ifndef TMACPRE
# define TMACPRE "/tmac."
# endif
#endif
/*
* command codes. indented defines are commands not yet implemented
*/
#undef PI
#define MACRO 0 /* macro definition */
#define BP 1 /* begin page */
#define BR 2 /* break */
#define CE 3 /* center */
#define FI 4 /* fill */
#define FO 5 /* footer */
#define HE 6 /* header */
#define IN 7 /* indent */
#define LS 8 /* line spacing */
#define NF 9 /* no fill */
#define PL 10 /* page length */
#define RM 11 /* remove macro */
#define SP 12 /* line space */
#define TI 13 /* temp indent */
#define UL 14 /* underline */
#define JU 15 /* justify */
#define NJ 16 /* no justify */
#define M1 17 /* top margin */
#define M2 18 /* second top margin */
#define M3 19 /* first bottom margin */
#define M4 20 /* bottom-most margin */
#define BS 21 /* allow/disallow '\b' in output */
#define NE 22 /* need n lines */
#define PC 23 /* page number character (%) */
#define CC 24 /* control character (.) */
#define PO 25 /* page offset */
#define BO 26 /* bold face */
#define EH 27 /* header for even numbered pages */
#define OH 28 /* header for odd numbered pages */
#define EF 29 /* footer for even numbered pages */
#define OF 30 /* footer for odd numbered pages */
#define SO 31 /* source file */
#define CU 32 /* continuous underline */
#define DE 33 /* define macro */
#define EN 34 /* end macro definition */
#define NR 35 /* set number register */
#define EC 36 /* escape character (\) */
#define FT 37 /* font change (R,B,I,S,P) */
#define EO 38 /* turn escape parsing off */
#define LL 39 /* line length (same as RM) */
#define FL 40 /* flush output NOW */
#define PN 41 /* page number for next page */
#define RR 42 /* remove register */
#define C2 43 /* nobreak char */
# define TR 44 /* translate character */
#define LT 45 /* length of title */
# define FC 46 /* field delimeter */
#define TL 47 /* like HE */
#define AF 48 /* assign format to nr */
#define AD 49 /* adjust line */
#define NA 50 /* no adjust */
#define DS 51 /* define string */
#define PM 52 /* print macro names */
#define IF 53 /* if */
# define IE 54 /* if/else */
# define EL 55 /* else */
#define PS 56 /* point size (IGNORED in nroff) */
#define SS 57 /* space char size (IGNORED in nroff) */
#define CS 58 /* constant char space (IGNORED in nroff) */
#define BD 59 /* embolden font (IGNORED in nroff) */
# define FP 60 /* font position */
# define MK 61 /* mark vertical place */
# define RT 62 /* return to marked vert place */
# define VS 63 /* vertical baseline spacing */
# define SV 64 /* save vertical distance */
# define OS 65 /* output saved vertical distance */
# define NS 66 /* no-space mode */
# define RS 67 /* restore spacing mode */
# define AM 68 /* append to macro */
# define AS 69 /* append to string */
# define RN 70 /* rename */
# define DI 71 /* divert to macro */
# define DA 72 /* divert/append to macro */
# define WH 73 /* set location trap */
# define CH 74 /* change trap location */
# define DT 75 /* set diversion trap */
# define IT 76 /* set input line trap */
# define EM 77 /* end macro */
# define TA 78 /* tab settings */
# define TC 79 /* tab repetition char */
# define LC 80 /* leader repetition char */
# define LG 81 /* ligature mode */
# define UF 82 /* underline font */
# define NH 83 /* no hyphenation */
# define HY 84 /* hyphenate */
# define HC 85 /* hyphenation indication char */
# define HW 86 /* hyphenation exception words */
# define NM 87 /* number mode */
# define NN 88 /* no number next lines */
# define EV 89 /* environment switch */
# define RD 90 /* read insertion */
# define EX 91 /* exit */
# define NX 92 /* next file */
# define PI 93 /* pipe to program */
# define MC 94 /* set margin char */
# define TM 95 /* print to terminal */
#define IG 96 /* ignore */
#define COMMENT 1000 /* comment (.\") */
#define UNKNOWN -1
/*
* MAXLINE is set to a value slightly larger than twice the longest
* expected input line. Because of the way underlining is handled, the
* input line which is to be underlined, can almost triple in length.
* Unlike normal underlining and boldfacing, continuous underlining
* affects all characters in the buffer, and represents the worst case
* condition. If the distance between the left margin and the right
* margin is greater than about 65 characters, and continuous underlining
* is in effect, there is a high probability of buffer overflow.
*/
/* FIXME */
#define MAXLINE 500 /*500*/ /* 200 */
#define PAGELEN 66
#define PAGEWIDTH 80
#define HUGE 256
#define INFINITE 32760
#define LEFT 0 /* indecies into hdr margin lim arrays */
#define RIGHT 1
#define Nfiles 4 /* nesting depth for input files */
/*
* The following parameters may be defined elsewhere so undef/def
*/
#undef min
#undef max
#undef YES
#define YES 1
#undef NO
#define NO 0
#undef ERR
#define ERR -1
#define EOS '\0'
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE !FALSE
#undef OK
#define OK !ERR
/*
* a rational way of dealing with the NULL thing...
*/
#define NULL_CPTR (char *) 0
#define NULL_FPTR (FILE *) 0
#define NULL_IPTR (int *) 0
#define NULL_LPTR (long *) 0
#define NULL_SPTR (short *) 0
#define NULL_PTR (char *) 0
#define NULLP(type) (type *) 0
/*
* for justification during line fill
*/
#define ADJ_OFF 0
#define ADJ_LEFT 1
#define ADJ_RIGHT 2
#define ADJ_CENTER 3
#define ADJ_BOTH 4
/*
* Markers for various terminal/printer modes
*/
#define S_STANDOUT 128
#define E_STANDOUT 129
#define S_BOLD 130
#define E_BOLD 131
#define S_ITALIC 132
#define E_ITALIC 133
/*
* basic unit (b.u.) conversions. in nroff, all output is fixed spaced,
* at least in THIS nroff. so unit conversion to b.u. amount to 1 Em per
* character or 24 b.u. per character. thus 0.5i = 120 b.u. = 5 chars.
* everything is rounded up to the nearest Em. it is highly recommended
* to use inches for everything...
*
* to convert (say inches) to char spaces, do this:
*
* char_spaces = (int)(inches * (float) BU_INCH) / BU_EM;
*/
#define BU_INCH 240 /* 1.0i = 240 b.u. */
#define BU_CM 945/10 /* 1.0c = 240*50/127 b.u. */
#define BU_PICA 40 /* 1P = 240/6 b.u. */
#define BU_EM 24 /* 1m = 240/10 b.u. (10 char/inch) */
#define BU_EN 24 /* 1n = 240/10 b.u. */
#define BU_POINT 240/72 /* 1p = 240/72 b.u. */
#define BU_BU 1 /* 1 = 1 b.u. */
/*
* The parameter values selected for macro definitions are somewhat
* arbitrary. MACBUF is the storage area for both macro names and
* definitions. Since macro processing is handled by pushing back
* the expansion into the input buffer, the longest possible expansion
* would be MAXLINE characters. Allowing for argument expansion,
* MXMLEN was chosen slightly less than MAXLINE. It is assumed that
* most macro definitions will not exceed 20 characters, hence MXMDEF
* of 150.
*/
#define MXMDEF 150 /* max no. of macro definitions */
#define MACBUF 32000 /*100000*//* macro definition buffer size (32000) */
#define MXMLEN 1000 /* max length of each macro definition (250) */
#define MNLEN 10 /* max length of macro name */
#define MAXREGS 100 /* max number of registers (2-char) */
#define MAXPBB 5000 /* size of push back buffer */
/*
* number registers
*/
#define RF_READ 0x0001 /* register flags */
#define RF_WRITE 0x0002
struct regs
{
char rname[4]; /* 2-char register name */
int rauto; /* autoincrement value */
int rval; /* current value of the register */
int rflag; /* register flags */
char rfmt; /* register format (1,a,A,i,I,...) */
};
/*
* control parameters for nroff
*/
struct docctl
{
int fill; /* fill if YES, init = YES */
int dofnt; /* handle font change, init = YES */
int lsval; /* current line spacing, init = 1 */
int inval; /* current indent, >= 0, init = 0 */
int rmval; /* current right margin, init = 60 */
int llval; /* current line length, init = 60 */
int ltval; /* current title length, init = 60 */
int tival; /* current temp indent, init = 0 */
int ceval; /* number of lines to center, init = 0 */
int ulval; /* number of lines to underline, init = 0 */
int cuval; /* no lines to continuously uline, init = 0 */
int juval; /* justify if YES, init = YES */
int adjval; /* adjust type, init = ADJ_BOTH */
int boval; /* number of lines to bold face, init = 0 */
int bsflg; /* can output contain '\b', init = FALSE */
int prflg; /* print on or off, init = TRUE */
int sprdir; /* direction for spread(), init = 0 */
int flevel; /* nesting depth for source cmd, init = 0 */
int lastfnt; /* previous used font */
int thisfnt; /* current font, init = 1 (1=R,2=I,3=B,4=S) */
int escon; /* whether esc parsing is on, init = YES */
int nr[26]; /* number registers */
int nrauto[26]; /* number registers auto increment */
char nrfmt[26]; /* number registers formats, init = '1' */
/* input code how printed */
/* 1 '1' 1,2,3,... */
/* a 'a' a,b,c,...,aa,bb,cc,... */
/* A 'A' A,B,C,...,AA,BB,CC,... */
/* i 'i' i,ii,iii,iv,v... */
/* I 'I' I,II,III,IV,V... */
/* 01 2 01,02,03,... */
/* 001 3 001,002,003,... */
/* 0..1 8 00000001,00000002,... */
char pgchr; /* page number character, init = '%' */
char cmdchr; /* command character, init = '.' */
char escchr; /* escape char, init = '\' */
char nobrchr; /* nobreak char, init = '\'' */
};
/*
* page control parameters
*/
struct page
{
int curpag; /* current output page number, init =0 */
int newpag; /* next output page number, init = 1 */
int lineno; /* next line to be printed, init = 0 */
int plval; /* page length in lines, init = 66 */
int m1val; /* margin before and including header */
int m2val; /* margin after header */
int m3val; /* margin after last text line */
int m4val; /* bottom margin, including footer */
int bottom; /* last live line on page
= plval - m3val - m4val */
int offset; /* page offset from left, init = 0 */
int frstpg; /* first page to print, init = 0 */
int lastpg; /* last page to print, init = 30000 */
int ehlim[2]; /* left/right margins for headers/footers */
int ohlim[2]; /* init = 0 and PAGEWIDTH */
int eflim[2];
int oflim[2];
char ehead[MAXLINE]; /* top of page title, init = '\n' */
char ohead[MAXLINE];
char efoot[MAXLINE]; /* bottom of page title, init = '\n' */
char ofoot[MAXLINE];
};
/*
* forward refs from nroff
*/
/* main.c */
void debugMessage (const char *fmt, ...);
/* command.c */
void comand (char *p);
int set_ireg (const char *name, int val, int opt);
void set (int *param, int val, char type, int defval, int minval, int maxval);
/* low.c */
int ctod (char *p);
char *skipbl (char *p);
char *skipwd (char *p);
void nroffSpace (int n);
char *getfield (char *p, char *q, char delim);
int getwrd (char *src, char *dest);
int countesc (char *p);
int itoda (int value, char *p, int size);
int itoROMAN (int value, char *p, int size);
int itoroman (int value, char *p, int size);
int itoLETTER (int value, char *p, int size);
int itoletter (int value, char *p, int size);
void err_exit (int code);
/* text.c */
void initOutbuf (void);
void pfoot (void);
void phead (void);
void robrk (void);
void setPrinting (int val);
void skip (int n);
int strkovr (char *p, char *q);
void text (char *p);
/* strings.c */
void defstr (char *line);
/*
* Globals.
*/
extern struct docctl dc;
extern struct page pg;
extern struct regs rg[MAXREGS];
extern FILE *out_stream;
extern FILE *err_stream;
extern FILE *dbg_stream;
extern FILE *sofile[Nfiles+1];
extern int ignoring;
extern int hold_screen;
extern int debugging;
extern int stepping;
extern int mc_ing;
extern int mc_space;
extern char mc_char;
extern char tmpdir[];
extern char s_standout[];
extern char e_standout[];
extern char s_italic[];
extern char e_italic[];
extern char s_bold[];
extern char e_bold[];
extern char *dbgfile;
extern char *printer;
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define DEBUGGING(args) \
{ \
if (debugging) { \
debugMessage args; \
} \
}
#ifdef DEBUG
#define ASSERT(condition, args) \
{ \
if (!(condition)) { \
printf("%s:%d: assertion failed (%s): ",__FILE__,__LINE__,#condition);\
printf args; \
abort(); \
} \
}
#else
#define ASSERT(condition, args)
#endif
#endif /*NRO_H*/

18
usr.bin/nroff/nroff.rez Normal file
View File

@ -0,0 +1,18 @@
/*
* $Id: nroff.rez,v 1.1 1997/03/14 06:22:29 gdr Exp $
*/
#include "Types.Rez"
resource rVersion (0x1, purgeable3, nocrossbank) {
{ 1, 2, 0, /* version 1.2.0 */
release, /* development|alpha|beta|final|release */
0 /* non-final release number */
},
verBritain, /* close enough */
"nroff",
"Text Processing Typesetter\n"
"Devin Reade <gdr@myrias.com>\n"
"Canada"
};

194
usr.bin/nroff/strings.c Normal file
View File

@ -0,0 +1,194 @@
/*
* strings.c - String input/output processing for nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: strings.c,v 1.1 1997/03/14 06:22:29 gdr Exp $
*/
#ifdef __ORCAC__
segment "strings___";
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __GNO__
#include <err.h>
#else
#include "err.h"
#endif
#ifdef sparc
#include "sunos.h"
#endif
#include "nroff.h"
#include "macros.h"
static int colstr (const char *src, char *dest, size_t len);
/*
* defstr
*
* Define a string. top level, read from command line.
*
* we should read string without interpretation EXCEPT:
*
* 1) number registers are interpolated
* 2) strings indicated by \* are interpolated
* 3) arguments indicated by \$ are interpolated
* 4) concealed newlines indicated by \(newline) are eliminated
* 5) comments indicated by \" are eliminated
* 6) \t and \a are interpreted as ASCII h tab and SOH.
* 7) \\ is interpreted as backslash and \. is interpreted as a period.
*
* currently, we do only 3. a good place to do it would be here before
* putstr, after colstr...
*/
void
defstr (char *line) {
register char *q;
register int i;
static char name[MNLEN];
static char defn[MXMLEN+1];
name[0] = '\0';
defn[0] = '\0';
#ifdef BORK
fprintf(stderr, "DEBUG: %s:%d name = 0x%x\tdefn = 0x%x line=%s\n",
__FILE__, __LINE__, name, defn, line);
#endif
/*
* skip the .ds and get to the name...
*/
q = skipwd (line);
q = skipbl (q);
/*
* ok, name now holds the name. make sure it is valid (i.e. first
* char is alpha...). getwrd returns the length of the word.
*/
i = getwrd (q, name);
if (!name[0]) {
errx(-1, "missing or illegal string definition name");
}
/*
* truncate to 2 char max name.
*/
if (i > 2) {
name[2] = EOS;
}
/*
* skip the name to get to the string. it CAN start with a " to
* have leading blanks...
*/
q = skipwd (q);
q = skipbl (q);
/*
* read rest of line from input stream and collect string into
* temp buffer defn
*/
if ((i = colstr (q, defn, MXMLEN)) == ERR) {
errx(-1, "string definition too long");
}
/*
* store the string
*/
if (putstr (name, defn) == ERR) {
errx(-1, "string definition table full");
}
}
/*
* colstr
* Collect string definition from input stream
*/
static int
colstr (const char *src, char *dest, size_t len) {
const char *orgsrc;
char *orgdest, *destlimit;
orgsrc = src;
orgdest = dest;
destlimit = dest + len; /* don't let dest go past this pointer */
#ifdef BORK
fprintf(stderr,"DEBUG: %s:%d src=\"%s\"\n", __FILE__, __LINE__, src);
#endif
/*
* if there is a " here, we have leading blanks (skipbl in caller
* found it). just get past it...
*/
if (*src == '\"') {
src++;
}
while ((*src != '\n') && (*src != '\r') && (*src != '\0')
&& (dest < destlimit - 1)) {
/*
* If it's a comment, it ends terminates string collection
*/
if (*src == '\\' && *(src+1) == '\"') {
/*
* first back over any whitespace between the start of the
* comment and the last non-whitespace character preceeding
* the comment
*/
while (dest > orgdest && isspace(*dest)) {
--dest;
}
/* forward src until we hit newline or end of string */
while (*src != '\n' && *src != '\r' && *src != '\0') {
src++;
}
break;
}
/*
* stop at the newline...
*/
if (*src == '\n' || *src == '\r') {
break;
}
/*
* copy it
*/
*dest++ = *src++;
}
*dest = '\0';
/* did we attempt to go over the allowed length for dest? */
if (*src == '\0' || *src == '\n' || *src == '\r') {
return dest - orgdest;
} else {
return ERR;
}
}

849
usr.bin/nroff/text.c Normal file
View File

@ -0,0 +1,849 @@
#undef OLD_WAY
/*
* text.c - text output processing portion of nroff word processor
*
* adapted for atariST/TOS by Bill Rosenkranz 11/89
* net: rosenkra@hall.cray.com
* CIS: 71460,17
* GENIE: W.ROSENKRANZ
*
* original author:
*
* Stephen L. Browning
* 5723 North Parker Avenue
* Indianapolis, Indiana 46220
*
* history:
*
* - Originally written in BDS C;
* - Adapted for standard C by W. N. Paul
* - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
* - Heavily modified by Devin Reade to avoid memory trashing bugs.
*
* $Id: text.c,v 1.1 1997/03/14 06:22:29 gdr Exp $
*/
#ifdef __ORCAC__
segment "text______";
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __GNO__
#include <termcap.h>
#else
#include "termcap.h"
#endif
#include "nroff.h"
#include "io.h"
#include "escape.h"
/*
* output buffer control parameters
*/
static struct {
int outp; /* next avail char pos in outbuf, init = 0 */
int outw; /* width of text currently in buffer */
int outwds; /* number of words in buffer, init = 0 */
int lpr; /* output to printer, init = FALSE */
int outesc; /* number of escape char on this line */
char outbuf[MAXLINE];/* output of filled text */
} co;
static void bold (char *p0, char *p1, int size);
static void center (char *p);
static void expand (char *p0, char c, char *s);
static void justcntr (char *p, char *q, int *limit);
static void justleft (char *p, char *q, int limit);
static void justrite (char *p, char *q, int limit);
static void leadbl (char *p);
static void puttl (char *p, int *lim, int pgno);
static void putwrd (char *wrdbuf);
static void spread (char *p, int outp, int nextra, int outwds,int escapes);
static void underl (char *p0, char *p1, int size);
static int width (char *s);
static void do_mc (char *p);
/*
* text
* main text processing
*
* Pre: <line> contains the line we wish to process (and print)
* it is MAXLINE characters long, including the
* terminating NULL character.
*
* Post:
*/
void
text (char *line) {
register int i;
char wrdbuf[MAXLINE];
/*
* skip over leading blanks if in fill mode. we indent later.
* since leadbl does a robrk, do it if in .nf mode
*/
if (dc.fill == YES) {
if (*line == ' ' || *line == '\n' || *line == '\r') {
/* note that leadbl shifts <line> left as necessary */
leadbl (line);
}
} else {
robrk ();
}
/*
* expand escape sequences from <line> into <wrdbuf>
*/
expesc (line, wrdbuf, MAXLINE);
/*
* test for how to output
*/
if (dc.ulval > 0) {
/*
* underline (.ul)
*
* Because of the way underlining is handled,
* MAXLINE should be declared to be three times
* larger than the longest expected input line
* for underlining. Since many of the character
* buffers use this parameter, a lot of memory
* can be allocated when it may not really be
* needed. A MAXLINE of 180 would allow about
* 60 characters in the output line to be
* underlined (remember that only alphanumerics
* get underlined - no spaces or punctuation).
*/
underl (line, wrdbuf, MAXLINE);
--dc.ulval;
}
if (dc.cuval > 0) {
/*
* continuous underline (.cu)
*/
underl (line, wrdbuf, MAXLINE);
--dc.cuval;
}
if (dc.boval > 0) {
/*
* bold (.bo)
*/
bold (line, wrdbuf, MAXLINE);
--dc.boval;
}
if (dc.ceval > 0) {
/*
* centered (.ce)
*/
center (line);
do_mc (line);
put (line);
--dc.ceval;
} else if ((*line == '\r' || *line == '\n') && dc.fill == NO) {
/*
* all blank line
*/
do_mc (line);
put (line);
} else if (dc.fill == NO) {
/*
* unfilled (.nf)
*/
do_mc (line);
put (line);
} else {
/*
* anything else...
*
* init escape char counter for this line...
*/
/* co.outesc = 0;*/
/*
* get a word and put it out. increment ptr to the next
* word.
*/
while ((i = getwrd (line, wrdbuf)) > 0) {
/* co.outesc += countesc (wrdbuf);*/
putwrd (wrdbuf);
line += i;
}
}
}
/*
* bold
* insert bold face text (by overstriking)
*/
static void
bold (register char *p0, register char *p1, int size)
{
register int i;
register int j;
j = 0;
for (i = 0; (p0[i] != '\n') && (j < size - 1); ++i)
{
if (isalpha (p0[i]) || isdigit (p0[i]))
{
p1[j++] = p0[i];
p1[j++] = '\b';
}
p1[j++] = p0[i];
}
p1[j++] = '\n';
p1[j] = EOS;
while (*p1 != EOS)
*p0++ = *p1++;
*p0 = EOS;
}
/*
* center
* center a line by setting tival
*/
static void
center (register char *p) {
int t;
t = (dc.rmval + dc.tival - width (p)) >> 1;
dc.tival = MAX(t, 0);
}
/*
* expand
* expand title buffer to include character string
*/
static void
expand (register char *p0, char c, register char *s) {
register char *p;
register char *q;
register char *r;
char tmp[MAXLINE];
p = p0;
q = tmp;
while (*p != EOS) {
if (*p == c) {
r = s;
while (*r != EOS) {
*q++ = *r++;
}
} else {
*q++ = *p;
}
++p;
}
*q = EOS;
strcpy (p0, tmp); /* copy it back */
}
/*
* justcntr
* center title text into print buffer
*/
static void
justcntr (register char *p, char *q, int *limit) {
register int len;
len = width (p);
q = &q[(limit[RIGHT] + limit[LEFT] - len) >> 1];
while (*p != EOS) {
*q++ = *p++;
}
}
/*
* justleft
* left justify title text into print buffer
*/
static void
justleft (register char *p, char *q, int limit) {
q = &q[limit];
while (*p != EOS) {
*q++ = *p++;
}
}
/*
* justrite
* right justify title text into print buffer
*/
static void
justrite (register char *p, char *q, int limit) {
register int len;
len = width (p);
q = &q[limit - len];
while (*p != EOS) {
*q++ = *p++;
}
}
/*
* leadbl
* delete leading blanks, set tival
*
* REVIEWED
*/
static void
leadbl (register char *p) {
register char *q;
register int i;
/*
* end current line and reset co struct
*/
robrk ();
/*
* skip spaces
*/
for (i = 0; p[i] == ' ' || p[i] == '\t'; ++i);
/*
* if not end of line, reset current temp indent
*/
if (p[i] != '\n' && p[i] != '\r') {
dc.tival = i;
}
/*
* shift string
*/
q = &p[i];
#ifdef DEBUG
i = 0;
#endif
while (*q) {
#ifdef DEBUG
i++;
ASSERT(i<MAXLINE, ("leadbl buffer overflow\n"));
#endif
*p++ = *q++;
}
*p = '\0';
}
/*
* pfoot
* put out page footer
*/
void
pfoot (void) {
if (dc.prflg == TRUE) {
skip (pg.m3val);
if (pg.m4val > 0) {
if ((pg.curpag % 2) == 0) {
puttl (pg.efoot, pg.eflim, pg.curpag);
} else {
puttl (pg.ofoot, pg.oflim, pg.curpag);
}
skip (pg.m4val - 1);
}
}
}
/*
* phead
* put out page header
*/
void
phead (void) {
pg.curpag = pg.newpag;
if (pg.curpag >= pg.frstpg && pg.curpag <= pg.lastpg) {
dc.prflg = TRUE;
} else {
dc.prflg = FALSE;
}
++pg.newpag;
set_ireg ("%", pg.newpag, 0);
if (dc.prflg == TRUE) {
if (pg.m1val > 0) {
skip (pg.m1val - 1);
if ((pg.curpag % 2) == 0) {
puttl (pg.ehead, pg.ehlim, pg.curpag);
} else {
puttl (pg.ohead, pg.ohlim, pg.curpag);
}
}
skip (pg.m2val);
}
/*
* initialize lineno for the next page
*/
pg.lineno = pg.m1val + pg.m2val + 1;
set_ireg ("ln", pg.lineno, 0);
}
/*
* puttl
* put out title or footer
*/
static void
puttl (register char *p, int *lim, int pgno) {
register int i;
char pn[8];
char t[MAXLINE];
char h[MAXLINE];
char delim;
itoda (pgno, pn, 6);
for (i = 0; i < MAXLINE; ++i) {
h[i] = ' ';
}
delim = *p++;
p = getfield (p, t, delim);
expand (t, dc.pgchr, pn);
justleft (t, h, lim[LEFT]);
p = getfield (p, t, delim);
expand (t, dc.pgchr, pn);
justcntr (t, h, lim);
p = getfield (p, t, delim);
expand (t, dc.pgchr, pn);
justrite (t, h, lim[RIGHT]);
for (i = MAXLINE - 4; h[i] == ' '; --i) {
h[i] = EOS;
}
h[++i] = '\n';
h[++i] = '\r';
h[++i] = EOS;
if (strlen (h) > 2) {
for (i = 0; i < pg.offset; ++i) {
PRCHAR2(' ', out_stream);
}
}
putlin (h, out_stream);
}
/*
* putwrd
* put word in output buffer
*/
static void
putwrd (register char *wrdbuf) {
register char *p0;
register char *p1;
int w;
int last;
int llval;
int nextra;
/*
* check if this word puts us over the limit
*/
w = width (wrdbuf);
last = strlen (wrdbuf) + co.outp;
llval = dc.rmval - dc.tival;
/* if (((co.outp > 0) && ((co.outw + w) > llval))*/
co.outesc += countesc (wrdbuf);
if (((co.outp > 0) && ((co.outw + w - co.outesc) > llval))
||(last > MAXLINE)) {
/*
* last word exceeds limit so prepare to break line, print
* it, and reset outbuf.
*/
last -= co.outp;
if (dc.juval == YES) {
nextra = llval - co.outw + 1;
/*
* Do not take in the escape char of the
* word that didn't fit on this line anymore
*/
co.outesc -= countesc (wrdbuf);
/*
* Check whether last word was end of
* sentence and modify counts so that
* it is right justified.
*/
if (co.outbuf[co.outp - 2] == ' ') {
--co.outp;
++nextra;
}
#ifdef OLD_WAY
spread (co.outbuf, co.outp - 1, nextra, co.outwds, co.outesc);
if ((nextra > 0) && (co.outwds > 1)) {
co.outp += (nextra - 1);
}
#if 0
if (co.outesc > 0) {
co.outp += co.outesc;
}
#endif /* 0 */
#else /* OLD_WAY */
spread (co.outbuf, co.outp - 1, nextra, co.outwds, co.outesc);
if ((nextra + co.outesc > 0) && (co.outwds > 1)) {
co.outp += (nextra + co.outesc - 1);
}
#endif
}
/*
* break line, output it, and reset all co members. reset
* esc count.
*/
robrk ();
co.outesc = countesc (wrdbuf);
}
/*
* copy the current word to the out buffer which may have been
* reset
*/
p0 = wrdbuf;
p1 = co.outbuf + co.outp;
while (*p0 != EOS) {
*p1++ = *p0++;
}
co.outp = last;
co.outbuf[co.outp++] = ' ';
co.outw += w + 1;
co.outwds += 1;
}
/*
* skip
* skips the number of lines specified by n.
*/
void
skip (register int n) {
register int i;
register int j;
if (dc.prflg == TRUE && n > 0) {
for (i = 0; i < n; ++i) {
/*
* handle blank line with changebar
*/
if (mc_ing == TRUE) {
for (j = 0; j < pg.offset; ++j) {
PRCHAR2(' ', out_stream);
}
for (j = 0; j < dc.rmval; ++j) {
PRCHAR2(' ', out_stream);
}
for (j = 0; j < mc_space; j++) {
PRCHAR2(' ', out_stream);
}
PRCHAR(mc_char, out_stream);
}
PRCHAR2('\n', out_stream);
#if 0
/* gdr: not required */
prchar ('\r', out_stream);
#endif
}
}
}
/*
* spread
* spread words to justify right margin
*/
static void
spread (register char *p, int outp, int nextra, int outwds, int escapes) {
register int i;
register int j;
register int nb;
register int ne;
register int nholes;
/*
* quick sanity check...
*/
#ifdef OLDWAY
if ((nextra <= 0) || (outwds <= 1)) {
return;
}
#else
if ((nextra + escapes < 1) || (outwds < 2)) {
return;
}
#endif
/*
* set up for the spread and do it...
*/
dc.sprdir = ~dc.sprdir;
#ifdef OLD_WAY
ne = nextra;
#else
ne = nextra + escapes;
#endif
nholes = outwds - 1; /* holes between words */
i = outp - 1; /* last non-blank character */
j = MIN(MAXLINE - 3, i + ne); /* leave room for CR,LF,EOS */
#if 0
j += escapes;
if (p[i-1] == 27) {
j += 2;
}
j = MIN(j, MAXLINE - 3);
#endif
while (i < j) {
p[j] = p[i];
if (p[i] == ' ') {
if (dc.sprdir == 0) {
nb = (ne - 1) / nholes + 1;
} else {
nb = ne / nholes;
}
ne -= nb;
--nholes;
for (; nb > 0; --nb) {
--j;
p[j] = ' ';
}
}
--i;
--j;
}
}
/*
* strkovr
* split overstrikes (backspaces) into seperate buffer
*/
int
strkovr (char *p, char *q) {
register char *pp;
int bsflg;
bsflg = FALSE;
pp = p;
while (*p != EOS) {
*q = ' ';
*pp = *p;
++p;
if (*p == '\b') {
if (*pp >= ' ' && *pp <= '~') {
bsflg = TRUE;
*q = *pp;
++p;
*pp = *p;
++p;
}
}
++q;
++pp;
}
*q++ = NEWLINE;
*q = *pp = EOS;
return bsflg;
}
/*
* underl
* underline a line
*/
static void
underl (register char *p0, register char *p1, int size) {
register int i;
register int j;
j = 0;
for (i = 0; (p0[i] != '\n') && (j < size - 1); ++i) {
if (p0[i] >= ' ' &&
p0[i] <= '~' &&
(isalpha (p0[i]) || isdigit (p0[i]) || dc.cuval > 0))
{
p1[j++] = '_';
p1[j++] = '\b';
}
p1[j++] = p0[i];
}
p1[j++] = '\n';
p1[j] = EOS;
while (*p1 != EOS) {
*p0++ = *p1++;
}
*p0 = EOS;
}
/*
* width
* compute width of character string
*/
static int
width (char *s) {
register int w;
w = 0;
for (; *s != '\0'; s++) {
ASSERT((*s != '\n' && *s != '\r'), ("\n"));
if ((*s >= 32) && (*s < 127)) {
++w;
} else if (*s == '\b' || *s == 128) {
--w;
}
/* ignore high-bit chars and other control chars */
}
return w;
}
/*
* do_mc
* add margin char (change bar) for .nf and .ce lines.
*
* filled lines handled in robrk(). blank lines (.sp) handled in skip().
* note: robrk() calls this routine, too.
*/
static void
do_mc (char *p) {
register char *ps;
register int nspaces;
register int i;
register int has_cr;
register int has_lf;
int len;
int nesc;
if (mc_ing == FALSE) {
return;
}
len = strlen (p);
/*
* get to the end...
*/
ps = p;
while (*ps) {
ps++;
}
/*
* check for cr and lf
*/
ps--;
has_lf = 0;
has_cr = 0;
while (ps >= p && (*ps == '\r' || *ps == '\n')) {
if (*ps == '\n') {
has_lf++;
} else {
has_cr++;
}
len--;
ps--;
}
if (has_lf < has_cr) {
has_lf = has_cr;
} else if (has_cr < has_lf) {
has_cr = has_lf;
}
/*
* remove any trailing blanks here
*/
while (ps >= p && *ps == ' ') {
ps--;
len--;
}
*++ps = EOS;
/*
* add trailing spaces for short lines. count escapes, subtract
* from len. use rmval for rigth margin (minus tival which is
* added later in put).
*/
nesc = countesc (p);
len -= nesc;
nspaces = dc.rmval - dc.tival - len;
for (i = 0; i < nspaces; i++, ps++) {
*ps = ' ';
}
/*
* add the bar...
*/
for (i = 0; i < mc_space; i++, ps++) {
*ps = ' ';
}
*ps++ = mc_char;
/*
* replace cr, lf, and EOS
*/
while (has_lf--) {
*ps++ = '\r';
*ps++ = '\n';
}
*ps = EOS;
return;
}
void
initOutbuf (void) {
co.outp = 0;
co.outw = 0;
co.outwds = 0;
co.lpr = FALSE;
co.outesc = 0;
memset(co.outbuf, EOS, MAXLINE);
#if 0
for (i = 0; i < MAXLINE; ++i) {
co.outbuf[i] = EOS;
}
#endif
}
/*
* robrk
*
* End current filled line. References and modifies globals:
* co
*/
void
robrk (void) {
if (co.outp > 0) {
/*
* handle margin char (change bar) here for all filled lines
*/
ASSERT(MAXLINE - co.outp > 2, ("output buffer overrun: >%d:%d:%d<\n",
MAXLINE, co.outp, MAXLINE- co.outp));
co.outbuf[co.outp] = '\r';
co.outbuf[co.outp+1] = '\n';
co.outbuf[co.outp+2] = EOS;
do_mc (co.outbuf);
put (co.outbuf);
}
co.outp = 0;
co.outw = 0;
co.outwds = 0;
co.outesc = 0;
}
void
setPrinting(int val) {
co.lpr = val;
}

335
usr.bin/nroff/tmac.an Normal file
View File

@ -0,0 +1,335 @@
.\" set this non-zero to turn on debugging
.nr Z 1
.\" **************************************************************************
.\"
.\" -man package for nroff. not quite unix(tm), but adequate/working...
.\"
.\" usage: nroff -man file [...]
.\"
.\" included here are: TH, Th, SH, SS, IP, PP, LP, RS, RP, RE, I, B
.\"
.\" v1.10 7/22/90 rosenkra@convex.com (Bill Rosenkranz)
.\" freely distributable (no copyright, etc.)
.\"
.\" **************************************************************************
.\"
.\" some perdefined strings (quotes, etc)
.\"
.ds S s
.ds ` "`
.ds ' "'
.ds lq ""
.ds rq ""
.\"
.\" these are various predefined date and time strings
.\"
.\" DW day-of-week:
.if \n(dw=1 .ds DW "Sun
.if \n(dw=2 .ds DW "Mon
.if \n(dw=3 .ds DW "Tue
.if \n(dw=4 .ds DW "Wed
.if \n(dw=5 .ds DW "Thu
.if \n(dw=6 .ds DW "Fri
.if \n(dw=7 .ds DW "Sat
.\" Dy month day:
.if \n(mo=1 .ds Dy "Jan \n(dy
.if \n(mo=2 .ds Dy "Feb \n(dy
.if \n(mo=3 .ds Dy "Mar \n(dy
.if \n(mo=4 .ds Dy "Apr \n(dy
.if \n(mo=5 .ds Dy "May \n(dy
.if \n(mo=6 .ds Dy "Jun \n(dy
.if \n(mo=7 .ds Dy "Jul \n(dy
.if \n(mo=8 .ds Dy "Aug \n(dy
.if \n(mo=9 .ds Dy "Sep \n(dy
.if \n(mo=10 .ds Dy "Oct \n(dy
.if \n(mo=11 .ds Dy "Nov \n(dy
.if \n(mo=12 .ds Dy "Dec \n(dy
.ds Da "\n(hh:\n(mm:\n(ss \n(mo/\n(dy/\n(yr
.ds Yr "19\n(yr
.ds DY "\*(Dy, \*(Yr
.ds TM "\n(hh:\n(mm:\n(ss
.ds DA "\*(TM \*(DY
.ds CT "\*(DW \*(Dy \*(TM 19\n(yr
.\"
.\" they look like this:
.\"
.\" DW Sun
.\" Dy Mar 4
.\" DY Mar 4, 1990
.\" Yr 1990
.\" TM 16:34:00
.\" DA 16:34:00 Mar 4, 1990
.\" Da 16:34:00 2/4/90
.\" CT Sun Mar 4 16:34:00 1990 like ctime(2)
.\"
.\" **************************************************************************
.\"
.\" startup stuff...
.\"
.\" X is number register used internally here. it is initially 0. it gets
.\" set to 1 in TH if ONLINE is set. it is used in the EX macro to force
.\" an immediate exit at the end.
.\"
.in 0.0i
.po 0.0i
.lt 7.2i
.ll 7.2i
.m1 3
.m2 3
.m3 3
.m4 3
.nr X 0
.\"
.\" **************************************************************************
.\"
.\" MACROS...
.\"
.\" ----------------------------------------------------------------------- TH
.\" main page heading
.\"
.\" fields are usually: 1-name, 2-section, 3-section name, 4-version, 5-date
.\" 1,2,3 are on header, 4,5 and page on footer. empty strings are skipped
.\" by making the arg "". this must be first! there is an extra field at the
.\" end ($6) which, if "ONLINE", prints the page without page breaks (i.e.
.\" headers/footers).
.\"
.\" $1 $2 $3
.\" | | |
.\" v v v
.\" NAME (1) Section NAME (1)
.\" ...
.\" Version Date Page n
.\" ^ ^
.\" | |
.\" $4 $5
.\"
.\" .TH NAME 1 "Commands" "Version 1.0" "7 March 1990" ["ONLINE"]
.\"
.\" there is an extension here: if the 6th argument is "ONLINE" then the
.\" resultant output does not have any headers/footers. this is useful for
.\" making manpages for online use.
.\"
.de TH
.\" define Se as default chapter name based on input chapter number
.if $2=0 .ds Se "General Information
.if $2=1 .ds Se "Commands and Applications
.if $2=2 .ds Se "System Calls
.if $2=3 .ds Se "Library Calls
.if $2=4 .ds Se "Hardware and Special Files
.if $2=5 .ds Se "File Formats
.if $2=6 .ds Se "Games
.if $2=7 .ds Se "Miscellaneous
.if $2=8 .ds Se "Administation Commands
.\" if the 6th arg is "ONLINE", set up for online docs output (no head/foot)
.if !"$6"ONLINE" .pl 66
.if "$6"ONLINE" .m1 0
.if "$6"ONLINE" .m2 0
.if "$6"ONLINE" .m3 0
.if "$6"ONLINE" .m4 0
.if !"$6"ONLINE" .tl |$1 ($2)|$3|$1 ($2)|
.if !"$6"ONLINE" .if "$3"" .tl |$1 ($2)|\*(Se|$1 ($2)|
.if !"$6"ONLINE" .fo |$4|$5|Page %|
.if !"$6"ONLINE" .if "$4"" .fo |\*(CT|$5|Page %|
.\" this is used by macro EX (exit)
.if "$6"ONLINE" .nr X 1
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
..
.\" ----------------------------------------------------------------------- Th
.\" alternate main page heading
.\"
.\" this prints no header/footer so it is good for creating online docs
.\" for man(1). it ignores all args.
.\"
.\" .Th NAME 1
.\"
.de Th
.m1 0
.m2 0
.m3 0
.m4 0
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
.nr X 1
..
.de UC
.if t .ds ]W GNO/ME Version 1.0
..
.\" ----------------------------------------------------------------------- EX
.\" exit NOW! (no extra space at end of document)
.\"
.de EX
.if \nX=1 .sp
.if \nX=1 .ex
..
.\" ----------------------------------------------------------------------- RS
.\" start relative indent
.\"
.de RS
.br
.\" change to 0.5i for "normal" nroff output...
.in +0.8i
..
.\" ----------------------------------------------------------------------- RE
.\" end relative indent
.\"
.de RE
.br
.\" change to 0.5i for "normal" nroff output...
.in -0.8i
..
.\" ----------------------------------------------------------------------- TP
.\" indented paragraph with tag (no clue what the difference is)
.\"
.de TP
.IP
.\" .if \n(.$ \{ $1 $2 \}
.\" .if !\n(.$ \{ \fBHAS NO ARGS\fR \}
..
.\" ----------------------------------------------------------------------- IP
.\" indented paragraph with tag (from this line)
.\"
.de IP
.br
.sp 1
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
\&$1 $2 $3 $4 $5 $6 $7 $8 $9
.br
.\" change to 0.5i for "normal" nroff output...
.in +0.8i
..
.\" ----------------------------------------------------------------------- HP
.\" indented paragraph without tag (from this line)
.\"
.de HP
.br
.sp 1
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
.in +0.8i
..
.\" ----------------------------------------------------------------------- RP
.\" relative indented paragraph with tag. MUST end with .RE
.\"
.de RP
.br
.sp 1
.\".if !\\n(.i>8 .in 0.8i
\&$1 $2 $3 $4 $5 $6 $7 $8 $9
.br
.\" change to 0.5i for "normal" nroff output...
.in +0.8i
..
.\" ----------------------------------------------------------------------- pp
.\" start a new indented paragraph
.\"
.de pp
.sp 1
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
.ti +0.8i
..
.\" ----------------------------------------------------------------------- PP
.\" start a new unindented paragraph
.\"
.de PP
.sp 1
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
..
.\" ----------------------------------------------------------------------- LP
.\" start a new unindented paragraph (same as PP)
.\"
.de LP
.sp 1
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
..
.\" ----------------------------------------------------------------------- SH
.\" main section heading
.\"
.de SH
.sp 1
.ne 3
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
.ti -0.8i
.\".bo
\&$1 $2 $3 $4 $5 $6 $7 $8 $9
.br
..
.\" ----------------------------------------------------------------------- SS
.\" subsection heading, same indent
.\"
.de SS
.sp 1
.ne 3
.\" change to 0.5i for "normal" nroff output...
.in 0.8i
.\".bo
\&$1 $2 $3 $4 $5 $6 $7 $8 $9
.sp
..
.\" ----------------------------------------------------------------------- I
.\" italic text (must handle at least 2 args)
.\"
.de I
\&\fI$1\fR$2
..
.\" ----------------------------------------------------------------------- B
.\" bold text (must handle at least 2 args)
.\"
.de B
\&\fB$1\fR$2
..
.\" ----------------------------------------------------------------------- R
.\" Roman text
.\"
.de R
\&\fR$1$2
..
.\" ----------------------------------------------------------------------- IR
.\" alternate italic and Roman text (must handle at least 6 args)
.\"
.de IR
\&\fI$1\fR$2\fI$3\fR$4\fI$5\fR$6
..
.\" ----------------------------------------------------------------------- RI
.\" alternate Roman and italic text (must handle at least 6 args)
.\"
.de RI
\&\fR$1\fI$2\fR$3\fI$4\fR$5\fI$6\fR
..
.\" ----------------------------------------------------------------------- BR
.\" alternate bold and Roman text (must handle at least 6 args)
.\"
.de BR
\&\fB$1\fR$2\fB$3\fR$4\fB$5\fR$6
..
.\" ----------------------------------------------------------------------- RB
.\" alternate Roman and bold text (must handle at least 6 args)
.\"
.de RB
\&\fR$1\fB$2\fR$3\fB$4\fR$5\fB$6\fR
..
.\" ----------------------------------------------------------------------- SM
.\" small text
.\"
.de SM
\&\fB$1\fR
..
.\" ----------------------------------------------------------------------- IX
.\" make index entry (ignored by this nroff...)
.\"
.de IX
..
.\" ----------------------------------------------------------------------- }D
.\" debug. use (e.g. print current indent):
.\"
.\" .}D .br
.\" .}D "** DEBUG ** before RS \n(.i"
.\"
.de }D
.if \nZ>0 \&$1
..

406
usr.bin/nroff/tmac.s Normal file
View File

@ -0,0 +1,406 @@
.\" set this non-zero to turn on debugging
.nr Z 0
.\" **************************************************************************
.\"
.\" partial -ms package for nroff. macros for simple paper/report formats
.\"
.\" usage: nroff -ms file [...]
.\"
.\" included here are:
.\"
.\" TL, AU, AI, AB, AE, SH, NH, PP, LP, QP, XP, RS, RE, IP, I, B, R
.\"
.\" extensions include:
.\"
.\" TI (temp indent), EX (exit NOW)
.\"
.\" includes somewhat kludgy support for XS, XA, XE, PX (table of contents)
.\"
.\" v1.10 7/22/90 rosenkra@convex.com (Bill Rosenkranz)
.\" freely distributable (no copyright, etc.)
.\"
.\" **************************************************************************
.\"
.\" some perdefined strings (Quote, Unquote, dash, footer parts, etc):
.\"
.ds Q ""
.ds U ""
.ds - --
.ds CF "ImPoSsIbLe
.ds LF "\0
.ds RF "\0
.\"
.\" these are various predefined date and time strings
.\"
.\" DW day-of-week:
.if \n(dw=1 .ds DW "Sun
.if \n(dw=2 .ds DW "Mon
.if \n(dw=3 .ds DW "Tue
.if \n(dw=4 .ds DW "Wed
.if \n(dw=5 .ds DW "Thu
.if \n(dw=6 .ds DW "Fri
.if \n(dw=7 .ds DW "Sat
.\" MO month:
.if \n(mo=1 .ds MO "January
.if \n(mo=2 .ds MO "February
.if \n(mo=3 .ds MO "March
.if \n(mo=4 .ds MO "April
.if \n(mo=5 .ds MO "May
.if \n(mo=6 .ds MO "June
.if \n(mo=7 .ds MO "July
.if \n(mo=8 .ds MO "August
.if \n(mo=9 .ds MO "September
.if \n(mo=10 .ds MO "October
.if \n(mo=11 .ds MO "November
.if \n(mo=12 .ds MO "December
.\" make some composites:
.ds Dy "\*(MO \n(dy
.ds Da "\n(hh:\n(mm:\n(ss \n(mo/\n(dy/\n(yr
.ds Yr "19\n(yr
.ds dY "\*(Dy, \*(Yr
.ds DY "\n(dy \*(MO \*(Yr
.ds TM "\n(hh:\n(mm:\n(ss
.ds DA "\*(TM \*(DY
.ds CT "\*(DW \*(Dy \*(TM 19\n(yr
.\"
.\" they look like this:
.\"
.\" DW Sun
.\" MO March
.\" Dy March 4
.\" dY March 4, 1990
.\" DY 4 March 1990 <--- "normal" nroff form
.\" Yr 1990
.\" TM 16:34:00
.\" DA 16:34:00 March 4, 1990
.\" Da 16:34:00 2/4/90
.\" CT Sun March 4 16:34:00 1990 almost like ctime(2)
.\"
.\" **************************************************************************
.\"
.\" startup stuff...
.\"
.pl 66
.ll 6.0i
.lt 6.0i
.m1 3
.m2 2
.m3 3
.m4 3
.\" no header line on first page! (set back in AB, SH, NH, LP, PP, QP)
.tl ||||
.\" this is the default footer (date, centered) unless string CF is defined
.fo ||\*(DY||
.\" these are for NH numbering (up to 5 levels, a la sun, X holds level)
.nr A 0 1
.af A 1
.nr B 0 1
.af B 1
.nr C 0 1
.af C 1
.nr D 0 1
.af D 1
.nr E 0 1
.af E 1
.nr X 1 1
.\"
.\" **************************************************************************
.\"
.\" MACROS...
.\"
.\" ---------------------------------------------------------------------- TL
.\" title for document (optional)
.\"
.de TL
.sp 4
.ce 1000
.\" reset footer. you MUST define CF, even to blank, to get the others!
.if !"\*(CF"ImPoSsIbLe" .fo |\*(LF|\*(CF|\*(RF|
..
.\" ---------------------------------------------------------------------- AU
.\" author(s) (optional, requires .TL)
.\"
.de AU
.sp 2
..
.\" ---------------------------------------------------------------------- AI
.\" author's institution (optional, requires .TL)
.\"
.de AI
.sp 1
..
.\" ---------------------------------------------------------------------- AB
.\" abstract (optional, requires .TL, .AE)
.\"
.de AB
.br
.sp 2
.\" check for arg to AB. can be "no" or something like "SUMMARY". if "no",
.\" no title above the abstract
.if !"$1"no" .if "$1"" ABSTRACT
.if !"$1"no" .if !"$1"" $1
.if !"$1"no" .sp 1
.\" set new line length...
.ce 0
.ll 5.5i
.in 0.5i
.tl ||- % -||
..
.\" ---------------------------------------------------------------------- AE
.\" abstract end (optional, requires .TL)
.\"
.de AE
.br
.sp 1
.\" reset...
.ce 0
.in 0.0i
.ll 6.0i
..
.\" ----------------------------------------------------------------------- SH
.\" section heading, no number (optional)
.\"
.de SH
.\" reset...
.ll 6.0i
.in 0.0i
.tl ||- % -||
.\" see note in TL
.if !"\*(CF"ImPoSsIbLe" .fo |\*(LF|\*(CF|\*(RF|
.br
.ce 0
.sp 2
.ne 4
.\" section title goes here, fill mode only so far...
..
.\" ---------------------------------------------------------------------- NH
.\" numbered section heading. arg (required) is the section level.
.\" this would be MUCH simpler if the .if command supported "{...}". there is
.\" a bug in nroff. i does not set the .$ number register correctly (number of
.\" args for the current macro). that is the reason why level 1 must be set.
.\"
.de NH
.\" do everything from SH...
.SH
.\" if ".NH 0", reset numbering
.if $1=0 .nr A 1 1
.if $1=0 .nr B 0 1
.if $1=0 .nr C 0 1
.if $1=0 .nr D 0 1
.if $1=0 .nr E 0 1
.if $1=0 .nr X 1 1
.\" level 1 (two types here: ".NH" and ".NH 1"):
.\" once .$ num reg is fixed, these 5 should be: .if \n(.$=0 .nr A +1 etc.
.if "$1"" .nr A +1
.if "$1"" .nr B 0 1
.if "$1"" .nr C 0 1
.if "$1"" .nr D 0 1
.if "$1"" .nr E 0 1
.if "$1"" .nr X 1 1
.if "$1"1" .nr A +1
.if "$1"1" .nr B 0 1
.if "$1"1" .nr C 0 1
.if "$1"1" .nr D 0 1
.if "$1"1" .nr E 0 1
.if "$1"1" .nr X 1 1
.\" level 2 (increment B, reset lower levels):
.if "$1"2" .nr B +1
.if "$1"2" .nr C 0 1
.if "$1"2" .nr D 0 1
.if "$1"2" .nr E 0 1
.if "$1"2" .nr X 2 1
.\" level 3 (increment C, reset lower levels):
.if "$1"3" .nr C +1
.if "$1"3" .nr D 0 1
.if "$1"3" .nr E 0 1
.if "$1"3" .nr X 3 1
.\" level 4 (increment D, reset lower levels):
.if "$1"4" .nr D +1
.if "$1"4" .nr E 0 1
.if "$1"4" .nr X 4 1
.\" level 5 (increment E, no more lower levels!):
.if "$1"5" .nr E +1
.if "$1"5" .nr X 5 1
.\" print out the section number now, depending on current level...
.if \nX=1 \nA.
.if \nX=2 \nA.\nB.
.if \nX=3 \nA.\nB.\nC.
.if \nX=4 \nA.\nB.\nC.\nD.
.if \nX=5 \nA.\nB.\nC.\nD.\nE.
.\" section title goes here...
..
.\" ----------------------------------------------------------------------- LP
.\" start a new left block paragraph (either .LP or .PP required)
.\"
.de LP
.br
.\" reset...
.tl ||- % -||
.ce 0
.sp 1
.ll 6.0i
.in 0.0i
..
.\" ----------------------------------------------------------------------- PP
.\" start a new indented paragraph (either .LP or .PP required)
.\"
.de PP
.\" do everything for LP, then make a temp indent...
.LP
.ti +0.5i
..
.\" ----------------------------------------------------------------------- XP
.\" start a new extended paragraph (bibliography)
.\"
.de XP
.br
.\" reset...
.tl ||- % -||
.ce 0
.sp 1
.ll 6.0i
.in 0.5i
.ti -0.5i
..
.\" ----------------------------------------------------------------------- QP
.\" start a new quoted paragraph (indented and shorter)
.\"
.de QP
.br
.tl ||- % -||
.ce 0
.sp 1
.\" set new line length, indent. PP, LP, SH, and NH reset
.ll 6.0i
.in 0.0i
.ll -0.5i
.in +0.5i
..
.\" ----------------------------------------------------------------------- IP
.\" indented paragraph with tag (relative)
.\"
.de IP
.br
.tl ||- % -||
.ce 0
.sp 1
.if \n(.i>4 .in -0.5i
.in +0.5i
.}D "***DEBUG IP: indent before tag is: \n(.i"
.}D .br
.if !"$1"" .ti -0.5i
.if !"$1"" \&$1
.if !"$1"" .br
.}D "***DEBUG IP: indent after tag is: \n(.i"
..
.\" ----------------------------------------------------------------------- RS
.\" start relative indent (requires .RE)
.\"
.de RS
.ce 0
.br
.\" if there is arg, use that as indent, otherwise use +5
.if \n(.$>0 .in +$1
.if \n(.$=0 .in +0.5i
.}D "***DEBUG RS: indent after RS is: \n(.i"
.}D .br
..
.\" ----------------------------------------------------------------------- RE
.\" end relative indent
.\"
.de RE
.ce 0
.br
.\" if there is arg, use that as unindent, otherwise use -5
.if \n(.$>0 .in -$1
.if \n(.$=0 .in -0.5i
.if \n(.i<5 .in 0.0i
.}D "***DEBUG RE: indent after RE is: \n(.i"
.}D .br
..
.\" ----------------------------------------------------------------------- XS
.\" table of contents start
.\"
.de XS
.bp
.ce 1
Table of Contents
.ce 0
.ll 8.0i
.sp 1
.\" \&123456789012345678901234567890123456789012345678901234567890
\&NOTE: add/del "dots" until line ends here ---------------->| (del this line)
.br
.\" save the page number...
.ds Xx "$1
.\" first entry goes here...
..
.\" ----------------------------------------------------------------------- XE
.\" table of contents end
.\"
.de XE
.\" dump last page number...
\&\0........................... \*(Xx
.br
..
.\" ----------------------------------------------------------------------- XA
.\" subsequent table of contents entry
.\"
.de XA
.\" dump last page number...
\&\0........................... \*(Xx
.br
.\" save next page number...
.ds Xx "$1
.\" next entry goes here...
..
.\" ----------------------------------------------------------------------- PX
.\" print table of contents
.\"
.de PX
.\" this is a NOP without diversions...
.ll 6.0i
..
.\" ----------------------------------------------------------------------- TI
.\" temporary indent
.\"
.de TI
.ce 0
.ti +0.5i
..
.\" ----------------------------------------------------------------------- EX
.\" exit NOW! (no extra space at end of document)
.\"
.de EX
.sp
.ex
..
.\" ----------------------------------------------------------------------- I
.\" italic text
.\"
.de I
\&\fI
.if !"$1"" $1\fR$2
..
.\" ----------------------------------------------------------------------- B
.\" bold text
.\"
.de B
\&\fB
.if !"$1"" $1\fR$2
..
.\" ----------------------------------------------------------------------- R
.\" Roman (normal) text
.\"
.de R
\&\fR
..
.\" ----------------------------------------------------------------------- }D
.\" debug. use (e.g. print current indent):
.\"
.\" .}D .br
.\" .}D "** DEBUG ** before RS \n(.i"
.\"
.de }D
.if \nZ>0 \&$1
..

167
usr.bin/nroff/unix/err.c Normal file
View File

@ -0,0 +1,167 @@
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "err.h"
#if 0
extern char *__progname; /* Program name, from crt0. */
#else
static char *__progname = "nroff";
#endif
static FILE *err_file; /* file to use for error output */
static void (*err_exit)(int);
extern void iic_error(int, const char *, ...);
void
err_set_file(void *fp)
{
if (fp)
err_file = fp;
else
err_file = stderr;
}
void
err_set_exit(void (*ef)(int))
{
err_exit = ef;
}
void
err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verr(eval, fmt, ap);
va_end(ap);
}
void
verr(int eval, const char *fmt, va_list ap)
{
int sverrno;
sverrno = errno;
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL) {
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, ": ");
}
(void)fprintf(err_file, "%s\n", strerror(sverrno));
if(err_exit)
err_exit(eval);
exit(eval);
}
void
errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrx(eval, fmt, ap);
va_end(ap);
}
void
verrx(int eval, const char *fmt, va_list ap)
{
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL)
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, "\n");
if (err_exit)
err_exit(eval);
exit(eval);
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarn(fmt, ap);
va_end(ap);
}
void
vwarn(const char *fmt, va_list ap)
{
int sverrno;
sverrno = errno;
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL) {
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, ": ");
}
(void)fprintf(err_file, "%s\n", strerror(sverrno));
}
void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
void
vwarnx(const char *fmt, va_list ap)
{
if (! err_file)
err_set_file((FILE *)0);
(void)fprintf(err_file, "%s: ", __progname);
if (fmt != NULL)
(void)vfprintf(err_file, fmt, ap);
(void)fprintf(err_file, "\n");
}

12
usr.bin/nroff/unix/err.h Normal file
View File

@ -0,0 +1,12 @@
#include <stdarg.h>
void err_set_file(void *fp);
void err_set_exit(void (*ef)(int));
void err(int eval, const char *fmt, ...);
void verr(int eval, const char *fmt, va_list ap);
void errx(int eval, const char *fmt, ...);
void verrx(int eval, const char *fmt, va_list ap);
void warn(const char *fmt, ...);
void vwarn(const char *fmt, va_list ap);
void warnx(const char *fmt, ...);
void vwarnx(const char *fmt, va_list ap);

38
usr.bin/nroff/unix/int.c Normal file
View File

@ -0,0 +1,38 @@
/*
* This is an interface file for use with Insight.
*
* $Id: int.c,v 1.1 1997/03/14 06:22:27 gdr Exp $
*/
#include <stdarg.h>
#include "err.h"
void
verr(int eval, const char *fmt, va_list ap)
{
iic_error(USER_ERROR, "verr traceback");
verr(eval, fmt, ap);
}
void
verrx(int eval, const char *fmt, va_list ap)
{
iic_error(USER_ERROR, "verrx traceback");
verrx(eval, fmt, ap);
}
void
vwarn(const char *fmt, va_list ap)
{
iic_error(USER_ERROR, "dummy traceback");
vwarn(fmt, ap);
}
void
vwarnx(const char *fmt, va_list ap)
{
iic_error(USER_ERROR, "dummy traceback");
vwarnx(fmt, ap);
}

View File

@ -0,0 +1,19 @@
#ifdef SUNOS4
#ifdef FILE
int _filbuf(FILE *);
int _flsbuf(unsigned char, FILE *);
int fclose (FILE *);
int fflush (FILE *);
int fprintf(FILE *, const char *, ...);
#endif
#ifdef ITIMER_REAL
time_t time (time_t *);
#endif
int printf(const char *, ...);
int tolower (int);
#endif /* SUNOS4 */

View File

@ -0,0 +1,10 @@
extern char PC, *BC, *UP;
extern short ospeed;
int tgetent (char *bp, char *name);
int tgetnum (char *id);
int tgetflag (char *id);
char * tgetstr (char *id, char **area);
char * tgoto (char *cm, int destcol, int destline);
int tputs (char *cp, int affcnt, int (*outc)(char));