A possible bug in TCC

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

A possible bug in TCC

Ant_222
Hello, all

During the recent exercise in comp.lang.c in writing a C
program to strip comments from a C source, I have
encountered what seems to be a bug in TCC.  It is manifest
when compiling looser drug's entry with TCC and feeding it
the following test input (between --- markers):

---
a/\
\
\
\
/b
---

which causes the program to hang infinitely. When complied
with other compilers (e.g. GCC), however, it processes the
file correctly and terminates.  The source follows:

#define DEBUG(...)

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef union uobject *object;
typedef object list;
typedef enum tag { INVALID, INTEGER, LIST } tag;

union uobject { tag t;
       struct { tag t; int i, continues; } Int;
       struct { tag t; object a, b; } List;
};

typedef struct record {
  int mark;
  struct record *prev;
  union uobject o;
} record;


list cons( object a, object b );
list skip_quote( object q, list o );
list nested_comment( list o );
void print( list o );


record *allocation_list;
object global_roots;
object add_global_root( object o ){
  global_roots = cons( o, global_roots ); return  o;
}
record *alloc(){
  return  calloc( 1, sizeof(record) );
}
void mark( object ob ){
  if(  !ob  ) return;
  record *r = ((void*)( (char*)ob - offsetof( record, o ) ) );
  if(  r->mark  ) return;
  r->mark = 1;
  switch(  ob  ? ob->t  : 0  ){
    case LIST: mark( ob->List.a ); mark( ob->List.b ); break;
  }
}
int sweep( record **ptr ){
  int count = 0;
  while(  *ptr  ){
    if(  (*ptr)->mark  ){
      (*ptr)->mark = 0;
      ptr = &(*ptr)->prev;
    } else {
      record *z = *ptr;
      *ptr = (*ptr)->prev;
      free( z );
      ++count;
    }
  }
  return  count;
}
int collect( object local_roots ){
  mark( local_roots );
  mark( global_roots );
  return  sweep( &allocation_list );
}

#define OBJECT(...) new_( (union uobject[]){{ __VA_ARGS__ }} )
object new_( object a ){
  record *r = alloc();
  object p = NULL;
  if(  r  ){
    r->prev = allocation_list;
    allocation_list = r;
    p = (void*)( ((char*)r) + offsetof( record, o ) );
    *p = *a;
  }
  return  p;
}

object Int( int i ){ return  OBJECT( .Int = { INTEGER, i } ); }
list cons( object a, object b ){ return  OBJECT( .List = { LIST, a, b } ); }
list one( object a ){ return  cons( a, NULL ); }

object car( list o ){
  return  o  && o->t == LIST  ? o->List.a  : NULL;
}
object cdr( list o ){
  return  o  && o->t == LIST  ? o->List.b  : NULL;
}

int eq( object a, object b ){
  return  !a && !b                    ? 1  :
          !a || !b                    ? 0  :
          a->t != b->t                ? 0  :
          a->t == INTEGER  ? a->Int.i == b->Int.i
                           : !memcmp( a, b, sizeof *a );
}

int eqint( object a, int i ){
  union uobject b = { .Int = { INTEGER, i } };
  return  eq( a, &b );
}

int match( object pat, object it, object *matched, object *tail ){
  if(  !pat  ){
    return  *tail = it,  1;
  }
  if(  pat->t != (it  ? it->t  : 0)  ) return  0;
  switch(  pat->t  ){
    case LIST:
      {
        object sink;
        if(  match( car( pat ), car( it ), & sink, tail )  ){
          return  *matched = it,  match( cdr( pat ), cdr( it ), & sink, tail );
        }
      } break;
    case INTEGER:
      if(  eq( pat, it )  ){
        return  *matched = it,  1;
      }
  }
  return  0;
}

list chars_from_file( FILE *f ){
  int c = fgetc( f );
  return  c != EOF  ? cons( Int( c ), chars_from_file( f ) )  : one( Int( c ) );
}

list logical_lines( list o ){
  static list pat;
  if(  !pat  ) pat = add_global_root( cons( Int( '\\' ), one( Int( '\n' ) ) ) );

  object matched, tail;
  DEBUG( if( car(o)->Int.i!=EOF )
         fprintf( stderr, "[%c%c]", car(o)->Int.i, car(cdr(o))->Int.i ); )
  if(  match( pat, o, &matched, &tail )  ){
    DEBUG( fprintf( stderr, "@" ); )
    car( tail )->Int.continues = car( o )->Int.continues + 1;
    return  logical_lines( tail );
  } else {
    object a = car( o );
    return  eqint( a, EOF )  ? o  : cons( a, logical_lines( cdr( o ) ) );
  }
}

