Example #1
0
void RexxBehaviour::addMethod(
    RexxString *methodName,            /* name of the defined method        */
    RexxMethod *method)                /* method to add to the behaviour    */
/******************************************************************************/
/* Function:  Add a method to an object's behaviour                           */
/******************************************************************************/
{
    /* no method dictionary yet?         */
    if (this->methodDictionary == OREF_NULL)
    {
        /* allocate a table                  */
        OrefSet(this, this->methodDictionary, new_table());
    }
    /* now repeat for the instance       */
    if (this->instanceMethodDictionary == OREF_NULL)
    {
        /* methods to track additions        */
        OrefSet(this, this->instanceMethodDictionary, new_table());
    }
    /* already added one by this name?   */
    if (this->instanceMethodDictionary->stringGet(methodName) != OREF_NULL)
    {
        /* remove from the method dictionary */
        this->methodDictionary->remove(methodName);
    }

    /* now just add this directly        */
    this->methodDictionary->stringAdd(method, methodName);
    /* and also add to the instance one  */
    this->instanceMethodDictionary->stringPut(method, methodName);
}
Example #2
0
World *new_world(void)
{
    World *w;

    w = wtmalloc(sizeof(World));
    w->vertices = new_table(sizeof(Vertex));
    w->walls = new_table(sizeof(Wall));
    w->regions = new_table(sizeof(Region));
    w->textures = new_table(sizeof(Texture *));

    return w;
}
//select only certain attributes
Table Database::set_project(Table t1, vector<string> attrs){
	Table new_table(t1.get_name());
	vector<int> rows;
	vector<Attribute> new_attrs;
	for (int i = 0; i < attrs.size(); ++i){
		for (int j = 0; j < t1.get_attributes().size(); ++j){
			if (t1.get_attributes()[j].get_name() == attrs[i] ){
				new_attrs.push_back(t1.get_attributes()[j]);
				rows.push_back(j);
			}
		}
	}
	vector<Record> new_rec;
	for (int i = 0; i < t1.get_records().size(); ++i){
		Record temp;
		for (int j = 0; j < rows.size(); ++j){
			temp.add_entry(t1.get_record(i).get_entry(rows[j]));
		}
		new_rec.push_back(temp);
	}
	new_table.set_attributes(new_attrs);
	new_table.set_records(new_rec);
	return new_table;

}
Example #4
0
/*******************************MAIN***************************/
int main(){
  struct stack *initial_path_list=NULL;
  clock_t start=clock();
  
  // initialization
  input();        // input a problem
  init_pro_num();   // create number_position[] array
  blank_table=new_table();   // allocate memory for a blank table
  create_initial_path_list(&initial_path_list);   // create the initial path list
  n_ans=0;  // initially, number of answer is zero
  
  // Search for all solutions, starting with initial_path_list
  search_all_solution(initial_path_list);
  
  // check number of answers
  if(!n_ans)
    printf("There is no solution\n");

  else if(n_ans==1)
    printf("There is 1 solution.\n");
  else
    printf("There are %d solution(s)\n",n_ans);
  printf("Execution time:%e.\n",(double)(clock()-start)/CLOCKS_PER_SEC);
  return 0;
}
Example #5
0
DR_EXPORT
void dr_init(client_id_t id)
{
    table = new_table();
    dr_register_bb_event(bb_event);
    dr_register_exit_event(dr_exit);
}
Example #6
0
// Push data into stack
void push(struct stack **top, int *table,int step){
  struct stack *sp=NULL;
  sp=(struct stack *)malloc(sizeof(struct stack));   // allocate memory for a new stack
  sp->table=new_table();    // allocate memory for a new table
  copy_table(sp->table, table);
  sp->step=step;        
  sp->next=*top;
  *top=sp;
}
Example #7
0
symbol_table init_table(symbol_init symbols[]) {
	symbol_table table = new_table();
	int idx;

	for (idx = 0; symbols[idx].name; idx++) {
		set_symbol(table, symbols[idx].name, symbols[idx].value);
	}

	return table;
}
void resize(Hashtable* table, size_t size) {
  Hashtable new_table(size);
  for (auto entry: *table) {
    if (nullptr != entry) {
      auto index = hash_function(entry->key)
                   % new_table.size();
      new_table[index] = entry;
    }
  }
  table->swap(new_table);
}
Example #9
0
int resolve_all_label_refs(instruction *instr) {
	int failure = 0;

	unresolved_labels = new_table();

	while (instr) {
		failure |= resolve_label_refs(instr->args);
		instr = instr->next;
	}

	return failure;
}
Example #10
0
// Pop data from stack
struct data *pop(struct stack **top){
  struct data *data;
  struct stack *sp;
  sp=*top;
  data=(struct data*)malloc(sizeof(struct data));
  data->table=new_table();
  copy_table(data->table,sp->table);
  data->step=sp->step;
  *top=sp->next;
  free(sp->table);
  free(sp);
  return data;
}
Example #11
0
/* Init mem for entry, stores name, inits table field of entry struct. 
 * Returns entry pointer.
 */
