Previous 199869 Revisions Next

r23750 Monday 17th June, 2013 at 14:59:17 UTC by Miodrag Milanović
start work on makemak to produce dependency per driver, added @ sign into lst to declare source file import used by makemak only, added just few testing examples (nw)
[src/build]build.mak makelist.c makemak.c*
[src/mame]arcade.lst mame.mak

trunk/src/build/build.mak
r23749r23750
2020
2121FILE2STR_TARGET = $(BUILDOUT)/file2str$(BUILD_EXE)
2222MAKEDEP_TARGET = $(BUILDOUT)/makedep$(BUILD_EXE)
23MAKEMAK_TARGET = $(BUILDOUT)/makemak$(BUILD_EXE)
2324MAKELIST_TARGET = $(BUILDOUT)/makelist$(BUILD_EXE)
2425PNG2BDC_TARGET = $(BUILDOUT)/png2bdc$(BUILD_EXE)
2526VERINFO_TARGET = $(BUILDOUT)/verinfo$(BUILD_EXE)
r23749r23750
2728ifeq ($(TARGETOS),win32)
2829FILE2STR = $(subst /,\,$(FILE2STR_TARGET))
2930MAKEDEP = $(subst /,\,$(MAKEDEP_TARGET))
31MAKEMAK = $(subst /,\,$(MAKEMAK_TARGET))
3032MAKELIST = $(subst /,\,$(MAKELIST_TARGET))
3133PNG2BDC = $(subst /,\,$(PNG2BDC_TARGET))
3234VERINFO = $(subst /,\,$(VERINFO_TARGET))
3335else
3436FILE2STR = $(FILE2STR_TARGET)
3537MAKEDEP = $(MAKEDEP_TARGET)
38MAKEMAK = $(MAKEMAK_TARGET)
3639MAKELIST = $(MAKELIST_TARGET)
3740PNG2BDC = $(PNG2BDC_TARGET)
3841VERINFO = $(VERINFO_TARGET)
r23749r23750
4245BUILD += \
4346   $(FILE2STR_TARGET) \
4447   $(MAKEDEP_TARGET) \
48   $(MAKEMAK_TARGET) \
4549   $(MAKELIST_TARGET) \
4650   $(PNG2BDC_TARGET) \
4751   $(VERINFO_TARGET) \
r23749r23750
7579
7680
7781#-------------------------------------------------
82# makemak
83#-------------------------------------------------
84
85MAKEMAKOBJS = \
86   $(BUILDOBJ)/makemak.o \
87
88$(MAKEMAK_TARGET): $(MAKEMAKOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB)
89   @echo Linking $@...
90   $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
91
92
93
94#-------------------------------------------------
7895# makelist
7996#-------------------------------------------------
8097
trunk/src/build/makemak.c
r0r23750
1/***************************************************************************
2
3    MAME source code dependency generator
4
5****************************************************************************
6
7    Copyright Aaron Giles
8    All rights reserved.
9
10    Redistribution and use in source and binary forms, with or without
11    modification, are permitted provided that the following conditions are
12    met:
13
14        * Redistributions of source code must retain the above copyright
15          notice, this list of conditions and the following disclaimer.
16        * Redistributions in binary form must reproduce the above copyright
17          notice, this list of conditions and the following disclaimer in
18          the documentation and/or other materials provided with the
19          distribution.
20        * Neither the name 'MAME' nor the names of its contributors may be
21          used to endorse or promote products derived from this software
22          without specific prior written permission.
23
24    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
25    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
28    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34    POSSIBILITY OF SUCH DAMAGE.
35
36***************************************************************************/
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <ctype.h>
42#include <zlib.h>
43#include "osdcore.h"
44#include "astring.h"
45#include "corefile.h"
46#include "tagmap.h"
47
48
49/***************************************************************************
50    CONSTANTS
51***************************************************************************/
52
53#define HASH_SIZE       193
54#define MAX_SOURCES  65536
55
56
57/***************************************************************************
58    TYPE DEFINITIONS
59***************************************************************************/
60
61struct include_path
62{
63   include_path *  next;
64   astring         path;
65};
66
67
68struct exclude_path
69{
70   exclude_path *  next;
71   astring         path;
72   int             pathlen;
73   UINT8           recursive;
74};
75
76
77struct list_entry
78{
79   list_entry *    next;
80   astring         name;
81};
82
83
84struct file_entry;
85
86struct dependency
87{
88   dependency *    next;
89   file_entry *    file;
90};
91
92
93struct file_entry
94{
95   astring         name;
96   dependency *    deplist;
97};
98
99typedef tagmap_t<UINT8> dependency_map;
100
101
102
103/***************************************************************************
104    GLOBAL VARIABLES
105***************************************************************************/
106
107static include_path *incpaths;
108static exclude_path *excpaths;
109static tagmap_t<file_entry *> file_map;
110static const char *sourcelst[MAX_SOURCES];
111static int sourcecount;
112
113
114
115/***************************************************************************
116    PROTOTYPES
117***************************************************************************/
118
119// core output functions
120static int recurse_dir(int srcrootlen, astring &srcdir);
121static file_entry &compute_dependencies(astring &srcfile);
122
123// path helpers
124static bool find_include_file(astring &srcincpath, const astring &srcfile, const astring &filename);
125
126//-------------------------------------------------
127//  isonlist - return info if item is in source
128//  list or not
129//-------------------------------------------------
130
131bool isonlist(const char *drivname)
132{
133   if (sourcecount>0) {
134      for(int i=0;i<sourcecount;i++) {
135         if (strcmp(sourcelst[i],drivname)==0) return true;
136      }
137   }
138   return false;
139}
140
141//-------------------------------------------------
142//  parse_file - parse a single file, may be
143//  called recursively
144//-------------------------------------------------
145
146int parse_file(const char *srcfile)
147{
148   // read source file
149   void *buffer;
150   UINT32 length;
151   file_error filerr = core_fload(srcfile, &buffer, &length);
152   if (filerr != FILERR_NONE)
153   {
154      fprintf(stderr, "Unable to read source file '%s'\n", srcfile);
155      return 1;
156   }
157
158   // rip through it to find all drivers
159   char *srcptr = (char *)buffer;
160   char *endptr = srcptr + length;
161   int linenum = 1;
162   bool in_comment = false;
163   while (srcptr < endptr)
164   {
165      char c = *srcptr++;
166
167      // count newlines
168      if (c == 13 || c == 10)
169      {
170         if (c == 13 && *srcptr == 10)
171            srcptr++;
172         linenum++;
173         continue;
174      }
175
176      // skip any spaces
177      if (isspace(c))
178         continue;
179
180      // look for end of C comment
181      if (in_comment && c == '*' && *srcptr == '/')
182      {
183         srcptr++;
184         in_comment = false;
185         continue;
186      }
187
188      // skip anything else inside a C comment
189      if (in_comment)
190         continue;
191
192      // look for start of C comment
193      if (c == '/' && *srcptr == '*')
194      {
195         srcptr++;
196         in_comment = true;
197         continue;
198      }
199
200      // if we hit a C++ comment, scan to the end of line
201      if (c == '/' && *srcptr == '/')
202      {
203         while (srcptr < endptr && *srcptr != 13 && *srcptr != 10)
204            srcptr++;
205         continue;
206      }
207
208      // look for an import directive
209      if (c == '#')
210      {
211         char filename[256];
212         filename[0] = 0;
213         for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(filename) - 1 && !isspace(*srcptr); pos++)
214         {
215            filename[pos] = *srcptr++;
216            filename[pos+1] = 0;
217         }
218         fprintf(stderr, "Importing drivers from '%s'\n", filename);
219         parse_file(filename);
220         continue;
221      }
222      if (c == '@')
223      {
224         // Used for makemak tool
225         char drivname[256];
226         drivname[0] = 0;
227         for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++)
228         {
229            drivname[pos] = *srcptr++;
230            drivname[pos+1] = 0;
231         }
232         fprintf(stderr, "Creating make dependancy for '%s'\n", drivname);
233         char *name = (char *)malloc(strlen(drivname) + 1);
234         strcpy(name, drivname);
235         sourcelst[sourcecount++] = name;
236         continue;
237      }
238
239      srcptr--;
240      for (int pos = 0; srcptr < endptr && !isspace(*srcptr); pos++)
241      {
242         c = *srcptr++;
243      }
244   }
245
246   osd_free(buffer);
247
248   return 0;
249}
250
251/***************************************************************************
252    MAIN
253***************************************************************************/
254
255/*-------------------------------------------------
256    main - main entry point
257-------------------------------------------------*/
258
259void usage(const char *argv0)
260{
261   fprintf(stderr, "Usage:\n%s <source.lst> <srcroot> [-Iincpath [-Iincpath [...]]]\n", argv0);
262   exit(1);
263}
264
265int main(int argc, char *argv[])
266{
267   include_path **incpathhead = &incpaths;
268   exclude_path **excpathhead = &excpaths;
269   astring srcdir;
270   int unadorned = 0;
271   sourcecount = 0;
272   
273   // extract arguments
274   const char *srcfile = argv[1];   
275   if (parse_file(srcfile))
276      return 1;
277
278   // loop over arguments
279   for (int argnum = 2; argnum < argc; argnum++)
280   {
281      char *arg = argv[argnum];
282
283      // include path?
284      if (arg[0] == '-' && arg[1] == 'I')
285      {
286         *incpathhead = new include_path;
287         (*incpathhead)->next = NULL;
288         (*incpathhead)->path.cpy(&arg[2]).replacechr('/', PATH_SEPARATOR[0]);
289         incpathhead = &(*incpathhead)->next;
290      }
291
292      // exclude path?
293      else if (arg[0] == '-' && arg[1] == 'X')
294      {
295         *excpathhead = new exclude_path;
296         (*excpathhead)->next = NULL;
297         (*excpathhead)->path.cpy(&arg[2]).replacechr(PATH_SEPARATOR[0], '/');
298         (*excpathhead)->recursive = ((*excpathhead)->path.replace((*excpathhead)->path.len() - 4, "/...", "") != 0);
299         (*excpathhead)->pathlen = (*excpathhead)->path.len();
300         excpathhead = &(*excpathhead)->next;
301      }
302
303      // ignore -include which is used by sdlmame to include sdlprefix.h before all other includes
304      else if (strcmp(arg,"-include") == 0)
305      {
306         argnum++;
307      }
308
309      // other parameter
310      else if (arg[0] != '-' && unadorned == 0)
311      {
312         srcdir.cpy(arg).replacechr('/', PATH_SEPARATOR[0]);
313         unadorned++;
314      }
315      else
316         usage(argv[0]);
317   }
318
319   // make sure we got 1 parameter
320   if (srcdir.len() == 0)
321      usage(argv[0]);
322
323   // recurse over subdirectories
324   return recurse_dir(srcdir.len(), srcdir);
325}
326
327
328
329/***************************************************************************
330    CORE OUTPUT FUNCTIONS
331***************************************************************************/
332
333static int compare_list_entries(const void *p1, const void *p2)
334{
335   const list_entry *entry1 = *(const list_entry **)p1;
336   const list_entry *entry2 = *(const list_entry **)p2;
337   return entry1->name.cmp(entry2->name);
338}
339
340
341/*-------------------------------------------------
342    recurse_dependencies - recurse through the
343    dependencies found, adding the mto the tagmap
344    unless we already exist in the map
345-------------------------------------------------*/
346
347static void recurse_dependencies(file_entry &file, dependency_map &map)
348{
349   // skip if we're in an exclude path
350   int filelen = file.name.len();
351   for (exclude_path *exclude = excpaths; exclude != NULL; exclude = exclude->next)
352      if (exclude->pathlen < filelen && strncmp(file.name, exclude->path, exclude->pathlen) == 0)
353         if (exclude->recursive || file.name.chr(exclude->pathlen + 1, '/') == -1)
354            return;
355
356   // attempt to add; if we get an error, we're already present
357   if (map.add(file.name, 0) != TMERR_NONE)
358      return;
359
360   // recurse the list from there
361   for (dependency *dep = file.deplist; dep != NULL; dep = dep->next)
362      recurse_dependencies(*dep->file, map);
363}
364
365
366/*-------------------------------------------------
367    recurse_dir - recurse through a directory
368-------------------------------------------------*/
369
370static int recurse_dir(int srcrootlen, astring &srcdir)
371{
372   static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE };
373   int result = 0;
374
375   // iterate first over directories, then over files
376   for (int entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++)
377   {
378      osd_dir_entry_type entry_type = typelist[entindex];
379
380      // open the directory and iterate through it
381      osd_directory *dir = osd_opendir(srcdir);
382      if (dir == NULL)
383      {
384         result = 1;
385         goto error;
386      }
387
388      // build up the list of files
389      const osd_directory_entry *entry;
390      list_entry *list = NULL;
391      int found = 0;
392      while ((entry = osd_readdir(dir)) != NULL)
393         if (entry->type == entry_type && entry->name[0] != '.')
394         {
395            list_entry *lentry = new list_entry;
396            lentry->name.cpy(entry->name);
397            lentry->next = list;
398            list = lentry;
399            found++;
400         }
401
402      // close the directory
403      osd_closedir(dir);
404
405      // skip if nothing found
406      if (found == 0)
407         continue;
408
409      // allocate memory for sorting
410      list_entry **listarray = new list_entry *[found];
411      found = 0;
412      for (list_entry *curlist = list; curlist != NULL; curlist = curlist->next)
413         listarray[found++] = curlist;
414
415      // sort the list
416      qsort(listarray, found, sizeof(listarray[0]), compare_list_entries);
417
418      // rebuild the list
419      list = NULL;
420      while (--found >= 0)
421      {
422         listarray[found]->next = list;
423         list = listarray[found];
424      }
425      delete[] listarray;
426
427      // iterate through each file
428      for (list_entry *curlist = list; curlist != NULL && result == 0; curlist = curlist->next)
429      {
430         astring srcfile;
431
432         // build the source filename
433         srcfile.printf("%s%c%s", srcdir.cstr(), PATH_SEPARATOR[0], curlist->name.cstr());
434
435         // if we have a file, output it
436         if (entry_type == ENTTYPE_FILE)
437         {
438            // make sure we care, first
439            if (core_filename_ends_with(curlist->name, ".c"))
440            {
441               dependency_map depend_map;
442
443               // find dependencies
444               file_entry &file = compute_dependencies(srcfile);
445               recurse_dependencies(file, depend_map);
446               astring fn = astring(curlist->name);
447               fn.replace(".c","");
448               if (isonlist(fn))
449               {
450                  // convert the target from source to object (makes assumptions about rules)
451                  astring target(file.name);
452                  target.replace(0, "src/", "$(OBJ)/");
453                  target.replace(0, ".c", ".o");
454                  printf("\n%s : \\\n", target.cstr());
455
456                  // iterate over the hashed dependencies and output them as well
457                  for (dependency_map::entry_t *entry = depend_map.first(); entry != NULL; entry = depend_map.next(entry))
458                     printf("\t%s \\\n", entry->tag().cstr());
459               }
460            }
461         }
462      }
463
464      // free all the allocated entries
465      while (list != NULL)
466      {
467         list_entry *next = list->next;
468         delete list;
469         list = next;
470      }
471   }
472
473error:
474   return result;
475}
476
477static bool check_file(astring &srcincpath)
478{
479   // see if we can open it
480   core_file *testfile;
481   if (core_fopen(srcincpath, OPEN_FLAG_READ, &testfile) == FILERR_NONE)
482   {
483      // close the file
484      core_fclose(testfile);
485      return true;
486   }
487   return false;
488}
489
490/*-------------------------------------------------
491    output_file - output a file, converting to
492    HTML
493-------------------------------------------------*/
494
495static file_entry &compute_dependencies(astring &srcfile)
496{
497   // see if we already have an entry
498   astring normalfile(srcfile);
499   normalfile.replacechr(PATH_SEPARATOR[0], '/');
500   file_entry *foundfile = file_map.find(normalfile);
501   if (foundfile != NULL)
502      return *foundfile;
503
504   // create a new header entry
505   file_entry &file = *new file_entry;
506   file.deplist = NULL;
507   file.name = normalfile;
508   file_map.add(file.name, &file);
509
510   // read the source file
511   UINT32 filelength;
512   char *filedata;
513   if (core_fload(srcfile, (void **)&filedata, &filelength) != FILERR_NONE)
514   {
515      fprintf(stderr, "Unable to read file '%s'\n", srcfile.cstr());
516      return file;
517   }
518
519   astring audiofile = astring(srcfile);
520   audiofile.replace("drivers","audio");
521   if (check_file(audiofile))
522   {
523      dependency *dep = new dependency;
524      dep->next = file.deplist;
525      file.deplist = dep;
526      dep->file = &compute_dependencies(audiofile);
527   }
528
529   astring machinefile = astring(srcfile);
530   machinefile.replace("drivers","machine");
531   if (check_file(machinefile))
532   {
533      dependency *dep = new dependency;
534      dep->next = file.deplist;
535      file.deplist = dep;
536      dep->file = &compute_dependencies(machinefile);
537   }
538   
539   astring videofile = astring(srcfile);
540   videofile.replace("drivers","video");
541   if (check_file(videofile))
542   {
543      dependency *dep = new dependency;
544      dep->next = file.deplist;
545      file.deplist = dep;
546      dep->file = &compute_dependencies(videofile);
547   }
548   
549
550   // find the #include directives in this file
551   for (int index = 0; index < filelength; index++)
552      if (filedata[index] == '#' && strncmp(&filedata[index + 1], "include", 7) == 0)
553      {
554         // first make sure we're not commented or quoted
555         bool just_continue = false;
556         for (int scan = index; scan > 2 && filedata[scan] != 13 && filedata[scan] != 10; scan--)
557            if ((filedata[scan] == '/' && filedata[scan - 1] == '/') || filedata[scan] == '"')
558            {
559               just_continue = true;
560               break;
561            }
562         if (just_continue)
563            continue;
564
565         // scan forward to find the quotes or bracket
566         index += 7;
567         int scan;
568         for (scan = index; scan < filelength && filedata[scan] != '<' && filedata[scan] != '"' && filedata[scan] != 13 && filedata[scan] != 10; scan++) ;
569
570         // ignore if not found or if it's bracketed
571         if (scan >= filelength || filedata[scan] != '"')
572            continue;
573         int start = ++scan;
574
575         // find the closing quote
576         while (scan < filelength && filedata[scan] != '"')
577            scan++;
578         if (scan >= filelength)
579            continue;
580
581         // find the include file
582         astring filename(&filedata[start], scan - start);
583         astring target;
584
585         filename.replace(".lh",".lay");
586         
587         // create a new dependency
588         if (find_include_file(target, srcfile, filename))
589         {
590            dependency *dep = new dependency;
591            dep->next = file.deplist;
592            file.deplist = dep;
593            dep->file = &compute_dependencies(target);
594         }
595         // create a new dependency
596      }
597
598   osd_free(filedata);
599   return file;
600}
601
602
603
604/***************************************************************************
605    HELPERS
606***************************************************************************/
607
608/*-------------------------------------------------
609    find_include_file - find an include file
610-------------------------------------------------*/
611
612static bool find_include_file(astring &srcincpath, const astring &srcfile, const astring &filename)
613{
614   // iterate over include paths and find the file
615   for (include_path *curpath = incpaths; curpath != NULL; curpath = curpath->next)
616   {
617      // a '.' include path is specially treated
618      if (curpath->path == ".")
619         srcincpath.cpysubstr(srcfile, 0, srcfile.rchr(0, PATH_SEPARATOR[0]));
620      else
621         srcincpath.cpy(curpath->path);
622
623      // append the filename piecemeal to account for directories
624      int lastsepindex = 0;
625      int sepindex;
626      while ((sepindex = filename.chr(lastsepindex, '/')) != -1)
627      {
628         astring pathpart(filename, lastsepindex, sepindex - lastsepindex);
629
630         // handle .. by removing a chunk from the incpath
631         if (pathpart == "..")
632         {
633            int sepindex_part = srcincpath.rchr(0, PATH_SEPARATOR[0]);
634            if (sepindex_part != -1)
635               srcincpath.substr(0, sepindex_part);
636         }
637
638         // otherwise, append a path separator and the pathpart
639         else
640            srcincpath.cat(PATH_SEPARATOR).cat(pathpart);
641
642         // advance past the previous index
643         lastsepindex = sepindex + 1;
644      }
645
646      // now append the filename
647      srcincpath.cat(PATH_SEPARATOR).catsubstr(filename, lastsepindex, -1);
648
649      // see if we can open it
650      core_file *testfile;
651      if (core_fopen(srcincpath, OPEN_FLAG_READ, &testfile) == FILERR_NONE)
652      {
653         // close the file
654         core_fclose(testfile);
655         return true;
656      }
657   }
658   return false;
659}
Property changes on: trunk/src/build/makemak.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/build/makelist.c
r23749r23750
175175         ignorelst[ignorecount++] = name;
176176         continue;
177177      }
178      if (c == '@')
179      {
180         // Used for makemak tool
181         continue;
182      }
178183
179184      // otherwise treat as a driver name
180185      char drivname[32];
trunk/src/mame/arcade.lst
r23749r23750
10911091
10921092// Misc Namco games
1093109330test          // (c) 1997
1094@20pacgal
1094109525pacman        // (c) 2005 Ver 2.0 - Same hardware as 20pacgal
1095109620pacgal        // (c) 2000 Ver 1.08
1096109720pacgalr4      // (c) 2000 Ver 1.04
r23749r23750
27952796sonson          //  7/1984 (c) 1984
27962797sonsonj         //  7/1984 (c) 1984 (Japan)
27972798higemaru        //  9/1984 (c) 1984
2799@1942
279828001942            // 12/1984 (c) 1984
279928011942a           // 12/1984 (c) 1984
280028021942abl         // bootleg
r23749r23750
98789880wallca          // (c) 1984 Midcoin
98799881wink            // (c) 1985 Midcoin
98809882winka           // (c) 1985 Midcoin
9883@24cdjuke
9881988424cdjuke        // (c) 1988 Midcoin
98829885skyarmy         // (c) 1982 Shoei
98839886lethalj         // (c) 1996 The Game Room
trunk/src/mame/mame.mak
r23749r23750
1919   $(MAKEDEP) -I. $(INCPATH) -X$(SRC)/emu -X$(SRC)/osd/... -X$(OBJ)/... $(SRC)/$(TARGET) > depend_$(TARGET).mak
2020endif
2121
22mak: maketree $(MAKEMAK_TARGET)
23   @echo Rebuilding $(SUBTARGET).mak...
24   $(MAKEMAK) $(SRC)/$(TARGET)/$(SUBTARGET).lst -I. $(INCPATH) -I$(SRC)/$(TARGET)/layout -X$(SRC)/emu -X$(SRC)/osd/... -X$(OBJ)/... $(SRC)/$(TARGET)/drivers > $(SUBTARGET).mak
25
2226MAMESRC = $(SRC)/mame
2327MAMEOBJ = $(OBJ)/mame
2428

Previous 199869 Revisions Next


© 1997-2024 The MAME Team