source: trunk/src/kmk/incdep.c@ 1908

Last change on this file since 1908 was 1903, checked in by bird, 17 years ago

strcache2: some cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 46.9 KB
Line 
1#ifdef CONFIG_WITH_INCLUDEDEP
2/* $Id: incdep.c 1903 2008-10-21 04:25:19Z bird $ */
3/** @file
4 * incdep - Simple dependency files.
5 */
6
7/*
8 * Copyright (c) 2006-2008 knut st. osmundsen <bird-src-spam@anduin.net>
9 *
10 * This file is part of kBuild.
11 *
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 2 of the License, or
15 * (at your option) any later version.
16 *
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.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with kBuild; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28
29/*******************************************************************************
30* Header Files *
31*******************************************************************************/
32#ifdef __OS2__
33# define INCL_BASE
34# define INCL_ERRORS
35#endif
36
37#include "make.h"
38
39#if !defined(WINDOWS32) && !defined(__OS2__)
40# define HAVE_PTHREAD
41#endif
42
43#include <assert.h>
44
45#include <glob.h>
46
47#include "dep.h"
48#include "filedef.h"
49#include "job.h"
50#include "commands.h"
51#include "variable.h"
52#include "rule.h"
53#include "debug.h"
54#include "strcache2.h"
55
56#ifdef HAVE_FCNTL_H
57# include <fcntl.h>
58#else
59# include <sys/file.h>
60#endif
61
62#ifdef WINDOWS32
63# include <io.h>
64# include <process.h>
65# include <Windows.h>
66# define PARSE_IN_WORKER
67#endif
68
69#ifdef __OS2__
70# include <os2.h>
71# include <sys/fmutex.h>
72#endif
73
74#ifdef HAVE_PTHREAD
75# include <pthread.h>
76#endif
77
78#ifdef __APPLE__
79# include <malloc/malloc.h>
80# define PARSE_IN_WORKER
81#endif
82
83#if defined(__gnu_linux__) || defined(__linux__)
84# define PARSE_IN_WORKER
85#endif
86
87
88/*******************************************************************************
89* Structures and Typedefs *
90*******************************************************************************/
91struct incdep_variable_in_set
92{
93 struct incdep_variable_in_set *next;
94 /* the parameters */
95 struct strcache2_entry *name_entry; /* dep strcache - WRONG */
96 const char *value; /* xmalloc'ed */
97 unsigned int value_length;
98 int duplicate_value; /* 0 */
99 enum variable_origin origin;
100 int recursive;
101 struct variable_set *set;
102 const struct floc *flocp; /* NILF */
103};
104
105struct incdep_variable_def
106{
107 struct incdep_variable_def *next;
108 /* the parameters */
109 const struct floc *flocp; /* NILF */
110 struct strcache2_entry *name_entry; /* dep strcache - WRONG */
111 char *value; /* xmalloc'ed, free it */
112 unsigned int value_length;
113 enum variable_origin origin;
114 enum variable_flavor flavor;
115 int target_var;
116};
117
118struct incdep_recorded_files
119{
120 struct incdep_recorded_files *next;
121
122 /* the parameters */
123 struct strcache2_entry *filename_entry; /* dep strcache; converted to a nameseq record. */
124 const char *pattern; /* NULL */
125 const char *pattern_percent; /* NULL */
126 struct dep *deps; /* All the names are dep strcache entries. */
127 unsigned int cmds_started; /* 0 */
128 char *commands; /* NULL */
129 unsigned int commands_idx; /* 0 */
130 int two_colon; /* 0 */
131 const struct floc *flocp; /* NILF */
132};
133
134
135/* per dep file structure. */
136struct incdep
137{
138 struct incdep *next;
139 char *file_base;
140 char *file_end;
141
142 int worker_tid;
143#ifdef PARSE_IN_WORKER
144 unsigned int err_line_no;
145 const char *err_msg;
146
147 struct incdep_variable_in_set *recorded_variables_in_set_head;
148 struct incdep_variable_in_set *recorded_variables_in_set_tail;
149
150 struct incdep_variable_def *recorded_variable_defs_head;
151 struct incdep_variable_def *recorded_variable_defs_tail;
152
153 struct incdep_recorded_files *recorded_files_head;
154 struct incdep_recorded_files *recorded_files_tail;
155#endif
156
157 char name[1];
158};
159
160
161/*******************************************************************************
162* Global Variables *
163*******************************************************************************/
164
165/* mutex protecting the globals and an associated condition/event. */
166#ifdef HAVE_PTHREAD
167static pthread_mutex_t incdep_mtx;
168static pthread_cond_t incdep_cond_todo;
169static pthread_cond_t incdep_cond_done;
170
171#elif defined (WINDOWS32)
172static CRITICAL_SECTION incdep_mtx;
173static HANDLE incdep_hev_todo;
174static HANDLE incdep_hev_done;
175static int volatile incdep_hev_todo_waiters;
176static int volatile incdep_hev_done_waiters;
177
178#elif defined (__OS2__)
179static fmutex incdep_mtx;
180static HEV incdep_hev_todo;
181static HEV incdep_hev_done;
182static int volatile incdep_hev_todo_waiters;
183static int volatile incdep_hev_done_waiters;
184#endif
185
186/* flag indicating whether the threads, lock and event/condvars has
187 been initialized or not. */
188static int incdep_initialized;
189
190/* the list of files that needs reading. */
191static struct incdep * volatile incdep_head_todo;
192static struct incdep * volatile incdep_tail_todo;
193
194/* the number of files that are currently being read. */
195static int volatile incdep_num_reading;
196
197/* the list of files that have been read. */
198static struct incdep * volatile incdep_head_done;
199static struct incdep * volatile incdep_tail_done;
200
201
202/* The handles to the worker threads. */
203#ifdef HAVE_PTHREAD
204# define INCDEP_MAX_THREADS 1
205static pthread_t incdep_threads[INCDEP_MAX_THREADS];
206
207#elif defined (WINDOWS32)
208# define INCDEP_MAX_THREADS 2
209static HANDLE incdep_threads[INCDEP_MAX_THREADS];
210
211#elif defined (__OS2__)
212# define INCDEP_MAX_THREADS 2
213static TID incdep_threads[INCDEP_MAX_THREADS];
214#endif
215
216static struct alloccache incdep_rec_caches[INCDEP_MAX_THREADS];
217static struct alloccache incdep_dep_caches[INCDEP_MAX_THREADS];
218static struct strcache2 incdep_dep_strcaches[INCDEP_MAX_THREADS];
219static struct strcache2 incdep_var_strcaches[INCDEP_MAX_THREADS];
220static unsigned incdep_num_threads;
221
222/* flag indicating whether the worker threads should terminate or not. */
223static int volatile incdep_terminate;
224
225#ifdef __APPLE__
226/* malloc zone for the incdep threads. */
227static malloc_zone_t *incdep_zone;
228#endif
229
230
231/*******************************************************************************
232* Internal Functions *
233*******************************************************************************/
234static void incdep_flush_it (struct floc *);
235static void eval_include_dep_file (struct incdep *, struct floc *);
236
237
238/* xmalloc wrapper.
239 For working around multithreaded performance problems found on Darwin,
240 Linux (glibc), and possibly other systems. */
241static void *
242incdep_xmalloc (struct incdep *cur, size_t size)
243{
244 void *ptr;
245
246#ifdef __APPLE__
247 if (cur && cur->worker_tid != -1)
248 {
249 ptr = malloc_zone_malloc (incdep_zone, size);
250 if (!ptr)
251 fatal (NILF, _("virtual memory exhausted"));
252 }
253 else
254 ptr = xmalloc (size);
255#else
256 ptr = xmalloc (size);
257#endif
258
259 (void)cur;
260 return ptr;
261}
262
263#if 0
264/* memset(malloc(sz),'\0',sz) wrapper. */
265static void *
266incdep_xcalloc (struct incdep *cur, size_t size)
267{
268 void *ptr;
269
270#ifdef __APPLE__
271 if (cur && cur->worker_tid != -1)
272 ptr = malloc_zone_calloc (incdep_zone, size, 1);
273 else
274 ptr = calloc (size, 1);
275#else
276 ptr = calloc (size, 1);
277#endif
278 if (!ptr)
279 fatal (NILF, _("virtual memory exhausted"));
280
281 (void)cur;
282 return ptr;
283}
284#endif /* unused */
285
286/* free wrapper */
287static void
288incdep_xfree (struct incdep *cur, void *ptr)
289{
290 /* free() *must* work for the allocation hacks above because
291 of free_dep_chain. */
292 free (ptr);
293 (void)cur;
294}
295
296/* alloc a dep structure. These are allocated in bunches to save time. */
297struct dep *
298incdep_alloc_dep (struct incdep *cur)
299{
300 struct alloccache *cache;
301 if (cur->worker_tid != -1)
302 cache = &incdep_dep_caches[cur->worker_tid];
303 else
304 cache = &dep_cache;
305 return alloccache_calloc (cache);
306}
307
308/* allocate a record. */
309static void *
310incdep_alloc_rec (struct incdep *cur)
311{
312 return alloccache_alloc (&incdep_rec_caches[cur->worker_tid]);
313}
314
315/* free a record. */
316static void
317incdep_free_rec (struct incdep *cur, void *rec)
318{
319 /*alloccache_free (&incdep_rec_caches[cur->worker_tid], rec); - doesn't work of course. */
320}
321
322
323/* grow a cache. */
324static void *
325incdep_cache_allocator (void *thrd, unsigned int size)
326{
327 (void)thrd;
328#ifdef __APPLE__
329 return malloc_zone_malloc (incdep_zone, size);
330#else
331 return xmalloc (size);
332#endif
333}
334
335/* term a cache. */
336static void
337incdep_cache_deallocator (void *thrd, void *ptr, unsigned int size)
338{
339 (void)thrd;
340 (void)size;
341 free (ptr);
342}
343
344/* acquires the lock */
345void
346incdep_lock(void)
347{
348#ifdef HAVE_PTHREAD
349 pthread_mutex_lock (&incdep_mtx);
350#elif defined (WINDOWS32)
351 EnterCriticalSection (&incdep_mtx);
352#elif defined (__OS2__)
353 _fmutex_request (&incdep_mtx, 0)
354#endif
355}
356
357/* releases the lock */
358void
359incdep_unlock(void)
360{
361#ifdef HAVE_PTHREAD
362 pthread_mutex_unlock (&incdep_mtx);
363#elif defined(WINDOWS32)
364 LeaveCriticalSection (&incdep_mtx);
365#elif defined(__OS2__)
366 _fmutex_release (&incdep_mtx)
367#endif
368}
369
370/* signals the main thread that there is stuff todo. caller owns the lock. */
371static void
372incdep_signal_done (void)
373{
374#ifdef HAVE_PTHREAD
375 pthread_cond_broadcast (&incdep_cond_done);
376#elif defined (WINDOWS32)
377 if (incdep_hev_done_waiters)
378 SetEvent (incdep_hev_done);
379#elif defined (__OS2__)
380 if (incdep_hev_done_waiters)
381 DosPostEventSem (incdep_hev_done);
382#endif
383}
384
385/* waits for a reader to finish reading. caller owns the lock. */
386static void
387incdep_wait_done (void)
388{
389#ifdef HAVE_PTHREAD
390 pthread_cond_wait (&incdep_cond_done, &incdep_mtx);
391
392#elif defined (WINDOWS32)
393 ResetEvent (incdep_hev_done);
394 incdep_hev_done_waiters++;
395 incdep_unlock ();
396 WaitForSingleObject (incdep_hev_done, INFINITE);
397 incdep_lock ();
398 incdep_hev_done_waiters--;
399
400#elif defined (__OS2__)
401 ULONG ulIgnore;
402 DosResetEventSem (incdep_hev_done, &ulIgnore);
403 incdep_hev_done_waiters++;
404 incdep_unlock ();
405 DosWaitEventSem (incdep_hev_done, SEM_INDEFINITE_WAIT);
406 incdep_lock ();
407 incdep_hev_done_waiters--;
408#endif
409}
410
411/* signals the worker threads. caller owns the lock. */
412static void
413incdep_signal_todo (void)
414{
415#ifdef HAVE_PTHREAD
416 pthread_cond_broadcast (&incdep_cond_todo);
417#elif defined(WINDOWS32)
418 if (incdep_hev_todo_waiters)
419 SetEvent (incdep_hev_todo);
420#elif defined(__OS2__)
421 if (incdep_hev_todo_waiters)
422 DosPostEventSem (incdep_hev_todo);
423#endif
424}
425
426/* waits for stuff to arrive in the todo list. caller owns the lock. */
427static void
428incdep_wait_todo (void)
429{
430#ifdef HAVE_PTHREAD
431 pthread_cond_wait (&incdep_cond_todo, &incdep_mtx);
432
433#elif defined (WINDOWS32)
434 ResetEvent (incdep_hev_todo);
435 incdep_hev_todo_waiters++;
436 incdep_unlock ();
437 WaitForSingleObject (incdep_hev_todo, INFINITE);
438 incdep_lock ();
439 incdep_hev_todo_waiters--;
440
441#elif defined (__OS2__)
442 ULONG ulIgnore;
443 DosResetEventSem (incdep_hev_todo, &ulIgnore);
444 incdep_hev_todo_waiters++;
445 incdep_unlock ();
446 DosWaitEventSem (incdep_hev_todo, SEM_INDEFINITE_WAIT);
447 incdep_lock ();
448 incdep_hev_todo_waiters--;
449#endif
450}
451
452/* Reads a dep file into memory. */
453static int
454incdep_read_file (struct incdep *cur, struct floc *f)
455{
456 int fd;
457 struct stat st;
458
459 errno = 0;
460#ifdef O_BINARY
461 fd = open (cur->name, O_RDONLY | O_BINARY, 0);
462#else
463 fd = open (cur->name, O_RDONLY, 0);
464#endif
465 if (fd < 0)
466 {
467 /* ignore non-existing dependency files. */
468 int err = errno;
469 if (err == ENOENT || stat (cur->name, &st) != 0)
470 return 1;
471 error (f, "%s: %s", cur->name, strerror (err));
472 return -1;
473 }
474 if (!fstat (fd, &st))
475 {
476 cur->file_base = incdep_xmalloc (cur, st.st_size + 1);
477 if (read (fd, cur->file_base, st.st_size) == st.st_size)
478 {
479 close (fd);
480 cur->file_end = cur->file_base + st.st_size;
481 cur->file_base[st.st_size] = '\0';
482 return 0;
483 }
484
485 /* bail out */
486
487 error (f, "%s: read: %s", cur->name, strerror (errno));
488 incdep_xfree (cur, cur->file_base);
489 }
490 else
491 error (f, "%s: fstat: %s", cur->name, strerror (errno));
492
493 close (fd);
494 cur->file_base = cur->file_end = NULL;
495 return -1;
496}
497
498/* Free the incdep structure. */
499static void
500incdep_freeit (struct incdep *cur)
501{
502#ifdef PARSE_IN_WORKER
503 assert (!cur->recorded_variables_in_set_head);
504 assert (!cur->recorded_variable_defs_head);
505 assert (!cur->recorded_files_head);
506#endif
507
508 incdep_xfree (cur, cur->file_base);
509 cur->next = NULL;
510 free (cur);
511}
512
513/* A worker thread. */
514void
515incdep_worker (int thrd)
516{
517 incdep_lock ();
518
519 while (!incdep_terminate)
520 {
521 /* get job from the todo list. */
522
523 struct incdep *cur = incdep_head_todo;
524 if (!cur)
525 {
526 incdep_wait_todo ();
527 continue;
528 }
529 if (cur->next)
530 incdep_head_todo = cur->next;
531 else
532 incdep_head_todo = incdep_tail_todo = NULL;
533 incdep_num_reading++;
534
535 /* read the file. */
536
537 incdep_unlock ();
538 cur->worker_tid = thrd;
539
540 incdep_read_file (cur, NILF);
541#ifdef PARSE_IN_WORKER
542 eval_include_dep_file (cur, NILF);
543#endif
544
545 cur->worker_tid = -1;
546 incdep_lock ();
547
548 /* insert finished job into the done list. */
549
550 incdep_num_reading--;
551 cur->next = NULL;
552 if (incdep_tail_done)
553 incdep_tail_done->next = cur;
554 else
555 incdep_head_done = cur;
556 incdep_tail_done = cur;
557
558 incdep_signal_done ();
559 }
560
561 incdep_unlock ();
562}
563
564/* Thread library specific thread functions wrapping incdep_wroker. */
565#ifdef HAVE_PTHREAD
566static void *
567incdep_worker_pthread (void *thrd)
568{
569 incdep_worker ((size_t)thrd);
570 return NULL;
571}
572
573#elif defined (WINDOWS32)
574static unsigned __stdcall
575incdep_worker_windows (void *thrd)
576{
577 incdep_worker ((size_t)thrd);
578 return 0;
579}
580
581#elif defined (__OS2__)
582static void
583incdep_worker_os2 (void *thrd)
584{
585 incdep_worker ((size_t)thrd);
586}
587#endif
588
589/* Creates the the worker threads. */
590static void
591incdep_init (struct floc *f)
592{
593 unsigned i;
594#ifdef HAVE_PTHREAD
595 int rc;
596 pthread_attr_t attr;
597
598#elif defined (WINDOWS32)
599 unsigned tid;
600 uintptr_t hThread;
601
602#elif defined (__OS2__)
603 int rc;
604 int tid;
605#endif
606
607 /* heap hacks */
608
609#ifdef __APPLE__
610 incdep_zone = malloc_create_zone (0, 0);
611 if (!incdep_zone)
612 incdep_zone = malloc_default_zone ();
613#endif
614
615
616 /* create the mutex and two condition variables / event objects. */
617
618#ifdef HAVE_PTHREAD
619 rc = pthread_mutex_init (&incdep_mtx, NULL);
620 if (rc)
621 fatal (f, _("pthread_mutex_init failed: err=%d"), rc);
622 rc = pthread_cond_init (&incdep_cond_todo, NULL);
623 if (rc)
624 fatal (f, _("pthread_cond_init failed: err=%d"), rc);
625 rc = pthread_cond_init (&incdep_cond_done, NULL);
626 if (rc)
627 fatal (f, _("pthread_cond_init failed: err=%d"), rc);
628
629#elif defined (WINDOWS32)
630 InitializeCriticalSection (&incdep_mtx);
631 incdep_hev_todo = CreateEvent (NULL, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL);
632 if (!incdep_hev_todo)
633 fatal (f, _("CreateEvent failed: err=%d"), GetLastError());
634 incdep_hev_done = CreateEvent (NULL, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL);
635 if (!incdep_hev_done)
636 fatal (f, _("CreateEvent failed: err=%d"), GetLastError());
637 incdep_hev_todo_waiters = 0;
638 incdep_hev_done_waiters = 0;
639
640#elif defined (__OS2__)
641 _fmutex_create (&incdep_mtx, 0)
642 rc = DosCreateEventSem (NULL, &incdep_hev_todo, 0, FALSE);
643 if (rc)
644 fatal (f, _("DosCreateEventSem failed: rc=%d"), rc);
645 rc = DosCreateEventSem (NULL, &incdep_hev_done, 0, FALSE);
646 if (rc)
647 fatal (f, _("DosCreateEventSem failed: rc=%d"), rc);
648 incdep_hev_todo_waiters = 0;
649 incdep_hev_done_waiters = 0;
650#endif
651
652 /* create the worker threads and associated per thread data. */
653
654 incdep_terminate = 0;
655 incdep_num_threads = sizeof (incdep_threads) / sizeof (incdep_threads[0]);
656 if (incdep_num_threads + 1 > job_slots)
657 incdep_num_threads = job_slots <= 1 ? 1 : job_slots - 1;
658 for (i = 0; i < incdep_num_threads; i++)
659 {
660 /* init caches */
661 unsigned rec_size = sizeof (struct incdep_variable_in_set);
662 if (rec_size < sizeof (struct incdep_variable_def))
663 rec_size = sizeof (struct incdep_variable_def);
664 if (rec_size < sizeof (struct incdep_recorded_files))
665 rec_size = sizeof (struct incdep_recorded_files);
666 alloccache_init (&incdep_rec_caches[i], rec_size, "incdep rec",
667 incdep_cache_allocator, (void *)(size_t)i);
668 alloccache_init (&incdep_dep_caches[i], sizeof(struct dep), "incdep dep",
669 incdep_cache_allocator, (void *)(size_t)i);
670 strcache2_init (&incdep_dep_strcaches[i],
671 "incdep dep", /* name */
672 65536, /* hash size */
673 0, /* default segment size*/
674#ifdef HAVE_CASE_INSENSITIVE_FS
675 1, /* case insensitive */
676#else
677 0, /* case insensitive */
678#endif
679 0); /* thread safe */
680
681 strcache2_init (&incdep_var_strcaches[i],
682 "incdep var", /* name */
683 32768, /* hash size */
684 0, /* default segment size*/
685 0, /* case insensitive */
686 0); /* thread safe */
687
688 /* create the thread. */
689#ifdef HAVE_PTHREAD
690 rc = pthread_attr_init (&attr);
691 if (rc)
692 fatal (f, _("pthread_attr_init failed: err=%d"), rc);
693 /*rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); */
694 rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
695 if (rc)
696 fatal (f, _("pthread_attr_setdetachstate failed: err=%d"), rc);
697 rc = pthread_create(&incdep_threads[i], &attr,
698 incdep_worker_pthread, (void *)(size_t)i);
699 if (rc)
700 fatal (f, _("pthread_mutex_init failed: err=%d"), rc);
701 pthread_attr_destroy (&attr);
702
703#elif defined (WINDOWS32)
704 tid = 0;
705 hThread = _beginthreadex (NULL, 128*1024, incdep_worker_windows,
706 (void *)i, 0, &tid);
707 if (hThread == 0 || hThread == ~(uintptr_t)0)
708 fatal (f, _("_beginthreadex failed: err=%d"), errno);
709 incdep_threads[i] = (HANDLE)hThread;
710
711#elif defined (__OS2__)
712 tid = _beginthread (incdep_worker_os2, NULL, 128*1024, (void *)i);
713 if (tid <= 0)
714 fatal (f, _("_beginthread failed: err=%d"), errno);
715 incdep_threads[i] = tid;
716#endif
717 }
718
719 incdep_initialized = 1;
720}
721
722/* Flushes outstanding work and terminates the worker threads.
723 This is called from snap_deps(). */
724void
725incdep_flush_and_term (void)
726{
727 unsigned i;
728
729 if (!incdep_initialized)
730 return;
731
732 /* flush any out standing work */
733
734 incdep_flush_it (NILF);
735
736 /* tell the threads to terminate */
737
738 incdep_lock ();
739 incdep_terminate = 1;
740 incdep_signal_todo ();
741 incdep_unlock ();
742
743 /* wait for the threads to quit */
744
745 for (i = 0; i < incdep_num_threads; i++)
746 {
747 /* more later? */
748
749 /* terminate or join up the allocation caches. */
750 alloccache_term (&incdep_rec_caches[i], incdep_cache_deallocator, (void *)(size_t)i);
751 alloccache_join (&dep_cache, &incdep_dep_caches[i]);
752 strcache2_term (&incdep_dep_strcaches[i]);
753 strcache2_term (&incdep_var_strcaches[i]);
754 }
755 incdep_num_threads = 0;
756
757 /* destroy the lock and condition variables / event objects. */
758
759 /* later */
760
761 incdep_initialized = 0;
762}
763
764#ifdef PARSE_IN_WORKER
765/* Flushes a strcache entry returning the actual string cache entry.
766 The input is freed! */
767static const char *
768incdep_flush_strcache_entry (struct strcache2_entry *entry)
769{
770 if (!entry->user)
771 entry->user = (void *)strcache2_add_hashed_file (&file_strcache,
772 (const char *)(entry + 1),
773 entry->length,
774 entry->hash1,
775 entry->hash2);
776 return (const char *)entry->user;
777}
778
779/* Flushes the recorded instructions. */
780static void
781incdep_flush_recorded_instructions (struct incdep *cur)
782{
783 struct incdep_variable_in_set *rec_vis;
784 struct incdep_variable_def *rec_vd;
785 struct incdep_recorded_files *rec_f;
786
787 /* define_variable_in_set */
788
789 rec_vis = cur->recorded_variables_in_set_head;
790 cur->recorded_variables_in_set_head = cur->recorded_variables_in_set_tail = NULL;
791 if (rec_vis)
792 do
793 {
794 void *free_me = rec_vis;
795 unsigned int name_length = rec_vis->name_entry->length;
796 define_variable_in_set (incdep_flush_strcache_entry (rec_vis->name_entry),
797 name_length,
798 rec_vis->value,
799 rec_vis->value_length,
800 rec_vis->duplicate_value,
801 rec_vis->origin,
802 rec_vis->recursive,
803 rec_vis->set,
804 rec_vis->flocp);
805 rec_vis = rec_vis->next;
806 incdep_free_rec (cur, free_me);
807 }
808 while (rec_vis);
809
810 /* do_variable_definition */
811
812 rec_vd = cur->recorded_variable_defs_head;
813 cur->recorded_variable_defs_head = cur->recorded_variable_defs_tail = NULL;
814 if (rec_vd)
815 do
816 {
817 void *free_me = rec_vd;
818 do_variable_definition_2 (rec_vd->flocp,
819 incdep_flush_strcache_entry (rec_vd->name_entry),
820 rec_vd->value,
821 rec_vd->value_length,
822 0,
823 rec_vd->value,
824 rec_vd->origin,
825 rec_vd->flavor,
826 rec_vd->target_var);
827 rec_vd = rec_vd->next;
828 incdep_free_rec (cur, free_me);
829 }
830 while (rec_vd);
831
832 /* record_files */
833
834 rec_f = cur->recorded_files_head;
835 cur->recorded_files_head = cur->recorded_files_tail = NULL;
836 if (rec_f)
837 do
838 {
839 void *free_me = rec_f;
840 struct dep *dep;
841 struct nameseq *filenames;
842
843 for (dep = rec_f->deps; dep; dep = dep->next)
844 dep->name = incdep_flush_strcache_entry ((struct strcache2_entry *)dep->name);
845
846 filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
847 filenames->next = 0;
848 filenames->name = incdep_flush_strcache_entry (rec_f->filename_entry);
849
850 record_files (filenames,
851 rec_f->pattern,
852 rec_f->pattern_percent,
853 rec_f->deps,
854 rec_f->cmds_started,
855 rec_f->commands,
856 rec_f->commands_idx,
857 rec_f->two_colon,
858 rec_f->flocp);
859
860 rec_f = rec_f->next;
861 incdep_free_rec (cur, free_me);
862 }
863 while (rec_f);
864}
865#endif /* PARSE_IN_WORKER */
866
867/* Record / issue a warning about a misformed dep file. */
868static void
869incdep_warn (struct incdep *cur, unsigned int line_no, const char *msg)
870{
871 if (cur->worker_tid == -1)
872 error (NILF, "%s(%d): %s", cur->name, line_no, msg);
873#ifdef PARSE_IN_WORKER
874 else
875 {
876 cur->err_line_no = line_no;
877 cur->err_msg = msg;
878 }
879#endif
880}
881
882/* Dependency or file strcache allocation / recording. */
883static const char *
884incdep_dep_strcache (struct incdep *cur, const char *str, int len)
885{
886 const char *ret;
887 if (cur->worker_tid == -1)
888 {
889 /* Make sure the string is terminated before we hand it to
890 strcache_add_len so it does have to make a temporary copy
891 of it on the stack. */
892 char ch = str[len];
893 ((char *)str)[len] = '\0';
894 ret = strcache_add_len (str, len);
895 ((char *)str)[len] = ch;
896 }
897 else
898 {
899 /* Add it out the strcache of the thread. */
900 ret = strcache2_add (&incdep_dep_strcaches[cur->worker_tid], str, len);
901 ret = (const char *)strcache2_get_entry(&incdep_dep_strcaches[cur->worker_tid], ret);
902 }
903 return ret;
904}
905
906/* Variable name allocation / recording. */
907static const char *
908incdep_var_strcache (struct incdep *cur, const char *str, int len)
909{
910 const char *ret;
911 if (cur->worker_tid == -1)
912 {
913 /* XXX: we're leaking this memory now! This will be fixed later. */
914 ret = xmalloc (len + 1);
915 memcpy ((char *)ret, str, len);
916 ((char *)ret)[len] = '\0';
917 }
918 else
919 {
920 /* Add it out the strcache of the thread. */
921 ret = strcache2_add (&incdep_var_strcaches[cur->worker_tid], str, len);
922 ret = (const char *)strcache2_get_entry(&incdep_var_strcaches[cur->worker_tid], ret);
923 }
924 return ret;
925}
926
927/* Record / perform a variable definition in a set.
928 The NAME is in the string cache.
929 The VALUE is on the heap.
930 The DUPLICATE_VALUE is always 0. */
931static void
932incdep_record_variable_in_set (struct incdep *cur,
933 const char *name, unsigned int name_length,
934 const char *value,
935 unsigned int value_length,
936 int duplicate_value,
937 enum variable_origin origin,
938 int recursive,
939 struct variable_set *set,
940 const struct floc *flocp)
941{
942 assert (!duplicate_value);
943 if (cur->worker_tid == -1)
944 define_variable_in_set (name, name_length, value, value_length,
945 duplicate_value, origin, recursive, set, flocp);
946#ifdef PARSE_IN_WORKER
947 else
948 {
949 struct incdep_variable_in_set *rec =
950 (struct incdep_variable_in_set *)incdep_alloc_rec (cur);
951 rec->name_entry = (struct strcache2_entry *)name;
952 rec->value = value;
953 rec->value_length = value_length;
954 rec->duplicate_value = duplicate_value;
955 rec->origin = origin;
956 rec->recursive = recursive;
957 rec->set = set;
958 rec->flocp = flocp;
959
960 rec->next = NULL;
961 if (cur->recorded_variables_in_set_tail)
962 cur->recorded_variables_in_set_tail->next = rec;
963 else
964 cur->recorded_variables_in_set_head = rec;
965 cur->recorded_variables_in_set_tail = rec;
966 }
967#endif
968}
969
970/* Record / perform a variable definition. The VALUE should be disposed of. */
971static void
972incdep_record_variable_def (struct incdep *cur,
973 const struct floc *flocp,
974 const char *name,
975 unsigned int name_length,
976 char *value,
977 unsigned int value_length,
978 enum variable_origin origin,
979 enum variable_flavor flavor,
980 int target_var)
981{
982 if (cur->worker_tid == -1)
983 do_variable_definition_2 (flocp, name, value, value_length, 0, value,
984 origin, flavor, target_var);
985#ifdef PARSE_IN_WORKER
986 else
987 {
988 struct incdep_variable_def *rec =
989 (struct incdep_variable_def *)incdep_alloc_rec (cur);
990 rec->flocp = flocp;
991 rec->name_entry = (struct strcache2_entry *)name;
992 rec->value = value;
993 rec->value_length = value_length;
994 rec->origin = origin;
995 rec->flavor = flavor;
996 rec->target_var = target_var;
997
998 rec->next = NULL;
999 if (cur->recorded_variable_defs_tail)
1000 cur->recorded_variable_defs_tail->next = rec;
1001 else
1002 cur->recorded_variable_defs_head = rec;
1003 cur->recorded_variable_defs_tail = rec;
1004 }
1005#else
1006 (void)name_length;
1007#endif
1008}
1009
1010/* Record files.*/
1011static void
1012incdep_record_files (struct incdep *cur,
1013 const char *filename, const char *pattern,
1014 const char *pattern_percent, struct dep *deps,
1015 unsigned int cmds_started, char *commands,
1016 unsigned int commands_idx, int two_colon,
1017 const struct floc *flocp)
1018{
1019 if (cur->worker_tid == -1)
1020 {
1021 struct nameseq *filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
1022 filenames->next = 0;
1023 filenames->name = filename;
1024 record_files (filenames, pattern, pattern_percent, deps, cmds_started,
1025 commands, commands_idx, two_colon, flocp);
1026 }
1027#ifdef PARSE_IN_WORKER
1028 else
1029 {
1030 struct incdep_recorded_files *rec =
1031 (struct incdep_recorded_files *) incdep_alloc_rec (cur);
1032
1033 rec->filename_entry = (struct strcache2_entry *)filename;
1034 rec->pattern = pattern;
1035 rec->pattern_percent = pattern_percent;
1036 rec->deps = deps;
1037 rec->cmds_started = cmds_started;
1038 rec->commands = commands;
1039 rec->commands_idx = commands_idx;
1040 rec->two_colon = two_colon;
1041 rec->flocp = flocp;
1042
1043 rec->next = NULL;
1044 if (cur->recorded_files_tail)
1045 cur->recorded_files_tail->next = rec;
1046 else
1047 cur->recorded_files_head = rec;
1048 cur->recorded_files_tail = rec;
1049 }
1050#endif
1051}
1052
1053
1054/* no nonsense dependency file including.
1055
1056 Because nobody wants bogus dependency files to break their incremental
1057 builds with hard to comprehend error messages, this function does not
1058 use the normal eval routine but does all the parsing itself. This isn't,
1059 as much work as it sounds, because the necessary feature set is very
1060 limited.
1061
1062 eval_include_dep_file groks:
1063
1064 define var
1065 endef
1066
1067 var [|:|?|>]= value [\]
1068
1069 [\]
1070 file: [deps] [\]
1071
1072 */
1073static void
1074eval_include_dep_file (struct incdep *curdep, struct floc *f)
1075{
1076 unsigned line_no = 1;
1077 const char *file_end = curdep->file_end;
1078 const char *cur = curdep->file_base;
1079 const char *endp;
1080
1081 /* if no file data, just return immediately. */
1082 if (!cur)
1083 return;
1084
1085 /* now parse the file. */
1086 while (cur < file_end)
1087 {
1088 /* skip empty lines */
1089 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
1090 ++cur;
1091 if (cur >= file_end)
1092 break;
1093 if (*cur == '#')
1094 {
1095 cur = memchr (cur, '\n', file_end - cur);
1096 if (!cur)
1097 break;
1098 }
1099 if (*cur == '\\')
1100 {
1101 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
1102 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
1103 : (file_end - cur == 1) ? 1 : 0;
1104 if (eol_len)
1105 {
1106 cur += eol_len;
1107 line_no++;
1108 continue;
1109 }
1110 }
1111 if (*cur == '\n')
1112 {
1113 cur++;
1114 line_no++;
1115 continue;
1116 }
1117
1118 /* define var
1119 ...
1120 endef */
1121 if (strneq (cur, "define ", 7))
1122 {
1123 const char *var;
1124 unsigned var_len;
1125 const char *value_start;
1126 const char *value_end;
1127 char *value;
1128 unsigned value_len;
1129 int found_endef = 0;
1130
1131 /* extract the variable name. */
1132 cur += 7;
1133 while (isblank ((unsigned char)*cur))
1134 ++cur;
1135 value_start = endp = memchr (cur, '\n', file_end - cur);
1136 if (!endp)
1137 endp = cur;
1138 while (endp > cur && isspace ((unsigned char)endp[-1]))
1139 --endp;
1140 var_len = endp - cur;
1141 if (!var_len)
1142 {
1143 incdep_warn (curdep, line_no, "bogus define statement.");
1144 break;
1145 }
1146 var = incdep_var_strcache (curdep, cur, var_len);
1147
1148 /* find the end of the variable. */
1149 cur = value_end = value_start = value_start + 1;
1150 ++line_no;
1151 while (cur < file_end)
1152 {
1153 /* check for endef, don't bother with skipping leading spaces. */
1154 if ( file_end - cur >= 5
1155 && strneq (cur, "endef", 5))
1156 {
1157 endp = cur + 5;
1158 while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n')
1159 endp++;
1160 if (endp >= file_end || *endp == '\n')
1161 {
1162 found_endef = 1;
1163 cur = endp >= file_end ? file_end : endp + 1;
1164 break;
1165 }
1166 }
1167
1168 /* skip a line ahead. */
1169 cur = value_end = memchr (cur, '\n', file_end - cur);
1170 if (cur != NULL)
1171 ++cur;
1172 else
1173 cur = value_end = file_end;
1174 ++line_no;
1175 }
1176
1177 if (!found_endef)
1178 {
1179 incdep_warn (curdep, line_no, "missing endef, dropping the rest of the file.");
1180 break;
1181 }
1182 value_len = value_end - value_start;
1183 if (memchr (value_start, '\0', value_len))
1184 {
1185 incdep_warn (curdep, line_no, "'\\0' in define, dropping the rest of the file.");
1186 break;
1187 }
1188
1189 /* make a copy of the value, converting \r\n to \n, and define it. */
1190 value = incdep_xmalloc (curdep, value_len + 1);
1191 endp = memchr (value_start, '\r', value_len);
1192 if (endp)
1193 {
1194 const char *src = value_start;
1195 char *dst = value;
1196 for (;;)
1197 {
1198 size_t len = endp - src;
1199 memcpy (dst, src, len);
1200 dst += len;
1201 src = endp;
1202 if (src + 1 < file_end && src[1] == '\n')
1203 src++; /* skip the '\r' */
1204 if (src >= value_end)
1205 break;
1206 endp = memchr (endp + 1, '\r', src - value_end);
1207 if (!endp)
1208 endp = value_end;
1209 }
1210 value_len = dst - value;
1211 }
1212 else
1213 memcpy (value, value_start, value_len);
1214 value [value_len] = '\0';
1215
1216 incdep_record_variable_in_set (curdep,
1217 var, var_len, value, value_len,
1218 0 /* don't duplicate */, o_file,
1219 0 /* defines are recursive but this is faster */,
1220 NULL /* global set */, f);
1221 }
1222
1223 /* file: deps
1224 OR
1225 variable [:]= value */
1226 else
1227 {
1228 const char *colonp;
1229 const char *equalp;
1230
1231 /* Look for a colon and an equal sign, optimize for colon.
1232 Only one file is support and the colon / equal must be on
1233 the same line. */
1234 colonp = memchr (cur, ':', file_end - cur);
1235#ifdef HAVE_DOS_PATHS
1236 while ( colonp
1237 && colonp + 1 < file_end
1238 && (colonp[1] == '/' || colonp[1] == '\\')
1239 && colonp > cur
1240 && isalpha ((unsigned char)colonp[-1])
1241 && ( colonp == cur + 1
1242 || strchr (" \t(", colonp[-2]) != 0))
1243 colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
1244#endif
1245 endp = NULL;
1246 if ( !colonp
1247 || (endp = memchr (cur, '\n', colonp - cur)))
1248 {
1249 colonp = NULL;
1250 equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);
1251 if ( !equalp
1252 || (!endp && memchr (cur, '\n', equalp - cur)))
1253 {
1254 incdep_warn (curdep, line_no, "no colon.");
1255 break;
1256 }
1257 }
1258 else
1259 equalp = memchr (cur, '=', (colonp + 2 <= file_end
1260 ? colonp + 2 : file_end) - cur);
1261 if (equalp)
1262 {
1263 /* An assignment of some sort. */
1264 const char *var;
1265 unsigned var_len;
1266 const char *value_start;
1267 const char *value_end;
1268 char *value;
1269 unsigned value_len;
1270 unsigned multi_line = 0;
1271 enum variable_flavor flavor;
1272
1273 /* figure the flavor first. */
1274 flavor = f_recursive;
1275 if (equalp > cur)
1276 {
1277 if (equalp[-1] == ':')
1278 flavor = f_simple;
1279 else if (equalp[-1] == '?')
1280 flavor = f_conditional;
1281 else if (equalp[-1] == '+')
1282 flavor = f_append;
1283 else if (equalp[-1] == '>')
1284 flavor = f_prepend;
1285 }
1286
1287 /* extract the variable name. */
1288 endp = flavor == f_recursive ? equalp : equalp - 1;
1289 while (endp > cur && isblank ((unsigned char)endp[-1]))
1290 --endp;
1291 var_len = endp - cur;
1292 if (!var_len)
1293 {
1294 incdep_warn (curdep, line_no, "empty variable. (includedep)");
1295 break;
1296 }
1297 if ( memchr (cur, '$', var_len)
1298 || memchr (cur, ' ', var_len)
1299 || memchr (cur, '\t', var_len))
1300 {
1301 incdep_warn (curdep, line_no, "fancy variable name. (includedep)");
1302 break;
1303 }
1304 var = incdep_var_strcache (curdep, cur, var_len);
1305
1306 /* find the start of the value. */
1307 cur = equalp + 1;
1308 while (cur < file_end && isblank ((unsigned char)*cur))
1309 cur++;
1310 value_start = cur;
1311
1312 /* find the end of the value / line (this isn't 101% correct). */
1313 value_end = cur;
1314 while (cur < file_end)
1315 {
1316 endp = value_end = memchr (cur, '\n', file_end - cur);
1317 if (!value_end)
1318 value_end = file_end;
1319 if (value_end - 1 >= cur && value_end[-1] == '\r')
1320 --value_end;
1321 if (value_end - 1 < cur || value_end[-1] != '\\')
1322 {
1323 cur = endp ? endp + 1 : file_end;
1324 break;
1325 }
1326 --value_end;
1327 if (value_end - 1 >= cur && value_end[-1] == '\\')
1328 {
1329 incdep_warn (curdep, line_no, "fancy escaping! (includedep)");
1330 cur = NULL;
1331 break;
1332 }
1333 if (!endp)
1334 {
1335 cur = file_end;
1336 break;
1337 }
1338
1339 cur = endp + 1;
1340 ++multi_line;
1341 ++line_no;
1342 }
1343 if (!cur)
1344 break;
1345 ++line_no;
1346
1347 /* make a copy of the value, converting \r\n to \n, and define it. */
1348 value_len = value_end - value_start;
1349 value = incdep_xmalloc (curdep, value_len + 1);
1350 if (!multi_line)
1351 memcpy (value, value_start, value_len);
1352 else
1353 {
1354 /* unescape it */
1355 const char *src = value_start;
1356 char *dst = value;
1357 while (src < value_end)
1358 {
1359 const char *nextp;
1360
1361 endp = memchr (src, '\n', value_end - src);
1362 if (!endp)
1363 nextp = endp = value_end;
1364 else
1365 nextp = endp + 1;
1366 if (endp > src && endp[-1] == '\r')
1367 --endp;
1368 if (endp > src && endp[-1] == '\\')
1369 --endp;
1370
1371 if (src != value_start)
1372 *dst++ = ' ';
1373 memcpy (dst, src, endp - src);
1374 dst += endp - src;
1375 src = nextp;
1376 }
1377 value_len = dst - value;
1378 }
1379 value [value_len] = '\0';
1380
1381 /* do the definition */
1382 if (flavor == f_recursive
1383 || ( flavor == f_simple
1384 && !memchr (value, '$', value_len)))
1385 incdep_record_variable_in_set (curdep,
1386 var, var_len, value, value_len,
1387 0 /* don't duplicate */, o_file,
1388 flavor == f_recursive /* recursive */,
1389 NULL /* global set */, f);
1390 else
1391 incdep_record_variable_def (curdep,
1392 f, var, var_len, value, value_len,
1393 o_file, flavor, 0 /* not target var */);
1394 }
1395 else
1396 {
1397 /* file: dependencies */
1398
1399 const char *filename;
1400 struct dep *deps = 0;
1401 struct dep **nextdep = &deps;
1402 struct dep *dep;
1403
1404 /* extract the filename, ASSUME a single one. */
1405 endp = colonp;
1406 while (endp > cur && isblank ((unsigned char)endp[-1]))
1407 --endp;
1408 if (cur == endp)
1409 {
1410 incdep_warn (curdep, line_no, "empty filename.");
1411 break;
1412 }
1413 if ( memchr (cur, '$', endp - cur)
1414 || memchr (cur, ' ', endp - cur)
1415 || memchr (cur, '\t', endp - cur))
1416 {
1417 incdep_warn (curdep, line_no, "multiple / fancy file name. (includedep)");
1418 break;
1419 }
1420 filename = incdep_dep_strcache (curdep, cur, endp - cur);
1421
1422 /* parse any dependencies. */
1423 cur = colonp + 1;
1424 while (cur < file_end)
1425 {
1426 /* skip blanks and count lines. */
1427 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
1428 ++cur;
1429 if (cur >= file_end)
1430 break;
1431 if (*cur == '\n')
1432 {
1433 cur++;
1434 line_no++;
1435 break;
1436 }
1437
1438 /* continuation + eol? */
1439 if (*cur == '\\')
1440 {
1441 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
1442 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
1443 : (file_end - cur == 1) ? 1 : 0;
1444 if (eol_len)
1445 {
1446 cur += eol_len;
1447 line_no++;
1448 continue;
1449 }
1450 }
1451
1452 /* find the end of the filename */
1453 endp = cur;
1454 while (endp < file_end && !isspace ((unsigned char)*endp))
1455 ++endp;
1456
1457 /* add it to the list. */
1458 *nextdep = dep = incdep_alloc_dep (curdep);
1459 dep->name = incdep_dep_strcache (curdep, cur, endp - cur);
1460 dep->includedep = 1;
1461 nextdep = &dep->next;
1462
1463 cur = endp;
1464 }
1465
1466 /* enter the file with its dependencies. */
1467 incdep_record_files (curdep,
1468 filename, NULL, NULL, deps, 0, NULL, 0, 0, f);
1469 }
1470 }
1471 }
1472
1473 /* free the file data */
1474 incdep_xfree (curdep, curdep->file_base);
1475 curdep->file_base = curdep->file_end = NULL;
1476}
1477
1478/* Flushes the incdep todo and done lists. */
1479static void
1480incdep_flush_it (struct floc *f)
1481{
1482 incdep_lock ();
1483 for (;;)
1484 {
1485 struct incdep *cur = incdep_head_done;
1486
1487 /* if the done list is empty, grab a todo list entry. */
1488 if (!cur && incdep_head_todo)
1489 {
1490 cur = incdep_head_todo;
1491 if (cur->next)
1492 incdep_head_todo = cur->next;
1493 else
1494 incdep_head_todo = incdep_tail_todo = NULL;
1495 incdep_unlock ();
1496
1497 incdep_read_file (cur, f);
1498 eval_include_dep_file (cur, f);
1499 incdep_freeit (cur);
1500
1501 incdep_lock ();
1502 continue;
1503 }
1504
1505 /* if the todo list and done list are empty we're either done
1506 or will have to wait for the thread(s) to finish. */
1507 if (!cur && !incdep_num_reading)
1508 break; /* done */
1509 if (!cur)
1510 {
1511 while (!incdep_head_done)
1512 incdep_wait_done ();
1513 cur = incdep_head_done;
1514 }
1515
1516 /* we grab the entire done list and work thru it. */
1517 incdep_head_done = incdep_tail_done = NULL;
1518 incdep_unlock ();
1519
1520 while (cur)
1521 {
1522 struct incdep *next = cur->next;
1523#ifdef PARSE_IN_WORKER
1524 incdep_flush_recorded_instructions (cur);
1525#else
1526 eval_include_dep_file (cur, f);
1527#endif
1528 incdep_freeit (cur);
1529 cur = next;
1530 }
1531
1532 incdep_lock ();
1533 } /* outer loop */
1534 incdep_unlock ();
1535}
1536
1537
1538/* splits up a list of file names and feeds it to eval_include_dep_file,
1539 employing threads to try speed up the file reading. */
1540void
1541eval_include_dep (const char *names, struct floc *f, enum incdep_op op)
1542{
1543 struct incdep *head = 0;
1544 struct incdep *tail = 0;
1545 struct incdep *cur;
1546 const char *names_iterator = names;
1547 const char *name;
1548 unsigned int name_len;
1549
1550 /* loop through NAMES, creating a todo list out of them. */
1551
1552 while ((name = find_next_token (&names_iterator, &name_len)) != 0)
1553 {
1554 cur = xmalloc (sizeof (*cur) + name_len); /* not incdep_xmalloc here */
1555 cur->file_base = cur->file_end = NULL;
1556 memcpy (cur->name, name, name_len);
1557 cur->name[name_len] = '\0';
1558 cur->worker_tid = -1;
1559#ifdef PARSE_IN_WORKER
1560 cur->err_line_no = 0;
1561 cur->err_msg = NULL;
1562 cur->recorded_variables_in_set_head = NULL;
1563 cur->recorded_variables_in_set_tail = NULL;
1564 cur->recorded_variable_defs_head = NULL;
1565 cur->recorded_variable_defs_tail = NULL;
1566 cur->recorded_files_head = NULL;
1567 cur->recorded_files_tail = NULL;
1568#endif
1569
1570 cur->next = NULL;
1571 if (tail)
1572 tail->next = cur;
1573 else
1574 head = cur;
1575 tail = cur;
1576 }
1577
1578#ifdef ELECTRIC_HEAP
1579 if (1)
1580#else
1581 if (op == incdep_read_it)
1582#endif
1583 {
1584 /* work our way thru the files directly */
1585
1586 cur = head;
1587 while (cur)
1588 {
1589 struct incdep *next = cur->next;
1590 incdep_read_file (cur, f);
1591 eval_include_dep_file (cur, f);
1592 incdep_freeit (cur);
1593 cur = next;
1594 }
1595 }
1596 else
1597 {
1598 /* initialize the worker threads and related stuff the first time around. */
1599
1600 if (!incdep_initialized)
1601 incdep_init (f);
1602
1603 /* queue the files and notify the worker threads. */
1604
1605 incdep_lock ();
1606
1607 if (incdep_tail_todo)
1608 incdep_tail_todo->next = head;
1609 else
1610 incdep_head_todo = head;
1611 incdep_tail_todo = tail;
1612
1613 incdep_signal_todo ();
1614 incdep_unlock ();
1615
1616 /* flush the todo queue if we're requested to do so. */
1617
1618 if (op == incdep_flush)
1619 incdep_flush_it (f);
1620 }
1621}
1622
1623#endif /* CONFIG_WITH_INCLUDEDEP */
1624
Note: See TracBrowser for help on using the repository browser.