ppp.device: Remove stale header
[AROS.git] / tools / MetaMake / dirnode.c
blobd83a55fd86ec01332c3358b63343906742fc49ec
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 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 fgets (line+strlen(line), linelen-strlen(line), fh);
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->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 fgets (line+strlen(line), linelen-strlen(line), fh);
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 /* Line with only #MM, metatarget is on next line */
204 char ** targets;
205 fgets (line, linelen, fh);
206 lineno ++;
208 ptr = line;
209 while (*ptr != ':' && *ptr)
210 ptr ++;
212 *ptr = 0;
214 targets = getargs (line, &count, NULL);
216 if (count > 0)
218 if (count > 1)
220 printf ("Warning: Multiple metatargets, only the 1st will be added in %s:%d (%s)\n",
221 makefile->node.name, lineno, buildpath(node)
223 /* FIXME: should we better add all metatargets? */
225 mftarget = FindNode (&makefile->targets, targets[0]);
227 if (mftarget == NULL)
229 mftarget = newmakefiletarget (targets[0], 0);
230 AddTail (&makefile->targets, mftarget);
232 else
233 mftarget->virtualtarget = 0;
235 else
236 printf ("Warning: Can't find metatarget in %s:%d (%s)\n", makefile->node.name, lineno, buildpath(node));
238 else
240 struct List newtargets;
241 char * ptr2 = ptr, ** tptr;
242 struct MakefileTarget * mftarget2, * mftarget3;
244 NewList (&newtargets);
246 while (*ptr2 != ':' && *ptr2)
247 ptr2 ++;
249 if (*ptr2 == ':')
250 *ptr2 ++ = 0;
252 tptr = getargs (ptr, &count, NULL);
254 for (t = 0; t < count; t++)
256 mftarget = newmakefiletarget (tptr[t], (flags & FLAG_VIRTUAL) != 0);
257 AddTail (&newtargets, mftarget);
260 tptr = getargs (ptr2, &count2, NULL);
262 if (count > 1 && count2 == 0)
264 /* could mean a missing colon */
265 printf ("Warning: multiple metatargets but no prerequisites %s:%d (%s)\n",
266 makefile->node.name, lineno, buildpath(node)
270 for (t = 0; t < count2; t++)
272 ForeachNode (&newtargets, mftarget)
273 addnodeonce (&mftarget->deps, tptr[t]);
276 ForeachNodeSafe (&newtargets, mftarget, mftarget2)
278 mftarget3 = FindNode (&makefile->targets, mftarget->node.name);
280 /* mftarget doesn't exists yet add it to targets */
281 if (mftarget3 == NULL)
283 Remove (mftarget);
284 AddTail (&makefile->targets, mftarget);
286 else
288 /* Merge data in mftarget into mftarget3 */
289 struct Node * node;
291 mftarget3->virtualtarget = mftarget3->virtualtarget && mftarget->virtualtarget;
293 ForeachNode (&mftarget->deps, node)
294 addnodeonce (&mftarget3->deps, node->name);
296 /* Free the targets from which the data was merged in other targets */
297 freemakefiletargetlist (&newtargets);
300 } /* If this is a MetaMake line in the makefile */
301 } /* For all lines in a makefile */
303 #if 0
304 printf ("Read %d lines\n", lineno);
305 #endif
308 /* Call mmakefile with _MM_ target */
309 static int
310 callmake_mm (struct Project * prj, struct Makefile * makefile)
312 static char buffer[4096];
313 const char * path = buildpath (makefile->dir);
314 const char * tname = "_MM_";
315 int t;
317 debug(printf("MMAKE:project.c->callmake()\n"));
319 #if 0
320 if (makefile->generated)
321 chdir (prj->buildtop);
322 else
323 chdir (prj->srctop);
324 chdir (path);
325 #endif
327 setvar (&prj->vars, "CURDIR", path);
328 setvar (&prj->vars, "TARGET", tname);
330 buffer[0] = '\0';
332 for (t=0; t<mflagc; t++)
334 strcat (buffer, mflags[t]);
335 strcat (buffer, " ");
338 if (strcmp (makefile->node.name, "Makefile")!=0 && strcmp (makefile->node.name, "makefile")!=0);
340 strcat (buffer, "--file=");
341 strcat (buffer, makefile->node.name);
342 strcat (buffer, " ");
345 strcat (buffer, tname);
347 printf ("Making %s in %s\n", tname, path);
349 /* TODO: create filename for output */
350 /* execute returns 0 for error */
351 return execute (prj, prj->maketool, "-", "-" /* "/home/mazze/mmtest" */, buffer);
354 void
355 freemakefiletarget (struct MakefileTarget * mftarget)
357 freelist (&mftarget->deps);
358 Remove(mftarget);
359 xfree (mftarget);
362 void
363 freemakefiletargetlist (struct List * targets)
365 struct MakefileTarget * mftarget, * mftarget2;
367 ForeachNodeSafe (targets, mftarget, mftarget2)
368 freemakefiletarget (mftarget);
370 NewList (targets);
373 void
374 printdirnode (struct DirNode * node, int level)
376 struct DirNode * subdir;
377 int t;
379 for (t=0; t<level; t++)
380 printf (" ");
382 printf ("%s\n", node->node.name);
384 level ++;
386 ForeachNode (&node->subdirs, subdir)
387 printdirnode (subdir, level);
390 void
391 printdirnodemftarget (struct DirNode * node)
393 struct Makefile * makefile;
394 struct MakefileTarget * mftarget;
395 struct Node * dep;
396 struct DirNode * subdir;
398 ForeachNode (&node->makefiles, makefile)
400 printf ("%s/%s:\n", buildpath(node), makefile->node.name);
401 ForeachNode (&makefile->targets, mftarget)
403 printf (" %s:", mftarget->node.name);
404 ForeachNode (&mftarget->deps, dep)
405 printf (" %s", dep->name);
406 printf ("\n");
410 ForeachNode (&node->subdirs, subdir)
411 printdirnodemftarget (subdir);
414 void
415 freedirnode (struct DirNode * node)
417 struct DirNode * subnode, * subnode2;
419 ForeachNodeSafe (&node->subdirs, subnode, subnode2)
420 freedirnode (subnode);
422 xfree (node->node.name);
423 xfree (node);
426 void
427 freemakefile (struct Makefile * makefile)
429 freemakefiletargetlist (&makefile->targets);
430 xfree (makefile->node.name);
431 xfree (makefile);
434 struct DirNode *
435 finddirnode (struct DirNode * topnode, const char * path)
437 const char * ptr;
438 char dirname[256];
439 int len;
440 struct DirNode * node = topnode, * subdir;
442 ptr = path+2;
444 if (!*ptr)
445 return node;
447 subdir = NULL;
449 while (*ptr)
451 for (len=0; ptr[len] && ptr[len] != '/'; len++);
453 strncpy (dirname, ptr, len);
454 dirname[len] = 0;
455 ptr += len;
456 while (*ptr == '/')
457 ptr ++;
459 subdir = FindNode (&node->subdirs, dirname);
461 if (!subdir)
462 break;
464 node = subdir;
467 return subdir;
470 static int nodedepth (struct DirNode * node)
472 int depth;
474 for (depth = 0; node->parent; depth++, node = node->parent);
476 return depth;
480 scandirnode (struct DirNode * node, const char * mfname, struct List * ignoredirs)
482 struct stat st;
483 DIR * dirh;
484 struct dirent * dirent;
486 int mfnamelen = strlen(mfname), scanned = 0;
489 * To avoid MetaMake going into infinite loop when circular
490 * linking is present, we limit the total depth.
492 if (nodedepth(node) > MAX_NODEDEPTH) {
493 error("scandirnode(): exceeded maximum directory depth of %d\n%s\n", MAX_NODEDEPTH, buildpath(node));
494 exit(20);
497 debug(printf("MMAKE:dirnode.c->scandirnode('%s')\n", node->node.name));
499 if (stat(".", &st) != 0)
501 error("scandirnode(): scanning %s\n",
502 strlen(node->node.name) == 0
503 ? "topdir"
504 : node->node.name);
506 exit(20);
509 if (st.st_mtime > node->time)
511 struct List newdirs, newmakefiles;
512 struct DirNode * subdir = NULL, * subdir2;
513 struct Makefile * makefile;
515 debug(printf("MMAKE:dirnode.c->scandirnode dir->time changed .. scanning\n"));
517 if (debug)
518 printf("scandirnode(): scanning %s\n",
519 strlen(node->node.name)==0 ? "topdir" : buildpath(node)
522 NewList (&newdirs);
523 NewList (&newmakefiles);
525 node->time = st.st_mtime;
527 dirh = opendir (".");
528 if (!dirh)
530 error("opendir: could not open current dir");
531 exit(20);
534 while ((dirent = readdir (dirh)))
536 /* Add makefile if it present or the file with .src is present */
537 if (strcmp(dirent->d_name, mfname) == 0
538 || (strlen(dirent->d_name) == mfnamelen + 4
539 && strncmp(dirent->d_name, mfname, mfnamelen) == 0
540 && strcmp(dirent->d_name + mfnamelen, ".src") == 0
544 /* Don't add makefile twice */
545 debug(printf("MMAKE:dirnode.c->scandirnode: %s found ('%s')\n", mfname, dirent->d_name));
547 makefile = FindNode (&newmakefiles, mfname);
548 if (makefile == NULL)
550 debug(printf("MMAKE:dirnode.c->scandirnode: Creating New Makefile node\n"));
551 makefile = FindNode (&node->makefiles, mfname);
552 if (makefile != NULL)
554 Remove (makefile);
556 else
558 makefile = newnodesize (mfname, sizeof (struct Makefile));
559 makefile->dir = node;
560 debug(printf("MMAKE:dirnode.c->scandirnode: Makefile node dir '%s'\n", node->node.name));
561 makefile->time = (time_t)0;
562 NewList (&makefile->targets);
564 AddTail (&newmakefiles, makefile);
566 if (strcmp(dirent->d_name + mfnamelen, ".src") == 0)
567 makefile->generated = 1;
569 else
571 /* If the file is already in the makefiles from the current dirnode
572 * and it is still present in the directory copy it to the new makefiles
573 * list
575 if (strlen (dirent->d_name) > 4
576 && strcmp (dirent->d_name + strlen(dirent->d_name) - 4, ".src") == 0
579 dirent->d_name[strlen(dirent->d_name) - 4] = 0;
580 makefile = FindNode (&node->makefiles, dirent->d_name);
581 dirent->d_name[strlen(dirent->d_name)] = '.';
583 else
584 makefile = FindNode (&node->makefiles, dirent->d_name);
586 if (makefile != NULL)
588 Remove (makefile);
589 AddTail (&newmakefiles, makefile);
593 /* Add file to newsubdirs if it is a directory and it has not to be ignored
595 st.st_mode = 0; /* This makes us to ignore the file if it can't be stat()'ed.
596 This lets us to succesfully skip Unicode-named files under Windows */
597 stat (dirent->d_name, &st);
599 if (S_ISDIR (st.st_mode)
600 && strcmp (dirent->d_name, ".") != 0
601 && strcmp (dirent->d_name, "..") != 0
602 && !FindNode (ignoredirs, dirent->d_name)
605 subdir = FindNode (&node->subdirs, dirent->d_name);
607 if (subdir != NULL)
609 Remove (subdir);
611 else
613 subdir = newnodesize (dirent->d_name, sizeof(struct DirNode));
614 debug(printf("MMAKE:dirnode.c->scandirnode: New SubDir Node '%s' @ %p\n", dirent->d_name, subdir));
615 subdir->parent = node;
616 subdir->time = (time_t)0;
617 NewList (&subdir->subdirs);
618 NewList (&subdir->makefiles);
620 AddTail (&newdirs, subdir);
625 closedir (dirh);
627 ForeachNodeSafe (&node->subdirs, subdir, subdir2)
628 freedirnode (subdir);
629 AssignList (&node->subdirs, &newdirs);
631 /* Clear the makefiles that have disappeared */
632 ForeachNode (&node->makefiles, makefile)
634 struct MakefileTarget * mftarget;
636 ForeachNode (&makefile->targets, mftarget)
637 freelist (&mftarget->deps);
639 freelist (&makefile->targets);
642 freelist (&node->makefiles);
644 AssignList (&node->makefiles, &newmakefiles);
646 scanned = 1;
649 debug(printf("MMAKE:dirnode.c->scandirnode: Finished scanning dir '%s'\n", node->node.name));
650 if (debug)
652 printf ("scandirnode()\n");
653 printdirnode (node, 1);
656 return scanned;
661 scanmakefiles (struct Project * prj, struct DirNode * node, struct List * vars)
663 struct Makefile * makefile;
664 struct stat st;
665 int reread = 0;
666 FILE * fh;
668 debug(printf("MMAKE:dirnode.c->scanmakefiles('%s')\n", node->node.name));
670 assert (node);
672 ForeachNode (&node->makefiles, makefile)
674 debug(printf("MMAKE:dirnode.c->scanmakefiles: %d '%s'\n", makefile->generated, makefile->node.name));
676 if (makefile->generated == 0)
678 if (chdir(mm_srcdir) < 0)
680 error("Could not change to dir '%s'", mm_srcdir);
681 exit (20);
684 else
686 if (chdir(mm_builddir) < 0)
688 error("Could not change to dir '%s'", mm_builddir);
689 exit (20);
693 if ((strlen(makefile->dir->node.name) != 0) && (strcmp(makefile->dir->node.name, mm_srcdir) != 0))
695 if (chdir(buildpath(makefile->dir)) < 0)
697 error("Could not change to dir '%s'", makefile->dir->node.name);
698 exit (20);
702 if (stat(makefile->node.name, &st) != 0)
704 error("Could not stat %s", makefile->node.name);
705 exit(20);
708 if (st.st_mtime > makefile->time)
710 if (debug)
711 printf("scanmakefiles(): scanning makefile in %s/%s\n",
712 strlen(node->node.name)==0 ? "topdir" : buildpath(node),
713 makefile->node.name
716 #if 0
717 printf ("Opening %s\n", makefile->name);
718 #endif
720 fh = fopen (makefile->node.name, "r");
721 if (!fh)
723 error ("buildtargetlist:fopen(): Opening %s for reading",
724 makefile->node.name
728 /* Free old metatargets when the file is reread */
729 freemakefiletargetlist (&makefile->targets);
730 NewList (&makefile->targets);
732 readtargets(node, makefile, fh);
734 reread ++;
735 makefile->time = st.st_mtime;
737 fclose (fh);
739 #if 0
740 /* Call make for _MM_ target */
741 if (callmake_mm (prj, makefile))
743 /* _MM_ found */
744 /* TODO: parsing of the result */
745 /* exit (666); */
747 #endif
749 } /* If the makefile needed to be scanned */
750 } /* For all makefiles in the project */
752 return reread;
756 struct Makefile *
757 addmakefile (struct DirNode * node, const char * filename)
759 static char curdir[PATH_MAX];
760 const char * ptr = filename;
761 char * name;
762 int len = 0;
763 struct DirNode * subnode;
764 struct Makefile * makefile = NULL;
766 getcwd(curdir, PATH_MAX);
768 while (ptr != NULL)
770 len = 0;
771 while (ptr[len] != '/' && ptr[len] != 0)
772 len++;
774 name = xmalloc (len+4+1); /* Make room for possibly adding .src at the end */
775 strncpy (name, ptr, len);
776 name[len] = 0;
778 if (ptr[len] == '/')
780 subnode = FindNode (&node->subdirs, name);
781 if (subnode == NULL)
783 xfree(name);
784 chdir (curdir);
785 return NULL;
787 chdir (name);
788 node = subnode;
789 ptr = ptr + len + 1;
791 else
793 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
794 name[len-4] = 0;
796 makefile = FindNode (&node->makefiles, name);
798 if (makefile == NULL)
800 struct stat st;
802 printf ("Trying to stat %s\n", name);
804 if (stat(name, &st) != 0)
806 len = strlen(name);
807 strcat (name, ".src");
808 if (stat (name, &st) != 0)
810 xfree (name);
811 chdir (curdir);
812 return NULL;
814 name[len]=0;
817 makefile = newnodesize (name, sizeof (struct Makefile));
818 makefile->dir = node;
819 makefile->time = (time_t)0;
820 NewList (&makefile->targets);
821 AddTail (&node->makefiles, makefile);
824 ptr = NULL;
827 xfree (name);
830 chdir (curdir);
832 return makefile;
836 struct Makefile *
837 findmakefile (struct DirNode * node, const char *filename)
839 const char * ptr = filename;
840 char * name;
841 int len;
842 struct DirNode * subnode;
843 struct Makefile * makefile = NULL;
845 while (ptr != NULL)
847 len = 0;
848 while (ptr[len] != '/' && ptr[len] != 0)
849 len++;
851 name = xstrndup (ptr, len);
852 name[len] = 0;
854 if (ptr[len] == '/')
856 subnode = FindNode (&node->subdirs, name);
858 if (subnode == NULL)
860 xfree(name);
861 return NULL;
863 node = subnode;
864 ptr = ptr + len + 1;
866 else
868 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
869 name[len-4] = 0;
871 makefile = FindNode (&node->makefiles, name);
872 ptr = NULL;
875 xfree (name);
878 return makefile;
881 struct DirNodeRef
883 struct Node node;
884 struct DirNode * dirnode;
888 const char *
889 buildpath (struct DirNode * node)
891 static char path[PATH_MAX];
892 struct List tree;
893 struct DirNodeRef * ref = NULL;
895 NewList (&tree);
899 if ((strlen (node->node.name) > 0) && (strcmp(node->node.name, mm_srcdir) != 0))
901 ref = newnodesize ("", sizeof (struct DirNodeRef));
902 ref->dirnode = node;
903 AddHead (&tree, ref);
905 node = node->parent;
906 } while (node != NULL);
908 strcpy (path, "");
909 ForeachNode (&tree, ref)
911 if (path[0] != 0)
912 strcat (path, "/");
913 strcat (path, ref->dirnode->node.name);
916 freelist (&tree);
918 return path;
921 struct Makefile *
922 readmakefile (FILE * fh)
924 struct Makefile * makefile;
925 struct MakefileTarget * mftarget;
926 struct Node * n;
927 uint32_t intt;
928 char * s;
930 if (!readstring(fh, &s))
932 error ("readmakefile:readstring():%d", __LINE__);
933 exit (20);
936 if (s == NULL)
937 return NULL;
939 makefile = newnodesize(s, sizeof(struct Makefile));
940 xfree(s);
941 NewList(&makefile->targets);
943 if (!readuint32 (fh, &intt))
945 error ("readmakefile:fread():%d", __LINE__);
946 exit (20);
948 makefile->time = intt;
950 if (!readuint32 (fh, &intt))
952 error ("readmakefile:fread():%d", __LINE__);
953 exit (20);
955 makefile->generated = intt;
957 for (;;)
959 int32_t in;
961 if (!readstring(fh, &s))
963 error ("readmakefile:readstring():%d", __LINE__);
964 exit (20);
967 if (s == NULL)
968 break;
970 mftarget = newnodesize(s, sizeof(struct MakefileTarget));
971 xfree(s);
972 AddTail (&makefile->targets, mftarget);
973 NewList (&mftarget->deps);
975 if (!readint32 (fh, &in))
977 error ("readmakefile:fread():%d", __LINE__);
978 exit (20);
980 mftarget->virtualtarget = in;
982 for (;;)
984 if (!readstring(fh, &s))
986 error ("readmakefile:readstring():%d", __LINE__);
987 exit (20);
990 if (s == NULL)
991 break;
993 n = newnode(s);
994 xfree(s);
995 AddTail (&mftarget->deps, n);
999 return makefile;
1004 writemakefile (FILE * fh, struct Makefile * makefile)
1006 struct MakefileTarget * mftarget;
1007 struct Node * n;
1009 if (makefile == NULL)
1011 if (!writestring (fh, NULL))
1013 error ("writemakefile/writestring():%d", __LINE__);
1014 return 0;
1017 return 1;
1020 if (!writestring (fh, makefile->node.name))
1022 error ("writemakefile/writestring():%d", __LINE__);
1023 return 0;
1026 if (!writeuint32 (fh, makefile->time))
1028 error ("writemakefile/fwrite():%d", __LINE__);
1029 return 0;
1032 if (!writeuint32 (fh, makefile->generated))
1034 error ("writemakefile/fwrite():%d", __LINE__);
1035 return 0;
1038 ForeachNode (&makefile->targets, mftarget)
1040 if (!writestring (fh, mftarget->node.name))
1042 error ("writemakefile/writestring():%d", __LINE__);
1043 return 0;
1046 if (!writeint32 (fh, mftarget->virtualtarget))
1048 error ("writemakefile/fwrite():%d", __LINE__);
1049 return 0;
1052 ForeachNode (&mftarget->deps, n)
1054 if (!writestring (fh, n->name))
1056 error ("writemakefile/writestring():%d", __LINE__);
1057 return 0;
1061 if (!writestring (fh, NULL))
1063 error ("writemakefile/writestring():%d", __LINE__);
1064 return 0;
1068 if (!writestring(fh, NULL))
1070 error ("writemakefile/writestring():%d", __LINE__);
1071 return 0;
1074 return 1;
1078 struct DirNode *
1079 readcachedir (FILE * fh)
1081 struct DirNode * node, * subnode;
1082 struct Makefile * makefile;
1083 uint32_t intt;
1084 char * s;
1086 if (!readstring(fh, &s))
1088 error ("readcachedir:readstring():%d", __LINE__);
1089 return NULL;
1092 if (s == NULL)
1093 return NULL;
1095 node = newnodesize(s, sizeof(struct DirNode));
1096 xfree (s);
1097 NewList(&node->makefiles);
1098 NewList(&node->subdirs);
1100 if (!readuint32 (fh, &intt))
1102 error ("readcachedir:fread():%d", __LINE__);
1103 free (node);
1104 return NULL;
1106 node->time = intt;
1108 while ((makefile = readmakefile (fh)))
1110 makefile->dir = node;
1111 AddTail (&node->makefiles, makefile);
1114 while ((subnode = readcachedir (fh)))
1116 subnode->parent = node;
1117 AddTail (&node->subdirs, subnode);
1120 return node;
1124 writecachedir (FILE * fh, struct DirNode * node)
1126 int out;
1127 struct DirNode * subnode;
1128 struct Makefile * makefile;
1130 if (node == NULL)
1132 if (!writestring(fh, NULL))
1134 error ("writecachedir/writestring():%d", __LINE__);
1135 return 0;
1138 return 1;
1141 if (!writestring(fh, node->node.name))
1143 error ("writecachedir/writestring():%d", __LINE__);
1144 return 0;
1147 if (!writeuint32 (fh, node->time))
1149 error ("writecachedir/fwrite():%d", __LINE__);
1150 return 0;
1153 ForeachNode (&node->makefiles, makefile)
1154 writemakefile (fh, makefile);
1156 if (!writemakefile (fh, NULL))
1157 return 0;
1159 ForeachNode (&node->subdirs, subnode)
1161 if (!writecachedir (fh, subnode))
1162 return 0;
1165 return writecachedir (fh, NULL);