Workbook: big pile of rendering cleanups
[AROS.git] / tools / MetaMake / dirnode.c
blobe6954d464f0cc3e67cd7a6c9eba62fe2e988eacd
1 /* MetaMake - A Make extension
2 Copyright © 1995-2012, 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->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 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 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 fgets (line, linelen, fh);
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 ("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 ("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 ("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 /* Call mmakefile with _MM_ target */
331 static int
332 callmake_mm (struct Project * prj, struct Makefile * makefile)
334 static char buffer[4096];
335 const char * path = buildpath (makefile->dir);
336 const char * tname = "_MM_";
337 int t;
339 debug(printf("MMAKE:project.c->callmake()\n"));
341 #if 0
342 if (makefile->generated)
343 chdir (prj->buildtop);
344 else
345 chdir (prj->srctop);
346 chdir (path);
347 #endif
349 setvar (&prj->vars, "CURDIR", path);
350 setvar (&prj->vars, "TARGET", tname);
352 buffer[0] = '\0';
354 for (t=0; t<mflagc; t++)
356 strcat (buffer, mflags[t]);
357 strcat (buffer, " ");
360 if (strcmp (makefile->node.name, "Makefile")!=0 && strcmp (makefile->node.name, "makefile")!=0);
362 strcat (buffer, "--file=");
363 strcat (buffer, makefile->node.name);
364 strcat (buffer, " ");
367 strcat (buffer, tname);
369 printf ("Making %s in %s\n", tname, path);
371 /* TODO: create filename for output */
372 /* execute returns 0 for error */
373 return execute (prj, prj->maketool, "-", "-" /* "/home/mazze/mmtest" */, buffer);
376 void
377 freemakefiletarget (struct MakefileTarget * mftarget)
379 freelist (&mftarget->deps);
380 Remove(mftarget);
381 xfree (mftarget);
384 void
385 freemakefiletargetlist (struct List * targets)
387 struct MakefileTarget * mftarget, * mftarget2;
389 ForeachNodeSafe (targets, mftarget, mftarget2)
390 freemakefiletarget (mftarget);
392 NewList (targets);
395 void
396 printdirnode (struct DirNode * node, int level)
398 struct DirNode * subdir;
399 int t;
401 for (t=0; t<level; t++)
402 printf (" ");
404 printf ("%s\n", node->node.name);
406 level ++;
408 ForeachNode (&node->subdirs, subdir)
409 printdirnode (subdir, level);
412 void
413 printdirnodemftarget (struct DirNode * node)
415 struct Makefile * makefile;
416 struct MakefileTarget * mftarget;
417 struct Node * dep;
418 struct DirNode * subdir;
420 ForeachNode (&node->makefiles, makefile)
422 printf ("%s/%s:\n", buildpath(node), makefile->node.name);
423 ForeachNode (&makefile->targets, mftarget)
425 printf (" %s:", mftarget->node.name);
426 ForeachNode (&mftarget->deps, dep)
427 printf (" %s", dep->name);
428 printf ("\n");
432 ForeachNode (&node->subdirs, subdir)
433 printdirnodemftarget (subdir);
436 void
437 freedirnode (struct DirNode * node)
439 struct DirNode * subnode, * subnode2;
441 ForeachNodeSafe (&node->subdirs, subnode, subnode2)
442 freedirnode (subnode);
444 xfree (node->node.name);
445 xfree (node);
448 void
449 freemakefile (struct Makefile * makefile)
451 freemakefiletargetlist (&makefile->targets);
452 xfree (makefile->node.name);
453 xfree (makefile);
456 struct DirNode *
457 finddirnode (struct DirNode * topnode, const char * path)
459 const char * ptr;
460 char dirname[256];
461 int len;
462 struct DirNode * node = topnode, * subdir;
464 ptr = path+2;
466 if (!*ptr)
467 return node;
469 subdir = NULL;
471 while (*ptr)
473 for (len=0; ptr[len] && ptr[len] != '/'; len++);
475 strncpy (dirname, ptr, len);
476 dirname[len] = 0;
477 ptr += len;
478 while (*ptr == '/')
479 ptr ++;
481 subdir = FindNode (&node->subdirs, dirname);
483 if (!subdir)
484 break;
486 node = subdir;
489 return subdir;
492 static int nodedepth (struct DirNode * node)
494 int depth;
496 for (depth = 0; node->parent; depth++, node = node->parent);
498 return depth;
502 scandirnode (struct DirNode * node, const char * mfname, struct List * ignoredirs)
504 struct stat st;
505 DIR * dirh;
506 struct dirent * dirent;
508 int mfnamelen = strlen(mfname), scanned = 0;
511 * To avoid MetaMake going into infinite loop when circular
512 * linking is present, we limit the total depth.
514 if (nodedepth(node) > MAX_NODEDEPTH) {
515 error("scandirnode(): exceeded maximum directory depth of %d\n%s\n", MAX_NODEDEPTH, buildpath(node));
516 exit(20);
519 debug(printf("MMAKE:dirnode.c->scandirnode('%s')\n", node->node.name));
521 if (stat(".", &st) != 0)
523 error("scandirnode(): scanning %s\n",
524 strlen(node->node.name) == 0
525 ? "topdir"
526 : node->node.name);
528 exit(20);
531 if (st.st_mtime > node->time)
533 struct List newdirs, newmakefiles;
534 struct DirNode * subdir = NULL, * subdir2;
535 struct Makefile * makefile;
537 debug(printf("MMAKE:dirnode.c->scandirnode dir->time changed .. scanning\n"));
539 if (debug)
540 printf("scandirnode(): scanning %s\n",
541 strlen(node->node.name)==0 ? "topdir" : buildpath(node)
544 NewList (&newdirs);
545 NewList (&newmakefiles);
547 node->time = st.st_mtime;
549 dirh = opendir (".");
550 if (!dirh)
552 error("opendir: could not open current dir");
553 exit(20);
556 while ((dirent = readdir (dirh)))
558 /* Add makefile if it present or the file with .src is present */
559 if (strcmp(dirent->d_name, mfname) == 0
560 || (strlen(dirent->d_name) == mfnamelen + 4
561 && strncmp(dirent->d_name, mfname, mfnamelen) == 0
562 && strcmp(dirent->d_name + mfnamelen, ".src") == 0
566 /* Don't add makefile twice */
567 debug(printf("MMAKE:dirnode.c->scandirnode: %s found ('%s')\n", mfname, dirent->d_name));
569 makefile = FindNode (&newmakefiles, mfname);
570 if (makefile == NULL)
572 debug(printf("MMAKE:dirnode.c->scandirnode: Creating New Makefile node\n"));
573 makefile = FindNode (&node->makefiles, mfname);
574 if (makefile != NULL)
576 Remove (makefile);
578 else
580 makefile = newnodesize (mfname, sizeof (struct Makefile));
581 makefile->dir = node;
582 debug(printf("MMAKE:dirnode.c->scandirnode: Makefile node dir '%s'\n", node->node.name));
583 makefile->time = (time_t)0;
584 NewList (&makefile->targets);
586 AddTail (&newmakefiles, makefile);
588 if (strcmp(dirent->d_name + mfnamelen, ".src") == 0)
589 makefile->generated = 1;
591 else
593 /* If the file is already in the makefiles from the current dirnode
594 * and it is still present in the directory copy it to the new makefiles
595 * list
597 if (strlen (dirent->d_name) > 4
598 && strcmp (dirent->d_name + strlen(dirent->d_name) - 4, ".src") == 0
601 dirent->d_name[strlen(dirent->d_name) - 4] = 0;
602 makefile = FindNode (&node->makefiles, dirent->d_name);
603 dirent->d_name[strlen(dirent->d_name)] = '.';
605 else
606 makefile = FindNode (&node->makefiles, dirent->d_name);
608 if (makefile != NULL)
610 Remove (makefile);
611 AddTail (&newmakefiles, makefile);
615 /* Add file to newsubdirs if it is a directory and it has not to be ignored
617 st.st_mode = 0; /* This makes us to ignore the file if it can't be stat()'ed.
618 This lets us to succesfully skip Unicode-named files under Windows */
619 stat (dirent->d_name, &st);
621 if (S_ISDIR (st.st_mode)
622 && strcmp (dirent->d_name, ".") != 0
623 && strcmp (dirent->d_name, "..") != 0
624 && !FindNode (ignoredirs, dirent->d_name)
627 subdir = FindNode (&node->subdirs, dirent->d_name);
629 if (subdir != NULL)
631 Remove (subdir);
633 else
635 subdir = newnodesize (dirent->d_name, sizeof(struct DirNode));
636 debug(printf("MMAKE:dirnode.c->scandirnode: New SubDir Node '%s' @ %p\n", dirent->d_name, subdir));
637 subdir->parent = node;
638 subdir->time = (time_t)0;
639 NewList (&subdir->subdirs);
640 NewList (&subdir->makefiles);
642 AddTail (&newdirs, subdir);
647 closedir (dirh);
649 ForeachNodeSafe (&node->subdirs, subdir, subdir2)
650 freedirnode (subdir);
651 AssignList (&node->subdirs, &newdirs);
653 /* Clear the makefiles that have disappeared */
654 ForeachNode (&node->makefiles, makefile)
656 struct MakefileTarget * mftarget;
658 ForeachNode (&makefile->targets, mftarget)
659 freelist (&mftarget->deps);
661 freelist (&makefile->targets);
664 freelist (&node->makefiles);
666 AssignList (&node->makefiles, &newmakefiles);
668 scanned = 1;
671 debug(printf("MMAKE:dirnode.c->scandirnode: Finished scanning dir '%s'\n", node->node.name));
672 if (debug)
674 printf ("scandirnode()\n");
675 printdirnode (node, 1);
678 return scanned;
683 scanmakefiles (struct Project * prj, struct DirNode * node, struct List * vars)
685 struct Makefile * makefile;
686 struct stat st;
687 int reread = 0;
688 FILE * fh;
690 debug(printf("MMAKE:dirnode.c->scanmakefiles('%s')\n", node->node.name));
692 assert (node);
694 ForeachNode (&node->makefiles, makefile)
696 debug(printf("MMAKE:dirnode.c->scanmakefiles: %d '%s'\n", makefile->generated, makefile->node.name));
698 if (makefile->generated == 0)
700 if (chdir(mm_srcdir) < 0)
702 error("Could not change to dir '%s'", mm_srcdir);
703 exit (20);
706 else
708 if (chdir(mm_builddir) < 0)
710 error("Could not change to dir '%s'", mm_builddir);
711 exit (20);
715 if ((strlen(makefile->dir->node.name) != 0) && (strcmp(makefile->dir->node.name, mm_srcdir) != 0))
717 if (chdir(buildpath(makefile->dir)) < 0)
719 error("Could not change to dir '%s'", makefile->dir->node.name);
720 exit (20);
724 if (stat(makefile->node.name, &st) != 0)
726 error("Could not stat %s", makefile->node.name);
727 exit(20);
730 if (st.st_mtime > makefile->time)
732 if (debug)
733 printf("scanmakefiles(): scanning makefile in %s/%s\n",
734 strlen(node->node.name)==0 ? "topdir" : buildpath(node),
735 makefile->node.name
738 #if 0
739 printf ("Opening %s\n", makefile->name);
740 #endif
742 fh = fopen (makefile->node.name, "r");
743 if (!fh)
745 error ("buildtargetlist:fopen(): Opening %s for reading",
746 makefile->node.name
750 /* Free old metatargets when the file is reread */
751 freemakefiletargetlist (&makefile->targets);
752 NewList (&makefile->targets);
754 readtargets(node, makefile, fh);
756 reread ++;
757 makefile->time = st.st_mtime;
759 fclose (fh);
761 #if 0
762 /* Call make for _MM_ target */
763 if (callmake_mm (prj, makefile))
765 /* _MM_ found */
766 /* TODO: parsing of the result */
767 /* exit (666); */
769 #endif
771 } /* If the makefile needed to be scanned */
772 } /* For all makefiles in the project */
774 return reread;
778 struct Makefile *
779 addmakefile (struct DirNode * node, const char * filename)
781 static char curdir[PATH_MAX];
782 const char * ptr = filename;
783 char * name;
784 int len = 0;
785 struct DirNode * subnode;
786 struct Makefile * makefile = NULL;
788 getcwd(curdir, PATH_MAX);
790 while (ptr != NULL)
792 len = 0;
793 while (ptr[len] != '/' && ptr[len] != 0)
794 len++;
796 name = xmalloc (len+4+1); /* Make room for possibly adding .src at the end */
797 strncpy (name, ptr, len);
798 name[len] = 0;
800 if (ptr[len] == '/')
802 subnode = FindNode (&node->subdirs, name);
803 if (subnode == NULL)
805 xfree(name);
806 chdir (curdir);
807 return NULL;
809 chdir (name);
810 node = subnode;
811 ptr = ptr + len + 1;
813 else
815 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
816 name[len-4] = 0;
818 makefile = FindNode (&node->makefiles, name);
820 if (makefile == NULL)
822 struct stat st;
824 printf ("Trying to stat %s\n", name);
826 if (stat(name, &st) != 0)
828 len = strlen(name);
829 strcat (name, ".src");
830 if (stat (name, &st) != 0)
832 xfree (name);
833 chdir (curdir);
834 return NULL;
836 name[len]=0;
839 makefile = newnodesize (name, sizeof (struct Makefile));
840 makefile->dir = node;
841 makefile->time = (time_t)0;
842 NewList (&makefile->targets);
843 AddTail (&node->makefiles, makefile);
846 ptr = NULL;
849 xfree (name);
852 chdir (curdir);
854 return makefile;
858 struct Makefile *
859 findmakefile (struct DirNode * node, const char *filename)
861 const char * ptr = filename;
862 char * name;
863 int len;
864 struct DirNode * subnode;
865 struct Makefile * makefile = NULL;
867 while (ptr != NULL)
869 len = 0;
870 while (ptr[len] != '/' && ptr[len] != 0)
871 len++;
873 name = xstrndup (ptr, len);
874 name[len] = 0;
876 if (ptr[len] == '/')
878 subnode = FindNode (&node->subdirs, name);
880 if (subnode == NULL)
882 xfree(name);
883 return NULL;
885 node = subnode;
886 ptr = ptr + len + 1;
888 else
890 if (len >= 4 && strcmp (name+len-4, ".src") == 0)
891 name[len-4] = 0;
893 makefile = FindNode (&node->makefiles, name);
894 ptr = NULL;
897 xfree (name);
900 return makefile;
903 struct DirNodeRef
905 struct Node node;
906 struct DirNode * dirnode;
910 const char *
911 buildpath (struct DirNode * node)
913 static char path[PATH_MAX];
914 struct List tree;
915 struct DirNodeRef * ref = NULL;
917 NewList (&tree);
921 if ((strlen (node->node.name) > 0) && (strcmp(node->node.name, mm_srcdir) != 0))
923 ref = newnodesize ("", sizeof (struct DirNodeRef));
924 ref->dirnode = node;
925 AddHead (&tree, ref);
927 node = node->parent;
928 } while (node != NULL);
930 strcpy (path, "");
931 ForeachNode (&tree, ref)
933 if (path[0] != 0)
934 strcat (path, "/");
935 strcat (path, ref->dirnode->node.name);
938 freelist (&tree);
940 return path;
943 struct Makefile *
944 readmakefile (FILE * fh)
946 struct Makefile * makefile;
947 struct MakefileTarget * mftarget;
948 struct Node * n;
949 uint32_t intt;
950 char * s;
952 if (!readstring(fh, &s))
954 error ("readmakefile:readstring():%d", __LINE__);
955 exit (20);
958 if (s == NULL)
959 return NULL;
961 makefile = newnodesize(s, sizeof(struct Makefile));
962 xfree(s);
963 NewList(&makefile->targets);
965 if (!readuint32 (fh, &intt))
967 error ("readmakefile:fread():%d", __LINE__);
968 exit (20);
970 makefile->time = intt;
972 if (!readuint32 (fh, &intt))
974 error ("readmakefile:fread():%d", __LINE__);
975 exit (20);
977 makefile->generated = intt;
979 for (;;)
981 int32_t in;
983 if (!readstring(fh, &s))
985 error ("readmakefile:readstring():%d", __LINE__);
986 exit (20);
989 if (s == NULL)
990 break;
992 mftarget = newnodesize(s, sizeof(struct MakefileTarget));
993 xfree(s);
994 AddTail (&makefile->targets, mftarget);
995 NewList (&mftarget->deps);
997 if (!readint32 (fh, &in))
999 error ("readmakefile:fread():%d", __LINE__);
1000 exit (20);
1002 mftarget->virtualtarget = in;
1004 for (;;)
1006 if (!readstring(fh, &s))
1008 error ("readmakefile:readstring():%d", __LINE__);
1009 exit (20);
1012 if (s == NULL)
1013 break;
1015 n = newnode(s);
1016 xfree(s);
1017 AddTail (&mftarget->deps, n);
1021 return makefile;
1026 writemakefile (FILE * fh, struct Makefile * makefile)
1028 struct MakefileTarget * mftarget;
1029 struct Node * n;
1031 if (makefile == NULL)
1033 if (!writestring (fh, NULL))
1035 error ("writemakefile/writestring():%d", __LINE__);
1036 return 0;
1039 return 1;
1042 if (!writestring (fh, makefile->node.name))
1044 error ("writemakefile/writestring():%d", __LINE__);
1045 return 0;
1048 if (!writeuint32 (fh, makefile->time))
1050 error ("writemakefile/fwrite():%d", __LINE__);
1051 return 0;
1054 if (!writeuint32 (fh, makefile->generated))
1056 error ("writemakefile/fwrite():%d", __LINE__);
1057 return 0;
1060 ForeachNode (&makefile->targets, mftarget)
1062 if (!writestring (fh, mftarget->node.name))
1064 error ("writemakefile/writestring():%d", __LINE__);
1065 return 0;
1068 if (!writeint32 (fh, mftarget->virtualtarget))
1070 error ("writemakefile/fwrite():%d", __LINE__);
1071 return 0;
1074 ForeachNode (&mftarget->deps, n)
1076 if (!writestring (fh, n->name))
1078 error ("writemakefile/writestring():%d", __LINE__);
1079 return 0;
1083 if (!writestring (fh, NULL))
1085 error ("writemakefile/writestring():%d", __LINE__);
1086 return 0;
1090 if (!writestring(fh, NULL))
1092 error ("writemakefile/writestring():%d", __LINE__);
1093 return 0;
1096 return 1;
1100 struct DirNode *
1101 readcachedir (FILE * fh)
1103 struct DirNode * node, * subnode;
1104 struct Makefile * makefile;
1105 uint32_t intt;
1106 char * s;
1108 if (!readstring(fh, &s))
1110 error ("readcachedir:readstring():%d", __LINE__);
1111 return NULL;
1114 if (s == NULL)
1115 return NULL;
1117 node = newnodesize(s, sizeof(struct DirNode));
1118 xfree (s);
1119 NewList(&node->makefiles);
1120 NewList(&node->subdirs);
1122 if (!readuint32 (fh, &intt))
1124 error ("readcachedir:fread():%d", __LINE__);
1125 free (node);
1126 return NULL;
1128 node->time = intt;
1130 while ((makefile = readmakefile (fh)))
1132 makefile->dir = node;
1133 AddTail (&node->makefiles, makefile);
1136 while ((subnode = readcachedir (fh)))
1138 subnode->parent = node;
1139 AddTail (&node->subdirs, subnode);
1142 return node;
1146 writecachedir (FILE * fh, struct DirNode * node)
1148 int out;
1149 struct DirNode * subnode;
1150 struct Makefile * makefile;
1152 if (node == NULL)
1154 if (!writestring(fh, NULL))
1156 error ("writecachedir/writestring():%d", __LINE__);
1157 return 0;
1160 return 1;
1163 if (!writestring(fh, node->node.name))
1165 error ("writecachedir/writestring():%d", __LINE__);
1166 return 0;
1169 if (!writeuint32 (fh, node->time))
1171 error ("writecachedir/fwrite():%d", __LINE__);
1172 return 0;
1175 ForeachNode (&node->makefiles, makefile)
1176 writemakefile (fh, makefile);
1178 if (!writemakefile (fh, NULL))
1179 return 0;
1181 ForeachNode (&node->subdirs, subnode)
1183 if (!writecachedir (fh, subnode))
1184 return 0;
1187 return writecachedir (fh, NULL);