/*
-- ANSI C code generated by :
-- SmallEiffel The GNU Eiffel Compiler -- Release (- 0.79Beta#5)--
-- Copyright (C), 1994-98 - LORIA - UHP - CRIN - INRIA - FRANCE --
-- Dominique COLNET and Suzanne COLLIN -    colnet@loria.fr     --
--                 http://www.loria.fr/SmallEiffel              --
*/
#include "example01.h"
T571 M571={571};


void se_prinT571(T571**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"STD_ERROR");
fprintf(SE_ERR,"#%p",*o);
}


void se_prinT1939(T1939*o){
fprintf(SE_ERR,"NATIVE_ARRAY[DIRENT]");
fprintf(SE_ERR,"#%p",*o);
}


void se_prinT2135(T2135*o){
fprintf(SE_ERR,"NATIVE_ARRAY[STRING]");
fprintf(SE_ERR,"#%p",*o);
}
T474 M474={474,0};


void se_prinT474(T474**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"BOOLEAN_REF");
fprintf(SE_ERR,"#%p",*o);
fprintf(SE_ERR,"\n\t[ ");
fprintf(SE_ERR,"item = ");
se_prinT6((void*)(&((*o)->_item)));
fprintf(SE_ERR,"\n\t]");
}
T1405 M1405={1405,NULL,NULL};


void se_prinT1405(T1405**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"BASIC_DIRECTORY");
fprintf(SE_ERR,"#%p",*o);
fprintf(SE_ERR,"\n\t[ ");
fprintf(SE_ERR,"path_memory = ");
se_prinT7((void*)(&((*o)->_path_memory)));
fprintf(SE_ERR,"\n\t  ");
fprintf(SE_ERR,"memory = ");
se_prinT0((void*)(&((*o)->_memory)));
fprintf(SE_ERR,"\n\t]");
}
T701 M701={701};


void se_prinT701(T701**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"EXAMPLE01");
fprintf(SE_ERR,"#%p",*o);
}
T1707 M1707={1707,NULL,0,0};


void se_prinT1707(T1707**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"FIXED_ARRAY[DIRENT]");
fprintf(SE_ERR,"#%p",*o);
fprintf(SE_ERR,"\n\t[ ");
fprintf(SE_ERR,"storage = ");
se_prinT1939((void*)(&((*o)->_storage)));
fprintf(SE_ERR,"\n\t  ");
fprintf(SE_ERR,"capacity = ");
se_prinT2((void*)(&((*o)->_capacity)));
fprintf(SE_ERR,"\n\t  ");
fprintf(SE_ERR,"upper = ");
se_prinT2((void*)(&((*o)->_upper)));
fprintf(SE_ERR,"\n\t]");
}
T1886 M1886={1886,NULL,0,0};


void se_prinT1886(T1886**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"FIXED_ARRAY[STRING]");
fprintf(SE_ERR,"#%p",*o);
fprintf(SE_ERR,"\n\t[ ");
fprintf(SE_ERR,"storage = ");
se_prinT2135((void*)(&((*o)->_storage)));
fprintf(SE_ERR,"\n\t  ");
fprintf(SE_ERR,"capacity = ");
se_prinT2((void*)(&((*o)->_capacity)));
fprintf(SE_ERR,"\n\t  ");
fprintf(SE_ERR,"upper = ");
se_prinT2((void*)(&((*o)->_upper)));
fprintf(SE_ERR,"\n\t]");
}


void se_prinT9(T9*o){
fprintf(SE_ERR,"NATIVE_ARRAY[CHARACTER]");
fprintf(SE_ERR,"#%p",*o);
}
T265 M265=0;


void se_prinT265(T265*o){
fprintf(SE_ERR,"DIRENT");
}
T7 M7={7,NULL,0,0};
T2074 M2074={2074};


void se_prinT2074(T2074**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"STD_INPUT_OUTPUT");
fprintf(SE_ERR,"#%p",*o);
}
T528 M528={528,0};