list restore_continues( list o ){
  if(  !o  ) return  NULL;
  object a = car( o );
  if(  eqint( a, EOF )  ) return  o;
  object z = cdr( o );
  object r = cons( a, restore_continues( z ) );
  while(  a->Int.continues  ){
    r = cons( Int( '\\' ), cons( Int( '\n' ), r ) );
    --a->Int.continues;
  }
  return  r;
}

list strip_comments( list o ){
  static list single, multi;
  if(  !single  ) single = add_global_root( cons( Int('/'), one(Int('/')) ) );
  if(  !multi   ) multi = add_global_root( cons( Int('/'), one(Int('*')) ) );

  object matched, tail;
  DEBUG( if(car(o)->Int.i!=EOF)
          fprintf(stderr,"<%c%c>", car(o)->Int.i, car(cdr(o))->Int.i); )
  if(  match( single, o, &matched, &tail )  ){
    DEBUG( fprintf( stderr, "@" ); )
    do {
      tail = cdr( tail );
      matched = car( tail );
    } while(  !eqint( matched, '\n' )  );
    return  strip_comments( tail );
  } else if(  match( multi, o, &matched, &tail )  ){
    DEBUG( fprintf( stderr, "@" ); )
    return  cons( Int( ' ' ),
                  strip_comments( nested_comment( cdr( tail ) ) ) );
  }

  object a = car( o );
  if(  eqint( a, '\'' ) || eqint( a, '"' )  )
    return  cons( a, skip_quote( a, cdr( o ) ) );
  return  eqint( a, EOF )  ? o
                           : cons( a, strip_comments( cdr( o ) ) );
}

list nested_comment( list o ){
  DEBUG(fprintf( stderr, "(%c%c)", car( o )->Int.i, car( cdr( o ) )->Int.i );)
  static list end;
  if(  !end  ) end = add_global_root( cons( Int( '*' ), one( Int( '/' ) ) ) );

  object matched, tail;
  if(  match( end, o, &matched, &tail )  )
    return  tail;
  if(  eqint( car( o ), EOF )  )
    fprintf( stderr, "Unterminated comment\n"),
    exit( 1 );
  return  nested_comment( cdr( o ) );
}

list skip_quote( object q, list o ){
  object a = car( o );
  if(  eqint( a, '\\' )  ){
    return  cons( a, cons( car( cdr( o ) ),
                           skip_quote( q, cdr( cdr( o ) ) ) ) );
  } else if(  eq( a, q )  ){
    return  cons( a, strip_comments( cdr( o ) ) );
  }
  if(  eqint( a, EOF )  )
    fprintf( stderr, "Unterminated literal\n"),
    exit( 1 );
  return  cons( a, skip_quote( q, cdr( o ) ) );
}

void print( list o ){
  switch(  o  ? o->t  : 0  ){
    case INTEGER: if(  o->Int.i != EOF  ) fputc( o->Int.i, stdout );
                  break;
    case LIST: print( car( o ) );
               print( cdr( o ) ); break;
  }
}


int main( int argc, char **argv ){
  list input = chars_from_file( argc > 1 ? fopen( argv[1], "r" )  : stdin );
  DEBUG( printf( "input:\n"); print( input ); )
  list logical = logical_lines( input );
  DEBUG( printf( "logical:\n"); print( logical ); )
  list stripped = strip_comments( logical );
  DEBUG( printf( "stripped:\n"); print( stripped ); )
  list restored = restore_continues( stripped );
  DEBUG( printf( "restored:\n"); )
  print( restored );
  DEBUG( printf( "@%d\n", collect( restored ) ); )
}


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: A possible bug in TCC

Vincent Lefevre-10
On 2020-12-13 14:40:17 +0300, Anton Shepelev wrote:

> Hello, all
>
> During the recent exercise in comp.lang.c in writing a C
> program to strip comments from a C source, I have
> encountered what seems to be a bug in TCC.  It is manifest
> when compiling looser drug's entry with TCC and feeding it
> the following test input (between --- markers):
>
> ---
> a/\
> \
> \
> \
> /b
> ---
>
> which causes the program to hang infinitely. When complied
> with other compilers (e.g. GCC), however, it processes the
> file correctly and terminates.  The source follows:
[...]

