trunk/src/build/build.mak
| r243507 | r243508 | |
| 20 | 20 | |
| 21 | 21 | MAKEDEP_TARGET = $(BUILDOUT)/makedep$(BUILD_EXE) |
| 22 | 22 | MAKEMAK_TARGET = $(BUILDOUT)/makemak$(BUILD_EXE) |
| 23 | | MAKELIST_TARGET = $(BUILDOUT)/makelist$(BUILD_EXE) |
| 24 | 23 | VERINFO_TARGET = $(BUILDOUT)/verinfo$(BUILD_EXE) |
| 25 | 24 | |
| 26 | 25 | MAKEDEP = $(MAKEDEP_TARGET) |
| 27 | 26 | MAKEMAK = $(MAKEMAK_TARGET) |
| 28 | | MAKELIST = $(MAKELIST_TARGET) |
| 29 | 27 | VERINFO = $(VERINFO_TARGET) |
| 30 | 28 | |
| 31 | 29 | ifneq ($(TERM),cygwin) |
| 32 | 30 | ifeq ($(OS),Windows_NT) |
| 33 | 31 | MAKEDEP = $(subst /,\,$(MAKEDEP_TARGET)) |
| 34 | 32 | MAKEMAK = $(subst /,\,$(MAKEMAK_TARGET)) |
| 35 | | MAKELIST = $(subst /,\,$(MAKELIST_TARGET)) |
| 36 | 33 | VERINFO = $(subst /,\,$(VERINFO_TARGET)) |
| 37 | 34 | endif |
| 38 | 35 | endif |
| r243507 | r243508 | |
| 41 | 38 | BUILD += \ |
| 42 | 39 | $(MAKEDEP_TARGET) \ |
| 43 | 40 | $(MAKEMAK_TARGET) \ |
| 44 | | $(MAKELIST_TARGET) \ |
| 45 | 41 | $(VERINFO_TARGET) \ |
| 46 | 42 | |
| 47 | 43 | |
| r243507 | r243508 | |
| 84 | 80 | |
| 85 | 81 | |
| 86 | 82 | #------------------------------------------------- |
| 87 | | # makelist |
| 88 | | #------------------------------------------------- |
| 89 | | |
| 90 | | MAKELISTOBJS = \ |
| 91 | | $(BUILDOBJ)/makelist.o \ |
| 92 | | $(OBJ)/lib/util/astring.o \ |
| 93 | | $(OBJ)/lib/util/corealloc.o \ |
| 94 | | $(OBJ)/lib/util/cstrpool.o \ |
| 95 | | $(OBJ)/lib/util/corefile.o \ |
| 96 | | $(OBJ)/lib/util/unicode.o \ |
| 97 | | $(OBJ)/lib/util/tagmap.o \ |
| 98 | | |
| 99 | | $(MAKELIST_TARGET): $(MAKELISTOBJS) $(LIBOCORE) $(ZLIB) |
| 100 | | @echo Linking $@... |
| 101 | | $(LD) $(LDFLAGS) $^ $(BASELIBS) -o $@ |
| 102 | | |
| 103 | | |
| 104 | | |
| 105 | | #------------------------------------------------- |
| 106 | 83 | # verinfo |
| 107 | 84 | #------------------------------------------------- |
| 108 | 85 | |
| r243507 | r243508 | |
| 120 | 97 | $(MAKEDEP_TARGET): |
| 121 | 98 | @echo $@ should be built natively. Nothing to do. |
| 122 | 99 | |
| 123 | | $(MAKELIST_TARGET): |
| 124 | | @echo $@ should be built natively. Nothing to do. |
| 125 | | |
| 126 | 100 | $(VERINFO_TARGET): |
| 127 | 101 | @echo $@ should be built natively. Nothing to do. |
| 128 | 102 | |
trunk/src/build/makelist.c
| r243507 | r243508 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Aaron Giles |
| 3 | | /*************************************************************************** |
| 4 | | |
| 5 | | makelist.c |
| 6 | | |
| 7 | | Create and sort the driver list. |
| 8 | | |
| 9 | | ***************************************************************************/ |
| 10 | | |
| 11 | | #include <stdio.h> |
| 12 | | #include <stdlib.h> |
| 13 | | #include <ctype.h> |
| 14 | | #include "corefile.h" |
| 15 | | #include "cstrpool.h" |
| 16 | | |
| 17 | | |
| 18 | | static dynamic_array<const char *> drivlist; |
| 19 | | static dynamic_array<const char *> ignorelst; |
| 20 | | static const_string_pool string_pool; |
| 21 | | |
| 22 | | |
| 23 | | //------------------------------------------------- |
| 24 | | // driver_sort_callback - compare two items in |
| 25 | | // a string array |
| 26 | | //------------------------------------------------- |
| 27 | | |
| 28 | | int sort_callback(const void *elem1, const void *elem2) |
| 29 | | { |
| 30 | | const char **item1 = (const char **)elem1; |
| 31 | | const char **item2 = (const char **)elem2; |
| 32 | | return strcmp(*item1, *item2); |
| 33 | | } |
| 34 | | |
| 35 | | //------------------------------------------------- |
| 36 | | // isignored - return info if item is in ignore |
| 37 | | // list or not |
| 38 | | //------------------------------------------------- |
| 39 | | |
| 40 | | bool isignored(const char *drivname) |
| 41 | | { |
| 42 | | for (int i = 0; i < ignorelst.count(); i++) |
| 43 | | if (strcmp(ignorelst[i], drivname) == 0) |
| 44 | | return true; |
| 45 | | return false; |
| 46 | | } |
| 47 | | |
| 48 | | //------------------------------------------------- |
| 49 | | // parse_file - parse a single file, may be |
| 50 | | // called recursively |
| 51 | | //------------------------------------------------- |
| 52 | | |
| 53 | | int parse_file(const char *srcfile) |
| 54 | | { |
| 55 | | // read source file |
| 56 | | dynamic_buffer buffer; |
| 57 | | file_error filerr = core_fload(srcfile, buffer); |
| 58 | | if (filerr != FILERR_NONE) |
| 59 | | { |
| 60 | | fprintf(stderr, "Unable to read source file '%s'\n", srcfile); |
| 61 | | return 1; |
| 62 | | } |
| 63 | | |
| 64 | | // rip through it to find all drivers |
| 65 | | char *srcptr = (char *)&buffer[0]; |
| 66 | | char *endptr = srcptr + buffer.count(); |
| 67 | | int linenum = 1; |
| 68 | | bool in_comment = false; |
| 69 | | while (srcptr < endptr) |
| 70 | | { |
| 71 | | char c = *srcptr++; |
| 72 | | |
| 73 | | // count newlines |
| 74 | | if (c == 13 || c == 10) |
| 75 | | { |
| 76 | | if (c == 13 && *srcptr == 10) |
| 77 | | srcptr++; |
| 78 | | linenum++; |
| 79 | | continue; |
| 80 | | } |
| 81 | | |
| 82 | | // skip any spaces |
| 83 | | if (isspace(c)) |
| 84 | | continue; |
| 85 | | |
| 86 | | // look for end of C comment |
| 87 | | if (in_comment && c == '*' && *srcptr == '/') |
| 88 | | { |
| 89 | | srcptr++; |
| 90 | | in_comment = false; |
| 91 | | continue; |
| 92 | | } |
| 93 | | |
| 94 | | // skip anything else inside a C comment |
| 95 | | if (in_comment) |
| 96 | | continue; |
| 97 | | |
| 98 | | // look for start of C comment |
| 99 | | if (c == '/' && *srcptr == '*') |
| 100 | | { |
| 101 | | srcptr++; |
| 102 | | in_comment = true; |
| 103 | | continue; |
| 104 | | } |
| 105 | | |
| 106 | | // if we hit a C++ comment, scan to the end of line |
| 107 | | if (c == '/' && *srcptr == '/') |
| 108 | | { |
| 109 | | while (srcptr < endptr && *srcptr != 13 && *srcptr != 10) |
| 110 | | srcptr++; |
| 111 | | continue; |
| 112 | | } |
| 113 | | |
| 114 | | // look for an import directive |
| 115 | | if (c == '#') |
| 116 | | { |
| 117 | | char filename[256]; |
| 118 | | filename[0] = 0; |
| 119 | | for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(filename) - 1 && !isspace(*srcptr); pos++) |
| 120 | | { |
| 121 | | filename[pos] = *srcptr++; |
| 122 | | filename[pos+1] = 0; |
| 123 | | } |
| 124 | | fprintf(stderr, "Importing drivers from '%s'\n", filename); |
| 125 | | parse_file(filename); |
| 126 | | continue; |
| 127 | | } |
| 128 | | if (c == '!') |
| 129 | | { |
| 130 | | char drivname[256]; |
| 131 | | drivname[0] = 0; |
| 132 | | for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++) |
| 133 | | { |
| 134 | | drivname[pos] = *srcptr++; |
| 135 | | drivname[pos+1] = 0; |
| 136 | | } |
| 137 | | fprintf(stderr, "Place driver '%s' to ignore list\n", drivname); |
| 138 | | ignorelst.append(string_pool.add(drivname)); |
| 139 | | continue; |
| 140 | | } |
| 141 | | |
| 142 | | // otherwise treat as a driver name |
| 143 | | char drivname[32]; |
| 144 | | drivname[0] = 0; |
| 145 | | srcptr--; |
| 146 | | for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++) |
| 147 | | { |
| 148 | | drivname[pos] = *srcptr++; |
| 149 | | drivname[pos+1] = 0; |
| 150 | | } |
| 151 | | |
| 152 | | // verify the name as valid |
| 153 | | for (char *drivch = drivname; *drivch != 0; drivch++) |
| 154 | | { |
| 155 | | if ((*drivch >= 'a' && *drivch <= 'z') || (*drivch >= '0' && *drivch <= '9') || *drivch == '_') |
| 156 | | continue; |
| 157 | | fprintf(stderr, "%s:%d - Invalid character '%c' in driver \"%s\"\n", srcfile, linenum, *drivch, drivname); |
| 158 | | return 1; |
| 159 | | } |
| 160 | | |
| 161 | | // add it to the list |
| 162 | | if (!isignored(drivname)) |
| 163 | | drivlist.append(string_pool.add(drivname)); |
| 164 | | } |
| 165 | | |
| 166 | | return 0; |
| 167 | | } |
| 168 | | |
| 169 | | |
| 170 | | //------------------------------------------------- |
| 171 | | // main - primary entry point |
| 172 | | //------------------------------------------------- |
| 173 | | |
| 174 | | int main(int argc, char *argv[]) |
| 175 | | { |
| 176 | | // needs at least 1 argument |
| 177 | | if (argc < 2) |
| 178 | | { |
| 179 | | fprintf(stderr, |
| 180 | | "Usage:\n" |
| 181 | | " makelist <source.lst>\n" |
| 182 | | ); |
| 183 | | return 0; |
| 184 | | } |
| 185 | | |
| 186 | | // extract arguments |
| 187 | | const char *srcfile = argv[1]; |
| 188 | | |
| 189 | | // parse the root file, exit early upon failure |
| 190 | | if (parse_file(srcfile)) |
| 191 | | return 1; |
| 192 | | |
| 193 | | // output a count |
| 194 | | if (drivlist.count() == 0) |
| 195 | | { |
| 196 | | fprintf(stderr, "No drivers found\n"); |
| 197 | | return 1; |
| 198 | | } |
| 199 | | fprintf(stderr, "%d drivers found\n", drivlist.count()); |
| 200 | | |
| 201 | | // add a reference to the ___empty driver |
| 202 | | drivlist.append("___empty"); |
| 203 | | |
| 204 | | // sort the list |
| 205 | | qsort(drivlist, drivlist.count(), sizeof(drivlist[0]), sort_callback); |
| 206 | | |
| 207 | | // start with a header |
| 208 | | printf("#include \"emu.h\"\n\n"); |
| 209 | | printf("#include \"drivenum.h\"\n\n"); |
| 210 | | |
| 211 | | // output the list of externs first |
| 212 | | for (int index = 0; index < drivlist.count(); index++) |
| 213 | | printf("GAME_EXTERN(%s);\n", drivlist[index]); |
| 214 | | printf("\n"); |
| 215 | | |
| 216 | | // then output the array |
| 217 | | printf("const game_driver * const driver_list::s_drivers_sorted[%d] =\n", drivlist.count()); |
| 218 | | printf("{\n"); |
| 219 | | for (int index = 0; index < drivlist.count(); index++) |
| 220 | | printf("\t&GAME_NAME(%s)%s\n", drivlist[index], (index == drivlist.count() - 1) ? "" : ","); |
| 221 | | printf("};\n"); |
| 222 | | printf("\n"); |
| 223 | | |
| 224 | | // also output a global count |
| 225 | | printf("int driver_list::s_driver_count = %d;\n", drivlist.count()); |
| 226 | | |
| 227 | | return 0; |
| 228 | | } |