%{
#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>


  extern char* yytext;

  /*extern char * yylval;*/
  /* 
     Parser for linker map files.
  */

  void print_node(xmlNodePtr node) {
    xmlDocPtr doc = NULL;
    doc = xmlNewDoc("1.0");
    xmlDocSetRootElement(doc, node);
    xmlSaveFile("ldmap.out.xml", doc);
  }

%}

%union {
  char* strn;
  xmlNodePtr node;
};

%token SYMBOL LPAREN RPAREN HEX;
%token OBJ_FILE ARCH_FILE DYN_FILE;
%token HEADER ARCH_HEADER

%type<strn> thingie file objfile archfile dynfile sym hexval head

%type<node> arch_section arch_list arch_entry


%%

thingie: thingie file { printf("File: %s\n", $2); $$ = $2;}
    | thingie sym { printf("Sym: %s\n", $2); $$ = $2;}
    | thingie  hexval { printf("Hex: %s\n", $2); $$ = $2;}
    | thingie head { printf("Header: %s\n", $2); $$ = $2;}
    | thingie arch_section  { printf("Arch section:\n"); print_node($2); $$ = ""}
    | thingie '('  { $$= "";}
    | thingie ')'  { $$= "";}
    | thingie '*' { $$ = ""; }
    | thingie ','  { $$ = ""; }
    | thingie '='  { $$ = ""; }
    | thingie '+'  { $$ = ""; }
    | thingie '&'  { $$ = ""; }
    | thingie '!'  { $$ = ""; }
    | thingie '?'  { $$ = ""; }
    | thingie ':'  { $$ = ""; }
    | { $$ = "end" }
    ;
    
    
    arch_section: ARCH_HEADER arch_list 
 { 
        $$ = xmlNewNode(NULL, "arch-section"); 
   xmlAddChild($$, $2);
 }

arch_list: 
arch_list arch_entry arch_entry '(' sym ')' 
{ 
  xmlNodePtr tmp;
  tmp = xmlNewNode(NULL, "added");
  
    /*$$ = $6; xmlAddChild($6, $1); */
  xmlAddChild(tmp, $2);
  xmlAddChild(tmp, $3);
  xmlNewProp(tmp, "symbol", $5);
  xmlAddChild($1, tmp); 
  $$ = $1;
}

| arch_list arch_entry file  '(' sym ')' 
{ 
  xmlNodePtr tmp;
  tmp = xmlNewNode(NULL, "added");
  xmlAddChild(tmp, $2);
  xmlNewChild(tmp, NULL, "file", $3);
  xmlNewProp(tmp, "symbol", $5);
  xmlAddChild($1, tmp);
  $$ = $1; 
}

| {$$ = xmlNewNode(NULL, "arch-list")}

arch_entry: archfile '(' file ')' 
{ 
  $$= xmlNewNode(NULL, "archive");
  xmlNodeAddContent($$, $1);
  xmlNewProp($$, "member", $3);
}

file: objfile { $$ = $1; }
      | archfile { $$ = $1; }
      | dynfile { $$ = $1; };

dynfile: DYN_FILE { $$ = strdup(yytext); };

objfile: OBJ_FILE { $$ = strdup(yytext); };

archfile: ARCH_FILE { $$ = strdup(yytext); };

sym: SYMBOL { $$ = strdup(yytext); };

hexval: HEX { $$ = strdup(yytext); };

head: HEADER { $$ = strdup(yytext); };


%%

main() {
  /*  do {*/
    yyparse();
    /* } while (!feof(yyin) );*/
}

yyerror( char * s) {

  fprintf(stderr, "yyerror is: %s ; %s\n", s, yytext);
}