[gnu.gcc.bug] bug in gcc?

TEX7%ICNUCEVM.BITNET@MITVMA.MIT.EDU (Stefano Diomedi TECSIEL) (06/07/89)

I'm reporting a possible bug in gcc.


GNU CC version: 1.35

Input File: ckudia.c in ckermit 4E(070) 29 Jan 88
            After running 'gcc -E' you get:

===============================================================================
# 1 "ckudia.c"
char *dialv = "Dial Command, V2.0(009) 24 Jan 88";

# 1 "ckcdeb.h"

typedef void SIGTYP;

typedef unsigned char CHAR;
typedef long LONG;

# 116 "ckudia.c"

# 1 "/usr/include/stdio.h"

extern  struct  _iobuf {
        int     _cnt;
        char    *_ptr;
        char    *_base;
        int     _bufsiz;
        short   _flag;
        char    _file;
} _iob[3];

extern struct _iobuf    *fopen(), *fdopen(), *freopen(), *popen(), *tmpfile();
extern long     ftell();
extern void     rewind(), setbuf(), setbuffer(), setlinebuf();
extern char     *fgets(), *gets(), *ctermid(), *cuserid(),
                *tempnam(), *tmpnam();

extern char     *sprintf();

# 117 "ckudia.c"

# 1 "/usr/include/ctype.h"

extern  unsigned short *_pctype;
extern  unsigned short _ctype__[];


# 118 "ckudia.c"

# 1 "/usr/include/signal.h"

struct  sigvec {
        void     (*sv_handler)();
        int      sv_mask;
        int     sv_flags;
};

struct  sigaction {
        void     (*sa_handler)();
        int      sa_mask;
        int      sa_flags;
};

struct  sigstack {
        char    *ss_sp;
        int     ss_onstack;
};

struct  sigcontext {
        int     sc_onstack;
        int     sc_mask;
        int     sc_sp;
        int     sc_pc;
        int     sc_ps;
};

extern void     (*signal())();

# 119 "ckudia.c"

# 1 "ckcker.h"

# 120 "ckudia.c"

# 1 "ckucmd.h"

struct keytab {
    char *kwd;
    int val;
    int flgs;
};
# 121 "ckudia.c"



# 1 "/usr/include/setjmp.h"

typedef int jmp_buf[10];

extern int setjmp();
extern void longjmp();

# 124 "ckudia.c"

extern int flow, local, mdmtyp, quiet, speed, parity, seslog;
extern char ttname[], sesfil[];



struct mdminf
    {
    int         dial_time;
    char        *pause_chars;
    int         pause_time;
    char        *wake_str;
    int         wake_rate;
    char        *wake_prompt;
    char        *dmode_str;
    char        *dmode_prompt;
    char        *dial_str;
    int         dial_rate;
    };



static
struct mdminf CERMETEK =
    {
    20,
    "BbPpTt",
    0,
    "  XY\016R\r",
    200,
    "",
    "",
    "",
    "\016D '%s'\r",
    200
    };

static
struct mdminf DF03 =
    {
    27,
    "=",
    15,
    "\001\002",
    0,
    "",
    "",
    "",
    "%s",
    0
    };

static
struct mdminf DF100 =

    {
    30,
    "=",
    15,
    "\001",
    0,
    "",
    "",
    "",
    "%s#",
    0
    };

static
struct mdminf DF200 =

    {
    30,
    "=W",
    15,
    "\002",
    0,
    "",
    "",
    "",
    "%s!",
    0
    };

static
struct mdminf GDC =
    {
    32,
    "%",
    3,
    "\r\r",
    500,
    "$",
    "D\r",
    ":",
    "T%s\r",
    0
    };

static
struct mdminf HAYES =
    {
    35,
    ",",
    2,
    "AT\r",
    0,
    "",
    "",
    "",
    "AT DP%s\r",
    0
    };

static
struct mdminf PENRIL =
    {
    50,
    "",
    0,
    "\r\r",
    300,
    ">",
    "k\r",
    ":",
    "%s\r",
    0
    };

static
struct mdminf RACAL =
    {
    35,
    "Kk",
    5,
    "\005\r",
    50,
    "*",
    "D\r",
    "?",
    "%s\r",
    0
    };

static
struct mdminf UNKNOWN =
    {
    30,
    "",
    0,
    "",
    0,
    "",
    "",
    "",
    "%s\r",
    0
    };

