program to create output with a table of contents
wise at cal-unix.UUCP
wise at cal-unix.UUCP
Wed Aug 17 23:16:55 AEST 1983
The table of contents program as originally given was excellent. However,
it seemed worthwhile to make a few minor modifications and one addition.
These changes are in our local version, and if you can use them,
they are:
An alphabetically sorted index is appended to the files.
If no file names are given, the standard input is read.
If a '-' (minus sign) is encountered in a file list, the standard
input is read.
My compliments to Mr. Breslin. The program was well done, which allowed me
to make these mods in less than an hour.
/*
* This program prints the files named in its argument list, preceding
* the output with a table of contents and appending an index.
* Each file is assumed to be C source code (but doesn't have to be) in
* that the program searches for the beginning and end of functions.
* Function names are added to the table of contents, provided the name
* starts at the beginning of a line. The function name in the output
* is double striken. White space is inserted after every terminating '}'
* character. Thus functions and structure declarations are nicely
* isolated in the output. The only drawback to this is that structure
* initialization tables sometimes produce large quantities of white
* space.
*
* The single option "-l" indicates that the following argument is to be
* the page length used for output (changing the page length hasn't been
* tested much).
*
* If no file names are given, stdin is read. '-' in the file list
* also causes stdin to be read.
*
* Try it! You'll like it. (I call it cpr.c)
*
* written by: Paul Breslin
* Human Computing Resources Corp.
* 10 St. Mary St.
* Toronto, Ontario
* Canada, M4Y 1P9
*
* decvax!utcsrgv!hcr!phb
*
* Index and standard input reading added by Rick Wise, CALCULON Corp.,
* Rockville, MD. -- decvax!harpo!seismo!rlgvax!cvl!umcp-cs!cal-unix!wise
*/
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#define BP 0xC /* Form feed */
FILE *File;
int Braces; /* Keeps track of brace depth */
int LineNumber; /* Count output lines */
int PageNumber = 1; /* You figure this one out */
int PageLength = 66; /* Normal paper length */
int PageEnd; /* Accounts for space at bottom */
int InComment;
int InString;
char *Name; /* Current file name */
char FunctionName[40];
char *ProgName;
char *Today;
main(argc, argv)
int argc;
char **argv;
{
register int i;
char *ctime();
long thetime, time();
ProgName = argv[0];
thetime = time(0);
Today = ctime(&thetime);
if( argv[1][0] == '-' && argv[1][1] == 'l' && argv[1][2] == '\0' )
{
PageLength = atoi(argv[2]);
i = 3;
if( argc < 3 ) Usage();
}
else
{
i = 1;
if( argc < 1 ) Usage();
}
PageEnd = PageLength - (PageLength / 20);
StartTempFile();
if (i == argc) { /* no file names */
File = stdin;
Name = "standard input";
List();
}
for(; i < argc; ++i )
{
if ( ! strcmp (argv[i], "-")) {
File = stdin;
Name = "standard input";
}
else {
if( (File = fopen( Name = argv[i], "r" )) == NULL ) {
fprintf(stderr, "%s: Can't open file \"%s\"\n",
ProgName, Name );
continue;
}
}
List();
if (File != stdin)
fclose(File);
}
if( PageNumber > 1 || LineNumber > 0 )
putchar(BP);
ListIndex();
EndTempFile();
DumpTableOfContents();
DumpTempFiles();
Done();
}
Usage()
{
fprintf(stderr, "Usage: %s [-l pagelength] file ...\n", ProgName);
exit(1);
}
int SaveOut;
char *TempName;
char *Temp2Name;
StartTempFile()
{
extern char *mktemp();
CatchSignalsPlease();
SaveOut = dup(1);
TempName = mktemp("/tmp/cprXXXXXX");
if( freopen(TempName, "w", stdout) == NULL )
{
fprintf(stderr, "%s: Can't open temp file!\n", ProgName);
exit(1);
}
}
EndTempFile()
{
Temp2Name = mktemp("/tmp/CPRXXXXXX");
if( freopen(Temp2Name, "w", stdout) == NULL )
{
fprintf(stderr, "%s: Can't open temp file!\n", ProgName);
exit(1);
}
}
DumpTempFiles()
{
register int pid, w;
fclose(stdout);
dup2(SaveOut, 1);
while( (pid = fork()) < 0 ) sleep(1);
if( pid )
while ((w = wait(0)) != pid && w != -1);
else
{
execl( "/bin/cat", "cat", Temp2Name, TempName, 0 );
fprintf(stderr, "%s: exec failed!\n", ProgName);
exit(0);
}
}
Done()
{
signal(SIGQUIT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
if( TempName ) unlink( TempName );
if( Temp2Name ) unlink( Temp2Name );
exit(0);
}
CatchSignalsPlease()
{
signal(SIGQUIT, Done);
signal(SIGHUP, Done);
signal(SIGINT, Done);
}
List()
{
register int bp;
char buffer[256];
NewPage();
NewFile();
bp = Braces = 0;
while( fgets(buffer, 256, File) != NULL )
{
if( bp )
NewFunction();
if( ++LineNumber > PageEnd ) NewPage();
if( (Braces == 0) && LooksLikeFunction(buffer) )
AddToTableOfContents();
bp = PutLine(buffer);
}
}
PutLine(l)
register char *l;
{
extern char *EndComment();
extern char *EndString();
register char c;
int bp;
char *save;
save = l;
bp = 0;
for( save = l; c = *l; ++l )
if( InComment )
l = EndComment(l);
else if( InString )
l = EndString(l);
else
switch(c)
{
case '{':
++Braces;
break;
case '}':
if( --Braces == 0 )
bp = 1;
break;
case '\'':
++l;
break;
case '"':
InString = 1;
break;
case '/':
if( *(l+1) == '*' )
{
InComment = 1;
++l;
}
break;
}
printf("%s", save);
return(bp);
}
char *
EndComment(p)
register char *p;
{
register char c;
while( c = *p++ )
if( c == '*' && *p == '/' )
{
InComment = 0;
break;
}
return(p-1);
}
char *
EndString(p)
register char *p;
{
register char c;
while( c = *p++ )
if( c == '\\' )
{
++p;
continue;
}
else if( c == '"' )
{
InString = 0;
break;
}
return(p-1);
}
NewFunction()
{
register int i;
if( LineNumber > (PageLength * 3 / 4) )
NewPage();
else
{
for( i=0; i < (PageLength/7); ++i ) putchar('\n');
LineNumber += PageLength/7;
}
}
#define HEADER_SIZE 3
NewPage()
{
if( LineNumber > HEADER_SIZE )
{
if( PageNumber >= 0 ) ++PageNumber;
putchar(BP);
LineNumber = 0;
}
if( LineNumber == 0 )
PutHeader();
}
PutHeader()
{
register int i, l, j;
putchar('\n');
l = strlen(Name);
for( j=0; j < 3; ++j )
{
printf("%s", Name);
if( j < 2 )
for( i=0; i < l; ++i ) putchar('\b');
}
if( PageNumber > 0 )
{
for( i = (l+7)/8; i < 9; ++i ) putchar('\t');
printf("Page: %d\n\n", PageNumber);
}
else
{
for( i = (l+7)/8; i < 7; ++i ) putchar('\t');
printf("%s\n\n", Today);
}
LineNumber += HEADER_SIZE;
}
#define isidchr(c) (isalnum(c) || (c == '_'))
LooksLikeFunction(s)
register char *s;
{
register char *p;
register int i;
char *save;
if( InComment || InString ) return(0);
p = FunctionName;
save = s;
if( *s == '*' ) ++s;
if( (*s == '_') || isalpha(*s) )
{
while( isidchr(*s) )
*p++ = *s++;
*p = '\0';
while( *s == ' ' ) ++s;
if( *s != '(' ) return(0);
while( *s ) if( *s == ')' ) break; else ++s;
if( !*s ) return(0);
/*
* This will cause the function name part of the line to
* be double striken.
*/
for( i=0; *save && *save != '('; ++i ) putchar(*save++);
while( i --> 0 ) putchar('\b');
return(1);
}
return(0);
}
char *Toc[1024];
int TocPages[1024];
int TocCount;
AddToTableOfContents()
{
register int l;
register char *p;
l = strlen(FunctionName);
p = Toc[TocCount] = (char *)malloc(l+1);
strcpy(p, FunctionName);
TocPages[TocCount] = PageNumber;
++TocCount;
}
NewFile()
{
register int i, l;
char temp[20];
Toc[TocCount] = (char *)malloc(130);
sprintf(Toc[TocCount], "\n\tFile: %s ", Name);
l = strlen(Toc[TocCount]) - 1;
if( l < 64 )
{
i = (64 - l) / 8;
for( l=0; l < i; ++l ) strcat(Toc[TocCount], "\t");
}
sprintf(temp, " Page %d\n", PageNumber);
strcat(Toc[TocCount], temp);
++TocCount;
}
DumpTableOfContents()
{
register int i, j, l;
if( TocCount == 0 ) return;
Name = "Table of Contents";
PageNumber = -1;
LineNumber = 0;
NewPage();
for( i=0; i < TocCount; ++i )
{
if( Toc[i][0] == '\n' )
{
if( (LineNumber + 5) > PageEnd )
NewPage();
printf("%s", Toc[i]);
LineNumber += 2;
continue;
}
if( ++LineNumber > PageEnd )
NewPage();
printf("\t\t%s ", Toc[i]);
l = strlen(Toc[i]);
for( j=l; j < 48; ++j ) putchar('.');
printf(" %d\n", TocPages[i]);
}
putchar(BP);
}
ListIndex()
{
register int i, j, l;
int index[1024],
temp,
flag;
if( TocCount == 0 ) return;
for (i = 0; i < TocCount; i++)
index[i] = i;
do {
flag = 0;
for (i = 0; i < TocCount - 1; i++) {
if (Toc[index[i]][0] == '\n' || Toc[index[i+1]][0] == '\n')
continue; /* don't sort across file names */
if (strcmp (Toc[index[i]], Toc[index[i+1]]) > 0) {
temp = index[i];
index[i] = index[i+1];
index[i+1] = temp;
flag = 1;
}
}
} while (flag);
Name = "Index";
PageNumber = -1;
LineNumber = 0;
NewPage();
for( i=0; i < TocCount; ++i )
{
if( Toc[index[i]][0] == '\n' )
{
if( (LineNumber + 5) > PageEnd )
NewPage();
printf("%s", Toc[index[i]]);
LineNumber += 2;
continue;
}
if( ++LineNumber > PageEnd )
NewPage();
printf("\t\t%s ", Toc[index[i]]);
l = strlen(Toc[index[i]]);
for( j=l; j < 48; ++j ) putchar('.');
printf(" %d\n", TocPages[index[i]]);
}
putchar(BP);
}
More information about the Comp.sources.unix
mailing list