VirtualBox

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

最後變更 在這個檔案從2024是 2019,由 bird 提交於 16 年 前

GPLv2 -> GPLv3. See Ticket #44 for clarifications. Fixes #44.

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

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