census_context *census_context_create(const census_context *base, const census_tag *tags, int ntags, census_context_status const **status) { census_context *context = (census_context *)gpr_malloc(sizeof(census_context)); // If we are given a base, copy it into our new tag set. Otherwise set it // to zero/NULL everything. if (base == NULL) { memset(context, 0, sizeof(census_context)); } else { tag_set_copy(&context->tags[PROPAGATED_TAGS], &base->tags[PROPAGATED_TAGS]); tag_set_copy(&context->tags[LOCAL_TAGS], &base->tags[LOCAL_TAGS]); memset(&context->status, 0, sizeof(context->status)); } // Walk over the additional tags and, for those that aren't invalid, modify // the context to add/replace/delete as required. for (int i = 0; i < ntags; i++) { const census_tag *tag = &tags[i]; size_t key_len = validate_tag(tag->key); // ignore the tag if it is invalid or too short. if (key_len <= 1) { context->status.n_invalid_tags++; } else { if (tag->value != NULL) { size_t value_len = validate_tag(tag->value); if (value_len != 0) { context_modify_tag(context, tag, key_len, value_len); } else { context->status.n_invalid_tags++; } } else { if (context_delete_tag(context, tag, key_len)) { context->status.n_deleted_tags++; } } } } // Remove any deleted tags, update status if needed, and return. tag_set_flatten(&context->tags[PROPAGATED_TAGS]); tag_set_flatten(&context->tags[LOCAL_TAGS]); context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags; context->status.n_local_tags = context->tags[LOCAL_TAGS].ntags; if (status) { *status = &context->status; } return context; }
// test many changes at once. static void replace_add_delete_test(void) { struct census_tag_set *cts = census_tag_set_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL); const census_tag_set_create_status *status; struct census_tag_set *cts2 = census_tag_set_create(cts, modify_tags, MODIFY_TAG_COUNT, &status); census_tag_set_create_status expected = {2, 1, 6, 2, 3, 4, 0, 2}; GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0); // validate tag set contents. Use specific indices into the two arrays // holding tag values. GPR_ASSERT(validate_tag(cts2, &basic_tags[3])); GPR_ASSERT(validate_tag(cts2, &basic_tags[4])); GPR_ASSERT(validate_tag(cts2, &modify_tags[0])); GPR_ASSERT(validate_tag(cts2, &modify_tags[1])); GPR_ASSERT(validate_tag(cts2, &modify_tags[6])); GPR_ASSERT(validate_tag(cts2, &modify_tags[7])); GPR_ASSERT(validate_tag(cts2, &modify_tags[8])); GPR_ASSERT(validate_tag(cts2, &modify_tags[9])); GPR_ASSERT(validate_tag(cts2, &modify_tags[10])); GPR_ASSERT(!validate_tag(cts2, &basic_tags[0])); GPR_ASSERT(!validate_tag(cts2, &basic_tags[1])); GPR_ASSERT(!validate_tag(cts2, &basic_tags[2])); GPR_ASSERT(!validate_tag(cts2, &basic_tags[5])); GPR_ASSERT(!validate_tag(cts2, &basic_tags[6])); GPR_ASSERT(!validate_tag(cts2, &basic_tags[7])); census_tag_set_destroy(cts); census_tag_set_destroy(cts2); }
bool device_memory_interface::interface_validity_check(emu_options &options, const game_driver &driver) const { bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true; bool error = false; // loop over all address spaces for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) { const address_space_config *spaceconfig = space_config(spacenum); if (spaceconfig != NULL) { int datawidth = spaceconfig->m_databus_width; int alignunit = datawidth / 8; // construct the maps ::address_map *map = global_alloc(::address_map(device(), spacenum)); // if this is an empty map, just skip it if (map->m_entrylist.first() == NULL) { global_free(map); continue; } // validate the global map parameters if (map->m_spacenum != spacenum) { mame_printf_error("%s: %s device '%s' space %d has address space %d handlers!\n", driver.source_file, driver.name, device().tag(), spacenum, map->m_spacenum); error = true; } if (map->m_databits != datawidth) { mame_printf_error("%s: %s device '%s' uses wrong memory handlers for %s space! (width = %d, memory = %08x)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, datawidth, map->m_databits); error = true; } // loop over entries and look for errors for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next()) { UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart); UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend); // look for overlapping entries if (!detected_overlap) { address_map_entry *scan; for (scan = map->m_entrylist.first(); scan != entry; scan = scan->next()) if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart && ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) || (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE))) { mame_printf_warning("%s: %s '%s' %s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); detected_overlap = true; break; } } // look for inverted start/end pairs if (byteend < bytestart) { mame_printf_error("%s: %s wrong %s memory read handler start = %08x > end = %08x\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend); error = true; } // look for misaligned entries if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1)) { mame_printf_error("%s: %s wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit); error = true; } // if this is a program space, auto-assign implicit ROM entries if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) { entry->m_region = device().tag(); entry->m_rgnoffs = entry->m_addrstart; } // if this entry references a memory region, validate it if (entry->m_region != NULL && entry->m_share == 0) { // look for the region bool found = false; for (const rom_source *source = rom_first_source(device().mconfig()); source != NULL && !found; source = rom_next_source(*source)) for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp) && !found; romp++) { const char *regiontag_c = ROMREGION_GETTAG(romp); if (regiontag_c != NULL) { astring fulltag; astring regiontag; // a leading : on a region name indicates an absolute region, so fix up accordingly if (entry->m_region[0] == ':') { regiontag = &entry->m_region[1]; } else { if (strchr(entry->m_region,':')) { regiontag = entry->m_region; } else { device().siblingtag(regiontag, entry->m_region); } } rom_region_name(fulltag, &driver, source, romp); if (fulltag.cmp(regiontag) == 0) { // verify the address range is within the region's bounds offs_t length = ROMREGION_GETLENGTH(romp); if (entry->m_rgnoffs + (byteend - bytestart + 1) > length) { mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length); error = true; } found = true; } } } // error if not found if (!found) { mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X references non-existant region '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); error = true; } } // make sure all devices exist if ((entry->m_read.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_read.m_tag != NULL && device().mconfig().devicelist().find(entry->m_read.m_tag) == NULL) || (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag != NULL && device().mconfig().devicelist().find(entry->m_write.m_tag) == NULL)) { mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_write.m_tag); error = true; } // make sure ports exist // if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) || // (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL)) // { // mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_read.tag); // error = true; // } // validate bank and share tags if (entry->m_read.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_read.m_tag)) error = true ; if (entry->m_write.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_write.m_tag)) error = true; if (entry->m_share != NULL && !validate_tag(driver, "share", entry->m_share)) error = true; } // release the address map global_free(map); } } return error; }
/* basic xml parser */ static int xml_parse(request *req, tag_t *parent, char *xstr, int len) { int i; int next_ch = -1; int last_ch = -1; int this_ch = -1; int rval; int state; tag_t *tag = NULL; state = set_xstate(XST_DONE); nest++; i = 0; while(i < len) { last_ch = xstr[i-1]; this_ch = xstr[i]; next_ch = xstr[i+1]; if(state == XST_DONE) { /* done processing at this level, return processed count to previous level */ if(this_ch == '<' && next_ch == '/') return i; state = set_xstate(XST_GET_START_TAG); tag = create_tag(req, parent); } switch (state) { case XST_GET_START_TAG: if(!tag->start_name) { tag->start_name = &xstr[i]; } tag->start_len++; /* process any tag attributes */ if(!tag->attr_name) { if((this_ch == ' ') && (next_ch != '/')) tag->attr_name = &xstr[i+1]; } else { if(this_ch != '>') tag->attr_len++; } if (this_ch == '>') { if(last_ch == '?') { if(!req->prolog_tag) { req->prolog_tag = tag; state = set_xstate(XST_DONE); goto NextChar; } else return -1; } else if(!req->root_tag) { req->root_tag = tag; } if(last_ch == '/') { // empty tag state = set_xstate(XST_VALIDATE); tag->empty = 1; } else state = set_xstate(XST_GET_VALUE); } break; case XST_GET_VALUE: if (this_ch != '<') { if(!tag->value_name) tag->value_name = &xstr[i]; tag->value_len++; break; } else state = set_xstate(XST_GET_END_TAG); /* fall through is deliberate */ case XST_GET_END_TAG: if(!tag->end_name) tag->end_name = &xstr[i]; tag->end_len++; if (this_ch == '>') state = set_xstate(XST_VALIDATE); break; } if(state == XST_VALIDATE) { state = set_xstate(XST_DONE); rval = validate_tag(tag); //fprintf(stderr,"\r\After validate_tag with retval:%d\n",rval); if (rval == 0) { tag = NULL; goto NextChar; } /* tag is invalid */ else if (rval < 0) { return -1; } // tag mismatch, adjust len and process child i = i - tag->end_len; rval = xml_parse(req, tag, tag->end_name, len-i); if(rval < 0) return rval; tag->end_name = 0; // clear end tag tag->end_len = 0; nest--; state = set_xstate(XST_GET_END_TAG); i = i+rval; // advance processed offset } NextChar: i++; }; //fprintf(stderr,"\r\nAfter xml_parse\n"); return i; }
static int probe_udf(SECTION *section, int level, int sector_size) { unsigned char *buffer; u4 count, addr, sect; int seen_primary = 0; int seen_logical = 0; int i; char s[256]; /* first read the Anchor Volume Descriptor Pointer @ sector 256 */ if (get_buffer(section, 256 * sector_size, 512, (void **)&buffer) < 512) return 0; if (!validate_tag(buffer, 256)) return 0; /* tag identifier */ if (get_le_short(buffer) != 2) return 0; print_line(level, "UDF file system"); print_line(level + 1, "Sector size %d bytes", sector_size); /* get the Volume Descriptor Area */ count = get_le_long(buffer + 16) / sector_size; addr = get_le_long(buffer + 20); /* look for a Logical Volume Descriptor */ for (i = 0; i < count; i++) { sect = addr + i; if (get_buffer(section, (u8)sect * sector_size, 512, (void **)&buffer) < 512) break; if (!validate_tag(buffer, sect)) continue; /* switch by tag identifier */ switch (get_le_short(buffer)) { case 1: /* Primary Volume Descriptor */ if (!seen_primary) { seen_primary = 1; if (buffer[24] == 8) { get_string(buffer + 25, 30, s); print_line(level+1, "Volume name \"%s\"", s); } else if (buffer[24] == 16) { format_utf16_le(buffer + 25, 30, s); print_line(level+1, "Volume name \"%s\"", s); } else { print_line(level+1, "Volume name encoding not supported"); } } break; case 6: /* Logical Volume Descriptor */ if (!seen_logical) { seen_logical = 1; if (memcmp(buffer + 216+1, "*OSTA UDF Compliant", 19) == 0) { print_line(level+1, "UDF version %x.%02x", (int)buffer[216+25], (int)buffer[216+24]); } } break; } } if (!seen_primary) { print_line(level + 1, "Primary Volume Descriptor missing"); } return 1; /* some problems */ }