[comp.sys.acorn] Another query about the behaviour of the C compiler

vanaards@p4.cs.man.ac.uk (Steven van Aardt) (03/08/91)

  Still developing this project of mine. The previous bug I reported wasn't
a bug at all - in fact just bad programming, I was clobbering one of my
data structures, thanks to Arthur Norman  (Codemist Ltd, aka Norcroft), for
pointing this out to me. (In future I'll be more cautious about declaring that
I've found a bug - ref reading from system devices kbd: (which actually was a
bug in the system devices module!).

  Well here's another problem I've come across, the include files are okay,
so I needn't include them here. What's interesting is the output I've got
from the compiler - all I've done here is type *spool cbug    (opps sorry
that should read 'coutput'). OKay so I know that my source has a few
bugs - but why did the compiler give-up on me ?


---------------------- Here's the output -----------------------------------

$.!Hypertext *cc -gfvl -c -zpc1p2s0v3z0 rl
Norcroft RISC OS ARM C vsn 3.00 [Jul 12 1989]
"c.rl", line 11: Error: expected ';' or ',' - inserted ';' before 'struct'
"c.rl", line 23: Serious error: type 'char' inconsistent with 'struct'
"c.rl", line 45: Error: 'return': implicit cast of pointer to non-equal pointer

Illegal address (e.g. wildly outside array bounds)

Postmortem requested
Function name can not be found
Function name can not be found
Function name can not be found
Function name can not be found
Function name can not be found
Function name can not be found
  Arg2: 0x0004fd4c 326988
  Arg1: 0x00000008 8
Function name can not be found
  Arg2: 0x0004fd30 326960
  Arg1: 0x00000001 1
Function name can not be found
Function name can not be found
unknown procedure 61851de8
$.!Hypertext *



--------------------------- Here's the program -----------------------------
/* Prepape rich link files with lookup table */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>

#include "vi_stdio.h"
 
typedef TREE_NODE struct tree_structure;
typedef TREE_NODE *TREE_PTR;
struct tree_structure {
       char     *word;
       TREE_PTR up,left,right;
}

/*------------------------  nwrd  ---------------------------------*
 * Purpose : Extract the next word from a string
 * Argument: pointer to string
 * Returns : pointer to word copied from line and updated pointer
 *-----------------------------------------------------------------*/
static char *
nwrd(char **ptr1) {
  char *spc,*wrd=NULL,*ptr=*ptr1;
  int cnt=0;
  while ((ptr) && (*ptr) && (*ptr==' ')) ptr++; /* skip leading spaces */
  if (*ptr) {
    if (*ptr!='*') {
      spc=strchr(ptr,' ');
      if (spc) cnt=spc-ptr; 
      else {
        cnt=strlen(ptr);
        spc=strchr(ptr,'\n'); 
        if (spc) cnt-=1;
      }
      assert(cnt>=0);
      if (cnt==0) return NULL;
      wrd=calloc(cnt+2,sizeof(char));
      assert(wrd!=NULL);
      strncpy(wrd,ptr,cnt);
      *ptr1=ptr+strlen(wrd);
    }
  }
  return wrd;
}

TREE_PTR mk_treenode(char *word,TREE_PTR from) {
  TREE_PTR node=malloc(sizeof(TREE_NODE)); 
  strcpy(node->word,word);
  node->up=from;
  node->left=NULL;
  node->right=NULL;
  return node;
}

void insert_treenode(char *word,TREE_PTR root) {
  TREE_PTR ptr=root;
  register int br_right;
  while (ptr) {
    if (cstrcmp(ptr->word,word)<=0) br_right=FALSE; else br_right=TRUE;
    if (br_right) {
      if (ptr->right) ptr=ptr->right;
      else {
        ptr->right=mk_treenode(word,ptr);
        break;
      }
    } else {
      if (ptr->left) ptr=ptr->left;
      else {
        ptr->left=mk_treenode(word,ptr);
        break;
      }
    }
  }
  assert(ptr!=NULL);
}

