VirtualBox

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

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

strcache2: hash1 -> hash; -hash2.

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

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