home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume9
/
cpr_dt
< prev
next >
Wrap
Text File
|
1989-11-26
|
49KB
|
1,887 lines
Newsgroups: comp.sources.misc
organization: AT&T Bell Labs - Lincroft, NJ
subject: v09i010: New version of CPR - C Pretty-printer
from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Reply-To: dmt@pegasus.ATT.COM (Dave Tutelman)
Posting-number: Volume 9, Issue 10
Submitted-by: dmt@pegasus.ATT.COM (Dave Tutelman)
Archive-name: cpr_dt
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
: readme cpr.c parsargs.c list.c fold.c report.c wildfile.c cpr.h makefile
echo extracting - readme
sed 's/^X//' > readme << '!EOR!'
X
X README FILE FOR CPR
X ^^^^^^^^^^^^^^^^^^^
X
XOK, we gotta have a README file, so you can tell what this does and
Xwhere it came from. Well, I pulled it off the net myself early this
Xyear (1989), and found it sort of useful. It's a pretty-printer for
XC programs.
X
XWHAT IT DOES:
X - Paginates, with meaningful page headers.
X - Makes a table of contents for files and functions.
X - Won't start a function at the bottom of a page. (In fact,
X has an option to print only one function per page.)
X
XWHAT IT DOESN'T DO:
X - Indent.
X - Put brackets on separate lines.
X - Other stuff that "C beautifiers" do.
X
XWhen I inherited a couple of pretty big C programs to maintain, the
Xfirst thing I did was to try to get a bunch of listings with CPR. I
Xfound that CPR as I received it wasn't up to the job. It certainly
Xwas after I added a few enhancements. Here's the enhanced version,
Xcast back upon the waters of the net. The enhancements are:
X
X - Any arguments can appear in a file rather than on the command
X line, and in pretty free form. (As received, you could only have
X filename arguments in a file, one name per line.)
X - The table of contents can contain a single sorted index of
X all functions across all files.
X - The option "-?" will give a help screen for the options
X (more like the PC idiom than the usual UNIX utility).
X - Lines can be "intelligently" folded if they go beyond the
X width of a page. (You wouldn't believe this program I
X inherited, and its 160-column lines.)
X
XThis remains public domain, which is as I found it. (It's free, and
Xworth every penny :-)
X
X Dave Tutelman
XPHYSICAL: 16 Tilton Drive AT&T Bell Labs
X Wayside, NJ 07712 Lincroft, NJ 07738
XAUDIBLE: (201) 922-9576 (201) 576-2194
XLOGICAL: att!pegasus!dmt
X
XContributors to the code include:
X * Written by:
X * Paul Breslin
X * Human Computing Resources Corp.
X * 10 St. Mary St.
X * Toronto, Ontario
X * Canada, M4Y 1P9
X *
X * -- ...!decvax!utcsrgv!hcr!phb
X *
X * Sorting and standard input reading from:
X * Rick Wise, CALCULON Corp., Rockville, MD.
X * -- ...!decvax!harpo!seismo!rlgvax!cvl!umcp-cs!cal-unix!wise
X *
X * File modified time,
X * numbered output,
X * optional white space,
X * improved function start tests from:
X * David Wasley, U.C.Berkeley
X * -- ...!ucbvax!topaz.dlw
X *
X * Modified the -r to leave variable amounts of space
X * Patrick Powell, U. Waterloo
X *
X * Changed handling of form feeds to start a new page AND print heading:
X * Terry Doner, U of Waterloo
X *
X * Fixed up to locate more functions, and added -p option
X * Dennis Vadura, U of Waterloo
X *
X * It will find things like struct foo *f()...
X * but not things like int
X * f
X * ()...
X * ie. the constraint is that the () must appear on the same line
X * as the function name.
X *
X * Clean up a bit for 80286 machines (lints a bit cleaner, too)
X * Dan Frank, Prairie Computing
X *
X * Fixed a whole bunch of stuff and added lots of new flags.
X * -S sort and be case insensitive.
X * -N start numbering pages at 1 for each new file
X * -T title cat the file title before the table of contents.
X * -C print only the table of contents
X * -c only try to look for function names in files whose suffix ends
X * in .c
X * -f file to handle file containing list of files to print. (for MSDOS)
X * Dennis Vadura
X *
X * Set to work better in MS-DOS (and Turbo C).
X * Ported to Turbo C on MS-DOS.
X * Enabled wildcard expansion for systems that don't support it.
X * Broke BIG source file into several C files plus header.
X * Fixed argument parsing to be more forgiving.
X * Changed -f option to handle all args in a free-form file,
X * not just filenames.
X * Added options:
X * -? Help screen.
X * -x,-X Sort TOC across files, giving function index (xref-like?).
X * -w (n) Fold lines to a page width (fairly good-looking line folding).
X * Dave Tutelman - att!pegasus!dmt - 10/89
X
X
!EOR!
echo extracting - cpr.c
sed 's/^X//' > cpr.c << '!EOR!'
X/* CPR - Pretty-Printer for C programs
X *
X * This program prints the files named in its argument list, preceding
X * the output with a table of contents. Each file is assumed to be C
X * source code (but doesn't have to be) in that the program searches
X * for the beginning and end of functions. Function names are added to
X * the table of contents, provided the name starts at the beginning of
X * a line. The function name in the output is double striken.
X *
X * PAGE SIZE
X * The option "-l" indicates that the following argument is to be
X * the page length used for output (changing the page length hasn't been
X * tested much).
X * The option "-w" indicates that the following argument is to be
X * the page width (and lines are folded to that width, using a
X * reasonably aesthetic folding algorithm). The default, in the
X * absence of "-w" is not to fold lines.
X *
X * NUMBERING OF LINES & PAGES
X * The option "-n" indicates that output lines should be numbered with
X * the corresponding line number from the input file.
X * The option "-N" indicates that page numbers start at 1 within each
X * file.
X *
X * FORMATTING THE PROGRAM
X * The option "-p" indicates what proportion of the page in steps of 16
X * should be used for deciding if a new function needs a new page.
X * That is -p12 (the default) indicates that if a function starts
X * within the top 12/16 (3/4) of the page then do it, otherwise put it
X * on a new page. Thus the higher the number (upto 16) the closer to
X * the bottom of the page will functions be started. -p0 says put each
X * func on a new page.
X *
X * By default blank space is inserted after every closing '}'
X * character. Thus functions and structure declarations are nicely
X * isolated in the output. The only drawback to this is that structure
X * initialization tables sometimes produce lots of white space.
X * The "-r" option removes this space, or changes it to the indicated
X * length.
X *
X * TABLE OF CONTENTS OPTIONS
X * The option "-s" indicates that the table of contents should be sorted
X * by function name within each file.
X * The option "-S" also calls for a sorted table of contents, but with
X * a case-insensitive sort.
X * The option "-x" indicates that the table of contents should include
X * a sorted index of functions across all files.
X * The option "-X" also calls for a sorted index of functions, but with
X * a case-insensitive sort.
X *
X * The option "-C" indicates that ONLY the table of contents is to
X * be printed, not the source files themselves.
X *
X * The option "-c" indicates that only files with the extension ".c"
X * should be examined for files to list in the table of contents.
X *
X * The option "-T" indicates that the following argument is a file
X * name; the contents of that file is to be printed verbatim in the
X * output before the table of contents, as a Title Paragraph.
X *
X * MISCELLANEOUS OPTIONS
X * The option "-?" indicates that a help screen for CPR be sent
X * to stderr (generally the screen), but no processing done.
X * The help screen is more verbose than the usage message that's
X * printed on error, and summarizes all options of CPR.
X *
X * The option "-f" indicates that the following argument is a file
X * name; the contents of that file are to be treated just as command
X * line arguments. (Thus you can, for example, make a ".cprrc" file
X * with the right options and source files, in each of your
X * source directories.)
X *
X * HISTORY
X *
X * Written by:
X * Paul Breslin
X * Human Computing Resources Corp.
X * 10 St. Mary St.
X * Toronto, Ontario
X * Canada, M4Y 1P9
X *
X * -- ...!decvax!utcsrgv!hcr!phb
X *
X * Sorting and standard input reading from:
X * Rick Wise, CALCULON Corp., Rockville, MD.
X * -- ...!decvax!harpo!seismo!rlgvax!cvl!umcp-cs!cal-unix!wise
X *
X * File modified time,
X * numbered output,
X * optional white space,
X * improved function start tests from:
X * David Wasley, U.C.Berkeley
X * -- ...!ucbvax!topaz.dlw
X * Modified the -r to leave variable amounts of space
X * Patrick Powell, U. Waterloo
X *
X * Changed handling of form feeds to start a new page AND print heading:
X * Terry Doner, U of Waterloo
X *
X * Fixed up to locate more functions, and added -p option
X * Dennis Vadura, U of Waterloo
X *
X * It will find things like struct foo *f()...
X * but not things like int
X * f
X * ()...
X * ie. the constraint is that the () must appear on the same line
X * as the function name.
X *
X * Clean up a bit for 80286 machines (lints a bit cleaner, too)
X * Dan Frank, Prairie Computing
X *
X * Fixed a whole bunch of stuff and added lots of new flags.
X * -S sort and be case insensitive.
X * -N start numbering pages at 1 for each new file
X * -T title cat the file title before the table of contents.
X * -C print only the table of contents
X * -c only try to look for function names in files whose suffix ends
X * in .c
X * -f file to handle file containing list of files to print. (for MSDOS)
X * Dennis Vadura
X *
X * Set to work better in MS-DOS (and Turbo C).
X * Ported to Turbo C on MS-DOS.
X * Enabled wildcard expansion for systems that don't support it.
X * Broke BIG source file into several C files plus header.
X * Fixed argument parsing to be more forgiving.
X * Changed -f option to handle all args in a free-form file,
X * not just filenames.
X * Added options:
X * -? Help screen.
X * -x,-X Sort TOC across files, giving function index (xref-like?).
X * -w (n) Fold lines to a page width (fairly good-looking line folding).
X * Dave Tutelman - att!pegasus!dmt - 10/89
X */
X
X#include <sys/types.h>
X#include <ctype.h>
X#include <stdio.h>
X#include <signal.h>
X#include <string.h>
X
Xchar *synopsis [] = {
X"OPTIONS:",
X"-c Look for functions only if file is a '.c' file.",
X"-C Produce ONLY table of contents, no listing.",
X"-n Number lines in the listing.",
X"-N Start each file listing on page 1.",
X"-s Sort table of contents by function name (in each file).",
X"-S Like -s, but case-insensitive.",
X"-x,-X Like -s, -S, but sorts across files (Xref-like function index).",
X"-l n Page length. (Default = 66)",
X"-w n Page width, at which to fold lines. (Default = don't fold lines)",
X"-p n How many 16ths of a page can be used, and still start a new function",
X" on this page? (-p0 puts a new function on each page. Default = 12)",
X"-r n How many blank lines to leave after a '}'. (Default = 5)",
X"-t n Width of a tab stop. (Default = 8)",
X"-T title Print contents of file 'title' before table of contents.",
X"-f argfile Take next few arguments from file 'argfile'.",
X"- File name for the Standard Input.",
X'\0'
X};
X
X#define MAIN
X#include "cpr.h"
X
X/* Some macros for parsing parameters from the argument list */
X#define NEXPARM NexParm (&i,&parm, argc,argv)
X#define NUMPARM NumParm (&i,&parm, argc,argv)
X#define STRPARM StrParm (&i,&parm, argc,argv)
X
X#ifdef NOWILD
Xint NextName=0; /* Use next_file function to expand wildcard */
Xchar *first_file(), *next_file();
X#endif
X
Xchar *GetProgName();
Xchar *StrParm();
X
Xmain(argc, argv)
Xchar **argv;
X{
X int i;
X char *ctime();
X time_t thetime, time();
X char *parm; /* points to next thing to do in an arg */
X int num;
X int FirstFile=1;
X
X ProgName = GetProgName (argv[0]);
X thetime = time((time_t *)0);
X strcpy(Today,ctime(&thetime));
X
X if (argc < 2) Synop();
X
X i = 0;
X while ((i = NEXPARM) >0) /* get next argument if there is one */
X {
X if( arg[0] == '?'
X && arg[1] == '\0' ) Synop();
X
X if( arg[0] != '-' || arg[1] == '\0' ) { /* file name */
X parm--; /* back off to get whole name */
X Name = STRPARM;
X if (NULLSTR( Name )) Usage();
X if (FirstFile) {
X FirstFile=0;
X StartTempFile();
X }
X DoFile (Name);
X }
X
X else { /* this arg is options */
X switch( *parm ) {
X case '-':
X break; /* skip. just leading - for options */
X
X case '\0': /* check for end of this argument */
X case ' ': /* just for safety. */
X case '\t':
X case '\n':
X case '\r':
X break;
X
X case '?': Synop();
X
X case 'f': /* get next args from a file */
X listn = STRPARM; /* get next string parameter */
X if (NULLSTR( listn )) Usage();
X if ((listf = fopen (listn, "r")) == NULL) {
X fprintf(stderr,"%s: list file '%s' not found\n",
X ProgName, listn);
X exit (1);
X }
X InArgFile = 1;
X break;
X
X case 't':
X TabWidth = NUMPARM;
X if( TabWidth == -1) TabWidth = 0;
X if( TabWidth < 0 ) TabWidth = 0;
X break;
X
X case 'T':
X TitleFile = STRPARM;
X if (NULLSTR( TitleFile )) Usage();
X if ((Tfile = fopen (TitleFile, "r")) == NULL) {
X fprintf(stderr,"%s: title file '%s' not found\n",
X ProgName, TitleFile);
X exit (1);
X }
X ++Title;
X break;
X
X case 'l':
X PageLength = NUMPARM;
X if( PageLength == -1) Usage();
X if( PageLength < 10) PageLength = 10;
X PageEnd = PageLength - ((PageLength > 30) ? 7 : 1);
X break;
X
X case 'w':
X PageWidth = NUMPARM;
X if( PageWidth == -1 ) Usage();
X if( PageWidth < 0 ) PageWidth = 0;
X break;
X
X case 'S':
X ++CaseInsensitive;
X case 's':
X ++SortFlag;
X break;
X
X case 'X':
X ++CaseInsensitive;
X case 'x':
X ++SortFlag;
X ++XrefFlag;
X if (ResetPage) {
X fprintf(stderr,"%s: options -X and -N are incompatible\n",
X ProgName);
X exit (1);
X }
X break;
X
X case 'C':
X ++ContentsOnly;
X break;
X
X case 'c':
X ++OnlyCFiles;
X break;
X
X case 'n':
X ++NumberFlag;
X FirstCol = FORMATWIDTH; /* leave room for line numbering */
X break;
X
X case 'N':
X ++ResetPage;
X if (XrefFlag) {
X fprintf(stderr,"%s: options -X and -N are incompatible\n",
X ProgName);
X exit (1);
X }
X break;
X
X case 'r':
X Space_to_leave = NUMPARM;
X if (Space_to_leave == -1) Space_to_leave = 0;
X if (Space_to_leave < 0) Space_to_leave = 0;
X break;
X
X case 'p':
X PagePart = NUMPARM;
X if ( PagePart == -1) Usage();
X if ( PagePart < 0) PagePart = 0;
X if ( PagePart > 16) PagePart = 16;
X break;
X
X default:
X Usage();
X break;
X } /* end 'switch' */
X } /* end 'else' */
X } /* end 'while' */
X
X /* All files processed. Print the listings. */
X if( PageNumber > 1 || LineNumber > 0 )
X putchar(BP);
X EndTempFile();
X
X DumpTableOfContents();
X DumpTempFiles();
X Done();
X}
X
XUsage()
X{
X fprintf(stderr, "%s: Problem with argument %s", ProgName, arg);
X if (InArgFile) fprintf(stderr, " in argument file\n");
X else fprintf(stderr, "\n"); /* yeah, I know ... */
X fprintf(stderr, "Usage: %s [-?cCnNsSxX] [-t tabwidth] [-l pagelength] ",ProgName);
X fprintf(stderr, "[-w pagewidth]\n\t[-p[num]] [-r[num]] [-T title] [[-f] file] ...");
X exit(1);
X}
X
XSynop()
X{
X int i;
X
X fprintf(stderr,"Synopsis:\n%s [options] [filenames]\n\n", ProgName);
X for (i=0; *synopsis[i] != '\0'; i++)
X fprintf (stderr,"%s\n",synopsis[i]);
X exit(1);
X}
X
Xchar *
XGetProgName (s) /* We need to strip off path information, if there */
Xchar *s;
X{
X char *p;
X
X for (p=s; *p!='\0'; p++); /* get end of string */
X while (--p >= s) {
X#ifdef MSDOS
X if (*p == '.')
X *p='\0'; /* strip off .EXE extension */
X#endif
X if ((*p=='/') || (*p=='\\'))
X break;
X }
X return (++p);
X}
X
X
X/* Do the processing necessary to format one file */
XDoFile (fname)
X char *fname;
X{
X if (*fname=='-' && *(fname+1)=='\0') {
X File = stdin;
X Name = "Standard Input";
X List();
X return;
X }
X#ifndef NOWILD
X if( (File = fopen( fname, "r" )) == NULL )
X {
X fprintf(stderr,"%s: Can't open file '%s': %s\n",
X ProgName, Name, sys_errlist[errno] );
X }
X List();
X fclose(File);
X
X#else /* expand wildcards explicitly */
X Name = first_file (fname);
X while ((Name != NULL) && (*Name != '\0')) {
X if( (File = fopen( Name, "r" )) == NULL )
X {
X fprintf(stderr,"%s: Can't open file '%s': %s\n",
X ProgName, Name, sys_errlist[errno] );
X continue;
X }
X List();
X fclose(File);
X
X Name = next_file ();
X }
X#endif
X}
X
X
Xint SaveOut;
Xchar *TempName;
Xchar *Temp2Name;
X
XStartTempFile()
X{
X int Done();
X extern char *mktemp();
X
X CatchSignalsPlease(Done);
X
X SaveOut = dup(1);
X#ifdef MSDOS
X TempName = "cpr0001.tmp";
X#else
X TempName = mktemp("/tmp/cprXXXXXX");
X#endif
X if( freopen(TempName, "w", stdout) == NULL )
X {
X fprintf(stderr, "%s: Can't open temp file '%s': %s\n", ProgName,
X TempName, sys_errlist[errno]);
X exit(1);
X }
X}
X
XEndTempFile()
X{
X#ifdef MSDOS
X Temp2Name = "cpr0002.tmp";
X#else
X Temp2Name = mktemp("/tmp/cprXXXXXX");
X#endif
X if( freopen(Temp2Name, "w", stdout) == NULL )
X {
X fprintf(stderr, "%s: Can't open temp file '%s': %s\n", ProgName,
X Temp2Name, sys_errlist[errno]);
X exit(1);
X }
X}
X
XDumpTempFiles()
X{
X FILE *f;
X char b[256];
X register int pid, w;
X
X fclose(stdout);
X
X#ifndef MSDOS
X dup(SaveOut);
X while( (pid = fork()) < 0 ) sleep(1);
X if( pid )
X while ((w = wait((int *)0)) != pid && w != -1);
X else
X {
X CatchSignalsPlease(SIG_DFL);
X
X if( ContentsOnly )
X execl( "/bin/cat", "cat", Temp2Name, (char *)0 );
X else
X execl( "/bin/cat", "cat", Temp2Name, TempName, (char *)0 );
X fprintf(stderr, "%s: exec of /bin/cat failed: %s\n", ProgName,
X sys_errlist[errno]);
X exit(0);
X }
X#else
X CatchSignalsPlease(SIG_DFL);
X if( (f=fopen(Temp2Name,"r")) == NULL )
X fprintf(stderr,"%s: Can't open file '%s': %s\n",
X ProgName, TitleFile, sys_errlist[errno] );
X else
X {
X while( fgets(b, 256, f) != NULL )
X write(SaveOut,b,strlen(b));
X
X fclose(f);
X }
X
X if( !ContentsOnly )
X if( (f=fopen(TempName,"r")) == NULL )
X fprintf(stderr,"%s: Can't open file '%s': %s\n",
X ProgName, TitleFile, sys_errlist[errno] );
X else
X {
X while( fgets(b, 256, f) != NULL )
X write(SaveOut,b,strlen(b));
X
X fclose(f);
X }
X#endif
X}
X
XDone()
X{
X CatchSignalsPlease(SIG_DFL);
X
X fclose( stdout );
X if( TempName ) unlink( TempName );
X if( Temp2Name ) unlink( Temp2Name );
X
X exit(0);
X}
X
XCatchSignalsPlease(action)
Xvoid (*action)();
X{
X#ifndef TURBOC
X if( signal(SIGINT, SIG_IGN) != SIG_IGN ) signal(SIGINT, action);
X#else /* TURBOC */
X signal (SIGINT, action);
X#endif
X#ifndef MSDOS
X if( signal(SIGQUIT, SIG_IGN) != SIG_IGN ) signal(SIGQUIT, action);
X if( signal(SIGHUP, SIG_IGN) != SIG_IGN ) signal(SIGHUP, action);
X#endif
X}
X
!EOR!
echo extracting - parsargs.c
sed 's/^X//' > parsargs.c << '!EOR!'
X/* PARSARGS
X *
X * Functions to get parameters from:
X * - The command line.
X * - The argument file (if -f option is used).
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "cpr.h"
X
X
X/* Get the next parameter, and point to it with *pp.
X * Return current index into argv[], or -1 if no more parameters.
X * Put NEW argument into arg[], but just bump *pp if there's still
X * more to do in arg[].
X * Get NEW argument from argv[] or list file, depending on InArgFile.
X */
X
Xint
XNexParm (ip,pp, argc,argv)
X int *ip; /* pointer to arg[] index */
X char **pp; /* pointer to parm, which is (char *) */
X int argc;
X char *argv[];
X{
X int i = *ip;
X char *p = *pp;
X int c;
X int InArg = 0; /* state variable */
X int GotArg = 0;
X
X if (i==0) { /* need to initialize */
X strcpy (arg, argv[1]);
X *pp = arg;
X *ip = 1;
X return (1);
X }
X
X p++; /* bump the parameter pointer */
X
X if (WHITESPACE( *p )) { /* need a new arg */
X arg[0] = '\0'; /* blank the beginning of the arg[] array */
X if (InArgFile) { /* get the new arg from listf */
X p = arg;
X while (!GotArg) {
X c=getc (listf);
X if (!InArg) {
X if (c == EOF) { /* no more in listf */
X InArgFile = 0;
X GotArg++;
X }
X else if (!WHITESPACE( (char)c )) InArg++;
X }
X if (InArg) {
X if (WHITESPACE( (char)c ) || c==EOF) {
X *p = '\0';
X GotArg++;
X }
X else if (!WHITESPACE( (char)c )) *p++ = c;
X }
X } /* end while (!GotArg) */
X } /* end if (InArgFile) */
X
X if (arg[0]=='\0') { /* get the new arg from command line */
X if (++i >= argc) return (-1);
X strcpy (arg, argv[i]);
X *ip = i;
X GotArg++;
X }
X *pp = arg;
X } /* end of "need new arg" */
X
X else if (!GotArg) /* not a new arg, just bump pointer */
X *pp = p;
X
X return ( i );
X}
X
Xint
XNumParm (ip, pp, argc,argv) /* Returns next parameter as an integer if it
X * is a number. Otherwise returns -1. */
X int *ip; /* pointer to argument counter in main program */
X char **pp; /* pointer to "parm" pointer in main program */
X int argc;
X char *argv[];
X{
X int num=0; /* number accumulator */
X int i;
X char *p;
X
X /* Bump to next parm, if there is one */
X i = NexParm( ip, pp, argc, argv );
X if (i <= 0) return (-1);
X
X p = *pp; /* use updated parm pointer */
X
X /* is there at least one digit? */
X if (!isdigit( *p )) {
X *pp = p-1; /* back off to previous position */
X return (-1);
X }
X
X /* accumulate a decimal number */
X while (isdigit( *p ))
X num = 10*num + (int)(*p++ - '0');
X
X /* fix up pointers before returning */
X *pp = p-1; /* back off to end of number */
X return (num);
X}
X
X
Xchar *
XStrParm (ip, pp, argc,argv) /* Returns next string parameter if there
X * is one. Otherwise returns -1. */
X int *ip; /* pointer to argument counter in main program */
X char **pp; /* pointer to "parm" pointer in main program */
X int argc;
X char *argv[];
X{
X int i;
X char *p, *s;
X
X /* Bump to next parm, if there is one */
X i = NexParm( ip, pp, argc, argv );
X if (i <= 0) return (NULL);
X
X s = p = *pp; /* use updated parm pointer */
X if (WHITESPACE( *p )) return (NULL);
X
X /* Find end of string and null it out */
X while (! WHITESPACE( *p )) p++;
X *p = '\0'; /* now null-terminate the string */
X
X /* fix up pointers before returning */
X *pp = p-1; /* back off to end of string */
X return (s);
X}
X
!EOR!
echo extracting - list.c
sed 's/^X//' > list.c << '!EOR!'
X/* LIST.C
X *
X * Functions that go through the .C files,
X * parse them, and make entries in Table of Contents.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X#include "cpr.h"
X
Xint SawFunction;
Xint Braces;
X
X
XList()
X{
X register int bp;
X register char *bufp;
X char buffer[256];
X
X NewFile();
X bp = Braces = 0;
X InString = InComment = 0; /* reset for new file -DV */
X SawFunction = 0;
X bufp = buffer;
X while( fgets(bufp, sizeof(buffer), File) != NULL )
X {
X ++FileLineNumber;
X if( bp ) NewFunction();
X
X if( ++LineNumber >= PageEnd ) NewPage();
X
X if( bufp[0] == '\f'
X && bufp[1] == '\n'
X && bufp[2] == '\0' )
X {
X NewPage(); /* was strcpy(bufp, "^L\n");*/
X continue;
X }
X
X if( NumberFlag )
X {
X if( *bufp == '\n' )
X printf(BLANKFORMAT);
X else
X printf(NUMFORMAT, FileLineNumber);
X }
X if( (Braces == 0) && LooksLikeFunction(bufp) )
X AddToTableOfContents(NEWFUNCTION);
X
X bp = ScanLine(buffer);
X }
X}
X
XScanLine(l)
Xregister char *l;
X{
X extern char *EndComment();
X extern char *EndString();
X register char c;
X int bp;
X char *save;
X
X /* initialize line-checking variables */
X bp = 0;
X
X /* Now scan the line */
X for( save = l; c = *l; ++l )
X if( InComment )
X l = EndComment(l);
X else if( InString )
X l = EndString(l);
X else
X switch(c)
X {
X case '{':
X ++Braces;
X break;
X
X case '}':
X if( --Braces == 0 )
X bp = 1;
X break;
X
X case '\'':
X for( ++l; *l && *l != '\''; ++l )
X if( *l == '\\' && *(l+1) ) ++l;
X break;
X
X case '"':
X InString = 1;
X break;
X
X case '/':
X if( *(l+1) == '*' )
X {
X InComment = 1;
X ++l;
X }
X break;
X }
X if (PageWidth) FoldLine( save );
X OutputLine( save );
X return(bp);
X}
X
Xchar *
XEndComment(p)
Xregister char *p;
X{
X register char c;
X
X /*
X * Always return pointer to last non-null char looked at.
X */
X while( c = *p++ ) {
X if( c == '*' && *p == '/' )
X {
X InComment = 0;
X return(p);
X }
X }
X return(p-2);
X}
X
Xchar *
XEndString(p)
Xregister char *p;
X{
X register char c;
X
X /*
X * Always return pointer to last non-null char looked at.
X */
X while( c = *p++ ) {
X if( c == '\\' && *p )
X {
X ++p;
X continue;
X }
X else if( c == '"' )
X {
X InString = 0;
X return(p-1);
X }
X }
X return(p-2);
X}
X
XNewFunction()
X{
X register int i;
X
X if( Space_to_leave <= 0 || !SawFunction ) return;
X if( LineNumber + Space_to_leave > (PageLength * PagePart /16) )
X NewPage();
X else
X {
X for( i=0; i < (Space_to_leave); ++i ) putchar('\n');
X LineNumber += Space_to_leave;
X }
X
X SawFunction = 0;
X}
X
X#define isidchr(c) (isalnum(c) || (c == '_'))
X
X/* This used to incorrectly identify a declaration such as
X * int (*name[])() = { initializers ... }
X * as a function. It also picked up this in an assembler file:
X * #define MACRO(x) stuff
X * MACRO(x):
X * Fixed both of these. -IAN!
X */
XLooksLikeFunction(s)
Xregister char *s;
X{
X register char *p;
X register int i;
X char *save;
X int t = TabWidth;
X
X if( InComment || InString ) return(0);
X if( OnlyCFiles )
X {
X char *e = Name+strlen(Name)-1;
X if(( *e != 'c'
X#ifdef MSDOS
X && *e != 'C'
X#endif
X ) || e[-1] != '.' ) return(0);
X }
X
X if( !t ) t = 8;
X save = s;
X
X i = 0;
X do
X {
X p = FunctionName;
X
X while( *s && (*s == ' ') || (*s == '\t') ) ++s;
X if( *s == '*' ) ++s;
X if( *s && (*s == ' ') || (*s == '\t') ) continue;
X if( !*s || ((*s != '_') && !isalpha(*s)) ) return(0);
X
X while( isidchr(*s) )
X *p++ = *s++;
X *p = '\0';
X
X while( *s && (*s == ' ') || (*s == '\t') ) ++s;
X i++;
X }
X while ( *s && *s != '(' && i < 4 );
X
X if( *s != '(' || *(s+1) == '*' ) return(0);
X
X for (i = 0; *s; s++)
X {
X switch( *s )
X {
X case '(':
X ++i;
X continue;
X
X case ')':
X --i;
X break;
X
X default:
X break;
X }
X if( i == 0 ) break;
X }
X if( !*s ) return(0);
X
X while( *s )
X {
X if( *s == '{') break;
X if( *s == ';' || *s == ':' ) return(0);
X ++s;
X }
X
X /*
X * This will cause the function name part of the line to
X * be double striken. Note that this assumes the name and the opening
X * parentheses are on the same line...
X */
X
X if( p = strchr( save, '(' ) )
X {
X p--;
X while( p != save && isidchr( *(p-1) ) ) p--;
X for( i=0; save != p; save++ )
X if( *save == '\t' )
X {
X putchar('\t');
X i = ((i+t)/t)*t;
X }
X else
X {
X putchar(' ');
X i++;
X }
X
X for( ; *p != '('; p++ )
X if( *p == '\t' )
X {
X putchar('\t');
X i = ((i+t)/t)*t;
X }
X else
X {
X putchar(*p);
X i++;
X }
X }
X else
X for( i=0; *save && (*save == '*' || isidchr(*save)); ++save)
X if( *save == '*' )
X {
X putchar(' ');
X i++;
X }
X else
X {
X if( *save == '\t' )
X i = ((i+t)/t)*t;
X else
X i++;
X putchar(*save);
X }
X
X while( i --> 0 ) putchar('\b');
X
X SawFunction = 1;
X return(1);
X}
!EOR!
echo extracting - fold.c
sed 's/^X//' > fold.c << '!EOR!'
X/* FOLD
X *
X * Functions to fold an output line.
X */
X
X#include <stdio.h>
X#include <string.h>
X#include "cpr.h"
X
X/* The criteria for folding a line are, in order of aethetic desirability: */
X#define COMMENT 0 /* Comment starts here */
X#define BRACKET 1 /* Curly open bracket */
X#define SEMICOLON 2 /* First non-blank after semicolon */
X#define BLANK 3 /* First non-blank after whitespace */
X#define PAREN 4 /* Open parenthesis */
X#define N_CRIT 5 /* Number of criteria for folding a line */
X#define CLEAR_CRIT { int i; for(i=0;i<N_CRIT;i++) crit[i]=NULL; }
X
Xint NeedFold = 0; /* Number of folds needed for this line */
Xint FoldCol = -1; /* Proposed left edge of folded line */
Xchar *folds [64]; /* Places to fold the current line */
X
Xchar *FoldHeuristic ();
X
X
XFoldLine (s) /* Put Fold Marks in the right place in the line */
X char *s;
X{
X char *p;
X int i;
X int col = 0; /* Current column in output line */
X char *NonBlank = NULL; /* First non-blank character */
X int CantFold = 0; /* Set it if we have trouble folding */
X
X /* Set up array of pointers into the line of possible places to fold,
X * in order of aesthetic desirability. */
X char *crit [N_CRIT];
X char *SemiWait = NULL, *BlankWait = NULL;
X
X CLEAR_CRIT;
X FoldCol = -1;
X NeedFold = 0; /* assume we won't need to fold line */
X
X if (! PageWidth) return; /* Don't bother folding lines */
X
X /* Step through line, looking for good places to fold */
X for (p=s; *p; p++) {
X switch (*p) {
X case '\n': /* ignore */
X break;
X
X case ' ': /* Whitespace is harmless */
X col++;
X BlankWait = p; /* remember we've seen a blank */
X break;
X
X case '\t': /* Space out a tab's worth */
X while ((++col) % TabWidth);
X col++;
X BlankWait = p; /* remember we've seen a blank */
X break;
X
X case '/':
X if (*(p+1) == '*') /* beginning of a comment */
X crit [COMMENT] = p;
X col++;
X break;
X
X case '{':
X if (*(p-1) != '\'')
X crit [BRACKET] = p;
X col++;
X break;
X
X case ';': /* Remember we've seen a semicolon */
X col++;
X if (*(p-1) != '\'')
X SemiWait = p;
X break;
X
X case '(':
X if (*(p-1) != '\'')
X crit [PAREN] = p;
X col++;
X break;
X
X default:
X col++;
X break;
X }
X
X /* If non-blank, do a few housekeeping things */
X if (*p!=' ' && *p!='\t' && *p!='\n') {
X if (FoldCol == -1) {
X NonBlank = p;
X FoldCol = col + 1;
X }
X if (BlankWait) { /* waiting after blank */
X crit [BLANK] = p;
X BlankWait = 0;
X }
X if (SemiWait && SemiWait!=p) {
X crit [SEMICOLON] = p;
X if (*p!=';') SemiWait = 0;
X }
X }
X
X /* Do we need to fold yet ? */
X if (col+FirstCol >= PageWidth && *p!=' ' && *p!='\t') {
X /* Can we fold? We can tell by checking our pointers
X * in order of decreasing aesthetic result of fold.
X */
X char *FoldHere;
X
X FoldHere = FoldHeuristic (s, NonBlank, crit);
X if (FoldHere)
X folds [NeedFold++] = FoldHere;
X else
X CantFold++;
X
X /* Do some cleaning up after folding */
X if (FoldHere) {
X col = FoldCol;
X p = FoldHere;
X
X CLEAR_CRIT;
X BlankWait = SemiWait = NULL;
X }
X }
X }
X if (CantFold) /* complain, but print anyway and continue */
X fprintf(stderr,"%s: trouble folding line %ld of file %s\n",
X ProgName, FileLineNumber, Name);
X}
X
X/* Output the line, folding where indicated in folds[] */
X
XOutputLine (p)
X char *p;
X{
X int i = 0;
X
X if (! NeedFold) /* don't bother folding lines */
X printf ("%s",p);
X
X else { /* gotta fold lines */
X for (; *p; p++) {
X if (p==folds[i] && i<NeedFold) { /* fold to a new line */
X putchar ('\n');
X if (++LineNumber >= PageEnd) NewPage();
X if (NumberFlag)
X printf (BLANKFORMAT);
X GoToColumn (FirstCol, FoldCol+FirstCol);
X i++;
X }
X putchar (*p);
X }
X }
X}
X
X/* Heuristic for determining where to fold */
X
X#define MAX( x, y ) ((x) > (y)) ? x : y
X#define MIN( x, y ) ((x) < (y)) ? x : y
X#define MAXC( c, j ) for(i=j=0;i<N_CRIT;i++) if(c[i]>c[j]) j=i
X
Xchar *
XFoldHeuristic (s, NonBlank, crit)
X char *s; /* pointer to line */
X char *NonBlank; /* pointer to first non-blank character */
X char *crit[]; /* pointers to likely places to fold, based on
X * aesthetic criteria */
X{
X int i,j;
X int score [N_CRIT]; /* keep some "scores" here */
X int credit; /* score value increments (in columns) */
X char *lptr; /* points to start of partial line */
X char *p;
X
X /* For each crit[] pointer, it's worthless as a folding point if it's
X * the first non-blank in the line. */
X for (i=0; i<N_CRIT; i++)
X if (crit[i]==NonBlank) crit[i] = NULL;
X
X /* Fold on a comment, if we've got one */
X if (crit [COMMENT]) return (crit [COMMENT]);
X
X /* For the rest, we'll compute some heuristic "scores".
X * Start by seeing how much of the partial line each crit picks up. */
X score [COMMENT] = 0;
X if (NeedFold) /* line already folded */
X lptr = folds [NeedFold-1];
X else
X lptr = NonBlank;
X for (i=1; i<N_CRIT; i++)
X if (crit [i])
X score [i] = crit [i] - lptr;
X else score [i] = 0;
X
X /* Adjust the scores according to some "feel for aesthetics".
X * Start by giving each criterion credit for its order in the array;
X * "credit" is measured by the number of columns it's worth.
X * We'll estimate a unit of "credit" as a fraction of the line
X * that we're trying to fill.
X */
X
X credit = PageWidth - (lptr - s); /* width of current partial */
X credit = credit / 10; /* "arbitrary" fraction of line */
X for (i=1; i<N_CRIT; i++)
X if (score [i])
X score [i] += (N_CRIT - i - 1) * credit;
X
X /* Next, see how "valuable" a paren is from its context. */
X if (p = crit [PAREN]) {
X char *pp;
X pp = p-1;
X if (*pp==' ' || *pp=='\t')
X score[PAREN] += 2 * credit;
X else if (*pp=='(') {
X /* Find the left edge of string of parens */
X while (--pp) {
X if (pp < lptr) {
X /* Parens all the way left. Quit */
X score[PAREN] -= credit;
X break;
X }
X else if (*pp==' ' || *pp=='\t') {
X /* Isolated! Point to it & give bonus */
X crit [PAREN] = pp+1;
X score[PAREN] = (pp - lptr) + 1 + 2*credit;
X break;
X }
X else if (*pp!='(') {
X /* Nothing special. Point & give small bonus */
X crit [PAREN] = pp+1;
X score[PAREN] = (pp - lptr) + credit;
X break;
X }
X /* If we got here, keep searching */
X }
X }
X else /* Nothing special. Small bonus */
X score [PAREN] += credit - 1;
X }
X
X /* Now, just return the highest score. */
X MAXC( score, j );
X return ( crit[j] );
X}
X
!EOR!
echo extracting - report.c
sed 's/^X//' > report.c << '!EOR!'
X/* REPORT.C
X *
X * Prints out the table of contents and listed .C files.
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <ctype.h>
X#include <string.h>
X
X#include "cpr.h"
X
X#define HEADER_SIZE 3
X#define TOC_SIZE 4096
X
Xstatic char *Toc[TOC_SIZE]; /* array of pointers to malloc-ed TOC strings */
Xstatic int TocPages[TOC_SIZE]; /* page on which the item occurs */
Xstatic int TocCount; /* how many TOC lines so far */
X
Xchar FileDate[24]; /* Last modified time of file */
X
X
XNewPage()
X /* Note that PageNumber is -1 during TableOfCont processing */
X{
X static int CountNewPage=0; /* suppress blank pre-page */
X
X if( PageNumber >= 0 ) {
X ++PageNumber;
X putchar(BP);
X }
X else /* we're doing TOC */
X if( CountNewPage++ ) putchar(BP); /* don't put first BP */
X LineNumber = 0;
X
X PutHeader();
X}
X
XPutHeader()
X{
X register int i, l, j;
X
X putchar('\n');
X ++LineNumber;
X l = strlen(Name);
X for( j=0; j < l; ++j )
X printf("%c\b%c\b%c", Name[j], Name[j], Name[j]);
X
X if( PageNumber > 0 )
X {
X printf(" %.17s", FileDate);
X GoToColumn(l+19, 70);
X printf("Page:%4d\n\n", PageNumber);
X ++LineNumber;
X ++LineNumber;
X }
X else
X {
X GoToColumn(l, 55);
X printf("%s\n\n", Today);
X ++LineNumber;
X ++LineNumber;
X }
X}
X
XGoToColumn(from, to)
Xregister int from, to;
X{
X if( from < to)
X {
X if( TabWidth > 0 ){
X from &= ~(TabWidth-1);
X for( ; (from + TabWidth) <= to; from += TabWidth )
X putchar('\t');
X }
X for( ; from < to; from++ )
X putchar(' ');
X }
X}
X
X
XAddToTableOfContents(type)
X{
X if( TocCount > TOC_SIZE )
X return;
X if( TocCount == TOC_SIZE )
X {
X fprintf(stderr, "%s: More than %d Table of contents entries; others ignored.\n",
X ProgName, TOC_SIZE);
X ++TocCount;
X return;
X }
X
X if( type == NEWFILE )
X AddFile();
X else
X AddFunction();
X}
X
XAddFunction()
X{
X register int l;
X register char *p;
X
X /* This heuristic stops multiple occurrences of a function,
X * selected by #ifdefs, to all end up many times over in the
X * Table of Contents. One only needs to see it once. -IAN!
X */
X if( TocCount > 0 && TocPages[TocCount-1] == PageNumber
X && strcmp(Toc[TocCount-1],FunctionName) == 0 )
X return;
X l = strlen(FunctionName);
X p = Toc[TocCount] = (char *)malloc(l+1);
X strcpy(p, FunctionName);
X TocPages[TocCount] = PageNumber;
X ++TocCount;
X}
X
XAddFile()
X{
X register int i, l;
X register int len;
X char temp[20];
X
X len = strlen(Name) + 20;
X len = (len < 130) ? 130 : len;
X Toc[TocCount] = (char *)malloc(len);
X sprintf(Toc[TocCount], "\n File: %s ", Name);
X l = strlen(Toc[TocCount]);
X if( l < 64 )
X {
X if( TabWidth > 0 ){
X i = ((64 - l) /TabWidth) + 1;
X while( i-- > 0 )
X Toc[TocCount][l++] = '\t';
X }
X else{
X while( l < 64 )
X Toc[TocCount][l++] = ' ';
X }
X Toc[TocCount][l++] = '\0';
X }
X sprintf(temp, " Page %4d\n", PageNumber);
X strcat(Toc[TocCount], temp);
X ++TocCount;
X}
X
XNewFile()
X{
X GetFileTime();
X if( ResetPage ) PageNumber=0;
X NewPage();
X AddToTableOfContents(NEWFILE);
X FileLineNumber = 0;
X}
X
XGetFileTime()
X{
X struct stat st;
X extern char *ctime();
X
X if( File == stdin )
X strncpy(FileDate, &Today[4], 20);
X else
X {
X fstat(fileno(File), &st);
X strncpy(FileDate, ctime((time_t *)&st.st_mtime) + 4, 20);
X }
X strncpy(&FileDate[12], &FileDate[15], 5);
X FileDate[18] = '\0';
X}
X
XDumpTableOfContents()
X{
X register int i, j;
X int TocIncr = 0;
X int index[TOC_SIZE];
X int Files = 0; /* How many files reported so far */
X int Functions = 0; /* How many functions reported so far? */
X int EveryFourth;
X
X if( TocCount == 0 ) return;
X
X for (i = 0; i < TocCount; i++) index[i] = i;
X
X if( XrefFlag ) { /* XREF - put files as first entries.
X * SortTable() will do the rest. */
X FilesFirst ();
X TocIncr = 1; /* start printing AFTER the \n */
X }
X
X if( SortFlag )
X SortTable(index);
X
X Name = "Table of Contents";
X
X PageNumber = -1;
X LineNumber = 0;
X
X if( Title )
X {
X FILE *f;
X int n;
X char b[256];
X
X if( (f=fopen(TitleFile,"r")) == NULL )
X fprintf(stderr,"%s: Can't open file '%s': %s\n",
X ProgName, TitleFile, sys_errlist[errno] );
X else
X {
X while( fgets(b, 256, f) != NULL )
X {
X if( strlen(b) ) b[strlen(b)-1]=0;
X puts(b);
X LineNumber++;
X if( ++LineNumber >= PageEnd ) NewPage();
X }
X
X fclose(f);
X }
X }
X else
X NewPage();
X
X for( i=0; i < TocCount; ++i )
X {
X if( Toc[index[i]][0] == '\n' ) /* File entry */
X {
X if( (LineNumber + 5) >= PageEnd ) NewPage();
X
X /* Play with the leading \n in file entry */
X EveryFourth = ( !(Files++ & 3) && XrefFlag );
X printf("%s", Toc[index[i]]+TocIncr-EveryFourth);
X LineNumber += 2 - TocIncr + EveryFourth;
X continue;
X }
X else /* Function entry */
X {
X if (! Functions++ && XrefFlag) {
X printf( "\nFunction Index:\n");
X LineNumber += 2;
X }
X }
X if( ++LineNumber >= PageEnd ) NewPage();
X
X printf(" %s ", Toc[index[i]]);
X for( j=strlen(Toc[index[i]]); j < 48; ++j ) putchar('.');
X printf(" %4d\n", TocPages[index[i]]);
X }
X
X if( ContentsOnly ) NewPage();
X}
X
XFilesFirst ()
X{
X int i;
X int FirstNonFile = 0;
X char *Ctemp;
X int Itemp;
X
X for (i=0; i<TocCount; i++)
X if (Toc [i][0] == '\n') { /* swap file entry down */
X Ctemp = Toc [i];
X Toc [i] = Toc [FirstNonFile];
X Toc [FirstNonFile] = Ctemp;
X
X Itemp = TocPages [i];
X TocPages [i] = TocPages [FirstNonFile];
X TocPages [FirstNonFile] = Itemp;
X
X FirstNonFile++;
X }
X}
X
XSortTable(index)
Xregister int *index;
X{
X register int i, temp, flag;
X char name1[256];
X char name2[256];
X
X do {
X flag = 0;
X for (i = 0; i < TocCount - 1; i++)
X {
X if( Toc[index[i]][0] == '\n' || Toc[index[i+1]][0] == '\n' )
X continue; /* don't sort across file names */
X strcpy( name1, Toc[index[i]] );
X strcpy( name2, Toc[index[i+1]] );
X
X if( CaseInsensitive )
X {
X char *p;
X char c;
X for(p=name1; c=*p; p++ )
X if( islower(c) ) *p=toupper(c);
X for(p=name2; c=*p; p++ )
X if( islower(c) ) *p=toupper(c);
X }
X
X if( strcmp(name1, name2) > 0)
X {
X temp = index[i];
X index[i] = index[i+1];
X index[i+1] = temp;
X flag = 1;
X }
X }
X }
X while( flag );
X}
X
!EOR!
echo extracting - wildfile.c
sed 's/^X//' > wildfile.c << '!EOR!'
X/* Expand wildcards (e.g., for MSDOS, which doesn't do it for you).
X * Note that the MSDOS wildcard conventions are used, not the
X * UNIX conventions.
X *
X * The following code is a prototype of the use of these functions,
X * if 'fname' points to the [wildcarded] name of the file:
X *
X * #ifdef NOWILD
X * strncpy (fname, first_file (fname), MAXNAME);
X * while ((fname!=NULL) && (*fname!='\0')) {
X * process_file (fname);
X * strncpy (fname, next_file (fname), MAXNAME);
X * }
X * #else
X * process_file (fname);
X * #endif
X *
X * This file is an example of these functions for Turbo C.
X * (It isn't needed for Turbo C 2.0, but may be for earlier ones.)
X */
X
X#include <stdio.h>
X
X#ifdef NOWILD
X#ifdef TURBOC
X
X#include <dos.h>
X#include <dir.h>
X
Xstruct ffblk fb;
Xchar fullname[MAXPATH];
Xint dirlen;
X
X/* Find the first file meeting the wildcard spec, and return its name */
Xchar *
Xfirst_file (fn)
X char *fn; /* filename (perhaps complete pathname */
X{
X int ffflag;
X int splitflag;
X char drive[MAXDRIVE], dir[MAXDIR],
X name[MAXFILE], ext[MAXEXT];
X
X /* Get path part, if any */
X splitflag = fnsplit (fn, drive, dir, name, ext);
X strcpy (fullname, drive);
X strcat (fullname, dir);
X dirlen = strlen (fullname);
X
X ffflag = findfirst (fn, &fb, FA_RDONLY+FA_ARCH);
X if (ffflag) { /* No files match */
X if (splitflag & WILDCARDS) /* done if wildcard */
X return (NULL);
X else /* complain if not wild */
X return (fn);
X }
X else {
X if (dirlen) {
X strcpy (fullname+dirlen, fb.ff_name);
X return (fullname);
X }
X else
X return (fb.ff_name);
X }
X}
X
X/* Find the next file meeting the wildcard spec, and return its name */
Xchar *
Xnext_file ()
X{
X int ffflag;
X
X ffflag = findnext (&fb);
X if (ffflag) /* No more matching files */
X return (NULL);
X else {
X if (dirlen) {
X strcpy (fullname+dirlen, fb.ff_name);
X return (fullname);
X }
X else
X return (fb.ff_name);
X }
X}
X
X#endif
X#endif
!EOR!
echo extracting - cpr.h
sed 's/^X//' > cpr.h << '!EOR!'
X/************** Header File For CPR ************************/
X
X#ifdef MAIN
X# define EXTERN
X# define INIT(x) =x
X#else
X# define EXTERN extern
X# define INIT(x)
X#endif
X
Xextern int errno; /* system error number */
Xextern char *sys_errlist[]; /* error message */
Xextern char *malloc() ; /* important for 8086-like systems */
X
X#define BP 0xC /* Form feed */
X
X#define NEWFILE 1
X#define NEWFUNCTION 2
X
X/* Define formats for beginning of line */
X#define NUMFORMAT "%6ld "
X#define BLANKFORMAT " "
X#define FORMATWIDTH 8
X
X#define NULLSTR( x ) ((x == NULL) || (*x == '\0'))
X#define WHITESPACE(x) (strchr (" \n\r\t", x))
X
X/* Option flag variables */
XEXTERN int PageLength INIT( 66 ); /* -l, <len> Page length */
XEXTERN int PageWidth INIT( 0 ); /* -w, page width for line folding */
XEXTERN int PagePart INIT( 12 ); /* -p, Decision on paging for new fn*/
XEXTERN int PageEnd INIT( 59 ); /* Accounts for space at bottom (7 lines) */
XEXTERN int Title INIT( 0 ); /* -T, print a title file */
XEXTERN int ResetPage INIT( 0 ); /* -N, each file resets page # */
XEXTERN int ContentsOnly INIT( 0 ); /* -C, only ToC, no listings */
XEXTERN int SortFlag INIT( 0 ); /* -s, sort table of contents */
XEXTERN int CaseInsensitive INIT( 0 ); /* -S, case-insens sort */
XEXTERN int XrefFlag INIT( 0 ); /* -x, cross-reference */
XEXTERN int NumberFlag INIT( 0 ); /* -n, line numbers in output */
XEXTERN int FirstCol INIT( 0 ); /* starting column for listing (-n) */
XEXTERN int Space_to_leave INIT( 5 ); /* -r<number> space to leave */
XEXTERN int TabWidth INIT( 8 ); /* -t <number> width of tabs */
XEXTERN int OnlyCFiles INIT( 0 ); /* -c, only look in C files */
X
X/* State variables for the program */
XEXTERN long FileLineNumber; /* Input file line number */
XEXTERN int LineNumber; /* Output line on this page */
XEXTERN int PageNumber INIT( 0 ); /* You figure this one out */
XEXTERN int InComment;
XEXTERN int InString;
X
XEXTERN char *TitleFile;
XEXTERN char *ProgName;
XEXTERN char Today[30];
XEXTERN char *Name; /* Current file name */
XEXTERN char FunctionName[80];
X
X/* Help with parsing the command line and argument file */
XEXTERN int InArgFile INIT( 0 );
XEXTERN char arg[1024]; /* buffer for current argument */
XEXTERN char *listn; /* argument file name */
XEXTERN FILE *listf; /* argument file */
XEXTERN FILE *File;
XEXTERN FILE *Tfile; /* title file */
X
!EOR!
echo extracting - makefile
sed 's/^X//' > makefile << '!EOR!'
X# MAKEFILES FOR CPR:
X# Pick out your system, extract the sub-makefile, and go.
X# Note: this makefile is untested, and probably won't work as is;
X# use it as a guide.
X
X# For UNIX System V.
XSRC=cpr.c parsargs.c list.c fold.c report.c
XOBJ=cpr.o parsargs.o list.o fold.o report.o
XHDR=cpr.h
XTARGET=cpr
XCC=cc -c -O
XLINK=cc -o cpr
X
X# For MSDOS using Turbo C 2.0 or later
XSRC=cpr.c parsargs.c list.c fold.c report.c
XOBJ=cpr.obj parsargs.obj list.obj fold.obj report.obj \tc\lib\wildargs.obj
XHDR=cpr.h
XTARGET=cpr.exe
XCC=tcc -O -DMSDOS -DTURBOC
XLINK=tcc
X
X# For MSDOS using Microsoft C 5.0 or later
X# (Note: in the "rules" section, end each command line with ';')
XSRC=cpr.c parsargs.c list.c fold.c report.c
XOBJ=cpr.obj parsargs.obj list.obj fold.obj report.obj \msc\lib\setargv.obj
XHDR=cpr.h
XTARGET=CPR.EXE
XCC=msc -O -DMSDOS
XLINK=link
X
X# For systems that don't expand wildcards on command line
X# (including earlier MS C and Turbo C),
X# replace the "special" .obj with "wildfile.obj", which you will write
X# yourself. A sample wildfile.c is given for early Turbo C.
X# Also, compile with the additional flag NOWILD.
X
X# Generic Makefile section
X
X.c.o:
X $(CC) $*.c
X
X$(TARGET) : $(OBJ)
X $(LINK) $(OBJ)
X
X$(OBJ) : $(HDR)
X
X# Make a listing using cpr. This "bootstraps" from a good cpr.
Xlisting : cpr.cpr
Xcpr.cpr : $(SRC) $(HDR)
X cpr -Xp9w83 $(SRC) $(HDR) > cpr.cpr
X
!EOR!