[comp.unix.xenix] modified cci program

rac@sherpa.UUCP (Roger A. Cornelius) (05/21/89)

This is a repost of the cci program (previously reposted in March)
which calls cc with the -LARGE option if an out of heap space error
occurs.  I've hacked it to do the same for the "Function too large"
error.  I've made a few other changes which are listed below.

Roger
--
Roger A. Cornelius       rac@sherpa 
                         uunet!sherpa!rac

Changes:
    Prints the command line it uses to call cc (like make would).

    Handles "function too large for post optimizer" error internally,
    instead of using an environment variable.  Since this is not a fatal
    error i.e.  cc doesn't abort, only a flag is tested to indicate the
    error, instead of testing the return status of cc and the flag (as the
    previous version did).  The correct status is still returned to
    make.  While the "out of heap space" error usually occurs near the
    beginning of the compile, the "function too large" error usually
    occurs near the end, possibly causing cc to take twice as long to
    run on a file with the "Function too large" error.

    Since the "function too large" error is now handled internally, the calls
    to getenv() and regcmp() were removed, and pre-compiled reg-expressions
    (ala regcmp(CP)) were added for the error messages.

    Renamed some variables to be more meaningful (to me anyway)

    Indented the source.

------------ Excerpts from the previous posting -------------------

From: larry@tapa.UUCP (Larry Pajakowski)
Newsgroups: comp.unix.xenix
Subject: cc front end for Xenix-286 -LARGE compiler
Message-ID: <606@tapa.UUCP>
Date: 12 Mar 89 02:09:50 GMT
Reply-To: larry@.UUCP (Larry Pajakowski)
Organization: Pata System Consultants
Lines: 168

Due to the discussions of the -LARGE flag I've posted this program which was
posted a little over a year ago.  Info from the original author is included.
I frequently define "CC=cci" in my make files since the -LARGE vesion of the
compiler is about 3X slower than the normal version.

About all I did to this program is to correct the return of the status from
the compiler so make reports the correct error.  This little guy neatly solves
the -LARGE problems.

Larry

------------ Excerpts from the original posting -------------------


From: erskine@force10.UUCP (Neil Erskine)
Newsgroups: comp.unix.xenix
Subject: Program cci, fixes problems with cc (Xenix 286).
Keywords: LARGE, heap space
Message-ID: <641@force10.UUCP>
Date: 27 Jan 88 18:41:43 GMT
Organization: ForceTen Enterprises

    Have you ever cursed the fact that once in a while you have
    a large program with one file that generates the infamous 
    'out of heap space' message from the preprocessor? Tired of putting
    up with slow compiles because you always use the LARGE passes even
    when unnecessary? Or do you have to contort you makefiles to compensate
    for cc's brain damage? If so, here is a program that should take care of
    -LARGE for you. Too bad SCO didn't hack cc to do this in the first place.

    To compile:
    Save the following progam into the file cci.c
    Compile it with cc -O -lx cci.c -o cci

    To install:
    Place the file 'cci' resulting from the compile in a directory
    that gets searched when using 'make'.

    To use:
    Place the line
        CC = cci
    at the top of your make file. If you have hard coded the name of
    the compiler into a rule somewhere, replace cc with $(CC) wherever
    it occurs in your makefile.

    Type make. If an out of heap space message is printed, cci will rerun
    the compile with the -LARGE parameter.

    If you don't use 'make', just use cci instead of cc.

    Limitations:
    I only put in checking for the out of memory message from the pre-
    processor because that's the only pass I have problems with. The message
    about the optimizer not coping is not trapped by cci (essentially leaving
    the code non-optimized). Feel free to modify the code, or pass it on.
    I've never got the code generator or parser to barf through lack of memory
    so I'm not worrying at all about that.
    If the optimizer is your only concern, set the environment variable
    CCI_TRIGGER to the error message produced by the optimizer that you want
    to trigger use of the large passes.

    Relax. Enjoy. Bug reports (or extensions) to

    dalcs!force10!erskine

