PageRenderTime 106ms CodeModel.GetById 12ms app.highlight 80ms RepoModel.GetById 1ms app.codeStats 0ms

/test/language/unclassified/test_overload011.c

http://github.com/tybor/Liberty
C | 2439 lines | 1834 code | 173 blank | 432 comment | 410 complexity | 786908f8b66825480dcd99b05168bb80 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#ifdef __cplusplus
   2extern "C" {
   3#endif
   4/*
   5ANSI C code generated by SmartEiffel The GNU Eiffel Compiler, Eiffel tools and libraries
   6Release 2.4 (??? June ??th 2008) [????]
   7Copyright (C), 1994-2002 - INRIA - LORIA - ESIAL UHP Nancy 1 - FRANCE
   8Copyright (C), 2003-2005 - INRIA - LORIA - IUT Charlemagne Nancy 2 - FRANCE
   9D.COLNET, P.RIBET, C.ADRIAN, V.CROIZIER F.MERIZEN - SmartEiffel@loria.fr
  10http://SmartEiffel.loria.fr
  11C Compiler options used: -pipe
  12*/
  13
  14#ifdef __cplusplus
  15}
  16#endif
  17#include "test_overload01.h"
  18#ifdef __cplusplus
  19extern "C" {
  20#endif
  21/*
  22-- ------------------------------------------------------------------------------------------------------------
  23-- Copyright notice below. Please read.
  24--
  25-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P.       - University of Nancy 1 - FRANCE
  26-- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  27--
  28-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  29--
  30-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  31-- documentation files (the "Software"), to deal in the Software without restriction, including without
  32-- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  33-- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
  34-- conditions:
  35--
  36-- The above copyright notice and this permission notice shall be included in all copies or substantial
  37-- portions of the Software.
  38--
  39-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  40-- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
  41-- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  42-- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  43-- OR OTHER DEALINGS IN THE SOFTWARE.
  44--
  45-- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  46-- ------------------------------------------------------------------------------------------------------------
  47*/
  48/*
  49  This file (SmartEiffel/sys/runtime/base.c) is included for _all_ modes of
  50  compilation (-boost, -no_check, ... -all_check).
  51*/
  52
  53/*
  54  Byte swapping function
  55*/
  56void copy_swap_16(const uint16_t *src, uint16_t *dest, int count){
  57  while (count--) {
  58    *dest++ = (*src << 8) | (*src >> 8);
  59    src++;
  60  }
  61}
  62
  63
  64/*
  65  The wrapper for `malloc' (generated C code is supposed to use
  66  only `se_malloc' instead of direct `malloc').
  67*/
  68void* se_malloc(size_t size) {
  69  void *result = malloc(size);
  70  if (result == NULL) {
  71    handle(SE_HANDLE_NO_MORE_MEMORY, NULL);
  72#ifdef SE_EXCEPTIONS
  73    internal_exception_handler(No_more_memory);
  74#elif !defined(SE_BOOST)
  75    error0("No more memory.", NULL);
  76#else
  77  fprintf(SE_ERR,"No more memory (malloc failed).\n");
  78  exit(EXIT_FAILURE);
  79#endif
  80  }
  81  return result;
  82}
  83
  84/*
  85  The wrapper for `calloc' (generated C code is supposed to use
  86  only `se_calloc' instead of direct `calloc').
  87*/
  88void* se_calloc(size_t nmemb, size_t size) {
  89  void *result = calloc(nmemb,size);
  90  if (result == NULL) {
  91    handle(SE_HANDLE_NO_MORE_MEMORY, NULL);
  92#ifdef SE_EXCEPTIONS
  93    internal_exception_handler(No_more_memory);
  94#elif !defined(SE_BOOST)
  95    error0("No more memory.", NULL);
  96#else
  97  fprintf(SE_ERR,"No more memory (calloc failed).\n");
  98  exit(EXIT_FAILURE);
  99#endif
 100  }
 101  return result;
 102}
 103
 104/*
 105  The wrapper for `realloc' (generated C code is supposed to use
 106  only `se_realloc' instead of direct `realloc').
 107*/
 108void* se_realloc(void* src, size_t size) {
 109  void *result = realloc(src, size);
 110  if (result == NULL) {
 111    handle(SE_HANDLE_NO_MORE_MEMORY, NULL);
 112#ifdef SE_EXCEPTIONS
 113    internal_exception_handler(No_more_memory);
 114#elif !defined(SE_BOOST)
 115    error0("No more memory.", NULL);
 116#else
 117  fprintf(SE_ERR,"No more memory (realloc failed).\n");
 118  exit(EXIT_FAILURE);
 119#endif
 120  }
 121  return result;
 122}
 123
 124/* ---------------------------------------------------------------------- */
 125
 126void se_die (int code) {
 127  handle(SE_HANDLE_DIE_WITH_CODE, &code);
 128  exit(code);
 129}
 130
 131/*
 132    Runtime hooks
 133 */
 134
 135static se_runtime_handler_t** handlers = NULL;
 136int handlers_count=0;
 137
 138void register_handler(se_runtime_handler_t*handler) {
 139  int new_count = handlers_count + 1;
 140  handlers = (se_runtime_handler_t**)se_realloc(handlers, (new_count) * sizeof(void*));
 141  handlers[handlers_count] = handler;
 142  handlers_count = new_count;
 143}
 144
 145void _handle(se_handler_action_t action, void*data) {
 146  int i;
 147  for (i = 0; i < handlers_count; i++) {
 148    handlers[i](action, data);
 149    /* *** Check type of this array. Function pointer may have different size from data pointer. (PH 17/07/08) */
 150  }
 151}
 152/*
 153-- ------------------------------------------------------------------------------------------------------------
 154-- Copyright notice below. Please read.
 155--
 156-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P.       - University of Nancy 1 - FRANCE
 157-- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
 158--
 159-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
 160--
 161-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 162-- documentation files (the "Software"), to deal in the Software without restriction, including without
 163-- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 164-- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
 165-- conditions:
 166--
 167-- The above copyright notice and this permission notice shall be included in all copies or substantial
 168-- portions of the Software.
 169--
 170-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 171-- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
 172-- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 173-- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 174-- OR OTHER DEALINGS IN THE SOFTWARE.
 175--
 176-- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
 177-- ------------------------------------------------------------------------------------------------------------
 178*/
 179#if defined __USE_POSIX || defined __unix__ || defined _POSIX_C_SOURCE
 180/* macro read is used of read_stdin */
 181
 182void io_copy (char*source, char*target) {
 183  /* We use the low-level descriptor functions rather than stream-oriented functions.
 184   * This allows us to copy the file's permissions. */
 185
 186  int src;
 187  int tgt;
 188  struct stat info;
 189  static char *buffer = NULL;
 190  static int bufsize = 0;
 191  int read_count, write_count, written;
 192
 193  src=open (source, O_RDONLY);
 194  if (fstat (src, &info))
 195    return; /* Ooops */
 196  if (bufsize < info.st_blksize)
 197    buffer=se_realloc (buffer, info.st_blksize);
 198  tgt=creat (target, info.st_mode);
 199  do {
 200    read_count = read (src, buffer, info.st_blksize);
 201    write_count = 0; written = 0;
 202    while  ((write_count < read_count) && (written >= 0))
 203      {
 204	written = write (tgt, buffer + write_count, read_count - write_count);
 205	write_count += written;
 206      }
 207  } while ((read_count > 0) && (written >= 0));
 208  close (src);
 209  close (tgt);
 210}
 211
 212int io_same_physical_file(char*path1,char*path2) {
 213  struct stat info1, info2;
 214  if (stat(path1, &info1))
 215    return 0; /* oops */
 216  if (stat(path2, &info2))
 217    return 0; /* oops */
 218  return (info1.st_dev == info2.st_dev) && (info1.st_ino == info2.st_ino);
 219}
 220
 221#else
 222#define IO_COPY_BUFSIZE 4096
 223
 224int read_stdin(EIF_CHARACTER *buffer, int size) {
 225  int c;
 226  c = getc(stdin);
 227  if (c==EOF)
 228    return 0;
 229  *buffer = (EIF_CHARACTER)c;
 230  return 1;
 231}
 232
 233void io_copy(char*source, char*target) {
 234  static char *buffer = NULL;
 235  int read_count;
 236  FILE*src=fopen(source, "rb");
 237  FILE*tgt=fopen(target, "wb");
 238
 239  if(!buffer)
 240    buffer = (char*)se_malloc(IO_COPY_BUFSIZE);
 241
 242  while ((read_count = fread(buffer, 1, IO_COPY_BUFSIZE, src)), read_count) {
 243    size_t dummy = fwrite(buffer, 1, read_count, tgt);
 244  }
 245  fclose(src);
 246  fclose(tgt);
 247}
 248
 249int io_same_physical_file(char*path1,char*path2) {
 250  /* default implementation returns true only if the paths are the same */
 251  return !strcmp(path1, path2);
 252}
 253#endif
 254
 255int io_file_exists(char*source) {
 256  FILE*src=fopen(source, "rb");
 257  if (src!=NULL) {
 258    fclose(src);
 259    return 1;
 260  }
 261  else {
 262    return (errno != ENOENT);
 263  }
 264}
 265T53 M53={53,0};
 266
 267void se_prinT53(FILE* file,T53**o){
 268if(*o==NULL){
 269   fprintf(file, "void");
 270   return;}
 271fprintf(file,"COUNTER");
 272fprintf(file,"#%p",(void*)*o);
 273fprintf(file,"\n\t[ ");
 274fprintf(file,"value = ");
 275se_prinT2(file,(&((*o)->_value)));
 276fprintf(file,"\n\t]");
 277}/*--*/
 278T49 M49={49,(void*)0,0,(void*)0,0};
 279
 280void se_prinT49(FILE* file,T49**o){
 281if(*o==NULL){
 282   fprintf(file, "void");
 283   return;}
 284fprintf(file,"STD_OUTPUT");
 285fprintf(file,"#%p",(void*)*o);
 286fprintf(file,"\n\t[ ");
 287fprintf(file,"filter = ");
 288se_prinT0(file,(T0**)(&((*o)->_filter)));
 289fprintf(file,"\n\t  ");
 290fprintf(file,"buffer_position = ");
 291se_prinT2(file,(&((*o)->_buffer_position)));
 292fprintf(file,"\n\t  ");
 293fprintf(file,"buffer = ");
 294se_prinT9(file,(&((*o)->_buffer)));
 295fprintf(file,"\n\t  ");
 296fprintf(file,"capacity = ");
 297se_prinT2(file,(&((*o)->_capacity)));
 298fprintf(file,"\n\t]");
 299}/*--*/
 300T25 M25={25,0,(void*)0};
 301
 302void se_prinT25(FILE* file,T25**o){
 303if(*o==NULL){
 304   fprintf(file, "void");
 305   return;}
 306fprintf(file,"TEST_OVERLOAD01");
 307fprintf(file,"#%p",(void*)*o);
 308fprintf(file,"\n\t[ ");
 309fprintf(file,"assertion_level = ");
 310se_prinT2(file,(&((*o)->_assertion_level)));
 311fprintf(file,"\n\t  ");
 312fprintf(file,"external_object = ");
 313se_prinT8(file,(&((*o)->_external_object)));
 314fprintf(file,"\n\t]");
 315}/*--*/
 316
 317void se_prinT9(FILE* file,T9*o){
 318fprintf(file,"NATIVE_ARRAY[CHARACTER]");
 319fprintf(file,"#%p",(void*)*o);
 320}/*--*/
 321T7 M7={7,(void*)0,0,0};
 322/*Aliased storage area or unicode storage.*/
 323char*s26_0="";
 324char*s26_212160365="require_check";
 325char*s26_48390502="all_check";
 326char*s26_1690381566="invariant_check";
 327char*s26_1992063831="ensure_check";
 328char*s26_1325941860="ERROR: \173""EIFFELTEST_TOOLS\175"".assert call ";
 329char*s26_113001857=" in class ";
 330char*s26_2167877="number ";
 331char*s26_718083334="no_check or boost";
 332char*s26_1075456615="Assertion level was ";
 333char*s26_265093627="loop_check";
 334char*s26_1682790378=" failed.\nRerun this test under the -sedb debugger to find out what is going wrong.\n";
 335/*
 336-- ------------------------------------------------------------------------------------------------------------
 337-- Copyright notice below. Please read.
 338--
 339-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P.       - University of Nancy 1 - FRANCE
 340-- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
 341--
 342-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
 343--
 344-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 345-- documentation files (the "Software"), to deal in the Software without restriction, including without
 346-- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 347-- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
 348-- conditions:
 349--
 350-- The above copyright notice and this permission notice shall be included in all copies or substantial
 351-- portions of the Software.
 352--
 353-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 354-- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
 355-- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 356-- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 357-- OR OTHER DEALINGS IN THE SOFTWARE.
 358--
 359-- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
 360-- ------------------------------------------------------------------------------------------------------------
 361*/
 362/*
 363  This file (SmartEiffel/sys/runtime/no_check.c) is automatically included
 364  when `ace.no_check' is true (ie. all modes except -boost).
 365*/
 366
 367int assertion_depth=1;
 368
 369/*
 370   To print object into the trace-stack :
 371*/
 372void se_prinT0(FILE* file, T0** o) {
 373    if (*o == NULL) {
 374	fprintf(file,"Void");
 375    }
 376    else {
 377	fprintf(file,"#%p",(void*)*o);
 378    }
 379}
 380
 381void se_prinT1(FILE* file, EIF_INTEGER_8* o) {
 382    fprintf(file,"%"PRId8,*o);
 383}
 384
 385void se_prinT2(FILE* file, EIF_INTEGER* o) {
 386    fprintf(file,"%"PRId32,*o);
 387}
 388
 389void se_prinT10(FILE* file, EIF_INTEGER_16* o) {
 390    fprintf(file,"%"PRId16,*o);
 391}
 392
 393void se_prinT11(FILE* file,EIF_INTEGER_64* o) {
 394    fprintf(file,"%"PRId64,*o);
 395}
 396
 397static void se_print_character(FILE* file, char c) {
 398    /* Produce a visible output of `c' using an Eiffelish notation.
 399     */
 400    if ((' ' <= c)&&(c <= '~')&&(c != '\'')&&(c != '\"')&&(c != '%')) {
 401	putc(c,file);
 402    }
 403    else {
 404	switch (c) {
 405	    case '\b': fprintf(file,"%%B"); break;
 406	    case '\f': fprintf(file,"%%F"); break;
 407	    case '\n': fprintf(file,"%%N"); break;
 408	    case '\r': fprintf(file,"%%R"); break;
 409	    case '\t': fprintf(file,"%%T"); break;
 410	    case '\0': fprintf(file,"%%U"); break;
 411	    case '\'': fprintf(file,"%%\'"); break;
 412	    case '\"': fprintf(file,"%%\""); break;
 413	    case '%':  fprintf(file,"%%%%"); break;
 414	    default:
 415		fprintf(file,"%%/%d/", (int) ((unsigned char) c));
 416	}
 417    }
 418}
 419
 420void se_prinT3(FILE* file,EIF_CHARACTER* o) {
 421    putc('\'',file);
 422    se_print_character(file, *o);
 423    putc('\'',file);
 424}
 425
 426void se_prinT4(FILE* file, EIF_REAL_32* o) {
 427    fprintf(file, "%.7e", ((real64_t)*o));
 428}
 429
 430void se_prinT5(FILE* file, EIF_REAL_64* o) {
 431    fprintf(file, "%.16e", *o);
 432}
 433
 434void se_prinT12(FILE* file, EIF_REAL_EXTENDED* o) {
 435    fprintf(file, "%.19Le", *o);
 436}
 437
 438void se_prinT6(FILE* file, EIF_BOOLEAN* o) {
 439    if (*o) {
 440	fprintf(file,"True");
 441    }
 442    else {
 443	fprintf(file,"False");
 444    }
 445}
 446
 447void se_prinT7(FILE* file, EIF_STRING* o) {
 448    if (*o == NULL) {
 449	fprintf(file,"Void");
 450    }
 451    else {
 452	T3* storage = (*o)->_storage;
 453	int count = (*o)->_count;
 454	int i = 0;
 455	putc('\"',file);
 456	while (i < count) {
 457	    se_print_character(file, storage[i++]);
 458	}
 459	putc('\"',file);
 460    }
 461}
 462
 463void se_prinT8(FILE* file, EIF_POINTER* o) {
 464    if (*o == NULL) {
 465	fprintf(file,"NULL");
 466    }
 467    else {
 468	fprintf(file,"POINTER#%p",(void*)*o);
 469    }
 470}
 471
 472
 473/*
 474  The upper most context (SmartEiffel Dump stack Top) :
 475*/
 476se_dump_stack* se_dst=NULL;
 477
 478int se_stack_size(se_dump_stack* ds) {
 479  int result = 0;
 480  while (ds != NULL) {
 481    ds = ds->caller;
 482    result ++;
 483  }
 484  return result;
 485}
 486
 487void se_print_run_time_stack(void) {
 488  se_print_run_time_stack_in(SE_ERR);
 489}
 490
 491void se_print_run_time_stack_in(FILE* file) {
 492  /* ANY.print_run_time_stack */
 493  se_dump_stack* origin;
 494  se_dump_stack* ds;
 495  se_dump_stack* ds2;
 496  int frame_count = 1;
 497  int rescue = 0;
 498
 499  handle(SE_HANDLE_ENTER_PRINT_STACK, NULL);
 500  origin = se_dst;
 501  if (origin == NULL) {
 502    fprintf(file,"Empty stack.\n");
 503    return ;
 504  }
 505  else {
 506    while (origin->exception_origin != NULL) {
 507      origin = origin->exception_origin;
 508    }
 509
 510    ds = origin;
 511    while (ds->caller != NULL) {
 512      ds = ds->caller;
 513      frame_count++;
 514    }
 515  }
 516  fprintf(file,"%d frames in current stack.\n",frame_count);
 517  fprintf(file,"=====  Bottom of run-time stack  =====\n");
 518  while (ds != NULL) {
 519    se_print_one_frame_in(file,ds);
 520    /* Next frame : */
 521    if (ds == origin) {
 522      ds = NULL;
 523    }
 524    else if (ds->exception_origin != NULL) {
 525      rescue = 1;
 526      ds = ds->exception_origin;
 527    }
 528    else {
 529      ds2 = se_dst;
 530      while (ds2->caller != ds) {
 531	ds2 = ds2->caller;
 532      }
 533      ds = ds2;
 534    }
 535    if (--frame_count) {
 536      if (!rescue) {
 537        fprintf(file,"======================================\n");
 538      }
 539      else {
 540        fprintf(file,"====   Rescue stack  =================\n");
 541      }
 542    }
 543  }
 544  fprintf(file,"=====   Top of run-time stack    =====\n");
 545
 546  handle(SE_HANDLE_EXIT_PRINT_STACK, NULL);
 547}
 548
 549int se_print_one_frame(se_dump_stack* ds) {
 550  return se_print_one_frame_in(SE_ERR, ds);
 551}
 552
 553int se_print_one_frame_in(FILE* file, se_dump_stack* ds) {
 554  /* Return 1 for an ordinary frame (not a cecil frame or some dynamic
 555     dispatch extra frame). */
 556  se_frame_descriptor* fd = ds->fd;
 557  int i = 0;
 558  int local_count = 0;
 559  char* local_format;
 560  int expanded;
 561  int id;
 562  void** var;
 563
 564  if (fd == NULL) {
 565    fprintf(file,"External CECIL call.\n");
 566    return 0;
 567  }
 568  fprintf(file,"%s\n",fd->name);
 569  if (ds->p == 0) return 0;
 570  local_format = fd->local_format;
 571  if (fd->use_current) {
 572    fprintf(file,"Current = ");
 573    i = 2;
 574    id = 0;
 575    while (local_format[i] != '%') {
 576      id = (id * 10) + (local_format[i] - '0');
 577      i++;
 578    }
 579    i++;
 580    (se_prinT[id])(file, ds->current);
 581    fprintf(file,"\n");
 582  }
 583  while (local_count < fd->local_count) {
 584    while (local_format[i] != '%') {
 585      fprintf(file,"%c",local_format[i]);
 586      i++;
 587    }
 588    i++;
 589    expanded = ((local_format[i++] == 'E')?1:0);
 590    fprintf(file," = ");
 591    id = 0;
 592    while (local_format[i] != '%') {
 593      id = (id * 10) + (local_format[i] - '0');
 594      i++;
 595    }
 596    i++;
 597    if (ds->locals == NULL) {
 598      fprintf(file,"<unavailable>");
 599    }
 600    else {
 601      var = (ds->locals)[local_count];
 602      if (expanded) {
 603        (se_prinT[id])(file, (void**)(var));
 604      }
 605      else if (*var == NULL) {
 606        fprintf(file,"Void");
 607      }
 608      else {
 609        (se_prinT[((T0*)(*var))->id])(file, (void**)(var));
 610      }
 611    }
 612    fprintf(file,"\n");
 613    local_count++;
 614  }
 615  fprintf(file,"line %d ",se_position2line(ds->p));
 616  fflush(file);
 617  fprintf(file,"column %d ",se_position2column(ds->p));
 618  fflush(file);
 619  fprintf(file,"file %s \n",p[se_position2path_id(ds->p)]);
 620  fflush(file);
 621  return 1;
 622}
 623
 624int se_rci(se_dump_stack*caller,void*C) {
 625  /* Where `caller' is supposed to be reference type non Void Current
 626     object. This function return 1 if the class invariant must be
 627     checked for `C' before leaving the routine.
 628  */
 629  if (caller != NULL) {
 630    se_frame_descriptor* fd = caller->fd;
 631    if (fd == NULL) {
 632      /* As for example when coming via CECIL. */
 633      return 0;
 634    }
 635    else {
 636      if (fd->use_current) {
 637	if (fd->local_format[1] == 'R') {
 638	  if ((*((void**)caller->current)) == C) {
 639	    return 0;
 640	  }
 641	}
 642      }
 643    }
 644  }
 645  return 1;
 646}
 647
 648void error0(char* m, char* vv) {
 649  /* When there is nothing more to do than to exit or to go back
 650     into the debugger.
 651  */
 652  static char*f="*** Error at Run Time ***: %s\n";
 653
 654  fprintf(SE_ERR,f,m);
 655  if (vv!=NULL) fprintf(SE_ERR,f,vv);
 656#ifdef SE_EXCEPTIONS
 657  print_exception();
 658#endif
 659#ifdef SE_SEDB
 660  sedb_break(se_dst,0);
 661#else
 662  handle(SE_HANDLE_RUNTIME_ERROR, m);
 663  se_print_run_time_stack();
 664  fprintf(SE_ERR,f,m);
 665  if (vv!=NULL)
 666    fprintf(SE_ERR,f,vv);
 667  exit(EXIT_FAILURE);
 668#endif
 669}
 670
 671void error1(char*m,se_position position) {
 672  /* When there is nothing more to do than to exit or to go back
 673     into the debugger.
 674  */
 675  int l = se_position2line(position);
 676  int c = se_position2column(position);
 677  int f = se_position2path_id(position);
 678  char* f1 = "Line : %d column %d in %s.\n";
 679  char* f2 = "*** Error at Run Time ***: %s\n";
 680
 681  fprintf(SE_ERR,f1,l,c,p[f]);
 682  fprintf(SE_ERR,f2,m);
 683#ifdef SE_EXCEPTIONS
 684  print_exception();
 685#endif
 686#ifdef SE_SEDB
 687  sedb_break(se_dst,position);
 688#else
 689  handle(SE_HANDLE_RUNTIME_ERROR, m);
 690  se_print_run_time_stack();
 691  fprintf(SE_ERR,f1,l,c,p[f]);
 692  fprintf(SE_ERR,f2,m);
 693  exit(EXIT_FAILURE);
 694#endif
 695}
 696
 697void se_print_string(FILE*stream, EIF_STRING s) {
 698  /* To print some Eiffel STRING. */
 699  if (s == NULL) {
 700    fprintf(stream,"Void");
 701  }
 702  else {
 703    int count = s->_count;
 704    EIF_CHARACTER* storage = s->_storage;
 705    int i = 0;
 706    fprintf(stream,"\"");
 707    while (count != 0) {
 708      fprintf(stream,"%c",storage[i]);
 709      i++;
 710      count--;
 711    }
 712    fprintf(stream,"\"");
 713  }
 714}
 715
 716void se_print_bad_target(FILE*stream, int id, T0* o, int l, int c, int f) {
 717  /* Print Bad Target Type Error Message. */
 718  if (l != 0) {
 719    fprintf(stream,"Line : %d column %d in %s.\n",l,c,p[f]);
 720  }
 721  fprintf(stream,"*** Error at Run Time *** :\n");
 722  fprintf(stream,"   Target is not valid (not the good type).\n");
 723  fprintf(stream,"   Expected: ");
 724  se_print_string(stream,t[id]);
 725  fprintf(stream,", Actual: ");
 726  se_print_string(stream,t[o->id]);
 727  fprintf(stream,".\n");
 728}
 729
 730void error2(T0*o, se_position position) {
 731  fprintf(SE_ERR,"Target Type ");
 732  se_print_string(SE_ERR,t[o->id]);
 733  fprintf(SE_ERR," is not valid.\n");
 734  error1("Bad target.",position);
 735}
 736
 737T0* vc(T0* o, se_position position) {
 738  /*
 739    Void check for reference target.
 740  */
 741  if (o != NULL) {
 742    return o;
 743  }
 744  else {
 745#ifdef SE_EXCEPTIONS
 746    internal_exception_handler(Void_call_target);
 747#else
 748    error1("Call with a Void target.",position);
 749#endif
 750    return NULL;
 751  }
 752}
 753
 754T0* se_string_inspect_check(T0* o, se_position position) {
 755  /*
 756    Void check for expression of type STRING in inspect.
 757  */
 758  if (o != NULL) {
 759    return o;
 760  }
 761  else {
 762#ifdef SE_EXCEPTIONS
 763    internal_exception_handler(Incorrect_inspect_value);
 764#else
 765    error1("Expression just after \"inspect\" is Void.",position);
 766#endif
 767    return NULL;
 768  }
 769}
 770
 771T0* ci(int id, T0* o, se_position position) {
 772  /*
 773    Check Id for reference target.
 774  */
 775  if ( vc(o,position) != NULL) {
 776    if ( id == (o->id) ) {
 777      return o;
 778    }
 779    else {
 780#ifdef SE_EXCEPTIONS
 781      internal_exception_handler(System_level_type_error);
 782#else
 783      int l = se_position2line(position);
 784      int c = se_position2column(position);
 785      int f = se_position2path_id(position);
 786
 787      se_print_bad_target(SE_ERR,id,o,l,c,f);
 788      se_print_run_time_stack();
 789      se_print_bad_target(SE_ERR,id,o,l,c,f);
 790#ifdef SE_SEDB
 791      sedb_break(se_dst,0);
 792#else
 793      exit(EXIT_FAILURE);
 794#endif
 795#endif
 796    }
 797  }
 798  return o;
 799}
 800
 801void ac_req(int v,char*vv) {
 802  if (!v) {
 803#ifdef SE_EXCEPTIONS
 804    internal_exception_handler(Precondition);
 805#else
 806    error0("Require Assertion Violated.",vv);
 807#endif
 808  }
 809}
 810
 811void ac_ens(int v,char*vv) {
 812  if (!v) {
 813#ifdef SE_EXCEPTIONS
 814    internal_exception_handler(Postcondition);
 815#else
 816    error0("Ensure Assertion Violated.",vv);
 817#endif
 818  }
 819}
 820
 821void ac_inv(int v,char*vv) {
 822  if (!v) {
 823#ifdef SE_EXCEPTIONS
 824    internal_exception_handler(Class_invariant);
 825#else
 826    error0("Class Invariant Violation.",vv);
 827#endif
 828  }
 829}
 830
 831void ac_liv(int v,char*vv) {
 832  /* Assertion Check : Loop Invariant check. */
 833  if (!v) {
 834#ifdef SE_EXCEPTIONS
 835    internal_exception_handler(Loop_invariant);
 836#else
 837    error0("Loop Invariant Violation.",vv);
 838#endif
 839  }
 840}
 841
 842int ac_lvc(int lc,int lv1,int lv2) {
 843  /* Assertion Check : Loop Variant check. */
 844  if (lc == 0) {
 845    if (lv2 < 0) {
 846#ifdef SE_EXCEPTIONS
 847      internal_exception_handler(Loop_variant);
 848#else
 849      {
 850	char msg [64];
 851	sprintf(msg,"Bad First Variant Value = %d\n",lv2);
 852	error0(msg,NULL);
 853      }
 854#endif
 855    }
 856    else {
 857      return lv2;
 858    }
 859  }
 860  else if ((lv2 < 0) || (lv2 >= lv1)) {
 861#ifdef SE_EXCEPTIONS
 862    internal_exception_handler(Loop_variant);
 863#else
 864    {
 865      char msg [512];
 866      sprintf(msg,
 867	      "Bad loop variant.\nLoop body counter = %d (done)\n"
 868	      "Previous Variant = %d\nNew Variant = %d\n",
 869	      lc,lv1,lv2);
 870      error0(msg,NULL);
 871    }
 872#endif
 873  }
 874  return lv2;
 875}
 876
 877void ac_civ(int v,char*vv) {
 878  if (!v) {
 879#ifdef SE_EXCEPTIONS
 880    internal_exception_handler(Check_instruction);
 881#else
 882    error0("Check Assertion Violated.",vv);
 883#endif
 884  }
 885}
 886
 887T0* se_evobt(T0* o, se_position position) {
 888    /*
 889      Error Void Or Bad Type.
 890    */
 891    if (!o) {
 892#ifdef SE_EXCEPTIONS
 893	internal_exception_handler(Void_call_target);
 894#else
 895	error1("Target is Void.",position);
 896#endif
 897    }
 898    else {
 899#ifdef SE_EXCEPTIONS
 900	internal_exception_handler(System_level_type_error);
 901#else
 902	error2(o,position);
 903#endif
 904    }
 905    return o; /* Dummy return to avoid C warnings. */
 906}
 907
 908void se_signal_handler(int sig) {
 909  printf("Received signal %d.\n",sig);
 910#ifdef SE_SEDB
 911  signal(sig,se_signal_handler);
 912  sedb_signal_handler(sig);
 913#else
 914  se_print_run_time_stack();
 915  exit(EXIT_FAILURE);
 916#endif
 917}
 918
 919void se_gc_check_id(void*o,int id) {
 920  if (id != (((T0*)o)->id)) {
 921#ifdef SE_EXCEPTIONS
 922    internal_exception_handler(Routine_failure);
 923#else
 924    fprintf(SE_ERR,"System-validity error detected during GC cycle.\n");
 925    se_print_bad_target(SE_ERR,id,(T0*)o,0,0,0);
 926    se_print_run_time_stack();
 927    fprintf(SE_ERR,"System-validity error detected during GC cycle.\n");
 928    se_print_bad_target(SE_ERR,id,(T0*)o,0,0,0);
 929    exit(EXIT_FAILURE);
 930#endif
 931  }
 932}
 933
 934se_dump_stack* se_new_dump_stack(se_dump_stack* copy) {
 935  se_dump_stack* result = NULL;
 936  se_frame_descriptor* fd;
 937  int i, j, o, p, n;
 938  int local_count;
 939  char* local_format;
 940  int id;
 941  void** var;
 942  int local_size;
 943  int expanded;
 944
 945  void*** _i;
 946  void** _ref;
 947  char*  _exp;
 948
 949  if (copy != NULL) {
 950    fd = copy->fd;
 951    result = (se_dump_stack*)se_malloc(sizeof(se_dump_stack));
 952    if (result != NULL) {
 953      result->fd               = fd;
 954      result->p                = copy->p;
 955      result->caller           = copy->caller;
 956      result->current          = NULL;
 957      result->locals           = NULL;
 958      result->exception_origin = NULL;
 959
 960      if (fd != NULL) {
 961	local_format = fd->local_format;
 962	i = 0;
 963	if (fd->use_current) {
 964	  result->current = copy->current;
 965	  /* Place i after the Current definition: */
 966	  i = 2;
 967	  id = 0;
 968	  while (local_format[i] != '%') {
 969	    id = (id * 10) + (local_format[i++] - '0');
 970	  }
 971	  i++;
 972	}
 973
 974	/*
 975	 *
 976	 * p: sum of the number of pointers ("indirections") per local
 977	 *    -> 1 for an expanded
 978	 *    -> 2 for a reference
 979	 *
 980	 * o: total malloc'ed size
 981	 *
 982	 * _i: access to the first indirection pointer
 983	 *
 984	 * _ref: access to the second indirection pointer of a reference object
 985	 *       _ref == (T0*)(*_i)
 986	 *
 987	 * _exp: access to a copy of the expanded object
 988	 *       _exp == *((char*)_i)
 989	 *
 990	 *
 991	 *
 992	 * For instance, if "0" is the first local, a reference and "4" is the
 993	 * second local, an expanded type (say, a 6-byte structure noted
 994	 * "XXXXXXXXXXX", with 64-bit padding "/"):
 995	 *
 996	 *
 997	 *
 998	 * result->locals
 999	 *       |                ------------
1000	 *       |               |            |
1001	 *       |    -----------|------------v--------------
1002	 *        -->| | | | |===+===|===+===|XXXXXXXXXXX|/|/|
1003	 *           |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|
1004	 *           |===+===| | | | |===+===| | | | | | | | |
1005	 *            ---|------------^--|-------------------
1006	 *               |            |  |
1007	 *                ------------    --------------------------> object
1008	 *
1009	 *           |-> _i          |-> _ref         _exp <-|
1010	 *
1011	 *
1012	 *
1013	 * Note: Those "|->" denote the start value and way of
1014	 *       progression of the pointers
1015	 *
1016	 *
1017	 * result->locals is defined as a (void***) but its real "type" depends on
1018	 * which element is accessed (as in the live stack; but in the live stack,
1019	 * only the first indirection is in the struct; the remaining data is on
1020	 * the native stack).
1021	 *
1022	 */
1023
1024	if (copy->locals != NULL) {
1025	  j = i;
1026
1027	  local_count = local_size = p = o = 0;
1028
1029	  while (local_count < fd->local_count) {
1030	    while (local_format[i++] != '%');
1031	    expanded = ((local_format[i++] == 'E')?1:0);
1032	    id = 0;
1033	    while (local_format[i] != '%') {
1034	      id = (id * 10) + (local_format[i++] - '0');
1035	    }
1036	    i++;
1037	    if (expanded) {
1038	      p++;
1039	      o = se_strucT[id];
1040	      o = (o + 7) & ~7; /* 64-bit align: should be fine for most systems */
1041	      local_size += o;
1042	    }
1043	    else {
1044	      p+=2;
1045	    }
1046	    local_count++;
1047	  }
1048
1049	  o = p * sizeof(void*) + local_size;
1050	  result->locals = (void***)se_malloc(o);
1051	  _i   = result->locals;
1052	  _exp = (char*)_i + o;
1053	  _ref = (void**)_i + local_count;
1054
1055	  i = j;
1056	  local_count = 0;
1057	  while (local_count < fd->local_count) {
1058	    while (local_format[i++] != '%');
1059	    expanded = ((local_format[i++] == 'E')?1:0);
1060	    id = 0;
1061	    while (local_format[i] != '%') {
1062	      id = (id * 10) + (local_format[i++] - '0');
1063	    }
1064	    i++;
1065	    var = (copy->locals)[local_count];
1066	    if (expanded) {
1067	      o = n = se_strucT[id];
1068	      o = (o + 7) & ~7; /* 64-bit align: should be fine for most systems */
1069	      _exp -= o;
1070	      *(char**)_i = _exp;
1071	      memset(_exp, 0, o);
1072	      memcpy(_exp, var, n);
1073	    }
1074	    else {
1075	      *_i = _ref;
1076	      *_ref = *var;
1077	      _ref++;
1078	    }
1079	    local_count++;
1080	    _i++;
1081	  }
1082	}
1083      }
1084    }
1085  }
1086  return result;
1087}
1088
1089void se_delete_dump_stack(se_dump_stack* ds) {
1090  if (ds != NULL) {
1091    if (ds->locals != NULL) free(ds->locals);
1092    free(ds);
1093  }
1094}
1095
1096
1097void se_print_locals_in(FILE* file, se_dump_stack* ds, int enter) {
1098  se_frame_descriptor* fd = ds->fd;
1099  int i = 0;
1100  int local_count = 0;
1101  char* local_format;
1102  int expanded;
1103  int id;
1104  void** var;
1105  int printed = 0;
1106  int display;
1107
1108  if (ds->p == 0) return;
1109  local_format = fd->local_format;
1110  if (fd->use_current) {
1111    i = 2;
1112    id = 0;
1113    while (local_format[i] != '%') {
1114      i++;
1115    }
1116    i++;
1117  }
1118  while (local_count < fd->local_count) {
1119    display = (strncmp(local_format+i, "Result%", 7)==0) != enter;
1120    if (display) {
1121      if (printed)
1122	fprintf(file,", ");
1123      else
1124	fprintf(file,"(");
1125      printed++;
1126    }
1127    
1128    while (local_format[i] != '%') {
1129      if (display) fprintf(file,"%c",local_format[i]);
1130      i++;
1131    }
1132    i++;
1133    expanded = ((local_format[i++] == 'E')?1:0);
1134    if (display) fprintf(file," = ");
1135    id = 0;
1136    while (local_format[i] != '%') {
1137      id = (id * 10) + (local_format[i] - '0');
1138      i++;
1139    }
1140    i++;
1141    if (display) {
1142      if (ds->locals == NULL) {
1143	fprintf(file,"<unavailable>");
1144      }
1145      else {
1146	var = (ds->locals)[local_count];
1147	if (expanded) {
1148	  (se_prinT[id])(file, (void**)(var));
1149	}
1150	else if (*var == NULL) {
1151	  fprintf(file,"Void");
1152	}
1153	else {
1154	  (se_prinT[((T0*)(*var))->id])(file, (void**)(var));
1155	}
1156      }
1157    }
1158    local_count++;
1159  }
1160  if (printed)
1161    fprintf(file,")\n");
1162  else
1163    fprintf(file,"\n");
1164
1165}
1166
1167#ifdef SE_TRACE
1168static int se_call_depth=0;
1169
1170void se_print_call_trace(se_dump_stack *ds) {
1171  int i;
1172  if (ds) {
1173    int enter = ds->caller == se_dst;
1174    
1175    if (enter)
1176      se_call_depth++;
1177
1178    if (se_call_depth < 0)
1179      se_call_depth=0;
1180
1181    for(i=se_call_depth<<1; i; i--)
1182      putchar(' ');
1183
1184    if (enter) {
1185      printf("enter ");
1186      printf("%s", ds->fd->name);
1187      se_print_locals_in(stdout, ds, 1);
1188    } else {
1189      if (se_dst) {
1190	printf("leave ");
1191	printf("%s", se_dst->fd->name);
1192	se_print_locals_in(stdout, se_dst, 0);
1193	se_call_depth--;
1194      }
1195    }
1196  } else {
1197    for(i=se_call_depth<<1; i; i--)
1198      putchar(' ');
1199    printf("leave ");
1200    printf("%s", se_dst->fd->name);
1201    se_print_locals_in(stdout, se_dst, 0);
1202    se_call_depth--;
1203  }
1204}
1205#endif
1206/*
1207-- ------------------------------------------------------------------------------------------------------------
1208-- Copyright notice below. Please read.
1209--
1210-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P.       - University of Nancy 1 - FRANCE
1211-- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
1212--
1213-- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
1214--
1215-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
1216-- documentation files (the "Software"), to deal in the Software without restriction, including without
1217-- limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
1218-- the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
1219-- conditions:
1220--
1221-- The above copyright notice and this permission notice shall be included in all copies or substantial
1222-- portions of the Software.
1223--
1224-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
1225-- LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
1226-- EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1227-- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
1228-- OR OTHER DEALINGS IN THE SOFTWARE.
1229--
1230-- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
1231-- ------------------------------------------------------------------------------------------------------------
1232*/
1233
1234/*
1235   This file (SmartEiffel/sys/runtime/gc_lib.c) is automatically included
1236   when the Garbage Collector is used (default, unless option -no_gc has been
1237   selected).
1238*/
1239/*
1240   The `mark_stack_and_registers' C function is called by the Garbage
1241   Collector (GC) of SmartEiffel. It has to be customized for some systems,
1242   but also for some C compilers. This file provides some definitions in the
1243   end and has to be completed for systems which need specific work.
1244
1245   On some architectures, addresses increase as the stack grows; or,
1246   conversely, addresses decrease as the stack grows. A C compiler may be
1247   clever enough to hide some root object inside registers. Unfortunately all
1248   registers are not always accessible via the C `setjmp' function!
1249
1250   Thus, in order to be able to use the GC on your architecture/C-compiler,
1251   you have to provide the correct `mark_stack_and_registers' function.
1252
1253   What is the `mark_stack_and_registers' function supposed to do?  The
1254   `mark_stack_and_registers' function is supposed to notify the GC with all
1255   the possible roots one can find in the C stack and registers by calling the
1256   `gc_mark' function. A root is an object which must not be collected.  The
1257   SmartEiffel GC already knows about some root objects like once function
1258   results or manifest strings. The `mark_stack_and_registers' function has to
1259   notify the other possible roots. Obviously, one can find in the C stack any
1260   kind of adresses, but the `gc_mark' function is clever enough to determine
1261   if the passed pointer is an Eiffel object or not.  When the passed pointer
1262   reaches some Eiffel object, this object as well as its descendant(s) are
1263   automatically marked as un-collectable.
1264
1265   In order to provide the most appropriate `mark_stack_and_registers'
1266   function, the very first question is to know about the way the C stack is
1267   managed (addresses of the stack may increase or decrease as the C stack
1268   grows). The DEFAULT BEHAVIOUR FOR UNKNOWN SYSTEMS is to consider ADDRESSES
1269   DECREASE AS THE STACK GROWS, as it's the most common case.  The global C
1270   variable `stack_bottom' is set with some pointer which is supposed to be
1271   the bottom of the stack (this variable is automatically initialized in the
1272   C main function).  Note: using the current stack pointer inside
1273   `mark_stack_and_registers', it is quite obvious to determine if addresses
1274   increase or not as the C stack grows.  Note2: on some systems, the stack is
1275   not in contiguous addresses. In such case, `mark_stack_and_registers' has
1276   to go through all the stack fragments.
1277
1278   Some roots may be stored only in registers and not in the C stack.  In
1279   order to reach the registers as well, the first attempt is to use setjmp,
1280   in the hope that setjmp will save registers in the stack!  Note: this
1281   technique do not work on processors using windows registers (such as sparc
1282   processors).
1283
1284*/
1285
1286int se_gc_strategy = SE_GC_DEFAULT_MEMORY_STRATEGY;
1287
1288int collector_counter = 0;
1289
1290static void gcna_align_mark(rsoc*c,void*o);
1291static rsoc*rsocfl=NULL; /* ReSizable Object Chunk Free List. */
1292
1293void**stack_bottom=NULL;
1294mch**gcmt=NULL; /* Garbage Collector Main Table. */
1295int gcmt_max=2048;
1296int gcmt_used=0;
1297fsoc*fsocfl=NULL; /* Fixed Size Object Chunk Free List. */
1298int gc_is_off=1;
1299unsigned int fsoc_count=0;
1300unsigned int rsoc_count=0;
1301void*gcmt_tail_addr=NULL;
1302
1303static int chunk_rounded(int size) {
1304  int rounded_size = size;
1305  int diff = rounded_size%RSOC_SIZE;
1306
1307  if (diff != 0) rounded_size += (RSOC_SIZE-diff);
1308  return rounded_size;
1309}
1310
1311/* Return the index where chunk `c' is (or is to be) in the `gcmt', 
1312   between `min' and `max' indexes. */
1313static unsigned int binary_search_in_gcmt(register unsigned int min, 
1314					  register unsigned int max, 
1315					  register mch* c){
1316  register unsigned int mid;
1317  while (min<max){
1318    mid=(min+max)>>1;
1319    if (gcmt[mid]<c)
1320      min=mid+1;
1321    else
1322      max=mid;
1323  }
1324  if (gcmt[min]<c)
1325    return min+1;
1326  else
1327    return min;
1328}
1329
1330static void may_free_rsocfl(void) {
1331  /* May free all chunks of `rsocfl' (ReSizable Object Chunk Free List)
1332     in some circumstances.
1333  */
1334  rsoc* next; register rsoc *current;
1335  unsigned int count = rsocfl_count();
1336  register unsigned int where = gcmt_used;
1337  register unsigned int how_many;
1338
1339  if ((count > 50) && (count > (rsoc_count >> 1))) {
1340    current=rsocfl;
1341    rsocfl=NULL;
1342    while (NULL != current) {
1343      next=current->next;
1344      if (current->isize == current->header.size) {
1345	where = binary_search_in_gcmt(0, where-1, (mch*)current);
1346	how_many = gcmt_used - 1 - where;
1347	if (how_many > 0)
1348	  memmove(gcmt+where, gcmt+where+1, how_many*sizeof(mch*));
1349	free(current); gcmt_used--; rsoc_count--;
1350      }
1351      else {
1352	current->next=rsocfl;
1353	rsocfl=current;
1354      }
1355      current = next;
1356    }
1357  }
1358}
1359
1360int gc_memory_used(void) {
1361  int i;
1362  int result = 0;
1363  mch* mch;
1364  for (i = gcmt_used; i --> 0; ) {
1365    mch = gcmt[i];
1366    switch(mch->state_type) {
1367    case RSO_USED_CHUNK:
1368    case FSO_USED_CHUNK:
1369    case FSO_STORE_CHUNK:
1370      result += mch->size;
1371      break;
1372    default:
1373      break;
1374    }
1375  }
1376  return result;
1377}
1378
1379void gc_sweep(void) {
1380  mch** p2 = gcmt;
1381  mch** p1 = gcmt+1;
1382  mch**eogcmt=gcmt+gcmt_used;
1383  if (FREE_CHUNK((*p2)->state_type)) {
1384    if (RSO_FREE_CHUNK == ((*p2)->state_type)) {
1385      ((rsoc*)(*p2))->next=NULL;
1386      rsocfl=((rsoc*)(*p2));
1387    }
1388    else {
1389      rsocfl=NULL;
1390    }
1391  }
1392  else {
1393    ((*gcmt)->swfp)(*p2);
1394    if (RSO_FREE_CHUNK==((*p2)->state_type)) {
1395      ((rsoc*)(*p2))->next=NULL;
1396      rsocfl=((rsoc*)(*p2));
1397    }
1398    else {
1399      rsocfl=NULL;
1400    }
1401  }
1402  while (p1 < eogcmt) {
1403    if (FREE_CHUNK((*p1)->state_type)) {
1404      if (RSO_FREE_CHUNK == ((*p1)->state_type)) {
1405	if (RSO_FREE_CHUNK == ((*p2)->state_type)) {
1406	  if ( (((rsoc*)*p1)->isize==0) && ((char*)(*p2))+(*p2)->size == ((char*)(*p1))) {
1407	    ((*p2)->size)+=((*p1)->size);
1408	    p1++;
1409	  }
1410	  else {
1411	    ((rsoc*)(*p1))->next=rsocfl;
1412	    rsocfl=((rsoc*)(*p1));
1413	    *(p2+1)=*p1; p2++; p1++;
1414	  }
1415	}
1416	else {
1417	  ((rsoc*)(*p1))->next=rsocfl;
1418	  rsocfl=((rsoc*)(*p1));
1419	  *(p2+1)=*p1; p2++; p1++;
1420	}
1421      }
1422      else {
1423	*(p2+1)=*p1; p2++; p1++;
1424      }
1425    }
1426    else {
1427      ((*p1)->swfp)(*p1);
1428      if (RSO_FREE_CHUNK == ((*p1)->state_type)) {
1429	if (RSO_FREE_CHUNK == ((*p2)->state_type)) {
1430	  if ( (((rsoc*)*p1)->isize==0) && ((char*)(*p2))+(*p2)->size == ((char*)(*p1))) {
1431	    ((*p2)->size)+=((*p1)->size);
1432	    p1++;
1433	  }
1434	  else {
1435	    ((rsoc*)(*p1))->next=rsocfl;
1436	    rsocfl=((rsoc*)(*p1));
1437	    *(p2+1)=*p1; p2++; p1++;
1438	  }
1439	}
1440	else {
1441	  ((rsoc*)(*p1))->next=rsocfl;
1442	  rsocfl=((rsoc*)(*p1));
1443	  *(p2+1)=*p1; p2++; p1++;
1444	}
1445      }
1446      else {
1447	*(p2+1)=*p1; p2++; p1++;
1448      }
1449    }
1450  }
1451  gcmt_used=(p2-gcmt)+1;
1452  may_free_rsocfl();
1453}
1454
1455/* return the mch containing p or NULL if p is not 
1456 * a valid address or was externally allocated 
1457 */
1458mch * gc_find_chunk(void * p){
1459  if ((p>((void*)*gcmt))&&(p<=gcmt_tail_addr)) {
1460    int i1=0;
1461    int i2=gcmt_used-1;
1462    int m=i2>>1;
1463    mch*c;
1464    for (;i2>i1;m=((i1+i2)>>1)) {
1465      if (p<=((void*)gcmt[m+1])) {
1466	i2=m;
1467      }
1468      else {
1469	i1=m+1;
1470      }
1471    }
1472    c=gcmt[i2];
1473    if((char*)p<(char*)c+c->size)   /* check for upper bound */
1474      if (!(FREE_CHUNK(c->state_type))){
1475	return c;
1476      }
1477  }
1478  return NULL;
1479}
1480
1481void gc_mark(void*p) {
1482  mch * c;
1483  c = gc_find_chunk(p);
1484  if(NULL != c) {
1485    (c->amfp)(c,p);
1486  }
1487}
1488
1489int gc_stack_size(void) {
1490  void*stack_top[2]={NULL,NULL};
1491  if (stack_top > stack_bottom) {
1492    return ((void**)stack_top)-((void**)stack_bottom);
1493  }
1494  else {
1495    return ((void**)stack_bottom)-((void**)stack_top);
1496  }
1497}
1498
1499/*
1500  To delay Garbage Collection when the stack is too large.
1501  To allow fast increase of ceils.
1502*/
1503#define FSOC_LIMIT (10240/((FSOC_SIZE)>>10))
1504#define RSOC_LIMIT (10240/((RSOC_SIZE)>>10))
1505
1506/*
1507  When stack is too large, collection may be delayed.
1508*/
1509#define GCLARGESTACK 50000
1510
1511int garbage_delayed(void) {
1512  /*
1513    To delay the first GC call.
1514  */
1515  if (gc_stack_size() > GCLARGESTACK) {
1516    if (fsoc_count_ceil <= fsoc_count) {
1517      if (rsoc_count_ceil <= rsoc_count) {
1518	if ((fsoc_count<FSOC_LIMIT)&&(rsoc_count<RSOC_LIMIT)) {
1519	  fsoc_count_ceil++;
1520	  rsoc_count_ceil++;
1521	  return 1;
1522	}
1523	else return 0;
1524      }
1525      else {
1526	if (fsoc_count<FSOC_LIMIT) {
1527	  fsoc_count_ceil++;
1528	  return 1;
1529	}
1530	else return 0;
1531      }
1532    }
1533    else {
1534      if (rsoc_count_ceil <= rsoc_count) {
1535	if (rsoc_count<RSOC_LIMIT) {
1536	  rsoc_count_ceil++;
1537	  return 1;
1538	}
1539	else return 0;
1540      }
1541      else return 0;
1542    }
1543  }
1544  else {
1545    return 0;
1546  }
1547}
1548
1549void gc_update_ceils(void) {
1550  /* This function is automatically called after each collection
1551     cycle.
1552  */
1553  if (se_gc_strategy == SE_GC_LOW_MEMORY_STRATEGY) {
1554    fsoc_count_ceil = fsoc_count;
1555    rsoc_count_ceil = rsoc_count;
1556    /* Todo: we should also consider to free unused chunks here. */
1557    return;
1558  }
1559  if (se_gc_strategy == SE_GC_HIGH_MEMORY_STRATEGY) {
1560    fsoc_count_ceil = (256 + fsoc_count) << 2;
1561    rsoc_count_ceil = (256 + rsoc_count) << 2;
1562    return;
1563  }
1564  /* The SE_GC_DEFAULT_MEMORY_STRATEGY. */
1565  /* Compute fsoc_count_ceil: */
1566
1567  /* The lines commented out with --perf-- were killing performance under certain circumstances, *
1568   * especially with gcc -O3 <FM-15/04/2005>                                                     */
1569
1570  /* --perf-- if (fsocfl == NULL) { */
1571  if (fsoc_count >= fsoc_count_ceil) {
1572    if (fsoc_count_ceil < FSOC_LIMIT) {
1573      fsoc_count_ceil <<= 1;
1574    }
1575    else {
1576      unsigned int c = fsoc_count + (fsoc_count/3);
1577      if (fsoc_count_ceil < c)
1578	fsoc_count_ceil = c;
1579    }
1580  }
1581  /* --perf-- }
1582     else {
1583     if (fsoc_count_ceil < fsoc_count) {
1584     fsoc_count_ceil = fsoc_count;
1585     }
1586     }
1587  */
1588  /* Compute rsoc_count_ceil: */
1589  /* --perf-- if (rsocfl == NULL) {*/
1590  if (rsoc_count >= rsoc_count_ceil) {
1591    if (rsoc_count_ceil < RSOC_LIMIT) {
1592      rsoc_count_ceil <<= 1;
1593    }
1594    else {
1595      unsigned int c = rsoc_count + (rsoc_count / 3);
1596      if (rsoc_count_ceil < c) {
1597	rsoc_count_ceil = c;
1598      }
1599    }
1600  }
1601  /* --perf -- }
1602     else {
1603     if (rsoc_count_ceil < rsoc_count) {
1604     rsoc_count_ceil = rsoc_count;
1605     }
1606     }
1607  */
1608}
1609
1610static void gc_add_into_gcmt(mch*c) {
1611  /* Update the `gcmt' (Garbage Collector Main Table) by adding the
1612     new `mch' (Memory Chunk Header).`gcmt_used' is updated.
1613  */
1614  unsigned int where=0;
1615  unsigned how_many;
1616  if (gcmt_used>0){
1617    where=binary_search_in_gcmt(0, gcmt_used-1, c);
1618    if (gcmt_used == gcmt_max) {
1619      gcmt_max <<= 1;
1620      gcmt = ((mch**)(se_realloc(gcmt,(gcmt_max+1)*sizeof(void*))));
1621    }
1622    how_many = gcmt_used - where;
1623    if (how_many > 0)    
1624      memmove(gcmt+where+1, gcmt+where, how_many*sizeof(mch*));
1625  }
1626  gcmt[where]=c;
1627  gcmt_used++;
1628}
1629
1630static char*rso_from_store(na_env*nae,unsigned int size) {
1631  rsoh*r=(nae->store);
1632  nae->store_left-=size;
1633  if ((nae->store_left) > sizeof(rsoh)) {
1634    r->header.size=size;
1635    nae->store=((rsoh*)(((char*)(nae->store))+size));
1636  }
1637  else {
1638    r->header.size=size+nae->store_left;
1639    nae->store_left=0;
1640  }
1641  (r->header.magic_flag)=RSOH_UNMARKED;
1642  ((void)memset((r+1),0,r->header.size-sizeof(rsoh)));
1643  return (char*)(r+1);
1644}
1645
1646static void rsoc_sweep(rsoc*c) {
1647  na_env*nae=c->nae;
1648  rsoh*gp=(rsoh*)&(c->first_header);
1649  rsoh*pp;
1650  rsoh*eoc=((rsoh*)(((char*)c)+c->header.size));
1651  c->free_list_of_large=NULL;
1652  if (c->header.size > RSOC_SIZE) {
1653    if (gp->header.magic_flag == RSOH_MARKED) {
1654      gp->header.magic_flag=RSOH_UNMARKED;
1655      /* No need to register chunks with no free_list_of_large
1656      c->next=nae->chunk_list;
1657      nae->chunk_list=c;
1658      */
1659    }
1660    else {
1661      c->header.state_type=RSO_FREE_CHUNK;
1662    }
1663    return;
1664  }
1665  while (gp<eoc) {
1666    while (gp->header.magic_flag == RSOH_MARKED) {
1667      gp->header.magic_flag=RSOH_UNMARKED;
1668      gp=((rsoh*)(((char*)gp)+gp->header.size));
1669      if(gp>=eoc) {
1670	/* No need to register chunks with no free_list_of_large
1671	c->next=nae->chunk_list;
1672	nae->chunk_list=c;
1673	*/
1674	return;
1675      }
1676    }
1677    gp->header.magic_flag=RSOH_FREE;
1678    pp=(rsoh*)(((char*)gp)+gp->header.size);
1679    while ((pp<eoc)&&(pp->header.magic_flag != RSOH_MARKED)) {
1680      gp->header.size+=pp->header.size;
1681      pp=((rsoh*)(((char*)pp)+pp->header.size));
1682    }
1683    if (gp->header.size >= RSOC_MIN_STORE) {
1684      if (nae->store_left==0) {
1685	nae->store_left=gp->header.size;
1686	nae->store=gp;
1687	nae->store_chunk=c;
1688      }
1689      else if (nae->store->header.size < gp->header.size) {
1690	((fll_rsoh*)nae->store)->nextflol=nae->store_chunk->free_list_of_large;
1691	nae->store_chunk->free_list_of_large=((fll_rsoh*)nae->store);
1692	nae->store_left=gp->header.size;
1693	nae->store=gp;
1694	nae->store_chunk=c;
1695      }
1696      else {
1697	((fll_rsoh*)gp)->nextflol=c->free_list_of_large;
1698	c->free_list_of_large=((fll_rsoh*)gp);
1699      }
1700    }
1701    gp=pp;
1702  }
1703  if (((rsoh*)(&c->first_header))->header.size >=
1704      (c->header.size-sizeof(rsoc)+sizeof(rsoh))){
1705    c->header.state_type=RSO_FREE_CHUNK;
1706    nae->store_chunk=NULL;
1707    nae->store_left=0;
1708  }
1709  else{
1710    c->next=nae->chunk_list;
1711    nae->chunk_list=c;
1712  }
1713}
1714
1715/* *** To be removed */
1716#ifdef __TINYC__
1717static rsoc MRSOC = {
1718#else
1719static const rsoc MRSOC = {
1720#endif
1721    {
1722	RSOC_SIZE,
1723	RSO_USED_CHUNK,
1724	((void(*)(mch*,void*))gcna_align_mark),
1725	((void(*)(mch*))rsoc_sweep)
1726    },
1727    0,
1728    NULL,
1729    NULL,
1730    NULL,
1731    {
1732      {
1733	0,
1734	RSOH_MARKED
1735      }
1736    }
1737};
1738
1739static void rsoc_malloc(na_env*nae) {
1740  rsoc* r = ((rsoc*)(se_malloc(RSOC_SIZE)));
1741  rsoc_count++;
1742  *r=MRSOC;
1743  r->nae=nae;
1744  r->isize=RSOC_SIZE;
1745  nae->store=(&(r->first_header));
1746  nae->store_left=RSOC_SIZE-sizeof(rsoc)+sizeof(rsoh);
1747  nae->store_chunk=r;
1748  r->next=nae->chunk_list;
1749  nae->chunk_list=r;
1750  gc_add_into_gcmt((mch*)r);
1751}
1752
1753static rsoc* rsocfl_best_fit(unsigned int size) {
1754  register unsigned int best_size = 0;
1755  unsigned int acceptable_loss;
1756  register rsoc *pc, *best_pc, *best_c, *c;
1757  if (NULL==rsocfl)
1758    return NULL;
1759  pc=NULL;
1760  best_pc=NULL;
1761  best_c=NULL;
1762  c=rsocfl;
1763  if (SE_GC_DEFAULT_MEMORY_STRATEGY == se_gc_strategy)
1764    acceptable_loss = (size >> 4);
1765  else if (SE_GC_LOW_MEMORY_STRATEGY == se_gc_strategy)
1766    acceptable_loss = 0;
1767  else /* SE_GC_HIGH_MEMORY_STRATEGY == se_gc_strategy */
1768    acceptable_loss = (size >> 2);
1769
1770  while ((NULL!=c)&&(NULL==best_c)){
1771    if (c->header.size>=size){
1772      best_c=c;
1773      best_pc=pc;
1774      best_size=c->header.size;
1775    }
1776    pc=c;
1777    c=c->next;
1778  }
1779  if (NULL==c){
1780    if (NULL != best_pc)
1781      best_pc->next=best_c->next;
1782    else if (best_c==rsocfl)
1783      rsocfl=best_c->next;
1784    return best_c;
1785  }
1786  if ((best_size - size) > acceptable_loss){
1787    do {
1788      if ((c->header.size >= size) && (c->header.size < best_size)) {
1789	best_c = c;
1790	best_pc = pc;
1791	best_size = c->header.size;
1792	if ((best_size - size) <= acceptable_loss) break;
1793      }
1794      pc=c;
1795      c=c->next;
1796    }
1797    while(NULL!=c);
1798  }
1799  if (NULL==best_pc) {
1800    rsocfl = best_c->next;
1801  }
1802  else {
1803    best_pc->next=best_c->next;
1804  }
1805  return best_c;
1806}
1807
1808static int get_store_in(rsoc*c,unsigned int size) {
1809  na_env*nae=c->nae;
1810  fll_rsoh*pf=NULL;
1811  fll_rsoh*f=c->free_list_of_large;
1812  while (f != NULL) {
1813    if (f->rsoh_field.size >= size) {
1814      nae->store_left=f->rsoh_field.size;
1815      nae->store=(rsoh*)f;
1816      nae->store_chunk=c;
1817      if (pf == NULL) {
1818	c->free_list_of_large=f->nextflol;
1819      }
1820      else {
1821	pf->nextflol=f->nextflol;
1822      }
1823      return 1;
1824    }
1825    pf = f;
1826    f = f->nextflol;
1827  }
1828  return 0;
1829}
1830
1831char*new_na_from_chunk_list(na_env*nae,unsigned int size) {
1832  rsoc*c=nae->chunk_list;
1833  unsigned int csize;
1834  while (c != NULL) {
1835    if (get_store_in(c,size)) {
1836      return rso_from_store(nae,size);
1837    }
1838    c = c->next;
1839  }
1840  csize=size+(sizeof(rsoc)-sizeof(rsoh));
1841  c=rsocfl_best_fit(csize);
1842  if (c != NULL){
1843    if (c->header.size > RSOC_SIZE) {
1844      if (c->header.size-csize > RSOC_MIN_STORE*4) {
1845	int csize_left=c->header.size-csize;
1846	if ((csize_left%sizeof(double))!=0) {
1847	  csize_left-=(csize_left%sizeof(double));
1848	  csize=c->header.size-csize_left;
1849	}
1850	c->header.size=csize_left;
1851	c->next=rsocfl;
1852	rsocfl=c;
1853	c=(rsoc*)(((char*)c)+csize_left);
1854	c->isize=0; /* c split from a larger chunk */
1855	gc_add_into_gcmt((mch*)c);      
1856	c->header.amfp=(void(*)(mch*,void*))gcna_align_mark;
1857	c->header.swfp=(void(*)(mch*))rsoc_sweep;
1858      }
1859      /* since objects bigger than RSOC_SIZE must be the only object in their chunk, we do not want to have
1860	 some store left after them. Therefore, we do not set csize to c->header.size in an else block
1861	 here. */
1862      c->header.size=csize;
1863    }
1864    else {
1865      csize=c->header.size;
1866    }
1867    c->header.state_type=RSO_USED_CHUNK;
1868    c->free_list_of_large=NULL;
1869    c->nae=nae;
1870    nae->store=(&(c->first_header));
1871    nae->store_left=csize-sizeof(rsoc)+sizeof(rsoh);
1872    nae->store_chunk=c;
1873    /* No need to register chunks with no free_list_of_large
1874    c->next=nae->chunk_list;
1875    nae->chunk_list=c;
1876    */
1877    return rso_from_store(nae,size);
1878  }
1879  return NULL;
1880}
1881
1882/* size in bytes, including header size */
1883char*new_na(na_env*nae,unsigned i

Large files files are truncated, but you can click here to view the full file