entryptr new_scope(char *n) {

  entryptr e = new_entry(n);
  
  e->name = strdup(n);
  e->entrytable = new_table(n);

  /* not needed, as this is a scope table entry */
  free(e->entrytype);

  return e;
 
};
Example #12
0
RexxObject *RexxBehaviour::define(
    RexxString *methodName,            /* name of the defined method        */
    RexxMethod *method)                /* method to add to the behaviour    */
/******************************************************************************/
/* Function:  Add or remove a method from an object's behaviour               */
/******************************************************************************/
{
    RexxMethod  * tableMethod;           /* method from the table             */

                                         /* no method dictionary yet?         */
    if (this->methodDictionary == OREF_NULL)
    {
        /* allocate a table                  */
        OrefSet(this, this->methodDictionary, new_table());
    }


    if (method == OREF_NULL || method == TheNilObject)
    {
        /* replace the method with .nil      */
        this->methodDictionary->stringPut(TheNilObject, methodName);

    }
    else
    {
        /* already have this method?         */
        if ((tableMethod = (RexxMethod *)this->methodDictionary->stringGet(methodName)) == OREF_NULL)
        {
            /* No, just add this directly        */
            this->methodDictionary->stringAdd(method, methodName);
        }
        else
        {
            /* are the scopes the same?          */
            if (tableMethod->getScope() == method->getScope())
            {
                /* same scope, so replace existing   */
                /* method with the new one           */
                this->methodDictionary->stringPut(method, methodName);

            }
            else
            {
                /* new scope, for this, just replace */
                this->methodDictionary->stringAdd(method, methodName);

            }
        }
    }
    return OREF_NULL;                    /* always return nothing             */
}
/**
 *	process(fmt, data)
 *
 *	Purpose: read from datafile, format and output selected records
 *	Input:   fmt 		- input stream from format file
 *		 data		- stream from datafile
 *	Output:  copied fmt to stdout with insertions
 *	Errors:  not reported, functions call fatal() and die
 *	history: 2012-11-28 added free_table (10q BW)
 **/
int process(FILE *fmt, FILE *data)
{
	symtab_t *tab;

	if ( (tab = new_table()) == NULL )
		fatal("Cannot create storage object","");

	while ( get_record(tab,data) != NO )/* while more data	*/
	{
		printf("Inside the process while loop\n");
		mailmerge( tab, fmt );		/* merge with format	*/
		clear_table(tab);		/* discard data		*/
	}

	//free_table(tab);			/* no memory leaks!	*/
}
Example #14
0
Hash_Table *G(New_Hash_Table)(int size)
{ Table *table;
  int    i, smax;

  size  = next_prime((int) (size/CELL_RATIO));
  smax  = size*STRING_RATIO;
  table = new_table(sizeof(int)*size,sizeof(Hash_Entry)*((int) (size*CELL_RATIO)),smax,
                    "New_Hash_Table");
  table->count  = 0;
  table->size   = size;
  table->strmax = smax;
  table->strtop = 0;
  for (i = 0; i < size; i++)
    table->vector[i] = -1;

  return ((Hash_Table *) table);
}
Example #15
0
static inline Table *copy_table(Table *table)
{ Table *copy = new_table(table_vsize(table),table_csize(table),table_ssize(table),"Copy_Hash_Table");
  void *_vector = copy->vector;
  void *_cells = copy->cells;
  void *_strings = copy->strings;
  *copy = *table;
  copy->vector = _vector;
  if (table->vector != NULL)
    memcpy(copy->vector,table->vector,table_vsize(table));
  copy->cells = _cells;
  if (table->cells != NULL)
    memcpy(copy->cells,table->cells,table_csize(table));
  copy->strings = _strings;
  if (table->strings != NULL)
    memcpy(copy->strings,table->strings,table_ssize(table));
  return (copy);
}
Example #16
0
File: monkc.c Project: sunpaq/monkc
MCInline mc_class* findclass(const char* name)
{
	//create a class hashtable
	if (mc_global_classtable == null)
		mc_global_classtable = new_table(MCHashTableLevel1);

	//cache
	//    mc_hashitem* cache = mc_global_classtable->cache;
	//    if (cache && cache->key == name) {
	//        return (mc_class*)(cache->value.mcvoidptr);
	//    }

	mc_hashitem* item = get_item_byhash(mc_global_classtable, hash(name), name);
	if (item == null)
		return null;
	else
		runtime_log("findClass item key:%s, value:%p\n", item->key, item->value.mcvoidptr);
	return (mc_class*)(item->value.mcvoidptr);
}
Example #17
0
// almost identical with extend function, except this is done
// at the beginning.
void create_initial_path_list(struct stack **initial_path_list){
  int *tmp_table=NULL;
  struct around aro;
  int value=number_position[0].value;
  struct position current_position=number_position[0].pos;
  tmp_table=new_table();
 
  for(aro.left=0; aro.left<value; ++aro.left){
    for(aro.right=0; aro.right<value-aro.left; ++aro.right){
      for(aro.up=0; aro.up<value-aro.left-aro.right; ++aro.up){
	aro.down=value-1-aro.left-aro.right-aro.up;
	if(check(blank_table,current_position,aro)){
	  copy_table(tmp_table,blank_table);
	  update_table(tmp_table,current_position,aro);
	  push(initial_path_list,tmp_table,1);
	}
      }
    }
  }
}
Example #18
0
/* Shift the values of the gen whose table number is given in p0 by the number
   of array locations given in p1.  Positive values shift to the right;
   negative values to the left.  If a value is shifted off the end of the
   array in either direction, it reenters the other end of the array.

   Two examples:
      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      source table, size = 10
      [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]      shift = 3
      [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]      shift = -3
*/
double
m_shiftgen(float p[], int n_args, double pp[])
{
   int      slot, size, shift, abs_shift;
   size_t   movesize;
   double   *srctable, *desttable;

   slot = (int) p[0];
   srctable = floc(slot);
   if (srctable == NULL)
      return die("shiftgen", "No function table defined for slot %d.", slot);
   size = fsize(slot);
   shift = (int) p[1];
   abs_shift = abs(shift);
   if (abs_shift == 0 || abs_shift == size) {
      advise("shiftgen", "Your shift of %d has no effect on the table!", shift);
      return (double) size;
   }
   if (abs_shift > size)
      return die("shiftgen", "You can't shift by more than the table size.");

   desttable = new_table(size);
   if (desttable == NULL)
      return die("shiftgen", "No memory for new function table.");
   if (!install_gen(slot, size, desttable))
      return die("shiftgen", "No more function tables available.");

   movesize = (size_t) (size - abs_shift);  /* doubles to shift */
   if (shift > 0) {
      memcpy(desttable, srctable + movesize, (size_t) abs_shift
                                                            * sizeof(double));
      memcpy(desttable + abs_shift, srctable, movesize * sizeof(double));
   }
   else {
      memcpy(desttable, srctable + abs_shift, movesize * sizeof(double));
      memcpy(desttable + movesize, srctable, (size_t) abs_shift
                                                            * sizeof(double));
   }

   return (double) size;
}
Example #19
0
DR_EXPORT
void dr_init(client_id_t id)
{
    /* Look up start_instrument() and stop_instrument() in the app.
     * These functions are markers that tell us when to start and stop
     * instrumenting.
     */
    module_data_t *prog = dr_lookup_module_by_name("client.cbr4.exe");
    ASSERT(prog != NULL);

    start_pc = (app_pc)dr_get_proc_address(prog->handle, "start_instrument");
    stop_pc = (app_pc)dr_get_proc_address(prog->handle, "stop_instrument");

    ASSERT(start_pc != NULL && stop_pc != NULL);
    dr_free_module_data(prog);

    table = new_table();

    dr_register_bb_event(bb_event);
    dr_register_exit_event(dr_exit);
}
Example #20
0
/* Reverse the values of the gen whose table number is given in p0. */
double
m_reversegen(float p[], int n_args, double pp[])
{
   int   i, j, slot, size;
   double *srctable, *desttable;

   slot = (int) p[0];
   srctable = floc(slot);
   if (srctable == NULL)
      return die("reversegen", "No function table defined for slot %d.", slot);
   size = fsize(slot);
   desttable = new_table(size);
   if (desttable == NULL)
      return die("reversegen", "No memory for new function table.");
   if (!install_gen(slot, size, desttable))
      return die("reversegen", "No more function tables available.");

   for (i = 0, j = size - 1; i < size; i++, j--)
      desttable[i] = srctable[j];

   return (double) size;
}
Example #21
0
/* Invert the values of the gen whose table number is given in p0.  The
   y-axis center of symmetry is a point halfway between the min and max
   table values; inversion is performed around this center of symmetry.
*/
double
m_invertgen(float p[], int n_args, double pp[])
{
   int   i, slot, size;
   double min, max, center, *srctable, *desttable;

   slot = (int) p[0];
   srctable = floc(slot);
   if (srctable == NULL)
      return die("invertgen", "No function table defined for slot %d.", slot);
   size = fsize(slot);
   desttable = new_table(size);
   if (desttable == NULL)
      return die("invertgen", "No memory for new function table.");
   if (!install_gen(slot, size, desttable))
      return die("invertgen", "No more function tables available.");

   /* determine central y-axis value */
   min = DBL_MAX;
   max = -DBL_MAX;
   for (i = 0; i < size; i++) {
      if (srctable[i] < min)
         min = srctable[i];
      if (srctable[i] > max)
         max = srctable[i];
   }
   center = min + ((max - min) / 2.0);

//advise("invertgen", "min: %f, max: %f, center: %f", min, max, center);

   /* invert values around center */
   for (i = 0; i < size; i++) {
      double diff = srctable[i] - center;
      desttable[i] = center - diff;
   }

   return (double) size;
}
Example #22
0
/* Quantize the values of the gen whose table number is given in p0 to the
   quantum given in p1.
*/
double
m_quantizegen(float p[], int n_args, double pp[])
{
   int      i, slot, size;
   double   quantum, *srctable, *desttable;

   slot = (int) p[0];
   srctable = floc(slot);
   if (srctable == NULL)
      return die("quantizegen", "No function table defined for slot %d.", slot);
   size = fsize(slot);
   quantum = p[1];
   if (quantum <= 0.0)
      return die("quantizegen", "Quantum must be greater than zero.");
   desttable = new_table(size);
   if (desttable == NULL)
      return die("quantizegen", "No memory for new function table.");
   if (!install_gen(slot, size, desttable))
      return die("quantizegen", "No more function tables available.");

   /* It'd be nice to let the C library do the rounding, but rintf rounds
      to the nearest even integer, and round and roundf don't even work
      on my Slackware 8.1 system.  Screw it, we'll roll our own.  -JGG
   */
   for (i = 0; i < size; i++) {
      double quotient = fabs(srctable[i] / quantum);
      int floor = (int) quotient;
      double remainder = quotient - (double) floor;
      if (remainder >= 0.5)   /* round to nearest */
         floor++;
      if (srctable[i] < 0.0)
         desttable[i] = -floor * quantum;
      else
         desttable[i] = floor * quantum;
   }

   return (double) size;
}
Example #23
0
/* Add a constant, given in p1, to the values of the gen whose table number
   is given in p0.  Note that no rescaling of the resulting table is done,
   so that values outside [-1, 1] are possible.
*/
double
m_offsetgen(float p[], int n_args, double pp[])
{
   int   i, slot, size;
   double *srctable, *desttable, offset;

   slot = (int) p[0];
   srctable = floc(slot);
   if (srctable == NULL)
      return die("offsetgen", "No function table defined for slot %d.", slot);
   size = fsize(slot);
   offset = p[1];
   desttable = new_table(size);
   if (desttable == NULL)
      return die("offsetgen", "No memory for new function table.");
   if (!install_gen(slot, size, desttable))
      return die("offsetgen", "No more function tables available.");

   for (i = 0; i < size; i++)
      desttable[i] = srctable[i] + offset;

   return (double) size;
}
Example #24
0
/*store the problem read from a file into table problem */
void input(){
  int i,j;
  FILE *fp;
  char line[100],filename[100];

  printf("Input the file's name.\n");
  fgets(line,sizeof(line),stdin);
  sscanf(line,"%s",filename);
  fp=fopen(filename,"r");
  if(!fp){
    fprintf(stderr,"FILE not found.\n");
    exit(1);
  }
  fgets(line,sizeof(line),fp);
  
  // If there is no information about the size of the puzzle 
  if(strlen(line)>10){
    N_ROW=N_COL=DEFAULT_SIZE;   // assign default value to N_ROW, N_COL
    fclose(fp);                 // close the file
    fopen(filename,"r");        // open it again.
  }
  // If there is information about the size
  else{
    sscanf(line,"%d %d",&N_ROW,&N_COL);
  }
  problem=new_table();     // alocate memory
  for(i=0; i<N_ROW; ++i){
    for(j=0; j<N_COL; ++j){
      fscanf(fp,"%d ",&problem[i*N_ROW+j]);
    }
    fscanf(fp,"\n");
  }
  fclose(fp);
  printf("The input problem is:\n");
  print_table(problem);
}
Example #25
0
/* Extend path_list with all new possibilities, depth-first*/
struct stack* extend(struct stack **path_list,int *table,int step){
  int *tmp_table=NULL;
  struct around aro;
  int value=number_position[step].value;
  tmp_table=new_table();   // allocate memory for temporary table
  struct position current_position=number_position[step].pos;
  for(aro.left=0; aro.left<value; ++aro.left){
    for(aro.right=0; aro.right<value-aro.left; ++aro.right){
      for(aro.up=0; aro.up<value-aro.left-aro.right; ++aro.up){
	// assure the number of white grid is equal to value
	aro.down=value-1-aro.left-aro.right-aro.up;
	// if black grids can be placed around the grid in question
	// push the updated tatble to the path_list
	if(check(table,current_position,aro)){
	  copy_table(tmp_table,table);
	  update_table(tmp_table,current_position,aro);
	  push(path_list,tmp_table,step+1);
	}
      }
    }
  }
  free(tmp_table);
  return *path_list;
}
Example #26
0
static inline Table *read_table(FILE *input)
{ char name[10];
  fread(name,10,1,input);
  if (strncmp(name,"Hash_Table",10) != 0)
    return (NULL);
  Table *obj = new_table(0,0,0,"Read_Hash_Table");
  fread(obj,sizeof(Table),1,input);
  obj->vector = NULL;
  if (table_vsize(obj) != 0)
    { allocate_table_vector(obj,table_vsize(obj),"Read_Hash_Table");
      fread(obj->vector,table_vsize(obj),1,input);
    }
  obj->cells = NULL;
  if (table_csize(obj) != 0)
    { allocate_table_cells(obj,table_csize(obj),"Read_Hash_Table");
      fread(obj->cells,table_csize(obj),1,input);
    }
  obj->strings = NULL;
  if (table_ssize(obj) != 0)
    { allocate_table_strings(obj,table_ssize(obj),"Read_Hash_Table");
      fread(obj->strings,table_ssize(obj),1,input);
    }
  return (obj);
}
Example #27
0
//==========================================================================================================
// Mimimize the DFA using Myphill-Nerode based algorithm. The algorithm consider all state pairs, marking
// them as non-equivalent if possible. When finished, those not marked are put in the same new state.
// Steps:
// 1. Mark as non-equivalent those pairs with different accepting values
// 2. Iteratively mark pairs that for any input symbol go to a marked pair (or transition defined just for
//    one of them on that symbol).
// 3. Combine unmarked pairs to form new states.
// 4. Write the new transitions, mark accepting new states
//==========================================================================================================
void DFA::minimize() {
    //------------------------------------------------------------------------------------------------------
    // Create the pairs and do initial mark (true means pair is non-equivalent)
    //------------------------------------------------------------------------------------------------------
    vector<bool*> pairs;
    int num_states = get_num_states();
    
    for(int i = 0; i < num_states - 1; ++i) {
        pairs.push_back(new bool[num_states - i - 1]);
        pairs[i] -= (i+1); // This ugly trick enables accessing pairs[i][j], but actually using just half the memory
        
        for(int j = i+1; j < num_states; ++j) {
            pairs[i][j] = (accepting[i] != accepting[j]);
        }
    }
    
    //------------------------------------------------------------------------------------------------------
    // Mark until an iteration where no changes are made
    //------------------------------------------------------------------------------------------------------
    bool changed = true;
    while(changed) {
        changed = false;
        
        for(int i = 0; i < num_states - 1; ++i) {
            for(int j = i+1; j < num_states; ++j) {
                if(pairs[i][j]) continue; // Pair already marked
                
                for(int sym = 0; sym < NUM_SYMBOLS; ++sym) {
                    int x = get_next_state(i, sym), y = get_next_state(j, sym);
                    if(x == y) continue;

                    sort_pair(x,y); // Must have the smaller index first to access pairs table
                    
                    if(x == -1 or pairs[x][y]) {
                        pairs[i][j] = true;
                        changed = true;
                    }
                } // for each symbol
            }
        }
    }
    
    //------------------------------------------------------------------------------------------------------
    // Combine states:
    // 1. A new state is a set of old states which are equivalent
    // 2. If an old state is not equivalent to any other state, a new state is created that contains only it
    // 3. After adding a pair {i,j} (i < j}, there's no need to look at pairs {j,x} (j < x), because pair
    // {i,x} must have already been added.
    //------------------------------------------------------------------------------------------------------
    vector<vector<int>> new_states;
    vector<int> old_to_new(num_states, -1);
    set<int> added_states;
    
    for(int i = 0; i < num_states - 1; ++i) {
        if(added_states.count(i) != 0) continue;
        
        new_states.push_back({i});
        old_to_new[i] = new_states.size() - 1;
        
        for(int j = i+1; j < num_states; ++j) {
            if(not pairs[i][j]) {
                new_states.back().push_back(j);
                old_to_new[j] = new_states.size() - 1;
                added_states.insert(j);
            }
        }
    }
    
    if(added_states.empty()) // No minimization occurred
        return;
    
    // If the last state wasn't combined with any other state, add a new state that contains only it;
    // This is needed because the last state has no entry in the pairs table as a first of any pair
    if(added_states.count(num_states-1) == 0)
        new_states.push_back({num_states-1});
    
    //------------------------------------------------------------------------------------------------------
    // Write new transitions and mark accepting new states. Then replace the old DFA with the new one.
    //------------------------------------------------------------------------------------------------------
    vector<int> new_accepting(new_states.size(), -1);
    vector<vector<int>> new_table(new_states.size(), vector<int>(NUM_SYMBOLS, -1));
    
    for(int i = 0; i < new_states.size(); ++i) {
        for(auto s: new_states[i])
            if(accepting[s] != accepting[new_states[i][0]])
                throw string("DFA states found to be equivalent yet have different accepting values");
        
        new_accepting[i] = accepting[new_states[i][0]]; // If the first is accepting they all are, and vice versa
        
        for(int sym = 0; sym < NUM_SYMBOLS; ++sym) {
            // Since all old states in this new states are equivalent, need to check only one
            int old_next_state = get_next_state(new_states[i][0], sym);
            if(old_next_state != -1)
                new_table[i][sym] = old_to_new[old_next_state];
        }
    }
    
    accepting = new_accepting;
    table = new_table;
    

    //------------------------------------------------------------------------------------------------------
    // Free memory
    //------------------------------------------------------------------------------------------------------
    for(int i = 0; i < num_states - 1; ++i) {
        delete (pairs[i] + i + 1);
    }    
} // minimize()
	void new_table(lua_State* vm, Table& t)
	{
		new_table(vm).swap(t);
	}
Example #29
0
void begin_scope() { // Push to the top of stack
    scope_top = new_scope(new_table(), scope_top, scope_top->level + 1);
}
Example #30
0
struct table *parse_table(unsigned char *html, unsigned char *eof, unsigned char **end, struct rgb *bgcolor, int sh, struct s_e **bad_html, int *bhp)
{
	int qqq;
	struct table *t;
	struct table_cell *cell;
	unsigned char *t_name, *t_attr, *en;
	int t_namelen;
	int x = 0, y = -1;
	int p = 0;
	unsigned char *lbhp = NULL;
	int l_al = AL_LEFT;
	int l_val = VAL_MIDDLE;
	int csp, rsp;
	int group = 0;
	int i, j, k;
	struct rgb l_col;
	int c_al = AL_TR, c_val = VAL_TR, c_width = W_AUTO, c_span = 0;
	memcpy(&l_col, bgcolor, sizeof(struct rgb));
	*end = html;
	if (bad_html) {
		*bad_html = DUMMY;
		*bhp = 0;
	}
	if (!(t = new_table())) return NULL;
	se:
	en = html;
	see:
	html = en;
	if (bad_html && !p && !lbhp) {
		if (!(*bhp & (ALLOC_GR-1))) {
			if ((unsigned)*bhp > MAXINT / sizeof(struct s_e) - ALLOC_GR) overalloc();
			*bad_html = mem_realloc(*bad_html, (*bhp + ALLOC_GR) * sizeof(struct s_e));
		}
		lbhp = (*bad_html)[(*bhp)++].s = html;
	}
	while (html < eof && *html != '<') html++;
	if (html >= eof) {
		if (p) CELL(t, x, y)->end = html;
		if (lbhp) (*bad_html)[*bhp-1].e = html;
		goto scan_done;
	}
	if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) {
		html = skip_comment(html, eof);
		goto se;
	}
	if (parse_element(html, eof, &t_name, &t_namelen, &t_attr, &en)) {
		html++;
		goto se;
	}
	if (t_namelen == 5 && !casecmp(t_name, "TABLE", 5)) {
		en = skip_table(en, eof);
		goto see;
	}
	if (t_namelen == 6 && !casecmp(t_name, "/TABLE", 6)) {
		if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
		if (p) CELL(t, x, y)->end = html;
		if (lbhp) (*bad_html)[*bhp-1].e = html;
		goto scan_done;
	}
	if (t_namelen == 8 && !casecmp(t_name, "COLGROUP", 8)) {
		if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
		if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
		c_al = AL_TR;
		c_val = VAL_TR;
		c_width = W_AUTO;
		get_align(t_attr, &c_al);
		get_valign(t_attr, &c_val);
		get_c_width(t_attr, &c_width, sh);
		if ((c_span = get_num(t_attr, "span")) == -1) c_span = 1;
		goto see;
	}
	if (t_namelen == 9 && !casecmp(t_name, "/COLGROUP", 9)) {
		if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
		if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
		c_span = 0;
		c_al = AL_TR;
		c_val = VAL_TR;
		c_width = W_AUTO;
		goto see;
	}
	if (t_namelen == 3 && !casecmp(t_name, "COL", 3)) {
		int sp, wi, al, val;
		if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
		if ((sp = get_num(t_attr, "span")) == -1) sp = 1;
		wi = c_width;
		al = c_al;
		val = c_val;
		get_align(t_attr, &al);
		get_valign(t_attr, &val);
		get_c_width(t_attr, &wi, sh);
		new_columns(t, sp, wi, al, val, !!c_span);
		c_span = 0;
		goto see;
	}
	if (t_namelen == 3 && (!casecmp(t_name, "/TR", 3) || !casecmp(t_name, "/TD", 3) || !casecmp(t_name, "/TH", 3))) {
		if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
		if (p) CELL(t, x, y)->end = html, p = 0;
		if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
	}
	if (t_namelen == 2 && !casecmp(t_name, "TR", 2)) {
		if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
		if (p) CELL(t, x, y)->end = html, p = 0;
		if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
		if (group) group--;
		l_al = AL_LEFT;
		l_val = VAL_MIDDLE;
		memcpy(&l_col, bgcolor, sizeof(struct rgb));
		get_align(t_attr, &l_al);
		get_valign(t_attr, &l_val);
		get_bgcolor(t_attr, &l_col);
		y++, x = 0;
		goto see;
	}
	if (t_namelen == 5 && ((!casecmp(t_name, "THEAD", 5)) || (!casecmp(t_name, "TBODY", 5)) || (!casecmp(t_name, "TFOOT", 5)))) {
		if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
		if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
		group = 2;
	}
	if (t_namelen != 2 || (casecmp(t_name, "TD", 2) && casecmp(t_name, "TH", 2))) goto see;
	if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1);
	if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL;
	if (p) CELL(t, x, y)->end = html, p = 0;
	if (y == -1) y = 0, x = 0;
	nc:
	cell = new_cell(t, x, y);
	if (cell->used) {
		if (cell->colspan == -1) goto see;
		x++;
		goto nc;
	}
	cell->mx = x;
	cell->my = y;
	cell->used = 1;
	cell->start = en;
	p = 1;
	cell->align = l_al;
	cell->valign = l_val;
	if ((cell->b = upcase(t_name[1]) == 'H')) cell->align = AL_CENTER;
	if (group == 1) cell->group = 1;
	if (x < t->c) {
		if (t->cols[x].align != AL_TR) cell->align = t->cols[x].align;
		if (t->cols[x].valign != VAL_TR) cell->valign = t->cols[x].valign;
	}
	memcpy(&cell->bgcolor, &l_col, sizeof(struct rgb));
	get_align(t_attr, &cell->align);
	get_valign(t_attr, &cell->valign);
	get_bgcolor(t_attr, &cell->bgcolor);
	if ((csp = get_num(t_attr, "colspan")) == -1) csp = 1;
	if (!csp) csp = -1;
	if ((rsp = get_num(t_attr, "rowspan")) == -1) rsp = 1;
	if (!rsp) rsp = -1;
	if (csp >= 0 && rsp >= 0 && csp * rsp > 100000) {
		if (csp > 10) csp = -1;
		if (rsp > 10) rsp = -1;
	}
	cell->colspan = csp;
	cell->rowspan = rsp;
	if (csp == 1) {
		int w = W_AUTO;
		get_c_width(t_attr, &w, sh);
		if (w != W_AUTO) set_td_width(t, x, w, 0);
	}
	qqq = t->x;
	for (i = 1; csp != -1 ? i < csp : x + i < qqq; i++) {
		struct table_cell *sc = new_cell(t, x + i, y);
		if (sc->used) {
			csp = i;
			for (k = 0; k < i; k++) CELL(t, x + k, y)->colspan = csp;
			break;
		}
		sc->used = sc->spanned = 1;
		sc->rowspan = rsp;
		sc->colspan = csp;
		sc->mx = x;
		sc->my = y;
	}
	qqq = t->y;
	for (j = 1; rsp != -1 ? j < rsp : y + j < qqq; j++) {
		for (k = 0; k < i; k++) {
			struct table_cell *sc = new_cell(t, x + k, y + j);
			if (sc->used) {
				int l, m;
				if (sc->mx == x && sc->my == y) continue;
				/*internal("boo");*/
				for (l = 0; l < k; l++) memset(CELL(t, x + l, y + j), 0, sizeof(struct table_cell));
				rsp = j;
				for (l = 0; l < i; l++) for (m = 0; m < j; m++) CELL(t, x + l, y + m)->rowspan = j;
				goto brk;
			}
			sc->used = sc->spanned = 1;
			sc->rowspan = rsp;
			sc->colspan = csp;
			sc->mx = x;
			sc->my = y;
		}
	}
	brk:
	goto see;

	scan_done:
	*end = html;

	for (x = 0; x < t->x; x++) for (y = 0; y < t->y; y++) {
		struct table_cell *c = CELL(t, x, y);
		if (!c->spanned) {
			if (c->colspan == -1) c->colspan = t->x - x;
			if (c->rowspan == -1) c->rowspan = t->y - y;
		}
	}

	if ((unsigned)t->y > MAXINT / sizeof(int)) overalloc();
	t->r_heights = mem_alloc(t->y * sizeof(int));
	memset(t->r_heights, 0, t->y * sizeof(int));

	for (x = 0; x < t->c; x++) if (t->cols[x].width != W_AUTO) set_td_width(t, x, t->cols[x].width, 1);
	set_td_width(t, t->x, W_AUTO, 0);

	return t;
}