VirtualBox

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

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

incdep: The variable names should live in a different string cache.

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