1 #ifdef CONFIG_WITH_INCLUDEDEP
4 * incdep - Simple dependency files.
8 * Copyright (c) 2007-2008 knut st. osmundsen <bird-src-spam@anduin.net>
10 * This file is part of kBuild.
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.
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.
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/>
27 /*******************************************************************************
29 *******************************************************************************/
37 #if !defined(WINDOWS32) && !defined(__OS2__)
52 #include "strcache2.h"
57 # include <sys/file.h>
64 # define PARSE_IN_WORKER
69 # include <sys/fmutex.h>
77 # include <malloc/malloc.h>
78 # define PARSE_IN_WORKER
81 #if defined(__gnu_linux__) || defined(__linux__)
82 # define PARSE_IN_WORKER
86 /*******************************************************************************
87 * Structures and Typedefs *
88 *******************************************************************************/
89 struct incdep_variable_in_set
91 struct incdep_variable_in_set
*next
;
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
;
99 struct variable_set
*set
;
100 const struct floc
*flocp
; /* NILF */
103 struct incdep_variable_def
105 struct incdep_variable_def
*next
;
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
;
116 struct incdep_recorded_files
118 struct incdep_recorded_files
*next
;
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 */
133 /* per dep file structure. */
141 #ifdef PARSE_IN_WORKER
142 unsigned int err_line_no
;
145 struct incdep_variable_in_set
*recorded_variables_in_set_head
;
146 struct incdep_variable_in_set
*recorded_variables_in_set_tail
;
148 struct incdep_variable_def
*recorded_variable_defs_head
;
149 struct incdep_variable_def
*recorded_variable_defs_tail
;
151 struct incdep_recorded_files
*recorded_files_head
;
152 struct incdep_recorded_files
*recorded_files_tail
;
159 /*******************************************************************************
161 *******************************************************************************/
163 /* mutex protecting the globals and an associated condition/event. */
165 static pthread_mutex_t incdep_mtx
;
166 static pthread_cond_t incdep_cond_todo
;
167 static pthread_cond_t incdep_cond_done
;
169 #elif defined (WINDOWS32)
170 static CRITICAL_SECTION incdep_mtx
;
171 static HANDLE incdep_hev_todo
;
172 static HANDLE incdep_hev_done
;
173 static int volatile incdep_hev_todo_waiters
;
174 static int volatile incdep_hev_done_waiters
;
176 #elif defined (__OS2__)
177 static _fmutex incdep_mtx
;
178 static HEV incdep_hev_todo
;
179 static HEV incdep_hev_done
;
180 static int volatile incdep_hev_todo_waiters
;
181 static int volatile incdep_hev_done_waiters
;
184 /* flag indicating whether the threads, lock and event/condvars has
185 been initialized or not. */
186 static int incdep_initialized
;
188 /* the list of files that needs reading. */
189 static struct incdep
* volatile incdep_head_todo
;
190 static struct incdep
* volatile incdep_tail_todo
;
192 /* the number of files that are currently being read. */
193 static int volatile incdep_num_reading
;
195 /* the list of files that have been read. */
196 static struct incdep
* volatile incdep_head_done
;
197 static struct incdep
* volatile incdep_tail_done
;
200 /* The handles to the worker threads. */
202 # define INCDEP_MAX_THREADS 1
203 static pthread_t incdep_threads
[INCDEP_MAX_THREADS
];
205 #elif defined (WINDOWS32)
206 # define INCDEP_MAX_THREADS 2
207 static HANDLE incdep_threads
[INCDEP_MAX_THREADS
];
209 #elif defined (__OS2__)
210 # define INCDEP_MAX_THREADS 2
211 static TID incdep_threads
[INCDEP_MAX_THREADS
];
214 static struct alloccache incdep_rec_caches
[INCDEP_MAX_THREADS
];
215 static struct alloccache incdep_dep_caches
[INCDEP_MAX_THREADS
];
216 static struct strcache2 incdep_dep_strcaches
[INCDEP_MAX_THREADS
];
217 static struct strcache2 incdep_var_strcaches
[INCDEP_MAX_THREADS
];
218 static unsigned incdep_num_threads
;
220 /* flag indicating whether the worker threads should terminate or not. */
221 static int volatile incdep_terminate
;
224 /* malloc zone for the incdep threads. */
225 static malloc_zone_t
*incdep_zone
;
229 /*******************************************************************************
230 * Internal Functions *
231 *******************************************************************************/
232 static void incdep_flush_it (struct floc
*);
233 static void eval_include_dep_file (struct incdep
*, struct floc
*);
237 For working around multithreaded performance problems found on Darwin,
238 Linux (glibc), and possibly other systems. */
240 incdep_xmalloc (struct incdep
*cur
, size_t size
)
245 if (cur
&& cur
->worker_tid
!= -1)
247 ptr
= malloc_zone_malloc (incdep_zone
, size
);
249 fatal (NILF
, _("virtual memory exhausted"));
252 ptr
= xmalloc (size
);
254 ptr
= xmalloc (size
);
262 /* memset(malloc(sz),'\0',sz) wrapper. */
264 incdep_xcalloc (struct incdep
*cur
, size_t size
)
269 if (cur
&& cur
->worker_tid
!= -1)
270 ptr
= malloc_zone_calloc (incdep_zone
, size
, 1);
272 ptr
= calloc (size
, 1);
274 ptr
= calloc (size
, 1);
277 fatal (NILF
, _("virtual memory exhausted"));
286 incdep_xfree (struct incdep
*cur
, void *ptr
)
288 /* free() *must* work for the allocation hacks above because
289 of free_dep_chain. */
294 /* alloc a dep structure. These are allocated in bunches to save time. */
296 incdep_alloc_dep (struct incdep
*cur
)
298 struct alloccache
*cache
;
299 if (cur
->worker_tid
!= -1)
300 cache
= &incdep_dep_caches
[cur
->worker_tid
];
303 return alloccache_calloc (cache
);
306 /* allocate a record. */
308 incdep_alloc_rec (struct incdep
*cur
)
310 return alloccache_alloc (&incdep_rec_caches
[cur
->worker_tid
]);
315 incdep_free_rec (struct incdep
*cur
, void *rec
)
317 /*alloccache_free (&incdep_rec_caches[cur->worker_tid], rec); - doesn't work of course. */
323 incdep_cache_allocator (void *thrd
, unsigned int size
)
327 return malloc_zone_malloc (incdep_zone
, size
);
329 return xmalloc (size
);
335 incdep_cache_deallocator (void *thrd
, void *ptr
, unsigned int size
)
342 /* acquires the lock */
346 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
347 pthread_mutex_lock (&incdep_mtx
);
348 #elif defined (WINDOWS32)
349 EnterCriticalSection (&incdep_mtx
);
350 #elif defined (__OS2__)
351 _fmutex_request (&incdep_mtx
, 0);
355 /* releases the lock */
359 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
360 pthread_mutex_unlock (&incdep_mtx
);
361 #elif defined(WINDOWS32)
362 LeaveCriticalSection (&incdep_mtx
);
363 #elif defined(__OS2__)
364 _fmutex_release (&incdep_mtx
);
368 /* signals the main thread that there is stuff todo. caller owns the lock. */
370 incdep_signal_done (void)
372 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
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
);
383 /* waits for a reader to finish reading. caller owns the lock. */
385 incdep_wait_done (void)
387 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
388 pthread_cond_wait (&incdep_cond_done
, &incdep_mtx
);
390 #elif defined (WINDOWS32)
391 ResetEvent (incdep_hev_done
);
392 incdep_hev_done_waiters
++;
394 WaitForSingleObject (incdep_hev_done
, INFINITE
);
396 incdep_hev_done_waiters
--;
398 #elif defined (__OS2__)
400 DosResetEventSem (incdep_hev_done
, &ulIgnore
);
401 incdep_hev_done_waiters
++;
403 DosWaitEventSem (incdep_hev_done
, SEM_INDEFINITE_WAIT
);
405 incdep_hev_done_waiters
--;
409 /* signals the worker threads. caller owns the lock. */
411 incdep_signal_todo (void)
413 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
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
);
424 /* waits for stuff to arrive in the todo list. caller owns the lock. */
426 incdep_wait_todo (void)
428 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
429 pthread_cond_wait (&incdep_cond_todo
, &incdep_mtx
);
431 #elif defined (WINDOWS32)
432 ResetEvent (incdep_hev_todo
);
433 incdep_hev_todo_waiters
++;
435 WaitForSingleObject (incdep_hev_todo
, INFINITE
);
437 incdep_hev_todo_waiters
--;
439 #elif defined (__OS2__)
441 DosResetEventSem (incdep_hev_todo
, &ulIgnore
);
442 incdep_hev_todo_waiters
++;
444 DosWaitEventSem (incdep_hev_todo
, SEM_INDEFINITE_WAIT
);
446 incdep_hev_todo_waiters
--;
450 /* Reads a dep file into memory. */
452 incdep_read_file (struct incdep
*cur
, struct floc
*f
)
459 fd
= open (cur
->name
, O_RDONLY
| O_BINARY
, 0);
461 fd
= open (cur
->name
, O_RDONLY
, 0);
465 /* ignore non-existing dependency files. */
467 if (err
== ENOENT
|| stat (cur
->name
, &st
) != 0)
469 error (f
, "%s: %s", cur
->name
, strerror (err
));
472 if (!fstat (fd
, &st
))
474 cur
->file_base
= incdep_xmalloc (cur
, st
.st_size
+ 1);
475 if (read (fd
, cur
->file_base
, st
.st_size
) == st
.st_size
)
478 cur
->file_end
= cur
->file_base
+ st
.st_size
;
479 cur
->file_base
[st
.st_size
] = '\0';
485 error (f
, "%s: read: %s", cur
->name
, strerror (errno
));
486 incdep_xfree (cur
, cur
->file_base
);
489 error (f
, "%s: fstat: %s", cur
->name
, strerror (errno
));
492 cur
->file_base
= cur
->file_end
= NULL
;
496 /* Free the incdep structure. */
498 incdep_freeit (struct incdep
*cur
)
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
);
506 incdep_xfree (cur
, cur
->file_base
);
511 /* A worker thread. */
513 incdep_worker (int thrd
)
517 while (!incdep_terminate
)
519 /* get job from the todo list. */
521 struct incdep
*cur
= incdep_head_todo
;
528 incdep_head_todo
= cur
->next
;
530 incdep_head_todo
= incdep_tail_todo
= NULL
;
531 incdep_num_reading
++;
536 cur
->worker_tid
= thrd
;
538 incdep_read_file (cur
, NILF
);
539 #ifdef PARSE_IN_WORKER
540 eval_include_dep_file (cur
, NILF
);
543 cur
->worker_tid
= -1;
546 /* insert finished job into the done list. */
548 incdep_num_reading
--;
550 if (incdep_tail_done
)
551 incdep_tail_done
->next
= cur
;
553 incdep_head_done
= cur
;
554 incdep_tail_done
= cur
;
556 incdep_signal_done ();
562 /* Thread library specific thread functions wrapping incdep_wroker. */
565 incdep_worker_pthread (void *thrd
)
567 incdep_worker ((size_t)thrd
);
571 #elif defined (WINDOWS32)
572 static unsigned __stdcall
573 incdep_worker_windows (void *thrd
)
575 incdep_worker ((size_t)thrd
);
579 #elif defined (__OS2__)
581 incdep_worker_os2 (void *thrd
)
583 incdep_worker ((size_t)thrd
);
587 /* Checks if threads are enabled or not.
589 This is a special hack so that is possible to disable the threads when in a
590 debian fakeroot environment. Thus, in addition to the KMK_THREADS_DISABLED
591 and KMK_THREADS_ENABLED environment variable check we also check for signs
594 incdep_are_threads_enabled (void)
596 #if defined (CONFIG_WITHOUT_THREADS)
600 if (getenv("KMK_THREADS_DISABLED"))
602 if (getenv("KMK_THREADS_ENABLED"))
604 #if defined(__gnu_linux__) || defined(__linux__)
605 if (getenv("FAKEROOTKEY"))
607 if (getenv("FAKEROOTUID"))
609 if (getenv("FAKEROOTGID"))
611 if (getenv("FAKEROOTEUID"))
613 if (getenv("FAKEROOTEGID"))
615 if (getenv("FAKEROOTSUID"))
617 if (getenv("FAKEROOTSGID"))
619 if (getenv("FAKEROOTFUID"))
621 if (getenv("FAKEROOTFGID"))
623 if (getenv("FAKEROOTDONTTRYCHOWN"))
625 if (getenv("FAKEROOT_FD_BASE"))
627 if (getenv("FAKEROOT_DB_SEARCH_PATHS"))
629 #endif /* GNU/Linux */
633 /* Creates the the worker threads. */
635 incdep_init (struct floc
*f
)
638 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
642 #elif defined (WINDOWS32)
646 #elif defined (__OS2__)
655 incdep_zone
= malloc_create_zone (0, 0);
657 incdep_zone
= malloc_default_zone ();
661 /* create the mutex and two condition variables / event objects. */
663 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
664 rc
= pthread_mutex_init (&incdep_mtx
, NULL
);
666 fatal (f
, _("pthread_mutex_init failed: err=%d"), rc
);
667 rc
= pthread_cond_init (&incdep_cond_todo
, NULL
);
669 fatal (f
, _("pthread_cond_init failed: err=%d"), rc
);
670 rc
= pthread_cond_init (&incdep_cond_done
, NULL
);
672 fatal (f
, _("pthread_cond_init failed: err=%d"), rc
);
674 #elif defined (WINDOWS32)
675 InitializeCriticalSection (&incdep_mtx
);
676 incdep_hev_todo
= CreateEvent (NULL
, TRUE
/*bManualReset*/, FALSE
/*bInitialState*/, NULL
);
677 if (!incdep_hev_todo
)
678 fatal (f
, _("CreateEvent failed: err=%d"), GetLastError());
679 incdep_hev_done
= CreateEvent (NULL
, TRUE
/*bManualReset*/, FALSE
/*bInitialState*/, NULL
);
680 if (!incdep_hev_done
)
681 fatal (f
, _("CreateEvent failed: err=%d"), GetLastError());
682 incdep_hev_todo_waiters
= 0;
683 incdep_hev_done_waiters
= 0;
685 #elif defined (__OS2__)
686 _fmutex_create (&incdep_mtx
, 0);
687 rc
= DosCreateEventSem (NULL
, &incdep_hev_todo
, 0, FALSE
);
689 fatal (f
, _("DosCreateEventSem failed: rc=%d"), rc
);
690 rc
= DosCreateEventSem (NULL
, &incdep_hev_done
, 0, FALSE
);
692 fatal (f
, _("DosCreateEventSem failed: rc=%d"), rc
);
693 incdep_hev_todo_waiters
= 0;
694 incdep_hev_done_waiters
= 0;
697 /* create the worker threads and associated per thread data. */
699 incdep_terminate
= 0;
700 if (incdep_are_threads_enabled())
702 incdep_num_threads
= sizeof (incdep_threads
) / sizeof (incdep_threads
[0]);
703 if (incdep_num_threads
+ 1 > job_slots
)
704 incdep_num_threads
= job_slots
<= 1 ? 1 : job_slots
- 1;
705 for (i
= 0; i
< incdep_num_threads
; i
++)
708 unsigned rec_size
= sizeof (struct incdep_variable_in_set
);
709 if (rec_size
< sizeof (struct incdep_variable_def
))
710 rec_size
= sizeof (struct incdep_variable_def
);
711 if (rec_size
< sizeof (struct incdep_recorded_files
))
712 rec_size
= sizeof (struct incdep_recorded_files
);
713 alloccache_init (&incdep_rec_caches
[i
], rec_size
, "incdep rec",
714 incdep_cache_allocator
, (void *)(size_t)i
);
715 alloccache_init (&incdep_dep_caches
[i
], sizeof(struct dep
), "incdep dep",
716 incdep_cache_allocator
, (void *)(size_t)i
);
717 strcache2_init (&incdep_dep_strcaches
[i
],
718 "incdep dep", /* name */
719 65536, /* hash size */
720 0, /* default segment size*/
721 #ifdef HAVE_CASE_INSENSITIVE_FS
722 1, /* case insensitive */
724 0, /* case insensitive */
726 0); /* thread safe */
728 strcache2_init (&incdep_var_strcaches
[i
],
729 "incdep var", /* name */
730 32768, /* hash size */
731 0, /* default segment size*/
732 0, /* case insensitive */
733 0); /* thread safe */
735 /* create the thread. */
736 #if defined (HAVE_PTHREAD) && !defined (CONFIG_WITHOUT_THREADS)
737 rc
= pthread_attr_init (&attr
);
739 fatal (f
, _("pthread_attr_init failed: err=%d"), rc
);
740 /*rc = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); */
741 rc
= pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
743 fatal (f
, _("pthread_attr_setdetachstate failed: err=%d"), rc
);
744 rc
= pthread_create(&incdep_threads
[i
], &attr
,
745 incdep_worker_pthread
, (void *)(size_t)i
);
747 fatal (f
, _("pthread_mutex_init failed: err=%d"), rc
);
748 pthread_attr_destroy (&attr
);
750 #elif defined (WINDOWS32)
752 hThread
= _beginthreadex (NULL
, 128*1024, incdep_worker_windows
,
754 if (hThread
== 0 || hThread
== ~(uintptr_t)0)
755 fatal (f
, _("_beginthreadex failed: err=%d"), errno
);
756 incdep_threads
[i
] = (HANDLE
)hThread
;
758 #elif defined (__OS2__)
759 tid
= _beginthread (incdep_worker_os2
, NULL
, 128*1024, (void *)i
);
761 fatal (f
, _("_beginthread failed: err=%d"), errno
);
762 incdep_threads
[i
] = tid
;
767 incdep_num_threads
= 0;
769 incdep_initialized
= 1;
772 /* Flushes outstanding work and terminates the worker threads.
773 This is called from snap_deps(). */
775 incdep_flush_and_term (void)
779 if (!incdep_initialized
)
782 /* flush any out standing work */
784 incdep_flush_it (NILF
);
786 /* tell the threads to terminate */
789 incdep_terminate
= 1;
790 incdep_signal_todo ();
793 /* wait for the threads to quit */
795 for (i
= 0; i
< incdep_num_threads
; i
++)
799 /* terminate or join up the allocation caches. */
800 alloccache_term (&incdep_rec_caches
[i
], incdep_cache_deallocator
, (void *)(size_t)i
);
801 alloccache_join (&dep_cache
, &incdep_dep_caches
[i
]);
802 strcache2_term (&incdep_dep_strcaches
[i
]);
803 strcache2_term (&incdep_var_strcaches
[i
]);
805 incdep_num_threads
= 0;
807 /* destroy the lock and condition variables / event objects. */
811 incdep_initialized
= 0;
814 #ifdef PARSE_IN_WORKER
815 /* Flushes a strcache entry returning the actual string cache entry.
816 The input is freed! */
818 incdep_flush_strcache_entry (struct strcache2_entry
*entry
)
821 entry
->user
= (void *) strcache2_add_hashed_file (&file_strcache
,
822 (const char *)(entry
+ 1),
823 entry
->length
, entry
->hash
);
824 return (const char *)entry
->user
;
827 /* Flushes the recorded instructions. */
829 incdep_flush_recorded_instructions (struct incdep
*cur
)
831 struct incdep_variable_in_set
*rec_vis
;
832 struct incdep_variable_def
*rec_vd
;
833 struct incdep_recorded_files
*rec_f
;
835 /* define_variable_in_set */
837 rec_vis
= cur
->recorded_variables_in_set_head
;
838 cur
->recorded_variables_in_set_head
= cur
->recorded_variables_in_set_tail
= NULL
;
842 void *free_me
= rec_vis
;
843 unsigned int name_length
= rec_vis
->name_entry
->length
;
844 define_variable_in_set (incdep_flush_strcache_entry (rec_vis
->name_entry
),
847 rec_vis
->value_length
,
848 rec_vis
->duplicate_value
,
853 rec_vis
= rec_vis
->next
;
854 incdep_free_rec (cur
, free_me
);
858 /* do_variable_definition */
860 rec_vd
= cur
->recorded_variable_defs_head
;
861 cur
->recorded_variable_defs_head
= cur
->recorded_variable_defs_tail
= NULL
;
865 void *free_me
= rec_vd
;
866 do_variable_definition_2 (rec_vd
->flocp
,
867 incdep_flush_strcache_entry (rec_vd
->name_entry
),
869 rec_vd
->value_length
,
875 rec_vd
= rec_vd
->next
;
876 incdep_free_rec (cur
, free_me
);
882 rec_f
= cur
->recorded_files_head
;
883 cur
->recorded_files_head
= cur
->recorded_files_tail
= NULL
;
887 void *free_me
= rec_f
;
889 struct nameseq
*filenames
;
891 for (dep
= rec_f
->deps
; dep
; dep
= dep
->next
)
892 dep
->name
= incdep_flush_strcache_entry ((struct strcache2_entry
*)dep
->name
);
894 filenames
= (struct nameseq
*) alloccache_alloc (&nameseq_cache
);
896 filenames
->name
= incdep_flush_strcache_entry (rec_f
->filename_entry
);
898 record_files (filenames
,
900 rec_f
->pattern_percent
,
909 incdep_free_rec (cur
, free_me
);
913 #endif /* PARSE_IN_WORKER */
915 /* Record / issue a warning about a misformed dep file. */
917 incdep_warn (struct incdep
*cur
, unsigned int line_no
, const char *msg
)
919 if (cur
->worker_tid
== -1)
920 error (NILF
, "%s(%d): %s", cur
->name
, line_no
, msg
);
921 #ifdef PARSE_IN_WORKER
924 cur
->err_line_no
= line_no
;
930 /* Dependency or file strcache allocation / recording. */
932 incdep_dep_strcache (struct incdep
*cur
, const char *str
, int len
)
935 if (cur
->worker_tid
== -1)
937 /* Make sure the string is terminated before we hand it to
938 strcache_add_len so it does have to make a temporary copy
939 of it on the stack. */
941 ((char *)str
)[len
] = '\0';
942 ret
= strcache_add_len (str
, len
);
943 ((char *)str
)[len
] = ch
;
947 /* Add it out the strcache of the thread. */
948 ret
= strcache2_add (&incdep_dep_strcaches
[cur
->worker_tid
], str
, len
);
949 ret
= (const char *)strcache2_get_entry(&incdep_dep_strcaches
[cur
->worker_tid
], ret
);
954 /* Variable name allocation / recording. */
956 incdep_var_strcache (struct incdep
*cur
, const char *str
, int len
)
959 if (cur
->worker_tid
== -1)
961 /* XXX: we're leaking this memory now! This will be fixed later. */
962 ret
= xmalloc (len
+ 1);
963 memcpy ((char *)ret
, str
, len
);
964 ((char *)ret
)[len
] = '\0';
968 /* Add it out the strcache of the thread. */
969 ret
= strcache2_add (&incdep_var_strcaches
[cur
->worker_tid
], str
, len
);
970 ret
= (const char *)strcache2_get_entry(&incdep_var_strcaches
[cur
->worker_tid
], ret
);
975 /* Record / perform a variable definition in a set.
976 The NAME is in the string cache.
977 The VALUE is on the heap.
978 The DUPLICATE_VALUE is always 0. */
980 incdep_record_variable_in_set (struct incdep
*cur
,
981 const char *name
, unsigned int name_length
,
983 unsigned int value_length
,
985 enum variable_origin origin
,
987 struct variable_set
*set
,
988 const struct floc
*flocp
)
990 assert (!duplicate_value
);
991 if (cur
->worker_tid
== -1)
992 define_variable_in_set (name
, name_length
, value
, value_length
,
993 duplicate_value
, origin
, recursive
, set
, flocp
);
994 #ifdef PARSE_IN_WORKER
997 struct incdep_variable_in_set
*rec
=
998 (struct incdep_variable_in_set
*)incdep_alloc_rec (cur
);
999 rec
->name_entry
= (struct strcache2_entry
*)name
;
1001 rec
->value_length
= value_length
;
1002 rec
->duplicate_value
= duplicate_value
;
1003 rec
->origin
= origin
;
1004 rec
->recursive
= recursive
;
1009 if (cur
->recorded_variables_in_set_tail
)
1010 cur
->recorded_variables_in_set_tail
->next
= rec
;
1012 cur
->recorded_variables_in_set_head
= rec
;
1013 cur
->recorded_variables_in_set_tail
= rec
;
1018 /* Record / perform a variable definition. The VALUE should be disposed of. */
1020 incdep_record_variable_def (struct incdep
*cur
,
1021 const struct floc
*flocp
,
1023 unsigned int name_length
,
1025 unsigned int value_length
,
1026 enum variable_origin origin
,
1027 enum variable_flavor flavor
,
1030 if (cur
->worker_tid
== -1)
1031 do_variable_definition_2 (flocp
, name
, value
, value_length
, 0, value
,
1032 origin
, flavor
, target_var
);
1033 #ifdef PARSE_IN_WORKER
1036 struct incdep_variable_def
*rec
=
1037 (struct incdep_variable_def
*)incdep_alloc_rec (cur
);
1039 rec
->name_entry
= (struct strcache2_entry
*)name
;
1041 rec
->value_length
= value_length
;
1042 rec
->origin
= origin
;
1043 rec
->flavor
= flavor
;
1044 rec
->target_var
= target_var
;
1047 if (cur
->recorded_variable_defs_tail
)
1048 cur
->recorded_variable_defs_tail
->next
= rec
;
1050 cur
->recorded_variable_defs_head
= rec
;
1051 cur
->recorded_variable_defs_tail
= rec
;
1060 incdep_record_files (struct incdep
*cur
,
1061 const char *filename
, const char *pattern
,
1062 const char *pattern_percent
, struct dep
*deps
,
1063 unsigned int cmds_started
, char *commands
,
1064 unsigned int commands_idx
, int two_colon
,
1065 const struct floc
*flocp
)
1067 if (cur
->worker_tid
== -1)
1069 struct nameseq
*filenames
= (struct nameseq
*) alloccache_alloc (&nameseq_cache
);
1070 filenames
->next
= 0;
1071 filenames
->name
= filename
;
1072 record_files (filenames
, pattern
, pattern_percent
, deps
, cmds_started
,
1073 commands
, commands_idx
, two_colon
, flocp
);
1075 #ifdef PARSE_IN_WORKER
1078 struct incdep_recorded_files
*rec
=
1079 (struct incdep_recorded_files
*) incdep_alloc_rec (cur
);
1081 rec
->filename_entry
= (struct strcache2_entry
*)filename
;
1082 rec
->pattern
= pattern
;
1083 rec
->pattern_percent
= pattern_percent
;
1085 rec
->cmds_started
= cmds_started
;
1086 rec
->commands
= commands
;
1087 rec
->commands_idx
= commands_idx
;
1088 rec
->two_colon
= two_colon
;
1092 if (cur
->recorded_files_tail
)
1093 cur
->recorded_files_tail
->next
= rec
;
1095 cur
->recorded_files_head
= rec
;
1096 cur
->recorded_files_tail
= rec
;
1102 /* no nonsense dependency file including.
1104 Because nobody wants bogus dependency files to break their incremental
1105 builds with hard to comprehend error messages, this function does not
1106 use the normal eval routine but does all the parsing itself. This isn't,
1107 as much work as it sounds, because the necessary feature set is very
1110 eval_include_dep_file groks:
1115 var [|:|?|>]= value [\]
1122 eval_include_dep_file (struct incdep
*curdep
, struct floc
*f
)
1124 unsigned line_no
= 1;
1125 const char *file_end
= curdep
->file_end
;
1126 const char *cur
= curdep
->file_base
;
1129 /* if no file data, just return immediately. */
1133 /* now parse the file. */
1134 while (cur
< file_end
)
1136 /* skip empty lines */
1137 while (cur
< file_end
&& isspace ((unsigned char)*cur
) && *cur
!= '\n')
1139 if (cur
>= file_end
)
1143 cur
= memchr (cur
, '\n', file_end
- cur
);
1149 unsigned eol_len
= (file_end
- cur
> 1 && cur
[1] == '\n') ? 2
1150 : (file_end
- cur
> 2 && cur
[1] == '\r' && cur
[2] == '\n') ? 3
1151 : (file_end
- cur
== 1) ? 1 : 0;
1169 if (strneq (cur
, "define ", 7))
1173 const char *value_start
;
1174 const char *value_end
;
1177 int found_endef
= 0;
1179 /* extract the variable name. */
1181 while (isblank ((unsigned char)*cur
))
1183 value_start
= endp
= memchr (cur
, '\n', file_end
- cur
);
1186 while (endp
> cur
&& isspace ((unsigned char)endp
[-1]))
1188 var_len
= endp
- cur
;
1191 incdep_warn (curdep
, line_no
, "bogus define statement.");
1194 var
= incdep_var_strcache (curdep
, cur
, var_len
);
1196 /* find the end of the variable. */
1197 cur
= value_end
= value_start
= value_start
+ 1;
1199 while (cur
< file_end
)
1201 /* check for endef, don't bother with skipping leading spaces. */
1202 if ( file_end
- cur
>= 5
1203 && strneq (cur
, "endef", 5))
1206 while (endp
< file_end
&& isspace ((unsigned char)*endp
) && *endp
!= '\n')
1208 if (endp
>= file_end
|| *endp
== '\n')
1211 cur
= endp
>= file_end
? file_end
: endp
+ 1;
1216 /* skip a line ahead. */
1217 cur
= value_end
= memchr (cur
, '\n', file_end
- cur
);
1221 cur
= value_end
= file_end
;
1227 incdep_warn (curdep
, line_no
, "missing endef, dropping the rest of the file.");
1230 value_len
= value_end
- value_start
;
1231 if (memchr (value_start
, '\0', value_len
))
1233 incdep_warn (curdep
, line_no
, "'\\0' in define, dropping the rest of the file.");
1237 /* make a copy of the value, converting \r\n to \n, and define it. */
1238 value
= incdep_xmalloc (curdep
, value_len
+ 1);
1239 endp
= memchr (value_start
, '\r', value_len
);
1242 const char *src
= value_start
;
1246 size_t len
= endp
- src
;
1247 memcpy (dst
, src
, len
);
1250 if (src
+ 1 < file_end
&& src
[1] == '\n')
1251 src
++; /* skip the '\r' */
1252 if (src
>= value_end
)
1254 endp
= memchr (endp
+ 1, '\r', src
- value_end
);
1258 value_len
= dst
- value
;
1261 memcpy (value
, value_start
, value_len
);
1262 value
[value_len
] = '\0';
1264 incdep_record_variable_in_set (curdep
,
1265 var
, var_len
, value
, value_len
,
1266 0 /* don't duplicate */, o_file
,
1267 0 /* defines are recursive but this is faster */,
1268 NULL
/* global set */, f
);
1273 variable [:]= value */
1279 /* Look for a colon and an equal sign, optimize for colon.
1280 Only one file is support and the colon / equal must be on
1282 colonp
= memchr (cur
, ':', file_end
- cur
);
1283 #ifdef HAVE_DOS_PATHS
1285 && colonp
+ 1 < file_end
1286 && (colonp
[1] == '/' || colonp
[1] == '\\')
1288 && isalpha ((unsigned char)colonp
[-1])
1289 && ( colonp
== cur
+ 1
1290 || strchr (" \t(", colonp
[-2]) != 0))
1291 colonp
= memchr (colonp
+ 1, ':', file_end
- (colonp
+ 1));
1295 || (endp
= memchr (cur
, '\n', colonp
- cur
)))
1298 equalp
= memchr (cur
, '=', (endp
? endp
: file_end
) - cur
);
1300 || (!endp
&& memchr (cur
, '\n', equalp
- cur
)))
1302 incdep_warn (curdep
, line_no
, "no colon.");
1307 equalp
= memchr (cur
, '=', (colonp
+ 2 <= file_end
1308 ? colonp
+ 2 : file_end
) - cur
);
1311 /* An assignment of some sort. */
1314 const char *value_start
;
1315 const char *value_end
;
1318 unsigned multi_line
= 0;
1319 enum variable_flavor flavor
;
1321 /* figure the flavor first. */
1322 flavor
= f_recursive
;
1325 if (equalp
[-1] == ':')
1327 else if (equalp
[-1] == '?')
1328 flavor
= f_conditional
;
1329 else if (equalp
[-1] == '+')
1331 else if (equalp
[-1] == '>')
1335 /* extract the variable name. */
1336 endp
= flavor
== f_recursive
? equalp
: equalp
- 1;
1337 while (endp
> cur
&& isblank ((unsigned char)endp
[-1]))
1339 var_len
= endp
- cur
;
1342 incdep_warn (curdep
, line_no
, "empty variable. (includedep)");
1345 if ( memchr (cur
, '$', var_len
)
1346 || memchr (cur
, ' ', var_len
)
1347 || memchr (cur
, '\t', var_len
))
1349 incdep_warn (curdep
, line_no
, "fancy variable name. (includedep)");
1352 var
= incdep_var_strcache (curdep
, cur
, var_len
);
1354 /* find the start of the value. */
1356 while (cur
< file_end
&& isblank ((unsigned char)*cur
))
1360 /* find the end of the value / line (this isn't 101% correct). */
1362 while (cur
< file_end
)
1364 endp
= value_end
= memchr (cur
, '\n', file_end
- cur
);
1366 value_end
= file_end
;
1367 if (value_end
- 1 >= cur
&& value_end
[-1] == '\r')
1369 if (value_end
- 1 < cur
|| value_end
[-1] != '\\')
1371 cur
= endp
? endp
+ 1 : file_end
;
1375 if (value_end
- 1 >= cur
&& value_end
[-1] == '\\')
1377 incdep_warn (curdep
, line_no
, "fancy escaping! (includedep)");
1395 /* make a copy of the value, converting \r\n to \n, and define it. */
1396 value_len
= value_end
- value_start
;
1397 value
= incdep_xmalloc (curdep
, value_len
+ 1);
1399 memcpy (value
, value_start
, value_len
);
1403 const char *src
= value_start
;
1405 while (src
< value_end
)
1409 endp
= memchr (src
, '\n', value_end
- src
);
1411 nextp
= endp
= value_end
;
1414 if (endp
> src
&& endp
[-1] == '\r')
1416 if (endp
> src
&& endp
[-1] == '\\')
1419 if (src
!= value_start
)
1421 memcpy (dst
, src
, endp
- src
);
1425 value_len
= dst
- value
;
1427 value
[value_len
] = '\0';
1429 /* do the definition */
1430 if (flavor
== f_recursive
1431 || ( flavor
== f_simple
1432 && !memchr (value
, '$', value_len
)))
1433 incdep_record_variable_in_set (curdep
,
1434 var
, var_len
, value
, value_len
,
1435 0 /* don't duplicate */, o_file
,
1436 flavor
== f_recursive
/* recursive */,
1437 NULL
/* global set */, f
);
1439 incdep_record_variable_def (curdep
,
1440 f
, var
, var_len
, value
, value_len
,
1441 o_file
, flavor
, 0 /* not target var */);
1445 /* file: dependencies */
1447 const char *filename
;
1448 struct dep
*deps
= 0;
1449 struct dep
**nextdep
= &deps
;
1452 /* extract the filename, ASSUME a single one. */
1454 while (endp
> cur
&& isblank ((unsigned char)endp
[-1]))
1458 incdep_warn (curdep
, line_no
, "empty filename.");
1461 if ( memchr (cur
, '$', endp
- cur
)
1462 || memchr (cur
, ' ', endp
- cur
)
1463 || memchr (cur
, '\t', endp
- cur
))
1465 incdep_warn (curdep
, line_no
, "multiple / fancy file name. (includedep)");
1468 filename
= incdep_dep_strcache (curdep
, cur
, endp
- cur
);
1470 /* parse any dependencies. */
1472 while (cur
< file_end
)
1474 /* skip blanks and count lines. */
1475 while (cur
< file_end
&& isspace ((unsigned char)*cur
) && *cur
!= '\n')
1477 if (cur
>= file_end
)
1486 /* continuation + eol? */
1489 unsigned eol_len
= (file_end
- cur
> 1 && cur
[1] == '\n') ? 2
1490 : (file_end
- cur
> 2 && cur
[1] == '\r' && cur
[2] == '\n') ? 3
1491 : (file_end
- cur
== 1) ? 1 : 0;
1500 /* find the end of the filename */
1502 while (endp
< file_end
&& !isspace ((unsigned char)*endp
))
1505 /* add it to the list. */
1506 *nextdep
= dep
= incdep_alloc_dep (curdep
);
1507 dep
->name
= incdep_dep_strcache (curdep
, cur
, endp
- cur
);
1508 dep
->includedep
= 1;
1509 nextdep
= &dep
->next
;
1514 /* enter the file with its dependencies. */
1515 incdep_record_files (curdep
,
1516 filename
, NULL
, NULL
, deps
, 0, NULL
, 0, 0, f
);
1521 /* free the file data */
1522 incdep_xfree (curdep
, curdep
->file_base
);
1523 curdep
->file_base
= curdep
->file_end
= NULL
;
1526 /* Flushes the incdep todo and done lists. */
1528 incdep_flush_it (struct floc
*f
)
1533 struct incdep
*cur
= incdep_head_done
;
1535 /* if the done list is empty, grab a todo list entry. */
1536 if (!cur
&& incdep_head_todo
)
1538 cur
= incdep_head_todo
;
1540 incdep_head_todo
= cur
->next
;
1542 incdep_head_todo
= incdep_tail_todo
= NULL
;
1545 incdep_read_file (cur
, f
);
1546 eval_include_dep_file (cur
, f
);
1547 incdep_freeit (cur
);
1553 /* if the todo list and done list are empty we're either done
1554 or will have to wait for the thread(s) to finish. */
1555 if (!cur
&& !incdep_num_reading
)
1559 while (!incdep_head_done
)
1560 incdep_wait_done ();
1561 cur
= incdep_head_done
;
1564 /* we grab the entire done list and work thru it. */
1565 incdep_head_done
= incdep_tail_done
= NULL
;
1570 struct incdep
*next
= cur
->next
;
1571 #ifdef PARSE_IN_WORKER
1572 incdep_flush_recorded_instructions (cur
);
1574 eval_include_dep_file (cur
, f
);
1576 incdep_freeit (cur
);
1586 /* splits up a list of file names and feeds it to eval_include_dep_file,
1587 employing threads to try speed up the file reading. */
1589 eval_include_dep (const char *names
, struct floc
*f
, enum incdep_op op
)
1591 struct incdep
*head
= 0;
1592 struct incdep
*tail
= 0;
1594 const char *names_iterator
= names
;
1596 unsigned int name_len
;
1598 /* loop through NAMES, creating a todo list out of them. */
1600 while ((name
= find_next_token (&names_iterator
, &name_len
)) != 0)
1602 cur
= xmalloc (sizeof (*cur
) + name_len
); /* not incdep_xmalloc here */
1603 cur
->file_base
= cur
->file_end
= NULL
;
1604 memcpy (cur
->name
, name
, name_len
);
1605 cur
->name
[name_len
] = '\0';
1606 cur
->worker_tid
= -1;
1607 #ifdef PARSE_IN_WORKER
1608 cur
->err_line_no
= 0;
1609 cur
->err_msg
= NULL
;
1610 cur
->recorded_variables_in_set_head
= NULL
;
1611 cur
->recorded_variables_in_set_tail
= NULL
;
1612 cur
->recorded_variable_defs_head
= NULL
;
1613 cur
->recorded_variable_defs_tail
= NULL
;
1614 cur
->recorded_files_head
= NULL
;
1615 cur
->recorded_files_tail
= NULL
;
1626 #ifdef ELECTRIC_HEAP
1629 if (op
== incdep_read_it
)
1632 /* work our way thru the files directly */
1637 struct incdep
*next
= cur
->next
;
1638 incdep_read_file (cur
, f
);
1639 eval_include_dep_file (cur
, f
);
1640 incdep_freeit (cur
);
1646 /* initialize the worker threads and related stuff the first time around. */
1648 if (!incdep_initialized
)
1651 /* queue the files and notify the worker threads. */
1655 if (incdep_tail_todo
)
1656 incdep_tail_todo
->next
= head
;
1658 incdep_head_todo
= head
;
1659 incdep_tail_todo
= tail
;
1661 incdep_signal_todo ();
1664 /* flush the todo queue if we're requested to do so. */
1666 if (op
== incdep_flush
)
1667 incdep_flush_it (f
);
1671 #endif /* CONFIG_WITH_INCLUDEDEP */