Lhogho  0.0.028
 All Data Structures Files Functions Variables Typedefs Macros Pages
options.c
Go to the documentation of this file.
1 //
2 // Project: Lhogho
3 // File: options.c
4 //
5 // Copyright (C) 2007 P.Boytchev
6 //
7 // Revision history:
8 // 2007-05-31 - file created
9 // 2007-06-01 - case insensitive option
10 // 2007-06-02 - option_source_filename
11 // - option_memory_statistics
12 // - use ADVANCED define to filter options
13 // 2007-06-03 - errors renamed
14 // - ERROR_CROWDED_SOURCES
15 // - option_variables
16 // 2007-06-07 - definitions spread to where they belong
17 // 2007-06-09 - fixed bug #1734091 "Bad compiler option is misinterpreted"
18 // 2007-06-11 - added option -Zuv (-Zuser-variables)
19 // - added option -x (--executable)
20 // 2007-06-13 - fixed bug #1736021 "Alloc/dealloc statistics"
21 // 2007-06-19 - added mem atoms
22 // - added XALLOC() and xalloc()
23 // 2007-06-21 - OPTION_ASM, OPTION_ASM_LONG
24 // 2007-07-09 - OPTION_RUNTIME, OPTION_RUNTIME_LONG
25 // 2007-07-11 - OPTION_TRADITIONAL, OPTION_TRADITIONAL_LONG
26 // 2007-07-29 - set_option()
27 // 2007-09-23 - OPTION_MEMORY_ALL, OPTION_MEMORY_ALL_LONG,
28 // options -Zmad, --Zmemory-all-details
29 // 2007-10-06 - added REALLOC() and realloc()
30 // 2009-05-18 - OPTION_EXECCOMP, OPTION_EXECCOMP_LONG
31 // 2010-02-07 - Fixed bug #3174945 OS alloc balance is not 0
32 // - Fixed bug #3174840 Invalid options cause a crash
33 // 2011-12-02 - Added notification of out-of-memory situations
34 // 2011-12-26 - Error messages taken from string, stored to array of atoms
35 // 2012-01-02 - Added output_compiler_name()
36 // Command-line options are translatable
37 // 2012-10-14 - Fixed bug #314 -x compile on Windows needs lhogho.exe next to .lgo source file
38 //
39 //
40 // This program is free software; you can redistribute it and/or modify
41 // it under the terms of the GNU General Public License as published by
42 // the Free Software Foundation; either version 2 of the License, or
43 // (at your option) any later version.
44 //
45 // This program is distributed in the hope that it will be useful,
46 // but WITHOUT ANY WARRANTY; without even the implied warranty of
47 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 // GNU General Public License for more details.
49 //
50 // You should have received a copy of the GNU General Public License
51 // along with this program; if not, write to the Free Software
52 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53 //
54 
55 #undef __STRICT_ANSI__
56 
57 
58 #include <assert.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <stddef.h>
63 #include <sys/stat.h> // stat, S_ISDIR, ...
64 #include "globals.h"
65 #include "atoms.h"
66 #include "words.h"
67 #include "lists.h"
68 #include "options.h"
69 #include "parser.h"
70 #include "translate.h"
71 #include "unicode.h"
72 #include "errors.h"
73 #include "vars.h"
74 #include "compiler.h"
75 
76 #ifdef LINUX
77 #include <sys/mman.h> // for mprotect()
78 #endif
79 
80 #define CHECK(PARAM1,PARAM2,BODY) \
81  if( strcmp(*argv,PARAM1)==0 || strcmp(*argv,PARAM2)==0 ) \
82  BODY;
83 
86 
91 
94 
95 #ifdef ADVANCED
96 char* id_names[MAX_ID] = {
97  "Integers",
98  "Floats",
99  "Lists",
100  "Words",
101  "Subwords",
102  "Errors",
103  "Var",
104  "Memory" };
105 
106 int stats_free;
107 int stats_allocs;
109 #endif //ADVANCED
111 
112 
113 
114 //===================================================
119 //===================================================
120 void init_options( int argc, char*argv[] )
121 {
122  // clear string options
125 
128 
129  standalone = 0;
130  standalone_arguments = empty_list;
131 
132  // load options texts
133  atom_t names = new_word( TR_OPTIONS, UNKNOWN );
134  atom_t tokens = tokenize( names, TOKENIZE_DATA );
135  atom_t t = tokens;
136 
137  // create options texts
138  int i;
139  for( i = 0; i<OPTIONS_COUNT; i++ )
140  {
141  option_turned_on [i] = 0;
142  int j;
143  for( j=0; j<4; j++ )
144  {
145  #ifdef SAFEMODE
146  assert( IS_NOT_EMPTY(t) ); // too few words in TR_OPTIONS
147  #endif
148  option_texts[j][i] = USE(CAR(t));
149  t=CDR(t);
150  }
151  }
152 
153  #ifdef SAFEMODE
154  assert( IS_EMPTY(t) ); // too many words in TR_OPTIONS
155  #endif
156 
157  DEUSE( names );
158  DEUSE( tokens );
159 }
160 
161 
162 
163 
164 //===================================================
169 //===================================================
170 #ifdef ADVANCED
171 void dump_statistics( )
172 {
173  int i;
174  int stats_used=0;
175  PRINT("%s\n","");
176  PRINT(" %10s %8s %8s %8s %8s\n","Atom type","Max","Allocs","Deallocs","Balance");
177  PRINT(" %10s %8s %8s %8s %8s\n","----------","--------","--------","--------","--------");
178  for( i=MIN_ID; i<MAX_ID; i++ )
179  {
180  stats_used += stats[i].allocs-stats[i].deallocs;
181  if( stats[i].allocs )
182  {
183  PRINT(" %10s %8d %8d %8d %8d\n",
184  id_names[i],
185  stats[i].max,
186  stats[i].allocs,
187  stats[i].deallocs,
188  stats[i].allocs-stats[i].deallocs );
189  }
190  }
191  PRINT(" %39s\n","----------------");
192  PRINT(" %30s %8d\n","Used",stats_used);
193  PRINT(" %30s %8d\n","Free",stats_free);
194  PRINT(" %39s\n","----------------");
195  PRINT(" %30s %8d\n","OS alloc balance",stats_allocs);
196 }
197 #endif
198 
199 //===================================================
204 //===================================================
205 void finit_options( )
206 {
207  int i;
208  for( i = 0; i<OPTIONS_COUNT; i++ )
209  {
210  int j;
211  for( j = 0; j<4; j++ )
212  {
213  DEUSE(option_texts[j][i]);
214  }
215  }
216  DEUSE( standalone_arguments );
217 
220 
222  {
224  }
225 
226 #ifdef ADVANCED
227  int stats_used=0;
229  {
230  dump_statistics();
231  }
232 
234  {
235  for( i=MIN_ID; i<MAX_ID; i++ )
236  stats_used += stats[i].allocs-stats[i].deallocs;
237  PRINT("{MEM#%d:%d}\n",stats_used,stats_allocs);
238  }
239 #endif //ADVANCED
240 }
241 
242 
243 
244 //===================================================
252 //===================================================
253 void output_compiler_name( int show_help )
254 {
256  atom_t texts = new_word( TR_HELP_TEXTS, UNKNOWN );
257  atom_t help_texts = tokenize( texts, TOKENIZE_DATA );
258  atom_t t = help_texts;
259 
260  dump( CAR(t) ); t = CDR(t); // LHOGHO - The LOGO Compiler
261  outter( TEXT(" [" VERSION_STR ", " OS_NAME "-" PROCESSOR_NAME "(" LANG_STR "), " __DATE__ "]\n\n"), -1 );
262 
263  if( show_help )
264  {
265  dump( CAR(t) ); t = CDR(t); // Usage
266 
267  int i;
268  for( i=0; i<OPTIONS_COUNT; i++ )
269  {
270  int len;
271 
272  if( i==FIRST_ADVANCED_OPTION )
273  {
274  #ifndef ADVANCED
275  t = CDR(t);
276  #endif
277  dumpln( CAR(t) ); t = CDR(t); // options
278  }
279 
280  // show short version
281  len = LENGTH(option_texts[0][i]);
282  outter( TEXT(" "), -1 );
283  dump( option_texts[0][i] );
284  for( ; len<6; len++ ) outter( TEXT(" "), -1 );
285 
286  // show long version
287  len = LENGTH(option_texts[2][i]);
288  if( len )
289  {
290  dump( option_texts[2][i] );
291  }
292  else
293  {
294  len = LENGTH(option_texts[1][i]);
295  dump( option_texts[1][i] );
296  }
297  for( ; len<30; len++ ) outter( TEXT(" "), -1 );
298 
299  // show description
300  dumpln( option_texts[3][i] );
301  }
302  }
303 
304  DEUSE( texts );
305  DEUSE( help_texts );
306 }
307 
308 
309 
310 //===================================================
318 //===================================================
319 void set_compiler_filename( int argc, char*argv[] )
320 {
321  // get the name of the compiler (append extension if needed)
322  option_compiler_filename = (char*)ALLOC( strlen(*argv)+strlen(EXE_EXT) );
323  strcpy( option_compiler_filename, *argv );
324 
325  char* extension = option_compiler_filename+strlen(*argv);
326  if( strcasecmp(extension-strlen(EXE_EXT),EXE_EXT)==0 )
327  strcpy( extension-strlen(EXE_EXT), EXE_EXT );
328  else
329  strcpy( extension, EXE_EXT );
330 
331  //printf("compiler filename='%s'\n",option_compiler_filename);
332  //printf("search path='%s'\n",getenv("PATH"));
333 
334  struct stat buffer;
335  int err;
336 
337 #ifdef WINDOWS
338  // In WINDOWS the current folder is always checked first
339  // So, before checking PATH, check the current folder
340  err = stat( option_compiler_filename, &buffer );
341  //printf( "full name(err=%d)='%s'\n", err, option_compiler_filename );
342  if( !err ) goto ready;
343 #endif
344 
345  char* envpath;
346  envpath = strdup( getenv("PATH") );
347  char* path = strtok(envpath,PATH_DELIM);
348 
349  while( path )
350  {
351  //printf( "dir='%s'\n", path );
352  char filename[strlen(path)+1+strlen(option_compiler_filename)+10];
353  strcpy( filename, path );
354  strcpy( filename+strlen(path), PATH_SLASH );
355  strcpy( filename+strlen(path)+1, option_compiler_filename );
356  strcpy( filename+strlen(path)+1+strlen(option_compiler_filename), "\0" );
357 
358  err = stat( filename, &buffer );
359  //printf( "full name(err=%d)='%s'\n", err, filename );
360  if( !err )
361  {
362  // We found where the file is loaded from, remember it
364  option_compiler_filename = (char*)ALLOC( strlen(filename)+1 );
365  strcpy( option_compiler_filename, filename );
366  goto free_and_ready;
367  }
368 
369  path = strtok( NULL, PATH_DELIM );
370  }
371 
372 free_and_ready:
373  free( envpath );
374 
375 #ifdef WINDOWS
376 ready:
377 #endif
379 }
380 
381 //===================================================
389 //===================================================
390 void set_options( int argc, char*argv[] )
391 {
393 
394  set_compiler_filename( argc, argv );
395 
396  // get standalone mode
397  int ptr;
398  unsigned char* code = load_file( option_compiler_filename_chars, &ptr );
399  if( !code )
400  {
401  //atom_t error = new_os_error( option_compiler_filename_chars );
402  return;
403  }
404 
405  standalone = (*(int*)(code+ptr-4)==MAGIC_NUMBER);
406  DEALLOC( code );
407 
408  // get options only if not in standalone mode,
409  // otherwise collect them in a list
410  if( standalone )
411  { // standalone mode -- collect arguments in a list
412  for( argc--,argv++; argc--; argv++ )
413  {
414  atom_t word = decode_word( (unsigned char*)*argv, strlen(*argv), 0 );
415  append( word, &standalone_arguments, &last );
416  }
417  }
418  else
419  { // compiler mode -- process options till file name and then collect arguments
420  for( argc--,argv++; argc--; argv++ )
421  {
423  {
424  atom_t word = decode_word( (unsigned char*)*argv, strlen(*argv), 0 );
425  append ( word, &standalone_arguments, &last );
426  }
427  else
428  {
429  int found = 0;
430  chars_t option = UNFILENAME(*argv);
431  int len = STRLEN(option);
432  int i;
433  for( i=0; i<OPTIONS_SUPPORTED_COUNT; i++ )
434  {
435  int j;
436  for( j=0; j<4; j++ )
437  {
438  if( len==LENGTH(option_texts[j][i]) )
439  {
440  if( same_strings(1,option,STRING(option_texts[j][i]),len) )
441  {
442  found = 1;
443  option_turned_on[i] = 1;
444  break;
445  }
446  }
447  }
448  }
449  DEALLOC( option );
450 
451  if( OPTION_HELP )
452  {
454  exit(0);
455  }
456 
457  if( found ) continue;
458 
459  // check for invalid option or second file name
460  if( **argv=='-' )
461  {
462  chars_t name = UNFILENAME(*argv); // has ALLOC inside
463  atom_t word = new_word( name, UNKNOWN );
464  atom_t err = new_error( ERROR_UNKNOWN_OPTION, word );
465  dumpln( err );
466  DEUSE( word );
467  DEALLOC( name );
468  continue;
469  }
470 
471  // set file name
472  option_source_filename = *argv;
474  }
475  } // for
476  }
477 }
478 
479 
480 
481 
482 //===================================================
502 //===================================================
503 #ifdef DEBUG_HEAP
504 void* alloc( int size, const char* func, const char* file, const int line )
505 {
506  void* buffer = malloc( size );
507  printf( "<HEAP> +[%08x] %d bytes %s(%s:%d)\n",(int)buffer,size,func,file,line );
508  if( !buffer ) { dumpln(error_texts[ERROR_OUT_OF_MEM]); exit(1); }
509  #ifdef ADVANCED
510  stats_allocs++;
511  #endif
512  return buffer;
513 }
514 
515 void* reallocate( void * mem, int size, const char* func, const char* file, const int line )
516 {
517  #ifdef ADVANCED
518  if( !mem ) stats_allocs++;
519  #endif
520  void* buffer = realloc (mem, size);
521 
522  printf( "<HEAP> +[%08x] extended with %d bytes %s(%s:%d)\n", (int)buffer, size, func, file, line);
523  if( !buffer ) { dumpln(error_texts[ERROR_OUT_OF_MEM]); exit(1); }
524 
525  return buffer;
526 }
527 
528 void* xalloc( int size, const char* func, const char* file, const int line )
529 {
530  #if defined(WINDOWS) || defined(APPLE)
531  void* buffer = malloc( size );
532  #else
533  void* buffer = valloc( size );
534  if( buffer ) {mprotect( buffer, size, PROT_READ | PROT_WRITE | PROT_EXEC );}
535  #endif
536 
537  printf( "<HEAP> +[%08x] %d bytes %s(%s:%d)\n",(int)buffer,size,func,file,line );
538  if( !buffer ) { dumpln(error_texts[ERROR_OUT_OF_MEM]); exit(1); }
539 
540  #ifdef ADVANCED
541  stats_allocs++;
542  #endif
543  return buffer;
544 }
545 void dealloc( void* ptr, const char* func, const char* file, const int line )
546 {
547  printf( "<HEAP> -[%08x] %s(%s:%d)\n",(int)ptr,func,file,line );
548  #ifdef ADVANCED
549  stats_allocs--;
550  #endif
551  free( ptr );
552 }
553 #else //DEBUG_HEAP
554 void* alloc( int size )
555 {
556  void* buffer = malloc( size );
557  if( !buffer ) { dumpln(error_texts[ERROR_OUT_OF_MEM]); exit(1); }
558  #ifdef ADVANCED
559  stats_allocs++;
560  #endif
561  return buffer;
562 }
563 
564 void* reallocate(void * mem, int size)
565 {
566  #ifdef ADVANCED
567  if( !mem ) stats_allocs++;
568  #endif
569  void* buffer = realloc(mem, size);
570  if( !buffer ) { dumpln(error_texts[ERROR_OUT_OF_MEM]); exit(1); }
571  return buffer;
572 }
573 
574 void* xalloc( int size )
575 {
576  #if defined(WINDOWS) || defined(APPLE)
577  void* buffer = malloc( size );
578  #else
579  void* buffer = valloc( size );
580  mprotect( buffer, size, PROT_READ | PROT_WRITE | PROT_EXEC );
581  #endif
582 
583  if( !buffer ) { dumpln(error_texts[ERROR_OUT_OF_MEM]); exit(1); }
584 
585  #ifdef ADVANCED
586  stats_allocs++;
587  #endif
588  return buffer;
589 }
590 void dealloc( void* ptr )
591 {
592  #ifdef ADVANCED
593  stats_allocs--;
594  #endif
595  free( ptr );
596 }
597 #endif //DEBUG_HEAP
598 

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