void flatten(TREE_PTR root) {
  TREE_PTR node=root,flathd=NULL,flattl=NULL;
  if (root->left) flatten(root->left);
  printf("%s\n",root->word);
  if (root->right) flatten(root->right);
  free(root->word);
  free(root);
}


void sort_rl(const char *rlfilename) {
   char *line=NULL,*wrd=NULL,*ptr=NULL; 
   FILE *fp=fopen(rlfilename,"rb"); 
   TREE_PTR root=NULL;
   /* find word for root of tree */
   while (!feof(fp) &&  !wrd) {
     if (line) free(line);
     if (wrd) free(wrd);
     ptr=line=fgetl(fp);
     wrd=nwrd(&ptr);
   }
   if (wrd)  {
     printf("Building tree\n");
     mk_treenode(wrd,NULL);
     while (!feof(fp)) {
       if (line) free(line);
       if (wrd) free(wrd);
       ptr=line=fgetl(fp);
       wrd=nwrd(&ptr);
       insert_treenode(word,root);
     }
     printf("done\n");
     flatten(root);
   }
}


void
prepare_rl(const char *rlfilename) {
    FILE *fp=fopen(rlfilename,"rb");
    long int alphas[26],i=-1,n=0,m,pos=0;
    char *line,*hline;
    for (i=0; i<26; i++) alphas[i]=-1;
    i=-1;
    while (!feof(fp)) {
      line=fgetl(fp);
      if (line && line[0]!='*' && line[0]!='\n' && line[0]) {
        int c=tolower(line[0])-'a';
        if (c>i) {
          if (alphas[c]!=-1) exit(2);
          alphas[c]=pos;
          i=c;
        } else {
          if (c<i) {
            printf("file not sorted properly\n");
            printf("%ld :: %s",pos,line);
            exit(1);
          }
        }
      }
      pos+=strlen(line)+1;
      if (line) free(line);
    }
    hline=calloc(1+26+13*26,sizeof(char));
    for (i=0; i<26; i++) {
      n+=sprintf(hline+n,"%c %010.0x\n",(int) i+'a',(int) alphas[i]);
    }
    *(hline+n+1)='\0';
    m=0;
    for (i=0; i<26; i++) {
      m+=sprintf(hline+m,"%c %010.0x\n",(int) i+'a',(alphas[i]!=-1)?(int) (alphas[i]+n):-1);
    }
    *(hline+m+1)='\0';
    m=strlen(hline);
    if (m!=n) exit(1);
    printf("%s",hline);
    rewind(fp);
    while (!feof(fp)) {
      line=fgetl(fp);
      fprintf(stdout,"%s\n",line);
      free(line);
    }
    fclose(fp);
}


int main(int argc,char **argv) {
  if (argc>1) {
    prepare_rl(argv[1]);
  }
  return 0;
}


----------------------------------------------------------------------------

Steven van Aardt.
-- 
-------------------------------------------------------------------------------
       JANET E-mail : vanaards@uk.ac.man.cs.p4 (Steven van Aardt) 
-------------------------------------------------------------------------------

gtoal@tharr.UUCP (Graham Toal) (03/09/91)

In article <vanaards.668425401@p4.cs.man.ac.uk> vanaards@p4.cs.man.ac.uk (Steven van Aardt) writes:
:
:  Still developing this project of mine. The previous bug I reported wasn't
:a bug at all - in fact just bad programming, I was clobbering one of my
:data structures, thanks to Arthur Norman  (Codemist Ltd, aka Norcroft), for
:pointing this out to me. (In future I'll be more cautious about declaring that
:I've found a bug - ref reading from system devices kbd: (which actually was a
:bug in the system devices module!).
It's OK - we won't say we told you so ;-)

