VirtualBox

source: kBuild/trunk/src/kmk/incdep.c@ 1909

Last change on this file since 1909 was 1909, checked in by bird, 16 years ago

strcache2: Implemented collision resolution by chaining instead of open addressing. This is faster than the open addressing approach we're using.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 47.0 KB
Line 
1#ifdef CONFIG_WITH_INCLUDEDEP
2/* $Id: incdep.c 1909 2008-10-22 18:49:48Z bird $ */
3/** @file
4 * incdep - Simple dependency files.
5 */
6
7/*
8 * Copyright (c) 2006-2008 knut st. osmundsen <[email protected]>
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#ifdef STRCACHE2_USE_CHAINING
776 1);
777#else
778 entry->hash2);
779#endif
780 return (const char *)entry->user;
781}
782
783/* Flushes the recorded instructions. */
784static void
785incdep_flush_recorded_instructions (struct incdep *cur)
786{
787 struct incdep_variable_in_set *rec_vis;
788 struct incdep_variable_def *rec_vd;
789 struct incdep_recorded_files *rec_f;
790
791 /* define_variable_in_set */
792
793 rec_vis = cur->recorded_variables_in_set_head;
794 cur->recorded_variables_in_set_head = cur->recorded_variables_in_set_tail = NULL;
795 if (rec_vis)
796 do
797 {
798 void *free_me = rec_vis;
799 unsigned int name_length = rec_vis->name_entry->length;
800 define_variable_in_set (incdep_flush_strcache_entry (rec_vis->name_entry),
801 name_length,
802 rec_vis->value,
803 rec_vis->value_length,
804 rec_vis->duplicate_value,
805 rec_vis->origin,
806 rec_vis->recursive,
807 rec_vis->set,
808 rec_vis->flocp);
809 rec_vis = rec_vis->next;
810 incdep_free_rec (cur, free_me);
811 }
812 while (rec_vis);
813
814 /* do_variable_definition */
815
816 rec_vd = cur->recorded_variable_defs_head;
817 cur->recorded_variable_defs_head = cur->recorded_variable_defs_tail = NULL;
818 if (rec_vd)
819 do
820 {
821 void *free_me = rec_vd;
822 do_variable_definition_2 (rec_vd->flocp,
823 incdep_flush_strcache_entry (rec_vd->name_entry),
824 rec_vd->value,
825 rec_vd->value_length,
826 0,
827 rec_vd->value,
828 rec_vd->origin,
829 rec_vd->flavor,
830 rec_vd->target_var);
831 rec_vd = rec_vd->next;
832 incdep_free_rec (cur, free_me);
833 }
834 while (rec_vd);
835
836 /* record_files */
837
838 rec_f = cur->recorded_files_head;
839 cur->recorded_files_head = cur->recorded_files_tail = NULL;
840 if (rec_f)
841 do
842 {
843 void *free_me = rec_f;
844 struct dep *dep;
845 struct nameseq *filenames;
846
847 for (dep = rec_f->deps; dep; dep = dep->next)
848 dep->name = incdep_flush_strcache_entry ((struct strcache2_entry *)dep->name);
849
850 filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
851 filenames->next = 0;
852 filenames->name = incdep_flush_strcache_entry (rec_f->filename_entry);
853
854 record_files (filenames,
855 rec_f->pattern,
856 rec_f->pattern_percent,
857 rec_f->deps,
858 rec_f->cmds_started,
859 rec_f->commands,
860 rec_f->commands_idx,
861 rec_f->two_colon,
862 rec_f->flocp);
863
864 rec_f = rec_f->next;
865 incdep_free_rec (cur, free_me);
866 }
867 while (rec_f);
868}
869#endif /* PARSE_IN_WORKER */
870
871/* Record / issue a warning about a misformed dep file. */
872static void
873incdep_warn (struct incdep *cur, unsigned int line_no, const char *msg)
874{
875 if (cur->worker_tid == -1)
876 error (NILF, "%s(%d): %s", cur->name, line_no, msg);
877#ifdef PARSE_IN_WORKER
878 else
879 {
880 cur->err_line_no = line_no;
881 cur->err_msg = msg;
882 }
883#endif
884}
885
886/* Dependency or file strcache allocation / recording. */
887static const char *
888incdep_dep_strcache (struct incdep *cur, const char *str, int len)
889{
890 const char *ret;
891 if (cur->worker_tid == -1)
892 {
893 /* Make sure the string is terminated before we hand it to
894 strcache_add_len so it does have to make a temporary copy
895 of it on the stack. */
896 char ch = str[len];
897 ((char *)str)[len] = '\0';
898 ret = strcache_add_len (str, len);
899 ((char *)str)[len] = ch;
900 }
901 else
902 {
903 /* Add it out the strcache of the thread. */
904 ret = strcache2_add (&incdep_dep_strcaches[cur->worker_tid], str, len);
905 ret = (const char *)strcache2_get_entry(&incdep_dep_strcaches[cur->worker_tid], ret);
906 }
907 return ret;
908}
909
910/* Variable name allocation / recording. */
911static const char *
912incdep_var_strcache (struct incdep *cur, const char *str, int len)
913{
914 const char *ret;
915 if (cur->worker_tid == -1)
916 {
917 /* XXX: we're leaking this memory now! This will be fixed later. */
918 ret = xmalloc (len + 1);
919 memcpy ((char *)ret, str, len);
920 ((char *)ret)[len] = '\0';
921 }
922 else
923 {
924 /* Add it out the strcache of the thread. */
925 ret = strcache2_add (&incdep_var_strcaches[cur->worker_tid], str, len);
926 ret = (const char *)strcache2_get_entry(&incdep_var_strcaches[cur->worker_tid], ret);
927 }
928 return ret;
929}
930
931/* Record / perform a variable definition in a set.
932 The NAME is in the string cache.
933 The VALUE is on the heap.
934 The DUPLICATE_VALUE is always 0. */
935static void
936incdep_record_variable_in_set (struct incdep *cur,
937 const char *name, unsigned int name_length,
938 const char *value,
939 unsigned int value_length,
940 int duplicate_value,
941 enum variable_origin origin,
942 int recursive,
943 struct variable_set *set,
944 const struct floc *flocp)
945{
946 assert (!duplicate_value);
947 if (cur->worker_tid == -1)
948 define_variable_in_set (name, name_length, value, value_length,
949 duplicate_value, origin, recursive, set, flocp);
950#ifdef PARSE_IN_WORKER
951 else
952 {
953 struct incdep_variable_in_set *rec =
954 (struct incdep_variable_in_set *)incdep_alloc_rec (cur);
955 rec->name_entry = (struct strcache2_entry *)name;
956 rec->value = value;
957 rec->value_length = value_length;
958 rec->duplicate_value = duplicate_value;
959 rec->origin = origin;
960 rec->recursive = recursive;
961 rec->set = set;
962 rec->flocp = flocp;
963
964 rec->next = NULL;
965 if (cur->recorded_variables_in_set_tail)
966 cur->recorded_variables_in_set_tail->next = rec;
967 else
968 cur->recorded_variables_in_set_head = rec;
969 cur->recorded_variables_in_set_tail = rec;
970 }
971#endif
972}
973
974/* Record / perform a variable definition. The VALUE should be disposed of. */
975static void
976incdep_record_variable_def (struct incdep *cur,
977 const struct floc *flocp,
978 const char *name,
979 unsigned int name_length,
980 char *value,
981 unsigned int value_length,
982 enum variable_origin origin,
983 enum variable_flavor flavor,
984 int target_var)
985{
986 if (cur->worker_tid == -1)
987 do_variable_definition_2 (flocp, name, value, value_length, 0, value,
988 origin, flavor, target_var);
989#ifdef PARSE_IN_WORKER
990 else
991 {
992 struct incdep_variable_def *rec =
993 (struct incdep_variable_def *)incdep_alloc_rec (cur);
994 rec->flocp = flocp;
995 rec->name_entry = (struct strcache2_entry *)name;
996 rec->value = value;
997 rec->value_length = value_length;
998 rec->origin = origin;
999 rec->flavor = flavor;
1000 rec->target_var = target_var;
1001
1002 rec->next = NULL;
1003 if (cur->recorded_variable_defs_tail)
1004 cur->recorded_variable_defs_tail->next = rec;
1005 else
1006 cur->recorded_variable_defs_head = rec;
1007 cur->recorded_variable_defs_tail = rec;
1008 }
1009#else
1010 (void)name_length;
1011#endif
1012}
1013
1014/* Record files.*/
1015static void
1016incdep_record_files (struct incdep *cur,
1017 const char *filename, const char *pattern,
1018 const char *pattern_percent, struct dep *deps,
1019 unsigned int cmds_started, char *commands,
1020 unsigned int commands_idx, int two_colon,
1021 const struct floc *flocp)
1022{
1023 if (cur->worker_tid == -1)
1024 {
1025 struct nameseq *filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache);
1026 filenames->next = 0;
1027 filenames->name = filename;
1028 record_files (filenames, pattern, pattern_percent, deps, cmds_started,
1029 commands, commands_idx, two_colon, flocp);
1030 }
1031#ifdef PARSE_IN_WORKER
1032 else
1033 {
1034 struct incdep_recorded_files *rec =
1035 (struct incdep_recorded_files *) incdep_alloc_rec (cur);
1036
1037 rec->filename_entry = (struct strcache2_entry *)filename;
1038 rec->pattern = pattern;
1039 rec->pattern_percent = pattern_percent;
1040 rec->deps = deps;
1041 rec->cmds_started = cmds_started;
1042 rec->commands = commands;
1043 rec->commands_idx = commands_idx;
1044 rec->two_colon = two_colon;
1045 rec->flocp = flocp;
1046
1047 rec->next = NULL;
1048 if (cur->recorded_files_tail)
1049 cur->recorded_files_tail->next = rec;
1050 else
1051 cur->recorded_files_head = rec;
1052 cur->recorded_files_tail = rec;
1053 }
1054#endif
1055}
1056
1057
1058/* no nonsense dependency file including.
1059
1060 Because nobody wants bogus dependency files to break their incremental
1061 builds with hard to comprehend error messages, this function does not
1062 use the normal eval routine but does all the parsing itself. This isn't,
1063 as much work as it sounds, because the necessary feature set is very
1064 limited.
1065
1066 eval_include_dep_file groks:
1067
1068 define var
1069 endef
1070
1071 var [|:|?|>]= value [\]
1072
1073 [\]
1074 file: [deps] [\]
1075
1076 */
1077static void
1078eval_include_dep_file (struct incdep *curdep, struct floc *f)
1079{
1080 unsigned line_no = 1;
1081 const char *file_end = curdep->file_end;
1082 const char *cur = curdep->file_base;
1083 const char *endp;
1084
1085 /* if no file data, just return immediately. */
1086 if (!cur)
1087 return;
1088
1089 /* now parse the file. */
1090 while (cur < file_end)
1091 {
1092 /* skip empty lines */
1093 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
1094 ++cur;
1095 if (cur >= file_end)
1096 break;
1097 if (*cur == '#')
1098 {
1099 cur = memchr (cur, '\n', file_end - cur);
1100 if (!cur)
1101 break;
1102 }
1103 if (*cur == '\\')
1104 {
1105 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
1106 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
1107 : (file_end - cur == 1) ? 1 : 0;
1108 if (eol_len)
1109 {
1110 cur += eol_len;
1111 line_no++;
1112 continue;
1113 }
1114 }
1115 if (*cur == '\n')
1116 {
1117 cur++;
1118 line_no++;
1119 continue;
1120 }
1121
1122 /* define var
1123 ...
1124 endef */
1125 if (strneq (cur, "define ", 7))
1126 {
1127 const char *var;
1128 unsigned var_len;
1129 const char *value_start;
1130 const char *value_end;
1131 char *value;
1132 unsigned value_len;
1133 int found_endef = 0;
1134
1135 /* extract the variable name. */
1136 cur += 7;
1137 while (isblank ((unsigned char)*cur))
1138 ++cur;
1139 value_start = endp = memchr (cur, '\n', file_end - cur);
1140 if (!endp)
1141 endp = cur;
1142 while (endp > cur && isspace ((unsigned char)endp[-1]))
1143 --endp;
1144 var_len = endp - cur;
1145 if (!var_len)
1146 {
1147 incdep_warn (curdep, line_no, "bogus define statement.");
1148 break;
1149 }
1150 var = incdep_var_strcache (curdep, cur, var_len);
1151
1152 /* find the end of the variable. */
1153 cur = value_end = value_start = value_start + 1;
1154 ++line_no;
1155 while (cur < file_end)
1156 {
1157 /* check for endef, don't bother with skipping leading spaces. */
1158 if ( file_end - cur >= 5
1159 && strneq (cur, "endef", 5))
1160 {
1161 endp = cur + 5;
1162 while (endp < file_end && isspace ((unsigned char)*endp) && *endp != '\n')
1163 endp++;
1164 if (endp >= file_end || *endp == '\n')
1165 {
1166 found_endef = 1;
1167 cur = endp >= file_end ? file_end : endp + 1;
1168 break;
1169 }
1170 }
1171
1172 /* skip a line ahead. */
1173 cur = value_end = memchr (cur, '\n', file_end - cur);
1174 if (cur != NULL)
1175 ++cur;
1176 else
1177 cur = value_end = file_end;
1178 ++line_no;
1179 }
1180
1181 if (!found_endef)
1182 {
1183 incdep_warn (curdep, line_no, "missing endef, dropping the rest of the file.");
1184 break;
1185 }
1186 value_len = value_end - value_start;
1187 if (memchr (value_start, '\0', value_len))
1188 {
1189 incdep_warn (curdep, line_no, "'\\0' in define, dropping the rest of the file.");
1190 break;
1191 }
1192
1193 /* make a copy of the value, converting \r\n to \n, and define it. */
1194 value = incdep_xmalloc (curdep, value_len + 1);
1195 endp = memchr (value_start, '\r', value_len);
1196 if (endp)
1197 {
1198 const char *src = value_start;
1199 char *dst = value;
1200 for (;;)
1201 {
1202 size_t len = endp - src;
1203 memcpy (dst, src, len);
1204 dst += len;
1205 src = endp;
1206 if (src + 1 < file_end && src[1] == '\n')
1207 src++; /* skip the '\r' */
1208 if (src >= value_end)
1209 break;
1210 endp = memchr (endp + 1, '\r', src - value_end);
1211 if (!endp)
1212 endp = value_end;
1213 }
1214 value_len = dst - value;
1215 }
1216 else
1217 memcpy (value, value_start, value_len);
1218 value [value_len] = '\0';
1219
1220 incdep_record_variable_in_set (curdep,
1221 var, var_len, value, value_len,
1222 0 /* don't duplicate */, o_file,
1223 0 /* defines are recursive but this is faster */,
1224 NULL /* global set */, f);
1225 }
1226
1227 /* file: deps
1228 OR
1229 variable [:]= value */
1230 else
1231 {
1232 const char *colonp;
1233 const char *equalp;
1234
1235 /* Look for a colon and an equal sign, optimize for colon.
1236 Only one file is support and the colon / equal must be on
1237 the same line. */
1238 colonp = memchr (cur, ':', file_end - cur);
1239#ifdef HAVE_DOS_PATHS
1240 while ( colonp
1241 && colonp + 1 < file_end
1242 && (colonp[1] == '/' || colonp[1] == '\\')
1243 && colonp > cur
1244 && isalpha ((unsigned char)colonp[-1])
1245 && ( colonp == cur + 1
1246 || strchr (" \t(", colonp[-2]) != 0))
1247 colonp = memchr (colonp + 1, ':', file_end - (colonp + 1));
1248#endif
1249 endp = NULL;
1250 if ( !colonp
1251 || (endp = memchr (cur, '\n', colonp - cur)))
1252 {
1253 colonp = NULL;
1254 equalp = memchr (cur, '=', (endp ? endp : file_end) - cur);
1255 if ( !equalp
1256 || (!endp && memchr (cur, '\n', equalp - cur)))
1257 {
1258 incdep_warn (curdep, line_no, "no colon.");
1259 break;
1260 }
1261 }
1262 else
1263 equalp = memchr (cur, '=', (colonp + 2 <= file_end
1264 ? colonp + 2 : file_end) - cur);
1265 if (equalp)
1266 {
1267 /* An assignment of some sort. */
1268 const char *var;
1269 unsigned var_len;
1270 const char *value_start;
1271 const char *value_end;
1272 char *value;
1273 unsigned value_len;
1274 unsigned multi_line = 0;
1275 enum variable_flavor flavor;
1276
1277 /* figure the flavor first. */
1278 flavor = f_recursive;
1279 if (equalp > cur)
1280 {
1281 if (equalp[-1] == ':')
1282 flavor = f_simple;
1283 else if (equalp[-1] == '?')
1284 flavor = f_conditional;
1285 else if (equalp[-1] == '+')
1286 flavor = f_append;
1287 else if (equalp[-1] == '>')
1288 flavor = f_prepend;
1289 }
1290
1291 /* extract the variable name. */
1292 endp = flavor == f_recursive ? equalp : equalp - 1;
1293 while (endp > cur && isblank ((unsigned char)endp[-1]))
1294 --endp;
1295 var_len = endp - cur;
1296 if (!var_len)
1297 {
1298 incdep_warn (curdep, line_no, "empty variable. (includedep)");
1299 break;
1300 }
1301 if ( memchr (cur, '$', var_len)
1302 || memchr (cur, ' ', var_len)
1303 || memchr (cur, '\t', var_len))
1304 {
1305 incdep_warn (curdep, line_no, "fancy variable name. (includedep)");
1306 break;
1307 }
1308 var = incdep_var_strcache (curdep, cur, var_len);
1309
1310 /* find the start of the value. */
1311 cur = equalp + 1;
1312 while (cur < file_end && isblank ((unsigned char)*cur))
1313 cur++;
1314 value_start = cur;
1315
1316 /* find the end of the value / line (this isn't 101% correct). */
1317 value_end = cur;
1318 while (cur < file_end)
1319 {
1320 endp = value_end = memchr (cur, '\n', file_end - cur);
1321 if (!value_end)
1322 value_end = file_end;
1323 if (value_end - 1 >= cur && value_end[-1] == '\r')
1324 --value_end;
1325 if (value_end - 1 < cur || value_end[-1] != '\\')
1326 {
1327 cur = endp ? endp + 1 : file_end;
1328 break;
1329 }
1330 --value_end;
1331 if (value_end - 1 >= cur && value_end[-1] == '\\')
1332 {
1333 incdep_warn (curdep, line_no, "fancy escaping! (includedep)");
1334 cur = NULL;
1335 break;
1336 }
1337 if (!endp)
1338 {
1339 cur = file_end;
1340 break;
1341 }
1342
1343 cur = endp + 1;
1344 ++multi_line;
1345 ++line_no;
1346 }
1347 if (!cur)
1348 break;
1349 ++line_no;
1350
1351 /* make a copy of the value, converting \r\n to \n, and define it. */
1352 value_len = value_end - value_start;
1353 value = incdep_xmalloc (curdep, value_len + 1);
1354 if (!multi_line)
1355 memcpy (value, value_start, value_len);
1356 else
1357 {
1358 /* unescape it */
1359 const char *src = value_start;
1360 char *dst = value;
1361 while (src < value_end)
1362 {
1363 const char *nextp;
1364
1365 endp = memchr (src, '\n', value_end - src);
1366 if (!endp)
1367 nextp = endp = value_end;
1368 else
1369 nextp = endp + 1;
1370 if (endp > src && endp[-1] == '\r')
1371 --endp;
1372 if (endp > src && endp[-1] == '\\')
1373 --endp;
1374
1375 if (src != value_start)
1376 *dst++ = ' ';
1377 memcpy (dst, src, endp - src);
1378 dst += endp - src;
1379 src = nextp;
1380 }
1381 value_len = dst - value;
1382 }
1383 value [value_len] = '\0';
1384
1385 /* do the definition */
1386 if (flavor == f_recursive
1387 || ( flavor == f_simple
1388 && !memchr (value, '$', value_len)))
1389 incdep_record_variable_in_set (curdep,
1390 var, var_len, value, value_len,
1391 0 /* don't duplicate */, o_file,
1392 flavor == f_recursive /* recursive */,
1393 NULL /* global set */, f);
1394 else
1395 incdep_record_variable_def (curdep,
1396 f, var, var_len, value, value_len,
1397 o_file, flavor, 0 /* not target var */);
1398 }
1399 else
1400 {
1401 /* file: dependencies */
1402
1403 const char *filename;
1404 struct dep *deps = 0;
1405 struct dep **nextdep = &deps;
1406 struct dep *dep;
1407
1408 /* extract the filename, ASSUME a single one. */
1409 endp = colonp;
1410 while (endp > cur && isblank ((unsigned char)endp[-1]))
1411 --endp;
1412 if (cur == endp)
1413 {
1414 incdep_warn (curdep, line_no, "empty filename.");
1415 break;
1416 }
1417 if ( memchr (cur, '$', endp - cur)
1418 || memchr (cur, ' ', endp - cur)
1419 || memchr (cur, '\t', endp - cur))
1420 {
1421 incdep_warn (curdep, line_no, "multiple / fancy file name. (includedep)");
1422 break;
1423 }
1424 filename = incdep_dep_strcache (curdep, cur, endp - cur);
1425
1426 /* parse any dependencies. */
1427 cur = colonp + 1;
1428 while (cur < file_end)
1429 {
1430 /* skip blanks and count lines. */
1431 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n')
1432 ++cur;
1433 if (cur >= file_end)
1434 break;
1435 if (*cur == '\n')
1436 {
1437 cur++;
1438 line_no++;
1439 break;
1440 }
1441
1442 /* continuation + eol? */
1443 if (*cur == '\\')
1444 {
1445 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2
1446 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3
1447 : (file_end - cur == 1) ? 1 : 0;
1448 if (eol_len)
1449 {
1450 cur += eol_len;
1451 line_no++;
1452 continue;
1453 }
1454 }
1455
1456 /* find the end of the filename */
1457 endp = cur;
1458 while (endp < file_end && !isspace ((unsigned char)*endp))
1459 ++endp;
1460
1461 /* add it to the list. */
1462 *nextdep = dep = incdep_alloc_dep (curdep);
1463 dep->name = incdep_dep_strcache (curdep, cur, endp - cur);
1464 dep->includedep = 1;
1465 nextdep = &dep->next;
1466
1467 cur = endp;
1468 }
1469
1470 /* enter the file with its dependencies. */
1471 incdep_record_files (curdep,
1472 filename, NULL, NULL, deps, 0, NULL, 0, 0, f);
1473 }
1474 }
1475 }
1476
1477 /* free the file data */
1478 incdep_xfree (curdep, curdep->file_base);
1479 curdep->file_base = curdep->file_end = NULL;
1480}
1481
1482/* Flushes the incdep todo and done lists. */
1483static void
1484incdep_flush_it (struct floc *f)
1485{
1486 incdep_lock ();
1487 for (;;)
1488 {
1489 struct incdep *cur = incdep_head_done;
1490
1491 /* if the done list is empty, grab a todo list entry. */
1492 if (!cur && incdep_head_todo)
1493 {
1494 cur = incdep_head_todo;
1495 if (cur->next)
1496 incdep_head_todo = cur->next;
1497 else
1498 incdep_head_todo = incdep_tail_todo = NULL;
1499 incdep_unlock ();
1500
1501 incdep_read_file (cur, f);
1502 eval_include_dep_file (cur, f);
1503 incdep_freeit (cur);
1504
1505 incdep_lock ();
1506 continue;
1507 }
1508
1509 /* if the todo list and done list are empty we're either done
1510 or will have to wait for the thread(s) to finish. */
1511 if (!cur && !incdep_num_reading)
1512 break; /* done */
1513 if (!cur)
1514 {
1515 while (!incdep_head_done)
1516 incdep_wait_done ();
1517 cur = incdep_head_done;
1518 }
1519
1520 /* we grab the entire done list and work thru it. */
1521 incdep_head_done = incdep_tail_done = NULL;
1522 incdep_unlock ();
1523
1524 while (cur)
1525 {
1526 struct incdep *next = cur->next;
1527#ifdef PARSE_IN_WORKER
1528 incdep_flush_recorded_instructions (cur);
1529#else
1530 eval_include_dep_file (cur, f);
1531#endif
1532 incdep_freeit (cur);
1533 cur = next;
1534 }
1535
1536 incdep_lock ();
1537 } /* outer loop */
1538 incdep_unlock ();
1539}
1540
1541
1542/* splits up a list of file names and feeds it to eval_include_dep_file,
1543 employing threads to try speed up the file reading. */
1544void
1545eval_include_dep (const char *names, struct floc *f, enum incdep_op op)
1546{
1547 struct incdep *head = 0;
1548 struct incdep *tail = 0;
1549 struct incdep *cur;
1550 const char *names_iterator = names;
1551 const char *name;
1552 unsigned int name_len;
1553
1554 /* loop through NAMES, creating a todo list out of them. */
1555
1556 while ((name = find_next_token (&names_iterator, &name_len)) != 0)
1557 {
1558 cur = xmalloc (sizeof (*cur) + name_len); /* not incdep_xmalloc here */
1559 cur->file_base = cur->file_end = NULL;
1560 memcpy (cur->name, name, name_len);
1561 cur->name[name_len] = '\0';
1562 cur->worker_tid = -1;
1563#ifdef PARSE_IN_WORKER
1564 cur->err_line_no = 0;
1565 cur->err_msg = NULL;
1566 cur->recorded_variables_in_set_head = NULL;
1567 cur->recorded_variables_in_set_tail = NULL;
1568 cur->recorded_variable_defs_head = NULL;
1569 cur->recorded_variable_defs_tail = NULL;
1570 cur->recorded_files_head = NULL;
1571 cur->recorded_files_tail = NULL;
1572#endif
1573
1574 cur->next = NULL;
1575 if (tail)
1576 tail->next = cur;
1577 else
1578 head = cur;
1579 tail = cur;
1580 }
1581
1582#ifdef ELECTRIC_HEAP
1583 if (1)
1584#else
1585 if (op == incdep_read_it)
1586#endif
1587 {
1588 /* work our way thru the files directly */
1589
1590 cur = head;
1591 while (cur)
1592 {
1593 struct incdep *next = cur->next;
1594 incdep_read_file (cur, f);
1595 eval_include_dep_file (cur, f);
1596 incdep_freeit (cur);
1597 cur = next;
1598 }
1599 }
1600 else
1601 {
1602 /* initialize the worker threads and related stuff the first time around. */
1603
1604 if (!incdep_initialized)
1605 incdep_init (f);
1606
1607 /* queue the files and notify the worker threads. */
1608
1609 incdep_lock ();
1610
1611 if (incdep_tail_todo)
1612 incdep_tail_todo->next = head;
1613 else
1614 incdep_head_todo = head;
1615 incdep_tail_todo = tail;
1616
1617 incdep_signal_todo ();
1618 incdep_unlock ();
1619
1620 /* flush the todo queue if we're requested to do so. */
1621
1622 if (op == incdep_flush)
1623 incdep_flush_it (f);
1624 }
1625}
1626
1627#endif /* CONFIG_WITH_INCLUDEDEP */
1628
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette