diff options
Diffstat (limited to 'pcilib/xml.c')
-rw-r--r-- | pcilib/xml.c | 1127 |
1 files changed, 603 insertions, 524 deletions
diff --git a/pcilib/xml.c b/pcilib/xml.c index 31b9926..c431b73 100644 --- a/pcilib/xml.c +++ b/pcilib/xml.c @@ -39,18 +39,25 @@ #include "register.h" #include "xml.h" #include "error.h" -#include "views.h" +#include "view.h" +#include "views/enum.h" +#include "views/transform.h" -#define BANKS_PATH ((xmlChar*)"/model/banks/bank/bank_description") /**< path to complete nodes of banks.*/ -//#define REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register") /**< all standard registers nodes.*/ -//#define BIT_REGISTERS_PATH ((xmlChar*)"/model/banks/bank/registers/register/registers_bits/register_bits") /**< all bits registers nodes.*/ -#define REGISTERS_PATH ((xmlChar*)"../registers/register") /**< all standard registers nodes.*/ -#define BIT_REGISTERS_PATH ((xmlChar*)"./registers_bits/register_bits") /**< all bits registers nodes.*/ -#define VIEWS_PATH ((xmlChar*)"/model/views/view") /**< path to complete nodes of views.*/ -#define UNITS_PATH ((xmlChar*)"/model/units/unit") /**< path to complete nodes of units.*/ +#define BANKS_PATH ((xmlChar*)"/model/bank") /**< path to complete nodes of banks */ +#define REGISTERS_PATH ((xmlChar*)"./register") /**< all standard registers nodes */ +#define BIT_REGISTERS_PATH ((xmlChar*)"./field") /**< all bits registers nodes */ +#define REGISTER_VIEWS_PATH ((xmlChar*)"./view") /**< supported register & field views */ +#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform") /**< path to complete nodes of views */ +#define ENUM_VIEWS_PATH ((xmlChar*)"/model/enum") /**< path to complete nodes of views */ +#define ENUM_ELEMENTS_PATH ((xmlChar*)"./name") /**< all elements in the enum */ +#define UNITS_PATH ((xmlChar*)"/model/unit") /**< path to complete nodes of units */ +#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform") /**< all transforms of the unit */ -static char *pcilib_xml_bank_default_format = "0x%lx"; + + +static const char *pcilib_xml_bank_default_format = "0x%lx"; +static const char *pcilib_xml_enum_view_unit = "name"; typedef struct { pcilib_register_description_t base; @@ -63,7 +70,7 @@ static xmlNodePtr pcilib_xml_get_parent_bank_node(xmlDocPtr doc, xmlNodePtr node bank_node = node->parent->parent; // bank_description is always a first node according to the XSD schema return xmlFirstElementChild(bank_node); - + } static xmlNodePtr pcilib_xml_get_parent_register_node(xmlDocPtr doc, xmlNodePtr node) { @@ -71,150 +78,105 @@ static xmlNodePtr pcilib_xml_get_parent_register_node(xmlDocPtr doc, xmlNodePtr } */ -/** - * get the associated unit of a view - * this function is maybe completekly useless : we need to decide if we iterate directly in ctx or n view when we want to apply a unit. (in the second choice of course keep it). - */ -static void -pcilib_get_unit_of_view(pcilib_t* ctx,pcilib_view_t* myview, char* base_unit){ - int j; - if((strcasecmp(base_unit,"name"))){ - for(j=0;ctx->units[j].name;j++){ - if(!(strcasecmp(base_unit,ctx->units[j].name))){ - myview->base_unit=ctx->units[j]; - break; - } - } - } -} - -/** - * get the associated views of a register, to fill its register context - */ -static int -pcilib_get_associated_views(pcilib_t* ctx, const char* reg_name,xmlXPathContextPtr xpath,pcilib_register_t id,int mode){ - - /* i find this solution pretty elegant, but what about perf?*/ - char* VIEWS_NAME_PATH_BITS="/model/banks/bank/registers/register[./name=\"%s\"]/registers_bits/register_bits/views/view"; - char* VIEWS_NAME_PATH="/model/banks/bank/registers/register[./name=\"%s\"]/views/view"; - char* path; - xmlXPathObjectPtr nodes; - xmlNodeSetPtr nodeset; - char* view_name; - - /*we get first the nodes corresponding to the given register*/ - if(mode==1) path=malloc(strlen(VIEWS_NAME_PATH)+strlen(reg_name)); - else path=malloc(strlen(VIEWS_NAME_PATH_BITS)+strlen(reg_name)); - if(!(path)){ - pcilib_error("can't allocate memory for getting path to get associated views of %s",reg_name); - return PCILIB_ERROR_MEMORY; - } - - if(mode==1) sprintf(path,VIEWS_NAME_PATH,reg_name); - else sprintf(path,VIEWS_NAME_PATH_BITS,reg_name); - nodes = xmlXPathEvalExpression((xmlChar*)path, xpath); - nodeset = nodes->nodesetval; - ctx->register_ctx[id].views=malloc(sizeof(pcilib_view_t)); - if(!(ctx->register_ctx[id].views)){ - pcilib_error("error allocating memory for enum views in register context %i",id); - return PCILIB_ERROR_MEMORY; - } +static int pcilib_xml_parse_view_reference(pcilib_t *ctx, xmlDocPtr doc, xmlNodePtr node, pcilib_view_reference_t *desc) { + xmlAttr *cur; + char *value, *name; - if (!xmlXPathNodeSetIsEmpty(nodeset)) { - int i,k,l=0; - /*if we correctly get a nodeset, then we iterate through the nodeset to get all views, using their names*/ - for (i = 0; i < nodeset->nodeNr; i++) { - view_name=(char*)nodeset->nodeTab[i]->children->content; - /* if the view name obtained is for an enum view, we get all pcilib_enum_t corresponding to the register*/ - for(k=0; ctx->views[k].name; k++){ - if(!(strcasecmp(view_name, ctx->views[k].name))){ - ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(l+1)*sizeof(pcilib_view_t)); - ctx->register_ctx[id].views[l]=ctx->views[k]; - l++; - } - } - } - ctx->register_ctx[id].views=realloc(ctx->register_ctx[id].views,(l+1)*sizeof(pcilib_view_t)); - ctx->register_ctx[id].views[l].name=NULL; + for (cur = node->properties; cur != NULL; cur = cur->next) { + if(!cur->children) continue; + if(!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + if (!strcasecmp(name, "name")) { + desc->name = value; + } else if (!strcasecmp(name, "view")) { + desc->view = value; + } } - - xmlXPathFreeObject(nodes); - free(path); + + if (!desc->name) + desc->name = desc->view; + return 0; } - -static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_description_t *xml_desc, xmlDocPtr doc, xmlNodePtr node, pcilib_register_bank_description_t *bdesc, int* views_ok) { +static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_description_t *xml_desc, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_register_bank_description_t *bdesc) { + int err; pcilib_register_description_t *desc = (pcilib_register_description_t*)xml_desc; - xmlNodePtr cur; + xmlXPathObjectPtr nodes; + xmlNodeSetPtr nodeset; + + xmlAttrPtr cur; char *value, *name; char *endptr; - for (cur = node->children; cur != NULL; cur = cur->next) { - if (!cur->children) continue; - if (!xmlNodeIsText(cur->children)) continue; - - name = (char*)cur->name; + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; value = (char*)cur->children->content; if (!value) continue; - + if (!strcasecmp((char*)name, "address")) { - uintptr_t addr = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid address (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } + uintptr_t addr = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid address (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc->addr = addr; } else if(!strcasecmp(name, "offset")) { - int offset = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)||(offset < 0)||(offset > (8 * sizeof(pcilib_register_value_t)))) { - pcilib_error("Invalid offset (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } + int offset = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)||(offset < 0)||(offset > (8 * sizeof(pcilib_register_value_t)))) { + pcilib_error("Invalid offset (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc->offset = (pcilib_register_size_t)offset; } else if (!strcasecmp(name,"size")) { - int size = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)||(size <= 0)||(size > (8 * sizeof(pcilib_register_value_t)))) { - pcilib_error("Invalid size (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } + int size = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)||(size <= 0)||(size > (8 * sizeof(pcilib_register_value_t)))) { + pcilib_error("Invalid size (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc->bits = (pcilib_register_size_t)size; } else if (!strcasecmp(name, "default")) { - pcilib_register_value_t val = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid default value (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } + pcilib_register_value_t val = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid default value (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc->defvalue = val; } else if (!strcasecmp(name,"min")) { - pcilib_register_value_t min = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } - xml_desc->min = min; + pcilib_register_value_t min = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } + xml_desc->min = min; } else if (!strcasecmp(name, "max")) { - pcilib_register_value_t max = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } - xml_desc->max = max; + pcilib_register_value_t max = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid minimum value (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } + xml_desc->max = max; } else if (!strcasecmp((char*)name,"rwmask")) { if (!strcasecmp(value, "all")) { desc->rwmask = PCILIB_REGISTER_ALL_BITS; } else if (!strcasecmp(value, "none")) { desc->rwmask = 0; } else { - uintptr_t mask = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid mask (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; - } - desc->rwmask = mask; - } + uintptr_t mask = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid mask (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; + } + desc->rwmask = mask; + } } else if (!strcasecmp(name, "mode")) { if (!strcasecmp(value, "R")) { desc->mode = PCILIB_REGISTER_R; @@ -229,113 +191,138 @@ static int pcilib_xml_parse_register(pcilib_t *ctx, pcilib_xml_register_descript } else if (!strcasecmp(value, "W1C")) { desc->mode = PCILIB_REGISTER_W1C; } else { - pcilib_error("Invalid access mode (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; + pcilib_error("Invalid access mode (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; } } else if (!strcasecmp(name, "type")) { if (!strcasecmp(value, "fifo")) { desc->type = PCILIB_REGISTER_FIFO; } else { - pcilib_error("Invalid register type (%s) is specified in the XML register description", value); - return PCILIB_ERROR_INVALID_DATA; + pcilib_error("Invalid register type (%s) is specified in the XML register description", value); + return PCILIB_ERROR_INVALID_DATA; } } else if (!strcasecmp(name,"name")) { desc->name = value; } else if (!strcasecmp(name,"description")) { desc->description = value; } - else if (!strcasecmp(name,"views")) { - *views_ok=1; + } + + xpath->node = node; + nodes = xmlXPathEvalExpression(REGISTER_VIEWS_PATH, xpath); + xpath->node = NULL; + + if (!nodes) { + xmlErrorPtr xmlerr = xmlGetLastError(); + + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTER_VIEWS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", REGISTER_VIEWS_PATH); + return PCILIB_ERROR_FAILED; + } + + + nodeset = nodes->nodesetval; + if (!xmlXPathNodeSetIsEmpty(nodeset)) { + int i; + + desc->views = (pcilib_view_reference_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t)); + if (!desc->views) { + xmlXPathFreeObject(nodes); + pcilib_error("Failed to allocate %zu bytes of memory to store supported register views", (nodeset->nodeNr + 1) * sizeof(char*)); + return PCILIB_ERROR_MEMORY; } + + memset(desc->views, 0, (nodeset->nodeNr + 1) * sizeof(pcilib_view_reference_t)); + for (i = 0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_parse_view_reference(ctx, doc, nodeset->nodeTab[i], &desc->views[i]); + if (err) { + xmlXPathFreeObject(nodes); + return err; + } + } } + xmlXPathFreeObject(nodes); return 0; } static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; - int views_ok=0; xmlXPathObjectPtr nodes; xmlNodeSetPtr nodeset; pcilib_xml_register_description_t desc = {{0}}; pcilib_xml_register_description_t fdesc; - + pcilib_register_t reg; desc.base.bank = ctx->banks[bank].addr; desc.base.rwmask = PCILIB_REGISTER_ALL_BITS; desc.base.mode = PCILIB_REGISTER_R; desc.base.type = PCILIB_REGISTER_STANDARD; - - err = pcilib_xml_parse_register(ctx, &desc, doc, node, &ctx->banks[bank],&views_ok); + + err = pcilib_xml_parse_register(ctx, &desc, xpath, doc, node, &ctx->banks[bank]); if (err) { - pcilib_error("Error (%i) parsing an XML register", err); - return err; + pcilib_error("Error (%i) parsing an XML register", err); + return err; } - + err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &desc.base, ®); if (err) { - pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, desc.base.name); - return err; + if (desc.base.views) free(desc.base.views); + pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, desc.base.name); + return err; } - ctx->register_ctx[reg].xml = node; + ctx->register_ctx[reg].xml = node; ctx->register_ctx[reg].min = desc.min; ctx->register_ctx[reg].max = desc.max; - - /* if the register had a node of type views, then we compute its associated registers. I do that here as i need the index for register context*/ - if(views_ok){ - err=pcilib_get_associated_views(ctx,desc.base.name,xpath,reg,1); - if(err) pcilib_warning("can't get correctly the associated views of the register %s",desc.base.name); - } + ctx->register_ctx[reg].views = desc.base.views; + xpath->node = node; nodes = xmlXPathEvalExpression(BIT_REGISTERS_PATH, xpath); xpath->node = NULL; - + if (!nodes) { - xmlErrorPtr xmlerr = xmlGetLastError(); + xmlErrorPtr xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BIT_REGISTERS_PATH, xmlerr->code, xmlerr->message); - else pcilib_error("Failed to parse XPath expression %s", BIT_REGISTERS_PATH); - return PCILIB_ERROR_FAILED; + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BIT_REGISTERS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", BIT_REGISTERS_PATH); + return PCILIB_ERROR_FAILED; } nodeset = nodes->nodesetval; if (!xmlXPathNodeSetIsEmpty(nodeset)) { - int i; - - for (i = 0; i < nodeset->nodeNr; i++) { - views_ok=0; - memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t)); - - fdesc.base.bank = desc.base.bank; - fdesc.base.addr = desc.base.addr; - fdesc.base.mode = desc.base.mode; - fdesc.base.rwmask = desc.base.rwmask; - fdesc.base.type = PCILIB_REGISTER_BITS; - - err = pcilib_xml_parse_register(ctx, &fdesc, doc, nodeset->nodeTab[i], &ctx->banks[bank],&views_ok); - if (err) { - pcilib_error("Error parsing field in the XML register %s", desc.base.name); - continue; - } - - err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, ®); - if (err) { - pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, fdesc.base.name); - continue; - } - - ctx->register_ctx[reg].xml = nodeset->nodeTab[i]; - ctx->register_ctx[reg].min = fdesc.min; - ctx->register_ctx[reg].max = fdesc.max; - if(views_ok){ - err=pcilib_get_associated_views(ctx, desc.base.name,xpath,reg,0); - if(err) pcilib_warning("can't get correctly the associated views of the register %s",fdesc.base.name); - } - } + int i; + + for (i = 0; i < nodeset->nodeNr; i++) { + memset(&fdesc, 0, sizeof(pcilib_xml_register_description_t)); + + fdesc.base.bank = desc.base.bank; + fdesc.base.addr = desc.base.addr; + fdesc.base.mode = desc.base.mode; + fdesc.base.rwmask = desc.base.rwmask; + fdesc.base.type = PCILIB_REGISTER_BITS; + + err = pcilib_xml_parse_register(ctx, &fdesc, xpath, doc, nodeset->nodeTab[i], &ctx->banks[bank]); + if (err) { + pcilib_error("Error parsing field in the XML register %s", desc.base.name); + continue; + } + + err = pcilib_add_registers(ctx, PCILIB_MODEL_MODIFICATION_FLAG_OVERRIDE, 1, &fdesc.base, ®); + if (err) { + if (fdesc.base.views) free(fdesc.base.views); + pcilib_error("Error (%i) adding a new XML register (%s) to the model", err, fdesc.base.name); + continue; + } + + ctx->register_ctx[reg].xml = nodeset->nodeTab[i]; + ctx->register_ctx[reg].min = fdesc.min; + ctx->register_ctx[reg].max = fdesc.max; + ctx->register_ctx[reg].views = fdesc.base.views; + } } xmlXPathFreeObject(nodes); @@ -344,11 +331,11 @@ static int pcilib_xml_create_register(pcilib_t *ctx, pcilib_register_bank_t bank static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; - + int override = 0; pcilib_register_bank_description_t desc = {0}; pcilib_register_bank_t bank; - xmlNodePtr cur; + xmlAttrPtr cur; char *value, *name; char *endptr; @@ -365,70 +352,70 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo desc.endianess = PCILIB_HOST_ENDIAN; desc.raw_endianess = PCILIB_HOST_ENDIAN; - // iterate through all children, representing bank properties, to fill the structure - for (cur = node->children; cur != NULL; cur = cur->next) { - if (!cur->children) continue; - if (!xmlNodeIsText(cur->children)) continue; - - name = (char*)cur->name; + // iterate through all children, representing bank properties, to fill the structure + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; value = (char*)cur->children->content; if (!value) continue; - + if (!strcasecmp(name, "bar")) { - char bar = value[0]-'0'; - if ((strlen(value) != 1)||(bar < 0)||(bar > 5)) { - pcilib_error("Invalid BAR (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; - } + char bar = value[0]-'0'; + if ((strlen(value) != 1)||(bar < 0)||(bar > 5)) { + pcilib_error("Invalid BAR (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc.bar = (pcilib_bar_t)bar; override = 1; } else if (!strcasecmp(name,"size")) { - long size = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)||(size<=0)) { - pcilib_error("Invalid bank size (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; - } + long size = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)||(size<=0)) { + pcilib_error("Invalid bank size (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc.size = (size_t)size; override = 1; } else if (!strcasecmp(name,"protocol")) { - pcilib_register_protocol_t protocol = pcilib_find_register_protocol_by_name(ctx, value); - if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) { - pcilib_error("Unsupported protocol (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_NOTSUPPORTED; - } - desc.protocol = ctx->protocols[protocol].addr; + pcilib_register_protocol_t protocol = pcilib_find_register_protocol_by_name(ctx, value); + if (protocol == PCILIB_REGISTER_PROTOCOL_INVALID) { + pcilib_error("Unsupported protocol (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_NOTSUPPORTED; + } + desc.protocol = ctx->protocols[protocol].addr; override = 1; } else if (!strcasecmp(name,"address")) { - uintptr_t addr = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid address (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; - } + uintptr_t addr = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid address (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc.read_addr = addr; desc.write_addr = addr; override = 1; } else if (!strcasecmp(name,"read_address")) { - uintptr_t addr = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid address (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; - } + uintptr_t addr = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid address (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc.read_addr = addr; override = 1; } else if (!strcasecmp(name,"write_address")) { - uintptr_t addr = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid address (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; - } + uintptr_t addr = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid address (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc.write_addr = addr; override = 1; } else if(strcasecmp((char*)name,"word_size")==0) { - int access = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)||(access%8)||(access<=0)||(access>(8 * sizeof(pcilib_register_value_t)))) { - pcilib_error("Invalid word size (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; - } + int access = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)||(access%8)||(access<=0)||(access>(8 * sizeof(pcilib_register_value_t)))) { + pcilib_error("Invalid word size (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } desc.access = access; override = 1; } else if (!strcasecmp(name,"endianess")) { @@ -436,8 +423,8 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo else if (!strcasecmp(value,"big")) desc.endianess = PCILIB_BIG_ENDIAN; else if (!strcasecmp(value,"host")) desc.endianess = PCILIB_HOST_ENDIAN; else { - pcilib_error("Invalid endianess (%s) is specified in the XML bank description", value); - return PCILIB_ERROR_INVALID_DATA; + pcilib_error("Invalid endianess (%s) is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; } override = 1; } else if (!strcasecmp(name,"format")) { @@ -449,7 +436,7 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo desc.description = value; override = 1; } else if (!strcasecmp((char*)name,"override")) { - override = 1; + override = 1; } } @@ -461,30 +448,237 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo ctx->xml.bank_nodes[bank] = node; if (ctx->bank_ctx[bank]) { - ctx->bank_ctx[bank]->xml = node; + ctx->bank_ctx[bank]->xml = node; } xpath->node = node; nodes = xmlXPathEvalExpression(REGISTERS_PATH, xpath); xpath->node = NULL; - + if (!nodes) { - xmlErrorPtr xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTERS_PATH, xmlerr->code, xmlerr->message); - else pcilib_error("Failed to parse XPath expression %s", REGISTERS_PATH); - return PCILIB_ERROR_FAILED; + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", REGISTERS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", REGISTERS_PATH); + return PCILIB_ERROR_FAILED; } nodeset = nodes->nodesetval; if (!xmlXPathNodeSetIsEmpty(nodeset)) { - int i; - for (i = 0; i < nodeset->nodeNr; i++) { - err = pcilib_xml_create_register(ctx, bank, xpath, doc, nodeset->nodeTab[i]); - if (err) pcilib_error("Error creating XML registers for bank %s", desc.name); + int i; + for (i = 0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_create_register(ctx, bank, xpath, doc, nodeset->nodeTab[i]); + if (err) pcilib_error("Error creating XML registers for bank %s", desc.name); + } + } + xmlXPathFreeObject(nodes); + + return 0; +} + +static int pcilib_xml_parse_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_view_description_t *desc) { + xmlAttrPtr cur; + const char *value, *name; + + desc->type = PCILIB_TYPE_STRING; + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + if (!value) continue; + + if (!strcasecmp(name, "name")) { + desc->name = value; + } else if (!strcasecmp((char*)name, "description")) { + desc->description = value; + } else if (!strcasecmp((char*)name, "unit")) { + desc->unit = value; + } else if (!strcasecmp((char*)name, "type")) { + if (!strcasecmp(value, "string")) desc->type = PCILIB_TYPE_STRING; + else if (!strcasecmp(value, "float")) desc->type = PCILIB_TYPE_DOUBLE; + else if (!strcasecmp(value, "int")) desc->type = PCILIB_TYPE_LONG; + else { + pcilib_error("Invalid type (%s) of register view is specified in the XML bank description", value); + return PCILIB_ERROR_INVALID_DATA; + } + } + } + + return 0; +} + +static int pcilib_xml_create_transform_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { + int err; + xmlAttrPtr cur; + const char *value, *name; + + pcilib_transform_view_description_t desc = {0}; + + desc.base.api = &pcilib_enum_view_xml_api; + + err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc); + if (err) return err; + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + if (!value) continue; + + if (!strcasecmp(name, "read_from_register")) { + desc.read_from_reg = value; + } else if (!strcasecmp(name, "write_to_register")) { + desc.write_to_reg = value; + } + } + + + return pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc); +} + + +static int pcilib_xml_parse_value_name(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_value_name_t *desc) { + xmlAttr *cur; + char *value, *name; + char *endptr; + + int min_set = 0, max_set = 0; + pcilib_register_value_t val; + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if(!cur->children) continue; + if(!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + + if (!strcasecmp(name, "name")) { + desc->name = value; + } else if (!strcasecmp(name, "value")) { + val = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid enum value (%s) is specified in the XML enum node", value); + return PCILIB_ERROR_INVALID_DATA; + } + desc->value = val; + } else if (!strcasecmp(name, "min")) { + val = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid enum min-value (%s) is specified in the XML enum node", value); + return PCILIB_ERROR_INVALID_DATA; + } + desc->min = val; + min_set = 1; + } else if (!strcasecmp(name, "max")) { + val = strtol(value, &endptr, 0); + if ((strlen(endptr) > 0)) { + pcilib_error("Invalid enum max-value (%s) is specified in the XML enum node", value); + return PCILIB_ERROR_INVALID_DATA; + } + desc->max = val; + max_set = 1; } } + + if ((!min_set)&&(!max_set)) { + desc->min = desc->value; + desc->max = desc->value; + } else if (max_set) { + desc->min = 0; + } else if (min_set) { + desc->max = (pcilib_register_value_t)-1; + } + + if ((desc->min > desc->max)||(desc->value < desc->min)||(desc->value > desc->max)) { + pcilib_error("Invalid enum configuration (min: %lu, max: %lu, value: %lu)", desc->min, desc->max, desc->value); + return PCILIB_ERROR_INVALID_DATA; + } + + return 0; +} + +static int pcilib_xml_create_enum_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { + int i; + int err; + + xmlXPathObjectPtr nodes; + xmlNodeSetPtr nodeset; + + pcilib_enum_view_description_t desc = {0}; + + desc.base.unit = pcilib_xml_enum_view_unit; + desc.base.api = &pcilib_enum_view_xml_api; + + err = pcilib_xml_parse_view(ctx, xpath, doc, node, (pcilib_view_description_t*)&desc); + if (err) return err; + + + xpath->node = node; + nodes = xmlXPathEvalExpression(ENUM_ELEMENTS_PATH, xpath); + xpath->node = NULL; + + if (!nodes) { + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", ENUM_ELEMENTS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", ENUM_ELEMENTS_PATH); + return PCILIB_ERROR_FAILED; + } + + nodeset = nodes->nodesetval; + if (xmlXPathNodeSetIsEmpty(nodeset)) { + xmlXPathFreeObject(nodes); + pcilib_error("No names is defined for enum view (%s)", desc.base.name); + return PCILIB_ERROR_INVALID_DATA; + } + + desc.names = (pcilib_value_name_t*)malloc((nodeset->nodeNr + 1) * sizeof(pcilib_value_name_t)); + if (!desc.names) { + xmlXPathFreeObject(nodes); + pcilib_error("No names is defined for enum view (%s)", desc.base.name); + return PCILIB_ERROR_INVALID_DATA; + } + + + for (i = 0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_parse_value_name(ctx, xpath, doc, nodeset->nodeTab[i], &desc.names[i]); + if (err) { + xmlXPathFreeObject(nodes); + free(desc.names); + return err; + } + } + memset(&desc.names[nodeset->nodeNr], 0, sizeof(pcilib_value_name_t)); + xmlXPathFreeObject(nodes); + + err = pcilib_add_views(ctx, 1, (pcilib_view_description_t*)&desc); + if (err) free(desc.names); + return err; +} + +static int pcilib_xml_parse_unit_transform(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node, pcilib_unit_transform_t *desc) { + xmlAttrPtr cur; + char *value, *name; + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; + value = (char*)cur->children->content; + + if (!strcasecmp(name, "unit")) { + desc->unit = value; + } else if (!strcasecmp(name, "transform")) { + desc->transform = value; + } + } + return 0; } @@ -496,171 +690,60 @@ static int pcilib_xml_create_bank(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo *@param[in] node - the node representing the unit *@return an error code: 0 if evrythinh is ok */ -static int -pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { +static int pcilib_xml_create_unit(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { int err; - - pcilib_unit_t desc = {0}; - xmlNodePtr cur; - char *value, *name, *value2; - xmlAttr *attr; - int i=0; + pcilib_unit_description_t desc = {0}; - /* we get the attribute type of the view node*/ - attr=node->properties; - value=(char*)attr->children->content; - desc.name=value; - - for (cur = node->children; cur != NULL; cur = cur->next) { - if (!cur->children) continue; - if (!xmlNodeIsText(cur->children)) continue; - - name = (char*)cur->name; + xmlXPathObjectPtr nodes; + xmlNodeSetPtr nodeset; + + xmlAttrPtr cur; + char *value, *name; + + for (cur = node->properties; cur != NULL; cur = cur->next) { + if (!cur->children) continue; + if (!xmlNodeIsText(cur->children)) continue; + + name = (char*)cur->name; value = (char*)cur->children->content; - attr= cur->properties; - value2=(char*)attr->children->content; - if (!value || !attr) continue; - - if (!strcasecmp(name, "convert_unit")) { - desc.transforms[i].name=value2; - desc.transforms[i].transform_formula=value; - i++; + if (!strcasecmp(name, "name")) { + desc.name = value; } } - err = pcilib_add_units(ctx, 1, &desc); - if (err) { - pcilib_error("Error adding unit (%s) specified in the XML", desc.name); - return err; - } - - return 0; -} + xpath->node = node; + nodes = xmlXPathEvalExpression(UNIT_TRANSFORMS_PATH, xpath); + xpath->node = NULL; -/** - * function that create a view from a view node, and populate ctx views list - */ -static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDocPtr doc, xmlNodePtr node) { - int err; - - pcilib_view_t desc={0}; - xmlNodePtr cur; - char *value, *name; - char *endptr; - xmlAttr *attr; - int i=0; - int ok_min=0, ok_max=0; + if (!nodes) { + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", UNIT_TRANSFORMS_PATH, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", UNIT_TRANSFORMS_PATH); + return PCILIB_ERROR_FAILED; + } - desc.description="default description"; + nodeset = nodes->nodesetval; + if (!xmlXPathNodeSetIsEmpty(nodeset)) { + int i; - /* we get the attribute type of the view node*/ - attr=node->properties; - value=(char*)attr->children->content; - /* regarding the architecture, i decided to follow what has been done for registers and banks. but without the context*/ - /*if the view is of type enum, we get recursively its properties and then populate ctx enum views*/ - if(!(strcasecmp(value,"enum"))){ - desc.op=&operation_enum; - desc.parameters=malloc(sizeof(pcilib_enum_t)); - desc.base_unit.name="name"; - for (cur = node->children; cur != NULL; cur = cur->next) { - if (!cur->children) continue; - if (!xmlNodeIsText(cur->children)) continue; - - name = (char*)cur->name; - value = (char*)cur->children->content; - if (!value) continue; - - if (!(strcasecmp((char*)name,"name"))) { - desc.name = value; - - }else if (!(strcasecmp((char*)name,"description"))) { - desc.description = value; - - }else if (!(strcasecmp((char*)name,"enum"))) { - desc.parameters=realloc(desc.parameters,(i+1)*sizeof(pcilib_enum_t)); - ((pcilib_enum_t*)(desc.parameters))[i].name=value; - - /* we need to iterate through the different attributes of an enum node to get all properties*/ - for(attr=cur->properties; attr!=NULL;attr=attr->next){ - if(!attr->children) continue; - if(!xmlNodeIsText(attr->children)) continue; - - name=(char*)attr->name; - value=(char*)attr->children->content; - - if(!(strcasecmp(name,"value"))){ - pcilib_register_value_t dat_value = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid value (%s) is specified in the XML enum node", value); - return PCILIB_ERROR_INVALID_DATA; - } - ((pcilib_enum_t*)(desc.parameters))[i].value=dat_value; - }else if(!(strcasecmp(name,"min"))){ - pcilib_register_value_t dat_min = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid min (%s) is specified in the XML enum node", value); - return PCILIB_ERROR_INVALID_DATA; - } - ((pcilib_enum_t*)(desc.parameters))[i].min=dat_min; - ok_min=1; - }else if(!(strcasecmp(name,"max"))){ - pcilib_register_value_t dat_max = strtol(value, &endptr, 0); - if ((strlen(endptr) > 0)) { - pcilib_error("Invalid max (%s) is specified in the XML enum node", value); - return PCILIB_ERROR_INVALID_DATA; - } - ((pcilib_enum_t*)(desc.parameters))[i].max=dat_max; - ok_max=1; - } - if(ok_min==0) ((pcilib_enum_t*)(desc.parameters))[i].min=((pcilib_enum_t*)(desc.parameters))[i].value; - if(ok_max==0) ((pcilib_enum_t*)(desc.parameters))[i].max=((pcilib_enum_t*)(desc.parameters))[i].value; - - } - i++; + if (nodeset->nodeNr > PCILIB_MAX_TRANSFORMS_PER_UNIT) { + xmlXPathFreeObject(nodes); + pcilib_error("Too many transforms for unit %s are defined, only %lu are supported", desc.name, PCILIB_MAX_TRANSFORMS_PER_UNIT); + return PCILIB_ERROR_INVALID_DATA; } - } - err=pcilib_add_views(ctx,1,&desc); - if (err) { - pcilib_error("Error (%i) adding a new enum view (%s) to the pcilib_t", err, desc.name); - return err; - } - - /* we do the same here but for a iew of type formula if the attribute gives formula*/ - }else if(!(strcasecmp(value,"formula"))){ - desc.op=&operation_formula; - desc.parameters=malloc(sizeof(pcilib_formula_t)); - for (cur = node->children; cur != NULL; cur = cur->next) { - if (!cur->children) continue; - if (!xmlNodeIsText(cur->children)) continue; - name = (char*)cur->name; - value = (char*)cur->children->content; - - if (!value) continue; - - if (!(strcasecmp((char*)name,"name"))) { - desc.name = value; - }else if (!(strcasecmp((char*)name,"read_from_register"))) { - ((pcilib_formula_t*)(desc.parameters))->read_formula=value; - }else if (!(strcasecmp((char*)name,"write_to_register"))) { - ((pcilib_formula_t*)(desc.parameters))->write_formula=value; - }else if (!(strcasecmp((char*)name,"description"))) { - desc.description=value; - }else if (!(strcasecmp((char*)name,"unit"))){ - desc.base_unit.name=value; + for (i = 0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_parse_unit_transform(ctx, xpath, doc, nodeset->nodeTab[i], &desc.transforms[i]); + if (err) { + xmlXPathFreeObject(nodes); + return err; + } } - } - - err=pcilib_add_views(ctx,1,&desc); - if (err) { - pcilib_error("Error (%i) adding a new formula view (%s) to the pcilib_t", err, desc.name); - return err; - } - } - - return 0; + xmlXPathFreeObject(nodes); + + return pcilib_add_units(ctx, 1, &desc); } @@ -672,97 +755,108 @@ static int pcilib_xml_create_view(pcilib_t *ctx, xmlXPathContextPtr xpath, xmlDo * @param[in] pci the pcilib_t running, which will be filled */ static int pcilib_xml_process_document(pcilib_t *ctx, xmlDocPtr doc, xmlXPathContextPtr xpath) { - xmlXPathObjectPtr bank_nodes,views_nodes, units_nodes; + int err; + xmlXPathObjectPtr bank_nodes = NULL, transform_nodes = NULL, enum_nodes = NULL, unit_nodes = NULL; xmlNodeSetPtr nodeset; int i; - xmlErrorPtr xmlerr; - - units_nodes=xmlXPathEvalExpression(UNITS_PATH,xpath); - if(!units_nodes){ - goto views; - } - - nodeset=units_nodes->nodesetval; - if(!xmlXPathNodeSetIsEmpty(nodeset)){ - for(i=0;i < nodeset->nodeNr; i++){ - pcilib_xml_create_unit(ctx,xpath,doc,nodeset->nodeTab[i]); - } - } - xmlXPathFreeObject(units_nodes); - views: - views_nodes=xmlXPathEvalExpression(VIEWS_PATH,xpath); - if(!views_nodes){ - goto banks; + bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); + if (bank_nodes) transform_nodes = xmlXPathEvalExpression(TRANSFORM_VIEWS_PATH, xpath); + if (transform_nodes) enum_nodes = xmlXPathEvalExpression(ENUM_VIEWS_PATH, xpath); + if (enum_nodes) unit_nodes = xmlXPathEvalExpression(UNITS_PATH, xpath); + + if (!unit_nodes) { + const unsigned char *expr = (enum_nodes?UNITS_PATH:(transform_nodes?ENUM_VIEWS_PATH:(bank_nodes?TRANSFORM_VIEWS_PATH:BANKS_PATH))); + + if (enum_nodes) xmlXPathFreeObject(enum_nodes); + if (transform_nodes) xmlXPathFreeObject(transform_nodes); + if (bank_nodes) xmlXPathFreeObject(bank_nodes); + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", expr, xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XPath expression %s", expr); + return PCILIB_ERROR_FAILED; } - - nodeset=views_nodes->nodesetval; - if(!xmlXPathNodeSetIsEmpty(nodeset)){ - for(i=0;i < nodeset->nodeNr; i++){ - pcilib_xml_create_view(ctx,xpath,doc,nodeset->nodeTab[i]); - } + + nodeset = unit_nodes->nodesetval; + if(!xmlXPathNodeSetIsEmpty(nodeset)) { + for(i=0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_create_unit(ctx, xpath, doc, nodeset->nodeTab[i]); + if (err) pcilib_error("Error (%i) creating unit", err); + } } - xmlXPathFreeObject(views_nodes); - banks: - bank_nodes = xmlXPathEvalExpression(BANKS_PATH, xpath); - if (!bank_nodes) { - xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", BANKS_PATH, xmlerr->code, xmlerr->message); - else pcilib_error("Failed to parse XPath expression %s", BANKS_PATH); - return PCILIB_ERROR_FAILED; + nodeset = transform_nodes->nodesetval; + if (!xmlXPathNodeSetIsEmpty(nodeset)) { + for(i=0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_create_transform_view(ctx, xpath, doc, nodeset->nodeTab[i]); + if (err) pcilib_error("Error (%i) creating register transform", err); + } } + nodeset = enum_nodes->nodesetval; + if (!xmlXPathNodeSetIsEmpty(nodeset)) { + for(i=0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_create_enum_view(ctx, xpath, doc, nodeset->nodeTab[i]); + if (err) pcilib_error("Error (%i) creating register enum", err); + } + } nodeset = bank_nodes->nodesetval; if (!xmlXPathNodeSetIsEmpty(nodeset)) { - for (i = 0; i < nodeset->nodeNr; i++) { - pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]); - } + for (i = 0; i < nodeset->nodeNr; i++) { + err = pcilib_xml_create_bank(ctx, xpath, doc, nodeset->nodeTab[i]); + if (err) pcilib_error("Error (%i) creating bank", err); + } } + + + xmlXPathFreeObject(unit_nodes); + xmlXPathFreeObject(enum_nodes); + xmlXPathFreeObject(transform_nodes); xmlXPathFreeObject(bank_nodes); + return 0; } static int pcilib_xml_load_xsd(pcilib_t *ctx, char *xsd_filename) { int err; - + xmlSchemaParserCtxtPtr ctxt; /** we first parse the xsd file for AST with validation*/ ctxt = xmlSchemaNewParserCtxt(xsd_filename); if (!ctxt) { - xmlErrorPtr xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("xmlSchemaNewParserCtxt reported error %d - %s", xmlerr->code, xmlerr->message); - else pcilib_error("Failed to create a parser for XML schemas"); - return PCILIB_ERROR_FAILED; + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("xmlSchemaNewParserCtxt reported error %d - %s", xmlerr->code, xmlerr->message); + else pcilib_error("Failed to create a parser for XML schemas"); + return PCILIB_ERROR_FAILED; } - + ctx->xml.schema = xmlSchemaParse(ctxt); if (!ctx->xml.schema) { - xmlErrorPtr xmlerr = xmlGetLastError(); - xmlSchemaFreeParserCtxt(ctxt); - if (xmlerr) pcilib_error("Failed to parse XML schema, xmlSchemaParse reported error %d - %s", xmlerr->code, xmlerr->message); - else pcilib_error("Failed to parse XML schema"); - return PCILIB_ERROR_INVALID_DATA; + xmlErrorPtr xmlerr = xmlGetLastError(); + xmlSchemaFreeParserCtxt(ctxt); + if (xmlerr) pcilib_error("Failed to parse XML schema, xmlSchemaParse reported error %d - %s", xmlerr->code, xmlerr->message); + else pcilib_error("Failed to parse XML schema"); + return PCILIB_ERROR_INVALID_DATA; } - + xmlSchemaFreeParserCtxt(ctxt); ctx->xml.validator = xmlSchemaNewValidCtxt(ctx->xml.schema); if (!ctx->xml.validator) { - xmlErrorPtr xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("xmlSchemaNewValidCtxt reported error %d - %s", xmlerr->code, xmlerr->message); - else pcilib_error("Failed to create a validation context"); - return PCILIB_ERROR_FAILED; + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("xmlSchemaNewValidCtxt reported error %d - %s", xmlerr->code, xmlerr->message); + else pcilib_error("Failed to create a validation context"); + return PCILIB_ERROR_FAILED; } - + err = xmlSchemaSetValidOptions(ctx->xml.validator, XML_SCHEMA_VAL_VC_I_CREATE); if (err) { - xmlErrorPtr xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("xmlSchemaSetValidOptions reported error %d - %s", xmlerr->code, xmlerr->message); - else pcilib_error("Failed to configure the validation context to populate default attributes"); - return PCILIB_ERROR_FAILED; + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("xmlSchemaSetValidOptions reported error %d - %s", xmlerr->code, xmlerr->message); + else pcilib_error("Failed to configure the validation context to populate default attributes"); + return PCILIB_ERROR_FAILED; } return 0; @@ -776,46 +870,46 @@ static int pcilib_xml_load_file(pcilib_t *ctx, const char *path, const char *nam full_name = (char*)alloca(strlen(path) + strlen(name) + 2); if (!name) { - pcilib_error("Error allocating %zu bytes of memory in stack to create a file name", strlen(path) + strlen(name) + 2); - return PCILIB_ERROR_MEMORY; + pcilib_error("Error allocating %zu bytes of memory in stack to create a file name", strlen(path) + strlen(name) + 2); + return PCILIB_ERROR_MEMORY; } sprintf(full_name, "%s/%s", path, name); doc = xmlCtxtReadFile(ctx->xml.parser, full_name, NULL, 0); if (!doc) { - xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser); - if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", full_name, xmlerr->code, xmlerr->message); - else pcilib_error("Error parsing %s", full_name); - return PCILIB_ERROR_INVALID_DATA; + xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser); + if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", full_name, xmlerr->code, xmlerr->message); + else pcilib_error("Error parsing %s", full_name); + return PCILIB_ERROR_INVALID_DATA; } err = xmlSchemaValidateDoc(ctx->xml.validator, doc); if (err) { - xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser); - xmlFreeDoc(doc); - if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", full_name, xmlerr->code, xmlerr->message); - else pcilib_error("Error validating %s", full_name); - return PCILIB_ERROR_VERIFY; + xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser); + xmlFreeDoc(doc); + if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", full_name, xmlerr->code, xmlerr->message); + else pcilib_error("Error validating %s", full_name); + return PCILIB_ERROR_VERIFY; } xpath = xmlXPathNewContext(doc); if (!xpath) { - xmlErrorPtr xmlerr = xmlGetLastError(); - xmlFreeDoc(doc); - if (xmlerr) pcilib_error("Document %s: xmlXpathNewContext reported error %d - %s for document %s", full_name, xmlerr->code, xmlerr->message); - else pcilib_error("Error creating XPath context for %s", full_name); - return PCILIB_ERROR_FAILED; + xmlErrorPtr xmlerr = xmlGetLastError(); + xmlFreeDoc(doc); + if (xmlerr) pcilib_error("Document %s: xmlXpathNewContext reported error %d - %s for document %s", full_name, xmlerr->code, xmlerr->message); + else pcilib_error("Error creating XPath context for %s", full_name); + return PCILIB_ERROR_FAILED; } - // This can only partially fail... Therefore we need to keep XML and just return the error... + // This can only partially fail... Therefore we need to keep XML and just return the error... err = pcilib_xml_process_document(ctx, doc, xpath); if (ctx->xml.num_files == PCILIB_MAX_MODEL_FILES) { - xmlFreeDoc(doc); + xmlFreeDoc(doc); xmlXPathFreeContext(xpath); - pcilib_error("Too many XML files for a model, only up to %zu are supported", PCILIB_MAX_MODEL_FILES); - return PCILIB_ERROR_TOOBIG; + pcilib_error("Too many XML files for a model, only up to %zu are supported", PCILIB_MAX_MODEL_FILES); + return PCILIB_ERROR_TOOBIG; } ctx->xml.docs[ctx->xml.num_files] = doc; @@ -833,8 +927,6 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { struct dirent *file = NULL; char *model_dir, *model_path; - int i,j; - model_dir = getenv("PCILIB_MODEL_DIR"); if (!model_dir) model_dir = PCILIB_MODEL_DIR; @@ -847,27 +939,14 @@ int pcilib_process_xml(pcilib_t *ctx, const char *location) { if (!rep) return PCILIB_ERROR_NOTFOUND; while ((file = readdir(rep)) != NULL) { - size_t len = strlen(file->d_name); - if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue; - if (file->d_type != DT_REG) continue; - - err = pcilib_xml_load_file(ctx, model_path, file->d_name); - if (err) pcilib_error("Error processing XML file %s", file->d_name); - } - - for(i=0;i<ctx->num_views;i++){ - pcilib_get_unit_of_view(ctx,&(ctx->views[i]),ctx->views[i].base_unit.name); - } - - for(i=0;i<ctx->num_reg;i++){ - if(!(ctx->register_ctx[i].views)) continue; - for(j=0;j<ctx->num_views;j++){ - if(!(ctx->register_ctx[i].views[j].name)) break; - if(ctx->register_ctx[i].views[j].name){ - pcilib_get_unit_of_view(ctx,&(ctx->register_ctx[i].views[j]),ctx->register_ctx[i].views[j].base_unit.name); - } - } + size_t len = strlen(file->d_name); + if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue; + if (file->d_type != DT_REG) continue; + + err = pcilib_xml_load_file(ctx, model_path, file->d_name); + if (err) pcilib_error("Error processing XML file %s", file->d_name); } + closedir(rep); return 0; @@ -896,16 +975,16 @@ int pcilib_init_xml(pcilib_t *ctx, const char *model) { sprintf(xsd_path, "%s/model.xsd", model_dir); if (stat(xsd_path, &st)) { - pcilib_info("XML models are not present"); - return PCILIB_ERROR_NOTFOUND; + pcilib_info("XML models are not present"); + return PCILIB_ERROR_NOTFOUND; } ctx->xml.parser = xmlNewParserCtxt(); if (!ctx->xml.parser) { - xmlErrorPtr xmlerr = xmlGetLastError(); - if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message); - else pcilib_error("Failed to create an XML parser context"); - return PCILIB_ERROR_FAILED; + xmlErrorPtr xmlerr = xmlGetLastError(); + if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message); + else pcilib_error("Failed to create an XML parser context"); + return PCILIB_ERROR_FAILED; } err = pcilib_xml_load_xsd(ctx, xsd_path); @@ -923,44 +1002,44 @@ void pcilib_free_xml(pcilib_t *ctx) { memset(ctx->xml.bank_nodes, 0, sizeof(ctx->xml.bank_nodes)); for (i = 0; i < ctx->num_banks; i++) { - if (ctx->bank_ctx[i]) - ctx->bank_ctx[i]->xml = NULL; + if (ctx->bank_ctx[i]) + ctx->bank_ctx[i]->xml = NULL; } - + for (i = 0; i < ctx->num_reg; i++) { - ctx->register_ctx[i].xml = NULL; + ctx->register_ctx[i].xml = NULL; } - + for (i = 0; i < ctx->xml.num_files; i++) { - if (ctx->xml.docs[i]) { - xmlFreeDoc(ctx->xml.docs[i]); - ctx->xml.docs[i] = NULL; - } - if (ctx->xml.xpath[i]) { - xmlXPathFreeContext(ctx->xml.xpath[i]); - ctx->xml.xpath[i] = NULL; - } + if (ctx->xml.docs[i]) { + xmlFreeDoc(ctx->xml.docs[i]); + ctx->xml.docs[i] = NULL; + } + if (ctx->xml.xpath[i]) { + xmlXPathFreeContext(ctx->xml.xpath[i]); + ctx->xml.xpath[i] = NULL; + } } ctx->xml.num_files = 0; if (ctx->xml.validator) { - xmlSchemaFreeValidCtxt(ctx->xml.validator); - ctx->xml.validator = NULL; + xmlSchemaFreeValidCtxt(ctx->xml.validator); + ctx->xml.validator = NULL; } - + if (ctx->xml.schema) { - xmlSchemaFree(ctx->xml.schema); - ctx->xml.schema = NULL; - + xmlSchemaFree(ctx->xml.schema); + ctx->xml.schema = NULL; + } if (ctx->xml.parser) { - xmlFreeParserCtxt(ctx->xml.parser); - ctx->xml.parser = NULL; + xmlFreeParserCtxt(ctx->xml.parser); + ctx->xml.parser = NULL; } -/* - xmlSchemaCleanupTypes(); - xmlCleanupParser(); - xmlMemoryDump(); -*/ + /* + xmlSchemaCleanupTypes(); + xmlCleanupParser(); + xmlMemoryDump(); + */ } |