:
:  Well here's another problem I've come across, the include files are okay,
:so I needn't include them here. What's interesting is the output I've got
:from the compiler - all I've done here is type *spool cbug    (opps sorry
:that should read 'coutput'). OKay so I know that my source has a few
:bugs - but why did the compiler give-up on me ?
:
:
:---------------------- Here's the output -----------------------------------
:
:$.!Hypertext *cc -gfvl -c -zpc1p2s0v3z0 rl
:Norcroft RISC OS ARM C vsn 3.00 [Jul 12 1989]
:"c.rl", line 11: Error: expected ';' or ',' - inserted ';' before 'struct'
:"c.rl", line 23: Serious error: type 'char' inconsistent with 'struct'
:"c.rl", line 45: Error: 'return': implicit cast of pointer to non-equal pointer
:
:Illegal address (e.g. wildly outside array bounds)

This is the only bug I've found in NorCroft, and it only happens with
a wrong program:  in Ansi, if you give a spec for a procedure which has a
struct as a parameter, and then actually declare the struct type *after*
the declaration, - when you come to the body of the procedure you will
get a type check error on the struct.  The solution is to move the struct
type declaration to above the external procedure/forward declarations.

The annoying thing is that this was legal in k&r, so many existing
programs do it :-(

I'm not sure this is your problem, but I thought it was worth telling
people anyway.

Graham.
-- 
(* Posted from tharr.uucp - Public Access Unix - +44 (234) 720202 *)

john@acorn.co.uk (John Bowler) (03/11/91)

In article <1925@tharr.UUCP> gtoal@tharr.UUCP (Graham Toal) writes:
>:"c.rl", line 45: Error: 'return': implicit cast of pointer to non-equal pointer
>:
>:Illegal address (e.g. wildly outside array bounds)
>
>This is the only bug I've found in NorCroft, and it only happens with
>a wrong program:  in Ansi, if you give a spec for a procedure which has a
>struct as a parameter, and then actually declare the struct type *after*
>the declaration, - when you come to the body of the procedure you will
>get a type check error on the struct.  The solution is to move the struct
>type declaration to above the external procedure/forward declarations.
>
>The annoying thing is that this was legal in k&r, so many existing
>programs do it :-(

It shouldn't ever occur in a pre-ANSI program; because K&R did not
support function prototypes it wasn't possible to do this:

                                                  Definitions in scope
                                                  ====================
void foo(
   struct foo1 x         /* Definition foo1A */    foo1A
);

struct foo1 { int y; };  /* Definition foo1B */    foo1B
struct foo2 { int z; };  /* Definition foo2A */    foo1B foo2A
                                                   foo1B foo2A
void foo(                                          foo1B foo2A
   struct foo1 x   /* == foo1B */                  foo1B foo2A
) {                                                foo1B foo2A
   struct foo2 { double a; } b;  /* foo2B */       foo1B (foo2A) foo2B
                                                   foo1B (foo2A) foo2B
   ...                                             foo1B (foo2A) foo2B
}                                                  foo1B foo2A

foo1A disappears after the closing ) of the foo function declaration,
just as foo2A disappears after the closing }.  You could do the
second with the K&R implementations which I know (ie have two
structs foo2, the second (type definition) obscuring the first).
You couldn't do the first, because K&R didn't permit declaration
of function arguments.  Purists might observe that the real reason
is that C permits implicit type definitions inside declarations.

I can't remember if the code:-

void foo() {
	struct foo1 { int y; } x; /* Definition A */

	....
}

void bar() {
	struct foo1 z; /* Programmer means definition A */

	....
}

was actually legal with pcc, but the chances of finding such a
thing in existing K&R code must be very small - writing the code
``correctly'' is so much easier and more obvious.  (Think what
happens in the above code if someone innocently adds a ``struct
foo1'' definition prior to function foo()).

Adding function argument prototypes to pre-ANSI code often throws
up this problem.  The easy workround is:-

struct foo1;		/* Add this line */

void foo(
	struct foo1 x
);

If you don't like the warning the compiler generates as a result :-(
use the following:-

typedef struct foo1 XX_foo1_dummy;

void foo (
	struct foo1 x
);

John Bowler (jbowler@acorn.co.uk)