void se_prinT528(T528**o){
if(*o==NULL){
fprintf(SE_ERR,"Void");
return;
}
fprintf(SE_ERR,"INTEGER_REF");
fprintf(SE_ERR,"#%p",*o);
fprintf(SE_ERR,"\n\t[ ");
fprintf(SE_ERR,"item = ");
se_prinT2((void*)(&((*o)->_item)));
fprintf(SE_ERR,"\n\t]");
}


T7*se_ms(int c,char*e){
T7*s=malloc(sizeof(gc7));
s->id=7;
s->_count=c;
s->_capacity=c+1;
s->_storage=new9(c+1);
memcpy(s->_storage,e,c);
return s;}


T7*e2s(char*e){
return se_ms(strlen(e),e);}


char*s2e(T7*s){
char*e=malloc(1+s->_count);
memcpy(e,s->_storage,s->_count);
e[s->_count]='\0';
return e;}
/*
-- This file is  free  software, which  comes  along  with  SmallEiffel. This
-- software  is  distributed  in the hope that it will be useful, but WITHOUT 
-- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
-- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
-- this header is kept unaltered, and a notification of the changes is added.
-- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
-- another product.
--          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
--            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
--                       http://www.loria.fr/SmallEiffel
--
*/

/*
  This file (no_check.c) is automatically included when `run_control.no_check'
  is true (ie. all modes ecxept -boost).
*/

/*
  The upper most context (SmallEiffel Dump stack Top) :
*/
se_dump_stack* se_dst=NULL;

void se_print_run_time_stack(void) {
  /* GENERAL.print_run_time_stack */
  se_dump_stack* ds = NULL;
  se_dump_stack* ds2;
  se_frame_descriptor* fd;
  int frame_count = 1;

  ds = se_dst;
  if (ds == NULL) {
    fprintf(SE_ERR,"%Empty stack.\n");
    return ;
  }
  else {
    while (ds->caller != NULL) {
      ds = ds->caller;
      frame_count++;
    }
  }
  fprintf(SE_ERR,"%d frames in current stack.\n",frame_count);
  fprintf(SE_ERR,"=====  Bottom of run-time stack  =====\n");
  while (ds != NULL) {
    if (ds->fd != NULL) {
      se_print_one_frame(ds);
    }
    else {
      fprintf(SE_ERR,"External CECIL call.\n");
    }
    /* Next frame : */
    if (ds == se_dst) {
      ds = NULL;
    }
    else {
      ds2 = se_dst;
      while (ds2->caller != ds) {
	ds2 = ds2->caller;
      }
      ds = ds2;
    }
    if (--frame_count) {
      fprintf(SE_ERR,"======================================\n");
    }
  }
  fprintf(SE_ERR,"=====   Top of run-time stack    =====\n");
}

void se_print_one_frame(se_dump_stack* ds) {
  se_frame_descriptor* fd = ds->fd;
  int i = 0;
  int local_count = 0;
  char* local_format = fd->local_format;
  int expanded;
  int id;
  void** var;
  fprintf(SE_ERR,"%s\n",fd->name);
  if (fd->use_current) {
    fprintf(SE_ERR,"Current = ");
    i = 2;
    id = 0;
    while (local_format[i] != '%') {
      id = (id * 10) + (local_format[i] - '0');
      i++;
    }
    i++;
    (se_prinT[id])(ds->current);
    fprintf(SE_ERR,"\n");
  }
  while (local_count < fd->local_count) {
    while (local_format[i] != '%') {
      fprintf(SE_ERR,"%c",local_format[i]);
      i++;
    }
    i++;
    expanded = ((local_format[i++] == 'E')?1:0);
    fprintf(SE_ERR," = ");
    id = 0;
    while (local_format[i] != '%') {
      id = (id * 10) + (local_format[i] - '0');
      i++;
    }
    i++;
    var = (ds->locals)[local_count];
    if (expanded) {
      (se_prinT[id])((void**)(var));
    }
    else if (*var == NULL) {
      fprintf(SE_ERR,"Void");
    }
    else {
      (se_prinT[((T0*)(*var))->id])((void**)(var));
    }
    fprintf(SE_ERR,"\n");
    local_count++;
  }
  fprintf(SE_ERR,"line %d ",ds->l);
  fflush(SE_ERR);
  fprintf(SE_ERR,"column %d ",ds->c);
  fflush(SE_ERR);
  fprintf(SE_ERR,"file %s \n",p[ds->f]);
  fflush(SE_ERR);
}

