astring *image_info_astring(running_machine *machine, astring *string) { device_image_interface *image = NULL; astring_printf(string, "%s\n\n", machine->gamedrv->description); #if 0 if (mess_ram_size > 0) { char buf2[RAM_STRING_BUFLEN]; astring_catprintf(string, "RAM: %s\n\n", ram_string(buf2, mess_ram_size)); } #endif for (bool gotone = machine->m_devicelist.first(image); gotone; gotone = image->next(image)) { const char *name = image->filename(); if (name != NULL) { const char *base_filename; const char *info; char *base_filename_noextension; base_filename = image->basename(); base_filename_noextension = strip_extension(base_filename); /* display device type and filename */ astring_catprintf(string, "%s: %s\n", image->image_config().devconfig().name(), base_filename); /* display long filename, if present and doesn't correspond to name */ info = image->longname(); if (info && (!base_filename_noextension || mame_stricmp(info, base_filename_noextension))) astring_catprintf(string, "%s\n", info); /* display manufacturer, if available */ info = image->manufacturer(); if (info != NULL) { astring_catprintf(string, "%s", info); info = stripspace(image->year()); if (info && *info) astring_catprintf(string, ", %s", info); astring_catprintf(string,"\n"); } /* display playable information, if available */ info = image->playable(); if (info != NULL) astring_catprintf(string, "%s\n", info); if (base_filename_noextension != NULL) free(base_filename_noextension); } else { astring_catprintf(string, "%s: ---\n", image->image_config().devconfig().name()); } } return string; }
static DEVICE_RESET( ti99_pcoden ) { logerror("ti99_pcode: reset\n"); ti99_pcoden_state *pcode = get_safe_token(device); /* If the card is selected in the menu, register the card */ if (input_port_read(device->machine(), "EXTCARD") & EXT_PCODE) { device_t *peb = device->owner(); int success = mount_card(peb, device, &pcode_ncard, get_pebcard_config(device)->slot); if (!success) return; astring *region = new astring(); astring_assemble_3(region, device->tag(), ":", pcode_region); pcode->rom0 = device->machine().region(astring_c(region))->base(); pcode->rom1 = pcode->rom0 + 0x1000; pcode->rom2 = pcode->rom0 + 0x2000; pcode->grom = pcode->rom0 + 0x3000; pcode->bank_select = 0; pcode->selected = 0; astring *gromname = new astring(); for (int i=0; i < 8; i++) { astring_printf(gromname, "grom_%d", i); pcode->gromdev[i] = device->subdevice(astring_c(gromname)); } } }
static int generate_png_diff(const summary_file *curfile, const astring *destdir, const char *destname) { bitmap_t *bitmaps[MAX_COMPARES] = { NULL }; astring *srcimgname = astring_alloc(); astring *dstfilename = astring_alloc(); astring *tempname = astring_alloc(); bitmap_t *finalbitmap = NULL; int width, height, maxwidth; int bitmapcount = 0; int listnum, bmnum; core_file *file = NULL; file_error filerr; png_error pngerr; int error = -1; int starty; /* generate the common source filename */ astring_printf(dstfilename, "%s" PATH_SEPARATOR "%s", astring_c(destdir), destname); astring_printf(srcimgname, "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", curfile->name); /* open and load all unique bitmaps */ for (listnum = 0; listnum < list_count; listnum++) if (curfile->matchbitmap[listnum] == listnum) { astring_printf(tempname, "%s" PATH_SEPARATOR "%s", lists[listnum].dir, astring_c(srcimgname)); /* open the source image */ filerr = core_fopen(astring_c(tempname), OPEN_FLAG_READ, &file); if (filerr != FILERR_NONE) goto error; /* load the source image */ pngerr = png_read_bitmap(file, &bitmaps[bitmapcount++]); core_fclose(file); if (pngerr != PNGERR_NONE) goto error; } /* if there's only one unique bitmap, skip it */ if (bitmapcount <= 1) goto error; /* determine the size of the final bitmap */ height = width = 0; maxwidth = bitmaps[0]->width; for (bmnum = 1; bmnum < bitmapcount; bmnum++) { int curwidth; /* determine the maximal width */ maxwidth = MAX(maxwidth, bitmaps[bmnum]->width); curwidth = bitmaps[0]->width + BITMAP_SPACE + maxwidth + BITMAP_SPACE + maxwidth; width = MAX(width, curwidth); /* add to the height */ height += MAX(bitmaps[0]->height, bitmaps[bmnum]->height); if (bmnum != 1) height += BITMAP_SPACE; } /* allocate the final bitmap */ finalbitmap = bitmap_alloc(width, height, BITMAP_FORMAT_ARGB32); if (finalbitmap == NULL) goto error; /* now copy and compare each set of bitmaps */ starty = 0; for (bmnum = 1; bmnum < bitmapcount; bmnum++) { bitmap_t *bitmap1 = bitmaps[0]; bitmap_t *bitmap2 = bitmaps[bmnum]; int curheight = MAX(bitmap1->height, bitmap2->height); int x, y; /* iterate over rows in these bitmaps */ for (y = 0; y < curheight; y++) { UINT32 *src1 = (y < bitmap1->height) ? BITMAP_ADDR32(bitmap1, y, 0) : NULL; UINT32 *src2 = (y < bitmap2->height) ? BITMAP_ADDR32(bitmap2, y, 0) : NULL; UINT32 *dst1 = BITMAP_ADDR32(finalbitmap, starty + y, 0); UINT32 *dst2 = BITMAP_ADDR32(finalbitmap, starty + y, bitmap1->width + BITMAP_SPACE); UINT32 *dstdiff = BITMAP_ADDR32(finalbitmap, starty + y, bitmap1->width + BITMAP_SPACE + maxwidth + BITMAP_SPACE); /* now iterate over columns */ for (x = 0; x < maxwidth; x++) { int pix1 = -1, pix2 = -2; if (src1 != NULL && x < bitmap1->width) pix1 = dst1[x] = src1[x]; if (src2 != NULL && x < bitmap2->width) pix2 = dst2[x] = src2[x]; dstdiff[x] = (pix1 != pix2) ? 0xffffffff : 0xff000000; } } /* update the starting Y position */ starty += BITMAP_SPACE + MAX(bitmap1->height, bitmap2->height); } /* write the final PNG */ filerr = core_fopen(astring_c(dstfilename), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file); if (filerr != FILERR_NONE) goto error; pngerr = png_write_bitmap(file, NULL, finalbitmap, 0, NULL); core_fclose(file); if (pngerr != PNGERR_NONE) goto error; /* if we get here, we are error free */ error = 0; error: if (finalbitmap != NULL) bitmap_free(finalbitmap); for (bmnum = 0; bmnum < bitmapcount; bmnum++) if (bitmaps[bmnum] != NULL) bitmap_free(bitmaps[bmnum]); if (error) osd_rmfile(astring_c(dstfilename)); astring_free(dstfilename); astring_free(srcimgname); astring_free(tempname); return error; }
static int compare_screenshots(summary_file *curfile) { bitmap_t *bitmaps[MAX_COMPARES]; int unique[MAX_COMPARES]; int numunique = 0; int listnum; /* iterate over all files and load their bitmaps */ for (listnum = 0; listnum < list_count; listnum++) { bitmaps[listnum] = NULL; if (curfile->status[listnum] == STATUS_SUCCESS) { astring *fullname = astring_alloc(); file_error filerr; core_file *file; /* get the filename for the image */ astring_printf(fullname, "%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "%s" PATH_SEPARATOR "final.png", lists[listnum].dir, curfile->name); /* open the file */ filerr = core_fopen(astring_c(fullname), OPEN_FLAG_READ, &file); /* if that failed, look in the old location */ if (filerr != FILERR_NONE) { /* get the filename for the image */ astring_printf(fullname, "%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name); /* open the file */ filerr = core_fopen(astring_c(fullname), OPEN_FLAG_READ, &file); } /* if that worked, load the file */ if (filerr == FILERR_NONE) { png_read_bitmap(file, &bitmaps[listnum]); core_fclose(file); } astring_free(fullname); } } /* now find all the different bitmap types */ for (listnum = 0; listnum < list_count; listnum++) { curfile->matchbitmap[listnum] = 0xff; if (bitmaps[listnum] != NULL) { bitmap_t *this_bitmap = bitmaps[listnum]; int compnum; /* compare against all unique bitmaps */ for (compnum = 0; compnum < numunique; compnum++) { bitmap_t *base_bitmap = bitmaps[unique[compnum]]; int bitmaps_differ; int x, y; /* if the sizes are different, we differ; otherwise start off assuming we are the same */ bitmaps_differ = (this_bitmap->width != base_bitmap->width || this_bitmap->height != base_bitmap->height); /* compare scanline by scanline */ for (y = 0; y < this_bitmap->height && !bitmaps_differ; y++) { UINT32 *base = BITMAP_ADDR32(base_bitmap, y, 0); UINT32 *curr = BITMAP_ADDR32(this_bitmap, y, 0); /* scan the scanline */ for (x = 0; x < this_bitmap->width; x++) if (*base++ != *curr++) break; bitmaps_differ = (x != this_bitmap->width); } /* if we matched, remember which listnum index we matched, and stop */ if (!bitmaps_differ) { curfile->matchbitmap[listnum] = unique[compnum]; break; } /* if different from the first unique entry, adjust the status */ if (bitmaps_differ && compnum == 0) curfile->status[listnum] = STATUS_SUCCESS_DIFFERENT; } /* if we're unique, add ourselves to the list */ if (compnum >= numunique) { unique[numunique++] = listnum; curfile->matchbitmap[listnum] = listnum; continue; } } } /* free the bitmaps */ for (listnum = 0; listnum < list_count; listnum++) if (bitmaps[listnum] != NULL) bitmap_free(bitmaps[listnum]); /* if all screenshots matched, we're good */ if (numunique == 1) return BUCKET_GOOD; /* if the last screenshot matched the first unique one, we're good but changed */ if (curfile->matchbitmap[listnum - 1] == unique[0]) return BUCKET_GOOD_BUT_CHANGED_SCREENSHOTS; /* otherwise we're just changed */ return BUCKET_CHANGED; }
static void output_report(const astring *dirname, const astring *tempheader, const astring *tempfooter, summary_file *filelist) { summary_file *buckethead[BUCKET_COUNT], **buckettailptr[BUCKET_COUNT]; summary_file *curfile; astring *title = astring_dupc("MAME Regressions"); astring *tempname = astring_alloc(); int listnum, bucknum; core_file *indexfile; int count = 0, total; /* initialize the lists */ for (bucknum = 0; bucknum < BUCKET_COUNT; bucknum++) { buckethead[bucknum] = NULL; buckettailptr[bucknum] = &buckethead[bucknum]; } /* compute the total number of files */ total = 0; for (curfile = filelist; curfile != NULL; curfile = curfile->next) total++; /* first bucketize the games */ for (curfile = filelist; curfile != NULL; curfile = curfile->next) { int statcount[STATUS_COUNT] = { 0 }; int bucket = BUCKET_UNKNOWN; int unique_codes = 0; int first_valid; /* print status */ if (++count % 100 == 0) fprintf(stderr, "Processing file %d/%d\n", count, total); /* find the first valid entry */ for (first_valid = 0; curfile->status[first_valid] == STATUS_NOT_PRESENT; first_valid++) ; /* do we need to output anything? */ for (listnum = first_valid; listnum < list_count; listnum++) if (statcount[curfile->status[listnum]]++ == 0) unique_codes++; /* were we consistent? */ if (unique_codes == 1) { /* were we consistently ok? */ if (curfile->status[first_valid] == STATUS_SUCCESS) bucket = compare_screenshots(curfile); /* must have been consistently erroring */ else bucket = BUCKET_CONSISTENT_ERROR; } /* ok, we're not consistent; could be a number of things */ else { /* were we ok at the start and end but not in the middle? */ if (curfile->status[first_valid] == STATUS_SUCCESS && curfile->status[list_count - 1] == STATUS_SUCCESS) bucket = BUCKET_GOOD_BUT_CHANGED; /* did we go from good to bad? */ else if (curfile->status[first_valid] == STATUS_SUCCESS) bucket = BUCKET_REGRESSED; /* did we go from bad to good? */ else if (curfile->status[list_count - 1] == STATUS_SUCCESS) bucket = BUCKET_IMPROVED; /* must have had multiple errors */ else bucket = BUCKET_MULTI_ERROR; } /* add us to the appropriate list */ *buckettailptr[bucket] = curfile; buckettailptr[bucket] = &curfile->next; } /* terminate all the lists */ for (bucknum = 0; bucknum < BUCKET_COUNT; bucknum++) *buckettailptr[bucknum] = NULL; /* output header */ astring_printf(tempname, "%s" PATH_SEPARATOR "%s", astring_c(dirname), "index.html"); indexfile = create_file_and_output_header(tempname, tempheader, title); if (indexfile == NULL) { fprintf(stderr, "Error creating file '%s'\n", astring_c(tempname)); astring_free(tempname); astring_free(title); return; } /* iterate over buckets and output them */ for (bucknum = 0; bucknum < ARRAY_LENGTH(bucket_output_order); bucknum++) { int curbucket = bucket_output_order[bucknum]; if (buckethead[curbucket] != NULL) { fprintf(stderr, "Outputting bucket: %s\n", bucket_name[curbucket]); append_driver_list_table(bucket_name[curbucket], dirname, indexfile, buckethead[curbucket], tempheader, tempfooter); } } /* output footer */ output_footer_and_close_file(indexfile, tempfooter, title); astring_free(tempname); astring_free(title); }
static void create_linked_file(const astring *dirname, const summary_file *curfile, const summary_file *prevfile, const summary_file *nextfile, const char *pngfile, const astring *tempheader, const astring *tempfooter) { astring *linkname = astring_alloc(); astring *filename = astring_alloc(); astring *title = astring_alloc(); core_file *linkfile; int listnum; /* create the filename */ astring_printf(filename, "%s.html", curfile->name); /* output header */ astring_printf(title, "%s Regressions (%s)", curfile->name, curfile->source); astring_printf(linkname, "%s" PATH_SEPARATOR "%s", astring_c(dirname), astring_c(filename)); linkfile = create_file_and_output_header(linkname, tempheader, title); if (linkfile == NULL) { fprintf(stderr, "Error creating file '%s'\n", astring_c(filename)); astring_free(title); astring_free(filename); astring_free(linkname); return; } /* link to the previous/next entries */ core_fprintf(linkfile, "\t<p>\n"); core_fprintf(linkfile, "\t<table width=\"100%%\">\n"); core_fprintf(linkfile, "\t\t<td align=\"left\" width=\"40%%\" style=\"border:none\">"); if (prevfile != NULL) core_fprintf(linkfile, "<a href=\"%s.html\"><< %s (%s)</a>", prevfile->name, prevfile->name, prevfile->source); core_fprintf(linkfile, "</td>\n"); core_fprintf(linkfile, "\t\t<td align=\"center\" width=\"20%%\" style=\"border:none\"><a href=\"index.html\">Home</a></td>\n"); core_fprintf(linkfile, "\t\t<td align=\"right\" width=\"40%%\" style=\"border:none\">"); if (nextfile != NULL) core_fprintf(linkfile, "<a href=\"%s.html\">%s (%s) >></a>", nextfile->name, nextfile->name, nextfile->source); core_fprintf(linkfile, "</td>\n"); core_fprintf(linkfile, "\t</table>\n"); core_fprintf(linkfile, "\t</p>\n"); /* output data for each one */ for (listnum = 0; listnum < list_count; listnum++) { int imageindex = -1; /* generate the HTML */ core_fprintf(linkfile, "\n\t<h2>%s</h2>\n", lists[listnum].version); core_fprintf(linkfile, "\t<p>\n"); core_fprintf(linkfile, "\t<b>Status:</b> %s\n", status_text[curfile->status[listnum]]); if (pngfile != NULL) imageindex = get_unique_index(curfile, listnum); if (imageindex != -1) core_fprintf(linkfile, " [%d]", imageindex); core_fprintf(linkfile, "\t</p>\n"); if (curfile->text[listnum] != NULL) { core_fprintf(linkfile, "\t<p>\n"); core_fprintf(linkfile, "\t<b>Errors:</b>\n"); core_fprintf(linkfile, "\t<pre>%s</pre>\n", curfile->text[listnum]); core_fprintf(linkfile, "\t</p>\n"); } } /* output link to the image */ if (pngfile != NULL) { core_fprintf(linkfile, "\n\t<h2>Screenshot Comparisons</h2>\n"); core_fprintf(linkfile, "\t<p>\n"); core_fprintf(linkfile, "\t<img src=\"%s\" />\n", pngfile); core_fprintf(linkfile, "\t</p>\n"); } /* output footer */ output_footer_and_close_file(linkfile, tempfooter, title); astring_free(title); astring_free(filename); astring_free(linkname); }
astring *image_info_astring(running_machine &machine, astring *string) { device_image_interface *image = NULL; astring_printf(string, "%s\n\n", machine.system().description); #if 0 if (mess_ram_size > 0) { char buf2[RAM_STRING_BUFLEN]; astring_catprintf(string, "RAM: %s\n\n", ram_string(buf2, mess_ram_size)); } #endif for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) { const char *name = image->filename(); if (name != NULL) { const char *base_filename; const char *info; char *base_filename_noextension; base_filename = image->basename(); base_filename_noextension = strip_extension(base_filename); /* display device type and filename */ astring_catprintf(string, "%s: %s\n", image->device().name(), base_filename); /* display long filename, if present and doesn't correspond to name */ info = image->longname(); if (info && (!base_filename_noextension || mame_stricmp(info, base_filename_noextension))) astring_catprintf(string, "%s\n", info); /* display manufacturer, if available */ info = image->manufacturer(); if (info != NULL) { astring_catprintf(string, "%s", info); info = stripspace(image->year()); if (info && *info) astring_catprintf(string, ", %s", info); astring_catprintf(string,"\n"); } /* display supported information, if available */ switch(image->supported()) { case SOFTWARE_SUPPORTED_NO : astring_catprintf(string, "Not supported\n"); break; case SOFTWARE_SUPPORTED_PARTIAL : astring_catprintf(string, "Partialy supported\n"); break; default : break; } if (base_filename_noextension != NULL) free(base_filename_noextension); } else { astring_catprintf(string, "%s: ---\n", image->device().name()); } } return string; }
static int recurse_dir(int srcrootlen, const astring *srcdir) { static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE }; int result = 0; int entindex; /* iterate first over directories, then over files */ for (entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++) { osd_dir_entry_type entry_type = typelist[entindex]; const osd_directory_entry *entry; list_entry **listarray = NULL; list_entry *list = NULL; list_entry *curlist; osd_directory *dir; int found = 0; /* open the directory and iterate through it */ dir = osd_opendir(astring_c(srcdir)); if (dir == NULL) { result = 1; goto error; } /* build up the list of files */ while ((entry = osd_readdir(dir)) != NULL) if (entry->type == entry_type && entry->name[0] != '.') { list_entry *lentry = (list_entry *)malloc(sizeof(*lentry)); lentry->name = astring_dupc(entry->name); lentry->next = list; list = lentry; found++; } /* close the directory */ osd_closedir(dir); /* skip if nothing found */ if (found == 0) continue; /* allocate memory for sorting */ listarray = (list_entry **)malloc(sizeof(list_entry *) * found); found = 0; for (curlist = list; curlist != NULL; curlist = curlist->next) listarray[found++] = curlist; /* sort the list */ qsort(listarray, found, sizeof(listarray[0]), compare_list_entries); /* rebuild the list */ list = NULL; while (--found >= 0) { listarray[found]->next = list; list = listarray[found]; } free(listarray); /* iterate through each file */ for (curlist = list; curlist != NULL && result == 0; curlist = curlist->next) { astring *srcfile; /* build the source filename */ srcfile = astring_alloc(); astring_printf(srcfile, "%s%c%s", astring_c(srcdir), PATH_SEPARATOR[0], astring_c(curlist->name)); /* if we have a file, output it */ if (entry_type == ENTTYPE_FILE) { /* make sure we care, first */ if (core_filename_ends_with(astring_c(curlist->name), ".c")) { tagmap *depend_map = tagmap_alloc(); tagmap_entry *map_entry; file_entry *file; astring *target; int taghash; /* find dependencies */ file = compute_dependencies(srcrootlen, srcfile); recurse_dependencies(file, depend_map); /* convert the target from source to object (makes assumptions about rules) */ target = astring_dup(file->name); astring_replacec(target, 0, "src/", "$(OBJ)/"); astring_replacec(target, 0, ".c", ".o"); printf("\n%s : \\\n", astring_c(target)); /* iterate over the hashed dependencies and output them as well */ for (taghash = 0; taghash < TAGMAP_HASH_SIZE; taghash++) for (map_entry = depend_map->table[taghash]; map_entry != NULL; map_entry = map_entry->next) printf("\t%s \\\n", astring_c((astring *)map_entry->object)); astring_free(target); tagmap_free(depend_map); } } /* if we have a directory, recurse */ else result = recurse_dir(srcrootlen, srcfile); /* free memory for the names */ astring_free(srcfile); } /* free all the allocated entries */ while (list != NULL) { list_entry *next = list->next; astring_free((astring *)list->name); free(list); list = next; } } error: return result; }
static int recurse_dir(int srcrootlen, int dstrootlen, const astring *srcdir, const astring *dstdir) { static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE }; const astring *srcdir_subpath; core_file *indexfile = NULL; astring *indexname; int result = 0; int entindex; /* extract a normalized subpath */ srcdir_subpath = normalized_subpath(srcdir, srcrootlen + 1); if (srcdir_subpath == NULL) return 1; /* create an index file */ indexname = astring_alloc(); astring_printf(indexname, "%s%c%s", astring_c(dstdir), PATH_SEPARATOR[0], "index.html"); indexfile = create_file_and_output_header(indexname, "MAME Source Code", astring_c(srcdir_subpath)); astring_free(indexname); /* output the directory navigation */ core_fprintf(indexfile, "<h3>Viewing Directory: "); output_path_as_links(indexfile, srcdir_subpath, TRUE, FALSE); core_fprintf(indexfile, "</h3>"); astring_free((astring *)srcdir_subpath); /* iterate first over directories, then over files */ for (entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++) { osd_dir_entry_type entry_type = typelist[entindex]; const osd_directory_entry *entry; list_entry *list = NULL; list_entry **listarray; list_entry *curlist; osd_directory *dir; int found = 0; /* open the directory and iterate through it */ dir = osd_opendir(astring_c(srcdir)); if (dir == NULL) { result = 1; goto error; } /* build up the list of files */ while ((entry = osd_readdir(dir)) != NULL) if (entry->type == entry_type && entry->name[0] != '.') { list_entry *lentry = malloc(sizeof(*lentry)); lentry->name = astring_dupc(entry->name); lentry->next = list; list = lentry; found++; } /* close the directory */ osd_closedir(dir); /* skip if nothing found */ if (found == 0) continue; /* allocate memory for sorting */ listarray = malloc(sizeof(list_entry *) * found); found = 0; for (curlist = list; curlist != NULL; curlist = curlist->next) listarray[found++] = curlist; /* sort the list */ qsort(listarray, found, sizeof(listarray[0]), compare_list_entries); /* rebuild the list */ list = NULL; while (--found >= 0) { listarray[found]->next = list; list = listarray[found]; } /* iterate through each file */ for (curlist = list; curlist != NULL && result == 0; curlist = curlist->next) { astring *srcfile, *dstfile; /* add a header */ if (curlist == list) core_fprintf(indexfile, "\t<h2>%s</h2>\n\t<ul>\n", (entry_type == ENTTYPE_DIR) ? "Directories" : "Files"); /* build the source filename */ srcfile = astring_alloc(); astring_printf(srcfile, "%s%c%s", astring_c(srcdir), PATH_SEPARATOR[0], astring_c(curlist->name)); /* if we have a file, output it */ dstfile = astring_alloc(); if (entry_type == ENTTYPE_FILE) { file_type type = FILE_TYPE_INVALID; int extnum; /* make sure we care, first */ for (extnum = 0; extnum < ARRAY_LENGTH(extension_lookup); extnum++) if (core_filename_ends_with(astring_c(curlist->name), extension_lookup[extnum].extension)) { type = extension_lookup[extnum].type; break; } /* if we got a valid file, process it */ if (type != FILE_TYPE_INVALID) { astring_printf(dstfile, "%s%c%s.html", astring_c(dstdir), PATH_SEPARATOR[0], astring_c(curlist->name)); if (indexfile != NULL) core_fprintf(indexfile, "\t<li><a href=\"%s.html\">%s</a></li>\n", astring_c(curlist->name), astring_c(curlist->name)); result = output_file(type, srcrootlen, dstrootlen, srcfile, dstfile, astring_cmp(srcdir, dstdir) == 0); } } /* if we have a directory, recurse */ else { astring_printf(dstfile, "%s%c%s", astring_c(dstdir), PATH_SEPARATOR[0], astring_c(curlist->name)); if (indexfile != NULL) core_fprintf(indexfile, "\t<li><a href=\"%s/index.html\">%s/</a></li>\n", astring_c(curlist->name), astring_c(curlist->name)); result = recurse_dir(srcrootlen, dstrootlen, srcfile, dstfile); } /* free memory for the names */ astring_free(srcfile); astring_free(dstfile); } /* close the list if we found some stuff */ if (list != NULL) core_fprintf(indexfile, "\t</ul>\n"); /* free all the allocated entries */ while (list != NULL) { list_entry *next = list->next; astring_free((astring *)list->name); free(list); list = next; } } error: if (indexfile != NULL) output_footer_and_close_file(indexfile); return result; }