Exemplo n.º 1
0
static int output_file(file_type type, int srcrootlen, int dstrootlen, std::string &srcfile, std::string &dstfile, bool link_to_file, std::string &tempheader, std::string &tempfooter)
{
	// extract a normalized subpath
	std::string srcfile_subpath;
	normalized_subpath(srcfile_subpath, srcfile, srcrootlen + 1);

	fprintf(stderr, "Processing %s\n", srcfile_subpath.c_str());

	// set some defaults
	bool color_quotes = false;
	const char *comment_start = "";
	const char *comment_start_esc = "";
	const char *comment_end = "";
	const char *comment_end_esc = "";
	const char *comment_inline = "";
	const char *comment_inline_esc = "";
	const char *token_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_#";
	const token_entry *token_table = dummy_token_table;

	// based on the file type, set the comment info
	switch (type)
	{
		case FILE_TYPE_C:
			color_quotes = true;
			comment_start = comment_start_esc = "/*";
			comment_end = comment_end_esc = "*/";
			comment_inline = comment_inline_esc = "//";
			token_table = c_token_table;
			break;

		case FILE_TYPE_MAKE:
			color_quotes = true;
			comment_inline = comment_inline_esc = "#";
			break;

		case FILE_TYPE_XML:
			color_quotes = true;
			comment_start = "<!--";
			comment_start_esc = "&lt;!--";
			comment_end = "-->";
			comment_end_esc = "--&gt;";
			break;

		default:
		case FILE_TYPE_TEXT:
			break;
	}

	// make the token lookup table
	bool is_token[256];
	memset(is_token, 0, sizeof(is_token));
	for (int toknum = 0; token_chars[toknum] != 0; toknum++)
		is_token[(uint8_t)token_chars[toknum]] = true;

	// open the source file
	util::core_file::ptr src;
	if (util::core_file::open(srcfile, OPEN_FLAG_READ, src) != osd_file::error::NONE)
	{
		fprintf(stderr, "Unable to read file '%s'\n", srcfile.c_str());
		return 1;
	}

	// open the output file
	util::core_file::ptr dst = create_file_and_output_header(dstfile, tempheader, srcfile_subpath);
	if (dst == nullptr)
	{
		fprintf(stderr, "Unable to write file '%s'\n", dstfile.c_str());
		return 1;
	}

	// output the directory navigation
	dst->printf("<h3>Viewing File: ");
	output_path_as_links(*dst, srcfile_subpath, false, link_to_file);
	dst->printf("</h3>");

	// start with some tags
	dst->printf("\t<pre class=\"source\">\n");

	// iterate over lines in the source file
	int linenum = 1;
	bool in_comment = false;
	char srcline[4096];
	std::ostringstream dstline;
	while (src->gets(srcline, ARRAY_LENGTH(srcline)) != nullptr)
	{
		// start with the line number
		dstline.str("");
		util::stream_format(dstline, "<span class=\"linenum\">%5d</span>&nbsp;&nbsp;", linenum++);

		// iterate over characters in the source line
		bool escape = false;
		bool in_quotes = false;
		bool in_inline_comment = false;
		bool last_token_was_include = false;
		bool last_was_token = false;
		bool quotes_are_linked = false;
		uint8_t curquote = 0;
		int curcol = 0;
		for (char *srcptr = srcline; *srcptr != 0; )
		{
			uint8_t ch = *srcptr++;

			// track whether or not we are within an extended (C-style) comment
			if (!in_quotes && !in_inline_comment)
			{
				if (!in_comment && ch == comment_start[0] && strncmp(srcptr - 1, comment_start, strlen(comment_start)) == 0)
				{
					util::stream_format(dstline, "<span class=\"comment\">%s", comment_start_esc);
					curcol += strlen(comment_start);
					srcptr += strlen(comment_start) - 1;
					ch = 0;
					in_comment = true;
				}
				else if (in_comment && ch == comment_end[0] && strncmp(srcptr - 1, comment_end, strlen(comment_end)) == 0)
				{
					util::stream_format(dstline, "%s</span>", comment_end_esc);
					curcol += strlen(comment_end);
					srcptr += strlen(comment_end) - 1;
					ch = 0;
					in_comment = false;
				}
			}

			// track whether or not we are within an inline (C++-style) comment
			if (!in_quotes && !in_comment && !in_inline_comment && ch == comment_inline[0] && strncmp(srcptr - 1, comment_inline, strlen(comment_inline)) == 0)
			{
				util::stream_format(dstline, "<span class=\"comment\">%s", comment_inline_esc);
				curcol += strlen(comment_inline);
				srcptr += strlen(comment_inline) - 1;
				ch = 0;
				in_inline_comment = true;
			}

			// if this is the start of a new token, see if we want to color it
			if (!in_quotes && !in_comment && !in_inline_comment && !last_was_token && is_token[ch])
			{
				const token_entry *curtoken;
				char *temp = srcptr;
				int toklength;

				// find the end of the token
				while (*temp != 0 && is_token[(uint8_t)*temp])
					temp++;
				toklength = temp - (srcptr - 1);

				// scan the token table
				last_token_was_include = false;
				for (curtoken = token_table; curtoken->token != nullptr; curtoken++)
					if (strncmp(srcptr - 1, curtoken->token, toklength) == 0 && strlen(curtoken->token) == toklength)
					{
						util::stream_format(dstline, "<span class=\"%s\">%s</span>", curtoken->color, curtoken->token);
						curcol += strlen(curtoken->token);
						srcptr += strlen(curtoken->token) - 1;
						ch = 0;

						// look for include tokens specially
						if (type == FILE_TYPE_C && strcmp(curtoken->token, "#include") == 0)
							last_token_was_include = true;
						break;
					}
			}
			last_was_token = is_token[ch];

			// if we hit a tab, expand it
			if (ch == 0x09)
			{
				// compute how many spaces
				int spaces = 4 - curcol % 4;
				while (spaces--)
				{
					dstline.put(' ');
					curcol++;
				}
			}

			// otherwise, copy the source character
			else if (ch != 0x0a && ch != 0x0d && ch != 0)
			{
				// track opening quotes
				if (!in_comment && !in_inline_comment && !in_quotes && (ch == '"' || ch == '\''))
				{
					if (color_quotes)
						util::stream_format(dstline, "<span class=\"string\">%c", ch);
					else
						dstline.put(ch);
					in_quotes = true;
					curquote = ch;

					// handle includes
					if (last_token_was_include)
					{
						char *endquote = strchr(srcptr, ch);
						if (endquote != nullptr)
						{
							std::string filename(srcptr, endquote - srcptr);
							std::string target;
							if (find_include_file(target, srcrootlen, dstrootlen, srcfile, dstfile, filename))
							{
								util::stream_format(dstline, "<a href=\"%s\">", target.c_str());
								quotes_are_linked = true;
							}
						}
					}
				}

				// track closing quotes
				else if (!in_comment && !in_inline_comment && in_quotes && (ch == curquote) && !escape)
				{
					if (quotes_are_linked)
						dstline << "</a>";
					if (color_quotes)
						util::stream_format(dstline, "%c</span>", ch);
					else
						dstline.put(ch);
					in_quotes = false;
					curquote = 0;
					quotes_are_linked = false;
				}

				// else just output the current character
				else if (ch == '&')
					dstline << "&amp;";
				else if (ch == '<')
					dstline << "&lt;";
				else if (ch == '>')
					dstline << "&gt;";
				else
					dstline.put(ch);
				curcol++;
			}

			// Update escape state
			if (in_quotes)
				escape = (ch == '\\' && type == FILE_TYPE_C) ? !escape : false;
		}

		// finish inline comments
		if (in_inline_comment)
		{
			dstline << "</span>";
			in_inline_comment = false;
		}

		// append a break and move on
		dstline.put('\n');
		dst->puts(dstline.str().c_str());
	}

	// close tags
	dst->printf("\t</pre>\n");

	// close the file
	output_footer_and_close_file(std::move(dst), tempfooter, srcfile_subpath);
	return 0;
}
Exemplo n.º 2
0
static void create_linked_file(std::string &dirname, const summary_file *curfile, const summary_file *prevfile, const summary_file *nextfile, const char *pngfile, std::string &tempheader, std::string &tempfooter)
{
	std::string linkname;
	std::string filename;
	std::string title;
	util::core_file::ptr linkfile;
	int listnum;

	/* create the filename */
	filename = string_format("%s.html", curfile->name);

	/* output header */
	title = string_format("%s Regressions (%s)", curfile->name, curfile->source);
	linkname = string_format("%s" PATH_SEPARATOR "%s", dirname.c_str(), filename.c_str());
	linkfile = create_file_and_output_header(linkname, tempheader, title);
	if (linkfile == nullptr)
	{
		fprintf(stderr, "Error creating file '%s'\n", filename.c_str());
		return;
	}

	/* link to the previous/next entries */
	linkfile->printf("\t<p>\n");
	linkfile->printf("\t<table width=\"100%%\">\n");
	linkfile->printf("\t\t<td align=\"left\" width=\"40%%\" style=\"border:none\">");
	if (prevfile != nullptr)
		linkfile->printf("<a href=\"%s.html\"><< %s (%s)</a>", prevfile->name, prevfile->name, prevfile->source);
	linkfile->printf("</td>\n");
	linkfile->printf("\t\t<td align=\"center\" width=\"20%%\" style=\"border:none\"><a href=\"index.html\">Home</a></td>\n");
	linkfile->printf("\t\t<td align=\"right\" width=\"40%%\" style=\"border:none\">");
	if (nextfile != nullptr)
		linkfile->printf("<a href=\"%s.html\">%s (%s) >></a>", nextfile->name, nextfile->name, nextfile->source);
	linkfile->printf("</td>\n");
	linkfile->printf("\t</table>\n");
	linkfile->printf("\t</p>\n");

	/* output data for each one */
	for (listnum = 0; listnum < list_count; listnum++)
	{
		int imageindex = -1;

		/* generate the HTML */
		linkfile->printf("\n\t<h2>%s</h2>\n", lists[listnum].version);
		linkfile->printf("\t<p>\n");
		linkfile->printf("\t<b>Status:</b> %s\n", status_text[curfile->status[listnum]]);
		if (pngfile != nullptr)
			imageindex = get_unique_index(curfile, listnum);
		if (imageindex != -1)
			linkfile->printf(" [%d]", imageindex);
		linkfile->printf("\t</p>\n");
		if (curfile->text[listnum].length() != 0)
		{
			linkfile->printf("\t<p>\n");
			linkfile->printf("\t<b>Errors:</b>\n");
			linkfile->printf("\t<pre>%s</pre>\n", curfile->text[listnum].c_str());
			linkfile->printf("\t</p>\n");
		}
	}

	/* output link to the image */
	if (pngfile != nullptr)
	{
		linkfile->printf("\n\t<h2>Screenshot Comparisons</h2>\n");
		linkfile->printf("\t<p>\n");
		linkfile->printf("\t<img src=\"%s\" />\n", pngfile);
		linkfile->printf("\t</p>\n");
	}

	/* output footer */
	output_footer_and_close_file(std::move(linkfile), tempfooter, title);
}
Exemplo n.º 3
0
static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std::string &dstdir, std::string &tempheader, std::string &tempfooter)
{
	static const osd::directory::entry::entry_type typelist[] = { osd::directory::entry::entry_type::DIR, osd::directory::entry::entry_type::FILE };

	// extract a normalized subpath
	std::string srcdir_subpath;
	normalized_subpath(srcdir_subpath, srcdir, srcrootlen + 1);

	// create an index file
	std::string indexname;
	indexname = string_format("%s%c%s", dstdir.c_str(), PATH_SEPARATOR[0], "index.html");
	util::core_file::ptr indexfile = create_file_and_output_header(indexname, tempheader, srcdir_subpath);

	// output the directory navigation
	indexfile->printf("<h3>Viewing Directory: ");
	output_path_as_links(*indexfile, srcdir_subpath, true, false);
	indexfile->printf("</h3>");

	// iterate first over directories, then over files
	int result = 0;
	for (int entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++)
	{
		auto entry_type = typelist[entindex];

		// open the directory and iterate through it
		auto dir = osd::directory::open(srcdir.c_str());
		if (dir == nullptr)
		{
			result = 1;
			break;
		}

		// build up the list of files
		const osd::directory::entry *entry;
		int found = 0;
		list_entry *list = nullptr;
		while ((entry = dir->read()) != nullptr)
			if (entry->type == entry_type && entry->name[0] != '.')
			{
				auto lentry = new list_entry;
				lentry->name.assign(entry->name);
				lentry->next = list;
				list = lentry;
				found++;
			}

		// close the directory
		dir.reset();

		// skip if nothing found
		if (found == 0)
			continue;

		// allocate memory for sorting
		auto listarray = new list_entry *[found];
		found = 0;
		for (list_entry *curlist = list; curlist != nullptr; curlist = curlist->next)
			listarray[found++] = curlist;

		// sort the list
		qsort(listarray, found, sizeof(listarray[0]), compare_list_entries);

		// rebuild the list
		list = nullptr;
		while (--found >= 0)
		{
			listarray[found]->next = list;
			list = listarray[found];
		}
		delete[] listarray;

		// iterate through each file
		for (list_entry *curlist = list; curlist != nullptr && result == 0; curlist = curlist->next)
		{
			// add a header
			if (curlist == list)
				indexfile->printf("\t<h2>%s</h2>\n\t<ul>\n", (entry_type == osd::directory::entry::entry_type::DIR) ? "Directories" : "Files");

			// build the source filename
			std::string srcfile;
			srcfile = string_format("%s%c%s", srcdir.c_str(), PATH_SEPARATOR[0], curlist->name.c_str());

			// if we have a file, output it
			std::string dstfile;
			if (entry_type == osd::directory::entry::entry_type::FILE)
			{
				// make sure we care, first
				file_type type = FILE_TYPE_INVALID;
				for (auto & elem : extension_lookup)
					if (core_filename_ends_with(curlist->name, elem.extension))
					{
						type = elem.type;
						break;
					}

				// if we got a valid file, process it
				if (type != FILE_TYPE_INVALID)
				{
					dstfile = string_format("%s%c%s.html", dstdir.c_str(), PATH_SEPARATOR[0], curlist->name.c_str());
					if (indexfile != nullptr)
						indexfile->printf("\t<li><a href=\"%s.html\">%s</a></li>\n", curlist->name.c_str(), curlist->name.c_str());
					result = output_file(type, srcrootlen, dstrootlen, srcfile, dstfile, srcdir.compare(dstdir) == 0, tempheader, tempfooter);
				}
			}

			// if we have a directory, recurse
			else
			{
				dstfile = string_format("%s%c%s", dstdir.c_str(), PATH_SEPARATOR[0], curlist->name.c_str());
				if (indexfile != nullptr)
					indexfile->printf("\t<li><a href=\"%s/index.html\">%s/</a></li>\n", curlist->name.c_str(), curlist->name.c_str());
				result = recurse_dir(srcrootlen, dstrootlen, srcfile, dstfile, tempheader, tempfooter);
			}
		}

		// close the list if we found some stuff
		if (list != nullptr)
			indexfile->printf("\t</ul>\n");

		// free all the allocated entries
		while (list != nullptr)
		{
			list_entry *next = list->next;
			delete list;
			list = next;
		}
	}

	if (indexfile != nullptr)
		output_footer_and_close_file(std::move(indexfile), tempfooter, srcdir_subpath);
	return result;
}
Exemplo n.º 4
0
static void output_report(std::string &dirname, std::string &tempheader, std::string &tempfooter, summary_file *filelist)
{
	summary_file *buckethead[BUCKET_COUNT], **buckettailptr[BUCKET_COUNT];
	summary_file *curfile;
	std::string title("MAME Regressions");
	std::string tempname;
	int listnum, bucknum;
	util::core_file::ptr indexfile;
	int count = 0, total;

	/* initialize the lists */
	for (bucknum = 0; bucknum < BUCKET_COUNT; bucknum++)
	{
		buckethead[bucknum] = nullptr;
		buckettailptr[bucknum] = &buckethead[bucknum];
	}

	/* compute the total number of files */
	total = 0;
	for (curfile = filelist; curfile != nullptr; curfile = curfile->next)
		total++;

	/* first bucketize the games */
	for (curfile = filelist; curfile != nullptr; 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] = nullptr;

	/* output header */
	tempname = string_format("%s" PATH_SEPARATOR "%s", dirname.c_str(), "index.html");
	indexfile = create_file_and_output_header(tempname, tempheader, title);
	if (!indexfile)
	{
		fprintf(stderr, "Error creating file '%s'\n", tempname.c_str());
		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] != nullptr)
		{
			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(std::move(indexfile), tempfooter, title);
}
Exemplo n.º 5
0
static int recurse_dir(int srcrootlen, int dstrootlen, astring &srcdir, astring &dstdir, astring &tempheader, astring &tempfooter)
{
	static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE };

	// extract a normalized subpath
	astring srcdir_subpath;
	normalized_subpath(srcdir_subpath, srcdir, srcrootlen + 1);

	// create an index file
	astring indexname;
	indexname.printf("%s%c%s", dstdir.cstr(), PATH_SEPARATOR[0], "index.html");
	core_file *indexfile = create_file_and_output_header(indexname, tempheader, srcdir_subpath);

	// output the directory navigation
	core_fprintf(indexfile, "<h3>Viewing Directory: ");
	output_path_as_links(indexfile, srcdir_subpath, true, false);
	core_fprintf(indexfile, "</h3>");

	// iterate first over directories, then over files
	int result = 0;
	for (int entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++)
	{
		osd_dir_entry_type entry_type = typelist[entindex];

		// open the directory and iterate through it
		osd_directory *dir = osd_opendir(srcdir);
		if (dir == NULL)
		{
			result = 1;
			break;
		}

		// build up the list of files
		const osd_directory_entry *entry;
		int found = 0;
		list_entry *list = NULL;
		while ((entry = osd_readdir(dir)) != NULL)
			if (entry->type == entry_type && entry->name[0] != '.')
			{
				list_entry *lentry = new list_entry;
				lentry->name.cpy(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
		list_entry **listarray = new list_entry *[found];
		found = 0;
		for (list_entry *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];
		}
		delete[] listarray;

		// iterate through each file
		for (list_entry *curlist = list; curlist != NULL && result == 0; curlist = curlist->next)
		{
			// 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
			astring srcfile;
			srcfile.printf("%s%c%s", srcdir.cstr(), PATH_SEPARATOR[0], curlist->name.cstr());

			// if we have a file, output it
			astring dstfile;
			if (entry_type == ENTTYPE_FILE)
			{
				// make sure we care, first
				file_type type = FILE_TYPE_INVALID;
				for (int extnum = 0; extnum < ARRAY_LENGTH(extension_lookup); extnum++)
					if (core_filename_ends_with(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)
				{
					dstfile.printf("%s%c%s.html", dstdir.cstr(), PATH_SEPARATOR[0], curlist->name.cstr());
					if (indexfile != NULL)
						core_fprintf(indexfile, "\t<li><a href=\"%s.html\">%s</a></li>\n", curlist->name.cstr(), curlist->name.cstr());
					result = output_file(type, srcrootlen, dstrootlen, srcfile, dstfile, srcdir == dstdir, tempheader, tempfooter);
				}
			}

			// if we have a directory, recurse
			else
			{
				dstfile.printf("%s%c%s", dstdir.cstr(), PATH_SEPARATOR[0], curlist->name.cstr());
				if (indexfile != NULL)
					core_fprintf(indexfile, "\t<li><a href=\"%s/index.html\">%s/</a></li>\n", curlist->name.cstr(), curlist->name.cstr());
				result = recurse_dir(srcrootlen, dstrootlen, srcfile, dstfile, tempheader, tempfooter);
			}
		}

		// 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;
			delete list;
			list = next;
		}
	}

	if (indexfile != NULL)
		output_footer_and_close_file(indexfile, tempfooter, srcdir_subpath);
	return result;
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
static int output_file(file_type type, int srcrootlen, int dstrootlen, const astring *srcfile, const astring *dstfile, int link_to_file)
{
	const char *comment_start, *comment_end, *comment_inline, *token_chars;
	const char *comment_start_esc, *comment_end_esc, *comment_inline_esc;
	const token_entry *token_table;
	const astring *srcfile_subpath;
	char srcline[4096], *srcptr;
	int in_comment = FALSE;
	UINT8 is_token[256];
	int color_quotes;
	core_file *src;
	core_file *dst;
	int toknum;
	int linenum = 1;

	/* extract a normalized subpath */
	srcfile_subpath = normalized_subpath(srcfile, srcrootlen + 1);
	if (srcfile_subpath == NULL)
		return 1;

	fprintf(stderr, "Processing %s\n", astring_c(srcfile_subpath));

	/* set some defaults */
	color_quotes = FALSE;
	comment_start = comment_start_esc = "";
	comment_end = comment_end_esc = "";
	comment_inline = comment_inline_esc = "";
	token_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_#";
	token_table = dummy_token_table;

	/* based on the file type, set the comment info */
	switch (type)
	{
		case FILE_TYPE_C:
			color_quotes = TRUE;
			comment_start = comment_start_esc = "/*";
            comment_end = comment_end_esc = "*/";
			comment_inline = comment_inline_esc = "//";
			token_table = c_token_table;
			break;

		case FILE_TYPE_MAKE:
			color_quotes = TRUE;
			comment_inline = comment_inline_esc = "#";
			break;

		case FILE_TYPE_XML:
			color_quotes = TRUE;
			comment_start = "<!--";
			comment_start_esc = "&lt;!--";
			comment_end = "-->";
			comment_end_esc = "--&gt;";
			break;

		default:
		case FILE_TYPE_TEXT:
			break;
	}

	/* make the token lookup table */
	memset(is_token, 0, sizeof(is_token));
	for (toknum = 0; token_chars[toknum] != 0; toknum++)
		is_token[(UINT8)token_chars[toknum]] = TRUE;

	/* open the source file */
	if (core_fopen(astring_c(srcfile), OPEN_FLAG_READ, &src) != FILERR_NONE)
	{
		fprintf(stderr, "Unable to read file '%s'\n", astring_c(srcfile));
		return 1;
	}

	/* open the output file */
	dst = create_file_and_output_header(dstfile, "MAME Source Code", astring_c(srcfile_subpath));
	if (dst == NULL)
	{
		fprintf(stderr, "Unable to write file '%s'\n", astring_c(dstfile));
		core_fclose(src);
		return 1;
	}

	/* output the directory navigation */
	core_fprintf(dst, "<h3>Viewing File: ");
	output_path_as_links(dst, srcfile_subpath, FALSE, link_to_file);
	core_fprintf(dst, "</h3>");
	astring_free((astring *)srcfile_subpath);

	/* start with some tags */
	core_fprintf(dst, "\t<pre style=\"font-family:'Courier New','Courier',monospace; font-size:12px;\">\n");

	/* iterate over lines in the source file */
	while (core_fgets(srcline, ARRAY_LENGTH(srcline), src) != NULL)
	{
		char dstline[4096], *dstptr = dstline;
		int in_inline_comment = FALSE;
		int last_token_was_include = FALSE;
		int last_was_token = FALSE;
		int quotes_are_linked = FALSE;
		char in_quotes = 0;
		int curcol = 0;

		/* start with the line number */
		dstptr += sprintf(dstptr, "<span style=\"" LINENUM_STYLE "\">%5d</span>&nbsp;&nbsp;", linenum++);

		/* iterate over characters in the source line */
		for (srcptr = srcline; *srcptr != 0; )
		{
			UINT8 ch = *srcptr++;

			/* track whether or not we are within an extended (C-style) comment */
			if (!in_quotes && !in_inline_comment)
			{
				if (!in_comment && ch == comment_start[0] && strncmp(srcptr - 1, comment_start, strlen(comment_start)) == 0)
				{
					dstptr += sprintf(dstptr, "<span style=\"" COMMENT_STYLE "\">%s", comment_start_esc);
					curcol += strlen(comment_start);
					srcptr += strlen(comment_start) - 1;
					ch = 0;
					in_comment = TRUE;
				}
				else if (in_comment && ch == comment_end[0] && strncmp(srcptr - 1, comment_end, strlen(comment_end)) == 0)
				{
					dstptr += sprintf(dstptr, "%s</span>", comment_end_esc);
					curcol += strlen(comment_end);
					srcptr += strlen(comment_end) - 1;
					ch = 0;
					in_comment = FALSE;
				}
			}

			/* track whether or not we are within an inline (C++-style) comment */
			if (!in_quotes && !in_comment && !in_inline_comment && ch == comment_inline[0] && strncmp(srcptr - 1, comment_inline, strlen(comment_inline)) == 0)
			{
				dstptr += sprintf(dstptr, "<span style=\"" COMMENT_STYLE "\">%s", comment_inline_esc);
				curcol += strlen(comment_inline);
				srcptr += strlen(comment_inline) - 1;
				ch = 0;
				in_inline_comment = TRUE;
			}

			/* if this is the start of a new token, see if we want to color it */
			if (!in_quotes && !in_comment && !in_inline_comment && !last_was_token && is_token[ch])
			{
				const token_entry *curtoken;
				char *temp = srcptr;
				int toklength;

				/* find the end of the token */
				while (*temp != 0 && is_token[(UINT8)*temp])
					temp++;
				toklength = temp - (srcptr - 1);

				/* scan the token table */
				last_token_was_include = FALSE;
				for (curtoken = token_table; curtoken->token != NULL; curtoken++)
					if (strncmp(srcptr - 1, curtoken->token, toklength) == 0 && strlen(curtoken->token) == toklength)
					{
						dstptr += sprintf(dstptr, "<span style=\"%s\">%s</span>", curtoken->color, curtoken->token);
						curcol += strlen(curtoken->token);
						srcptr += strlen(curtoken->token) - 1;
						ch = 0;

						/* look for include tokens specially */
						if (type == FILE_TYPE_C && strcmp(curtoken->token, "#include") == 0)
							last_token_was_include = TRUE;
						break;
					}
			}
			last_was_token = is_token[ch];

			/* if we hit a tab, expand it */
			if (ch == 0x09)
			{
				/* compute how many spaces */
				int spaces = 4 - curcol % 4;
				while (spaces--)
				{
					*dstptr++ = ' ';
					curcol++;
				}
			}

			/* otherwise, copy the source character */
			else if (ch != 0x0a && ch != 0x0d && ch != 0)
			{
				/* track opening quotes */
				if (!in_comment && !in_inline_comment && !in_quotes && (ch == '"' || ch == '\''))
				{
					if (color_quotes)
						dstptr += sprintf(dstptr, "<span style=\"" STRING_STYLE "\">%c", ch);
					else
						*dstptr++ = ch;
					in_quotes = ch;

					/* handle includes */
					if (last_token_was_include)
					{
						char *endquote = strchr(srcptr, ch);
						if (endquote != NULL)
						{
							astring *filename = astring_dupch(srcptr, endquote - srcptr);
							astring *target = find_include_file(srcrootlen, dstrootlen, srcfile, dstfile, filename);
							if (target != NULL)
							{
								dstptr += sprintf(dstptr, "<a href=\"%s\">", astring_c(target));
								quotes_are_linked = TRUE;
								astring_free(target);
							}
							astring_free(filename);
						}
					}
				}

				/* track closing quotes */
				else if (!in_comment && !in_inline_comment && in_quotes && ch == in_quotes && (type != FILE_TYPE_C || srcptr[-2] != '\\' || srcptr[-3] == '\\'))
				{
					if (quotes_are_linked)
						dstptr += sprintf(dstptr, "</a>");
					if (color_quotes)
						dstptr += sprintf(dstptr, "%c</span>", ch);
					else
						*dstptr++ = ch;
					in_quotes = 0;
					quotes_are_linked = FALSE;
				}

				/* else just output the current character */
				else if (ch == '&')
					dstptr += sprintf(dstptr, "&amp;");
				else if (ch == '<')
					dstptr += sprintf(dstptr, "&lt;");
				else if (ch == '>')
					dstptr += sprintf(dstptr, "&gt;");
				else
					*dstptr++ = ch;
				curcol++;
			}
		}

		/* finish inline comments */
		if (in_inline_comment)
		{
			dstptr += sprintf(dstptr, "</span>");
			in_inline_comment = FALSE;
		}

		/* append a break and move on */
		dstptr += sprintf(dstptr, "\n");
		core_fputs(dst, dstline);
	}

	/* close tags */
	core_fprintf(dst, "\t</pre>\n");

	/* close the file */
	output_footer_and_close_file(dst);
	core_fclose(src);
	return 0;
}
Exemplo n.º 8
0
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;
}