void se_core_dump(char*msg) {
  if (msg != NULL) {
    fprintf(SE_ERR,"%s\n",msg);
  }
#ifdef SE_EXCEPTIONS
  print_exception();
#endif
  se_print_run_time_stack();
  exit(1);
}

int se_require_uppermost_flag;

/*
  Require Last Result :
*/
int se_require_last_result;

int se_rci(void*C) {
  /* Return 1 if class invariant must be checked for Current 
     before leaving the routine.
  */
  se_dump_stack*ds = se_dst;
  ds = ds->caller;
  if (ds != NULL) {
    se_frame_descriptor* fd = ds->fd;
    if (fd == NULL) {
      /* As for example when coming via CECIL. */
      return 0;
    }
    else {
      if (fd->use_current) {
	if (fd->local_format[1] == 'R') {
	  if (((void*)*(ds->current)) == C) {
	    return 0;
	  }
	}
      }
    }
  }
  return 1;
}

void error0(char*m) {
  static char*f1="*** Error at Run Time *** : %s\n";
  fprintf(SE_ERR,f1,m);
#ifdef SE_EXCEPTIONS
  print_exception();
#endif
  se_print_run_time_stack();
  fprintf(SE_ERR,f1,m);
  exit(1);
}

void error1(char*m,int l,int c,int f) {
  char*f1="Line : %d column %d in %s.\n";
  char*f2="*** Error at Run Time *** : %s\n";
  fprintf(SE_ERR,f1,l,c,p[f]);
  fprintf(SE_ERR,f2,m);
#ifdef SE_EXCEPTIONS
  print_exception();
#endif
  se_print_run_time_stack();
  fprintf(SE_ERR,f1,l,c,p[f]);
  fprintf(SE_ERR,f2,m);
  exit(1);
}

void error2(T0*o,int l,int c,int f) {
  char*f1="Target Type %s not legal.\n";
  fprintf(SE_ERR,f1,s2e(t[o->id]));
  error1("Bad target.",l,c,f);
}

T0* vc(void*o,int l,int c,int f) {
  /* VoidCheck for reference target.*/
  if (o != NULL) {
    return o;
  }
  else {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Void_call_target);
#else
    error1("Call with a Void target.",l,c,f);
#endif
    return NULL;
  }
}

T0* ci(int id,void*o,int l,int c,int f) {
  /* Check Id for reference target. */
  vc(o,l,c,f);
  if (id == (((T0*)o)->id)) {
    return o;
  }
  else {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Routine_failure);
#else
    fprintf(SE_ERR,"Line : %d column %d in %s.\n",l,c,p[f]);
    fprintf(SE_ERR,"*** Error at Run Time *** : ");
    fprintf(SE_ERR,"Target is not valid (not the good type).\n");
    fprintf(SE_ERR,"Expected: %s, Actual: %s.\n",
	    s2e(t[id]),s2e(t[((T0*)o)->id]));
    se_print_run_time_stack();
    exit(1);
#endif
  }
}

void ac_req(int v) {
  if (!v && se_require_uppermost_flag) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Precondition);
#else
    error0("Require Assertion Violated.");
#endif
  }
  se_require_last_result=se_require_last_result&&v;
}

void ac_ens(int v) {
  if (!v) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Postcondition);
#else
    error0("Ensure Assertion Violated.");
