| 1 | /* Target file hash table management for GNU Make. | 
|---|
| 2 | Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, | 
|---|
| 3 | 2002 Free Software Foundation, Inc. | 
|---|
| 4 | This file is part of GNU Make. | 
|---|
| 5 |  | 
|---|
| 6 | GNU Make is free software; you can redistribute it and/or modify | 
|---|
| 7 | it under the terms of the GNU General Public License as published by | 
|---|
| 8 | the Free Software Foundation; either version 2, or (at your option) | 
|---|
| 9 | any later version. | 
|---|
| 10 |  | 
|---|
| 11 | GNU Make is distributed in the hope that it will be useful, | 
|---|
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 14 | GNU General Public License for more details. | 
|---|
| 15 |  | 
|---|
| 16 | You should have received a copy of the GNU General Public License | 
|---|
| 17 | along with GNU Make; see the file COPYING.  If not, write to | 
|---|
| 18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 
|---|
| 19 | Boston, MA 02111-1307, USA.  */ | 
|---|
| 20 |  | 
|---|
| 21 | #include "make.h" | 
|---|
| 22 |  | 
|---|
| 23 | #include <assert.h> | 
|---|
| 24 |  | 
|---|
| 25 | #include "dep.h" | 
|---|
| 26 | #include "filedef.h" | 
|---|
| 27 | #include "job.h" | 
|---|
| 28 | #include "commands.h" | 
|---|
| 29 | #include "variable.h" | 
|---|
| 30 | #include "debug.h" | 
|---|
| 31 | #include "hash.h" | 
|---|
| 32 |  | 
|---|
| 33 |  | 
|---|
| 34 | /* Hash table of files the makefile knows how to make.  */ | 
|---|
| 35 |  | 
|---|
| 36 | static unsigned long | 
|---|
| 37 | file_hash_1 (const void *key) | 
|---|
| 38 | { | 
|---|
| 39 | return_ISTRING_HASH_1 (((struct file const *) key)->hname); | 
|---|
| 40 | } | 
|---|
| 41 |  | 
|---|
| 42 | static unsigned long | 
|---|
| 43 | file_hash_2 (const void *key) | 
|---|
| 44 | { | 
|---|
| 45 | return_ISTRING_HASH_2 (((struct file const *) key)->hname); | 
|---|
| 46 | } | 
|---|
| 47 |  | 
|---|
| 48 | static int | 
|---|
| 49 | file_hash_cmp (const void *x, const void *y) | 
|---|
| 50 | { | 
|---|
| 51 | return_ISTRING_COMPARE (((struct file const *) x)->hname, | 
|---|
| 52 | ((struct file const *) y)->hname); | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 | #ifndef FILE_BUCKETS | 
|---|
| 56 | #define FILE_BUCKETS    1007 | 
|---|
| 57 | #endif | 
|---|
| 58 | static struct hash_table files; | 
|---|
| 59 |  | 
|---|
| 60 | /* Whether or not .SECONDARY with no prerequisites was given.  */ | 
|---|
| 61 | static int all_secondary = 0; | 
|---|
| 62 |  | 
|---|
| 63 | /* Access the hash table of all file records. | 
|---|
| 64 | lookup_file  given a name, return the struct file * for that name, | 
|---|
| 65 | or nil if there is none. | 
|---|
| 66 | enter_file   similar, but create one if there is none.  */ | 
|---|
| 67 |  | 
|---|
| 68 | struct file * | 
|---|
| 69 | lookup_file (char *name) | 
|---|
| 70 | { | 
|---|
| 71 | register struct file *f; | 
|---|
| 72 | struct file file_key; | 
|---|
| 73 | #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) | 
|---|
| 74 | register char *lname, *ln; | 
|---|
| 75 | #endif | 
|---|
| 76 |  | 
|---|
| 77 | assert (*name != '\0'); | 
|---|
| 78 |  | 
|---|
| 79 | /* This is also done in parse_file_seq, so this is redundant | 
|---|
| 80 | for names read from makefiles.  It is here for names passed | 
|---|
| 81 | on the command line.  */ | 
|---|
| 82 | #ifdef VMS | 
|---|
| 83 | # ifndef WANT_CASE_SENSITIVE_TARGETS | 
|---|
| 84 | { | 
|---|
| 85 | register char *n; | 
|---|
| 86 | lname = (char *) malloc (strlen (name) + 1); | 
|---|
| 87 | for (n = name, ln = lname; *n != '\0'; ++n, ++ln) | 
|---|
| 88 | *ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n; | 
|---|
| 89 | *ln = '\0'; | 
|---|
| 90 | name = lname; | 
|---|
| 91 | } | 
|---|
| 92 | # endif | 
|---|
| 93 |  | 
|---|
| 94 | while (name[0] == '[' && name[1] == ']' && name[2] != '\0') | 
|---|
| 95 | name += 2; | 
|---|
| 96 | #endif | 
|---|
| 97 | while (name[0] == '.' && name[1] == '/' && name[2] != '\0') | 
|---|
| 98 | { | 
|---|
| 99 | name += 2; | 
|---|
| 100 | while (*name == '/') | 
|---|
| 101 | /* Skip following slashes: ".//foo" is "foo", not "/foo".  */ | 
|---|
| 102 | ++name; | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | if (*name == '\0') | 
|---|
| 106 | /* It was all slashes after a dot.  */ | 
|---|
| 107 | #ifdef VMS | 
|---|
| 108 | name = "[]"; | 
|---|
| 109 | #else | 
|---|
| 110 | #ifdef _AMIGA | 
|---|
| 111 | name = ""; | 
|---|
| 112 | #else | 
|---|
| 113 | name = "./"; | 
|---|
| 114 | #endif /* AMIGA */ | 
|---|
| 115 | #endif /* VMS */ | 
|---|
| 116 |  | 
|---|
| 117 | file_key.hname = name; | 
|---|
| 118 | f = (struct file *) hash_find_item (&files, &file_key); | 
|---|
| 119 | #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) | 
|---|
| 120 | free (lname); | 
|---|
| 121 | #endif | 
|---|
| 122 | return f; | 
|---|
| 123 | } | 
|---|
| 124 |  | 
|---|
| 125 | struct file * | 
|---|
| 126 | enter_file (char *name) | 
|---|
| 127 | { | 
|---|
| 128 | register struct file *f; | 
|---|
| 129 | register struct file *new; | 
|---|
| 130 | register struct file **file_slot; | 
|---|
| 131 | struct file file_key; | 
|---|
| 132 | #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) | 
|---|
| 133 | char *lname, *ln; | 
|---|
| 134 | #endif | 
|---|
| 135 |  | 
|---|
| 136 | assert (*name != '\0'); | 
|---|
| 137 |  | 
|---|
| 138 | #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) | 
|---|
| 139 | { | 
|---|
| 140 | register char *n; | 
|---|
| 141 | lname = (char *) malloc (strlen (name) + 1); | 
|---|
| 142 | for (n = name, ln = lname; *n != '\0'; ++n, ++ln) | 
|---|
| 143 | { | 
|---|
| 144 | if (isupper ((unsigned char)*n)) | 
|---|
| 145 | *ln = tolower ((unsigned char)*n); | 
|---|
| 146 | else | 
|---|
| 147 | *ln = *n; | 
|---|
| 148 | } | 
|---|
| 149 |  | 
|---|
| 150 | *ln = 0; | 
|---|
| 151 | /* Creates a possible leak, old value of name is unreachable, but I | 
|---|
| 152 | currently don't know how to fix it. */ | 
|---|
| 153 | name = lname; | 
|---|
| 154 | } | 
|---|
| 155 | #endif | 
|---|
| 156 |  | 
|---|
| 157 | file_key.hname = name; | 
|---|
| 158 | file_slot = (struct file **) hash_find_slot (&files, &file_key); | 
|---|
| 159 | f = *file_slot; | 
|---|
| 160 | if (! HASH_VACANT (f) && !f->double_colon) | 
|---|
| 161 | { | 
|---|
| 162 | #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) | 
|---|
| 163 | free(lname); | 
|---|
| 164 | #endif | 
|---|
| 165 | return f; | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | new = (struct file *) xmalloc (sizeof (struct file)); | 
|---|
| 169 | bzero ((char *) new, sizeof (struct file)); | 
|---|
| 170 | new->name = new->hname = name; | 
|---|
| 171 | new->update_status = -1; | 
|---|
| 172 |  | 
|---|
| 173 | if (HASH_VACANT (f)) | 
|---|
| 174 | hash_insert_at (&files, new, file_slot); | 
|---|
| 175 | else | 
|---|
| 176 | { | 
|---|
| 177 | /* There is already a double-colon entry for this file.  */ | 
|---|
| 178 | new->double_colon = f; | 
|---|
| 179 | while (f->prev != 0) | 
|---|
| 180 | f = f->prev; | 
|---|
| 181 | f->prev = new; | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | return new; | 
|---|
| 185 | } | 
|---|
| 186 |  | 
|---|
| 187 |  | 
|---|
| 188 | /* Rename FILE to NAME.  This is not as simple as resetting | 
|---|
| 189 | the `name' member, since it must be put in a new hash bucket, | 
|---|
| 190 | and possibly merged with an existing file called NAME.  */ | 
|---|
| 191 |  | 
|---|
| 192 | void | 
|---|
| 193 | rename_file (struct file *from_file, char *to_hname) | 
|---|
| 194 | { | 
|---|
| 195 | rehash_file (from_file, to_hname); | 
|---|
| 196 | while (from_file) | 
|---|
| 197 | { | 
|---|
| 198 | from_file->name = from_file->hname; | 
|---|
| 199 | from_file = from_file->prev; | 
|---|
| 200 | } | 
|---|
| 201 | } | 
|---|
| 202 |  | 
|---|
| 203 | /* Rehash FILE to NAME.  This is not as simple as resetting | 
|---|
| 204 | the `hname' member, since it must be put in a new hash bucket, | 
|---|
| 205 | and possibly merged with an existing file called NAME.  */ | 
|---|
| 206 |  | 
|---|
| 207 | void | 
|---|
| 208 | rehash_file (struct file *from_file, char *to_hname) | 
|---|
| 209 | { | 
|---|
| 210 | struct file file_key; | 
|---|
| 211 | struct file **file_slot; | 
|---|
| 212 | struct file *to_file; | 
|---|
| 213 | struct file *deleted_file; | 
|---|
| 214 | struct file *f; | 
|---|
| 215 |  | 
|---|
| 216 | file_key.hname = to_hname; | 
|---|
| 217 | if (0 == file_hash_cmp (from_file, &file_key)) | 
|---|
| 218 | return; | 
|---|
| 219 |  | 
|---|
| 220 | file_key.hname = from_file->hname; | 
|---|
| 221 | while (from_file->renamed != 0) | 
|---|
| 222 | from_file = from_file->renamed; | 
|---|
| 223 | if (file_hash_cmp (from_file, &file_key)) | 
|---|
| 224 | /* hname changed unexpectedly */ | 
|---|
| 225 | abort (); | 
|---|
| 226 |  | 
|---|
| 227 | deleted_file = hash_delete (&files, from_file); | 
|---|
| 228 | if (deleted_file != from_file) | 
|---|
| 229 | /* from_file isn't the one stored in files */ | 
|---|
| 230 | abort (); | 
|---|
| 231 |  | 
|---|
| 232 | file_key.hname = to_hname; | 
|---|
| 233 | file_slot = (struct file **) hash_find_slot (&files, &file_key); | 
|---|
| 234 | to_file = *file_slot; | 
|---|
| 235 |  | 
|---|
| 236 | from_file->hname = to_hname; | 
|---|
| 237 | for (f = from_file->double_colon; f != 0; f = f->prev) | 
|---|
| 238 | f->hname = to_hname; | 
|---|
| 239 |  | 
|---|
| 240 | if (HASH_VACANT (to_file)) | 
|---|
| 241 | hash_insert_at (&files, from_file, file_slot); | 
|---|
| 242 | else | 
|---|
| 243 | { | 
|---|
| 244 | /* TO_FILE already exists under TO_HNAME. | 
|---|
| 245 | We must retain TO_FILE and merge FROM_FILE into it.  */ | 
|---|
| 246 |  | 
|---|
| 247 | if (from_file->cmds != 0) | 
|---|
| 248 | { | 
|---|
| 249 | if (to_file->cmds == 0) | 
|---|
| 250 | to_file->cmds = from_file->cmds; | 
|---|
| 251 | else if (from_file->cmds != to_file->cmds) | 
|---|
| 252 | { | 
|---|
| 253 | /* We have two sets of commands.  We will go with the | 
|---|
| 254 | one given in the rule explicitly mentioning this name, | 
|---|
| 255 | but give a message to let the user know what's going on.  */ | 
|---|
| 256 | if (to_file->cmds->fileinfo.filenm != 0) | 
|---|
| 257 | error (&from_file->cmds->fileinfo, | 
|---|
| 258 | _("Commands were specified for file `%s' at %s:%lu,"), | 
|---|
| 259 | from_file->name, to_file->cmds->fileinfo.filenm, | 
|---|
| 260 | to_file->cmds->fileinfo.lineno); | 
|---|
| 261 | else | 
|---|
| 262 | error (&from_file->cmds->fileinfo, | 
|---|
| 263 | _("Commands for file `%s' were found by implicit rule search,"), | 
|---|
| 264 | from_file->name); | 
|---|
| 265 | error (&from_file->cmds->fileinfo, | 
|---|
| 266 | _("but `%s' is now considered the same file as `%s'."), | 
|---|
| 267 | from_file->name, to_hname); | 
|---|
| 268 | error (&from_file->cmds->fileinfo, | 
|---|
| 269 | _("Commands for `%s' will be ignored in favor of those for `%s'."), | 
|---|
| 270 | to_hname, from_file->name); | 
|---|
| 271 | } | 
|---|
| 272 | } | 
|---|
| 273 |  | 
|---|
| 274 | /* Merge the dependencies of the two files.  */ | 
|---|
| 275 |  | 
|---|
| 276 | if (to_file->deps == 0) | 
|---|
| 277 | to_file->deps = from_file->deps; | 
|---|
| 278 | else | 
|---|
| 279 | { | 
|---|
| 280 | register struct dep *deps = to_file->deps; | 
|---|
| 281 | while (deps->next != 0) | 
|---|
| 282 | deps = deps->next; | 
|---|
| 283 | deps->next = from_file->deps; | 
|---|
| 284 | } | 
|---|
| 285 |  | 
|---|
| 286 | merge_variable_set_lists (&to_file->variables, from_file->variables); | 
|---|
| 287 |  | 
|---|
| 288 | if (to_file->double_colon && from_file->is_target && !from_file->double_colon) | 
|---|
| 289 | fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"), | 
|---|
| 290 | from_file->name, to_hname); | 
|---|
| 291 | if (!to_file->double_colon  && from_file->double_colon) | 
|---|
| 292 | { | 
|---|
| 293 | if (to_file->is_target) | 
|---|
| 294 | fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"), | 
|---|
| 295 | from_file->name, to_hname); | 
|---|
| 296 | else | 
|---|
| 297 | to_file->double_colon = from_file->double_colon; | 
|---|
| 298 | } | 
|---|
| 299 |  | 
|---|
| 300 | if (from_file->last_mtime > to_file->last_mtime) | 
|---|
| 301 | /* %%% Kludge so -W wins on a file that gets vpathized.  */ | 
|---|
| 302 | to_file->last_mtime = from_file->last_mtime; | 
|---|
| 303 |  | 
|---|
| 304 | to_file->mtime_before_update = from_file->mtime_before_update; | 
|---|
| 305 |  | 
|---|
| 306 | #define MERGE(field) to_file->field |= from_file->field | 
|---|
| 307 | MERGE (precious); | 
|---|
| 308 | MERGE (tried_implicit); | 
|---|
| 309 | MERGE (updating); | 
|---|
| 310 | MERGE (updated); | 
|---|
| 311 | MERGE (is_target); | 
|---|
| 312 | MERGE (cmd_target); | 
|---|
| 313 | MERGE (phony); | 
|---|
| 314 | MERGE (ignore_vpath); | 
|---|
| 315 | #undef MERGE | 
|---|
| 316 |  | 
|---|
| 317 | from_file->renamed = to_file; | 
|---|
| 318 | } | 
|---|
| 319 | } | 
|---|
| 320 |  | 
|---|
| 321 |  | 
|---|
| 322 | /* Remove all nonprecious intermediate files. | 
|---|
| 323 | If SIG is nonzero, this was caused by a fatal signal, | 
|---|
| 324 | meaning that a different message will be printed, and | 
|---|
| 325 | the message will go to stderr rather than stdout.  */ | 
|---|
| 326 |  | 
|---|
| 327 | void | 
|---|
| 328 | remove_intermediates (int sig) | 
|---|
| 329 | { | 
|---|
| 330 | register struct file **file_slot; | 
|---|
| 331 | register struct file **file_end; | 
|---|
| 332 | int doneany = 0; | 
|---|
| 333 |  | 
|---|
| 334 | /* If there's no way we will ever remove anything anyway, punt early.  */ | 
|---|
| 335 | if (question_flag || touch_flag || all_secondary) | 
|---|
| 336 | return; | 
|---|
| 337 |  | 
|---|
| 338 | if (sig && just_print_flag) | 
|---|
| 339 | return; | 
|---|
| 340 |  | 
|---|
| 341 | file_slot = (struct file **) files.ht_vec; | 
|---|
| 342 | file_end = file_slot + files.ht_size; | 
|---|
| 343 | for ( ; file_slot < file_end; file_slot++) | 
|---|
| 344 | if (! HASH_VACANT (*file_slot)) | 
|---|
| 345 | { | 
|---|
| 346 | register struct file *f = *file_slot; | 
|---|
| 347 | if (f->intermediate && (f->dontcare || !f->precious) | 
|---|
| 348 | && !f->secondary && !f->cmd_target) | 
|---|
| 349 | { | 
|---|
| 350 | int status; | 
|---|
| 351 | if (f->update_status == -1) | 
|---|
| 352 | /* If nothing would have created this file yet, | 
|---|
| 353 | don't print an "rm" command for it.  */ | 
|---|
| 354 | continue; | 
|---|
| 355 | if (just_print_flag) | 
|---|
| 356 | status = 0; | 
|---|
| 357 | else | 
|---|
| 358 | { | 
|---|
| 359 | status = unlink (f->name); | 
|---|
| 360 | if (status < 0 && errno == ENOENT) | 
|---|
| 361 | continue; | 
|---|
| 362 | } | 
|---|
| 363 | if (!f->dontcare) | 
|---|
| 364 | { | 
|---|
| 365 | if (sig) | 
|---|
| 366 | error (NILF, _("*** Deleting intermediate file `%s'"), f->name); | 
|---|
| 367 | else | 
|---|
| 368 | { | 
|---|
| 369 | if (! doneany) | 
|---|
| 370 | DB (DB_BASIC, (_("Removing intermediate files...\n"))); | 
|---|
| 371 | if (!silent_flag) | 
|---|
| 372 | { | 
|---|
| 373 | if (! doneany) | 
|---|
| 374 | { | 
|---|
| 375 | fputs ("rm ", stdout); | 
|---|
| 376 | doneany = 1; | 
|---|
| 377 | } | 
|---|
| 378 | else | 
|---|
| 379 | putchar (' '); | 
|---|
| 380 | fputs (f->name, stdout); | 
|---|
| 381 | fflush (stdout); | 
|---|
| 382 | } | 
|---|
| 383 | } | 
|---|
| 384 | if (status < 0) | 
|---|
| 385 | perror_with_name ("unlink: ", f->name); | 
|---|
| 386 | } | 
|---|
| 387 | } | 
|---|
| 388 | } | 
|---|
| 389 |  | 
|---|
| 390 | if (doneany && !sig) | 
|---|
| 391 | { | 
|---|
| 392 | putchar ('\n'); | 
|---|
| 393 | fflush (stdout); | 
|---|
| 394 | } | 
|---|
| 395 | } | 
|---|
| 396 |  | 
|---|
| 397 |  | 
|---|
| 398 | /* Set the intermediate flag.  */ | 
|---|
| 399 |  | 
|---|
| 400 | static void | 
|---|
| 401 | set_intermediate (const void *item) | 
|---|
| 402 | { | 
|---|
| 403 | struct file *f = (struct file *) item; | 
|---|
| 404 | f->intermediate = 1; | 
|---|
| 405 | } | 
|---|
| 406 |  | 
|---|
| 407 | /* For each dependency of each file, make the `struct dep' point | 
|---|
| 408 | at the appropriate `struct file' (which may have to be created). | 
|---|
| 409 |  | 
|---|
| 410 | Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT, | 
|---|
| 411 | and various other special targets.  */ | 
|---|
| 412 |  | 
|---|
| 413 | void | 
|---|
| 414 | snap_deps (void) | 
|---|
| 415 | { | 
|---|
| 416 | register struct file *f; | 
|---|
| 417 | register struct file *f2; | 
|---|
| 418 | register struct dep *d; | 
|---|
| 419 | register struct file **file_slot_0; | 
|---|
| 420 | register struct file **file_slot; | 
|---|
| 421 | register struct file **file_end; | 
|---|
| 422 |  | 
|---|
| 423 | /* Enter each dependency name as a file.  */ | 
|---|
| 424 | /* We must use hash_dump (), because within this loop | 
|---|
| 425 | we might add new files to the table, possibly causing | 
|---|
| 426 | an in-situ table expansion.  */ | 
|---|
| 427 | file_slot_0 = (struct file **) hash_dump (&files, 0, 0); | 
|---|
| 428 | file_end = file_slot_0 + files.ht_fill; | 
|---|
| 429 | for (file_slot = file_slot_0; file_slot < file_end; file_slot++) | 
|---|
| 430 | for (f2 = *file_slot; f2 != 0; f2 = f2->prev) | 
|---|
| 431 | for (d = f2->deps; d != 0; d = d->next) | 
|---|
| 432 | if (d->name != 0) | 
|---|
| 433 | { | 
|---|
| 434 | d->file = lookup_file (d->name); | 
|---|
| 435 | if (d->file == 0) | 
|---|
| 436 | d->file = enter_file (d->name); | 
|---|
| 437 | else | 
|---|
| 438 | free (d->name); | 
|---|
| 439 | d->name = 0; | 
|---|
| 440 | } | 
|---|
| 441 | free (file_slot_0); | 
|---|
| 442 |  | 
|---|
| 443 | for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev) | 
|---|
| 444 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 445 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 446 | f2->precious = 1; | 
|---|
| 447 |  | 
|---|
| 448 | for (f = lookup_file (".LOW_RESOLUTION_TIME"); f != 0; f = f->prev) | 
|---|
| 449 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 450 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 451 | f2->low_resolution_time = 1; | 
|---|
| 452 |  | 
|---|
| 453 | for (f = lookup_file (".PHONY"); f != 0; f = f->prev) | 
|---|
| 454 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 455 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 456 | { | 
|---|
| 457 | /* Mark this file as phony and nonexistent.  */ | 
|---|
| 458 | f2->phony = 1; | 
|---|
| 459 | f2->last_mtime = NONEXISTENT_MTIME; | 
|---|
| 460 | f2->mtime_before_update = NONEXISTENT_MTIME; | 
|---|
| 461 | } | 
|---|
| 462 |  | 
|---|
| 463 | for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev) | 
|---|
| 464 | { | 
|---|
| 465 | /* .INTERMEDIATE with deps listed | 
|---|
| 466 | marks those deps as intermediate files.  */ | 
|---|
| 467 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 468 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 469 | f2->intermediate = 1; | 
|---|
| 470 | /* .INTERMEDIATE with no deps does nothing. | 
|---|
| 471 | Marking all files as intermediates is useless | 
|---|
| 472 | since the goal targets would be deleted after they are built.  */ | 
|---|
| 473 | } | 
|---|
| 474 |  | 
|---|
| 475 | for (f = lookup_file (".SECONDARY"); f != 0; f = f->prev) | 
|---|
| 476 | { | 
|---|
| 477 | /* .SECONDARY with deps listed | 
|---|
| 478 | marks those deps as intermediate files | 
|---|
| 479 | in that they don't get rebuilt if not actually needed; | 
|---|
| 480 | but unlike real intermediate files, | 
|---|
| 481 | these are not deleted after make finishes.  */ | 
|---|
| 482 | if (f->deps) | 
|---|
| 483 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 484 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 485 | f2->intermediate = f2->secondary = 1; | 
|---|
| 486 | /* .SECONDARY with no deps listed marks *all* files that way.  */ | 
|---|
| 487 | else | 
|---|
| 488 | { | 
|---|
| 489 | all_secondary = 1; | 
|---|
| 490 | hash_map (&files, set_intermediate); | 
|---|
| 491 | } | 
|---|
| 492 | } | 
|---|
| 493 |  | 
|---|
| 494 | f = lookup_file (".EXPORT_ALL_VARIABLES"); | 
|---|
| 495 | if (f != 0 && f->is_target) | 
|---|
| 496 | export_all_variables = 1; | 
|---|
| 497 |  | 
|---|
| 498 | f = lookup_file (".IGNORE"); | 
|---|
| 499 | if (f != 0 && f->is_target) | 
|---|
| 500 | { | 
|---|
| 501 | if (f->deps == 0) | 
|---|
| 502 | ignore_errors_flag = 1; | 
|---|
| 503 | else | 
|---|
| 504 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 505 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 506 | f2->command_flags |= COMMANDS_NOERROR; | 
|---|
| 507 | } | 
|---|
| 508 |  | 
|---|
| 509 | f = lookup_file (".SILENT"); | 
|---|
| 510 | if (f != 0 && f->is_target) | 
|---|
| 511 | { | 
|---|
| 512 | if (f->deps == 0) | 
|---|
| 513 | silent_flag = 1; | 
|---|
| 514 | else | 
|---|
| 515 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 516 | for (f2 = d->file; f2 != 0; f2 = f2->prev) | 
|---|
| 517 | f2->command_flags |= COMMANDS_SILENT; | 
|---|
| 518 | } | 
|---|
| 519 |  | 
|---|
| 520 | f = lookup_file (".POSIX"); | 
|---|
| 521 | if (f != 0 && f->is_target) | 
|---|
| 522 | posix_pedantic = 1; | 
|---|
| 523 |  | 
|---|
| 524 | f = lookup_file (".NOTPARALLEL"); | 
|---|
| 525 | if (f != 0 && f->is_target) | 
|---|
| 526 | not_parallel = 1; | 
|---|
| 527 | } | 
|---|
| 528 |  | 
|---|
| 529 |  | 
|---|
| 530 | /* Set the `command_state' member of FILE and all its `also_make's.  */ | 
|---|
| 531 |  | 
|---|
| 532 | void | 
|---|
| 533 | set_command_state (struct file *file, int state) | 
|---|
| 534 | { | 
|---|
| 535 | struct dep *d; | 
|---|
| 536 |  | 
|---|
| 537 | file->command_state = state; | 
|---|
| 538 |  | 
|---|
| 539 | for (d = file->also_make; d != 0; d = d->next) | 
|---|
| 540 | d->file->command_state = state; | 
|---|
| 541 | } | 
|---|
| 542 |  | 
|---|
| 543 |  | 
|---|
| 544 | /* Convert an external file timestamp to internal form.  */ | 
|---|
| 545 |  | 
|---|
| 546 | FILE_TIMESTAMP | 
|---|
| 547 | file_timestamp_cons (const char *fname, time_t s, int ns) | 
|---|
| 548 | { | 
|---|
| 549 | int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0); | 
|---|
| 550 | FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS; | 
|---|
| 551 | FILE_TIMESTAMP ts = product + offset; | 
|---|
| 552 |  | 
|---|
| 553 | if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX) | 
|---|
| 554 | && product <= ts && ts <= ORDINARY_MTIME_MAX)) | 
|---|
| 555 | { | 
|---|
| 556 | char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; | 
|---|
| 557 | ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX; | 
|---|
| 558 | file_timestamp_sprintf (buf, ts); | 
|---|
| 559 | error (NILF, _("%s: Timestamp out of range; substituting %s"), | 
|---|
| 560 | fname ? fname : _("Current time"), buf); | 
|---|
| 561 | } | 
|---|
| 562 |  | 
|---|
| 563 | return ts; | 
|---|
| 564 | } | 
|---|
| 565 |  | 
|---|
| 566 |  | 
|---|
| 567 | /* Return the current time as a file timestamp, setting *RESOLUTION to | 
|---|
| 568 | its resolution.  */ | 
|---|
| 569 | FILE_TIMESTAMP | 
|---|
| 570 | file_timestamp_now (int *resolution) | 
|---|
| 571 | { | 
|---|
| 572 | int r; | 
|---|
| 573 | time_t s; | 
|---|
| 574 | int ns; | 
|---|
| 575 |  | 
|---|
| 576 | /* Don't bother with high-resolution clocks if file timestamps have | 
|---|
| 577 | only one-second resolution.  The code below should work, but it's | 
|---|
| 578 | not worth the hassle of debugging it on hosts where it fails.  */ | 
|---|
| 579 | #if FILE_TIMESTAMP_HI_RES | 
|---|
| 580 | # if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME | 
|---|
| 581 | { | 
|---|
| 582 | struct timespec timespec; | 
|---|
| 583 | if (clock_gettime (CLOCK_REALTIME, ×pec) == 0) | 
|---|
| 584 | { | 
|---|
| 585 | r = 1; | 
|---|
| 586 | s = timespec.tv_sec; | 
|---|
| 587 | ns = timespec.tv_nsec; | 
|---|
| 588 | goto got_time; | 
|---|
| 589 | } | 
|---|
| 590 | } | 
|---|
| 591 | # endif | 
|---|
| 592 | # if HAVE_GETTIMEOFDAY | 
|---|
| 593 | { | 
|---|
| 594 | struct timeval timeval; | 
|---|
| 595 | if (gettimeofday (&timeval, 0) == 0) | 
|---|
| 596 | { | 
|---|
| 597 | r = 1000; | 
|---|
| 598 | s = timeval.tv_sec; | 
|---|
| 599 | ns = timeval.tv_usec * 1000; | 
|---|
| 600 | goto got_time; | 
|---|
| 601 | } | 
|---|
| 602 | } | 
|---|
| 603 | # endif | 
|---|
| 604 | #endif | 
|---|
| 605 |  | 
|---|
| 606 | r = 1000000000; | 
|---|
| 607 | s = time ((time_t *) 0); | 
|---|
| 608 | ns = 0; | 
|---|
| 609 |  | 
|---|
| 610 | #if FILE_TIMESTAMP_HI_RES | 
|---|
| 611 | got_time: | 
|---|
| 612 | #endif | 
|---|
| 613 | *resolution = r; | 
|---|
| 614 | return file_timestamp_cons (0, s, ns); | 
|---|
| 615 | } | 
|---|
| 616 |  | 
|---|
| 617 | /* Place into the buffer P a printable representation of the file | 
|---|
| 618 | timestamp TS.  */ | 
|---|
| 619 | void | 
|---|
| 620 | file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts) | 
|---|
| 621 | { | 
|---|
| 622 | time_t t = FILE_TIMESTAMP_S (ts); | 
|---|
| 623 | struct tm *tm = localtime (&t); | 
|---|
| 624 |  | 
|---|
| 625 | if (tm) | 
|---|
| 626 | sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d", | 
|---|
| 627 | tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | 
|---|
| 628 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 
|---|
| 629 | else if (t < 0) | 
|---|
| 630 | sprintf (p, "%ld", (long) t); | 
|---|
| 631 | else | 
|---|
| 632 | sprintf (p, "%lu", (unsigned long) t); | 
|---|
| 633 | p += strlen (p); | 
|---|
| 634 |  | 
|---|
| 635 | /* Append nanoseconds as a fraction, but remove trailing zeros. | 
|---|
| 636 | We don't know the actual timestamp resolution, since clock_getres | 
|---|
| 637 | applies only to local times, whereas this timestamp might come | 
|---|
| 638 | from a remote filesystem.  So removing trailing zeros is the | 
|---|
| 639 | best guess that we can do.  */ | 
|---|
| 640 | sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts)); | 
|---|
| 641 | p += strlen (p) - 1; | 
|---|
| 642 | while (*p == '0') | 
|---|
| 643 | p--; | 
|---|
| 644 | p += *p != '.'; | 
|---|
| 645 |  | 
|---|
| 646 | *p = '\0'; | 
|---|
| 647 | } | 
|---|
| 648 |  | 
|---|
| 649 |  | 
|---|
| 650 | /* Print the data base of files.  */ | 
|---|
| 651 |  | 
|---|
| 652 | static void | 
|---|
| 653 | print_file (const void *item) | 
|---|
| 654 | { | 
|---|
| 655 | struct file *f = (struct file *) item; | 
|---|
| 656 | struct dep *d; | 
|---|
| 657 | struct dep *ood = 0; | 
|---|
| 658 |  | 
|---|
| 659 | putchar ('\n'); | 
|---|
| 660 | if (!f->is_target) | 
|---|
| 661 | puts (_("# Not a target:")); | 
|---|
| 662 | printf ("%s:%s", f->name, f->double_colon ? ":" : ""); | 
|---|
| 663 |  | 
|---|
| 664 | /* Print all normal dependencies; note any order-only deps.  */ | 
|---|
| 665 | for (d = f->deps; d != 0; d = d->next) | 
|---|
| 666 | if (! d->ignore_mtime) | 
|---|
| 667 | printf (" %s", dep_name (d)); | 
|---|
| 668 | else if (! ood) | 
|---|
| 669 | ood = d; | 
|---|
| 670 |  | 
|---|
| 671 | /* Print order-only deps, if we have any.  */ | 
|---|
| 672 | if (ood) | 
|---|
| 673 | { | 
|---|
| 674 | printf (" | %s", dep_name (ood)); | 
|---|
| 675 | for (d = ood->next; d != 0; d = d->next) | 
|---|
| 676 | if (d->ignore_mtime) | 
|---|
| 677 | printf (" %s", dep_name (d)); | 
|---|
| 678 | } | 
|---|
| 679 |  | 
|---|
| 680 | putchar ('\n'); | 
|---|
| 681 |  | 
|---|
| 682 | if (f->precious) | 
|---|
| 683 | puts (_("#  Precious file (prerequisite of .PRECIOUS).")); | 
|---|
| 684 | if (f->phony) | 
|---|
| 685 | puts (_("#  Phony target (prerequisite of .PHONY).")); | 
|---|
| 686 | if (f->cmd_target) | 
|---|
| 687 | puts (_("#  Command-line target.")); | 
|---|
| 688 | if (f->dontcare) | 
|---|
| 689 | puts (_("#  A default or MAKEFILES makefile.")); | 
|---|
| 690 | puts (f->tried_implicit | 
|---|
| 691 | ? _("#  Implicit rule search has been done.") | 
|---|
| 692 | : _("#  Implicit rule search has not been done.")); | 
|---|
| 693 | if (f->stem != 0) | 
|---|
| 694 | printf (_("#  Implicit/static pattern stem: `%s'\n"), f->stem); | 
|---|
| 695 | if (f->intermediate) | 
|---|
| 696 | puts (_("#  File is an intermediate prerequisite.")); | 
|---|
| 697 | if (f->also_make != 0) | 
|---|
| 698 | { | 
|---|
| 699 | fputs (_("#  Also makes:"), stdout); | 
|---|
| 700 | for (d = f->also_make; d != 0; d = d->next) | 
|---|
| 701 | printf (" %s", dep_name (d)); | 
|---|
| 702 | putchar ('\n'); | 
|---|
| 703 | } | 
|---|
| 704 | if (f->last_mtime == UNKNOWN_MTIME) | 
|---|
| 705 | puts (_("#  Modification time never checked.")); | 
|---|
| 706 | else if (f->last_mtime == NONEXISTENT_MTIME) | 
|---|
| 707 | puts (_("#  File does not exist.")); | 
|---|
| 708 | else if (f->last_mtime == OLD_MTIME) | 
|---|
| 709 | puts (_("#  File is very old.")); | 
|---|
| 710 | else | 
|---|
| 711 | { | 
|---|
| 712 | char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; | 
|---|
| 713 | file_timestamp_sprintf (buf, f->last_mtime); | 
|---|
| 714 | printf (_("#  Last modified %s\n"), buf); | 
|---|
| 715 | } | 
|---|
| 716 | puts (f->updated | 
|---|
| 717 | ? _("#  File has been updated.") : _("#  File has not been updated.")); | 
|---|
| 718 | switch (f->command_state) | 
|---|
| 719 | { | 
|---|
| 720 | case cs_running: | 
|---|
| 721 | puts (_("#  Commands currently running (THIS IS A BUG).")); | 
|---|
| 722 | break; | 
|---|
| 723 | case cs_deps_running: | 
|---|
| 724 | puts (_("#  Dependencies commands running (THIS IS A BUG).")); | 
|---|
| 725 | break; | 
|---|
| 726 | case cs_not_started: | 
|---|
| 727 | case cs_finished: | 
|---|
| 728 | switch (f->update_status) | 
|---|
| 729 | { | 
|---|
| 730 | case -1: | 
|---|
| 731 | break; | 
|---|
| 732 | case 0: | 
|---|
| 733 | puts (_("#  Successfully updated.")); | 
|---|
| 734 | break; | 
|---|
| 735 | case 1: | 
|---|
| 736 | assert (question_flag); | 
|---|
| 737 | puts (_("#  Needs to be updated (-q is set).")); | 
|---|
| 738 | break; | 
|---|
| 739 | case 2: | 
|---|
| 740 | puts (_("#  Failed to be updated.")); | 
|---|
| 741 | break; | 
|---|
| 742 | default: | 
|---|
| 743 | puts (_("#  Invalid value in `update_status' member!")); | 
|---|
| 744 | fflush (stdout); | 
|---|
| 745 | fflush (stderr); | 
|---|
| 746 | abort (); | 
|---|
| 747 | } | 
|---|
| 748 | break; | 
|---|
| 749 | default: | 
|---|
| 750 | puts (_("#  Invalid value in `command_state' member!")); | 
|---|
| 751 | fflush (stdout); | 
|---|
| 752 | fflush (stderr); | 
|---|
| 753 | abort (); | 
|---|
| 754 | } | 
|---|
| 755 |  | 
|---|
| 756 | if (f->variables != 0) | 
|---|
| 757 | print_file_variables (f); | 
|---|
| 758 |  | 
|---|
| 759 | if (f->cmds != 0) | 
|---|
| 760 | print_commands (f->cmds); | 
|---|
| 761 | } | 
|---|
| 762 |  | 
|---|
| 763 | void | 
|---|
| 764 | print_file_data_base (void) | 
|---|
| 765 | { | 
|---|
| 766 | puts (_("\n# Files")); | 
|---|
| 767 |  | 
|---|
| 768 | hash_map (&files, print_file); | 
|---|
| 769 |  | 
|---|
| 770 | fputs (_("\n# files hash-table stats:\n# "), stdout); | 
|---|
| 771 | hash_print_stats (&files, stdout); | 
|---|
| 772 | } | 
|---|
| 773 |  | 
|---|
| 774 | #define EXPANSION_INCREMENT(_l)  ((((_l) / 500) + 1) * 500) | 
|---|
| 775 |  | 
|---|
| 776 | char * | 
|---|
| 777 | build_target_list (char *value) | 
|---|
| 778 | { | 
|---|
| 779 | static unsigned long last_targ_count = 0; | 
|---|
| 780 |  | 
|---|
| 781 | if (files.ht_fill != last_targ_count) | 
|---|
| 782 | { | 
|---|
| 783 | unsigned long max = EXPANSION_INCREMENT (strlen (value)); | 
|---|
| 784 | unsigned long len; | 
|---|
| 785 | char *p; | 
|---|
| 786 | struct file **fp = (struct file **) files.ht_vec; | 
|---|
| 787 | struct file **end = &fp[files.ht_size]; | 
|---|
| 788 |  | 
|---|
| 789 | /* Make sure we have at least MAX bytes in the allocated buffer.  */ | 
|---|
| 790 | value = xrealloc (value, max); | 
|---|
| 791 |  | 
|---|
| 792 | p = value; | 
|---|
| 793 | len = 0; | 
|---|
| 794 | for (; fp < end; ++fp) | 
|---|
| 795 | if (!HASH_VACANT (*fp) && (*fp)->is_target) | 
|---|
| 796 | { | 
|---|
| 797 | struct file *f = *fp; | 
|---|
| 798 | int l = strlen (f->name); | 
|---|
| 799 |  | 
|---|
| 800 | len += l + 1; | 
|---|
| 801 | if (len > max) | 
|---|
| 802 | { | 
|---|
| 803 | unsigned long off = p - value; | 
|---|
| 804 |  | 
|---|
| 805 | max += EXPANSION_INCREMENT (l + 1); | 
|---|
| 806 | value = xrealloc (value, max); | 
|---|
| 807 | p = &value[off]; | 
|---|
| 808 | } | 
|---|
| 809 |  | 
|---|
| 810 | bcopy (f->name, p, l); | 
|---|
| 811 | p += l; | 
|---|
| 812 | *(p++) = ' '; | 
|---|
| 813 | } | 
|---|
| 814 | *(p-1) = '\0'; | 
|---|
| 815 |  | 
|---|
| 816 | last_targ_count = files.ht_fill; | 
|---|
| 817 | } | 
|---|
| 818 |  | 
|---|
| 819 | return value; | 
|---|
| 820 | } | 
|---|
| 821 |  | 
|---|
| 822 | void | 
|---|
| 823 | init_hash_files (void) | 
|---|
| 824 | { | 
|---|
| 825 | hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp); | 
|---|
| 826 | } | 
|---|
| 827 |  | 
|---|
| 828 | /* EOF */ | 
|---|