Lhogho  0.0.027
Defines | Functions | Variables
errors.c File Reference

Defines

#define LEFT_DIST   10
#define RIGHT_DIST   40
#define DUMP_BUF_SIZE   128

Functions

void init_errors ()
 initializes errors
void finit_errors ()
 finalizes errors
atom_t new_error (uint_t code, atom_t data)
 creates a new error atom
atom_t new_os_error (chars_t filename)
 creates error atom for OS error
atom_t new_os_error_atom (atom_t filename)
atom_t new_parse_error (uint_t code, int position, atom_t source)
 creates error atom for parser's error
void add_error_source (atom_t error, atom_t source)
 adds new error position to an error
void delete_error (atom_t a)
 deletes error atom
int get_error_position (atom_t data, chars_t *source)
 gets error position
void dump_neighbourhood (chars_t source, int position)
 dumps source around some position
void dump_error (atom_t a, int level)
 dumps error atom
void clear_all_errors ()
 clears all errors

Variables

atom_t error_texts [LAST_ERROR_CODE+1]
 Texts for error messages.
int last_os_error
 records last OS error code
atom_t all_errors = NULL
 list of all occurred errors

Define Documentation

#define LEFT_DIST   10
#define RIGHT_DIST   40
#define DUMP_BUF_SIZE   128

Function Documentation

Initializes the table with error messages taken from TR_ERRORS.

{
  error_texts[0] = unbound;
  
  atom_t names = new_word( TR_ERRORS, UNKNOWN );
  atom_t tokens = tokenize( names, TOKENIZE_DATA );
  atom_t t = tokens; 

  // create error texts
  int i;
  for( i = 1; i<=LAST_ERROR_CODE; i++, t=CDR(t) )
    {
      #ifdef SAFEMODE
        assert( IS_NOT_EMPTY(t) ); // too few words in TR_PRIMITIVES
      #endif

      error_texts[i] = USE(CAR(t));
  }

  #ifdef SAFEMODE
    assert( IS_EMPTY(t) ); // too many words in TR_PRIMITIVES
  #endif

  DEUSE( names );
  DEUSE( tokens );
}

Frees atoms holding error texts.

{
  int i;
  for( i = 1; i<=LAST_ERROR_CODE; i++ )
    {
      DEUSE(error_texts[i]);
  }
}
atom_t new_error ( uint_t  code,
atom_t  data 
)
Parameters:
codeerror code
dataerror data
Returns:
error atom

Creates an error atom with reference count 1. The reference count of data is increased. Initializes the error position to be a list containing one element, which is the data parameter itself.

{
  //printf("-----------\n");
  //printf("new error code=%d\n",code);
  //printf("new error data="); dumpln(data);
  //printf("-----------\n");

  atom_t a = take_from_pool( &data_pool );

  #ifdef SAFEMODE
    assert( data );
  #endif //SAFEMODE

  REF(a) = 1;
  ID(a)  = ERROR_ID;
  ERRCODE(a)  = code;
  ERRPOS(a)   = new_list( USE(data), empty_list );
  ERRDATA(a)  = USE(data);

  #ifdef DEBUG_ATOM
    printf("<ATOM>  [%08x] error=[code=%d]\n",(int)a,code);
  #endif //DEBUG_ATOM

  #ifdef ADVANCED
    stats[ID(a)].allocs++;
    if( stats[ID(a)].max<(stats[ID(a)].allocs-stats[ID(a)].deallocs) )
      stats[ID(a)].max=(stats[ID(a)].allocs-stats[ID(a)].deallocs);
    stats_free--;
  #endif //ADVANCED

  #ifdef DEBUG_RUNTIME_ATOMS
  if( running_compiled_code )
    {
      outter( TEXT("<RUNTIME> new  "), -1 );
      dump_atom_address( a );
      dump_atom( a, 1 );
      outter( TEXT("\n"), -1 );
    }
  #endif
  #ifdef DEBUG_COMPILETIME_ATOMS
  if( compiling_code )
    {
      outter( TEXT("<COMPILETIME> new  "), -1 );
      dump_atom_address( a );
      dump_atom( a, 1 );
      outter( TEXT("\n"), -1 );
    }
  #endif

  if( all_errors==NULL ) all_errors = empty_list;
  all_errors = new_list( a, all_errors );

  return a;
}
atom_t new_os_error ( chars_t  filename)
Parameters:
filenamefile name associated with the error
Returns:
error atom

