Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site hcr.UUCP Path: utzoo!hcr!phb From: phb@hcr.UUCP (Paul Breslin) Newsgroups: net.sources Subject: program to create output with a table of contents Message-ID: <457@hcr.UUCP> Date: Wed, 3-Aug-83 17:08:07 EDT Article-I.D.: hcr.457 Posted: Wed Aug 3 17:08:07 1983 Date-Received: Wed, 3-Aug-83 18:46:20 EDT Organization: Human Computing Resources, Toronto Lines: 418 /* * This program prints the files named in its argument list, preceding * the output with a table of contents. 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). * * 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 */ #include#include #include #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) 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(); for(; i < argc; ++i ) { if( (File = fopen( Name = argv[i], "r" )) == NULL ) { fprintf(stderr, "%s: Can't open file \"%s\"\n", ProgName, Name ); continue; } List(); fclose(File); } if( PageNumber > 1 || LineNumber > 0 ) putchar(BP); 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); }