#endif
  }
}

void ac_inv(int v) {
  if (!v) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Class_invariant);
#else
    error0("Class Invariant Violation.");
#endif
  }
}

void ac_liv(int v) {
  /* Assertion Check : Loop Invariant check. */
  if (!v) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Loop_invariant);
#else
    error0("Loop Invariant Violation.");
#endif
  }
}

int ac_lvc(int lc,int lv1,int lv2) {
  /* Assertion Check : Loop Variant check. */
  if (lc == 0) {
    if (lv2 < 0) {
#ifdef SE_EXCEPTIONS
      internal_exception_handler(Loop_variant);
#else
      se_print_run_time_stack();
      fprintf(SE_ERR,"Bad First Variant Value = %d\n",lv2);
#endif
    }
    else {
      return lv2;
    }
  }
  else if ((lv2 < 0) || (lv2 >= lv1)) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Loop_variant);
#else
    se_print_run_time_stack();
    fprintf(SE_ERR,"Loop Body Count = %d (done)\n",lc);
    fprintf(SE_ERR,"New Variant = %d\n",lv2);
    fprintf(SE_ERR,"Previous Variant = %d\n",lv1);
#endif
  }
  else {
    return lv2;
  }
}

void ac_civ(int v) {
  if (!v) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Check_instruction);
#else
    error0("Check Assertion Violated.");
#endif
  }
}

void se_evobt(void*o,int l,int c,int f) {
  /* Error Void Or Bad Type. */
  if (!o) {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Void_call_target);
#else
    error1("Target is Void.",l,c,f);
#endif
  }
  else {
#ifdef SE_EXCEPTIONS
    internal_exception_handler(Void_call_target);
#else
    error2(o,l,c,f);
#endif
  }
}

void sigrsp(int sig) {
  printf("Received signal %d (man signal).\n",sig);
  se_print_run_time_stack();
  exit(1);
}
/*
-- This file is  free  software, which  comes  along  with  SmallEiffel. This
-- software  is  distributed  in the hope that it will be useful, but WITHOUT 
-- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
-- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
-- this header is kept unaltered, and a notification of the changes is added.
-- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
-- another product.
--          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
--            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
--                       http://www.loria.fr/SmallEiffel
--
*/

/*
  This file (trace.c) is automatically included when `run_control.no_check' is
  true (ie. all modes ecxept -boost).
  This file comes after no_check.[hc] to implements the -trace flag as well as
  some other printing stuff.
*/

/* 
   To print object into the trace-stack :
*/
void se_prinT0(T0** o) {
  if (*o == NULL) {
    fprintf(SE_ERR,"Void");
  }
  else {
    fprintf(SE_ERR,"#%p",*o);
  }
}
void se_prinT2(T2* o) {
  fprintf(SE_ERR,"%d",*o);
}
void se_prinT3(T3* o) {
  fprintf(SE_ERR,"'%c'",*o);
}
void se_prinT4(T4* o) {
  fprintf(SE_ERR,"%f",((double)*o));
}
void se_prinT5(T5* o) {
  fprintf(SE_ERR,"%f",*o);
}
void se_prinT6(T6* o) {
  if (*o) {
    fprintf(SE_ERR,"true");
  }
  else {
    fprintf(SE_ERR,"false");
  }
}
void se_prinT7(T7** o) {
  if (*o == NULL) {
    fprintf(SE_ERR,"Void");
  }
  else {
    char*storage = (*o)->_storage;
    int count = (*o)->_count;
    int i = 0;
    fprintf(SE_ERR,"\"");
    while (i < count) {
      fprintf(SE_ERR,"%c",storage[i]);
      i++;
    }
    fprintf(SE_ERR,"\"");
  }
}
void se_prinT8(T8* o) {
  if (*o == NULL) {
    fprintf(SE_ERR,"NULL");
  }
  else {
    fprintf(SE_ERR,"POINTER#%p",*o);
  }
}

