mkid 06/11 (identifier cross reference tool)
Tom Horsley
tom at ssd.csd.harris.com
Thu Dec 13 01:44:12 AEST 1990
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 6 (of 11)."
# Contents: getscan.c scan-c.c
# Wrapped by tom at hcx2 on Wed Dec 12 07:21:57 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'getscan.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'getscan.c'\"
else
echo shar: Extracting \"'getscan.c'\" \(7141 characters\)
sed "s/^X//" >'getscan.c' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
Xstatic char sccsid[] = "@(#)getscan.c 1.1 86/10/09";
X
X#include <stdio.h>
X#include <string.h>
X#include <id.h>
X#include <ctype.h>
X#include <extern.h>
X
Xchar *getLanguage();
Xchar *(*getScanner())();
Xvoid setScanArgs();
X
Xstatic struct sufftab *suffSlot();
Xstatic struct langtab *langSlot();
Xstatic void sorryNoScan();
X
Xvoid setAdaArgs(lang) { sorryNoScan(lang); }
Xchar *getAdaId() { setAdaArgs("ada"); return NULL; }
X
Xvoid setPascalArgs(lang) { sorryNoScan(lang); }
Xchar *getPascalId() { setPascalArgs("pascal"); return NULL; }
X
Xvoid setLispArgs(lang) { sorryNoScan(lang); }
Xchar *getLispId() { setLispArgs("lisp"); return NULL; }
X
Xstruct langtab {
X struct langtab *lt_next;
X char *lt_name;
X char *(*lt_getid)();
X void (*lt_setargs)();
X char *lt_filter;
X};
X
Xstruct sufftab {
X struct sufftab *st_next;
X char *st_suffix;
X struct langtab *st_lang;
X};
X
X
Xstruct langtab langtab[] = {
X#define SCAN_C (&langtab[0])
X{&langtab[1], "c", getCId, setCArgs, NULL},
X#define SCAN_ASM (&langtab[1])
X{&langtab[2], "asm", getAsmId, setAsmArgs, NULL},
X#define SCAN_ADA (&langtab[2])
X{&langtab[3], "ada", getAdaId, setAdaArgs, NULL},
X#define SCAN_PASCAL (&langtab[3])
X{&langtab[4], "pascal", getPascalId, setPascalArgs, NULL},
X#define SCAN_LISP (&langtab[4])
X{&langtab[5], "lisp", getLispId, setLispArgs, NULL},
X#define SCAN_TEXT (&langtab[5])
X{&langtab[6], "text", getTextId, setTextArgs, NULL},
X#define SCAN_VHIL (&langtab[6])
X{&langtab[7], "vhil", getVhilId, setCArgs, NULL},
X#define SCAN_TEX (&langtab[7])
X{&langtab[8], "tex", getTextId, setTextArgs, "detex -i %s"},
X#define SCAN_ROFF (&langtab[8])
X{&langtab[9], "roff", getTextId, setTextArgs, "sed '/^\\.so/d' < %s | deroff"},
X#define SCAN_CATMAN (&langtab[9])
X{&langtab[10], "catman", getTextId, setTextArgs, "pcat %s | col -b"},
X{ NULL, NULL, NULL, NULL, NULL}
X};
X
X/*
X This is a rather incomplete list of default associations
X between suffixes and languages. You may add more to the
X default list, or you may define them dynamically with the
X `-S<suff>=<lang>' argument to mkid(1) and idx(1). e.g. to
X associate a `.ada' suffix with the Ada language, use
X `-S.ada=ada'
X*/
Xstruct sufftab sufftab[] = {
X{&sufftab[1], ".c", SCAN_C },
X{&sufftab[2], ".h", SCAN_C },
X{&sufftab[3], ".y", SCAN_C },
X{&sufftab[4], ".s", SCAN_ASM },
X{&sufftab[5], ".p", SCAN_PASCAL },
X{&sufftab[6], ".pas", SCAN_PASCAL },
X{&sufftab[7], ".x", SCAN_VHIL },
X{&sufftab[8], ".l", SCAN_C }, /* lex */
X{&sufftab[9], ".doc", SCAN_TEXT },
X{&sufftab[10], ".1", SCAN_ROFF },
X{&sufftab[11], ".tex", SCAN_TEX },
X{&sufftab[12], ".z", SCAN_CATMAN },
X{&sufftab[13], "", SCAN_TEXT }, /* default to text */
X{ NULL, NULL, NULL },
X};
X
X/*
X Return an index into the langtab array for the given suffix.
X*/
Xstatic struct sufftab *
XsuffSlot(suffix)
X register char *suffix;
X{
X register struct sufftab *stp;
X
X if (suffix == NULL)
X suffix = "";
X
X for (stp = sufftab; stp->st_next; stp = stp->st_next)
X if (strequ(stp->st_suffix, suffix))
X return stp;
X return stp;
X}
X
Xstatic struct langtab *
XlangSlot(lang)
X char *lang;
X{
X register struct langtab *ltp;
X
X if (lang == NULL)
X lang = "";
X
X for (ltp = langtab; ltp->lt_next; ltp = ltp->lt_next)
X if (strequ(ltp->lt_name, lang))
X return ltp;
X return ltp;
X}
X
Xchar *
XgetLanguage(suffix)
X char *suffix;
X{
X struct sufftab *stp;
X
X if ((stp = suffSlot(suffix))->st_next == NULL)
X return NULL;
X return (stp->st_lang->lt_name);
X}
X
Xchar *
XgetFilter(suffix)
X char *suffix;
X{
X struct sufftab *stp;
X
X if ((stp = suffSlot(suffix))->st_next == NULL)
X return NULL;
X return (stp->st_lang->lt_filter);
X}
X
Xchar *(*
XgetScanner(lang))()
X char *lang;
X{
X struct langtab *ltp;
X
X if ((ltp = langSlot(lang))->lt_next == NULL)
X return NULL;
X return (ltp->lt_getid);
X}
X
Xstatic void
Xusage()
X{
X fprintf(stderr, "Usage: %s [-S<suffix>=<lang>] [+S(+|-)<arg>] [-S<lang>(+|-)<arg>] [-S<lang>/<lang>/<filter>]\n", MyName);
X exit(1);
X}
Xvoid
XsetScanArgs(op, arg)
X int op;
X char *arg;
X{
X struct langtab *ltp, *ltp2;
X struct sufftab *stp;
X char *lhs, *lhs2;
X int count = 0;
X
X lhs = arg;
X while (isalnum(*arg) || *arg == '.')
X arg++;
X
X if (strequ(lhs, "?=?")) {
X for (stp = sufftab; stp->st_next; stp = stp->st_next) {
X printf("%s%s=%s", (count++>0)?", ":"", stp->st_suffix, stp->st_lang->lt_name);
X if (stp->st_lang->lt_filter)
X printf(" (%s)", stp->st_lang->lt_filter);
X }
X if (count)
X putchar('\n');
X return;
X }
X
X if (strnequ(lhs, "?=", 2)) {
X lhs += 2;
X if ((ltp = langSlot(lhs))->lt_next == NULL) {
X printf("No scanner for language `%s'\n", lhs);
X return;
X }
X for (stp = sufftab; stp->st_next; stp = stp->st_next)
X if (stp->st_lang == ltp) {
X printf("%s%s=%s", (count++>0)?", ":"", stp->st_suffix, ltp->lt_name);
X if (stp->st_lang->lt_filter)
X printf(" (%s)", stp->st_lang->lt_filter);
X }
X if (count)
X putchar('\n');
X return;
X }
X
X if (strequ(arg, "=?")) {
X lhs[strlen(lhs)-2] = '\0';
X if ((stp = suffSlot(lhs))->st_next == NULL) {
X printf("No scanner assigned to suffix `%s'\n", lhs);
X return;
X }
X printf("%s=%s", stp->st_suffix, stp->st_lang->lt_name);
X if (stp->st_lang->lt_filter)
X printf(" (%s)",stp->st_lang->lt_filter);
X printf("\n");
X return;
X }
X
X if (*arg == '=') {
X *arg++ = '\0';
X
X if ((ltp = langSlot(arg))->lt_next == NULL) {
X fprintf(stderr, "%s: Language undefined: %s\n", MyName, arg);
X return;
X }
X if ((stp = suffSlot(lhs))->st_next == NULL) {
X stp->st_suffix = lhs;
X stp->st_lang = ltp;
X stp->st_next = NEW(struct sufftab);
X } else if (!strequ(arg, stp->st_lang->lt_name)) {
X fprintf(stderr, "%s: Note: `%s=%s' overrides `%s=%s'\n", MyName, lhs, arg, lhs, stp->st_lang->lt_name);
X stp->st_lang = ltp;
X }
X return;
X } else if (*arg == '/') {
X *arg++ = '\0';
X if ((ltp = langSlot(lhs))->lt_next == NULL) {
X ltp->lt_name = lhs;
X ltp->lt_getid = getTextId;
X ltp->lt_setargs = setTextArgs;
X ltp->lt_filter = NULL;
X ltp->lt_next = NEW(struct langtab);
X }
X lhs2 = arg;
X arg = strchr(arg, '/');
X if (arg == NULL) {
X ltp2 = ltp;
X } else {
X *arg++ = '\0';
X if ((ltp2 = langSlot(lhs2))->lt_next == NULL) {
X fprintf(stderr,"%s: language %s not defined.\n", MyName, lhs2);
X ltp2 = ltp;
X }
X }
X ltp->lt_getid = ltp2->lt_getid;
X ltp->lt_setargs = ltp2->lt_setargs;
X if ((ltp->lt_filter != NULL) && (!strequ(arg, ltp->lt_filter))){
X fprintf(stderr, "%s: Note: `%s/%s' overrides `%s/%s'\n", MyName, lhs, arg, lhs, ltp->lt_filter);
X }
X ltp->lt_filter = arg;
X return;
X }
X
X if (op == '+') {
X switch (op = *arg++)
X {
X case '+':
X case '-':
X case '?':
X break;
X default:
X usage();
X }
X for (ltp = langtab; ltp->lt_next; ltp = ltp->lt_next)
X (*ltp->lt_setargs)(NULL, op, arg);
X return;
X }
X
X if (*arg == '-' || *arg == '+' || *arg == '?') {
X op = *arg;
X *arg++ = '\0';
X
X if ((ltp = langSlot(lhs))->lt_next == NULL) {
X fprintf(stderr, "%s: Language undefined: %s\n", MyName, lhs);
X return;
X }
X (*ltp->lt_setargs)(lhs, op, arg);
X return;
X }
X
X usage();
X}
X
X/*
X Notify user of unimplemented scanners.
X*/
Xstatic void
XsorryNoScan(lang)
X char *lang;
X{
X if (lang == NULL)
X return;
X fprintf(stderr, "Sorry, no scanner is implemented for %s...\n", lang);
X}
END_OF_FILE
if test 7141 -ne `wc -c <'getscan.c'`; then
echo shar: \"'getscan.c'\" unpacked with wrong size!
fi
# end of 'getscan.c'
fi
if test -f 'scan-c.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'scan-c.c'\"
else
echo shar: Extracting \"'scan-c.c'\" \(8401 characters\)
sed "s/^X//" >'scan-c.c' <<'END_OF_FILE'
X/* Copyright (c) 1986, Greg McGary */
X/* Vhil scanning mods added Jan 7th, 1988 by Tom Horsley */
Xstatic char sccsid[] = "@(#)scan-c.c 1.1 86/10/09";
X
X#include <bool.h>
X#include <stdio.h>
X#include <string.h>
X#include <id.h>
X
Xchar *getCId();
Xchar *getVhilId();
Xvoid setCArgs();
X
Xstatic void clrCtype();
Xstatic void setCtype();
X
X#define I1 0x0001 /* 1st char of an identifier [a-zA-Z_] */
X#define DG 0x0002 /* decimal digit [0-9] */
X#define NM 0x0004 /* extra chars in a hex or long number [a-fA-FxXlL] */
X#define C1 0x0008 /* C comment introduction char: / */
X#define C2 0x0010 /* C comment termination char: * */
X#define Q1 0x0020 /* single quote: ' */
X#define Q2 0x0040 /* double quote: " */
X#define ES 0x0080 /* escape char: \ */
X#define NL 0x0100 /* newline: \n */
X#define EF 0x0200 /* EOF */
X#define SK 0x0400 /* Make these chars valid for names within strings */
X#define VH 0x0800 /* VHIL comment introduction char: # */
X#define WS 0x1000 /* White space characters */
X
X/*
X character class membership macros:
X*/
X#define ISDIGIT(c) ((rct)[c]&(DG)) /* digit */
X#define ISNUMBER(c) ((rct)[c]&(DG|NM)) /* legal in a number */
X#define ISEOF(c) ((rct)[c]&(EF)) /* EOF */
X#define ISID1ST(c) ((rct)[c]&(I1)) /* 1st char of an identifier */
X#define ISIDREST(c) ((rct)[c]&(I1|DG)) /* rest of an identifier */
X#define ISSTRKEEP(c) ((rct)[c]&(I1|DG|SK)) /* keep contents of string */
X#define ISSPACE(c) ((rct)[c]&(WS)) /* white space character */
X/*
X The `BORING' classes should be skipped over
X until something interesting comes along...
X*/
X#define ISBORING(c) (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1|VH))) /* fluff */
X#define ISCBORING(c) (!((rct)[c]&(EF|C2))) /* comment fluff */
X#define ISVBORING(c) (!((rct)[c]&(EF|NL))) /* vhil comment fluff */
X#define ISQ1BORING(c) (!((rct)[c]&(EF|NL|Q1|ES))) /* char const fluff */
X#define ISQ2BORING(c) (!((rct)[c]&(EF|NL|Q2|ES))) /* quoted str fluff */
X
Xstatic short idctype[] = {
X
X EF,
X
X /* 0 1 2 3 4 5 6 7 */
X /* ----- ----- ----- ----- ----- ----- ----- ----- */
X
X /*000*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*010*/ 0, 0, NL, 0, 0, 0, 0, 0,
X /*020*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*030*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*040*/ 0, 0, Q2, 0, 0, 0, 0, Q1,
X /*050*/ 0, 0, C2, 0, 0, 0, 0, C1,
X /*060*/ DG, DG, DG, DG, DG, DG, DG, DG,
X /*070*/ DG, DG, 0, 0, 0, 0, 0, 0,
X /*100*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1,
X /*110*/ I1, I1, I1, I1, I1|NM, I1, I1, I1,
X /*120*/ I1, I1, I1, I1, I1, I1, I1, I1,
X /*130*/ I1|NM, I1, I1, 0, ES, 0, 0, I1,
X /*140*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1,
X /*150*/ I1, I1, I1, I1, I1|NM, I1, I1, I1,
X /*160*/ I1, I1, I1, I1, I1, I1, I1, I1,
X /*170*/ I1|NM, I1, I1, 0, 0, 0, 0, 0,
X
X /*200*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*210*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*220*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*230*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*240*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*250*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*260*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*270*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*300*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*310*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*320*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*330*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*340*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*350*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*360*/ 0, 0, 0, 0, 0, 0, 0, 0,
X /*370*/ 0, 0, 0, 0, 0, 0, 0, 0,
X
X};
X
Xstatic bool eatUnder = TRUE;
Xstatic bool scanVhil = FALSE;
X
X/*
X*/
Xchar *
XgetVhilId(inFILE, flagP)
X{
X if (! scanVhil) {
X setCArgs("vhil",'+',"v");
X }
X return(getCId(inFILE, flagP));
X}
X
X/*
X Grab the next identifier the C source
X file opened with the handle `inFILE'.
X This state machine is built for speed, not elegance.
X*/
Xchar *
XgetCId(inFILE, flagP)
X FILE *inFILE;
X int *flagP;
X{
X static char idBuf[BUFSIZ];
X static bool newLine = TRUE;
X register short *rct = &idctype[1];
X register int c;
X register char *id = idBuf;
X
Xtop:
X c = getc(inFILE);
X if (newLine) {
X newLine = FALSE;
X if (c == '.') {
X /* Auto-recognize vhil code when you see a . in column 1.
X * also ignore lines that start with a .
X */
X if (! scanVhil) {
X setCArgs("vhil",'+',"v");
X }
X while (ISVBORING(c))
X c = getc(inFILE);
X newLine = TRUE;
X goto top;
X }
X if (c != '#')
X goto next;
X c = getc(inFILE);
X if (scanVhil && ISSPACE(c)) {
X while (ISVBORING(c))
X c = getc(inFILE);
X newLine = TRUE;
X goto top;
X }
X while (ISBORING(c))
X c = getc(inFILE);
X if (!ISID1ST(c))
X goto next;
X id = idBuf;
X *id++ = c;
X while (ISIDREST(c = getc(inFILE)))
X *id++ = c;
X *id = '\0';
X if (strequ(idBuf, "include")) {
X while (c == ' ' || c == '\t') c = getc(inFILE) ;
X if (c == '\n') {newLine = TRUE; goto top;}
X id = idBuf;
X if (c == '"') {
X c = getc(inFILE);
X while (c != '\n' && c != EOF && c != '"') {
X *id++ = c;
X c = getc(inFILE);
X }
X *flagP = IDN_STRING;
X } else if (c == '<') {
X c = getc(inFILE);
X while (c != '\n' && c != EOF && c != '>') {
X *id++ = c;
X c = getc(inFILE);
X }
X *flagP = IDN_STRING;
X } else if (ISID1ST(c)) {
X *id++ = c ;
X while (ISIDREST(c = getc(inFILE))) *id++ = c;
X *flagP = IDN_NAME;
X } else {
X while (c != '\n' && c != EOF) c = getc(inFILE);
X newLine = TRUE;
X goto top;
X }
X while (c != '\n' && c != EOF) c = getc(inFILE) ;
X newLine = TRUE;
X *id = '\0';
X return idBuf;
X }
X if (strnequ(idBuf, "if", 2)
X || strequ(idBuf, "define")
X || strequ(idBuf, "elif") /* ansi C */
X || (scanVhil && strequ(idBuf, "elsif"))
X || strequ(idBuf, "undef"))
X goto next;
X while ((c != '\n') && (c != EOF))
X c = getc(inFILE);
X newLine = TRUE;
X goto top;
X }
X
Xnext:
X while (ISBORING(c))
X c = getc(inFILE);
X
X switch (c)
X {
X case '"':
X id = idBuf;
X *id++ = c = getc(inFILE);
X for (;;) {
X while (ISQ2BORING(c))
X *id++ = c = getc(inFILE);
X if (c == '\\') {
X *id++ = c = getc(inFILE);
X continue;
X } else if (c != '"')
X goto next;
X break;
X }
X *--id = '\0';
X id = idBuf;
X while (ISSTRKEEP(*id))
X id++;
X if (*id || id == idBuf) {
X c = getc(inFILE);
X goto next;
X }
X *flagP = IDN_STRING;
X if (eatUnder && idBuf[0] == '_' && idBuf[1])
X return &idBuf[1];
X else
X return idBuf;
X
X case '\'':
X c = getc(inFILE);
X for (;;) {
X while (ISQ1BORING(c))
X c = getc(inFILE);
X if (c == '\\') {
X c = getc(inFILE);
X continue;
X } else if (c == '\'')
X c = getc(inFILE);
X goto next;
X }
X
X case '/':
X if ((c = getc(inFILE)) != '*')
X goto next;
X c = getc(inFILE);
X for (;;) {
X while (ISCBORING(c))
X c = getc(inFILE);
X if ((c = getc(inFILE)) == '/') {
X c = getc(inFILE);
X goto next;
X } else if (ISEOF(c)) {
X newLine = TRUE;
X return NULL;
X }
X }
X
X case '\n':
X newLine = TRUE;
X goto top;
X
X case '#':
X if (! scanVhil) {
X /* Auto-recognize vhil when find a # in the middle of a line.
X */
X setCArgs("vhil",'+',"v");
X }
X c = getc(inFILE);
X while (ISVBORING(c))
X c = getc(inFILE);
X newLine = TRUE;
X goto top;
X default:
X if (ISEOF(c)) {
X newLine = TRUE;
X return NULL;
X }
X name:
X id = idBuf;
X *id++ = c;
X if (ISID1ST(c)) {
X *flagP = IDN_NAME;
X while (ISIDREST(c = getc(inFILE)))
X *id++ = c;
X } else if (ISDIGIT(c)) {
X *flagP = IDN_NUMBER;
X while (ISNUMBER(c = getc(inFILE)))
X *id++ = c;
X } else
X fprintf(stderr, "junk: `\\%3o'", c);
X ungetc(c, inFILE);
X *id = '\0';
X *flagP |= IDN_LITERAL;
X return idBuf;
X }
X}
X
Xstatic void
XsetCtype(chars, type)
X char *chars;
X int type;
X{
X short *rct = &idctype[1];
X
X while (*chars)
X rct[*chars++] |= type;
X}
Xstatic void
XclrCtype(chars, type)
X char *chars;
X int type;
X{
X short *rct = &idctype[1];
X
X while (*chars)
X rct[*chars++] &= ~type;
X}
X
Xextern char *MyName;
Xstatic void
Xusage(lang)
X char *lang;
X{
X fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang);
X exit(1);
X}
Xstatic char *cDocument[] =
X{
X"The C scanner arguments take the form -Sc<arg>, where <arg>",
X"is one of the following: (<cc> denotes one or more characters)",
X" (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.",
X" -s<cc> . . . . Allow <cc> in string ids.",
X" -v . . . . . . Skip vhil comments.",
XNULL
X};
Xvoid
XsetCArgs(lang, op, arg)
X char *lang;
X int op;
X char *arg;
X{
X if (op == '?') {
X document(cDocument);
X return;
X }
X switch (*arg++)
X {
X case 'u':
X eatUnder = (op == '+');
X break;
X case 's':
X setCtype(arg, SK);
X break;
X case 'v':
X setCtype("$", I1);
X setCtype("#", VH);
X setCtype(" \t", WS);
X scanVhil = TRUE;
X break;
X default:
X if (lang)
X usage(lang);
X break;
X }
X}
END_OF_FILE
if test 8401 -ne `wc -c <'scan-c.c'`; then
echo shar: \"'scan-c.c'\" unpacked with wrong size!
fi
# end of 'scan-c.c'
fi
echo shar: End of archive 6 \(of 11\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 11 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
======================================================================
domain: tahorsley at csd.harris.com USMail: Tom Horsley
uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle
Delray Beach, FL 33444
+==== Censorship is the only form of Obscenity ======================+
| (Wait, I forgot government tobacco subsidies...) |
+====================================================================+
More information about the Alt.sources
mailing list