TaggedOpenLibrary constants off by one fix.
[AROS.git] / tools / MetaMake / dirnode.c
blobd170e46edc38c98137484d0fb57e3f13621409d6
1 /* MetaMake - A Make extension
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
4 This file is part of MetaMake.
6 MetaMake is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 MetaMake is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 //#define DEBUG_DIRNODE
23 #include "config.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <errno.h>
29 #ifdef HAVE_STRING_H
30 # include <string.h>
31 #else
32 # include <strings.h>
33 #endif
34 #ifdef HAVE_SYS_STAT_H
35 # include <sys/stat.h>
36 #endif
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif
40 #ifndef PATH_MAX
41 #include <limits.h>
42 #endif
44 #include "dirnode.h"
45 #include "mem.h"
46 #include "var.h"
47 #include "mmake.h"
48 #include "io_.h"
49 #include "project.h"
50 #include "list.h"
51 #include "win32.h"
53 #if defined(DEBUG_DIRNODE)
54 #define debug(a) a
55 #else
56 #define debug(v)
57 #endif
59 #define FLAG_VIRTUAL 0x0001
61 /* Return true if last non whitespace character is a '\' */
62 static int
63 check_continue(const char *str)
65 int pos = strlen(str) - 1;
66 while (pos >= 0 && isspace(str[pos]))
68 pos--;
70 if (pos >= 0 && str[pos] == '\\')
72 return 1;
74 return 0;
77 static struct MakefileTarget *
78 newmakefiletarget (char *name, int virtualtarget)
80 struct MakefileTarget * mftarget;
82 mftarget = newnodesize (name, sizeof(struct MakefileTarget));
83 mftarget->virtualtarget = virtualtarget;
84 NewList (&mftarget->deps);
86 return mftarget;
89 /* Read the metatargets from a file handle */
90 static void
91 readtargets(struct DirNode * node, struct Makefile * makefile, FILE * fh)
93 int lineno = 0;
94 int flags = 0;
95 struct MakefileTarget * mftarget = NULL;
96 static char * line = NULL;
97 static int linelen = 512;
99 if (line == NULL)
100 line = xmalloc(linelen);
102 while (fgets (line, linelen, fh))
104 lineno ++;
106 while (line[strlen(line)-1] != '\n' && !feof(fh))
108 char * ptr;
110 linelen += 512;
111 ptr = xmalloc (linelen);
112 strcpy (ptr, line);
113 xfree (line);
114 line = ptr;
115 fgets (line+strlen(line), linelen-strlen(line), fh);
118 if (line[strlen(line)-1] == '\n')
120 line[strlen(line)-1] = 0;
123 if (strncmp (line, "#MM", 3) == 0)
125 char * ptr;
126 int count, count2, t;
128 #if 0
129 printf ("found #MM in %s\n", makefile->name);
130 #endif
132 /* Read in next lines if there is continuation */
133 while (check_continue(line))
135 ptr = line + strlen(line) - 1;
137 if (!fgets (ptr, linelen-strlen(line)+1, fh))
139 error("%s/%s:unexpected end of makefile",
140 getcwd(NULL, 0),
141 makefile->node.name
143 exit(20);
146 lineno ++;
148 while (line[strlen(line)-1] != '\n' && !feof(fh))
150 int pos = ptr - line;
151 linelen += 512;
152 ptr = xmalloc (linelen);
153 strcpy (ptr, line);
154 xfree (line);
155 line = ptr;
156 fgets (line+strlen(line), linelen-strlen(line), fh);
157 ptr = line + pos;
160 if (line[strlen(line)-1] == '\n')
162 line[strlen(line)-1] = 0;
165 if (strncmp (ptr, "##MM", 3) == 0)
167 *ptr = line[strlen(line)-1];
168 ptr[1] = 0;
169 continue;
172 if (strncmp (ptr, "#MM", 3) != 0)
174 errno = 0;
175 error("%s/%s:%d:continuation line has to start with #MM",
176 getcwd (NULL, 0),
177 makefile->node.name,
178 lineno
180 exit(20);
183 memmove (ptr, ptr+4, strlen(ptr)-4+1);
186 ptr = line+3;
188 if (*ptr == '-')
190 flags |= FLAG_VIRTUAL;
191 ptr ++;
193 else
194 flags &= ~FLAG_VIRTUAL;
196 while (isspace (*ptr))
197 ptr ++;
199 if (!*ptr)
201 /* Line with only #MM, metatarget is on next line */
202 char ** targets;
203 fgets (line, linelen, fh);
204 lineno ++;
206 ptr = line;
207 while (*ptr != ':' && *ptr)
208 ptr ++;
210 *ptr = 0;
212 targets = getargs (line, &count, NULL);
214 if (count > 0)
216 if (count > 1)
218 printf ("Warning: Multiple metatargets, only the 1st will be added in %s:%d (%s)\n",
219 makefile->node.name, lineno, buildpath(node)
221 /* FIXME: should we better add all metatargets? */
223 mftarget = FindNode (&makefile->targets, targets[0]);
225 if (mftarget == NULL)
227 mftarget = newmakefiletarget (targets[0], 0);
228 AddTail (&makefile->targets, mftarget);
230 else
231 mftarget->virtualtarget = 0;
233 else
234 printf ("Warning: Can't find metatarget in %s:%d (%s)\n", makefile->node.name, lineno, buildpath(node));
236 else
238 struct List newtargets;
239 char * ptr2 = ptr, ** tptr;
240 struct MakefileTarget * mftarget2, * mftarget3;
242 NewList (&newtargets);
244 while (*ptr2 != ':' && *ptr2)
245 ptr2 ++;
247 if (*ptr2 == ':')
248 *ptr2 ++ = 0;
250 tptr = getargs (ptr, &count, NULL);
252 for (t = 0; t < count; t++)
254 mftarget = newmakefiletarget (tptr[t], (flags & FLAG_VIRTUAL) != 0);
255 AddTail (&newtargets, mftarget);
258 tptr = getargs (ptr2, &count2, NULL);
260 if (count > 1 && count2 == 0)
262 /* could mean a missing colon */
263 printf ("Warning: multiple metatargets but no prerequisites %s:%d (%s)\n",
264 makefile->node.name, lineno, buildpath(node)
268 for (t = 0; t < count2; t++)
270 ForeachNode (&newtargets, mftarget)
271 addnodeonce (&mftarget->deps, tptr[t]);
274 ForeachNodeSafe (&newtargets, mftarget, mftarget2)
276 mftarget3 = FindNode (&makefile->targets, mftarget->node.name);
278 /* mftarget doesn't exists yet add it to targets */
279 if (mftarget3 == NULL)
281 Remove (mftarget);
282 AddTail (&makefile->targets, mftarget);
284 else
286 /* Merge data in mftarget into mftarget3 */
287 struct Node * node;
289 mftarget3->virtualtarget = mftarget3->virtualtarget && mftarget->virtualtarget;
291 ForeachNode (&mftarget->deps, node)
292 addnodeonce (&mftarget3->deps, node->name);
294 /* Free the targets from which the data was merged in other targets */
295 freemakefiletargetlist (&newtargets);
298 } /* If this is a MetaMake line in the makefile */
299 } /* For all lines in a makefile */
301 #if 0
302 printf ("Read %d lines\n", lineno);
303 #endif
306 /* Call mmakefile with _MM_ target */
307 static int
308 callmake_mm (struct Project * prj, struct Makefile * makefile)
310 static char buffer[4096];
311 const char * path = buildpath (makefile->dir);
312 const char * tname = "_MM_";
313 int t;
315 debug(printf("MMAKE:project.c->callmake()\n"));
317 #if 0
318 if (makefile->generated)
319 chdir (prj->buildtop);
320 else
321 chdir (prj->srctop);
322 chdir (path);
323 #endif
325 setvar (&prj->vars, "CURDIR", path);
326 setvar (&prj->vars, "TARGET", tname);
328 buffer[0] = '\0';
330 for (t=0; t<mflagc; t++)
332 strcat (buffer, mflags[t]);
333 strcat (buffer, " ");
336 if (strcmp (makefile->node.name, "Makefile")!=0 && strcmp (makefile->node.name, "makefile")!=0);
338 strcat (buffer, "--file=");
339 strcat (buffer, makefile->node.name);
340 strcat (buffer, " ");
343 strcat (buffer, tname);
345 printf ("Making %s in %s\n", tname, path);
347 /* TODO: create filename for output */
348 /* execute returns 0 for error */
349 return execute (prj, prj->maketool, "-", "-" /* "/home/mazze/mmtest" */, buffer);
352 void
353 freemakefiletarget (struct MakefileTarget * mftarget)
355 freelist (&mftarget->deps);
356 xfree (mftarget);
359 void
360 freemakefiletargetlist (struct List * targets)
362 struct MakefileTarget * mftarget, * mftarget2;
364 ForeachNodeSafe (targets, mftarget, mftarget2)
365 freemakefiletarget (mftarget);
367 NewList (targets);
370 void
371 printdirnode (struct DirNode * node, int level)
373 struct DirNode * subdir;
374 int t;
376 for (t=0; t<level; t++)
377 printf (" ");
379 printf ("%s\n", node->node.name);
381 level ++;
383 ForeachNode (&node->subdirs, subdir)
384 printdirnode (subdir, level);
387 void
388 printdirnodemftarget (struct DirNode * node)
390 struct Makefile * makefile;
391 struct MakefileTarget * mftarget;
392 struct Node * dep;
393 struct DirNode * subdir;
395 ForeachNode (&node->makefiles, makefile)
397 printf ("%s/%s:\n", buildpath(node), makefile->node.name);
398 ForeachNode (&makefile->targets, mftarget)
400 printf (" %s:", mftarget->node.name);
401 ForeachNode (&mftarget->deps, dep)
402 printf (" %s", dep->name);
403 printf ("\n");
407 ForeachNode (&node->subdirs, subdir)
408 printdirnodemftarget (subdir);
411 void
412 freedirnode (struct DirNode * node)
414 struct DirNode * subnode, * subnode2;
416 ForeachNodeSafe (&node->subdirs, subnode, subnode2)
417 freedirnode (subnode);
419 xfree (node->node.name);
420 xfree (node);
423 void
424 freemakefile (struct Makefile * makefile)
426 freemakefiletargetlist (&makefile->targets);
427 xfree (makefile->node.name);
428 xfree (makefile);
431 struct DirNode *
432 finddirnode (struct DirNode * topnode, const char * path)
434 const char * ptr;
435 char dirname[256];
436 int len;
437 struct DirNode * node = topnode, * subdir;
439 ptr = path+2;
441 if (!*ptr)
442 return node;
444 subdir = NULL;
446 while (*ptr)
448 for (len=0; ptr[len] && ptr[len] != '/'; len++);
450 strncpy (dirname, ptr, len);
451 dirname[len] = 0;
452 ptr += len;
453 while (*ptr == '/')
454 ptr ++;
456 subdir = FindNode (&node->subdirs, dirname);
458 if (!subdir)
459 break;
461 node = subdir;
464 return subdir;
469 scandirnode (struct DirNode * node, const char * mfname, struct List * ignoredirs)
471 struct stat st;
472 DIR * dirh;
473 struct dirent * dirent;
475 int mfnamelen = strlen(mfname), scanned = 0;
477 debug(printf("MMAKE:dirnode.c->scandirnode('%s')\n", node->node.name));
479 if (stat(".", &st) != 0)
481 error("scandirnode(): scanning %s\n",
482 strlen(node->node.name) == 0
483 ? "topdir"
484 : node->node.name);
486 exit(20);
489 if (st.st_mtime > node->time)
491 struct List newdirs, newmakefiles;
492 struct DirNode * subdir = NULL, * subdir2;
493 struct Makefile * makefile;
495 debug(printf("MMAKE:dirnode.c->scandirnode dir->time changed .. scanning\n"));
497 if (debug)
498 printf("scandirnode(): scanning %s\n",
499 strlen(node->node.name)==0 ? "topdir" : buildpath(node)
502 NewList (&newdirs);
503 NewList (&newmakefiles);
505 node->time = st.st_mtime;
507 dirh = opendir (".");
508 if (!dirh)
510 error("opendir: could not open current dir");
511 exit(20);
514 while ((dirent = readdir (dirh)))
516 /* Add makefile if it present or the file with .src is present */
517 if (strcmp(dirent->d_name, mfname) == 0
518 || (strlen(dirent->d_name) == mfnamelen + 4
519 && strncmp(dirent->d_name, mfname, mfnamelen) == 0
520 && strcmp(dirent->d_name + mfnamelen, ".src") == 0
524 /* Don't add makefile twice */
525 debug(printf("MMAKE:dirnode.c->scandirnode: %s found ('%s')\n", mfname, dirent->d_name));
527 makefile = FindNode (&newmakefiles, mfname);
528 if (makefile == NULL)
530 debug(printf("MMAKE:dirnode.c->scandirnode: Creating New Makefile node\n"));
531 makefile = FindNode (&node->makefiles, mfname);
532 if (makefile != NULL)
534 Remove (makefile);
536 else
538 makefile = newnodesize (mfname, sizeof (struct Makefile));
539 makefile->dir = node;
540 debug(printf("MMAKE:dirnode.c->scandirnode: Makefile node dir '%s'\n", node->node.name));
541 makefile->time = (time_t)0;
542 NewList (&makefile->targets);
544 AddTail (&newmakefiles, makefile);
546 if (strcmp(dirent->d_name + mfnamelen, ".src") == 0)
547 makefile->generated = 1;
549 else
551 /* If the file is already in the makefiles from the current dirnode
552 * and it is still present in the directory copy it to the new makefiles
553 * list
555 if (strlen (dirent->d_name) > 4
556 && strcmp (dirent->d_name + strlen(dirent->d_name) - 4, ".src") == 0
559 dirent->d_name[strlen(dirent->d_name) - 4] = 0;
560 makefile = FindNode (&node->makefiles, dirent->d_name);
561 dirent->d_name[strlen(dirent->d_name)] = '.';
563 else
564 makefile = FindNode (&node->makefiles, dirent->d_name);
566 if (makefile != NULL)
568 Remove (makefile);
569 AddTail (&newmakefiles, makefile);
573 /* Add file to newsubdirs if it is a directory and it has not to be ignored
575 st.st_mode = 0; /* This makes us to ignore the file if it can't be stat()'ed.
576 This lets us to succesfully skip Unicode-named files under Windows */
577 lstat (dirent->d_name, &st);
579 /* TODO: Add support to MetaMake for going through links
580 * If this feature is to be supported one also has to implement
581 * checks to avoid MetaMake going into infinite loop when circular
582 * linking is present
584 if (S_ISDIR (st.st_mode)
585 && strcmp (dirent->d_name, ".") != 0
586 && strcmp (dirent->d_name, "..") != 0
587 && !S_ISLNK (st.st_mode)
588 && !FindNode (ignoredirs, dirent->d_name)
591 subdir = FindNode (&node->subdirs, dirent->d_name);
593 if (subdir != NULL)
595 Remove (subdir);
597 else
599 subdir = newnodesize (dirent->d_name, sizeof(struct DirNode));
600 debug(printf("MMAKE:dirnode.c->scandirnode: New SubDir Node '%s' @ %p\n", dirent->d_name, subdir));
601 subdir->parent = node;
602 subdir->time = (time_t)0;
603 NewList (&subdir->subdirs);
604 NewList (&subdir->makefiles);
606 AddTail (&newdirs, subdir);
611 closedir (dirh);
613 ForeachNodeSafe (&node->subdirs, subdir, subdir2)
614 freedirnode (subdir);
615 AssignList (&node->subdirs, &newdirs);
617 /* Clear the makefiles that have disappeared */
618 ForeachNode (&node->makefiles, makefile)
620 struct MakefileTarget * mftarget;
622 ForeachNode (&makefile->targets, mftarget)
623 freelist (&mftarget->deps);
625 freelist (&makefile->targets);
628 freelist (&node->makefiles);
630 AssignList (&node->makefiles, &newmakefiles);
632 scanned = 1;
635 debug(printf("MMAKE:dirnode.c->scandirnode: Finished scanning dir '%s'\n", node->node.name));
636 if (debug)
638 printf ("scandirnode()\n");
639 printdirnode (node, 1);
642 return scanned;
647 scanmakefiles (struct Project * prj, struct DirNode * node, struct List * vars)
649 struct Makefile * makefile;
650 struct stat st;
651 int reread = 0;
652 FILE * fh;
654 debug(printf("MMAKE:dirnode.c->scanmakefiles('%s')\n", node->node.name));
656 assert (node);
658 ForeachNode (&node->makefiles, makefile)
660 debug(printf("MMAKE:dirnode.c->scanmakefiles: %d '%s'\n", makefile->generated, makefile->node.name));
662 if (makefile->generated == 0)
664 if (chdir(mm_srcdir) < 0)
666 error("Could not change to dir '%s'", mm_srcdir);
667 exit (20);
670 else
672 if (chdir(mm_builddir) < 0)
674 error("Could not change to dir '%s'", mm_builddir);
675 exit (20);
679 if ((strlen(makefile->dir->node.name) != 0) && (strcmp(makefile->dir->node.name, mm_srcdir) != 0))
681 if (chdir(buildpath(makefile->dir)) < 0)
683 error("Could not change to dir '%s'", makefile->dir->node.name);
684 exit (20);
688 if (stat(makefile->node.name, &st) != 0)
690 error("Could not stat %s", makefile->node.name);
691 exit(20);
694 if (st.st_mtime > makefile->time)
696 if (debug)
697 printf("scanmakefiles(): scanning makefile in %s/%s\n",
698 strlen(node->node.name)==0 ? "topdir" : buildpath(node),
699 makefile->node.name
702 #if 0
703 printf ("Opening %s\n", makefile->name);
704 #endif
706 fh = fopen (makefile->node.name, "r");
707 if (!fh)
709 error ("buildtargetlist:fopen(): Opening %s for reading",
710 makefile->node.name
714 /* Free old metatargets when the file is reread */
715 freemakefiletargetlist (&makefile->targets);
716 NewList (&makefile->targets);
718 readtargets(node, makefile, fh);
720 reread ++;
721 makefile->time = st.st_mtime;
723 fclose (fh);
725 #if 0
726 /* Call make for _MM_ target */
727 if (callmake_mm (prj, makefile))
729 /* _MM_ found */
730 /* TODO: parsing of the result */
731 /* exit (666); */
733 #endif
735 } /* If the makefile needed to be scanned */
736 } /* For all makefiles in the project */
738 return reread;
742 struct Makefile *
743 addmakefile (struct DirNode * node, const char * filename)
745 static char curdir[PATH_MAX];
746 const char * ptr = filename;
747 char * name;
748 int len = 0;
749 struct DirNode * subnode;
750 struct Makefile * makefile = NULL;
752 getcwd(curdir, PATH_MAX);
754 while (ptr != NULL)
756 len = 0;
757 while (ptr[len] != '/' && ptr[len] != 0)
758 len++;
760 name = xmalloc (len+4+1); /* Make room for possibly adding .src at the end */
761 strncpy (name, ptr, len);
762 name[len] = 0;
764 if (ptr[len] == '/')
766 subnode = FindNode (&node->subdirs, name);
767 if (subnode == NULL)
769 xfree(name);
770 chdir (curdir);
771 return NULL;
773 chdir (name);
774 node = subnode;
775 ptr = ptr + len + 1;
777 else
779 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
780 name[len-4] = 0;
782 makefile = FindNode (&node->makefiles, name);
784 if (makefile == NULL)
786 struct stat st;
788 printf ("Trying to stat %s\n", name);
790 if (stat(name, &st) != 0)
792 len = strlen(name);
793 strcat (name, ".src");
794 if (stat (name, &st) != 0)
796 xfree (name);
797 chdir (curdir);
798 return NULL;
800 name[len]=0;
803 makefile = newnodesize (name, sizeof (struct Makefile));
804 makefile->dir = node;
805 makefile->time = (time_t)0;
806 NewList (&makefile->targets);
807 AddTail (&node->makefiles, makefile);
810 ptr = NULL;
813 xfree (name);
816 chdir (curdir);
818 return makefile;
822 struct Makefile *
823 findmakefile (struct DirNode * node, const char *filename)
825 const char * ptr = filename;
826 char * name;
827 int len;
828 struct DirNode * subnode;
829 struct Makefile * makefile = NULL;
831 while (ptr != NULL)
833 len = 0;
834 while (ptr[len] != '/' && ptr[len] != 0)
835 len++;
837 name = xstrndup (ptr, len);
838 name[len] = 0;
840 if (ptr[len] == '/')
842 subnode = FindNode (&node->subdirs, name);
844 if (subnode == NULL)
846 xfree(name);
847 return NULL;
849 node = subnode;
850 ptr = ptr + len + 1;
852 else
854 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
855 name[len-4] = 0;
857 makefile = FindNode (&node->makefiles, name);
858 ptr = NULL;
861 xfree (name);
864 return makefile;
867 struct DirNodeRef
869 struct Node node;
870 struct DirNode * dirnode;
874 const char *
875 buildpath (struct DirNode * node)
877 static char path[PATH_MAX];
878 struct List tree;
879 struct DirNodeRef * ref = NULL;
881 NewList (&tree);
885 if ((strlen (node->node.name) > 0) && (strcmp(node->node.name, mm_srcdir) != 0))
887 ref = newnodesize ("", sizeof (struct DirNodeRef));
888 ref->dirnode = node;
889 AddHead (&tree, ref);
891 node = node->parent;
892 } while (node != NULL);
894 strcpy (path, "");
895 ForeachNode (&tree, ref)
897 if (path[0] != 0)
898 strcat (path, "/");
899 strcat (path, ref->dirnode->node.name);
902 freelist (&tree);
904 return path;
907 struct Makefile *
908 readmakefile (FILE * fh)
910 struct Makefile * makefile;
911 struct MakefileTarget * mftarget;
912 struct Node * n;
913 uint32_t intt;
914 char * s;
916 if (!readstring(fh, &s))
918 error ("readmakefile:readstring():%d", __LINE__);
919 exit (20);
922 if (s == NULL)
923 return NULL;
925 makefile = newnodesize(s, sizeof(struct Makefile));
926 xfree(s);
927 NewList(&makefile->targets);
929 if (!readuint32 (fh, &intt))
931 error ("readmakefile:fread():%d", __LINE__);
932 exit (20);
934 makefile->time = intt;
936 if (!readuint32 (fh, &intt))
938 error ("readmakefile:fread():%d", __LINE__);
939 exit (20);
941 makefile->generated = intt;
943 for (;;)
945 int32_t in;
947 if (!readstring(fh, &s))
949 error ("readmakefile:readstring():%d", __LINE__);
950 exit (20);
953 if (s == NULL)
954 break;
956 mftarget = newnodesize(s, sizeof(struct MakefileTarget));
957 xfree(s);
958 AddTail (&makefile->targets, mftarget);
959 NewList (&mftarget->deps);
961 if (!readint32 (fh, &in))
963 error ("readmakefile:fread():%d", __LINE__);
964 exit (20);
966 mftarget->virtualtarget = in;
968 for (;;)
970 if (!readstring(fh, &s))
972 error ("readmakefile:readstring():%d", __LINE__);
973 exit (20);
976 if (s == NULL)
977 break;
979 n = newnode(s);
980 xfree(s);
981 AddTail (&mftarget->deps, n);
985 return makefile;
990 writemakefile (FILE * fh, struct Makefile * makefile)
992 struct MakefileTarget * mftarget;
993 struct Node * n;
995 if (makefile == NULL)
997 if (!writestring (fh, NULL))
999 error ("writemakefile/writestring():%d", __LINE__);
1000 return 0;
1003 return 1;
1006 if (!writestring (fh, makefile->node.name))
1008 error ("writemakefile/writestring():%d", __LINE__);
1009 return 0;
1012 if (!writeuint32 (fh, makefile->time))
1014 error ("writemakefile/fwrite():%d", __LINE__);
1015 return 0;
1018 if (!writeuint32 (fh, makefile->generated))
1020 error ("writemakefile/fwrite():%d", __LINE__);
1021 return 0;
1024 ForeachNode (&makefile->targets, mftarget)
1026 if (!writestring (fh, mftarget->node.name))
1028 error ("writemakefile/writestring():%d", __LINE__);
1029 return 0;
1032 if (!writeint32 (fh, mftarget->virtualtarget))
1034 error ("writemakefile/fwrite():%d", __LINE__);
1035 return 0;
1038 ForeachNode (&mftarget->deps, n)
1040 if (!writestring (fh, n->name))
1042 error ("writemakefile/writestring():%d", __LINE__);
1043 return 0;
1047 if (!writestring (fh, NULL))
1049 error ("writemakefile/writestring():%d", __LINE__);
1050 return 0;
1054 if (!writestring(fh, NULL))
1056 error ("writemakefile/writestring():%d", __LINE__);
1057 return 0;
1060 return 1;
1064 struct DirNode *
1065 readcachedir (FILE * fh)
1067 struct DirNode * node, * subnode;
1068 struct Makefile * makefile;
1069 uint32_t intt;
1070 char * s;
1072 if (!readstring(fh, &s))
1074 error ("readcachedir:readstring():%d", __LINE__);
1075 return NULL;
1078 if (s == NULL)
1079 return NULL;
1081 node = newnodesize(s, sizeof(struct DirNode));
1082 xfree (s);
1083 NewList(&node->makefiles);
1084 NewList(&node->subdirs);
1086 if (!readuint32 (fh, &intt))
1088 error ("readcachedir:fread():%d", __LINE__);
1089 free (node);
1090 return NULL;
1092 node->time = intt;
1094 while ((makefile = readmakefile (fh)))
1096 makefile->dir = node;
1097 AddTail (&node->makefiles, makefile);
1100 while ((subnode = readcachedir (fh)))
1102 subnode->parent = node;
1103 AddTail (&node->subdirs, subnode);
1106 return node;
1110 writecachedir (FILE * fh, struct DirNode * node)
1112 int out;
1113 struct DirNode * subnode;
1114 struct Makefile * makefile;
1116 if (node == NULL)
1118 if (!writestring(fh, NULL))
1120 error ("writecachedir/writestring():%d", __LINE__);
1121 return 0;
1124 return 1;
1127 if (!writestring(fh, node->node.name))
1129 error ("writecachedir/writestring():%d", __LINE__);
1130 return 0;
1133 if (!writeuint32 (fh, node->time))
1135 error ("writecachedir/fwrite():%d", __LINE__);
1136 return 0;
1139 ForeachNode (&node->makefiles, makefile)
1140 writemakefile (fh, makefile);
1142 if (!writemakefile (fh, NULL))
1143 return 0;
1145 ForeachNode (&node->subdirs, subnode)
1147 if (!writecachedir (fh, subnode))
1148 return 0;
1151 return writecachedir (fh, NULL);