||!][b

--------------
Neil S. Erskine        MT&T - (902) 453-4915
AP Computers         USENET { garfield, watmath, ihnp4!utzoo!utai,
3845 Dutch Village Rd.         uunet } !dalcs!force10!erskine
Halifax, N.S. B3L-4H9

---------------------------- CUT HERE -------------------------

/*     Compile it with cc -O -lx cci.c -o cci */
#include <stdio.h>

/*    The following is the output of regcmp(CP) - This just saves a
 *    call to the regcmp() function, and makes the executable a bit smaller
 */
/* "out of heap space" */
char trigger1[] = {
024,0157,024,0165,024,0164,024,040,024,0157,024,0146,
024,040,024,0150,024,0145,024,0141,024,0160,024,040,
024,0163,024,0160,024,0141,024,0143,024,0145,064,
0};
/* "function `.*' too large for post-optimizer" */
char trigger2[] = {
024,0146,024,0165,024,0156,024,0143,024,0164,024,0151,
024,0157,024,0156,024,040,024,0140,0101,024,047,024,
040,024,0164,024,0157,024,0157,024,040,024,0154,024,
0141,024,0162,024,0147,024,0145,024,040,024,0146,024,
0157,024,0162,024,040,024,0160,024,0157,024,0163,024,
0164,024,055,024,0157,024,0160,024,0164,024,0151,024,
0155,024,0151,024,0172,024,0145,024,0162,064,
0};

main(argc, argv)
int argc;
char *argv[];
{
    FILE *cc_stream;
    extern int errno;
    FILE *fdopen();
    int cc_error;
    int p[2];
    int pid, n;
    char *regex();
    char workbuf[256];
    int tsts;
    int status;

    if (pipe (p)) {
        fprintf (stderr, "cci: Gaak! Couldn't make pipes, errno = %d\n", errno);
        exit(1);
    }

    pid = fork();
    if (pid < 0) {
        fprintf (stderr, "cci: Gaak! Couldn't fork, ernro = %d\n", errno);
        exit(2);
    }

    if (pid == 0) {    /* Child process */
        dup2 (p[1], 2);        /* Redirect standard error through pipe */
        close (p[0]);        /* Don't need to read this */
        close (p[1]);        /* This is now attached to stderr */
        argv[0] = "cc";        /* Alter cc calling sequence */
        execv ("/bin/cc", argv);    /* Do it */
        sprintf (workbuf,
             "cci: Gaak! Couldn't exec /bin/cc, ernro = %d\n", errno);
        write (2, workbuf, strlen (workbuf));
        exit(3);
    }

    close (p[1]);    /* Used by child process */
    cc_stream = fdopen (p[0], "r");    /* Attach pipe to a stream */
    if (cc_stream == 0) {
        fprintf (stderr, "cci: Gaak! Couldn't fdopen, errno = %d\n", errno);
        fprintf (stderr, "     Any error messages will be lost\n");
        close (p[0]);    /* Make child get a pipe error if it writes */
        wait (&tsts);
        status = tsts >> 8;
        fprintf (stderr, "     cc exit value was %d. Goodbye\n", status);
        exit(status);
    }

    cc_error = 0;
    while (fgets(workbuf, sizeof(workbuf) - 1, cc_stream) != NULL) {
        fputs (workbuf, stderr);
        if (regex (trigger1, workbuf) || regex (trigger2, workbuf))
            cc_error = 1;
    }
    wait (&tsts);
    status = tsts >> 8;

    if (cc_error) {          /*    cc failed with "out of heap space" or    */
        char *nargv[256];    /*    "function too large" error               */
        char **c = nargv;
        char **c2 = argv;

        /* First, create a diddled argv adding the -LARGE parameter */
        *c++ = "cc";
        *c = "-LARGE";
        do {
            *++c = *++c2;
        } while (*c2 != 0);    /* Copy ending with the null */
        
        /* Now try the exec */
        fprintf (stderr, "cci: Trying cc again with the -LARGE parameter\n");

        /* imitate make's output */
        fprintf (stderr, "\tcci");
        for (n=1; nargv[n] != '\0'; n++)
            fprintf(stderr, " %s", nargv[n]);
        fprintf(stderr, "\n");
        fflush (stderr);
        execv ("/bin/cc", nargv);    /* Do it with LARGE passes */
        fprintf (stderr,
             "cci: Gaak! Couldn't re-exec /bin/cc, ernro = %d\n", errno);
        exit(4);
       }
    exit (status);    /* Normal error or success */
}