#include "xmlgiim.h"
#include <stdio.h>
#include <stdlib.h>

int yyerror (char * string)
{
	printf("%s\n",string);
	return 0;
}


struct td *td_now;
struct td *td_first;
struct td *td_temp;

struct column *column_now;
struct column *column_first;
struct column *column_temp;

struct table *table_now;

struct property *property_now;
struct property *property_first;
struct property *property_temp;

struct class *class_now;
struct class *class_first;
struct class *class_temp;

struct class_stack *class_stack_now;
struct class_stack *class_stack_temp;

int level;

char *supplier_bsu;
int element_number_now;



void property_out(struct class *local_class_now){
if (local_class_now->property_first != NULL) {
property_now = local_class_now->property_first;
while (property_now->next != NULL)
  {
   printf("#%d=PROPERTY_BSU('%s', '001', #%d);\n", element_number_now,
                                              property_now->property_bsu,
                                              local_class_now->element_number);
   property_now->element_number = element_number_now++;
   printf("#%d=ITEM_NAMES(LABEL('%s'), $, '%s', $, $);\n",element_number_now++,
                                              property_now->property_name,
                                              property_now->property_name);
   if(!strcmp(property_now->property_type,"STRING"))
      {
       printf("#%d=STRING_TYPE('A..25');\n",element_number_now++);
       printf("#%d=STRING_VARIABLE();\n",element_number_now++);
      } else if(!strcmp(property_now->property_type,"REAL"))
      {
       printf("#%d=REAL_TYPE('NR..3.3');\n",element_number_now++);
       printf("#%d=REAL_NUMERIC_VARIABLE();\n",element_number_now++);
      } else if(!strcmp(property_now->property_type,"INTEGER"))
      {
       printf("#%d=INT_TYPE('NR..3.3');\n",element_number_now++);
       printf("#%d=INT_NUMERIC_VARIABLE();\n",element_number_now++);
      } else {
       printf("#%d=UNKNOWN_TYPE();\n",element_number_now++);
       exit(0);
      }
   printf("#%d=SELF_PROPERTY_VALUE_SEMANTICS(#%d, $);\n",element_number_now++,
                                                         element_number_now-4);
   printf("#%d=ENVIRONMENT(#%d,#%d);\n",element_number_now++,
         element_number_now-2, element_number_now-1);
   printf("#%d=NON_DEPENDENT_P_DET(#%d, #1, '001', #%d, TEXT('%s'), $, $, $, $, (), $, $, #%d, $);\n",element_number_now++, element_number_now-6, 
  element_number_now-5, property_now->property_name, element_number_now-4);   
  printf("#%d=OPT_OR_MAND_PROPERTY_BSU(#%d, .F., .T.);\n",element_number_now++,  element_number_now-7);
   property_now = property_now->next;
  }
}
//printf("--------------++--------------------------------------------------\n");
return;
}

void table_out(struct class *local_class_now){
int column_count, i;
column_count = 0;

if (local_class_now->table != NULL) {
 table_now = local_class_now->table;

 column_now = table_now->column_first;
 property_now= local_class_now->property_first;
 column_count++;
 printf("#%d=TABLE_BSU('%s', '001', #%d);\n",element_number_now,
        table_now->table_bsu, local_class_now->element_number);
 table_now->element_number=element_number_now++;
// while ((column_now->next != NULL)&&(property_now->property_type != NULL))
//  printf("column(%d): %p %p\n",column_count, column_now, column_now->next);
//  printf("%s is %s\n",property_now->property_name, property_now->property_type);
 while (column_now->next != NULL)
  {
  // printf("column(%d):\n",column_count);
  // printf("%s is %s\n",property_now->property_name, property_now->property_type);
  // printf("ok\n");
   if (column_now->td_first == NULL) printf("empty column\n");
   if (property_now->property_name == NULL) {printf("column/property name missing\n"); exit(0);}
   column_count++;
   td_now = column_now->td_first;
   if(!strcmp(property_now->property_type,"STRING"))
      {
       printf("#%d=STRING_COLUMN((",element_number_now++);
       while (td_now->next->next != NULL)
         {printf("'%s', ",td_now->value);
         td_now = td_now->next;
         }
          printf("'%s'), 'A..15');\n",td_now->value);

      } else if(!strcmp(property_now->property_type,"REAL"))
      {
       printf("#%d=REAL_COLUMN((",element_number_now++);
       while (td_now->next->next != NULL)
         {printf("%s, ",td_now->value);
         td_now = td_now->next;
         }
          printf("%s), 'NR..3.3');\n",td_now->value);
      } else if(!strcmp(property_now->property_type,"INTEGER"))
      {
       printf("#%d=INTEGER_COLUMN((",element_number_now++);
       while (td_now->next->next != NULL)
         {printf("%d, ",td_now->value);
         td_now = td_now->next;
         }
          printf("%d), 'NR..3');\n",td_now->value);
      } else {
       printf("#%d=UNKNOWN_TYPE();\n",element_number_now++);
       exit(0);
      }
      column_now = column_now->next;
      if (property_now->next != NULL) {property_now = property_now->next;}
      else {printf("more table columns than properties\n"); exit(0);}
  }
  printf("#%d=ITEM_CLASS_EXTENSION(#%d, *, *, *, (), (), (), (), (), (), (), (), '001', '001', (), (",element_number_now++, local_class_now->element_number);
  for (i=0; i<column_count-2;i++)
    {printf("#%d, ",local_class_now->property_first->element_number+8*i+7);}
     printf("#%d",local_class_now->property_first->element_number+8*i+7);
  printf("), (), (), .F., $, $, $, $, (), $, (), ());\n");
  printf("#%d=TABLE_CONTENT(#%d, *, (",element_number_now++, table_now->element_number);
  for (i=1; i<column_count-1;i++)
    {printf("#%d, ",table_now->element_number+i);}
     printf("#%d",table_now->element_number+i);
  printf("), '001', '1999-09-09');\n");
}
//printf("--------------------------------------++--------------------------\n");
return;
}


void breadth_first_bsu_out() {
class_stack_now = (struct class_stack*)malloc(sizeof(struct class_stack));
class_stack_now->class = NULL;
class_stack_now->next = NULL;
class_stack_temp = (struct class_stack*)malloc(sizeof(struct class_stack));
class_stack_temp->next = class_stack_now;
class_stack_now = class_stack_temp;

class_stack_now->class = class_first->first_child;
class_now = class_stack_now->class;
 while (class_stack_now->class != NULL)
  {class_now = class_stack_now->class;
   class_stack_temp = class_stack_now;
   class_stack_now = class_stack_now->next;
   free(class_stack_temp);
  while(class_now->next != NULL)  
     {
      if(class_now->first_child != NULL)
	{class_stack_temp = (struct class_stack*)malloc(sizeof(struct class_stack));
         class_stack_temp->next = class_stack_now;
         class_stack_temp->class = class_now->first_child;
         class_stack_now = class_stack_temp;
	}
      /*****************************************************/
      if(class_now != NULL){
        printf("#%d=CLASS_BSU('%s', '001', #0);\n",element_number_now,
                                                   class_now->class_bsu);
        class_now->element_number = element_number_now++;
        printf("#%d=ITEM_NAMES('%s', (), '%s', $, $);\n",element_number_now++,
                                                        class_now->class_name,
                                                        class_now->class_name);
        property_out(class_now);
        if(class_now->property_first != NULL)
        printf("%s first_property\n",class_now->property_first->property_name);
        table_out(class_now);
      }
      /***********************************************************/
      class_now = class_now->next;
     }
     /* process the last one outside the while loop */
      if(class_now->first_child != NULL)
	{class_stack_temp = (struct class_stack*)malloc(sizeof(struct class_stack));
         class_stack_temp->next = class_stack_now;
         class_stack_temp->class = class_now->first_child;
         class_stack_now = class_stack_temp;
	}
      /*****************************************************/
      if(class_now != NULL){
        printf("#%d=CLASS_BSU('%s', '001', #0);\n",element_number_now,
                                                   class_now->class_bsu);
        class_now->element_number = element_number_now++;
        printf("#%d=ITEM_NAMES('%s', (), '%s', $, $);\n",element_number_now++,
                                                        class_now->class_name,
                                                        class_now->class_name);
        property_out(class_now);
        table_out(class_now);

      }
      /***********************************************************/


  }
}
void breadth_first_class_out() {
class_stack_now = (struct class_stack*)malloc(sizeof(struct class_stack));
class_stack_now->class = NULL;
class_stack_now->next = NULL;
class_stack_temp = (struct class_stack*)malloc(sizeof(struct class_stack));
class_stack_temp->next = class_stack_now;
class_stack_now = class_stack_temp;

class_stack_now->class = class_first->first_child;
class_now = class_stack_now->class;
 while (class_stack_now->class != NULL)
  {class_now = class_stack_now->class;
   class_stack_temp = class_stack_now;
   class_stack_now = class_stack_now->next;
   free(class_stack_temp);
  while(class_now->next != NULL)  
     {
      if(class_now->first_child != NULL)
	{class_stack_temp = (struct class_stack*)malloc(sizeof(struct class_stack));
         class_stack_temp->next = class_stack_now;
         class_stack_temp->class = class_now->first_child;
         class_stack_now = class_stack_temp;
	}
      /*****************************************************/
      if((class_now->parent != NULL)&&(class_now->parent->element_number > 0))
	{printf("#%d=COMPONENT_CLASS(#%d, #1, '001', #%d, TEXT('%s'), $, $, $, #%d, (", element_number_now++, class_now->element_number,
            class_now->element_number+1, class_now->class_name, 
                                class_now->parent->element_number);
	} else {
	printf("#%d=COMPONENT_CLASS(#%d, #1, '001', #%d, TEXT('%s'), $, $, $, $, (", element_number_now++, class_now->element_number,
                           class_now->element_number+1, 
                                class_now->class_name);
	}
        if (class_now->property_first != NULL)
	  {
           property_now=class_now->property_first;
           while(property_now->next->next != NULL)
	     {
              printf("#%d, ",property_now->element_number);
              property_now = property_now->next;
	     }
              printf("#%d",property_now->element_number);
	  }
        printf("), (), $, (), (), $);\n");
      /***********************************************************/
      class_now = class_now->next;
     }
     /* process the last one outside the while loop */
      if(class_now->first_child != NULL)
	{class_stack_temp = (struct class_stack*)malloc(sizeof(struct class_stack));
         class_stack_temp->next = class_stack_now;
         class_stack_temp->class = class_now->first_child;
         class_stack_now = class_stack_temp;
	}
      /*****************************************************/
      if((class_now->parent != NULL)&&(class_now->parent->element_number > 0))
	{printf("#%d=COMPONENT_CLASS(#%d, #1, '001', #%d, TEXT('%s'), $, $, $, #%d, (", element_number_now++, class_now->element_number,
                   class_now->element_number+1, class_now->class_name, 
                                class_now->parent->element_number);
	} else {
	printf("#%d=COMPONENT_CLASS(#%d, #1, '001', #%d, TEXT('%s'), $, $, $, $, (", element_number_now++, class_now->element_number,
                            class_now->element_number+1, 
                                class_now->class_name);
	}
        if (class_now->property_first != NULL)
	  {
           property_now=class_now->property_first;
           while(property_now->next->next != NULL)
	     {
              printf("#%d, ",property_now->element_number);
              property_now = property_now->next;
	     }
              printf("#%d",property_now->element_number);
	  }
        printf("), (), $, (), (), $);\n");
      /***********************************************************/


  }
}


int main()
{

td_first = (struct td*)malloc(sizeof(struct td));
td_now = td_first;
td_first->next = NULL;

column_first = (struct column*)malloc(sizeof(struct column));
column_now = column_first;
column_first->next = NULL;

table_now = (struct table*)malloc(sizeof(struct table));
table_now->column_first = NULL;

property_first = (struct property*)malloc(sizeof(struct property));
property_now = property_first;
property_first->next = NULL;

class_first = (struct class*)malloc(sizeof(struct class));
class_now = class_first;
class_first->next = NULL;
class_first->first_child = NULL;
class_first->parent = NULL;
class_first->level = 0;

level = 0;
element_number_now = 0;

 yyparse();

 /*
printf("level: %d, class_now->level: %d\n",level,class_now->level);

dump_class(class_now);

dump_class(class_now->next);
class_now = class_now->first_child;

dump_class(class_now);

class_now = class_now->next;
dump_class(class_now);

class_now = class_now->parent->next;
dump_class(class_now);
*/

/*
printf("--------------------------------------\n");
printf("|   Output from XML->GIIM            |\n");
printf("--------------------------------------\n");
printf("    Supplier Library(%s)\n\n",supplier_bsu);
*/

// breadth_first_dump_of_classes();

printf("ISO-10303-21;\n");
printf("HEADER;\n");
printf("FILE_DESCRIPTION((''),'2');\n");
printf("FILE_NAME('','',\n");
printf("         (''),\n");
printf("         (''),\n");
printf("          'RABECS XML HACK VERSION 0.0.1',\n");
printf("          'version 0.0.1',\n");
printf("          ':-)');\n");
printf("FILE_SCHEMA(('ISO13584_G_M_IIM_SCHEMA'));\n");
printf("ENDSEC;\n\n");

printf("DATA;\n");
printf("#%d=SUPPLIER_BSU('%s', *);\n",element_number_now++,supplier_bsu);
printf("#%d=DATES('1999-11-01', '1999-11-01', '1999-11-01:07:00');\n",element_number_now++);

 breadth_first_bsu_out();  
 breadth_first_class_out();

printf("ENDSEC;\n");
printf("END-ISO-10303-21;\n");
 
}







