From decwrl!ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!allbery Fri Nov  3 19:53:05 PST 1989
Article 1148 of comp.sources.misc:
Path: decwrl!ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!allbery
From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Newsgroups: comp.sources.misc
Subject: v08i101: Makedoc part 1 - make documentation from Objective C source.
Message-ID: <71227@uunet.UU.NET>
Date: 3 Nov 89 01:27:20 GMT
Sender: allbery@uunet.UU.NET
Reply-To: greg@watmath.waterloo.edu@sce.carleton.ca.UUCP (Greg Franks)
Organization: Systems Eng., Carleton Univ., Ottawa, Canada
Lines: 1040
Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)

Posting-number: Volume 8, Issue 101
Submitted-by: greg@watmath.waterloo.edu@sce.carleton.ca.UUCP (Greg Franks)
Archive-name: makedoc.gf/part01

Greetings.  Here is a little objective C documentation program that 
I have whipped up.  A couple of people on my mailing lists have
expressed interest in this program, so I thought I might as well
distribute it to everyone.  Please note that this is part1 of a three
part archive.  Concatenate all three parts then unshar.  (I wish we had
a better sharchiver...)

#! /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 shell archive."
# Contents:  README Makefile makedoc.h makedoc.c parse.c printclass.c
#   printmethod.c makedoc.1
# Wrapped by greg@organia on Wed Nov  1 11:01:41 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(743 characters\)
sed "s/^X//" >README <<'END_OF_README'
XMakedoc is a program that generates documentation for objective C
Xprograms.  The output format is similar to that used by StepStone.
XMakedoc will even generate a class heirarchy diagram.
X
XThe documentation is generated by searching for comment strings in the
Xsource file.  Objective C method and standard C function declarations
Xare formatted appropriately.  
X
XOutput is in Latex.  Other formatters can be accomodated by replacing
Xall of the printf statements.
X
XMakedoc was (and still is being) developed on a Sun3.  Porting to
Xother UNIXes should be straight forward although I tend to err on the
Xside of System V for library functions (old habits die hard).
X
XPlease send comments or suggestions to:
Xgreg@sce.carleton.ca
Xuunet!mitel!sce!greg
END_OF_README
if test 743 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(1994 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# $Header: /usr/sirius/greg/src/makedoc/RCS/Makefile,v 3.2 89/10/10 11:40:49 greg Exp Locker: greg $
X#
X# $Log:	Makefile,v $
X# Revision 3.2  89/10/10  11:40:49  greg
X# > Output now goes to .tex file.
X# -o and -c ala cc now added.
X# -c becomes -C.
X# 
X# -m becomes -M.
X# 
X# Revision 3.1  89/10/04  10:15:55  greg
X# Print out method index.  This scheme doesn't work.
X# 
X# Revision 1.1  89/09/29  08:41:12  greg
X# Initial revision
X# 
X# Initial revision
X# 
X#
X#
X# Variable definitions:
XSHELL=		/bin/sh
XCC=		/bin/cc
XLINT=		/usr/bin/lint
XLPRDEST=	
XCATMANDIR=	/tmp
XBINDIR=		$(ROOT)/usr/local/bin
XMANDIR	=	$(ROOT)/usr/local/man
X
X# Compile time options.  Use USG for Suns.
XOPTIONS=  -DUSG
X
X# CFLAGS, use optimizer + compile time options
XCFLAGS= -O $(OPTIONS)
X
X# Link flags shareable text and strip image
XLDFLAGS= -s
X
X# Lint flags
XLINT_FLAGS= -Dlint
X
X# CFLAGS in debug mode, tell program we are in debug mode, and use compile time options
XDEBUG_CFLAGS= -DDEBUG $(OPTIONS) -g
X
X# LDFLAGS in debug mode, do not strip image
XDEBUG_LDFLAGS= -g
X
XSRCS=		makedoc.c parse.c printclass.c printmethod.c
XOBJS=		makedoc.o parse.o printclass.o printmethod.o
XDOCS=		makedoc.1
XMAN=		makedoc.man
X
XPACK=		makedoc.1.z
X
X.SUFFIXES:	.1.z .man .1
X
X.1.man:
X		nroff -man $*.1 > $*.man
X
X.man.1.z:
X		cp $*.man $*XXX
X		pack -f $*XXX
X		mv $*XXX.z $*.1.z
X
Xall:		makedoc pack
X
Xmakedoc:	$(OBJS) Makefile
X		$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o makedoc
X
Xmakedoc.o:	makedoc.c makedoc.h
X
Xprintclass.o:	printclass.c makedoc.h
X
Xprintmethod.o:	printmethod.c makedoc.h
X
Xdebug:		Makefile
X		exec make "CFLAGS=$(DEBUG_CFLAGS)" "LDFLAGS=$(DEBUG_LDFLAGS)" makedoc
X
Xlint:
X		$(LINT) $(LINT_FLAGS) $(OPTIONS) $(SRCS)
X
Xclean:
X		rm -f $(OBJS) makedoc a.out $(MAN) $(PACK) print
X
Xarchive:
X		shar Makefile $(SRCS) > makedoc.src
X
Xman:		$(MAN)
X
Xprint:		$(MAN)
X		lpr $(LPRDEST) $?
X		touch print
X
Xpack:		man $(PACK)
X
Xinstall:	all
X		cpset makedoc $(BINDIR) 755 bin bin
X		cpset makedoc.1.z $(CATMANDIR)/man1 444 bin bin
X		cpset makedoc.1 $(MANDIR)/man1 444 bin bin
END_OF_Makefile
if test 1994 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makedoc.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makedoc.h\"
else
echo shar: Extracting \"makedoc.h\" \(3136 characters\)
sed "s/^X//" >makedoc.h <<'END_OF_makedoc.h'
X/************************************************************************/
X/* Copyright the Real-Time and Distributed Systems Group,		*/
X/* Department of Systems and Computer Engineering,			*/
X/* Carleton University, Ottawa, Ontario, Canada. K1S 5B6		*/
X/*									*/
X/* October 1989.							*/
X/* 									*/
X/*									*/
X/* This software is published on an as-is basis. There is ABSOLUTELY NO	*/
X/* WARRANTY for any part of this software to work correctly or as	*/
X/* described in the manuals. We do not accept any liability for any	*/
X/* kind of damage caused by use of this software, such as loss of data,	*/
X/* time, money, or effort.						*/
X/*									*/
X/* Permission is granted to use, copy, modify, or distribute any part	*/
X/* of this software as long as this is done without asking for		*/
X/* charge, and provided that this copyright notice is retained as	*/
X/* part of the source files. You may charge a distribution fee for	*/
X/* the physical act of transferring a copy, and you may at your		*/
X/* option offer warranty protection in exchange for a fee.		*/
X/*									*/
X/* Please send comments or suggestions to:				*/
X/*	Greg Franks							*/
X/* 	Department of Systems and Computer Engineering,			*/
X/* 	Carleton University, Ottawa, Ontario, Canada. K1S 5B6		*/
X/*	(613) 788-5736							*/
X/*									*/
X/*	BITNET: greg@sce.carleton.ca					*/
X/*	UUCP: uunet!mitel!sce!greg					*/
X/************************************************************************/
X
X/* Some customizable parameters.	*/
X
X#define	MAX_CLASS_ENTRIES	1024
X#define	MAX_METHOD_ENTRIES	8096
X#define	MAX_DIRS		10
X#define MAX_DEFINES		10
X#define COLUMNS_PER_PAGE	3
X
X/* Non-customizable parameters.	*/
X    
X#define COMMENT_BUFSIZ		128
X#define	ARGLIST_SIZE 		10
X
X#define isidchr(c)	(isalnum(c) || (c == '_') || (c == '$'))
X
Xtypedef	enum { false, true } boolean ;
X
Xtypedef struct BackLink {
X	struct BackLink *next;
X	int index;
X} BackLink;
X
Xtypedef struct ClassNameEntry {
X	char *class_name;
X	struct {
X		unsigned  defined:1;
X		unsigned  traversed:1;
X	} tag;
X	int parent_class_index;
X	struct BackLink *next;		/* For hierarchy printing	*/
X} ClassNameEntry;
X
Xtypedef struct CommentBuf {
X	char buf[COMMENT_BUFSIZ];
X	int n;
X	struct CommentBuf * next;
X} CommentBuf;
X
Xtypedef struct IncludeBuf {
X	char *buf;
X	struct IncludeBuf * next;
X} IncludeBuf;
X
Xtypedef struct MethodNameEntry {
X	char *method_name;
X	struct BackLink *next;		/* For hierarchy printing	*/
X} MethodNameEntry;
X
Xextern boolean PutHeader;
Xextern boolean MakeGlobalFile;
X
Xextern ClassNameEntry ClassNameTable[];
Xextern MethodNameEntry MethodNameTable[];
Xextern char * IncludeDir[];
Xextern int IncludeCount;
Xextern char * Defines[];
Xextern int DefinesCount;
X
Xextern char * ProgName;
X
X/*----------------------------------------------------------------------*/
X
XFILE * OpenIncludeFile();
Xint ReadFile();
Xvoid PrintClassHeader();
Xvoid PrintDescription();
Xvoid PrintMethod();
Xvoid PrintFunction();
Xvoid PrintComment();
X
Xvoid PrintClassHierarchy();
Xvoid DescendTree();
Xvoid PrintTree();
Xvoid PictureNewLine();
Xvoid InitializeTreePrint();
Xvoid TerminateTreePrint();
X
Xvoid PrintMethodIndex();
Xvoid PutLatexChar();
END_OF_makedoc.h
if test 3136 -ne `wc -c <makedoc.h`; then
    echo shar: \"makedoc.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makedoc.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makedoc.c\"
else
echo shar: Extracting \"makedoc.c\" \(18993 characters\)
sed "s/^X//" >makedoc.c <<'END_OF_makedoc.c'
X/************************************************************************/
X/* Copyright the Real-Time and Distributed Systems Group,		*/
X/* Department of Systems and Computer Engineering,			*/
X/* Carleton University, Ottawa, Ontario, Canada. K1S 5B6		*/
X/*									*/
X/* October 1989.							*/
X/* 									*/
X/*									*/
X/* This software is published on an as-is basis. There is ABSOLUTELY NO	*/
X/* WARRANTY for any part of this software to work correctly or as	*/
X/* described in the manuals. We do not accept any liability for any	*/
X/* kind of damage caused by use of this software, such as loss of data,	*/
X/* time, money, or effort.						*/
X/*									*/
X/* Permission is granted to use, copy, modify, or distribute any part	*/
X/* of this software as long as this is done without asking for		*/
X/* charge, and provided that this copyright notice is retained as	*/
X/* part of the source files. You may charge a distribution fee for	*/
X/* the physical act of transferring a copy, and you may at your		*/
X/* option offer warranty protection in exchange for a fee.		*/
X/*									*/
X/* Please send comments or suggestions to:				*/
X/*	Greg Franks							*/
X/* 	Department of Systems and Computer Engineering,			*/
X/* 	Carleton University, Ottawa, Ontario, Canada. K1S 5B6		*/
X/*	(613) 788-5736							*/
X/*									*/
X/*	BITNET: greg@sce.carleton.ca					*/
X/*	UUCP: uunet!mitel!sce!greg					*/
X/************************************************************************/
X
X/*
X * $Source: /usr/sirius/greg/src/makedoc/RCS/makedoc.c,v $
X *	Search through files looking for magical comments and extract them
X *	thus creating beautiful documentation.
X *
X *	Input is assumed to be objective C.
X */
X
X#ifndef lint
Xstatic char	*RCSid = "$Header: /usr/sirius/greg/src/makedoc/RCS/makedoc.c,v 3.6 89/10/24 14:29:55 greg Exp Locker: greg $";
X#endif
X
X/*
X * $Log:	makedoc.c,v $
X * Revision 3.6  89/10/24  14:29:55  greg
X * Print out 'classes used' information.
X * Print out last modified time of .m file.
X * 
X * Revision 3.5  89/10/11  18:02:30  greg
X * Print out functions properly.  Do not treat them as methods.
X * 
X * Revision 3.4  89/10/10  17:30:27  greg
X * Print out standard function names.
X * Print out stuff to make indexes.
X * 
X * Revision 3.3  89/10/10  11:38:09  greg
X * Output now goes to .tex file. 
X * -o and -c ala cc now added.
X * -c becomes -C
X * -m becomes -M
X * 
X * Revision 3.2  89/10/04  20:53:12  greg
X * Print comments properly.  Flush tex commands upon arrival.
X * 
X * Revision 3.1  89/10/04  10:14:48  greg
X * Print out method index.  This scheme doesn't work.
X * 
X * Revision 2.4  89/10/03  12:38:43  greg
X * Proper printing of class hierarchy.
X * Now searches for methods and indexes.
X * 
X * Revision 2.3  89/10/02  17:01:19  greg
X * tex drawing routines for hierarchy.
X * 
X * Revision 2.2  89/10/02  13:02:44  greg
X * Now restrict number of levels printed horizontally.
X * 
X * Revision 2.1  89/10/02  11:31:59  greg
X * Now prints out class hierarchies.  Table of contents stuff removed.
X * 
X * Revision 1.4  89/09/29  20:21:38  greg
X * Handles all comment forms properly.  Even searches include files.
X * 
X * Revision 1.3  89/09/29  18:49:04  greg
X * Now handles and displays commets (quote mode for methods).
X * 
X * Revision 1.2  89/09/29  13:53:48  greg
X * Now searches for dependencies.
X * 
X * Revision 1.1  89/09/29  08:42:06  greg
X * Initial revision
X * 
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <errno.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef USG
X#include <string.h>
X#endif
X#include "makedoc.h"
X
X
XFILE	*i_fptr;
X
Xchar * IncludeDir[MAX_DIRS];
Xint IncludeCount 	= 0;
Xchar * Defines[MAX_DEFINES];
Xint DefinesCount	= 0;
X
Xchar * CPPstring 	= "/lib/cpp -E -P ";
Xchar * ProgName;
X
XFILE * o_fptr		= (FILE *)0;	/* Output file pointer.		*/
XFILE * g_fptr		= (FILE *)0;	/* Global File pointer.		*/
XFILE * c_fptr		= (FILE *)0;	/* Output file for hierarchy. 	*/
XFILE * m_fptr		= (FILE *)0;	/* Output file for hierarchy. 	*/
X
Xboolean PutHeader	= true;
Xboolean MakeGlobalFile	= false;
Xboolean ClassFilePresent= false;
X
X/*----------------------------------------------------------------------*/
X/* Class Hierarch printing stuff.					*/
X/*----------------------------------------------------------------------*/
X
Xchar * ClassFileName	= (char *)0;
XClassNameEntry ClassNameTable[MAX_CLASS_ENTRIES];
X
X
X/*----------------------------------------------------------------------*/
X/* Method Index  printing stuff.					*/
X/*----------------------------------------------------------------------*/
X
Xchar * MethodFileName	= (char *)0;
XMethodNameEntry MethodNameTable[MAX_METHOD_ENTRIES];
X
X/*----------------------------------------------------------------------*/
X
XFILE *popen();
Xchar *malloc();
Xint perror(), exit();
Xchar * sprintf();
X
Xvoid Process();
Xvoid PrintHeader();
Xvoid PrintTrailer();
Xvoid PrintEntry();
Xvoid PrintUsesList();
X
X
Xint
Xmain(argc, argv)
Xchar	**argv;
X{
X	int c;
X	int i;
X	char OutputFileName[BUFSIZ];
X	char *p;
X	
X	extern int	errno;
X	extern char	*optarg;
X	extern int	optind;
X
X	ProgName = argv[0];
X
X	while (( c = getopt( argc, argv, "co:I:D:C:M:" )) != EOF) {
X		switch ( c ) {
X
X		case 'c':
X			PutHeader      = false;
X			break;
X
X		case 'o':
X			PutHeader      = false;
X			MakeGlobalFile = true;
X			g_fptr = fopen( optarg, "w" );
X			if ( !g_fptr ) {
X				(void) fprintf( stderr, "%s: cannot open %s", ProgName, optarg );
X				(void) perror( "" );
X				(void) exit( 1 );
X			}
X			break;
X			
X			
X		case 'C':
X			ClassFileName = optarg;
X			p = strrchr( optarg, '/' );
X			if ( !p ) p = optarg;
X			p = strchr( optarg, '.' );
X			(void) strcpy( OutputFileName, optarg );
X			if ( !p ) {
X				(void) strcat( OutputFileName, ".tex" );
X			} else if ( strcmp( p, ".tex" ) == 0 ) {
X				*p = '\0';	/* Chop off .tex */
X			} else {
X				(void) fprintf( stderr, "%s: Illegal extension for \"-C %s\"  -- %s\n", ProgName, optarg, p );
X				exit( 1 );
X			}
X
X			/* Now that we have a valid file name, see if	*/
X			/* a class file exists.  If it does, simply	*/
X			/* read its contents.  Otherwise generate it.	*/
X			
X			if ( ( c_fptr = fopen( OutputFileName, "r" ) ) ) {
X				(void) fclose( c_fptr );
X				c_fptr = (FILE *)0;
X			} else if ( !(c_fptr = fopen( OutputFileName, "w" )) ) {
X				(void) fprintf( stderr, "%s: cannot open %s", ProgName, OutputFileName );
X				(void) perror( "" );
X				(void) exit( 1 );
X			}
X			ClassFilePresent = true;
X			break;
X			
X		case 'D':
X			if ( DefinesCount >= MAX_DIRS ) {
X				(void) fprintf( stderr, "%s: Too many include directories, % s ignored\n", ProgName, optarg );
X			} else { 
X				Defines[DefinesCount++] = optarg;
X			}
X			break;
X			
X		case 'I':
X			if ( IncludeCount >= MAX_DIRS ) {
X				(void) fprintf( stderr, "%s: Too many include directories, % s ignored\n", ProgName, optarg );
X			} else { 
X				IncludeDir[IncludeCount++] = optarg;
X			}
X			break;
X			
X		case 'M':
X			MethodFileName = optarg;
X			m_fptr = fopen( optarg, "w" );
X			if ( !m_fptr ) {
X				(void) fprintf( stderr, "%s: cannot open %s", ProgName, optarg );
X				(void) perror( "" );
X				(void) exit( 1 );
X			}
X			break;
X			
X		default:
X			(void) fprintf( stderr, "Usage: %s file ...\n", ProgName);
X			(void) exit(1);
X		}
X	}
X
X	/* Some initialization */
X	
X	for ( i = 0; i < MAX_CLASS_ENTRIES; ++i ) {
X		ClassNameTable[i].parent_class_index = -1;
X		ClassNameTable[i].tag.defined   = 0;
X		ClassNameTable[i].tag.traversed = 0;
X		ClassNameTable[i].class_name = (char *)0;
X		ClassNameTable[i].next = (BackLink *)0;
X	}
X	ClassNameTable[0].class_name = "** ROOT **";
X	
X	for ( i = 0; i < MAX_METHOD_ENTRIES; ++i ) {
X		MethodNameTable[i].method_name = (char *)0;
X		MethodNameTable[i].next = (BackLink *)0;
X	}
X	MethodNameTable[0].method_name = "** ROOT **";
X	
X	/* and away we go */
X
X	if ( optind == argc ) {				/* no file names */
X		if ( DefinesCount == 0 ) { 
X			i_fptr = stdin;
X			o_fptr = stdout;
X			Process( i_fptr, o_fptr, "** stdin **" );
X		} else {
X/* 			i_fptr = popen( cmd, "r" ); */
X			/* Run CPP */
X		}
X		exit ( 0 );
X	}
X
X	if ( MakeGlobalFile ) {
X		PrintHeader( g_fptr );
X		if ( ClassFilePresent ) {
X			(void) fprintf( g_fptr, "\\include{%s}\n", ClassFileName );
X		}
X		(void) fprintf( g_fptr, "\\chapter{Classes}\n" );
X	}
X	
X	for ( ; optind < argc; ++optind ) {
X		if ( strcmp(argv[optind], "-") == 0 ) {
X
X			i_fptr = stdin;
X			o_fptr = MakeGlobalFile ? g_fptr : stdout;
X
X		} else {
X
X			/* Search for extension on file name	*/
X			
X			(void) strcpy( OutputFileName, argv[optind] );
X
X			p = strrchr( OutputFileName, '/' );
X			if ( !p ) p = OutputFileName;
X			p = strchr( OutputFileName, '.' );
X			if ( !p ) {
X				(void) fprintf( stderr, "%s: Cannot find file type -- %s\n", ProgName, argv[optind] );
X				continue;
X			} else if ( strcmp( p, ".m" ) == 0 || strcmp( p, ".c" ) == 0 || strcmp( p, ".h" ) == 0 ) {
X				if ( MakeGlobalFile ) {
X					(void) fprintf( g_fptr, "\\include{%.*s}\n", p-OutputFileName, OutputFileName );
X				}
X				(void) strcpy( p, ".tex" );
X			} else if ( strcmp( p, ".tex" ) == 0 ) {
X				if ( MakeGlobalFile ) {
X					(void) fprintf( g_fptr, "\\include{%.*s}\n", p-OutputFileName, OutputFileName );
X				}
X				continue;
X			} else {
X				(void) fprintf( stderr, "%s: Illegal file type -- %s\n", ProgName, argv[optind] );
X				continue;
X			}
X			
X			if ( (i_fptr = fopen( argv[optind], "r" )) == NULL ) {
X				(void) fprintf(stderr, "%s: Cannot open input file -- %s ", ProgName, argv[optind] );
X				(void) perror( "" );
X				exit( 1 );
X			}
X			
X			if ( (o_fptr = fopen( OutputFileName, "w" )) == NULL ) {
X				(void) fprintf(stderr, "%s: Cannot open output file -- %s ", ProgName, OutputFileName );
X				(void) perror( "" );
X				exit( 1 );
X			}
X
X		}
X
X		if ( DefinesCount == 0 ) {
X			Process( i_fptr, o_fptr, argv[optind] );
X		} else {
X			/* Run CPP */
X		}
X
X		if ( i_fptr != stdin ) {
X			(void) fclose( i_fptr );
X			(void) fclose( o_fptr );
X		}
X	}
X
X	if ( c_fptr ) {
X		PrintClassHierarchy( c_fptr );
X	}
X/*	if ( MethodFileName ) {
X		PrintMethodIndex( m_fptr );
X	} */
X	if ( g_fptr ) {
X		PrintTrailer( g_fptr );
X	}
X	
X	
X	(void) exit( 0 );
X
X	/*NOTREACHED*/
X}
X
X
X
Xvoid
XProcess( i_fptr, o_fptr, FileName )
XFILE * i_fptr;
XFILE * o_fptr;
Xchar * FileName;
X{
X	if ( PutHeader ) PrintHeader( o_fptr );
X	(void) ReadFile( i_fptr, FileName, 0 );
X	if ( PutHeader ) PrintTrailer( o_fptr );
X}
X
X
X
XFILE *
XOpenIncludeFile( ClassName, FileName )
Xchar * ClassName;
Xchar * FileName;
X{
X	register char *p;
X	register char *q;
X	FILE * fptr;
X	register int i;
X	
X	/* Try local directory first, then try search path	*/
X
X	p = FileName;
X	q = ClassName;
X	while( *q  ) {
X		*p++ = *q++;
X	}
X	*p++ = '.';
X	*p++ = 'h';
X	*p++ = '\0';
X
X	fptr = fopen( FileName, "r" );
X	for ( i = 0; !fptr && i < IncludeCount; ++i ) {
X		p = FileName;
X		q = IncludeDir[i];
X		while( *q ) {
X			*p++ = *q++;
X		}
X		if ( *(p-1) != '/' ) {
X			*p++ = '/';	/* Ignore trailin '/' */
X		}
X		q = ClassName;
X		while( *q ) {
X			*p++ = *q++;
X		}
X		*p++ = '.';
X		*p++ = 'h';
X		*p++ = '\0';
X		fptr = fopen( FileName, "r" );
X	}
X	return fptr;
X}
X
X
X
X/*----------------------------------------------------------------------*/
X
Xvoid
XPrintHeader( fp )
XFILE * fp;
X{
X	(void) fprintf( fp, "\\documentstyle[11pt]{report}\n" );
X	(void) fprintf( fp, "\\newcommand{\\heading}[1]{\n" );
X	(void) fprintf( fp, "\t\\addcontentsline{toc}{subsection}{\n" );
X	(void) fprintf( fp, "\t\t\\protect\\numberline{}{#1}}{\\begin{center}{\\LARGE\\bf #1}\\end{center}}}\n" );
X	(void) fprintf( fp, "\\newcommand{\\subheading}[1]{\n" );
X	(void) fprintf( fp, "\t\\addcontentsline{toc}{subsubsection}{\n" );
X	(void) fprintf( fp, "\t\t\\protect\\numberline{}{#1}}{\\begin{center}{\\Large\\bf #1}\\end{center}}}\n" );
X	(void) fprintf( fp, "\\makeindex\n" );
X	(void) fprintf( fp, "\\newlength{\\funkywidth}\n" );
X	(void) fprintf( fp, "\\newlength{\\classitemtagwidth}\n" );
X	(void) fprintf( fp, "\\begin{document}\n" );
X	(void) fprintf( fp, "\\settowidth{\\classitemtagwidth}{\\it Interface File:\\/}\n" );
X	(void) fprintf( fp, "\\setlength{\\funkywidth}{\\textwidth}\n" );
X	(void) fprintf( fp, "\\addtolength{\\funkywidth}{-1\\leftmargini}\n" );
X}
X
X
Xvoid
XPrintTrailer( fp )
XFILE * fp;
X{
X	(void) fprintf( fp, "\\end{document}\n" );
X}
X
X
X
Xvoid
XPrintClassHeader( ClassIndex, SourceFile, CommentPtr, IncludePtr )
Xint ClassIndex;
Xchar *SourceFile;
XCommentBuf * CommentPtr;
XIncludeBuf * IncludePtr;
X{
X	void PrintInheritsList();
X	char *ArgList[1];
X	int ArgCount		= 1;
X	struct stat statbuf;
X	long FileTime;
X	char InterfaceFile[BUFSIZ];
X	FILE * temp_fptr;
X	extern long time();
X	extern char * ctime();
X	
X	if ( stat( SourceFile, &statbuf ) == 0 ) {
X		FileTime = (long)statbuf.st_mtime;
X	} else {
X		FileTime = time((long *)0);
X	}
X
X	if ( ClassIndex != 0 ) {
X		ArgList[0] = ClassNameTable[ClassIndex].class_name;
X	} else {
X		ArgList[0] = "";
X	}
X	
X	(void) fprintf( o_fptr, "\\newpage" );
X	(void) fprintf( o_fptr, "\\begin{center}\\rule{\\textwidth}{0.5mm}\\end{center}" );
X	(void) fprintf( o_fptr, "\\pagestyle{myheadings}\n" );
X	(void) fprintf( o_fptr, "\\markright{ %s }\n", ArgList[0] );
X	(void) fprintf( o_fptr, "\\addcontentsline{toc}{section}{\\protect\\numberline{}{%s}}\n", ArgList[0] );
X	(void) fprintf( o_fptr, "\\begin{center} {\\Huge\\bf %s } \\end{center}\n", ArgList[0] );
X	(void) fprintf( o_fptr, "\\index{%s}\n", ArgList[0] );
X	(void) fprintf( o_fptr, "\\begin{description}\n" );
X	(void) fprintf( o_fptr, "\\item[\\parbox{\\classitemtagwidth}{\\it Inherits from:\\/}]\n" );
X	if ( ClassNameTable[ClassIndex].parent_class_index != 0 ) { 
X		PrintInheritsList( ClassNameTable[ClassIndex].parent_class_index );
X	} else {
X		(void) fprintf( o_fptr, "nobody\n" );
X	}
X	(void) fprintf( o_fptr, "\n" );
X	(void) fprintf( o_fptr, "\\item[\\parbox{\\classitemtagwidth}{\\it Classes used:\\/}] \n" );
X	if ( IncludePtr && IncludePtr->buf ) {
X		PrintUsesList( IncludePtr );
X	} else {
X		(void) fprintf( o_fptr, "none\n" );
X	}
X	(void) fprintf( o_fptr, "\\item[\\parbox{\\classitemtagwidth}{\\it Interface File:\\/}] \n" );
X	if ( strlen( ArgList[0] ) != 0 && (temp_fptr = OpenIncludeFile( ArgList[0], InterfaceFile )) ) {
X		(void) fprintf( o_fptr, "%s\n", InterfaceFile );
X		(void) fclose( temp_fptr );
X	} else {
X		(void) fprintf( o_fptr, "none\n" );
X	}
X	(void) fprintf( o_fptr, "\\item[\\parbox{\\classitemtagwidth}{\\it Source File:\\/}] %s\n", SourceFile );
X	(void) fprintf( o_fptr, "\\item[\\parbox{\\classitemtagwidth}{\\it Date:\\/}] %s\n", ctime( &FileTime ) );
X	(void) fprintf( o_fptr, "\\end{description}\n" );
X	(void) fprintf( o_fptr, "\\begin{center}\\rule{\\textwidth}{0.5mm}\\end{center}\n" );
X	if ( CommentPtr ) {
X		(void) fprintf( o_fptr, "\\begin{center}{\\LARGE\\bf Introduction}\\end{center}\n" );
X		
X		PrintComment( CommentPtr, ArgList, ArgCount );
X	}
X}
X
X
X
Xstatic void
XPrintInheritsList( i )
Xregister int i;
X{
X	while ( i != 0 ) {
X		(void) fprintf( o_fptr, ClassNameTable[i].class_name );
X		i = ClassNameTable[i].parent_class_index;
X		if ( i != 0 ) {
X			(void) fprintf( o_fptr, ", " );
X		}
X	}
X	fputc( '\n', o_fptr );
X}
X
X
Xstatic void
XPrintUsesList( bufp )
XIncludeBuf * bufp;
X{
X	while ( bufp != 0 && bufp->buf ) {
X		(void) fprintf( o_fptr, "%s", bufp->buf );
X		bufp = bufp->next;
X		if ( bufp != 0 && bufp->buf ) {
X			(void) fprintf( o_fptr, ", " );
X		}
X	}
X	fputc( '\n', o_fptr );
X}
X
X
Xvoid
XPrintMethod( MethodName, ArgList, ArgCount, CommentPtr )
Xchar * MethodName;
Xchar * ArgList[];
Xint ArgCount;
XCommentBuf * CommentPtr;
X{
X	register char *p;
X	register enum { roman, bold, italic } font;
X	
X	font = roman;
X	
X	(void) fprintf( o_fptr, "\\begin{description}\n\\item[" );
X
X	for ( p = MethodName; *p; ++p ) {
X		if ( (*p & 0x80) && font != bold ) {
X			if ( font == italic ) (void) fprintf( o_fptr, "\\/}" );
X			(void) fprintf( o_fptr, "{\\bf " );
X			font = bold;
X		} else if ( !(*p & 0x80) && font != italic ) {
X			if ( font == bold ) (void) fprintf( o_fptr, "}" );
X			(void) fprintf( o_fptr, "{\\it " );
X			font = italic;
X		}
X		PutLatexChar( *p, o_fptr );
X	}
X
X	if ( font != roman ) (void) fprintf( o_fptr, "}" );
X	(void) fprintf( o_fptr, "\\index{%s}", ArgList[0] );
X
X	/* Now print the comment.	*/
X	
X	(void) fprintf( o_fptr, "]\n\\mbox{}\n\n" );
X	PrintComment( CommentPtr, ArgList, ArgCount );
X       	(void) fprintf( o_fptr, "\\end{description}\n" );
X}
X
X
X
Xvoid
XPrintFunction( FunctionName, ArgList, ArgCount, CommentPtr )
Xchar * FunctionName;
Xchar * ArgList[];
Xint ArgCount;
XCommentBuf * CommentPtr;
X{
X	register char *p;
X	register enum { roman, bold, italic } font;
X	
X	font = roman;
X	
X	(void) fprintf( o_fptr, "\\begin{description}\n\\item[" );
X
X	for ( p = FunctionName; *p; ++p ) {
X		if ( (*p & 0x80) && font != bold ) {
X			if ( font == italic ) (void) fprintf( o_fptr, "\\/}" );
X			(void) fprintf( o_fptr, "{\\bf " );
X			font = bold;
X		} else if ( !(*p & 0x80) && font != italic ) {
X			if ( font == bold ) (void) fprintf( o_fptr, "}" );
X			(void) fprintf( o_fptr, "{\\it " );
X			font = italic;
X		}
X		PutLatexChar( *p, o_fptr );
X		if ( (*p & 0x7f) == ')' ) {
X			p++;
X			break;
X		}
X	}
X
X	if ( font != roman ) (void) fprintf( o_fptr, "}" );
X	(void) fprintf( o_fptr, "\\index{%s}", ArgList[0] );
X	(void) fprintf( o_fptr, "]\n\\mbox{}\n\n\\parbox{\\funkywidth}{\\it " );
X	for( ; *p; ++p ) {
X		PutLatexChar( *p, o_fptr );
X		if ( (*p & 0x7f) == ';' ) (void) fprintf( o_fptr, "\\\\\n" );
X	}
X	(void) fprintf( o_fptr, "}\n\n" );
X
X	/* Now print the comment.	*/
X	
X	PrintComment( CommentPtr, ArgList, ArgCount );
X       	(void) fprintf( o_fptr, "\\end{description}\n" );
X}
X
X
X
X/*
X * Print Comment
X * 	print out a comment.  Be picky about page breaks.
X */
X
Xvoid
XPrintComment( CommentPtr, ArgList, ArgCount )
XCommentBuf * CommentPtr;
Xchar *ArgList[];
Xint ArgCount;
X{
X	register char *p;
X	register int state	 = 0;
X	register int n;
X	int i;
X	register char * q;
X	
X	(void) fprintf( o_fptr, "{\\samepage " );
X	
X	while( CommentPtr ) {
X		for ( p = CommentPtr->buf, n = CommentPtr->n; n > 0; ++p, --n ) {
X
X			switch( state ) {
X			case 0:
X				if ( *p == '$' ) {
X					state = 2;
X				} else if ( !isspace( *p ) ) {
X					putc( *p, o_fptr );
X					state = 1;
X				}
X				break;
X
X			case 1:
X				if ( *p == '$' ) {
X					state = 2;
X				} else {
X					putc( *p, o_fptr );
X				}
X				break;
X
X			case 2:
X				if ( '0' <= *p && *p <= '9' ) {
X					i = *p - '0';
X					if ( i < ArgCount ) {
X						(void) fprintf( o_fptr, "{%s ", (i == 0) ? "\\bf" : "\\it" );
X						for ( q = ArgList[i]; q && *q && *q != ',' && *q != ';' && !isspace( *q ); ++q ) {
X							PutLatexChar( *q, o_fptr );
X						}
X						(void) fprintf( o_fptr, "%s}", ( i == 0 ) ? "" : "\\/" );
X					}
X				} else {
X					putc( *p, o_fptr );
X				}
X				state = 1;
X				break;
X			}
X		}
X		CommentPtr = CommentPtr->next;
X	}
X	(void) fprintf( o_fptr, "}\n" );
X		
X}
X
X
X/*
X * PutLatexChar
X *	Print out a character after attending to the fact that
X *	latex does horrible things witch certain characters.
X */
X
X
Xvoid
XPutLatexChar( c, fp )
Xregister char c;
XFILE * fp;
X{
X	c &= 0x7f;
X	
X	switch ( c ) {
X	case '#':
X	case '$':
X	case '%':
X	case '&':
X	case '~':
X	case '_':
X	case '^':
X	case '\\':
X	case '{':
X	case '}':
X		putc( '\\', fp );
X		break;
X	}
X	putc( c, fp );
X
X#ifdef	FOOBAR
X	/* Help latex with line breaking. */
X
X	switch( c ) {
X	case '_':
X	case ':':
X		putc( '\\', fp );
X		putc( '-', fp );
X		break;
X	}
X#endif	FOOBAR
-- 
Greg Franks   (613) 788-5726     Systems and Computer Engineering,
uunet!mitel!sce!greg (uucp)  	 Carleton University,
greg@sce.carleton.ca (bitnet)	 Ottawa, Ontario, Canada  K1S 5B6.
Overwhelm them with small bugs so that they don't see the big ones.


