diff options
Diffstat (limited to 'trunk/src/build/makelist.c')
-rw-r--r-- | trunk/src/build/makelist.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/trunk/src/build/makelist.c b/trunk/src/build/makelist.c new file mode 100644 index 00000000000..21b0d284e7e --- /dev/null +++ b/trunk/src/build/makelist.c @@ -0,0 +1,273 @@ +/*************************************************************************** + + makelist.c + + Create and sort the driver list. + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include "corefile.h" + + +#define MAX_DRIVERS 65536 +#define MAX_IGNORE 512 + +static const char *drivlist[MAX_DRIVERS]; +static int drivcount; +static const char *ignorelst[MAX_IGNORE]; +static int ignorecount; + + +//------------------------------------------------- +// driver_sort_callback - compare two items in +// a string array +//------------------------------------------------- + +int sort_callback(const void *elem1, const void *elem2) +{ + const char **item1 = (const char **)elem1; + const char **item2 = (const char **)elem2; + return strcmp(*item1, *item2); +} + +//------------------------------------------------- +// isignored - return info if item is in ignore +// list or not +//------------------------------------------------- + +bool isignored(const char *drivname) +{ + if (ignorecount>0) { + for(int i=0;i<ignorecount;i++) { + if (strcmp(ignorelst[i],drivname)==0) return true; + } + } + return false; +} + +//------------------------------------------------- +// parse_file - parse a single file, may be +// called recursively +//------------------------------------------------- + +int parse_file(const char *srcfile) +{ + // read source file + void *buffer; + UINT32 length; + file_error filerr = core_fload(srcfile, &buffer, &length); + if (filerr != FILERR_NONE) + { + fprintf(stderr, "Unable to read source file '%s'\n", srcfile); + return 1; + } + + // rip through it to find all drivers + char *srcptr = (char *)buffer; + char *endptr = srcptr + length; + int linenum = 1; + bool in_comment = false; + while (srcptr < endptr) + { + char c = *srcptr++; + + // count newlines + if (c == 13 || c == 10) + { + if (c == 13 && *srcptr == 10) + srcptr++; + linenum++; + continue; + } + + // skip any spaces + if (isspace(c)) + continue; + + // look for end of C comment + if (in_comment && c == '*' && *srcptr == '/') + { + srcptr++; + in_comment = false; + continue; + } + + // skip anything else inside a C comment + if (in_comment) + continue; + + // look for start of C comment + if (c == '/' && *srcptr == '*') + { + srcptr++; + in_comment = true; + continue; + } + + // if we hit a C++ comment, scan to the end of line + if (c == '/' && *srcptr == '/') + { + while (srcptr < endptr && *srcptr != 13 && *srcptr != 10) + srcptr++; + continue; + } + + // look for an import directive + if (c == '#') + { + char filename[256]; + filename[0] = 0; + for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(filename) - 1 && !isspace(*srcptr); pos++) + { + filename[pos] = *srcptr++; + filename[pos+1] = 0; + } + fprintf(stderr, "Importing drivers from '%s'\n", filename); + parse_file(filename); + continue; + } + if (c == '!') + { + char drivname[256]; + drivname[0] = 0; + for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++) + { + drivname[pos] = *srcptr++; + drivname[pos+1] = 0; + } + fprintf(stderr, "Place driver '%s' to ignore list\n", drivname); + char *name = (char *)malloc(strlen(drivname) + 1); + strcpy(name, drivname); + ignorelst[ignorecount++] = name; + continue; + } + + // otherwise treat as a driver name + char drivname[32]; + drivname[0] = 0; + srcptr--; + for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++) + { + drivname[pos] = *srcptr++; + drivname[pos+1] = 0; + } + + // verify the name as valid + for (char *drivch = drivname; *drivch != 0; drivch++) + { + if ((*drivch >= 'a' && *drivch <= 'z') || (*drivch >= '0' && *drivch <= '9') || *drivch == '_') + continue; + fprintf(stderr, "%s:%d - Invalid character '%c' in driver \"%s\"\n", srcfile, linenum, *drivch, drivname); + return 1; + } + + // add it to the list + if(!isignored(drivname)) + { + char *name = (char *)malloc(strlen(drivname) + 1); + strcpy(name, drivname); + drivlist[drivcount++] = name; + } + } + + osd_free(buffer); + + return 0; +} + + +//------------------------------------------------- +// main - primary entry point +//------------------------------------------------- + +int main(int argc, char *argv[]) +{ + // needs at least 1 argument + if (argc < 2) + { + fprintf(stderr, + "Usage:\n" + " makelist <source.lst>\n" + ); + return 0; + } + + // extract arguments + const char *srcfile = argv[1]; + + // parse the root file, exit early upon failure + drivcount = 0; + ignorecount = 0; + if (parse_file(srcfile)) + return 1; + + // add a reference to the ___empty driver + drivlist[drivcount++] = "___empty"; + + // output a count + if (drivcount == 0) + { + fprintf(stderr, "No drivers found\n"); + return 1; + } + fprintf(stderr, "%d drivers found\n", drivcount); + + // sort the list + qsort(drivlist, drivcount, sizeof(*drivlist), sort_callback); + + // start with a header + printf("#include \"emu.h\"\n\n"); + printf("#include \"drivenum.h\"\n\n"); + + // output the list of externs first + for (int index = 0; index < drivcount; index++) + printf("GAME_EXTERN(%s);\n", drivlist[index]); + printf("\n"); + + // then output the array + printf("const game_driver * const driver_list::s_drivers_sorted[%d] =\n", drivcount); + printf("{\n"); + for (int index = 0; index < drivcount; index++) + printf("\t&GAME_NAME(%s)%s\n", drivlist[index], (index == drivcount - 1) ? "" : ","); + printf("};\n"); + printf("\n"); + + // also output a global count + printf("int driver_list::s_driver_count = %d;\n", drivcount); + + return 0; +} |