kbuild.c: added todo for #80.
[kbuild-mirror.git] / src / kmk / incdep.c
blob5549d0f070c26fd7d8ad7e2e836cb843717bbc6e
1 #ifdef CONFIG_WITH_INCLUDEDEP
2 /* $Id$ */
3 /** @file
4 * incdep - Simple dependency files.
5 */
7 /*
8 * Copyright (c) 2007-2008 knut st. osmundsen <bird-src-spam@anduin.net>
10 * This file is part of kBuild.
12 * kBuild is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * kBuild is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
27 /*******************************************************************************
28 * Header Files *
29 *******************************************************************************/
30 #ifdef __OS2__
31 # define INCL_BASE
32 # define INCL_ERRORS
33 #endif
35 #include "make.h"
37 #if !defined(WINDOWS32) && !defined(__OS2__)
38 # define HAVE_PTHREAD
39 #endif
41 #include <assert.h>
43 #include <glob.h>
45 #include "dep.h"
46 #include "filedef.h"
47 #include "job.h"
48 #include "commands.h"
49 #include "variable.h"
50 #include "rule.h"
51 #include "debug.h"
52 #include "strcache2.h"
54 #ifdef HAVE_FCNTL_H
55 # include <fcntl.h>
56 #else
57 # include <sys/file.h>
58 #endif
60 #ifdef WINDOWS32
61 # include <io.h>
62 # include <process.h>
63 # include <Windows.h>
64 # define PARSE_IN_WORKER
65 #endif
67 #ifdef __OS2__
68 # include <os2.h>
69 # include <sys/fmutex.h>
70 #endif
72 #ifdef HAVE_PTHREAD
73 # include <pthread.h>
74 #endif
76 #ifdef __APPLE__
77 # include <malloc/malloc.h>
78 # define PARSE_IN_WORKER
79 #endif
81 #if defined(__gnu_linux__) || defined(__linux__)
82 # define PARSE_IN_WORKER
83 #endif
86 /*******************************************************************************
87 * Structures and Typedefs *
88 *******************************************************************************/
89 struct incdep_variable_in_set
91 struct incdep_variable_in_set *next;
92 /* the parameters */
93 struct strcache2_entry *name_entry; /* dep strcache - WRONG */
94 const char *value; /* xmalloc'ed */
95 unsigned int value_length;
96 int duplicate_value; /* 0 */
97 enum variable_origin origin;
98 int recursive;
99 struct variable_set *set;
100 const struct floc *flocp; /* NILF */
103 struct incdep_variable_def
105 struct incdep_variable_def *next;
106 /* the parameters */
107 const struct floc *flocp; /* NILF */
108 struct strcache2_entry *name_entry; /* dep strcache - WRONG */
109 char *value; /* xmalloc'ed, free it */
110 unsigned int value_length;
111 enum variable_origin origin;
112 enum variable_flavor flavor;
113 int target_var;
116 struct incdep_recorded_files
118 struct incdep_recorded_files *next;
120 /* the parameters */
121 struct strcache2_entry *filename_entry; /* dep strcache; converted to a nameseq record. */
122 const char *pattern; /* NULL */
123 const char *pattern_percent; /* NULL */
124 struct dep *deps; /* All the names are dep strcache entries. */
125 unsigned int cmds_started; /* 0 */
126 char *commands; /* NULL */
127 unsigned int commands_idx; /* 0 */
128 int two_colon; /* 0 */
129 const struct floc *flocp; /* NILF */
133 /* per dep file structure. */
134 struct incdep
136 struct incdep *next;
137 char *file_base;
138 char *file_end;
140 int worker_tid;
141 #ifdef PARSE_IN_WORKER
142 unsigned int err_line_no;
143 const char *err_msg;
145 struct incdep_variable_in_set *recorded_variables_in_set_head;
146 struct incdep_variable_in_set *recorded_variables_in_set_tail;
148 struct incdep_variable_def *recorded_variable_defs_head;
149 struct incdep_variable_def *recorded_variable_defs_tail;
151 struct incdep_recorded_files *recorded_files_head;
152 struct incdep_recorded_files *recorded_files_tail;
153 #endif
155 char name[1];
159 /*******************************************************************************
160 * Global Variables *
161 *******************************************************************************/
163 /* mutex protecting the globals and an associated condition/event. */
164 #ifdef HAVE_PTHREAD
165 static pthread_mutex_t incdep_mtx;
166 static pthread_cond_t incdep_cond_todo;
167 static pthread_cond_t incdep_cond_done;
169 #elif defined (WINDOWS32)
170 static CRITICAL_SECTION incdep_mtx;
171 static HANDLE incdep_hev_todo;
172 static HANDLE incdep_hev_done;
173 static int volatile incdep_hev_todo_waiters;
174 static int volatile incdep_hev_done_waiters;
176 #elif defined (__OS2__)
177 static _fmutex incdep_mtx;
178 static HEV incdep_hev_todo;
179 static HEV incdep_hev_done;
180 static int volatile incdep_hev_todo_waiters;
181 static int volatile incdep_hev_done_waiters;
182 #endif
184 /* flag indicating whether the threads, lock and event/condvars has
185 been initialized or not. */
186 static int incdep_initialized;
188 /* the list of files that needs reading. */
189 static struct incdep * volatile incdep_head_todo;
190 static struct incdep * volatile incdep_tail_todo;
192 /* the number of files that are currently being read. */
193 static int volatile incdep_num_reading;
195 /* the list of files that have been read. */
196 static struct incdep * volatile incdep_head_done;
197 static struct incdep * volatile incdep_tail_done;
200 /* The handles to the worker threads. */
201 #ifdef HAVE_PTHREAD
202 # define INCDEP_MAX_THREADS 1
203 static pthread_t incdep_threads[INCDEP_MAX_THREADS];
205 #elif defined (WINDOWS32)
206 # define INCDEP_MAX_THREADS 2
207 static HANDLE incdep_threads[INCDEP_MAX_THREADS];
209 #elif defined (__OS2__)
210 # define INCDEP_MAX_THREADS 2
211 static TID incdep_threads[INCDEP_MAX_THREADS];
212 #endif
214 static struct alloccache incdep_rec_caches[INCDEP_MAX_THREADS];
215 static struct alloccache incdep_dep_caches[INCDEP_MAX_THREADS];
216 static struct strcache2 incdep_dep_strcaches[INCDEP_MAX_THREADS];
217 static struct strcache2 incdep_var_strcaches[INCDEP_MAX_THREADS];
218 static unsigned incdep_num_threads;
220 /* flag indicating whether the worker threads should terminate or not. */
221 static int volatile incdep_terminate;
223 #ifdef __APPLE__
224 /* malloc zone for the incdep threads. */
225 static malloc_zone_t *incdep_zone;
226 #endif
229 /*******************************************************************************
230 * Internal Functions *
231 *******************************************************************************/
232 static void incdep_flush_it (struct floc *);
233 static void eval_include_dep_file (struct incdep *, struct floc *);
236 /* xmalloc wrapper.
237 For working around multithreaded performance problems found on Darwin,
238 Linux (glibc), and possibly other systems. */
239 static void *
240 incdep_xmalloc (struct incdep *cur, size_t size)
242 void *ptr;
244 #ifdef __APPLE__
245 if (cur && cur->worker_tid != -1)
247 ptr = malloc_zone_malloc (incdep_zone, size);
248 if (!ptr)
249 fatal (NILF, _("virtual memory exhausted"));
251 else
252 ptr = xmalloc (size);
253 #else
254 ptr = xmalloc (size);
255 #endif
257 (void)cur;
258 return ptr;
261 #if 0
262 /* memset(malloc(sz),'\0',sz) wrapper. */
263 static void *
264 incdep_xcalloc (struct incdep *cur, size_t size)
266 void *ptr;
268 #ifdef __APPLE__
269 if (cur && cur->worker_tid != -1)
270 ptr = malloc_zone_calloc (incdep_zone, size, 1);
271 else
272 ptr = calloc (size, 1);
273 #else
274 ptr = calloc (size, 1);
275 #endif
276 if (!ptr)
277 fatal (NILF, _("virtual memory exhausted"));
279 (void)cur;
280 return ptr;
282 #endif /* unused */
284 /* free wrapper */
285 static void
286 incdep_xfree (struct incdep *cur, void *ptr)
288 /* free() *must* work for the allocation hacks above because
289 of free_dep_chain. */
290 free (ptr);
291 (void)cur;
294 /* alloc a dep structure. These are allocated in bunches to save time. */
295 struct dep *
296 incdep_alloc_dep (struct incdep *cur)
298 struct alloccache *cache;
299 if (cur->worker_tid != -1)
300 cache = &incdep_dep_caches[cur->worker_tid];
301 else
302 cache = &dep_cache;
303 return alloccache_calloc (cache);
306 /* allocate a record. */
307 static void *
308 incdep_alloc_rec (struct incdep *cur)
310 return alloccache_alloc (&incdep_rec_caches[cur->worker_tid]);
313 /* free a record. */
314 static void
315 incdep_free_rec (struct incdep *cur, void *rec)
317 /*alloccache_free (&incdep_rec_caches[cur->worker_tid], rec); - doesn't work of course. */
321 /* grow a cache. */
322 static void *
323 incdep_cache_allocator (void *thrd, unsigned int size)
325 (void)thrd;
326 #ifdef __APPLE__
327 return malloc_zone_malloc (incdep_zone, size);
328 #else
329 return xmalloc (size);
330 #endif
333 /* term a cache. */
334 static void
335 incdep_cache_deallocator (void *thrd, void *ptr, unsigned int size)
337 (void)thrd;
338 (void)size;
339 free (ptr);
342 /* acquires the lock */
343 void
344 incdep_lock(void)
346 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
347 pthread_mutex_lock (&incdep_mtx);
348 #elif defined (WINDOWS32)
349 EnterCriticalSection (&incdep_mtx);
350 #elif defined (__OS2__)
351 _fmutex_request (&incdep_mtx, 0);
352 #endif
355 /* releases the lock */
356 void
357 incdep_unlock(void)
359 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
360 pthread_mutex_unlock (&incdep_mtx);
361 #elif defined(WINDOWS32)
362 LeaveCriticalSection (&incdep_mtx);
363 #elif defined(__OS2__)
364 _fmutex_release (&incdep_mtx);
365 #endif
368 /* signals the main thread that there is stuff todo. caller owns the lock. */
369 static void
370 incdep_signal_done (void)
372 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
373 pthread_cond_broadcast (&incdep_cond_done);
374 #elif defined (WINDOWS32)
375 if (incdep_hev_done_waiters)
376 SetEvent (incdep_hev_done);
377 #elif defined (__OS2__)
378 if (incdep_hev_done_waiters)
379 DosPostEventSem (incdep_hev_done);
380 #endif
383 /* waits for a reader to finish reading. caller owns the lock. */
384 static void
385 incdep_wait_done (void)
387 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
388 pthread_cond_wait (&incdep_cond_done, &incdep_mtx);
390 #elif defined (WINDOWS32)
391 ResetEvent (incdep_hev_done);
392 incdep_hev_done_waiters++;
393 incdep_unlock ();
394 WaitForSingleObject (incdep_hev_done, INFINITE);
395 incdep_lock ();
396 incdep_hev_done_waiters--;
398 #elif defined (__OS2__)
399 ULONG ulIgnore;
400 DosResetEventSem (incdep_hev_done, &ulIgnore);
401 incdep_hev_done_waiters++;
402 incdep_unlock ();
403 DosWaitEventSem (incdep_hev_done, SEM_INDEFINITE_WAIT);
404 incdep_lock ();
405 incdep_hev_done_waiters--;
406 #endif
409 /* signals the worker threads. caller owns the lock. */
410 static void
411 incdep_signal_todo (void)
413 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
414 pthread_cond_broadcast (&incdep_cond_todo);
415 #elif defined(WINDOWS32)
416 if (incdep_hev_todo_waiters)
417 SetEvent (incdep_hev_todo);
418 #elif defined(__OS2__)
419 if (incdep_hev_todo_waiters)
420 DosPostEventSem (incdep_hev_todo);
421 #endif
424 /* waits for stuff to arrive in the todo list. caller owns the lock. */
425 static void
426 incdep_wait_todo (void)
428 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
429 pthread_cond_wait (&incdep_cond_todo, &incdep_mtx);
431 #elif defined (WINDOWS32)
432 ResetEvent (incdep_hev_todo);
433 incdep_hev_todo_waiters++;
434 incdep_unlock ();
435 WaitForSingleObject (incdep_hev_todo, INFINITE);
436 incdep_lock ();
437 incdep_hev_todo_waiters--;
439 #elif defined (__OS2__)
440 ULONG ulIgnore;
441 DosResetEventSem (incdep_hev_todo, &ulIgnore);
442 incdep_hev_todo_waiters++;
443 incdep_unlock ();
444 DosWaitEventSem (incdep_hev_todo, SEM_INDEFINITE_WAIT);
445 incdep_lock ();
446 incdep_hev_todo_waiters--;
447 #endif
450 /* Reads a dep file into memory. */
451 static int
452 incdep_read_file (struct incdep *cur, struct floc *f)
454 int fd;
455 struct stat st;
457 errno = 0;
458 #ifdef O_BINARY
459 fd = open (cur->name, O_RDONLY | O_BINARY, 0);
460 #else
461 fd = open (cur->name, O_RDONLY, 0);
462 #endif
463 if (fd < 0)
465 /* ignore non-existing dependency files. */
466 int err = errno;
467 if (err == ENOENT || stat (cur->name, &st) != 0)
468 return 1;
469 error (f, "%s: %s", cur->name, strerror (err));
470 return -1;
472 if (!fstat (fd, &st))
474 cur->file_base = incdep_xmalloc (cur, st.st_size + 1);
475 if (read (fd, cur->file_base, st.st_size) == st.st_size)
477 close (fd);
478 cur->file_end = cur->file_base + st.st_size;
479 cur->file_base[st.st_size] = '\0';
480 return 0;
483 /* bail out */
485 error (f, "%s: read: %s", cur->name, strerror (errno));
486 incdep_xfree (cur, cur->file_base);
488 else
489 error (f, "%s: fstat: %s", cur->name, strerror (errno));
491 close (fd);
492 cur->file_base = cur->file_end = NULL;
493 return -1;
496 /* Free the incdep structure. */
497 static void
498 incdep_freeit (struct incdep *cur)
500 #ifdef PARSE_IN_WORKER
501 assert (!cur->recorded_variables_in_set_head);
502 assert (!cur->recorded_variable_defs_head);
503 assert (!cur->recorded_files_head);
504 #endif
506 incdep_xfree (cur, cur->file_base);
507 cur->next = NULL;
508 free (cur);
511 /* A worker thread. */
512 void
513 incdep_worker (int thrd)
515 incdep_lock ();
517 while (!incdep_terminate)
519 /* get job from the todo list. */
521 struct incdep *cur = incdep_head_todo;
522 if (!cur)
524 incdep_wait_todo ();
525 continue;
527 if (cur->next)
528 incdep_head_todo = cur->next;
529 else
530 incdep_head_todo = incdep_tail_todo = NULL;
531 incdep_num_reading++;
533 /* read the file. */
535 incdep_unlock ();
536 cur->worker_tid = thrd;
538 incdep_read_file (cur, NILF);
539 #ifdef PARSE_IN_WORKER
540 eval_include_dep_file (cur, NILF);
541 #endif
543 cur->worker_tid = -1;
544 incdep_lock ();
546 /* insert finished job into the done list. */
548 incdep_num_reading--;
549 cur->next = NULL;
550 if (incdep_tail_done)
551 incdep_tail_done->next = cur;
552 else
553 incdep_head_done = cur;
554 incdep_tail_done = cur;
556 incdep_signal_done ();
559 incdep_unlock ();
562 /* Thread library specific thread functions wrapping incdep_wroker. */
563 #ifdef HAVE_PTHREAD
564 static void *
565 incdep_worker_pthread (void *thrd)
567 incdep_worker ((size_t)thrd);
568 return NULL;
571 #elif defined (WINDOWS32)
572 static unsigned __stdcall
573 incdep_worker_windows (void *thrd)
575 incdep_worker ((size_t)thrd);
576 return 0;
579 #elif defined (__OS2__)
580 static void
581 incdep_worker_os2 (void *thrd)
583 incdep_worker ((size_t)thrd);
585 #endif
587 /* Checks if threads are enabled or not.
589 This is a special hack so that is possible to disable the threads when in a
590 debian fakeroot environment. Thus, in addition to the KMK_THREADS_DISABLED
591 and KMK_THREADS_ENABLED environment variable check we also check for signs
592 of fakeroot. */
593 static int
594 incdep_are_threads_enabled (void)
596 #if defined (CONFIG_WITHOUT_THREADS)
597 return 0;
598 #endif
600 if (getenv("KMK_THREADS_DISABLED"))
601 return 0;
602 if (getenv("KMK_THREADS_ENABLED"))
603 return 1;
604 #if defined(__gnu_linux__) || defined(__linux__)
605 if (getenv("FAKEROOTKEY"))
606 return 0;
607 if (getenv("FAKEROOTUID"))
608 return 0;
609 if (getenv("FAKEROOTGID"))
610 return 0;
611 if (getenv("FAKEROOTEUID"))
612 return 0;
613 if (getenv("FAKEROOTEGID"))
614 return 0;
615 if (getenv("FAKEROOTSUID"))
616 return 0;
617 if (getenv("FAKEROOTSGID"))
618 return 0;
619 if (getenv("FAKEROOTFUID"))
620 return 0;
621 if (getenv("FAKEROOTFGID"))
622 return 0;
623 if (getenv("FAKEROOTDONTTRYCHOWN"))
624 return 0;
625 if (getenv("FAKEROOT_FD_BASE"))
626 return 0;
627 if (getenv("FAKEROOT_DB_SEARCH_PATHS"))
628 return 0;
629 #endif /* GNU/Linux */
630 return 1;
633 /* Creates the the worker threads. */
634 static void
635 incdep_init (struct floc *f)
637 unsigned i;
638 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
639 int rc;
640 pthread_attr_t attr;
642 #elif defined (WINDOWS32)
643 unsigned tid;
644 uintptr_t hThread;
646 #elif defined (__OS2__)
647 int rc;
648 int tid;
649 #endif
650 (void)f;
652 /* heap hacks */
654 #ifdef __APPLE__
655 incdep_zone = malloc_create_zone (0, 0);
656 if (!incdep_zone)
657 incdep_zone = malloc_default_zone ();
658 #endif
661 /* create the mutex and two condition variables / event objects. */
663 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
664 rc = pthread_mutex_init (&incdep_mtx, NULL);
665 if (rc)
666 fatal (f, _("pthread_mutex_init failed: err=%d"), rc);
667 rc = pthread_cond_init (&incdep_cond_todo, NULL);
668 if (rc)
669 fatal (f, _("pthread_cond_init failed: err=%d"), rc);
670 rc = pthread_cond_init (&incdep_cond_done, NULL);
671 if (rc)
672 fatal (f, _("pthread_cond_init failed: err=%d"), rc);
674 #elif defined (WINDOWS32)
675 InitializeCriticalSection (&incdep_mtx);
676 incdep_hev_todo = CreateEvent (NULL, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL);
677 if (!incdep_hev_todo)
678 fatal (f, _("CreateEvent failed: err=%d"), GetLastError());
679 incdep_hev_done = CreateEvent (NULL, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL);
680 if (!incdep_hev_done)
681 fatal (f, _("CreateEvent failed: err=%d"), GetLastError());
682 incdep_hev_todo_waiters = 0;
683 incdep_hev_done_waiters = 0;
685 #elif defined (__OS2__)
686 _fmutex_create (&incdep_mtx, 0);
687 rc = DosCreateEventSem (NULL, &incdep_hev_todo, 0, FALSE);
688 if (rc)
689 fatal (f, _("DosCreateEventSem failed: rc=%d"), rc);
690 rc = DosCreateEventSem (NULL, &incdep_hev_done, 0, FALSE);
691 if (rc)
692 fatal (f, _("DosCreateEventSem failed: rc=%d"), rc);
693 incdep_hev_todo_waiters = 0;
694 incdep_hev_done_waiters = 0;
695 #endif
697 /* create the worker threads and associated per thread data. */
699 incdep_terminate = 0;
700 if (incdep_are_threads_enabled())
702 incdep_num_threads = sizeof (incdep_threads) / sizeof (incdep_threads[0]);
703 if (incdep_num_threads + 1 > job_slots)
704 incdep_num_threads = job_slots <= 1 ? 1 : job_slots - 1;
705 for (i = 0; i < incdep_num_threads; i++)
707 /* init caches */
708 unsigned rec_size = sizeof (struct incdep_variable_in_set);
709 if (rec_size < sizeof (struct incdep_variable_def))
710 rec_size = sizeof (struct incdep_variable_def);
711 if (rec_size < sizeof (struct incdep_recorded_files))
712 rec_size = sizeof (struct incdep_recorded_files);
713 alloccache_init (&incdep_rec_caches[i], rec_size, "incdep rec",
714 incdep_cache_allocator, (void *)(size_t)i);
715 alloccache_init (&incdep_dep_caches[i], sizeof(struct dep), "incdep dep",
716 incdep_cache_allocator, (void *)(size_t)i);
717 strcache2_init (&incdep_dep_strcaches[i],
718 "incdep dep", /* name */
719 65536, /* hash size */
720 0, /* default segment size*/
721 #ifdef HAVE_CASE_INSENSITIVE_FS
722 1, /* case insensitive */
723 #else
724 0, /* case insensitive */
725 #endif
726 0); /* thread safe */
728 strcache2_init (&incdep_var_strcaches[i],
729 "incdep var", /* name */
730 32768, /* hash size */
731 0, /* default segment size*/
732 0, /* case insensitive */
733 0); /* thread safe */
735 /* create the thread. */
736 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
737 rc = pthread_attr_init (&attr);
738 if (rc)
739 fatal (f, _("pthread_attr_init failed: err=%d"), rc);
740 /*rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); */
741 rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
742 if (rc)
743 fatal (f, _("pthread_attr_setdetachstate failed: err=%d"), rc);
744 rc = pthread_create(&incdep_threads[i], &attr,
745 incdep_worker_pthread, (void *)(size_t)i);
746 if (rc)
747 fatal (f, _("pthread_mutex_init failed: err=%d"), rc);
748 pthread_attr_destroy (&attr);
750 #elif defined (WINDOWS32)
751 tid = 0;
752 hThread = _beginthreadex (NULL, 128*1024, incdep_worker_windows,
753 (void *)i, 0, &tid);
754 if (hThread == 0 || hThread == ~(uintptr_t)0)
755 fatal (f, _("_beginthreadex failed: err=%d"), errno);
756 incdep_threads[i] = (HANDLE)hThread;
758 #elif defined (__OS2__)
759 tid = _beginthread (incdep_worker_os2, NULL, 128*1024, (void *)i);
760 if (tid <= 0)
761 fatal (f, _("_beginthread failed: err=%d"), errno);
762 incdep_threads[i] = tid;
763 #endif
766 else
767 incdep_num_threads = 0;
769 incdep_initialized = 1;
772 /* Flushes outstanding work and terminates the worker threads.
773 This is called from snap_deps(). */
774 void
775 incdep_flush_and_term (void)
777 unsigned i;
779 if (!incdep_initialized)
780 return;
782 /* flush any out standing work */
784 incdep_flush_it (NILF);
786 /* tell the threads to terminate */
788 incdep_lock ();
789 incdep_terminate = 1;
790 incdep_signal_todo ();
791 incdep_unlock ();
793 /* wait for the threads to quit */
795 for (i = 0; i < incdep_num_threads; i++)
797 /* more later? */
799 /* terminate or join up the allocation caches. */
800 alloccache_term (&incdep_rec_caches[i], incdep_cache_deallocator, (void *)(size_t)i);
801 alloccache_join (&dep_cache, &incdep_dep_caches[i]);
802 strcache2_term (&incdep_dep_strcaches[i]);
803 strcache2_term (&incdep_var_strcaches[i]);
805 incdep_num_threads = 0;
807 /* destroy the lock and condition variables / event objects. */
809 /* later */
811 incdep_initialized = 0;
814 #ifdef PARSE_IN_WORKER
815 /* Flushes a strcache entry returning the actual string cache entry.
816 The input is freed! */
817 static const char *
818 incdep_flush_strcache_entry (struct strcache2_entry *entry)
820 if (!entry->user)
821 entry->user = (void *) strcache2_add_hashed_file (&file_strcache,
822 (const char *)(entry + 1),
823 entry->length, entry->hash);
824 return (const char *)entry->user;
827 /* Flushes the recorded instructions. */
828 static void
829 incdep_flush_recorded_instructions (struct incdep *cur)
831 struct incdep_variable_in_set *rec_vis;
832 struct incdep_variable_def *rec_vd;
833 struct incdep_recorded_files *rec_f;
835 /* define_variable_in_set */
837 rec_vis = cur->recorded_variables_in_set_head;
838 cur->recorded_variables_in_set_head = cur->recorded_variables_in_set_tail = NULL;
839 if (rec_vis)
842 void *free_me = rec_vis;
843 unsigned int name_length = rec_vis->name_entry->length;
844 define_variable_in_set (incdep_flush_strcache_entry (rec_vis->name_entry),
845 name_length,
846 rec_vis->value,
847 rec_vis->value_length,
848 rec_vis->duplicate_value,
849 rec_vis->origin,
850 rec_vis->recursive,
851 rec_vis->set,
852 rec_vis->flocp);
853 rec_vis = rec_vis->next;
854 incdep_free_rec (cur, free_me);
856 while (rec_vis);
858 /* do_variable_definition */
860 rec_vd = cur->recorded_variable_defs_head;
861 cur->recorded_variable_defs_head = cur->recorded_variable_defs_tail = NULL;
862 if (rec_vd)
865 void *free_me = rec_vd;
866 do_variable_definition_2 (rec_vd->flocp,
867 incdep_flush_strcache_entry (rec_vd->name_entry),
868 rec_vd->value,
869 rec_vd->value_length,
871 rec_vd->value,
872 rec_vd->origin,
873 rec_vd->flavor,
874 rec_vd->target_var);
875 rec_vd = rec_vd->next;
876 incdep_free_rec (cur, free_me);
878 while (rec_vd);
880 /* record_files */
882 rec_f = cur->recorded_files_head;
883 cur->recorded_files_head = cur->recorded_files_tail = NULL;
884 if (rec_f)
887 void *free_me = rec_f;
888 struct dep *dep;
889 struct nameseq *filenames;
891 for (dep = rec_f->deps; dep; dep = dep->next)
892 dep->name = incdep_flush_strcache_entry ((struct strcache2_entry *)dep->name);
894 filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
895 filenames->next = 0;
896 filenames->name = incdep_flush_strcache_entry (rec_f->filename_entry);
898 record_files (filenames,
899 rec_f->pattern,
900 rec_f->pattern_percent,
901 rec_f->deps,
902 rec_f->cmds_started,
903 rec_f->commands,
904 rec_f->commands_idx,
905 rec_f->two_colon,
906 rec_f->flocp);
908 rec_f = rec_f->next;
909 incdep_free_rec (cur, free_me);
911 while (rec_f);
913 #endif /* PARSE_IN_WORKER */
915 /* Record / issue a warning about a misformed dep file. */
916 static void
917 incdep_warn (struct incdep *cur, unsigned int line_no, const char *msg)
919 if (cur->worker_tid == -1)
920 error (NILF, "%s(%d): %s", cur->name, line_no, msg);
921 #ifdef PARSE_IN_WORKER
922 else
924 cur->err_line_no = line_no;
925 cur->err_msg = msg;
927 #endif
930 /* Dependency or file strcache allocation / recording. */
931 static const char *
932 incdep_dep_strcache (struct incdep *cur, const char *str, int len)
934 const char *ret;
935 if (cur->worker_tid == -1)
937 /* Make sure the string is terminated before we hand it to
938 strcache_add_len so it does have to make a temporary copy
939 of it on the stack. */
940 char ch = str[len];
941 ((char *)str)[len] = '\0';
942 ret = strcache_add_len (str, len);
943 ((char *)str)[len] = ch;
945 else
947 /* Add it out the strcache of the thread. */
948 ret = strcache2_add (&incdep_dep_strcaches[cur->worker_tid], str, len);
949 ret = (const char *)strcache2_get_entry(&incdep_dep_strcaches[cur->worker_tid], ret);
951 return ret;
954 /* Variable name allocation / recording. */
955 static const char *
956 incdep_var_strcache (struct incdep *cur, const char *str, int len)
958 const char *ret;
959 if (cur->worker_tid == -1)
961 /* XXX: we're leaking this memory now! This will be fixed later. */
962 ret = xmalloc (len + 1);
963 memcpy ((char *)ret, str, len);
964 ((char *)ret)[len] = '\0';
966 else
968 /* Add it out the strcache of the thread. */
969 ret = strcache2_add (&incdep_var_strcaches[cur->worker_tid], str, len);
970 ret = (const char *)strcache2_get_entry(&incdep_var_strcaches[cur->worker_tid], ret);
972 return ret;
975 /* Record / perform a variable definition in a set.
976 The NAME is in the string cache.
977 The VALUE is on the heap.
978 The DUPLICATE_VALUE is always 0. */
979 static void
980 incdep_record_variable_in_set (struct incdep *cur,
981 const char *name, unsigned int name_length,
982 const char *value,
983 unsigned int value_length,
984 int duplicate_value,
985 enum variable_origin origin,
986 int recursive,
987 struct variable_set *set,
988 const struct floc *flocp)
990 assert (!duplicate_value);
991 if (cur->worker_tid == -1)
992 define_variable_in_set (name, name_length, value, value_length,
993 duplicate_value, origin, recursive, set, flocp);
994 #ifdef PARSE_IN_WORKER
995 else
997 struct incdep_variable_in_set *rec =
998 (struct incdep_variable_in_set *)incdep_alloc_rec (cur);
999 rec->name_entry = (struct strcache2_entry *)name;
1000 rec->value = value;
1001 rec->value_length = value_length;
1002 rec->duplicate_value = duplicate_value;
1003 rec->origin = origin;
1004 rec->recursive = recursive;
1005 rec->set = set;
1006 rec->flocp = flocp;
1008 rec->next = NULL;
1009 if (cur->recorded_variables_in_set_tail)
1010 cur->recorded_variables_in_set_tail->next = rec;
1011 else
1012 cur->recorded_variables_in_set_head = rec;
1013 cur->recorded_variables_in_set_tail = rec;
1015 #endif
1018 /* Record / perform a variable definition. The VALUE should be disposed of. */
1019 static void
1020 incdep_record_variable_def (struct incdep *cur,
1021 const struct floc *flocp,
1022 const char *name,
1023 unsigned int name_length,
1024 char *value,
1025 unsigned int value_length,
1026 enum variable_origin origin,
1027 enum variable_flavor flavor,
1028 int target_var)
1030 if (cur->worker_tid == -1)
1031 do_variable_definition_2 (flocp, name, value, value_length, 0, value,
1032 origin, flavor, target_var);
1033 #ifdef PARSE_IN_WORKER
1034 else
1036 struct incdep_variable_def *rec =
1037 (struct incdep_variable_def *)incdep_alloc_rec (cur);
1038 rec->flocp = flocp;
1039 rec->name_entry = (struct strcache2_entry *)name;
1040 rec->value = value;
1041 rec->value_length = value_length;
1042 rec->origin = origin;
1043 rec->flavor = flavor;
1044 rec->target_var = target_var;
1046 rec->next = NULL;
1047 if (cur->recorded_variable_defs_tail)
1048 cur->recorded_variable_defs_tail->next = rec;
1049 else
1050 cur->recorded_variable_defs_head = rec;
1051 cur->recorded_variable_defs_tail = rec;
1053 #else
1054 (void)name_length;
1055 #endif
1058 /* Record files.*/
1059 static void
1060 incdep_record_files (struct incdep *cur,
1061 const char *filename, const char *pattern,
1062 const char *pattern_percent, struct dep *deps,
1063 unsigned int cmds_started, char *commands,
1064 unsigned int commands_idx, int two_colon,
1065 const struct floc *flocp)
1067 if (cur->worker_tid == -1)
1069 struct nameseq *filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
1070 filenames->next = 0;
1071 filenames->name = filename;
1072 record_files (filenames, pattern, pattern_percent, deps, cmds_started,
1073 commands, commands_idx, two_colon, flocp);
1075 #ifdef PARSE_IN_WORKER
1076 else
1078 struct incdep_recorded_files *rec =
1079 (struct incdep_recorded_files *) incdep_alloc_rec (cur);
1081 rec->filename_entry = (struct strcache2_entry *)filename;
1082 rec->pattern = pattern;
1083 rec->pattern_percent = pattern_percent;
1084 rec->deps = deps;
1085 rec->cmds_started = cmds_started;
1086 rec->commands = commands;
1087 rec->commands_idx = commands_idx;
1088 rec->two_colon = two_colon;
1089 rec->flocp = flocp;
1091 rec->next = NULL;
1092 if (cur->recorded_files_tail)
1093 cur->recorded_files_tail->next = rec;
1094 else
1095 cur->recorded_files_head = rec;
1096 cur->recorded_files_tail = rec;
1098 #endif
1102 /* no nonsense dependency file including.
1104 Because nobody wants bogus dependency files to break their incremental
1105 builds with hard to comprehend error messages, this function does not
1106 use the normal eval routine but does all the parsing itself. This isn't,
1107 as much work as it sounds, because the necessary feature set is very
1108 limited.
1110 eval_include_dep_file groks:
1112 define var
1113 endef
1115 var [|:|?|>]= value [\]
1118 file: [deps] [\]
1121 static void
1122 eval_include_dep_file (struct incdep *curdep, struct floc *f)
1124 unsigned line_no = 1;
1125 const char *file_end = curdep->file_end;
1126 const char *cur = curdep->file_base;
1127 const char *endp;
1129 /* if no file data, just return immediately. */
1130 if (!cur)
1131 return;
1133 /* now parse the file. */
1134 while (cur < file_end)
1136 /* skip empty lines */
1137 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
1138 ++cur;
1139 if (cur >= file_end)
1140 break;
1141 if (*cur == '#')
1143 cur = memchr (cur, '\n', file_end - cur);
1144 if (!cur)
1145 break;
1147 if (*cur == '\\')
1149 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
1150 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
1151 : (file_end - cur == 1) ? 1 : 0;
1152 if (eol_len)
1154 cur += eol_len;
1155 line_no++;
1156 continue;
1159 if (*cur == '\n')
1161 cur++;
1162 line_no++;
1163 continue;
1166 /* define var
1168 endef */
1169 if (strneq (cur, "define ", 7))
1171 const char *var;
1172 unsigned var_len;
1173 const char *value_start;
1174 const char *value_end;
1175 char *value;
1176 unsigned value_len;
1177 int found_endef = 0;
1179 /* extract the variable name. */
1180 cur += 7;
1181 while (isblank ((unsigned char)*cur))
1182 ++cur;
1183 value_start = endp = memchr (cur, '\n', file_end - cur);
1184 if (!endp)
1185 endp = cur;
1186 while (endp > cur && isspace ((unsigned char)endp[-1]))
1187 --endp;
1188 var_len = endp - cur;
1189 if (!var_len)
1191 incdep_warn (curdep, line_no, "bogus define statement.");
1192 break;
1194 var = incdep_var_strcache (curdep, cur, var_len);
1196 /* find the end of the variable. */
1197 cur = value_end = value_start = value_start + 1;
1198 ++line_no;
1199 while (cur < file_end)
1201 /* check for endef, don't bother with skipping leading spaces. */
1202 if ( file_end - cur >= 5
1203 && strneq (cur, "endef", 5))
1205 endp = cur + 5;
1206 while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n')
1207 endp++;
1208 if (endp >= file_end || *endp == '\n')
1210 found_endef = 1;
1211 cur = endp >= file_end ? file_end : endp + 1;
1212 break;
1216 /* skip a line ahead. */
1217 cur = value_end = memchr (cur, '\n', file_end - cur);
1218 if (cur != NULL)
1219 ++cur;
1220 else
1221 cur = value_end = file_end;
1222 ++line_no;
1225 if (!found_endef)
1227 incdep_warn (curdep, line_no, "missing endef, dropping the rest of the file.");
1228 break;
1230 value_len = value_end - value_start;
1231 if (memchr (value_start, '\0', value_len))
1233 incdep_warn (curdep, line_no, "'\\0' in define, dropping the rest of the file.");
1234 break;
1237 /* make a copy of the value, converting \r\n to \n, and define it. */
1238 value = incdep_xmalloc (curdep, value_len + 1);
1239 endp = memchr (value_start, '\r', value_len);
1240 if (endp)
1242 const char *src = value_start;
1243 char *dst = value;
1244 for (;;)
1246 size_t len = endp - src;
1247 memcpy (dst, src, len);
1248 dst += len;
1249 src = endp;
1250 if (src + 1 < file_end && src[1] == '\n')
1251 src++; /* skip the '\r' */
1252 if (src >= value_end)
1253 break;
1254 endp = memchr (endp + 1, '\r', src - value_end);
1255 if (!endp)
1256 endp = value_end;
1258 value_len = dst - value;
1260 else
1261 memcpy (value, value_start, value_len);
1262 value [value_len] = '\0';
1264 incdep_record_variable_in_set (curdep,
1265 var, var_len, value, value_len,
1266 0 /* don't duplicate */, o_file,
1267 0 /* defines are recursive but this is faster */,
1268 NULL /* global set */, f);
1271 /* file: deps
1273 variable [:]= value */
1274 else
1276 const char *colonp;
1277 const char *equalp;
1279 /* Look for a colon and an equal sign, optimize for colon.
1280 Only one file is support and the colon / equal must be on
1281 the same line. */
1282 colonp = memchr (cur, ':', file_end - cur);
1283 #ifdef HAVE_DOS_PATHS
1284 while ( colonp
1285 && colonp + 1 < file_end
1286 && (colonp[1] == '/' || colonp[1] == '\\')
1287 && colonp > cur
1288 && isalpha ((unsigned char)colonp[-1])
1289 && ( colonp == cur + 1
1290 || strchr (" \t(", colonp[-2]) != 0))
1291 colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
1292 #endif
1293 endp = NULL;
1294 if ( !colonp
1295 || (endp = memchr (cur, '\n', colonp - cur)))
1297 colonp = NULL;
1298 equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);
1299 if ( !equalp
1300 || (!endp && memchr (cur, '\n', equalp - cur)))
1302 incdep_warn (curdep, line_no, "no colon.");
1303 break;
1306 else
1307 equalp = memchr (cur, '=', (colonp + 2 <= file_end
1308 ? colonp + 2 : file_end) - cur);
1309 if (equalp)
1311 /* An assignment of some sort. */
1312 const char *var;
1313 unsigned var_len;
1314 const char *value_start;
1315 const char *value_end;
1316 char *value;
1317 unsigned value_len;
1318 unsigned multi_line = 0;
1319 enum variable_flavor flavor;
1321 /* figure the flavor first. */
1322 flavor = f_recursive;
1323 if (equalp > cur)
1325 if (equalp[-1] == ':')
1326 flavor = f_simple;
1327 else if (equalp[-1] == '?')
1328 flavor = f_conditional;
1329 else if (equalp[-1] == '+')
1330 flavor = f_append;
1331 else if (equalp[-1] == '>')
1332 flavor = f_prepend;
1335 /* extract the variable name. */
1336 endp = flavor == f_recursive ? equalp : equalp - 1;
1337 while (endp > cur && isblank ((unsigned char)endp[-1]))
1338 --endp;
1339 var_len = endp - cur;
1340 if (!var_len)
1342 incdep_warn (curdep, line_no, "empty variable. (includedep)");
1343 break;
1345 if ( memchr (cur, '$', var_len)
1346 || memchr (cur, ' ', var_len)
1347 || memchr (cur, '\t', var_len))
1349 incdep_warn (curdep, line_no, "fancy variable name. (includedep)");
1350 break;
1352 var = incdep_var_strcache (curdep, cur, var_len);
1354 /* find the start of the value. */
1355 cur = equalp + 1;
1356 while (cur < file_end && isblank ((unsigned char)*cur))
1357 cur++;
1358 value_start = cur;
1360 /* find the end of the value / line (this isn't 101% correct). */
1361 value_end = cur;
1362 while (cur < file_end)
1364 endp = value_end = memchr (cur, '\n', file_end - cur);
1365 if (!value_end)
1366 value_end = file_end;
1367 if (value_end - 1 >= cur && value_end[-1] == '\r')
1368 --value_end;
1369 if (value_end - 1 < cur || value_end[-1] != '\\')
1371 cur = endp ? endp + 1 : file_end;
1372 break;
1374 --value_end;
1375 if (value_end - 1 >= cur && value_end[-1] == '\\')
1377 incdep_warn (curdep, line_no, "fancy escaping! (includedep)");
1378 cur = NULL;
1379 break;
1381 if (!endp)
1383 cur = file_end;
1384 break;
1387 cur = endp + 1;
1388 ++multi_line;
1389 ++line_no;
1391 if (!cur)
1392 break;
1393 ++line_no;
1395 /* make a copy of the value, converting \r\n to \n, and define it. */
1396 value_len = value_end - value_start;
1397 value = incdep_xmalloc (curdep, value_len + 1);
1398 if (!multi_line)
1399 memcpy (value, value_start, value_len);
1400 else
1402 /* unescape it */
1403 const char *src = value_start;
1404 char *dst = value;
1405 while (src < value_end)
1407 const char *nextp;
1409 endp = memchr (src, '\n', value_end - src);
1410 if (!endp)
1411 nextp = endp = value_end;
1412 else
1413 nextp = endp + 1;
1414 if (endp > src && endp[-1] == '\r')
1415 --endp;
1416 if (endp > src && endp[-1] == '\\')
1417 --endp;
1419 if (src != value_start)
1420 *dst++ = ' ';
1421 memcpy (dst, src, endp - src);
1422 dst += endp - src;
1423 src = nextp;
1425 value_len = dst - value;
1427 value [value_len] = '\0';
1429 /* do the definition */
1430 if (flavor == f_recursive
1431 || ( flavor == f_simple
1432 && !memchr (value, '$', value_len)))
1433 incdep_record_variable_in_set (curdep,
1434 var, var_len, value, value_len,
1435 0 /* don't duplicate */, o_file,
1436 flavor == f_recursive /* recursive */,
1437 NULL /* global set */, f);
1438 else
1439 incdep_record_variable_def (curdep,
1440 f, var, var_len, value, value_len,
1441 o_file, flavor, 0 /* not target var */);
1443 else
1445 /* file: dependencies */
1447 const char *filename;
1448 struct dep *deps = 0;
1449 struct dep **nextdep = &deps;
1450 struct dep *dep;
1452 /* extract the filename, ASSUME a single one. */
1453 endp = colonp;
1454 while (endp > cur && isblank ((unsigned char)endp[-1]))
1455 --endp;
1456 if (cur == endp)
1458 incdep_warn (curdep, line_no, "empty filename.");
1459 break;
1461 if ( memchr (cur, '$', endp - cur)
1462 || memchr (cur, ' ', endp - cur)
1463 || memchr (cur, '\t', endp - cur))
1465 incdep_warn (curdep, line_no, "multiple / fancy file name. (includedep)");
1466 break;
1468 filename = incdep_dep_strcache (curdep, cur, endp - cur);
1470 /* parse any dependencies. */
1471 cur = colonp + 1;
1472 while (cur < file_end)
1474 /* skip blanks and count lines. */
1475 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
1476 ++cur;
1477 if (cur >= file_end)
1478 break;
1479 if (*cur == '\n')
1481 cur++;
1482 line_no++;
1483 break;
1486 /* continuation + eol? */
1487 if (*cur == '\\')
1489 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
1490 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
1491 : (file_end - cur == 1) ? 1 : 0;
1492 if (eol_len)
1494 cur += eol_len;
1495 line_no++;
1496 continue;
1500 /* find the end of the filename */
1501 endp = cur;
1502 while (endp < file_end && !isspace ((unsigned char)*endp))
1503 ++endp;
1505 /* add it to the list. */
1506 *nextdep = dep = incdep_alloc_dep (curdep);
1507 dep->name = incdep_dep_strcache (curdep, cur, endp - cur);
1508 dep->includedep = 1;
1509 nextdep = &dep->next;
1511 cur = endp;
1514 /* enter the file with its dependencies. */
1515 incdep_record_files (curdep,
1516 filename, NULL, NULL, deps, 0, NULL, 0, 0, f);
1521 /* free the file data */
1522 incdep_xfree (curdep, curdep->file_base);
1523 curdep->file_base = curdep->file_end = NULL;
1526 /* Flushes the incdep todo and done lists. */
1527 static void
1528 incdep_flush_it (struct floc *f)
1530 incdep_lock ();
1531 for (;;)
1533 struct incdep *cur = incdep_head_done;
1535 /* if the done list is empty, grab a todo list entry. */
1536 if (!cur && incdep_head_todo)
1538 cur = incdep_head_todo;
1539 if (cur->next)
1540 incdep_head_todo = cur->next;
1541 else
1542 incdep_head_todo = incdep_tail_todo = NULL;
1543 incdep_unlock ();
1545 incdep_read_file (cur, f);
1546 eval_include_dep_file (cur, f);
1547 incdep_freeit (cur);
1549 incdep_lock ();
1550 continue;
1553 /* if the todo list and done list are empty we're either done
1554 or will have to wait for the thread(s) to finish. */
1555 if (!cur && !incdep_num_reading)
1556 break; /* done */
1557 if (!cur)
1559 while (!incdep_head_done)
1560 incdep_wait_done ();
1561 cur = incdep_head_done;
1564 /* we grab the entire done list and work thru it. */
1565 incdep_head_done = incdep_tail_done = NULL;
1566 incdep_unlock ();
1568 while (cur)
1570 struct incdep *next = cur->next;
1571 #ifdef PARSE_IN_WORKER
1572 incdep_flush_recorded_instructions (cur);
1573 #else
1574 eval_include_dep_file (cur, f);
1575 #endif
1576 incdep_freeit (cur);
1577 cur = next;
1580 incdep_lock ();
1581 } /* outer loop */
1582 incdep_unlock ();
1586 /* splits up a list of file names and feeds it to eval_include_dep_file,
1587 employing threads to try speed up the file reading. */
1588 void
1589 eval_include_dep (const char *names, struct floc *f, enum incdep_op op)
1591 struct incdep *head = 0;
1592 struct incdep *tail = 0;
1593 struct incdep *cur;
1594 const char *names_iterator = names;
1595 const char *name;
1596 unsigned int name_len;
1598 /* loop through NAMES, creating a todo list out of them. */
1600 while ((name = find_next_token (&names_iterator, &name_len)) != 0)
1602 cur = xmalloc (sizeof (*cur) + name_len); /* not incdep_xmalloc here */
1603 cur->file_base = cur->file_end = NULL;
1604 memcpy (cur->name, name, name_len);
1605 cur->name[name_len] = '\0';
1606 cur->worker_tid = -1;
1607 #ifdef PARSE_IN_WORKER
1608 cur->err_line_no = 0;
1609 cur->err_msg = NULL;
1610 cur->recorded_variables_in_set_head = NULL;
1611 cur->recorded_variables_in_set_tail = NULL;
1612 cur->recorded_variable_defs_head = NULL;
1613 cur->recorded_variable_defs_tail = NULL;
1614 cur->recorded_files_head = NULL;
1615 cur->recorded_files_tail = NULL;
1616 #endif
1618 cur->next = NULL;
1619 if (tail)
1620 tail->next = cur;
1621 else
1622 head = cur;
1623 tail = cur;
1626 #ifdef ELECTRIC_HEAP
1627 if (1)
1628 #else
1629 if (op == incdep_read_it)
1630 #endif
1632 /* work our way thru the files directly */
1634 cur = head;
1635 while (cur)
1637 struct incdep *next = cur->next;
1638 incdep_read_file (cur, f);
1639 eval_include_dep_file (cur, f);
1640 incdep_freeit (cur);
1641 cur = next;
1644 else
1646 /* initialize the worker threads and related stuff the first time around. */
1648 if (!incdep_initialized)
1649 incdep_init (f);
1651 /* queue the files and notify the worker threads. */
1653 incdep_lock ();
1655 if (incdep_tail_todo)
1656 incdep_tail_todo->next = head;
1657 else
1658 incdep_head_todo = head;
1659 incdep_tail_todo = tail;
1661 incdep_signal_todo ();
1662 incdep_unlock ();
1664 /* flush the todo queue if we're requested to do so. */
1666 if (op == incdep_flush)
1667 incdep_flush_it (f);
1671 #endif /* CONFIG_WITH_INCLUDEDEP */