static
struct mdminf USROBOT =
    {
    30,
    ",",
    2,
    "ATS2=01\r",
    0,
    "OK\r",
    "",
    "",
    "ATTD%s\r",
    0
    };

static
struct mdminf VENTEL =
    {
    20,
    "%",
    5,
    "\r\r\r",
    300,
    "$",
    "",
    "",
    "<K%s\r>",
    0
    };

static
struct mdminf CONCORD =
    {
    35,
    ",",
    2,
    "\r\r",
    20,
    "CDS >",
    "",
    "",
    "<D M%s\r>",
    0
    };

static
struct mdminf ATT7300 =
    {
    30,
    "",
    0,
    "",
    0,
    "",
    "",
    "",
    "%s\r",
    0
    };


static
struct mdminf *ptrtab[] =
    {
    &CERMETEK,
    &DF03,
    &DF100,
    &DF200,
    &GDC,
    &HAYES,
    &PENRIL,
    &RACAL,
    &UNKNOWN,
    &USROBOT,
    &VENTEL,
    &CONCORD,
    &ATT7300
    };

struct keytab mdmtab[] =
    {
    "att7300",          13      ,      0,
    "cermetek",          1,     0,
    "concord",                12,      0,
    "df03-ac",                   2,             0,
    "df100-series",              3,     0,
    "df200-series",              4,     0,
    "direct",           0,              0,
    "gendatacomm",               5,             0,
    "hayes",                     6,     0,
    "penril",            7,     0,
    "racalvadic",                8,     0,
    "unknown",           9,     0,
    "usrobotics-212a",  10,     0,
    "ventel",           11,     0
    };

int nmdm = (sizeof(mdmtab) / sizeof(struct keytab));


static
char *F_reason[5] = {
    "Unknown",  "Timeout", "Interrupt", "Modem", "Initialize" };

static int tries = 0;


static char lbuf[100];

static jmp_buf sjbuf;

static SIGTYP (*savAlrm)();
static SIGTYP (*savInt)();

dialtime() {
    longjmp( sjbuf,     1        );
}

dialint()
    {
    longjmp( sjbuf,     2        );
    }

static
ttolSlow(s,millisec) char *s; int millisec; {
    for (; *s; s++) {
        ttoc(*s);
        msleep(millisec);
        }
    }

static
waitFor(s) char *s;
    {
    CHAR c;
    while ( c = *s++ )
        while ( ( ttinc(0) & 0177 ) != c ) ;
    }

static
didWeGet(s,r) char *s, *r; {
    int lr = strlen(r);
    int i;
    for (i = strlen(s)-lr; i >= 0; i--)
        if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 );
    return( 0 );
}

static
reset ()
    {
    alarm(0);
    signal(  14 ,savAlrm);
    signal(    2        ,savInt);
    }


ckdial(telnbr) char *telnbr; {

    char c;
    char *i, *j;
    int waitct, status;
    char errmsg[50], *erp;
    struct mdminf *pmdminf;
    int augmdmtyp;
    int mdmEcho = 0;
    int n, n1;
    char *pc;

        if (!mdmtyp) {
            printf("Sorry, you must 'set modem' first\n");
            return(-2);
        }
        if (!local) {
            printf("Sorry, you must 'set line' first\n");
            return(-2);
        }
        if (speed < 0) {
            printf("Sorry, you must 'set speed' first\n");
            return(-2);
        }

# 588 "ckudia.c"


        if (ttopen(ttname,&local,mdmtyp) < 0) {
            erp = errmsg;
            sprintf(erp,"Sorry, can't open %s",ttname);
            perror(errmsg);
            return(-2);
        }
        pmdminf = ptrtab[mdmtyp-1];
        augmdmtyp = mdmtyp;




        waitct = 1*strlen(telnbr) ;
        waitct += pmdminf->dial_time;
        for (i=telnbr; *i; i++)
            for (j=pmdminf->pause_chars; *j; j++)
                if (*i == *j) {
                    waitct += pmdminf->pause_time;
                    break;
                    }

       printf("Dialing thru %s, speed %d, number %s.\r\n",ttname,speed,telnbr);
       printf("The timeout for completing the call is %d seconds.\r\n",waitct);
       printf("Type the interrupt character to cancel the dialing.\r\n");

        if ( tthang() < 0 ) {
            printf("Sorry, Can't hang up tty line\n");
            return(-2);
            }


        if ( ttpkt(speed,4              ,parity) < 0 )  {
            printf("Sorry, Can't condition communication line\n");
            return(-2);
        }

    if ( n = setjmp(sjbuf) )
        {
        alarm ( 0 );
        if ( n1 = setjmp(sjbuf) )
            {
            printf ( "%s failure while handling failure.\r\n", F_reason[n1] );
            }
        else
            {
            signal (   14       , dialtime );
            if ( signal (     2 ,       ((void (*)())( 1)) ) !=
	         ((void (*)())( 1)) )
                signal (     2  , dialint );
            alarm ( 5 );
            ttclos ();
            }
        switch ( n )
            {
            case        1       :
                {
                printf ( "No connection made within the allotted time.\r\n" );
                break;
                }
            case        2       :
                {
                printf ( "Dialing interrupted.\r\n" );
                break;
                }
            case        3       :
                {
                printf ( "Failed (\"" );
                for ( pc=lbuf; *pc; pc++ )
                    if ( ((_pctype+1)[*pc]&
	(0020        |0001   |0002   |0004   |0200   )) )
                        (--((&_iob[1]))->_cnt>=0? ((int)(*((&_iob[1]))->_ptr++=
(unsigned)(*pc))):_flsbuf((unsigned)(*pc),(&_iob[1])));
                printf ( "\").\r\n" );
                break;
                }
            case        4       :
                {
                printf ( "Cannot initialize modem.\r\n" );
                break;
                }
            }
        reset ();
        return ( -2 );
        }

    savAlrm = signal(  14       ,dialtime);
    if ( ( savInt = signal (     2      ,       ((void (*)())( 1)) ) ) !=
       ((void (*)())( 1)) )
        signal (     2  , dialint );
    alarm(10);

    ttflui();


switch (augmdmtyp) {
    case         6:
    case (       6 + ( 1<<8 ) ):
        while(tries++ < 4) {
            ttol( HAYES.wake_str, strlen(HAYES.wake_str) );
            status = 0;
            while ( status <= 0 ) {
                switch (ttinc(0) & 0177) {
                    case 'A':
                        status = -3;
                        break;
                    case 'T':
                        if (status == -3) {
                            mdmEcho = 1;
                            status = 0;
                            break;
                        }
                        status = 2;
                        break;
                    case '\n':
                    case '\r':
                        status = 0;
                        break;
                    case '0':
                        augmdmtyp = (    6 + ( 1<<8 ) );
                        status = 1                      ;
                        break;
                    case 'O':
                        status = -2;
                        break;
                    case 'K':
                        if (status == -2) {
                            augmdmtyp =          6;
                            status = 1                  ;
                            break;
                        }
                    default:
                        status = 2;
                        break;
                    }
                }
            if (status == 1                     ) break;
            if (status == 2) ttflui();
            sleep(1);
        }
        if (status != 0) break;
        longjmp( sjbuf,         4        );



    default:
        ttolSlow(pmdminf->wake_str, pmdminf->wake_rate);
        waitFor(pmdminf->wake_prompt);
        break;
    }
    alarm(0);
    msleep(500);
    alarm(10);

    ttolSlow(pmdminf->dmode_str, pmdminf->dial_rate);
    if (pmdminf->dmode_prompt) {
        waitFor(pmdminf->dmode_prompt);
        msleep(300);
        }

    alarm(0);
    alarm(waitct);
    ttflui();
    sprintf(lbuf, pmdminf->dial_str, telnbr);
    ttolSlow(lbuf,pmdminf->dial_rate);

    if (augmdmtyp ==     8) {
        sleep(3);
        ttflui();
        ttoc('\r');
        }



    status = 0;
    strcpy(lbuf,"No Connection");
    while (status == 0) {
      switch (augmdmtyp) {
        default:
            for (n=0; n < 100; n++) {
                lbuf[n] = (ttinc(0) & 0177);
                if ( lbuf[n] == '\r' || lbuf[n] == '\n' ) break;
                }
            lbuf[n] = '\0';
            if (n) {
                switch (augmdmtyp) {
                  case  1:
                    if (didWeGet(lbuf,"\016A")) {
                        status = 1              ;
                        ttolSlow("\016U 1\r",200);
                        }
                    break;
                  case   3:
                  case   4:
                    if (didWeGet(lbuf,"Attached")) status = 1           ;

                    if (didWeGet(lbuf,"Busy")) status =   2;
                    if (didWeGet(lbuf,"Disconnected")) status =   2;
                    if (didWeGet(lbuf,"Error")) status =   2;
                    if (didWeGet(lbuf,"No answer")) status =   2;
                    if (didWeGet(lbuf,"No dial tone")) status =   2;
                    if (didWeGet(lbuf,"Speed:")) status =   2;

                    break;
                  case   5:
                    if (didWeGet(lbuf,"ON LINE")) status = 1            ;
                    if (didWeGet(lbuf,"NO CONNECT")) status =   2;
                    break;
                  case   6:
                  case 10:
                    if (didWeGet(lbuf,"CONNECT")) status = 1            ;
                    if (didWeGet(lbuf,"NO CARRIER")) status =   2;
                    break;
                  case  7:
                    if (didWeGet(lbuf,"OK")) status = 1         ;
                    if (didWeGet(lbuf,"BUSY")) status =   2;
                    if (didWeGet(lbuf,"NO RING")) status =   2;
                    break;
                  case   8:
                    if (didWeGet(lbuf,"ON LINE")) status = 1            ;
                    if (didWeGet(lbuf,"FAILED CALL")) status =   2;
                    break;
                  case 11:
                    if (didWeGet(lbuf,"ONLINE!")) status = 1            ;
                    if (didWeGet(lbuf,"BUSY")) status =   2;
                    if (didWeGet(lbuf,"DEAD PHONE")) status =   2;
                    break;
                  case       12:
                    if (didWeGet(lbuf,"INITIATING")) status = 1         ;
                    if (didWeGet(lbuf,"BUSY")) status =   2;
                    if (didWeGet(lbuf,"CALL FAILED")) status =   2;
                    break;
                }
            }
            break;

        case     2:
            c = ttinc(0) & 0177;
            if ( c == 'A' ) status = 1          ;
            if ( c == 'B' ) status =   2;
            break;

        case (   6 + ( 1<<8 ) ):
            c = ttinc(0) & 0177;
            if (mdmEcho) {
                mdmEcho = c!='\r';
                break;
                }
            if (c == '1') status = 1            ;
            if (c == '3') status =   2;
            if (c == '5') status = 1            ;
            break;

        case  9:

            break;
        }
    }
    alarm(0);
    if ( status != 1             )
        longjmp( sjbuf,         3        );
    alarm(3);
    ttpkt(speed,5,parity);
    reset ();
    if ( ! quiet )
        printf ( "Call completed.\07\r\n" );
    return ( 0 );
}