Creates error atom describing OS error.

{
  atom_t wrd = new_word( filename, UNKNOWN );
  new_os_error_atom( wrd );
  return new_error( ERROR_OS_ERROR, wrd );
}
{
  last_os_error = errno;
  return new_error( ERROR_OS_ERROR, filename );
}
atom_t new_parse_error ( uint_t  code,
int  position,
atom_t  source 
)
Parameters:
codeerror code
positioncharacter position within the source
source(sub)word containing the source
Returns:
error atom

Creates error atom describing an error generated by the parser.

{
  atom_t errsrc = new_subword( source, STRING(source)+position, 1 );
  atom_t error = new_error( code, unbound );
  CAR(ERRPOS(error)) = errsrc;
  return error;
}
void add_error_source ( atom_t  error,
atom_t  source 
)
Parameters:
errorerror to which new position will be added
sourceerror source

Adds a new error position to an already existing error atom. The error position is simply an atom which may have been extracted from the actual source. The new error position is inserted in the first place of the list of error positions.

{
  //printf("register error pos>>>---------------\n");
  //printf("register error src>>>"); dumpln(source);
  //printf("register error err>>>"); dumpln(error);
  //printf("register error pos>>>---------------\n");
  //printf("errpos old ref=%d\n",REF(ERRPOS(error)));
  ERRPOS(error) = new_list( USE(source), ERRPOS(error) );
  //printf("errpos new ref=%d\n",REF(ERRPOS(error)));
}
Parameters:
aatom to delete

Deletes error atom by returning it back to the data pool. The source atom is dereferenced.

{
  //printf("****** DELETING ERROR ****** [%x]\n",(int)a);
  DEUSE( ERRPOS(a) );
  DEUSE( ERRDATA(a) );
  return_to_pool( &data_pool, a );
}
int get_error_position ( atom_t  data,
chars_t source 
)
Parameters:
datadata to search for
sourcesource where the data is found
Returns:
position of data within found source

Tries to identify the position of the first (sub)word in the data in the original source. This function returns the character position and the source. If the source cannot be identified, then return -1 and set source to NULL.

{
  // dig in a list to find the first (sub)word
  while( IS_LIST(data) & IS_NOT_EMPTY(data) ) data = CAR(data);

  // if it is a word then return we have found something
  if( IS_WORD(data) )
    {
      *source = STRING(data);
      return 0;
    }

  // if it is a subword then return we have found something
  if( IS_SUBWORD(data) )
    {
      *source = STRING(WORD(data));
      return STRING(data)-STRING(WORD(data));
    }

  // no, could not find the error position
  *source = NULL;
  return -1;
}
void dump_neighbourhood ( chars_t  source,
int  position 
)
Parameters:
sourcesource containing the neighbourhood
positionposition marking the neighbourhood

Dumps a piece of source code containing given position. The dumped neighbourhood starts before the position and end after it in a way that: (1) at most LEFT_DIST chars before the position are included (2) at most RIGHT_DIST chars after the position are included (3) the neightbourhood contains characters from a single line only Dumped neighbourhood is output as a single line with an arrow anove it pointing the exact position.

{
  if( !source || position<0 ) return;

  int left;
  int right;
  int ellipses = 1;
  for( left=0; left<LEFT_DIST; left++ )
    {
      // reached the beginning of the source?
      if( position-left == 0 ) {ellipses=0; break;}

      // reached the beginning of the line?
      char_t ch = *(source+(position-left-1));
      if( ch==TEXT('\n') || ch==TEXT('\r') ) {ellipses=0; break;}
    }
  while( left && ((*(source+position-left))<=TEXT(' ')) ) left--;

  for( right=0; right<RIGHT_DIST; right++ )
    {
      // reached the end of the line/file?
      char_t ch = *(source+(position+right+1));
      if( ch=='\n' || ch=='\r' || ch=='\0') break;
    }

  int i;
  chars_t s;
  if( ellipses ) outter( TEXT("..."), 3 );
  for( i=0,s=source+position-left; i<left+right+1; i++,s++ ) outter( s, 1 );
  if( *(source+position+right+1)>=TEXT(' ') )
    outter( TEXT("..."), 3 );
  outter( TEXT("\n"), -1 );
  for( i=0; i<left+3*ellipses; i++ ) outter( TEXT(" "), 1 );
  outter( TEXT("^"), -1 );
}
void dump_error ( atom_t  a,
int  level 
)
Parameters:
aatom to dump
leveldump level

Dumps error atom through the current outter function.

{
  #define DUMP_BUF_SIZE 128
  char_t buf[DUMP_BUF_SIZE];
  int n;

  //printf("<<err ref=%d>> ",REF(a));
  //printf("temporary dump of an error\n");
  //printf(">>>>>>error ref  = %d\n",REF(a));
  //printf(">>>>>>error code = %d\n",ERRCODE(a));
  //printf(">>>>>>error posn = "); dumpln(ERRPOS(a));
  //printf(">>>>>>error data = "); dumpln(ERRDATA(a));
  //return;

  int errpos = -1;
  int errpos2 = -1;
  int errpos3 = -1;
  chars_t errsrc = NULL;
  chars_t errsrc2 = NULL;
  chars_t errsrc3 = NULL;
  atom_t p;
  //printf("errpos="); dump_atom(ERRPOS(a),1); printf("\n------------\n");
  for( p=ERRPOS(a); IS_NOT_EMPTY(p); p=CDR(p) )
    {
      //printf("ERRPOS=");dumpln(CAR(p));
      chars_t src;
      int pos = get_error_position( CAR(p), &src );
      if( pos>-1 )
   {
     errpos3 = errpos2;
     errsrc3 = errsrc2;
     errpos2 = errpos;
     errsrc2 = errsrc;
     errpos = pos;
     errsrc = src;
   }
      //printf("pos=%d source=",pos); dumpln(CAR(p));
    }

  if( ERRCODE(a)==EXIT_BY_THROW_USER_ERROR )
    {
      errpos = errpos3;
      errsrc = errsrc3;
    }

  // print error code
  n = SPRINTF( buf, DUMP_BUF_SIZE, FORMAT_ERR_CODE, ERRCODE(a) );
  outter( buf, n );

  // print error position
  n = SPRINTF( buf, DUMP_BUF_SIZE, FORMAT_ERR_POS, errpos );
  outter( buf, n );

  // print error message
  if( ERRCODE(a)==EXIT_BY_THROW_USER_ERROR )
    {
      outter( TEXT(" - "), 3 );
      dump( ERRDATA(a) );
    }
  else
    {
      #ifdef SAFEMODE
        assert( ERRCODE(a)>0 );
        assert( ERRCODE(a)<=LAST_ERROR_CODE );
      #endif
      outter( TEXT(" - "), 3 );
      dump( error_texts[ERRCODE(a)] );
    }

  if( ERRCODE(a)==ERROR_OS_ERROR )
    {
      chars_t msg = UNFILENAME(strerror(last_os_error));
      outter( TEXT(": "), 2 );
      outter( msg, -1 );
      DEALLOC( msg );
    }
  outter( TEXT("\n"), -1 );

  // print error source
  dump_neighbourhood( errsrc, errpos );
}

Clears all errors recorder in all_errors except for the one stored in last_error

{
  atom_t err = all_errors;
  if( err==NULL ) return;

  //printf("===INSIDE CLEAR_ALL_ERRORS===\n");
  //printf("===EXCEPTION(%d):  ",REF(last_error)); dumpln(last_error);
  //printf("===ALL ERRORS (BEFORE): "); dumpln(all_errors);

  //printf("===START ERROR SCANNING===\n");
  while( IS_NOT_EMPTY(err) )
    {
      //printf("===ERROR: [%x]\n",CAR(err));
      if( CAR(err)!=last_error ) REF(CAR(err)) = 1;
      err = CDR(err);
    }
  //printf("===END ERROR SCANNING===\n");

  USE( last_error );
  //printf("AEREF=%d !!!!!!!!!!!!!!!!\n",REF(all_errors));
  DEUSE( all_errors );
  //printf("AEREF=%d !!!!!!!!!!!!!!!!\n",REF(all_errors));
  DEUSE( last_error );

  all_errors = empty_list;
  //printf("===END OF CLEAR_ALL_ERRORS===\n\n");
}

Variable Documentation


[ HOME | INDEX | ATOMS | VARS | REFERENCE ]
Lhogho Developer's Documentation
Tue Feb 7 2012