Lhogho  0.0.028
 All Data Structures Files Functions Variables Typedefs Macros Pages
errors.c
Go to the documentation of this file.
1 //
2 // Project: Lhogho
3 // File: errors.c
4 //
5 // Copyright (C) 2007 P.Boytchev
6 //
7 // Revision history:
8 // 2007-06-01 - file created
9 // 2007-06-03 - errors renamed
10 // - TR_ERROR_CROWDED_SOURCES, TR_ERROR_OS_ERROR
11 // - ERROR_INCOMPATIBLE_REDEFINITION
12 // 2007-06-05 - definitions spread to where they belong
13 // 2007-06-09 - added dump_error()
14 // 2007-06-26 - ERROR_NOT_A_NUMBER
15 // 2007-09-09 - ERROR_DO_NOT_KNOW
16 // - ERROR_UNKNOWN_VAR
17 // 2007-09-17 - ERROR_BOOLEAN_EXPECTED
18 // 2007-09-21 - ERROR_NOT_AN_INTEGER, ERROR_NOT_A_LIST
19 // 2007-10-06 - ERROR_NOT_A_WORD
20 // 2007-10-13 - ERROR_INCOMPATIBLE_DATA
21 // 2007-10-16 - Fixed bug #1814277 Memory leak in LAST [ ]
22 // - Fixed bug #1814278 Memory leak in BL [ ]
23 // - Fixed bug #1814439 No error position in some cases
24 // 2007-10-17 - ERROR_TOO_BIG_NUMBER, ERROR_TOO_SMALL_NUMBER
25 // 2007-11-12 - EXIT_BY_BYE, EXIT_BY_THROW_TOPLEVEL,
26 // EXIT_BY_THROW_SYSTEM, EXIT_BY_THROW_ERROR
27 // 2007-11-15 - EXIT_BY_THROW_TAG, EXIT_BY_THROW_TAG_VALUE
28 // 2007-12-04 - ERROR_NOT_A_USER_FUNCTION
29 // 2008-01-05 - ERROR_VAR_HAS_NO_VALUE
30 // 2008-09-11 - ERROR_NOT_A_TYPE_NAME
31 // 2008-09-13 - ERROR_BAD_PROTOTYPE
32 // 2008-11-22 - ERROR_NOT_A_MEM
33 // 2009-08-29 - Fixed bug #2845099 Memory leak in THROW
34 // - Fixed bug #2845579 DEBUG_MEMORY_LEAKS finds two bad tests
35 // - Fixed bug #2846281 Errors not (de)used correctly
36 // 2009-08-31 - Fixed bug #2847389 Memory leak for unknown file
37 // 2011-10-07 - Removed TR_WARNING_UNSUPPORTED_COMPILER, because GCC 4+ is now supported
38 // 2011-12-26 - Error messages taken from string, stored to array of atoms
39 // 2012-01-20 - Added new_os_error_atom()
40 //
41 //
42 // This program is free software; you can redistribute it and/or modify
43 // it under the terms of the GNU General Public License as published by
44 // the Free Software Foundation; either version 2 of the License, or
45 // (at your option) any later version.
46 //
47 // This program is distributed in the hope that it will be useful,
48 // but WITHOUT ANY WARRANTY; without even the implied warranty of
49 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50 // GNU General Public License for more details.
51 //
52 // You should have received a copy of the GNU General Public License
53 // along with this program; if not, write to the Free Software
54 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
55 //
56 
57 #include <assert.h>
58 #include <errno.h>
59 #include <stdio.h>
60 #include <unistd.h> // getcwd()
61 
62 #include "atoms.h"
63 #include "words.h"
64 #include "lists.h"
65 #include "translate.h"
66 #include "unicode.h"
67 #include "pools.h"
68 #include "errors.h"
69 #include "vars.h"
70 #include "compiler.h"
71 #include "numbers.h"
72 #include "parser.h"
73 
75 
76 
77 
78 
81 
82 
83 
84 //===================================================
90 //===================================================
91 void init_errors( )
92 {
93  error_texts[0] = unbound;
94 
95  atom_t names = new_word( TR_ERRORS, UNKNOWN );
96  atom_t tokens = tokenize( names, TOKENIZE_DATA );
97  atom_t t = tokens;
98 
99  // create error texts
100  int i;
101  for( i = 1; i<=LAST_ERROR_CODE; i++, t=CDR(t) )
102  {
103  #ifdef SAFEMODE
104  assert( IS_NOT_EMPTY(t) ); // too few words in TR_PRIMITIVES
105  #endif
106 
107  error_texts[i] = USE(CAR(t));
108  }
109 
110  #ifdef SAFEMODE
111  assert( IS_EMPTY(t) ); // too many words in TR_PRIMITIVES
112  #endif
113 
114  DEUSE( names );
115  DEUSE( tokens );
116 }
117 
118 
119 
120 
121 //===================================================
126 //===================================================
128 {
129  int i;
130  for( i = 1; i<=LAST_ERROR_CODE; i++ )
131  {
132  DEUSE(error_texts[i]);
133  }
134 }
135 
136 
137 
138 
139 //===================================================
151 //===================================================
153 {
154  //printf("-----------\n");
155  //printf("new error code=%d\n",code);
156  //printf("new error data="); dumpln(data);
157  //printf("-----------\n");
158 
160 
161  #ifdef SAFEMODE
162  assert( data );
163  #endif //SAFEMODE
164 
165  REF(a) = 1;
166  ID(a) = ERROR_ID;
167  ERRCODE(a) = code;
168  ERRPOS(a) = new_list( USE(data), empty_list );
169  ERRDATA(a) = USE(data);
170 
171  #ifdef DEBUG_ATOM
172  printf("<ATOM> [%08x] error=[code=%d]\n",(int)a,code);
173  #endif //DEBUG_ATOM
174 
175  #ifdef ADVANCED
176  stats[ID(a)].allocs++;
177  if( stats[ID(a)].max<(stats[ID(a)].allocs-stats[ID(a)].deallocs) )
178  stats[ID(a)].max=(stats[ID(a)].allocs-stats[ID(a)].deallocs);
179  stats_free--;
180  #endif //ADVANCED
181 
182  #ifdef DEBUG_RUNTIME_ATOMS
184  {
185  outter( TEXT("<RUNTIME> new "), -1 );
186  dump_atom_address( a );
187  dump_atom( a, 1 );
188  outter( TEXT("\n"), -1 );
189  }
190  #endif
191  #ifdef DEBUG_COMPILETIME_ATOMS
192  if( compiling_code )
193  {
194  outter( TEXT("<COMPILETIME> new "), -1 );
195  dump_atom_address( a );
196  dump_atom( a, 1 );
197  outter( TEXT("\n"), -1 );
198  }
199  #endif
200 
201  if( all_errors==NULL ) all_errors = empty_list;
202  all_errors = new_list( a, all_errors );
203 
204  return a;
205 }
206 
207 
208 
209 //===================================================
216 //===================================================
218 {
219  atom_t wrd = new_word( filename, UNKNOWN );
220  atom_t res = new_os_error_atom( wrd );
221  DEUSE( wrd );
222  return res;
223  //return new_error( ERROR_OS_ERROR, wrd );
224 }
226 {
227  last_os_error = errno;
228  return new_error( ERROR_OS_ERROR, filename );
229 }
230 
231 
232 
233 
234 //===================================================
244 //===================================================
245 atom_t new_parse_error( uint_t code, int position, atom_t source )
246 {
247  atom_t errsrc = new_subword( source, STRING(source)+position, 1 );
248  atom_t error = new_error( code, unbound );
249  CAR(ERRPOS(error)) = errsrc;
250  return error;
251 }
252 
253 
254 
255 
256 //===================================================
267 //===================================================
268 void add_error_source( atom_t error, atom_t source )
269 {
270  //printf("register error pos>>>---------------\n");
271  //printf("register error src>>>"); dumpln(source);
272  //printf("register error err>>>"); dumpln(error);
273  //printf("register error pos>>>---------------\n");
274  //printf("errpos old ref=%d\n",REF(ERRPOS(error)));
275  ERRPOS(error) = new_list( USE(source), ERRPOS(error) );
276  //printf("errpos new ref=%d\n",REF(ERRPOS(error)));
277 }
278 
279 
280 
281 
282 //===================================================
289 //===================================================
291 {
292  //printf("****** DELETING ERROR ****** [%x]\n",(int)a);
293  DEUSE( ERRPOS(a) );
294  DEUSE( ERRDATA(a) );
295  return_to_pool( &data_pool, a );
296 }
297 
298 
299 
300 
301 //===================================================
313 //===================================================
314 int get_error_position( atom_t data, chars_t* source )
315 {
316  // dig in a list to find the first (sub)word
317  while( IS_LIST(data) & IS_NOT_EMPTY(data) ) data = CAR(data);
318 
319  // if it is a word then return we have found something
320  if( IS_WORD(data) )
321  {
322  *source = STRING(data);
323  return 0;
324  }
325 
326  // if it is a subword then return we have found something
327  if( IS_SUBWORD(data) )
328  {
329  *source = STRING(WORD(data));
330  return STRING(data)-STRING(WORD(data));
331  }
332 
333  // no, could not find the error position
334  *source = NULL;
335  return -1;
336 }
337 
338 
339 
340 //===================================================
357 //===================================================
358 #define LEFT_DIST 10
359 #define RIGHT_DIST 40
360 void dump_neighbourhood( chars_t source, int position )
361 {
362  if( !source || position<0 ) return;
363 
364  int left;
365  int right;
366  int ellipses = 1;
367  for( left=0; left<LEFT_DIST; left++ )
368  {
369  // reached the beginning of the source?
370  if( position-left == 0 ) {ellipses=0; break;}
371 
372  // reached the beginning of the line?
373  char_t ch = *(source+(position-left-1));
374  if( ch==TEXT('\n') || ch==TEXT('\r') ) {ellipses=0; break;}
375  }
376  while( left && ((*(source+position-left))<=TEXT(' ')) ) left--;
377 
378  for( right=0; right<RIGHT_DIST; right++ )
379  {
380  // reached the end of the line/file?
381  char_t ch = *(source+(position+right+1));
382  if( ch=='\n' || ch=='\r' || ch=='\0') break;
383  }
384 
385  int i;
386  chars_t s;
387  if( ellipses ) outter( TEXT("..."), 3 );
388  for( i=0,s=source+position-left; i<left+right+1; i++,s++ ) outter( s, 1 );
389  if( *(source+position+right+1)>=TEXT(' ') )
390  outter( TEXT("..."), 3 );
391  outter( TEXT("\n"), -1 );
392  for( i=0; i<left+3*ellipses; i++ ) outter( TEXT(" "), 1 );
393  outter( TEXT("^"), -1 );
394 }
395 
396 
397 
398 
399 
400 
401 
402 
403 //===================================================
410 //===================================================
411 void dump_error( atom_t a, int level )
412 {
413  #define DUMP_BUF_SIZE 128
414  char_t buf[DUMP_BUF_SIZE];
415  int n;
416 
417  //printf("<<err ref=%d>> ",REF(a));
418  //printf("temporary dump of an error\n");
419  //printf(">>>>>>error ref = %d\n",REF(a));
420  //printf(">>>>>>error code = %d\n",ERRCODE(a));
421  //printf(">>>>>>error posn = "); dumpln(ERRPOS(a));
422  //printf(">>>>>>error data = "); dumpln(ERRDATA(a));
423  //return;
424 
425  int errpos = -1;
426  int errpos2 = -1;
427  int errpos3 = -1;
428  chars_t errsrc = NULL;
429  chars_t errsrc2 = NULL;
430  chars_t errsrc3 = NULL;
431  atom_t p;
432  //printf("errpos="); dump_atom(ERRPOS(a),1); printf("\n------------\n");
433  for( p=ERRPOS(a); IS_NOT_EMPTY(p); p=CDR(p) )
434  {
435  //printf("ERRPOS=");dumpln(CAR(p));
436  chars_t src;
437  int pos = get_error_position( CAR(p), &src );
438  if( pos>-1 )
439  {
440  errpos3 = errpos2;
441  errsrc3 = errsrc2;
442  errpos2 = errpos;
443  errsrc2 = errsrc;
444  errpos = pos;
445  errsrc = src;
446  }
447  //printf("pos=%d source=",pos); dumpln(CAR(p));
448  }
449 
451  {
452  errpos = errpos3;
453  errsrc = errsrc3;
454  }
455 
456  // print error code
457  n = SPRINTF( buf, DUMP_BUF_SIZE, FORMAT_ERR_CODE, ERRCODE(a) );
458  outter( buf, n );
459 
460  // print error position
461  n = SPRINTF( buf, DUMP_BUF_SIZE, FORMAT_ERR_POS, errpos );
462  outter( buf, n );
463 
464  // print error message
466  {
467  outter( TEXT(" - "), 3 );
468  dump( ERRDATA(a) );
469  }
470  else
471  {
472  #ifdef SAFEMODE
473  assert( ERRCODE(a)>0 );
474  assert( ERRCODE(a)<=LAST_ERROR_CODE );
475  #endif
476  outter( TEXT(" - "), 3 );
477  dump( error_texts[ERRCODE(a)] );
478  }
479 
480  if( ERRCODE(a)==ERROR_OS_ERROR )
481  {
482  chars_t msg = UNFILENAME(strerror(last_os_error));
483  outter( TEXT(": "), 2 );
484  outter( msg, -1 );
485  DEALLOC( msg );
486  }
487  outter( TEXT("\n"), -1 );
488 
489  // print error source
490  dump_neighbourhood( errsrc, errpos );
491 }
492 
493 
494 
495 
496 //===================================================
502 //===================================================
504 {
505  atom_t err = all_errors;
506  if( err==NULL ) return;
507 
508  //printf("===INSIDE CLEAR_ALL_ERRORS===\n");
509  //printf("===EXCEPTION(%d): ",REF(last_error)); dumpln(last_error);
510  //printf("===ALL ERRORS (BEFORE): "); dumpln(all_errors);
511 
512  //printf("===START ERROR SCANNING===\n");
513  while( IS_NOT_EMPTY(err) )
514  {
515  //printf("===ERROR: [%x]\n",CAR(err));
516  if( CAR(err)!=last_error ) REF(CAR(err)) = 1;
517  err = CDR(err);
518  }
519  //printf("===END ERROR SCANNING===\n");
520 
521  USE( last_error );
522  //printf("AEREF=%d !!!!!!!!!!!!!!!!\n",REF(all_errors));
523  DEUSE( all_errors );
524  //printf("AEREF=%d !!!!!!!!!!!!!!!!\n",REF(all_errors));
525  DEUSE( last_error );
526 
527  all_errors = empty_list;
528  //printf("===END OF CLEAR_ALL_ERRORS===\n\n");
529 }

[ HOME | INDEX | ATOMS | VARS | REFERENCE ]
Lhogho Developer's Documentation
Wed Jul 10 2013