re-order some parts of the code so that the msg and rect are only allocated once.
[AROS.git] / tools / MetaMake / dirnode.c
blobcdf40db75cb9b1f3b251a639fa02797598e4c8c4
1 /* MetaMake - A Make extension
2 Copyright © 1995-2016, 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 MAX_NODEDEPTH 128
61 #define FLAG_VIRTUAL 0x0001
63 /* Return true if last non whitespace character is a '\' */
64 static int
65 check_continue(const char *str)
67 int pos = strlen(str) - 1;
68 while (pos >= 0 && isspace(str[pos]))
70 pos--;
72 if (pos >= 0 && str[pos] == '\\')
74 return 1;
76 return 0;
79 static struct MakefileTarget *
80 newmakefiletarget (char *name, int virtualtarget)
82 struct MakefileTarget * mftarget;
84 mftarget = newnodesize (name, sizeof(struct MakefileTarget));
85 mftarget->virtualtarget = virtualtarget;
86 NewList (&mftarget->deps);
88 return mftarget;
91 /* Read the metatargets from a file handle */
92 static void
93 readtargets(struct DirNode * node, struct Makefile * makefile, FILE * fh)
95 int lineno = 0;
96 int flags = 0;
97 struct MakefileTarget * mftarget = NULL;
98 static char * line = NULL;
99 static int linelen = 512;
101 if (line == NULL)
102 line = xmalloc(linelen);
104 while (fgets (line, linelen, fh))
106 lineno ++;
108 while (line[strlen(line)-1] != '\n' && !feof(fh))
110 char * ptr;
112 linelen += 512;
113 ptr = xmalloc (linelen);
114 strcpy (ptr, line);
115 xfree (line);
116 line = ptr;
117 ASSERT(fgets (line+strlen(line), linelen-strlen(line), fh) != NULL);
120 if (line[strlen(line)-1] == '\n')
122 line[strlen(line)-1] = 0;
125 if (strncmp (line, "#MM", 3) == 0)
127 char * ptr;
128 int count, count2, t;
130 #if 0
131 printf ("found #MM in %s\n", makefile->node.name);
132 #endif
134 /* Read in next lines if there is continuation */
135 while (check_continue(line))
137 ptr = line + strlen(line) - 1;
139 if (!fgets (ptr, linelen-strlen(line)+1, fh))
141 error("%s/%s:unexpected end of makefile",
142 getcwd(NULL, 0),
143 makefile->node.name
145 exit(20);
148 lineno ++;
150 while (line[strlen(line)-1] != '\n' && !feof(fh))
152 int pos = ptr - line;
153 linelen += 512;
154 ptr = xmalloc (linelen);
155 strcpy (ptr, line);
156 xfree (line);
157 line = ptr;
158 ASSERT(fgets (line+strlen(line), linelen-strlen(line), fh) != NULL);
159 ptr = line + pos;
162 if (line[strlen(line)-1] == '\n')
164 line[strlen(line)-1] = 0;
167 if (strncmp (ptr, "##MM", 3) == 0)
169 *ptr = line[strlen(line)-1];
170 ptr[1] = 0;
171 continue;
174 if (strncmp (ptr, "#MM", 3) != 0)
176 errno = 0;
177 error("%s/%s:%d:continuation line has to start with #MM",
178 getcwd (NULL, 0),
179 makefile->node.name,
180 lineno
182 exit(20);
185 memmove (ptr, ptr+4, strlen(ptr)-4+1);
188 ptr = line+3;
190 if (*ptr == '-')
192 flags |= FLAG_VIRTUAL;
193 ptr ++;
195 else
196 flags &= ~FLAG_VIRTUAL;
198 while (isspace (*ptr))
199 ptr ++;
201 if (*ptr == '-')
203 errno = 0;
204 if (flags & FLAG_VIRTUAL)
206 error("%s/%s:%d:malformed virtual target, only one '-' allowed",
207 getcwd (NULL, 0),
208 makefile->node.name,
209 lineno
212 else
214 error("%s/%s:%d:malformed virtual target, '-' must follow directly after '#MM'",
215 getcwd (NULL, 0),
216 makefile->node.name,
217 lineno
220 exit(20);
223 if (!*ptr)
225 /* Line with only #MM, metatarget is on next line */
226 char ** targets;
227 ASSERT(fgets (line, linelen, fh) != NULL);
228 lineno ++;
230 ptr = line;
231 while (*ptr != ':' && *ptr)
232 ptr ++;
234 *ptr = 0;
236 targets = getargs (line, &count, NULL);
238 if (count > 0)
240 if (count > 1)
242 printf ("[MMAKE] Warning: Multiple metatargets, only the 1st will be added in %s:%d (%s)\n",
243 makefile->node.name, lineno, buildpath(node)
245 /* FIXME: should we better add all metatargets? */
247 mftarget = FindNode (&makefile->targets, targets[0]);
249 if (mftarget == NULL)
251 mftarget = newmakefiletarget (targets[0], 0);
252 AddTail (&makefile->targets, mftarget);
254 else
255 mftarget->virtualtarget = 0;
257 else
258 printf ("[MMAKE] Warning: Can't find metatarget in %s:%d (%s)\n", makefile->node.name, lineno, buildpath(node));
260 else
262 struct List newtargets;
263 char * ptr2 = ptr, ** tptr;
264 struct MakefileTarget * mftarget2, * mftarget3;
266 NewList (&newtargets);
268 while (*ptr2 != ':' && *ptr2)
269 ptr2 ++;
271 if (*ptr2 == ':')
272 *ptr2 ++ = 0;
274 tptr = getargs (ptr, &count, NULL);
276 for (t = 0; t < count; t++)
278 mftarget = newmakefiletarget (tptr[t], (flags & FLAG_VIRTUAL) != 0);
279 AddTail (&newtargets, mftarget);
282 tptr = getargs (ptr2, &count2, NULL);
284 if (count > 1 && count2 == 0)
286 /* could mean a missing colon */
287 printf ("[MMAKE] Warning: multiple metatargets but no prerequisites %s:%d (%s)\n",
288 makefile->node.name, lineno, buildpath(node)
292 for (t = 0; t < count2; t++)
294 ForeachNode (&newtargets, mftarget)
295 addnodeonce (&mftarget->deps, tptr[t]);
298 ForeachNodeSafe (&newtargets, mftarget, mftarget2)
300 mftarget3 = FindNode (&makefile->targets, mftarget->node.name);
302 /* mftarget doesn't exists yet add it to targets */
303 if (mftarget3 == NULL)
305 Remove (mftarget);
306 AddTail (&makefile->targets, mftarget);
308 else
310 /* Merge data in mftarget into mftarget3 */
311 struct Node * node;
313 mftarget3->virtualtarget = mftarget3->virtualtarget && mftarget->virtualtarget;
315 ForeachNode (&mftarget->deps, node)
316 addnodeonce (&mftarget3->deps, node->name);
318 /* Free the targets from which the data was merged in other targets */
319 freemakefiletargetlist (&newtargets);
322 } /* If this is a MetaMake line in the makefile */
323 } /* For all lines in a makefile */
325 #if 0
326 printf ("Read %d lines\n", lineno);
327 #endif
330 void
331 freemakefiletarget (struct MakefileTarget * mftarget)
333 freelist (&mftarget->deps);
334 Remove(mftarget);
335 xfree (mftarget);
338 void
339 freemakefiletargetlist (struct List * targets)
341 struct MakefileTarget * mftarget, * mftarget2;
343 ForeachNodeSafe (targets, mftarget, mftarget2)
344 freemakefiletarget (mftarget);
346 NewList (targets);
349 void
350 printdirnode (struct DirNode * node, int level)
352 struct DirNode * subdir;
353 int t;
355 for (t=0; t<level; t++)
356 printf (" ");
358 printf ("%s\n", node->node.name);
360 level ++;
362 ForeachNode (&node->subdirs, subdir)
363 printdirnode (subdir, level);
366 void
367 printdirnodemftarget (struct DirNode * node)
369 struct Makefile * makefile;
370 struct MakefileTarget * mftarget;
371 struct Node * dep;
372 struct DirNode * subdir;
374 ForeachNode (&node->makefiles, makefile)
376 printf ("%s/%s:\n", buildpath(node), makefile->node.name);
377 ForeachNode (&makefile->targets, mftarget)
379 printf (" %s:", mftarget->node.name);
380 ForeachNode (&mftarget->deps, dep)
381 printf (" %s", dep->name);
382 printf ("\n");
386 ForeachNode (&node->subdirs, subdir)
387 printdirnodemftarget (subdir);
390 void
391 freedirnode (struct DirNode * node)
393 struct DirNode * subnode, * subnode2;
395 ForeachNodeSafe (&node->subdirs, subnode, subnode2)
396 freedirnode (subnode);
398 xfree (node->node.name);
399 xfree (node);
402 void
403 freemakefile (struct Makefile * makefile)
405 freemakefiletargetlist (&makefile->targets);
406 xfree (makefile->node.name);
407 xfree (makefile);
410 struct DirNode *
411 finddirnode (struct DirNode * topnode, const char * path)
413 const char * ptr;
414 char dirname[256];
415 int len;
416 struct DirNode * node = topnode, * subdir;
418 ptr = path+2;
420 if (!*ptr)
421 return node;
423 subdir = NULL;
425 while (*ptr)
427 for (len=0; ptr[len] && ptr[len] != '/'; len++);
429 strncpy (dirname, ptr, len);
430 dirname[len] = 0;
431 ptr += len;
432 while (*ptr == '/')
433 ptr ++;
435 subdir = FindNode (&node->subdirs, dirname);
437 if (!subdir)
438 break;
440 node = subdir;
443 return subdir;
446 static int nodedepth (struct DirNode * node)
448 int depth;
450 for (depth = 0; node->parent; depth++, node = node->parent);
452 return depth;
456 scandirnode (struct DirNode * node, const char * mfname, struct List * ignoredirs)
458 struct stat st;
459 DIR * dirh;
460 struct dirent * dirent;
462 int mfnamelen = strlen(mfname), scanned = 0;
465 * To avoid MetaMake going into infinite loop when circular
466 * linking is present, we limit the total depth.
468 if (nodedepth(node) > MAX_NODEDEPTH) {
469 error("scandirnode(): exceeded maximum directory depth of %d\n%s\n", MAX_NODEDEPTH, buildpath(node));
470 exit(20);
473 debug(printf("MMAKE:dirnode.c->scandirnode('%s')\n", node->node.name));
475 if (stat(".", &st) != 0)
477 error("scandirnode(): scanning %s\n",
478 strlen(node->node.name) == 0
479 ? "topdir"
480 : node->node.name);
482 exit(20);
485 if (st.st_mtime > node->time)
487 struct List newdirs, newmakefiles;
488 struct DirNode * subdir = NULL, * subdir2;
489 struct Makefile * makefile;
491 debug(printf("MMAKE:dirnode.c->scandirnode dir->time changed .. scanning\n"));
493 if (debug)
494 printf("[MMAKE] scandirnode(): scanning %s\n",
495 strlen(node->node.name)==0 ? "topdir" : buildpath(node)
498 NewList (&newdirs);
499 NewList (&newmakefiles);
501 node->time = st.st_mtime;
503 dirh = opendir (".");
504 if (!dirh)
506 error("opendir: could not open current dir");
507 exit(20);
510 while ((dirent = readdir (dirh)))
512 /* Add makefile if it present or the file with .src is present */
513 if (strcmp(dirent->d_name, mfname) == 0
514 || (strlen(dirent->d_name) == mfnamelen + 4
515 && strncmp(dirent->d_name, mfname, mfnamelen) == 0
516 && strcmp(dirent->d_name + mfnamelen, ".src") == 0
520 /* Don't add makefile twice */
521 debug(printf("MMAKE:dirnode.c->scandirnode: %s found ('%s')\n", mfname, dirent->d_name));
523 makefile = FindNode (&newmakefiles, mfname);
524 if (makefile == NULL)
526 debug(printf("MMAKE:dirnode.c->scandirnode: Creating New Makefile node\n"));
527 makefile = FindNode (&node->makefiles, mfname);
528 if (makefile != NULL)
530 Remove (makefile);
532 else
534 makefile = newnodesize (mfname, sizeof (struct Makefile));
535 makefile->dir = node;
536 debug(printf("MMAKE:dirnode.c->scandirnode: Makefile node dir '%s'\n", node->node.name));
537 makefile->time = (time_t)0;
538 NewList (&makefile->targets);
540 AddTail (&newmakefiles, makefile);
542 if (strcmp(dirent->d_name + mfnamelen, ".src") == 0)
543 makefile->generated = 1;
545 else
547 /* If the file is already in the makefiles from the current dirnode
548 * and it is still present in the directory copy it to the new makefiles
549 * list
551 if (strlen (dirent->d_name) > 4
552 && strcmp (dirent->d_name + strlen(dirent->d_name) - 4, ".src") == 0
555 dirent->d_name[strlen(dirent->d_name) - 4] = 0;
556 makefile = FindNode (&node->makefiles, dirent->d_name);
557 dirent->d_name[strlen(dirent->d_name)] = '.';
559 else
560 makefile = FindNode (&node->makefiles, dirent->d_name);
562 if (makefile != NULL)
564 Remove (makefile);
565 AddTail (&newmakefiles, makefile);
569 /* Add file to newsubdirs if it is a directory and it has not to be ignored
571 st.st_mode = 0; /* This makes us ignore the file if it can't be stat()'ed.
572 This lets us successfully skip Unicode-named files under Windows */
573 stat (dirent->d_name, &st);
575 if (S_ISDIR (st.st_mode)
576 && strcmp (dirent->d_name, ".") != 0
577 && strcmp (dirent->d_name, "..") != 0
578 && !FindNode (ignoredirs, dirent->d_name)
581 subdir = FindNode (&node->subdirs, dirent->d_name);
583 if (subdir != NULL)
585 Remove (subdir);
587 else
589 subdir = newnodesize (dirent->d_name, sizeof(struct DirNode));
590 debug(printf("MMAKE:dirnode.c->scandirnode: New SubDir Node '%s' @ %p\n", dirent->d_name, subdir));
591 subdir->parent = node;
592 subdir->time = (time_t)0;
593 NewList (&subdir->subdirs);
594 NewList (&subdir->makefiles);
596 AddTail (&newdirs, subdir);
601 closedir (dirh);
603 ForeachNodeSafe (&node->subdirs, subdir, subdir2)
604 freedirnode (subdir);
605 AssignList (&node->subdirs, &newdirs);
607 /* Clear the makefiles that have disappeared */
608 ForeachNode (&node->makefiles, makefile)
610 struct MakefileTarget * mftarget;
612 ForeachNode (&makefile->targets, mftarget)
613 freelist (&mftarget->deps);
615 freelist (&makefile->targets);
618 freelist (&node->makefiles);
620 AssignList (&node->makefiles, &newmakefiles);
622 scanned = 1;
625 debug(printf("MMAKE:dirnode.c->scandirnode: Finished scanning dir '%s'\n", node->node.name));
626 if (debug)
628 printf ("[MMAKE] scandirnode()\n");
629 printdirnode (node, 1);
632 return scanned;
637 scanmakefiles (struct Project * prj, struct DirNode * node, struct List * vars)
639 struct Makefile * makefile;
640 struct stat st;
641 int reread = 0;
642 FILE * fh;
644 debug(printf("MMAKE:dirnode.c->scanmakefiles('%s')\n", node->node.name));
646 assert (node);
648 ForeachNode (&node->makefiles, makefile)
650 debug(printf("MMAKE:dirnode.c->scanmakefiles: %d '%s'\n", makefile->generated, makefile->node.name));
652 if (makefile->generated == 0)
654 if (chdir(mm_srcdir) < 0)
656 error("Could not change to dir '%s'", mm_srcdir);
657 exit (20);
660 else
662 if (chdir(mm_builddir) < 0)
664 error("Could not change to dir '%s'", mm_builddir);
665 exit (20);
669 if ((strlen(makefile->dir->node.name) != 0) && (strcmp(makefile->dir->node.name, mm_srcdir) != 0))
671 if (chdir(buildpath(makefile->dir)) < 0)
673 error("Could not change to dir '%s'", makefile->dir->node.name);
674 exit (20);
678 if (stat(makefile->node.name, &st) != 0)
680 error("Could not stat %s", makefile->node.name);
681 exit(20);
684 if (st.st_mtime > makefile->time)
686 if (debug)
687 printf("[MMAKE] scanmakefiles(): scanning makefile in %s/%s\n",
688 strlen(node->node.name)==0 ? "topdir" : buildpath(node),
689 makefile->node.name
692 #if 0
693 printf ("Opening %s\n", makefile->name);
694 #endif
696 fh = fopen (makefile->node.name, "r");
697 if (!fh)
699 error ("buildtargetlist:fopen(): Opening %s for reading",
700 makefile->node.name
704 /* Free old metatargets when the file is reread */
705 freemakefiletargetlist (&makefile->targets);
706 NewList (&makefile->targets);
708 readtargets(node, makefile, fh);
710 reread ++;
711 makefile->time = st.st_mtime;
713 fclose (fh);
715 } /* If the makefile needed to be scanned */
716 } /* For all makefiles in the project */
718 return reread;
722 struct Makefile *
723 addmakefile (struct DirNode * node, const char * filename)
725 static char curdir[PATH_MAX];
726 const char * ptr = filename;
727 char * name;
728 int len = 0;
729 struct DirNode * subnode;
730 struct Makefile * makefile = NULL;
732 ASSERT(getcwd(curdir, PATH_MAX) != NULL);
734 while (ptr != NULL)
736 len = 0;
737 while (ptr[len] != '/' && ptr[len] != 0)
738 len++;
740 name = xmalloc (len+4+1); /* Make room for possibly adding .src at the end */
741 strncpy (name, ptr, len);
742 name[len] = 0;
744 if (ptr[len] == '/')
746 subnode = FindNode (&node->subdirs, name);
747 if (subnode == NULL)
749 xfree(name);
750 ASSERT(chdir (curdir) == 0);
751 return NULL;
753 ASSERT(chdir (name) == 0);
754 node = subnode;
755 ptr = ptr + len + 1;
757 else
759 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
760 name[len-4] = 0;
762 makefile = FindNode (&node->makefiles, name);
764 if (makefile == NULL)
766 struct stat st;
768 printf ("[MMAKE] Trying to stat %s\n", name);
770 if (stat(name, &st) != 0)
772 len = strlen(name);
773 strcat (name, ".src");
774 if (stat (name, &st) != 0)
776 xfree (name);
777 ASSERT(chdir (curdir) == 0);
778 return NULL;
780 name[len]=0;
783 makefile = newnodesize (name, sizeof (struct Makefile));
784 makefile->dir = node;
785 makefile->time = (time_t)0;
786 NewList (&makefile->targets);
787 AddTail (&node->makefiles, makefile);
790 ptr = NULL;
793 xfree (name);
796 ASSERT(chdir (curdir) == 0);
798 return makefile;
802 struct Makefile *
803 findmakefile (struct DirNode * node, const char *filename)
805 const char * ptr = filename;
806 char * name;
807 int len;
808 struct DirNode * subnode;
809 struct Makefile * makefile = NULL;
811 while (ptr != NULL)
813 len = 0;
814 while (ptr[len] != '/' && ptr[len] != 0)
815 len++;
817 name = xstrndup (ptr, len);
818 name[len] = 0;
820 if (ptr[len] == '/')
822 subnode = FindNode (&node->subdirs, name);
824 if (subnode == NULL)
826 xfree(name);
827 return NULL;
829 node = subnode;
830 ptr = ptr + len + 1;
832 else
834 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
835 name[len-4] = 0;
837 makefile = FindNode (&node->makefiles, name);
838 ptr = NULL;
841 xfree (name);
844 return makefile;
847 struct DirNodeRef
849 struct Node node;
850 struct DirNode * dirnode;
854 const char *
855 buildpath (struct DirNode * node)
857 static char path[PATH_MAX];
858 struct List tree;
859 struct DirNodeRef * ref = NULL;
861 NewList (&tree);
865 if ((strlen (node->node.name) > 0) && (strcmp(node->node.name, mm_srcdir) != 0))
867 ref = newnodesize ("", sizeof (struct DirNodeRef));
868 ref->dirnode = node;
869 AddHead (&tree, ref);
871 node = node->parent;
872 } while (node != NULL);
874 strcpy (path, "");
875 ForeachNode (&tree, ref)
877 if (path[0] != 0)
878 strcat (path, "/");
879 strcat (path, ref->dirnode->node.name);
882 freelist (&tree);
884 return path;
887 struct Makefile *
888 readmakefile (FILE * fh)
890 struct Makefile * makefile;
891 struct MakefileTarget * mftarget;
892 struct Node * n;
893 uint32_t intt;
894 char * s;
896 if (!readstring(fh, &s))
898 error ("readmakefile:readstring():%d", __LINE__);
899 exit (20);
902 if (s == NULL)
903 return NULL;
905 makefile = newnodesize(s, sizeof(struct Makefile));
906 xfree(s);
907 NewList(&makefile->targets);
909 if (!readuint32 (fh, &intt))
911 error ("readmakefile:fread():%d", __LINE__);
912 exit (20);
914 makefile->time = intt;
916 if (!readuint32 (fh, &intt))
918 error ("readmakefile:fread():%d", __LINE__);
919 exit (20);
921 makefile->generated = intt;
923 for (;;)
925 int32_t in;
927 if (!readstring(fh, &s))
929 error ("readmakefile:readstring():%d", __LINE__);
930 exit (20);
933 if (s == NULL)
934 break;
936 mftarget = newnodesize(s, sizeof(struct MakefileTarget));
937 xfree(s);
938 AddTail (&makefile->targets, mftarget);
939 NewList (&mftarget->deps);
941 if (!readint32 (fh, &in))
943 error ("readmakefile:fread():%d", __LINE__);
944 exit (20);
946 mftarget->virtualtarget = in;
948 for (;;)
950 if (!readstring(fh, &s))
952 error ("readmakefile:readstring():%d", __LINE__);
953 exit (20);
956 if (s == NULL)
957 break;
959 n = newnode(s);
960 xfree(s);
961 AddTail (&mftarget->deps, n);
965 return makefile;
970 writemakefile (FILE * fh, struct Makefile * makefile)
972 struct MakefileTarget * mftarget;
973 struct Node * n;
975 if (makefile == NULL)
977 if (!writestring (fh, NULL))
979 error ("writemakefile/writestring():%d", __LINE__);
980 return 0;
983 return 1;
986 if (!writestring (fh, makefile->node.name))
988 error ("writemakefile/writestring():%d", __LINE__);
989 return 0;
992 if (!writeuint32 (fh, makefile->time))
994 error ("writemakefile/fwrite():%d", __LINE__);
995 return 0;
998 if (!writeuint32 (fh, makefile->generated))
1000 error ("writemakefile/fwrite():%d", __LINE__);
1001 return 0;
1004 ForeachNode (&makefile->targets, mftarget)
1006 if (!writestring (fh, mftarget->node.name))
1008 error ("writemakefile/writestring():%d", __LINE__);
1009 return 0;
1012 if (!writeint32 (fh, mftarget->virtualtarget))
1014 error ("writemakefile/fwrite():%d", __LINE__);
1015 return 0;
1018 ForeachNode (&mftarget->deps, n)
1020 if (!writestring (fh, n->name))
1022 error ("writemakefile/writestring():%d", __LINE__);
1023 return 0;
1027 if (!writestring (fh, NULL))
1029 error ("writemakefile/writestring():%d", __LINE__);
1030 return 0;
1034 if (!writestring(fh, NULL))
1036 error ("writemakefile/writestring():%d", __LINE__);
1037 return 0;
1040 return 1;
1044 struct DirNode *
1045 readcachedir (FILE * fh)
1047 struct DirNode * node, * subnode;
1048 struct Makefile * makefile;
1049 uint32_t intt;
1050 char * s;
1052 if (!readstring(fh, &s))
1054 error ("readcachedir:readstring():%d", __LINE__);
1055 return NULL;
1058 if (s == NULL)
1059 return NULL;
1061 node = newnodesize(s, sizeof(struct DirNode));
1062 xfree (s);
1063 NewList(&node->makefiles);
1064 NewList(&node->subdirs);
1066 if (!readuint32 (fh, &intt))
1068 error ("readcachedir:fread():%d", __LINE__);
1069 free (node);
1070 return NULL;
1072 node->time = intt;
1074 while ((makefile = readmakefile (fh)))
1076 makefile->dir = node;
1077 AddTail (&node->makefiles, makefile);
1080 while ((subnode = readcachedir (fh)))
1082 subnode->parent = node;
1083 AddTail (&node->subdirs, subnode);
1086 return node;
1090 writecachedir (FILE * fh, struct DirNode * node)
1092 int out;
1093 struct DirNode * subnode;
1094 struct Makefile * makefile;
1096 if (node == NULL)
1098 if (!writestring(fh, NULL))
1100 error ("writecachedir/writestring():%d", __LINE__);
1101 return 0;
1104 return 1;
1107 if (!writestring(fh, node->node.name))
1109 error ("writecachedir/writestring():%d", __LINE__);
1110 return 0;
1113 if (!writeuint32 (fh, node->time))
1115 error ("writecachedir/fwrite():%d", __LINE__);
1116 return 0;
1119 ForeachNode (&node->makefiles, makefile)
1120 writemakefile (fh, makefile);
1122 if (!writemakefile (fh, NULL))
1123 return 0;
1125 ForeachNode (&node->subdirs, subnode)
1127 if (!writecachedir (fh, subnode))
1128 return 0;
1131 return writecachedir (fh, NULL);