No issue with tcc 0.9.27+git20200814.62c30a4a-1 provided by Debian.

--
Vincent Lefèvre <[hidden email]> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: A possible bug in TCC

Ant_222
Vincent Lefevre:

> No issue with tcc 0.9.27+git20200814.62c30a4a-1 provided
> by Debian.

The bug on my side is reproduced with this version just five
days old:

   https://repo.or.cz/tinycc.git/snapshot/8ff705554de47f16726ec5f1a6c49a162b926732.zip

I had to compile it myself on Windows, using
win32\build-tcc.bat . Is there a pre-compiled win32 build
available?

I have also tried the same on a Linux. Since I had not
enough permissions to install TCC, I only built it and tried
the following from the root of the source directory:

   ./tcc -Iinclude -L. ld.c

tcc failed with error:

   file '/usr/local/lib/tcc/libtcc1.a' not found

The file libtcc1.a is right there in the working directory.
Why did it ignore -L. ?


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
ian
Reply | Threaded
Open this post in threaded view
|

Re: A possible bug in TCC

ian
Since I had not enough permissions to install TCC
Le 13/12/2020 à 21:35, Anton Shepelev a écrit :
Since I had not
enough permissions to install TCC
--
-- [hidden email]
-- Développeur compulsif

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: A possible bug in TCC

Christian Jullien-3
In reply to this post by Vincent Lefevre-10
I just recompiled you test program with mob. On Windows, cl, clang, gcc and ... tcc all produce the same output result.
Sorry, I can't reproduce.

C.

-----Original Message-----
From: Tinycc-devel [mailto:tinycc-devel-bounces+eligis=[hidden email]] On Behalf Of Vincent Lefevre
Sent: Sunday, December 13, 2020 14:17
To: [hidden email]
Subject: Re: [Tinycc-devel] A possible bug in TCC

On 2020-12-13 14:40:17 +0300, Anton Shepelev wrote:

> Hello, all
>
> During the recent exercise in comp.lang.c in writing a C
> program to strip comments from a C source, I have
> encountered what seems to be a bug in TCC.  It is manifest
> when compiling looser drug's entry with TCC and feeding it
> the following test input (between --- markers):
>
> ---
> a/\
> \
> \
> \
> /b
> ---
>
> which causes the program to hang infinitely. When complied
> with other compilers (e.g. GCC), however, it processes the
> file correctly and terminates.  The source follows:
[...]

No issue with tcc 0.9.27+git20200814.62c30a4a-1 provided by Debian.

--
Vincent Lefèvre <[hidden email]> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: A possible bug in TCC

Michael Matz-4
In reply to this post by Ant_222
Hello,

On Sun, 13 Dec 2020, Anton Shepelev wrote:

> Vincent Lefevre:
>
>> No issue with tcc 0.9.27+git20200814.62c30a4a-1 provided
>> by Debian.
>
> The bug on my side is reproduced with this version just five
> days old:
>
>   https://repo.or.cz/tinycc.git/snapshot/8ff705554de47f16726ec5f1a6c49a162b926732.zip
>
> I had to compile it myself on Windows, using
> win32\build-tcc.bat . Is there a pre-compiled win32 build
> available?
>
> I have also tried the same on a Linux. Since I had not
> enough permissions to install TCC, I only built it and tried
> the following from the root of the source directory:
>
>   ./tcc -Iinclude -L. ld.c

For uninstalled tcc you need to use './tcc -B. ...' to set the compiler
path to something else than the install directory.

> tcc failed with error:
>
>   file '/usr/local/lib/tcc/libtcc1.a' not found
>
> The file libtcc1.a is right there in the working directory.
> Why did it ignore -L. ?

A deficiency.  libtcc1.a is searched in a different way than normal -lfoo
libraries.

FWIW, I also can't reproduce the problem you're seeing on linux x86-64,
with various revisions of the mob branch.


Ciao,
Michael.

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: A possible bug in TCC

Ant_222
In reply to this post by Christian Jullien-3
Christian Jullien:

> I just recompiled you test program with mob. On Windows,
> cl, clang, gcc and ... tcc all produce the same output
> result.  Sorry, I can't reproduce.

I thank everybody for their help and answers and give up on
this one.  I will write it off as a hallucicatio of my PC.


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel