https://hal.archives-ouvertes.fr/hal-03445821
Raw File
arch_xml.c
/*
   Copyright Universite de Versailles Saint-Quentin en Yvelines 2009
   AUTHORS: Sebastien Briais, Sid Touati

   This file is part of GDD.
   
   GDD is free software: you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as
   published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.
   
   GDD 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.  See the GNU
   Lesser General Public License for more details.
   
   You should have received a copy of the GNU Lesser General Public
   License along with GDD.  If not, see
   <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/parser.h>

#include "util.h"
#include "opcode.h"
#include "arch.h"
#include "arch_xml.h"

/** Include xml utilities functions */
#include "xmlutil.h"

typedef struct {
  GDD_Arch *arch; // arch being built
  GDD_Opcode *op; // current opcode
  int error;
} BuildCtxt;

static void beginElement(void *user_data, const xmlChar *name, const xmlChar **attrs) {
  BuildCtxt *ctxt = (BuildCtxt *)user_data;
  if(ctxt->error) {
    return;
  }

  int i;

  if(xmlStrEqual(name, (xmlChar *)"arch")) {
    i = findAttr("version", attrs);
    int version = atoi_xml(attrs[i]);
    if(version != 1) {
      fprintf(stderr,"wrong arch version: %d\n",version);
      ctxt->error = TRUE;
      return;
    }
  } else if(xmlStrEqual(name, (xmlChar *)"regtype")) {
    i = findAttr("type", attrs);
    char *type = (char *)attrs[i];
    i = findAttr("number", attrs);
    int nb = atoi_xml(attrs[i]);
    safe_call(GDD_arch_add_regtype(ctxt->arch, type, nb));
  } else if(xmlStrEqual(name, (xmlChar *)"instruction")) {
    i = findAttr("opcode", attrs);
    char *mnemo = (char *)attrs[i];
    if(strcmp(mnemo, "dummy") == 0) {
      fprintf(stderr, "error: dummy is a reserved mnemonic\n");
      exit(1);
    }
    i = findAttr("latency", attrs);
    int latency = atoi_xml(attrs[i]);
    i = findAttr("delta_r", attrs);
    int delta_r = atoi_xml(attrs[i]);
    GDD_Opcode *op = GDD_opcode_create(mnemo, latency, delta_r);
    ctxt->op = op;
    safe_call(GDD_arch_add_opcode(ctxt->arch, op));
  } else if(xmlStrEqual(name, (xmlChar *)"write")) {
    i = findAttr("regtype", attrs);
    char *type = (char *)attrs[i];
    i = findAttr("delta_w", attrs);
    int delta_w = atoi_xml(attrs[i]);
    GDD_Opcode *op = ctxt->op;
    if(op == NULL) {
      ctxt->error = TRUE;
      return;
    }
    safe_call(GDD_opcode_extend_delta_w(op, type, delta_w));
  } else {
    fprintf(stderr,"ignoring %s tag\n", name);
  } 
}

/** Parse an architecture from an XML file stream.

    @param[in] stream = file stream

    @return the parsed architecture */
GDD_Arch *GDD_arch_of_xml_stream(FILE *stream) {
  BuildCtxt ctxt;
  ctxt.arch = GDD_arch_create();
  ctxt.op = NULL;
  ctxt.error = FALSE;

  xmlParserCtxtPtr xmlctxt;
  xmlSAXHandler sax = { 0 };
 
  // initialise SAX callbacks
  sax.startElement = beginElement;
 
  // create SAX context
  if ((xmlctxt = xmlCreateIOParserCtxt(&sax, &ctxt, sax_read, sax_close, stream, XML_CHAR_ENCODING_NONE)) == NULL) {
    fprintf(stderr,"error while creating SAX context\n");
    GDD_arch_delete(ctxt.arch);
    return NULL;
  }

/*   safe_call(GDD_arch_add_opcode(ctxt.arch, GDD_opcode_create("dummy",0,0))); */

  // parse stream
  if(xmlParseDocument(xmlctxt) != 0) {
    ctxt.error = TRUE;
  }
  //
  xmlFreeParserCtxt(xmlctxt);
  //  fprint_arch(stderr, ctxt.arch);

  if(ctxt.error) {
    fprintf(stderr,"error while parsing arch file\n");
    GDD_arch_delete(ctxt.arch);
    return NULL;
  }

  return ctxt.arch;
}

/** Parse an architecture from a file.

    @param[in] filename = filename

    @return the parsed architecture */
GDD_Arch *GDD_arch_of_xml_file(const char *filename) {
  FILE *f = fopen(filename, "r");
  if(f == NULL) {
    fprintf(stderr,"error while opening %s\n", filename);
    return NULL;
  }
  GDD_Arch *arch = GDD_arch_of_xml_stream(f);
  fclose(f);
  return arch;
}
back to top