===============================================================================

Command: gcc -traditional -fwritable-strings -g -O -c ckudia.c

Names of 'tm.h' and 'md' files: tm-vax.h and vax.md

Machine type - Operating System name and version:
         DEC VAX 8200 Ultrix-32 V3.0 (Rev 64)

Incorrect behaviour description:
        The optimizer produces the following assembly code for the
        'setjmp' calls in the routine ckdial.

C code:
    ...

    if ( n = setjmp(sjbuf) )
        {
        alarm ( 0 );
        if ( n1 = setjmp(sjbuf) )
            {
            printf ( "%s failure while handling failure.\r\n", F_reason[n1] );
            }
        else
            {
            signal (   14       , dialtime );

Assembly code:

L32:
        pushab _sjbuf
        movab _setjmp,r6
        calls $1,(r6)
        movl r0,-92(fp)
        jeql L33
        clrl -(sp)
        calls $1,_alarm
        pushab _sjbuf
        calls $1,(r6)
        movl r0,-96(fp)
        jeql L34
        pushl _F_reason[r0]
        pushab LC107
        calls $2,_printf
        jbr L35
L34:
        pushab _dialtime
        pushl $14
        movab _signal,r6
        calls $2,(r6)

Sometimes I get an Illegal Instruction signal just in the second call
to setjmp. It seems to me that the optimizer doesn't realize that
register r6 can have a value different from _setjmp, if we have
arrived here because of a longjmp call.


I hope this can help you in finding the bug (!?).

Regards

Stefano Diomedi
Tecsiel SpA
Via S. Maria 19
56100 PISA
Italy