#ifndef SE_TRACE

void se_trace(se_dump_stack*ds,int l,int c,int f) {
  ds->l=l;
  ds->c=c;
  ds->f=f;
}

# endif

#ifdef SE_TRACE
/*
  Basic SmallEiffel step-by-step execution.
*/

static FILE* se_trace_file = NULL;
static int se_write_trace_flag = 0;
static int se_trace_ready_flag = 0;
static int se_step_by_step_flag = 1;

int get_answer(void) {
  int result = 0;
  char c = getc(stdin);
  if (c != '\n') {
    result = c;
  }
  while (c != '\n') {
    c = getc(stdin);
  }
  return result;
}

static void sedb_help_command(void) {
  printf("SmallEiffel debugger.\n");
  printf("List of classes of commands:\n");
  printf("   (h) Help.\n");
  printf("   (s) Stack view.\n");
  printf("   (q) Quit.\n");
  printf("   Return to see the current Eiffel source line.");
  printf("   \n");
  printf("Please, feel free to debug or to complete this simple\n");
  printf("step-by-step debugger (see source file in\n");
  printf("\"SmallEiffel/sys/runtime/trace.c\".\n");
}

static void sedb_show_source_line(int l,int c,int f) {
  static int f_memo = 0;
  if (p[f] == NULL) {
    printf("line %d column %d of ???\t\t",l,c);
  }
  else {
    FILE *file = fopen(p[f],"r");
    if (file != NULL) {
      int line = 1;
      int column = 1;
      char cc;
      while (line < l) {
	cc = fgetc(file);
	if (cc == '\n') {
	  line++;
	}
      }
      cc = fgetc(file);
      while (cc != '\n') {
	if (cc == '\t') {
	  printf("        ");
	  column+=7;
	}
	else {
	  fputc(cc,stdout);
	}
	cc = fgetc(file);
	column++;
      }
      while (column < 72) {
	fputc(' ',stdout);
	column++;
      }
      printf("l%dc%d ",l,c);
      if (f_memo != f) {
	printf(" %s ",p[f]);
      }
      f_memo = f;
      fclose(file);
    }
    else {
      printf("line %d column %d of %s\t\t",l,c,p[f]);
    }
  }
}

void se_trace(se_dump_stack*ds,int l,int c,int f) {
  static char cmd_memo = 1;
  static char cmd;
  ds->l=l;
  ds->c=c;
  ds->f=f;
  if (se_trace_ready_flag) {
    if (se_write_trace_flag) {
      fprintf(se_trace_file,"line %d column %d in %s\n",l,c,p[f]);
      fflush(se_trace_file);
    }
  next_command:
    if (se_step_by_step_flag) {
      if (cmd_memo != 0) {
	printf("(sedb) ");
      }
      fflush(stdout);
      cmd = get_answer();
      cmd_memo = cmd;
      if ((cmd == 'h') || (cmd == 'H') || (cmd == '?')) {
	sedb_help_command();
	goto next_command;
      }
      else if ((cmd == 's') || (cmd == 'S')) {
	se_print_run_time_stack();
	goto next_command;
      }
      else if ((cmd == 'q') || (cmd == 'Q')) {
	exit(1);
      }
      else if (cmd == 0) {
	sedb_show_source_line(l,c,f);
      }
      else {
	printf("Unknown command.\nTtype H for help\n");
	goto next_command;
      }
    }
  }
  else {
    se_trace_ready_flag = 1;
    printf("Write the execution trace in \"trace.se\" file (y/n) ? [n]");
    fflush(stdout);
    if (get_answer() == 'y') {
      se_write_trace_flag = 1;
      se_trace_file = fopen("trace.se","w");
    }
    printf("Step-by-step execution (y/n) ? [y]");
    fflush(stdout);
    if (get_answer() == 'n') {
      se_step_by_step_flag = 0;
    }
    else {
	sedb_help_command();
    }
  }
}
# endif

