Print this page
make: translate using gettext, rather than the unmaintainable catgets
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/parallel.cc
+++ new/usr/src/cmd/make/bin/parallel.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * parallel.cc
29 29 *
30 30 * Deal with the parallel processing
31 31 */
32 32
33 33 /*
34 34 * Included files
35 35 */
36 36 #include <errno.h> /* errno */
37 37 #include <fcntl.h>
38 38 #include <mk/defs.h>
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
39 39 #include <mksh/dosys.h> /* redirect_io() */
40 40 #include <mksh/macro.h> /* expand_value() */
41 41 #include <mksh/misc.h> /* getmem() */
42 42 #include <sys/signal.h>
43 43 #include <sys/stat.h>
44 44 #include <sys/types.h>
45 45 #include <sys/utsname.h>
46 46 #include <sys/wait.h>
47 47 #include <unistd.h>
48 48 #include <netdb.h>
49 +#include <libintl.h>
49 50
50 51
51 52
52 53 /*
53 54 * Defined macros
54 55 */
55 56 #define MAXRULES 100
56 57
57 58 /*
58 59 * This const should be in avo_dms/include/AvoDmakeCommand.h
59 60 */
60 61 const int local_host_mask = 0x20;
61 62
62 63
63 64 /*
64 65 * typedefs & structs
65 66 */
66 67
67 68
68 69 /*
69 70 * Static variables
70 71 */
71 72 static Boolean just_did_subtree = false;
72 73 static char local_host[MAXNAMELEN] = "";
73 74 static char user_name[MAXNAMELEN] = "";
74 75 static int pmake_max_jobs = 0;
75 76 static pid_t process_running = -1;
76 77 static Running *running_tail = &running_list;
77 78 static Name subtree_conflict;
78 79 static Name subtree_conflict2;
79 80
80 81
81 82 /*
82 83 * File table of contents
83 84 */
84 85 static void delete_running_struct(Running rp);
85 86 static Boolean dependency_conflict(Name target);
86 87 static Doname distribute_process(char **commands, Property line);
87 88 static void doname_subtree(Name target, Boolean do_get, Boolean implicit);
88 89 static void dump_out_file(char *filename, Boolean err);
89 90 static void finish_doname(Running rp);
90 91 static void maybe_reread_make_state(void);
91 92 static void process_next(void);
92 93 static void reset_conditionals(int cnt, Name *targets, Property *locals);
93 94 static pid_t run_rule_commands(char *host, char **commands);
94 95 static Property *set_conditionals(int cnt, Name *targets);
95 96 static void store_conditionals(Running rp);
96 97
97 98
98 99 /*
99 100 * execute_parallel(line, waitflg)
100 101 *
101 102 * DMake 2.x:
102 103 * parallel mode: spawns a parallel process to execute the command group.
103 104 *
104 105 * Return value:
105 106 * The result of the execution
106 107 *
107 108 * Parameters:
108 109 * line The command group to execute
109 110 */
110 111 Doname
111 112 execute_parallel(Property line, Boolean waitflg, Boolean local)
112 113 {
113 114 int argcnt;
114 115 int cmd_options = 0;
115 116 char *commands[MAXRULES + 5];
116 117 char *cp;
117 118 Name dmake_name;
118 119 Name dmake_value;
119 120 int ignore;
120 121 Name make_machines_name;
121 122 char **p;
122 123 Property prop;
123 124 Doname result = build_ok;
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
124 125 Cmd_line rule;
125 126 Boolean silent_flag;
126 127 Name target = line->body.line.target;
127 128 Boolean wrote_state_file = false;
128 129
129 130 if ((pmake_max_jobs == 0) &&
130 131 (dmake_mode_type == parallel_mode)) {
131 132 if (local_host[0] == '\0') {
132 133 (void) gethostname(local_host, MAXNAMELEN);
133 134 }
134 - MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
135 + MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
135 136 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
136 137 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
137 138 ((dmake_value = prop->body.macro.value) != NULL)) {
138 139 pmake_max_jobs = atoi(dmake_value->string_mb);
139 140 if (pmake_max_jobs <= 0) {
140 - warning(catgets(catd, 1, 308, "DMAKE_MAX_JOBS cannot be less than or equal to zero."));
141 - warning(catgets(catd, 1, 309, "setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
141 + warning(gettext("DMAKE_MAX_JOBS cannot be less than or equal to zero."));
142 + warning(gettext("setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
142 143 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
143 144 }
144 145 } else {
145 146 /*
146 147 * For backwards compatibility w/ PMake 1.x, when
147 148 * DMake 2.x is being run in parallel mode, DMake
148 149 * should parse the PMake startup file
149 150 * $(HOME)/.make.machines to get the pmake_max_jobs.
150 151 */
151 - MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
152 + MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
152 153 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
153 154 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
154 155 ((dmake_value = prop->body.macro.value) != NULL)) {
155 156 make_machines_name = dmake_value;
156 157 } else {
157 158 make_machines_name = NULL;
158 159 }
159 160 if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) {
160 161 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
161 162 }
162 163 }
163 164 }
164 165
165 166 if ((dmake_mode_type == serial_mode) ||
166 167 ((dmake_mode_type == parallel_mode) && (waitflg))) {
167 168 return (execute_serial(line));
168 169 }
169 170
170 171 {
171 172 p = commands;
172 173 }
173 174
174 175 argcnt = 0;
175 176 for (rule = line->body.line.command_used;
176 177 rule != NULL;
177 178 rule = rule->next) {
178 179 if (posix && (touch || quest) && !rule->always_exec) {
179 180 continue;
180 181 }
181 182 if (vpath_defined) {
182 183 rule->command_line =
183 184 vpath_translation(rule->command_line);
184 185 }
185 186
186 187 silent_flag = false;
187 188 ignore = 0;
188 189
189 190 if (rule->command_line->hash.length > 0) {
190 191 if (++argcnt == MAXRULES) {
191 192 return build_serial;
192 193 }
193 194 {
194 195 if (rule->silent && !silent) {
195 196 silent_flag = true;
196 197 }
197 198 if (rule->ignore_error) {
198 199 ignore++;
199 200 }
200 201 /* XXX - need to add support for + prefix */
201 202 if (silent_flag || ignore) {
202 203 *p = getmem((silent_flag ? 1 : 0) +
203 204 ignore +
204 205 (strlen(rule->
205 206 command_line->
206 207 string_mb)) +
207 208 1);
208 209 cp = *p++;
209 210 if (silent_flag) {
210 211 *cp++ = (int) at_char;
211 212 }
212 213 if (ignore) {
213 214 *cp++ = (int) hyphen_char;
214 215 }
215 216 (void) strcpy(cp, rule->command_line->string_mb);
216 217 } else {
217 218 *p++ = rule->command_line->string_mb;
218 219 }
219 220 }
220 221 }
221 222 }
222 223 if ((argcnt == 0) ||
223 224 (report_dependencies_level > 0)) {
224 225 return build_ok;
225 226 }
226 227 {
227 228 *p = NULL;
228 229
229 230 Doname res = distribute_process(commands, line);
230 231 if (res == build_running) {
231 232 parallel_process_cnt++;
232 233 }
233 234
234 235 /*
235 236 * Return only those memory that were specially allocated
236 237 * for part of commands.
237 238 */
238 239 for (int i = 0; commands[i] != NULL; i++) {
239 240 if ((commands[i][0] == (int) at_char) ||
240 241 (commands[i][0] == (int) hyphen_char)) {
241 242 retmem_mb(commands[i]);
242 243 }
243 244 }
244 245 return res;
245 246 }
246 247 }
247 248
248 249
249 250 #define MAXJOBS_ADJUST_RFE4694000
250 251
251 252 #ifdef MAXJOBS_ADJUST_RFE4694000
252 253
253 254 #include <unistd.h> /* sysconf(_SC_NPROCESSORS_ONLN) */
254 255 #include <sys/ipc.h> /* ftok() */
255 256 #include <sys/shm.h> /* shmget(), shmat(), shmdt(), shmctl() */
256 257 #include <semaphore.h> /* sem_init(), sem_trywait(), sem_post(), sem_destroy() */
257 258 #include <sys/loadavg.h> /* getloadavg() */
258 259
259 260 /*
260 261 * adjust_pmake_max_jobs (int pmake_max_jobs)
261 262 *
262 263 * Parameters:
263 264 * pmake_max_jobs - max jobs limit set by user
264 265 *
265 266 * External functions used:
266 267 * sysconf()
267 268 * getloadavg()
268 269 */
269 270 static int
270 271 adjust_pmake_max_jobs (int pmake_max_jobs)
271 272 {
272 273 static int ncpu = 0;
273 274 double loadavg[3];
274 275 int adjustment;
275 276 int adjusted_max_jobs;
276 277
277 278 if (ncpu <= 0) {
278 279 if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) {
279 280 ncpu = 1;
280 281 }
281 282 }
282 283 if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs);
283 284 adjustment = ((int)loadavg[LOADAVG_1MIN]);
284 285 if (adjustment < 2) return(pmake_max_jobs);
285 286 if (ncpu > 1) {
286 287 adjustment = adjustment / ncpu;
287 288 }
288 289 adjusted_max_jobs = pmake_max_jobs - adjustment;
289 290 if (adjusted_max_jobs < 1) adjusted_max_jobs = 1;
290 291 return(adjusted_max_jobs);
291 292 }
292 293
293 294 /*
294 295 * M2 adjust mode data and functions
295 296 *
296 297 * m2_init() - initializes M2 shared semaphore
297 298 * m2_acquire_job() - decrements M2 semaphore counter
298 299 * m2_release_job() - increments M2 semaphore counter
299 300 * m2_fini() - destroys M2 semaphore and shared memory*
300 301 *
301 302 * Environment variables:
302 303 * __DMAKE_M2_FILE__
303 304 *
304 305 * External functions:
305 306 * ftok(), shmget(), shmat(), shmdt(), shmctl()
306 307 * sem_init(), sem_trywait(), sem_post(), sem_destroy()
307 308 * creat(), close(), unlink()
308 309 * getenv(), putenv()
309 310 *
310 311 * Static variables:
311 312 * m2_file - tmp file name to create ipc key for shared memory
312 313 * m2_shm_id - shared memory id
313 314 * m2_shm_sem - shared memory semaphore
314 315 */
↓ open down ↓ |
153 lines elided |
↑ open up ↑ |
315 316
316 317 static char m2_file[MAXPATHLEN];
317 318 static int m2_shm_id = -1;
318 319 static sem_t* m2_shm_sem = 0;
319 320
320 321 static int
321 322 m2_init() {
322 323 char *var;
323 324 key_t key;
324 325
325 - if ((var = getenv(NOCATGETS("__DMAKE_M2_FILE__"))) == 0) {
326 + if ((var = getenv("__DMAKE_M2_FILE__")) == 0) {
326 327 /* compose tmp file name */
327 - sprintf(m2_file, NOCATGETS("%s/dmake.m2.%d.XXXXXX"), tmpdir, getpid());
328 + sprintf(m2_file, "%s/dmake.m2.%d.XXXXXX", tmpdir, getpid());
328 329
329 330 /* create tmp file */
330 331 int fd = mkstemp(m2_file);
331 332 if (fd < 0) {
332 333 return -1;
333 334 } else {
334 335 close(fd);
335 336 }
336 337 } else {
337 338 /* using existing semaphore */
338 339 strcpy(m2_file, var);
339 340 }
340 341
341 342 /* combine IPC key */
342 343 if ((key = ftok(m2_file, 38)) == (key_t) -1) {
343 344 return -1;
344 345 }
345 346
346 347 /* create shared memory */
347 348 if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) {
348 349 return -1;
349 350 }
350 351
351 352 /* attach shared memory */
352 353 if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) {
353 354 return -1;
354 355 }
355 356
356 357 /* root process */
357 358 if (var == 0) {
358 359 /* initialize semaphore */
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
359 360 if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) {
360 361 return -1;
361 362 }
362 363
363 364 /* alloc memory for env variable */
364 365 if ((var = (char*) malloc(MAXPATHLEN)) == 0) {
365 366 return -1;
366 367 }
367 368
368 369 /* put key to env */
369 - sprintf(var, NOCATGETS("__DMAKE_M2_FILE__=%s"), m2_file);
370 + sprintf(var, "__DMAKE_M2_FILE__=%s", m2_file);
370 371 if (putenv(var)) {
371 372 return -1;
372 373 }
373 374 }
374 375 return 0;
375 376 }
376 377
377 378 static void
378 379 m2_fini() {
379 380 if (m2_shm_id >= 0) {
380 381 struct shmid_ds stat;
381 382
382 383 /* determine the number of attached processes */
383 384 if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) {
384 385 if (stat.shm_nattch <= 1) {
385 386 /* destroy semaphore */
386 387 if (m2_shm_sem != 0) {
387 388 (void) sem_destroy(m2_shm_sem);
388 389 }
389 390
390 391 /* destroy shared memory */
391 392 (void) shmctl(m2_shm_id, IPC_RMID, &stat);
392 393
393 394 /* remove tmp file created for the key */
394 395 (void) unlink(m2_file);
395 396 } else {
396 397 /* detach shared memory */
397 398 if (m2_shm_sem != 0) {
398 399 (void) shmdt((char*) m2_shm_sem);
399 400 }
400 401 }
401 402 }
402 403
403 404 m2_shm_id = -1;
404 405 m2_shm_sem = 0;
405 406 }
406 407 }
407 408
408 409 static int
409 410 m2_acquire_job() {
410 411 if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
411 412 if (sem_trywait(m2_shm_sem) == 0) {
412 413 return 1;
413 414 }
414 415 if (errno == EAGAIN) {
415 416 return 0;
416 417 }
417 418 }
418 419 return -1;
419 420 }
420 421
421 422 static int
422 423 m2_release_job() {
423 424 if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
424 425 if (sem_post(m2_shm_sem) == 0) {
425 426 return 0;
426 427 }
427 428 }
428 429 return -1;
429 430 }
430 431
431 432 /*
432 433 * job adjust mode
433 434 *
434 435 * Possible values:
435 436 * ADJUST_M1 - adjustment by system load (default)
436 437 * ADJUST_M2 - fixed limit of jobs for the group of nested dmakes
437 438 * ADJUST_NONE - no adjustment - fixed limit of jobs for the current dmake
438 439 */
439 440 static enum {
440 441 ADJUST_UNKNOWN,
441 442 ADJUST_M1,
442 443 ADJUST_M2,
443 444 ADJUST_NONE
444 445 } job_adjust_mode = ADJUST_UNKNOWN;
445 446
446 447 /*
447 448 * void job_adjust_fini()
448 449 *
449 450 * Description:
450 451 * Cleans up job adjust data.
451 452 *
452 453 * Static variables:
453 454 * job_adjust_mode Current job adjust mode
454 455 */
455 456 void
456 457 job_adjust_fini() {
457 458 if (job_adjust_mode == ADJUST_M2) {
458 459 m2_fini();
459 460 }
460 461 }
461 462
462 463 /*
463 464 * void job_adjust_error()
464 465 *
465 466 * Description:
466 467 * Prints warning message, cleans up job adjust data, and disables job adjustment
467 468 *
468 469 * Environment:
469 470 * DMAKE_ADJUST_MAX_JOBS
470 471 *
471 472 * External functions:
472 473 * putenv()
473 474 *
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
474 475 * Static variables:
475 476 * job_adjust_mode Current job adjust mode
476 477 */
477 478 static void
478 479 job_adjust_error() {
479 480 if (job_adjust_mode != ADJUST_NONE) {
480 481 /* cleanup internals */
481 482 job_adjust_fini();
482 483
483 484 /* warning message for the user */
484 - warning(catgets(catd, 1, 339, "Encountered max jobs auto adjustment error - disabling auto adjustment."));
485 + warning(gettext("Encountered max jobs auto adjustment error - disabling auto adjustment."));
485 486
486 487 /* switch off job adjustment for the children */
487 - putenv(strdup(NOCATGETS("DMAKE_ADJUST_MAX_JOBS=NO")));
488 + putenv(strdup("DMAKE_ADJUST_MAX_JOBS=NO"));
488 489
489 490 /* and for this dmake */
490 491 job_adjust_mode = ADJUST_NONE;
491 492 }
492 493 }
493 494
494 495 /*
495 496 * void job_adjust_init()
496 497 *
497 498 * Description:
498 499 * Parses DMAKE_ADJUST_MAX_JOBS env variable
499 500 * and performs appropriate initializations.
500 501 *
501 502 * Environment:
502 503 * DMAKE_ADJUST_MAX_JOBS
503 504 * DMAKE_ADJUST_MAX_JOBS == "NO" - no adjustment
504 505 * DMAKE_ADJUST_MAX_JOBS == "M2" - M2 adjust mode
505 506 * other - M1 adjust mode
506 507 *
507 508 * External functions:
508 509 * getenv()
509 510 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
510 511 * Static variables:
511 512 * job_adjust_mode Current job adjust mode
512 513 */
513 514 static void
514 515 job_adjust_init() {
515 516 if (job_adjust_mode == ADJUST_UNKNOWN) {
516 517 /* default mode */
517 518 job_adjust_mode = ADJUST_M1;
518 519
519 520 /* determine adjust mode */
520 - if (char *var = getenv(NOCATGETS("DMAKE_ADJUST_MAX_JOBS"))) {
521 - if (strcasecmp(var, NOCATGETS("NO")) == 0) {
521 + if (char *var = getenv("DMAKE_ADJUST_MAX_JOBS")) {
522 + if (strcasecmp(var, "NO") == 0) {
522 523 job_adjust_mode = ADJUST_NONE;
523 - } else if (strcasecmp(var, NOCATGETS("M2")) == 0) {
524 + } else if (strcasecmp(var, "M2") == 0) {
524 525 job_adjust_mode = ADJUST_M2;
525 526 }
526 527 }
527 528
528 529 /* M2 specific initialization */
529 530 if (job_adjust_mode == ADJUST_M2) {
530 531 if (m2_init()) {
531 532 job_adjust_error();
532 533 }
533 534 }
534 535 }
535 536 }
536 537
537 538 #endif /* MAXJOBS_ADJUST_RFE4694000 */
538 539
539 540 /*
540 541 * distribute_process(char **commands, Property line)
541 542 *
542 543 * Parameters:
543 544 * commands argv vector of commands to execute
544 545 *
545 546 * Return value:
546 547 * The result of the execution
547 548 *
548 549 * Static variables used:
549 550 * process_running Set to the pid of the process set running
550 551 * #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
551 552 * job_adjust_mode Current job adjust mode
552 553 * #endif
553 554 */
554 555 static Doname
555 556 distribute_process(char **commands, Property line)
556 557 {
557 558 static unsigned file_number = 0;
558 559 wchar_t string[MAXPATHLEN];
559 560 char mbstring[MAXPATHLEN];
560 561 int filed;
561 562 int res;
562 563 int tmp_index;
563 564 char *tmp_index_str_ptr;
564 565
565 566 #if !defined (TEAMWARE_MAKE_CMN) || !defined (MAXJOBS_ADJUST_RFE4694000)
566 567 while (parallel_process_cnt >= pmake_max_jobs) {
567 568 await_parallel(false);
568 569 finish_children(true);
569 570 }
570 571 #else /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */
571 572 /* initialize adjust mode, if not initialized */
572 573 if (job_adjust_mode == ADJUST_UNKNOWN) {
573 574 job_adjust_init();
574 575 }
575 576
576 577 /* actions depend on adjust mode */
577 578 switch (job_adjust_mode) {
578 579 case ADJUST_M1:
579 580 while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) {
580 581 await_parallel(false);
581 582 finish_children(true);
582 583 }
583 584 break;
584 585 case ADJUST_M2:
585 586 if ((res = m2_acquire_job()) == 0) {
586 587 if (parallel_process_cnt > 0) {
587 588 await_parallel(false);
588 589 finish_children(true);
589 590
590 591 if ((res = m2_acquire_job()) == 0) {
591 592 return build_serial;
592 593 }
593 594 } else {
594 595 return build_serial;
595 596 }
596 597 }
597 598 if (res < 0) {
598 599 /* job adjustment error */
599 600 job_adjust_error();
600 601
601 602 /* no adjustment */
602 603 while (parallel_process_cnt >= pmake_max_jobs) {
603 604 await_parallel(false);
604 605 finish_children(true);
605 606 }
606 607 }
607 608 break;
608 609 default:
609 610 while (parallel_process_cnt >= pmake_max_jobs) {
610 611 await_parallel(false);
611 612 finish_children(true);
612 613 }
613 614 }
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
614 615 #endif /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */
615 616 setvar_envvar();
616 617 /*
617 618 * Tell the user what DMake is doing.
618 619 */
619 620 if (!silent && output_mode != txt2_mode) {
620 621 /*
621 622 * Print local_host --> x job(s).
622 623 */
623 624 (void) fprintf(stdout,
624 - catgets(catd, 1, 325, "%s --> %d %s\n"),
625 + gettext("%s --> %d %s\n"),
625 626 local_host,
626 627 parallel_process_cnt + 1,
627 - (parallel_process_cnt == 0) ? catgets(catd, 1, 124, "job") : catgets(catd, 1, 125, "jobs"));
628 + (parallel_process_cnt == 0) ? gettext("job") : gettext("jobs"));
628 629
629 630 /* Print command line(s). */
630 631 tmp_index = 0;
631 632 while (commands[tmp_index] != NULL) {
632 633 /* No @ char. */
633 634 /* XXX - need to add [2] when + prefix is added */
634 635 if ((commands[tmp_index][0] != (int) at_char) &&
635 636 (commands[tmp_index][1] != (int) at_char)) {
636 637 tmp_index_str_ptr = commands[tmp_index];
637 638 if (*tmp_index_str_ptr == (int) hyphen_char) {
638 639 tmp_index_str_ptr++;
639 640 }
640 641 (void) fprintf(stdout, "%s\n", tmp_index_str_ptr);
641 642 }
642 643 tmp_index++;
643 644 }
644 645 (void) fflush(stdout);
645 646 }
646 647
647 648 (void) sprintf(mbstring,
648 - NOCATGETS("%s/dmake.stdout.%d.%d.XXXXXX"),
649 + "%s/dmake.stdout.%d.%d.XXXXXX",
649 650 tmpdir,
650 651 getpid(),
651 652 file_number++);
652 653
653 654 mktemp(mbstring);
654 655
655 656 stdout_file = strdup(mbstring);
656 657 stderr_file = NULL;
657 658
658 659 if (!out_err_same) {
659 660 (void) sprintf(mbstring,
660 - NOCATGETS("%s/dmake.stderr.%d.%d.XXXXXX"),
661 + "%s/dmake.stderr.%d.%d.XXXXXX",
661 662 tmpdir,
662 663 getpid(),
663 664 file_number++);
664 665
665 666 mktemp(mbstring);
666 667
667 668 stderr_file = strdup(mbstring);
668 669 }
669 670
670 671 process_running = run_rule_commands(local_host, commands);
671 672
672 673 return build_running;
673 674 }
674 675
675 676 /*
676 677 * doname_parallel(target, do_get, implicit)
677 678 *
678 679 * Processes the given target and finishes up any parallel
679 680 * processes left running.
680 681 *
681 682 * Return value:
682 683 * Result of target build
683 684 *
684 685 * Parameters:
685 686 * target Target to build
686 687 * do_get True if sccs get to be done
687 688 * implicit True if this is an implicit target
688 689 */
689 690 Doname
690 691 doname_parallel(Name target, Boolean do_get, Boolean implicit)
691 692 {
692 693 Doname result;
693 694
694 695 result = doname_check(target, do_get, implicit, false);
695 696 if (result == build_ok || result == build_failed) {
696 697 return result;
697 698 }
698 699 finish_running();
699 700 return (Doname) target->state;
700 701 }
701 702
702 703 /*
703 704 * doname_subtree(target, do_get, implicit)
704 705 *
705 706 * Completely computes an object and its dependents for a
706 707 * serial subtree build.
707 708 *
708 709 * Parameters:
709 710 * target Target to build
710 711 * do_get True if sccs get to be done
711 712 * implicit True if this is an implicit target
712 713 *
713 714 * Static variables used:
714 715 * running_tail Tail of the list of running processes
715 716 *
716 717 * Global variables used:
717 718 * running_list The list of running processes
718 719 */
719 720 static void
720 721 doname_subtree(Name target, Boolean do_get, Boolean implicit)
721 722 {
722 723 Running save_running_list;
723 724 Running *save_running_tail;
724 725
725 726 save_running_list = running_list;
726 727 save_running_tail = running_tail;
727 728 running_list = NULL;
728 729 running_tail = &running_list;
729 730 target->state = build_subtree;
730 731 target->checking_subtree = true;
731 732 while(doname_check(target, do_get, implicit, false) == build_running) {
732 733 target->checking_subtree = false;
733 734 finish_running();
734 735 target->state = build_subtree;
735 736 }
736 737 target->checking_subtree = false;
737 738 running_list = save_running_list;
738 739 running_tail = save_running_tail;
739 740 }
740 741
741 742 /*
742 743 * finish_running()
743 744 *
744 745 * Keeps processing until the running_list is emptied out.
745 746 *
746 747 * Parameters:
747 748 *
748 749 * Global variables used:
749 750 * running_list The list of running processes
750 751 */
751 752 void
752 753 finish_running(void)
753 754 {
754 755 while (running_list != NULL) {
755 756 {
756 757 await_parallel(false);
757 758 finish_children(true);
758 759 }
759 760 if (running_list != NULL) {
760 761 process_next();
761 762 }
762 763 }
763 764 }
764 765
765 766 /*
766 767 * process_next()
767 768 *
768 769 * Searches the running list for any targets which can start processing.
769 770 * This can be a pending target, a serial target, or a subtree target.
770 771 *
771 772 * Parameters:
772 773 *
773 774 * Static variables used:
774 775 * running_tail The end of the list of running procs
775 776 * subtree_conflict A target which conflicts with a subtree
776 777 * subtree_conflict2 The other target which conflicts
777 778 *
778 779 * Global variables used:
779 780 * commands_done True if commands executed
780 781 * debug_level Controls debug output
781 782 * parallel_process_cnt Number of parallel process running
782 783 * recursion_level Indentation for debug output
783 784 * running_list List of running processes
784 785 */
785 786 static void
786 787 process_next(void)
787 788 {
788 789 Running rp;
789 790 Running *rp_prev;
790 791 Property line;
791 792 Chain target_group;
792 793 Dependency dep;
793 794 Boolean quiescent = true;
794 795 Running *subtree_target;
795 796 Boolean saved_commands_done;
796 797 Property *conditionals;
797 798
798 799 subtree_target = NULL;
799 800 subtree_conflict = NULL;
800 801 subtree_conflict2 = NULL;
801 802 /*
802 803 * If nothing currently running, build a serial target, if any.
803 804 */
804 805 start_loop_1:
805 806 for (rp_prev = &running_list, rp = running_list;
806 807 rp != NULL && parallel_process_cnt == 0;
807 808 rp = rp->next) {
808 809 if (rp->state == build_serial) {
809 810 *rp_prev = rp->next;
810 811 if (rp->next == NULL) {
811 812 running_tail = rp_prev;
812 813 }
813 814 recursion_level = rp->recursion_level;
814 815 rp->target->state = build_pending;
815 816 (void) doname_check(rp->target,
816 817 rp->do_get,
817 818 rp->implicit,
818 819 false);
819 820 quiescent = false;
820 821 delete_running_struct(rp);
821 822 goto start_loop_1;
822 823 } else {
823 824 rp_prev = &rp->next;
824 825 }
825 826 }
826 827 /*
827 828 * Find a target to build. The target must be pending, have all
828 829 * its dependencies built, and not be in a target group with a target
829 830 * currently building.
830 831 */
831 832 start_loop_2:
832 833 for (rp_prev = &running_list, rp = running_list;
833 834 rp != NULL;
834 835 rp = rp->next) {
835 836 if (!(rp->state == build_pending ||
836 837 rp->state == build_subtree)) {
837 838 quiescent = false;
838 839 rp_prev = &rp->next;
839 840 } else if (rp->state == build_pending) {
840 841 line = get_prop(rp->target->prop, line_prop);
841 842 for (dep = line->body.line.dependencies;
842 843 dep != NULL;
843 844 dep = dep->next) {
844 845 if (dep->name->state == build_running ||
845 846 dep->name->state == build_pending ||
846 847 dep->name->state == build_serial) {
847 848 break;
848 849 }
849 850 }
850 851 if (dep == NULL) {
851 852 for (target_group = line->body.line.target_group;
852 853 target_group != NULL;
853 854 target_group = target_group->next) {
854 855 if (is_running(target_group->name)) {
855 856 break;
856 857 }
857 858 }
858 859 if (target_group == NULL) {
859 860 *rp_prev = rp->next;
860 861 if (rp->next == NULL) {
861 862 running_tail = rp_prev;
862 863 }
863 864 recursion_level = rp->recursion_level;
864 865 rp->target->state = rp->redo ?
865 866 build_dont_know : build_pending;
866 867 saved_commands_done = commands_done;
867 868 conditionals =
868 869 set_conditionals
869 870 (rp->conditional_cnt,
870 871 rp->conditional_targets);
871 872 rp->target->dont_activate_cond_values = true;
872 873 if ((doname_check(rp->target,
873 874 rp->do_get,
874 875 rp->implicit,
875 876 rp->target->has_target_prop ? true : false) !=
876 877 build_running) &&
877 878 !commands_done) {
878 879 commands_done =
879 880 saved_commands_done;
880 881 }
881 882 rp->target->dont_activate_cond_values = false;
882 883 reset_conditionals
883 884 (rp->conditional_cnt,
884 885 rp->conditional_targets,
885 886 conditionals);
886 887 quiescent = false;
887 888 delete_running_struct(rp);
888 889 goto start_loop_2;
889 890 } else {
890 891 rp_prev = &rp->next;
891 892 }
892 893 } else {
893 894 rp_prev = &rp->next;
894 895 }
895 896 } else {
896 897 rp_prev = &rp->next;
897 898 }
898 899 }
899 900 /*
900 901 * If nothing has been found to build and there exists a subtree
901 902 * target with no dependency conflicts, build it.
902 903 */
903 904 if (quiescent) {
904 905 start_loop_3:
905 906 for (rp_prev = &running_list, rp = running_list;
906 907 rp != NULL;
907 908 rp = rp->next) {
908 909 if (rp->state == build_subtree) {
909 910 if (!dependency_conflict(rp->target)) {
910 911 *rp_prev = rp->next;
911 912 if (rp->next == NULL) {
912 913 running_tail = rp_prev;
913 914 }
914 915 recursion_level = rp->recursion_level;
915 916 doname_subtree(rp->target,
916 917 rp->do_get,
917 918 rp->implicit);
918 919 quiescent = false;
919 920 delete_running_struct(rp);
920 921 goto start_loop_3;
921 922 } else {
922 923 subtree_target = rp_prev;
923 924 rp_prev = &rp->next;
924 925 }
925 926 } else {
926 927 rp_prev = &rp->next;
↓ open down ↓ |
256 lines elided |
↑ open up ↑ |
927 928 }
928 929 }
929 930 }
930 931 /*
931 932 * If still nothing found to build, we either have a deadlock
932 933 * or a subtree with a dependency conflict with something waiting
933 934 * to build.
934 935 */
935 936 if (quiescent) {
936 937 if (subtree_target == NULL) {
937 - fatal(catgets(catd, 1, 126, "Internal error: deadlock detected in process_next"));
938 + fatal(gettext("Internal error: deadlock detected in process_next"));
938 939 } else {
939 940 rp = *subtree_target;
940 941 if (debug_level > 0) {
941 - warning(catgets(catd, 1, 127, "Conditional macro conflict encountered for %s between %s and %s"),
942 + warning(gettext("Conditional macro conflict encountered for %s between %s and %s"),
942 943 subtree_conflict2->string_mb,
943 944 rp->target->string_mb,
944 945 subtree_conflict->string_mb);
945 946 }
946 947 *subtree_target = (*subtree_target)->next;
947 948 if (rp->next == NULL) {
948 949 running_tail = subtree_target;
949 950 }
950 951 recursion_level = rp->recursion_level;
951 952 doname_subtree(rp->target, rp->do_get, rp->implicit);
952 953 delete_running_struct(rp);
953 954 }
954 955 }
955 956 }
956 957
957 958 /*
958 959 * set_conditionals(cnt, targets)
959 960 *
960 961 * Sets the conditional macros for the targets given in the array of
961 962 * targets. The old macro values are returned in an array of
962 963 * Properties for later resetting.
963 964 *
964 965 * Return value:
965 966 * Array of conditional macro settings
966 967 *
967 968 * Parameters:
968 969 * cnt Number of targets
969 970 * targets Array of targets
970 971 */
971 972 static Property *
972 973 set_conditionals(int cnt, Name *targets)
973 974 {
974 975 Property *locals, *lp;
975 976 Name *tp;
976 977
977 978 locals = (Property *) getmem(cnt * sizeof(Property));
978 979 for (lp = locals, tp = targets;
979 980 cnt > 0;
980 981 cnt--, lp++, tp++) {
981 982 *lp = (Property) getmem((*tp)->conditional_cnt *
982 983 sizeof(struct _Property));
983 984 set_locals(*tp, *lp);
984 985 }
985 986 return locals;
986 987 }
987 988
988 989 /*
989 990 * reset_conditionals(cnt, targets, locals)
990 991 *
991 992 * Resets the conditional macros as saved in the given array of
992 993 * Properties. The resets are done in reverse order. Afterwards the
993 994 * data structures are freed.
994 995 *
995 996 * Parameters:
996 997 * cnt Number of targets
997 998 * targets Array of targets
998 999 * locals Array of dependency macro settings
999 1000 */
1000 1001 static void
1001 1002 reset_conditionals(int cnt, Name *targets, Property *locals)
1002 1003 {
1003 1004 Name *tp;
1004 1005 Property *lp;
1005 1006
1006 1007 for (tp = targets + (cnt - 1), lp = locals + (cnt - 1);
1007 1008 cnt > 0;
1008 1009 cnt--, tp--, lp--) {
1009 1010 reset_locals(*tp,
1010 1011 *lp,
1011 1012 get_prop((*tp)->prop, conditional_prop),
1012 1013 0);
1013 1014 retmem_mb((caddr_t) *lp);
1014 1015 }
1015 1016 retmem_mb((caddr_t) locals);
1016 1017 }
1017 1018
1018 1019 /*
1019 1020 * dependency_conflict(target)
1020 1021 *
1021 1022 * Returns true if there is an intersection between
1022 1023 * the subtree of the target and any dependents of the pending targets.
1023 1024 *
1024 1025 * Return value:
1025 1026 * True if conflict found
1026 1027 *
1027 1028 * Parameters:
1028 1029 * target Subtree target to check
1029 1030 *
1030 1031 * Static variables used:
1031 1032 * subtree_conflict Target conflict found
1032 1033 * subtree_conflict2 Second conflict found
1033 1034 *
1034 1035 * Global variables used:
1035 1036 * running_list List of running processes
1036 1037 * wait_name .WAIT, not a real dependency
1037 1038 */
1038 1039 static Boolean
1039 1040 dependency_conflict(Name target)
1040 1041 {
1041 1042 Property line;
1042 1043 Property pending_line;
1043 1044 Dependency dp;
1044 1045 Dependency pending_dp;
1045 1046 Running rp;
1046 1047
1047 1048 /* Return if we are already checking this target */
1048 1049 if (target->checking_subtree) {
1049 1050 return false;
1050 1051 }
1051 1052 target->checking_subtree = true;
1052 1053 line = get_prop(target->prop, line_prop);
1053 1054 if (line == NULL) {
1054 1055 target->checking_subtree = false;
1055 1056 return false;
1056 1057 }
1057 1058 /* Check each dependency of the target for conflicts */
1058 1059 for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
1059 1060 /* Ignore .WAIT dependency */
1060 1061 if (dp->name == wait_name) {
1061 1062 continue;
1062 1063 }
1063 1064 /*
1064 1065 * For each pending target, look for a dependency which
1065 1066 * is the same as a dependency of the subtree target. Since
1066 1067 * we can't build the subtree until all pending targets have
1067 1068 * finished which depend on the same dependency, this is
1068 1069 * a conflict.
1069 1070 */
1070 1071 for (rp = running_list; rp != NULL; rp = rp->next) {
1071 1072 if (rp->state == build_pending) {
1072 1073 pending_line = get_prop(rp->target->prop,
1073 1074 line_prop);
1074 1075 if (pending_line == NULL) {
1075 1076 continue;
1076 1077 }
1077 1078 for(pending_dp = pending_line->
1078 1079 body.line.dependencies;
1079 1080 pending_dp != NULL;
1080 1081 pending_dp = pending_dp->next) {
1081 1082 if (dp->name == pending_dp->name) {
1082 1083 target->checking_subtree
1083 1084 = false;
1084 1085 subtree_conflict = rp->target;
1085 1086 subtree_conflict2 = dp->name;
1086 1087 return true;
1087 1088 }
1088 1089 }
1089 1090 }
1090 1091 }
1091 1092 if (dependency_conflict(dp->name)) {
1092 1093 target->checking_subtree = false;
1093 1094 return true;
1094 1095 }
1095 1096 }
1096 1097 target->checking_subtree = false;
1097 1098 return false;
1098 1099 }
1099 1100
1100 1101 /*
1101 1102 * await_parallel(waitflg)
1102 1103 *
1103 1104 * Waits for parallel children to exit and finishes their processing.
1104 1105 * If waitflg is false, the function returns after update_delay.
1105 1106 *
1106 1107 * Parameters:
1107 1108 * waitflg dwight
1108 1109 */
1109 1110 void
1110 1111 await_parallel(Boolean waitflg)
1111 1112 {
1112 1113 Boolean nohang;
1113 1114 pid_t pid;
1114 1115 int status;
1115 1116 Running rp;
1116 1117 int waiterr;
1117 1118
1118 1119 nohang = false;
1119 1120 for ( ; ; ) {
1120 1121 if (!nohang) {
1121 1122 (void) alarm((int) update_delay);
1122 1123 }
1123 1124 pid = waitpid((pid_t)-1,
1124 1125 &status,
1125 1126 nohang ? WNOHANG : 0);
1126 1127 waiterr = errno;
1127 1128 if (!nohang) {
1128 1129 (void) alarm(0);
1129 1130 }
1130 1131 if (pid <= 0) {
1131 1132 if (waiterr == EINTR) {
1132 1133 if (waitflg) {
1133 1134 continue;
1134 1135 } else {
1135 1136 return;
1136 1137 }
↓ open down ↓ |
185 lines elided |
↑ open up ↑ |
1137 1138 } else {
1138 1139 return;
1139 1140 }
1140 1141 }
1141 1142 for (rp = running_list;
1142 1143 (rp != NULL) && (rp->pid != pid);
1143 1144 rp = rp->next) {
1144 1145 ;
1145 1146 }
1146 1147 if (rp == NULL) {
1147 - fatal(catgets(catd, 1, 128, "Internal error: returned child pid not in running_list"));
1148 + fatal(gettext("Internal error: returned child pid not in running_list"));
1148 1149 } else {
1149 1150 rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed;
1150 1151 }
1151 1152 nohang = true;
1152 1153 parallel_process_cnt--;
1153 1154
1154 1155 #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
1155 1156 if (job_adjust_mode == ADJUST_M2) {
1156 1157 if (m2_release_job()) {
1157 1158 job_adjust_error();
1158 1159 }
1159 1160 }
1160 1161 #endif
1161 1162 }
1162 1163 }
1163 1164
1164 1165 /*
1165 1166 * finish_children(docheck)
1166 1167 *
1167 1168 * Finishes the processing for all targets which were running
1168 1169 * and have now completed.
1169 1170 *
1170 1171 * Parameters:
1171 1172 * docheck Completely check the finished target
1172 1173 *
1173 1174 * Static variables used:
1174 1175 * running_tail The tail of the running list
1175 1176 *
1176 1177 * Global variables used:
1177 1178 * continue_after_error -k flag
1178 1179 * fatal_in_progress True if we are finishing up after fatal err
1179 1180 * running_list List of running processes
1180 1181 */
1181 1182 void
1182 1183 finish_children(Boolean docheck)
1183 1184 {
1184 1185 int cmds_length;
1185 1186 Property line;
1186 1187 Property line2;
1187 1188 struct stat out_buf;
1188 1189 Running rp;
1189 1190 Running *rp_prev;
1190 1191 Cmd_line rule;
1191 1192 Boolean silent_flag;
1192 1193
1193 1194 for (rp_prev = &running_list, rp = running_list;
1194 1195 rp != NULL;
1195 1196 rp = rp->next) {
1196 1197 bypass_for_loop_inc_4:
1197 1198 /*
1198 1199 * If the state is ok or failed, then this target has
1199 1200 * finished building.
1200 1201 * In parallel_mode, output the accumulated stdout/stderr.
1201 1202 * Read the auto dependency stuff, handle a failed build,
1202 1203 * update the target, then finish the doname process for
1203 1204 * that target.
1204 1205 */
1205 1206 if (rp->state == build_ok || rp->state == build_failed) {
1206 1207 *rp_prev = rp->next;
1207 1208 if (rp->next == NULL) {
1208 1209 running_tail = rp_prev;
1209 1210 }
1210 1211 if ((line2 = rp->command) == NULL) {
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
1211 1212 line2 = get_prop(rp->target->prop, line_prop);
1212 1213 }
1213 1214
1214 1215
1215 1216 /*
1216 1217 * Check if there were any job output
1217 1218 * from the parallel build.
1218 1219 */
1219 1220 if (rp->stdout_file != NULL) {
1220 1221 if (stat(rp->stdout_file, &out_buf) < 0) {
1221 - fatal(catgets(catd, 1, 130, "stat of %s failed: %s"),
1222 + fatal(gettext("stat of %s failed: %s"),
1222 1223 rp->stdout_file,
1223 1224 errmsg(errno));
1224 1225 }
1225 1226
1226 1227 if ((line2 != NULL) &&
1227 1228 (out_buf.st_size > 0)) {
1228 1229 cmds_length = 0;
1229 1230 for (rule = line2->body.line.command_used,
1230 1231 silent_flag = silent;
1231 1232 rule != NULL;
1232 1233 rule = rule->next) {
1233 1234 cmds_length += rule->command_line->hash.length + 1;
1234 1235 silent_flag = BOOLEAN(silent_flag || rule->silent);
1235 1236 }
1236 1237 if (out_buf.st_size != cmds_length || silent_flag ||
1237 1238 output_mode == txt2_mode) {
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1238 1239 dump_out_file(rp->stdout_file, false);
1239 1240 }
1240 1241 }
1241 1242 (void) unlink(rp->stdout_file);
1242 1243 retmem_mb(rp->stdout_file);
1243 1244 rp->stdout_file = NULL;
1244 1245 }
1245 1246
1246 1247 if (!out_err_same && (rp->stderr_file != NULL)) {
1247 1248 if (stat(rp->stderr_file, &out_buf) < 0) {
1248 - fatal(catgets(catd, 1, 130, "stat of %s failed: %s"),
1249 + fatal(gettext("stat of %s failed: %s"),
1249 1250 rp->stderr_file,
1250 1251 errmsg(errno));
1251 1252 }
1252 1253 if ((line2 != NULL) &&
1253 1254 (out_buf.st_size > 0)) {
1254 1255 dump_out_file(rp->stderr_file, true);
1255 1256 }
1256 1257 (void) unlink(rp->stderr_file);
1257 1258 retmem_mb(rp->stderr_file);
1258 1259 rp->stderr_file = NULL;
1259 1260 }
1260 1261
1261 1262 check_state(rp->temp_file);
1262 1263 if (rp->temp_file != NULL) {
1263 1264 free_name(rp->temp_file);
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1264 1265 }
1265 1266 rp->temp_file = NULL;
1266 1267 if (rp->state == build_failed) {
1267 1268 line = get_prop(rp->target->prop, line_prop);
1268 1269 if (line != NULL) {
1269 1270 line->body.line.command_used = NULL;
1270 1271 }
1271 1272 if (continue_after_error ||
1272 1273 fatal_in_progress ||
1273 1274 !docheck) {
1274 - warning(catgets(catd, 1, 256, "Command failed for target `%s'"),
1275 + warning(gettext("Command failed for target `%s'"),
1275 1276 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1276 1277 build_failed_seen = true;
1277 1278 } else {
1278 1279 /*
1279 1280 * XXX??? - DMake needs to exit(),
1280 1281 * but shouldn't call fatal().
1281 1282 */
1282 1283 #ifdef PRINT_EXIT_STATUS
1283 - warning(NOCATGETS("I'm in finish_children. rp->state == build_failed."));
1284 + warning("I'm in finish_children. rp->state == build_failed.");
1284 1285 #endif
1285 1286
1286 - fatal(catgets(catd, 1, 258, "Command failed for target `%s'"),
1287 + fatal(gettext("Command failed for target `%s'"),
1287 1288 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1288 1289 }
1289 1290 }
1290 1291 if (!docheck) {
1291 1292 delete_running_struct(rp);
1292 1293 rp = *rp_prev;
1293 1294 if (rp == NULL) {
1294 1295 break;
1295 1296 } else {
1296 1297 goto bypass_for_loop_inc_4;
1297 1298 }
1298 1299 }
1299 1300 update_target(get_prop(rp->target->prop, line_prop),
1300 1301 rp->state);
1301 1302 finish_doname(rp);
1302 1303 delete_running_struct(rp);
1303 1304 rp = *rp_prev;
1304 1305 if (rp == NULL) {
1305 1306 break;
1306 1307 } else {
1307 1308 goto bypass_for_loop_inc_4;
1308 1309 }
1309 1310 } else {
1310 1311 rp_prev = &rp->next;
1311 1312 }
1312 1313 }
1313 1314 }
1314 1315
1315 1316 /*
1316 1317 * dump_out_file(filename, err)
1317 1318 *
1318 1319 * Write the contents of the file to stdout, then unlink the file.
1319 1320 *
1320 1321 * Parameters:
1321 1322 * filename Name of temp file containing output
1322 1323 *
1323 1324 * Global variables used:
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
1324 1325 */
1325 1326 static void
1326 1327 dump_out_file(char *filename, Boolean err)
1327 1328 {
1328 1329 int chars_read;
1329 1330 char copybuf[BUFSIZ];
1330 1331 int fd;
1331 1332 int out_fd = (err ? 2 : 1);
1332 1333
1333 1334 if ((fd = open(filename, O_RDONLY)) < 0) {
1334 - fatal(catgets(catd, 1, 141, "open failed for output file %s: %s"),
1335 + fatal(gettext("open failed for output file %s: %s"),
1335 1336 filename,
1336 1337 errmsg(errno));
1337 1338 }
1338 1339 if (!silent && output_mode != txt2_mode) {
1339 1340 (void) fprintf(err ? stderr : stdout,
1340 1341 err ?
1341 - catgets(catd, 1, 338, "%s --> Job errors\n") :
1342 - catgets(catd, 1, 259, "%s --> Job output\n"),
1342 + gettext("%s --> Job errors\n") :
1343 + gettext("%s --> Job output\n"),
1343 1344 local_host);
1344 1345 (void) fflush(err ? stderr : stdout);
1345 1346 }
1346 1347 for (chars_read = read(fd, copybuf, BUFSIZ);
1347 1348 chars_read > 0;
1348 1349 chars_read = read(fd, copybuf, BUFSIZ)) {
1349 1350 /*
1350 1351 * Read buffers from the source file until end or error.
1351 1352 */
1352 1353 if (write(out_fd, copybuf, chars_read) < 0) {
1353 - fatal(catgets(catd, 1, 260, "write failed for output file %s: %s"),
1354 + fatal(gettext("write failed for output file %s: %s"),
1354 1355 filename,
1355 1356 errmsg(errno));
1356 1357 }
1357 1358 }
1358 1359 (void) close(fd);
1359 1360 (void) unlink(filename);
1360 1361 }
1361 1362
1362 1363 /*
1363 1364 * finish_doname(rp)
1364 1365 *
1365 1366 * Completes the processing for a target which was left running.
1366 1367 *
1367 1368 * Parameters:
1368 1369 * rp Running list entry for target
1369 1370 *
1370 1371 * Global variables used:
1371 1372 * debug_level Debug flag
1372 1373 * recursion_level Indentation for debug output
1373 1374 */
1374 1375 static void
1375 1376 finish_doname(Running rp)
1376 1377 {
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
1377 1378 int auto_count = rp->auto_count;
1378 1379 Name *automatics = rp->automatics;
1379 1380 Doname result = rp->state;
1380 1381 Name target = rp->target;
1381 1382 Name true_target = rp->true_target;
1382 1383 Property *conditionals;
1383 1384
1384 1385 recursion_level = rp->recursion_level;
1385 1386 if (result == build_ok) {
1386 1387 if (true_target == NULL) {
1387 - (void) printf(NOCATGETS("Target = %s\n"), target->string_mb);
1388 - (void) printf(NOCATGETS(" State = %d\n"), result);
1389 - fatal(NOCATGETS("Internal error: NULL true_target in finish_doname"));
1388 + (void) printf("Target = %s\n", target->string_mb);
1389 + (void) printf(" State = %d\n", result);
1390 + fatal("Internal error: NULL true_target in finish_doname");
1390 1391 }
1391 1392 /* If all went OK, set a nice timestamp */
1392 1393 if (true_target->stat.time == file_doesnt_exist) {
1393 1394 true_target->stat.time = file_max_time;
1394 1395 }
1395 1396 }
1396 1397 target->state = result;
1397 1398 if (target->is_member) {
1398 1399 Property member;
1399 1400
1400 1401 /* Propagate the timestamp from the member file to the member */
1401 1402 if ((target->stat.time != file_max_time) &&
1402 1403 ((member = get_prop(target->prop, member_prop)) != NULL) &&
1403 1404 (exists(member->body.member.member) > file_doesnt_exist)) {
1404 1405 target->stat.time =
1405 1406 /*
1406 1407 exists(member->body.member.member);
1407 1408 */
1408 1409 member->body.member.member->stat.time;
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
1409 1410 }
1410 1411 }
1411 1412 /*
1412 1413 * Check if we found any new auto dependencies when we
1413 1414 * built the target.
1414 1415 */
1415 1416 if ((result == build_ok) && check_auto_dependencies(target,
1416 1417 auto_count,
1417 1418 automatics)) {
1418 1419 if (debug_level > 0) {
1419 - (void) printf(catgets(catd, 1, 261, "%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
1420 + (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
1420 1421 recursion_level,
1421 1422 "",
1422 1423 true_target->string_mb);
1423 1424 }
1424 1425 target->rechecking_target = true;
1425 1426 target->state = build_running;
1426 1427
1427 1428 /* [tolik, Tue Mar 25 1997]
1428 1429 * Fix for bug 4038824:
1429 1430 * command line options set by conditional macros get dropped
1430 1431 * rp->conditional_cnt and rp->conditional_targets must be copied
1431 1432 * to new 'rp' during add_pending(). Set_conditionals() stores
1432 1433 * rp->conditional_targets to the global variable 'conditional_targets'
1433 1434 * Add_pending() will use this variable to set up 'rp'.
1434 1435 */
1435 1436 conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets);
1436 1437 add_pending(target,
1437 1438 recursion_level,
1438 1439 rp->do_get,
1439 1440 rp->implicit,
1440 1441 true);
1441 1442 reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals);
1442 1443 }
1443 1444 }
1444 1445
1445 1446 /*
1446 1447 * new_running_struct()
1447 1448 *
1448 1449 * Constructor for Running struct. Creates a structure and initializes
1449 1450 * its fields.
1450 1451 *
1451 1452 */
1452 1453 static Running new_running_struct()
1453 1454 {
1454 1455 Running rp;
1455 1456
1456 1457 rp = ALLOC(Running);
1457 1458 rp->target = NULL;
1458 1459 rp->true_target = NULL;
1459 1460 rp->command = NULL;
1460 1461 rp->sprodep_value = NULL;
1461 1462 rp->sprodep_env = NULL;
1462 1463 rp->auto_count = 0;
1463 1464 rp->automatics = NULL;
1464 1465 rp->pid = -1;
1465 1466 rp->job_msg_id = -1;
1466 1467 rp->stdout_file = NULL;
1467 1468 rp->stderr_file = NULL;
1468 1469 rp->temp_file = NULL;
1469 1470 rp->next = NULL;
1470 1471 return rp;
1471 1472 }
1472 1473
1473 1474 /*
1474 1475 * add_running(target, true_target, command, recursion_level, auto_count,
1475 1476 * automatics, do_get, implicit)
1476 1477 *
1477 1478 * Adds a record on the running list for this target, which
1478 1479 * was just spawned and is running.
1479 1480 *
1480 1481 * Parameters:
1481 1482 * target Target being built
1482 1483 * true_target True target for target
1483 1484 * command Running command.
1484 1485 * recursion_level Debug indentation level
1485 1486 * auto_count Count of automatic dependencies
1486 1487 * automatics List of automatic dependencies
1487 1488 * do_get Sccs get flag
1488 1489 * implicit Implicit flag
1489 1490 *
1490 1491 * Static variables used:
1491 1492 * running_tail Tail of running list
1492 1493 * process_running PID of process
1493 1494 *
1494 1495 * Global variables used:
1495 1496 * current_line Current line for target
1496 1497 * current_target Current target being built
1497 1498 * stderr_file Temporary file for stdout
1498 1499 * stdout_file Temporary file for stdout
1499 1500 * temp_file_name Temporary file for auto dependencies
1500 1501 */
1501 1502 void
1502 1503 add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit)
1503 1504 {
1504 1505 Running rp;
1505 1506 Name *p;
1506 1507
1507 1508 rp = new_running_struct();
1508 1509 rp->state = build_running;
1509 1510 rp->target = target;
1510 1511 rp->true_target = true_target;
1511 1512 rp->command = command;
1512 1513 rp->recursion_level = recursion_level;
1513 1514 rp->do_get = do_get;
1514 1515 rp->implicit = implicit;
1515 1516 rp->auto_count = auto_count;
1516 1517 if (auto_count > 0) {
1517 1518 rp->automatics = (Name *) getmem(auto_count * sizeof (Name));
1518 1519 for (p = rp->automatics; auto_count > 0; auto_count--) {
1519 1520 *p++ = *automatics++;
1520 1521 }
1521 1522 } else {
1522 1523 rp->automatics = NULL;
1523 1524 }
1524 1525 {
1525 1526 rp->pid = process_running;
1526 1527 process_running = -1;
1527 1528 childPid = -1;
1528 1529 }
1529 1530 rp->job_msg_id = job_msg_id;
1530 1531 rp->stdout_file = stdout_file;
1531 1532 rp->stderr_file = stderr_file;
1532 1533 rp->temp_file = temp_file_name;
1533 1534 rp->redo = false;
1534 1535 rp->next = NULL;
1535 1536 store_conditionals(rp);
1536 1537 stdout_file = NULL;
1537 1538 stderr_file = NULL;
1538 1539 temp_file_name = NULL;
1539 1540 current_target = NULL;
1540 1541 current_line = NULL;
1541 1542 *running_tail = rp;
1542 1543 running_tail = &rp->next;
1543 1544 }
1544 1545
1545 1546 /*
1546 1547 * add_pending(target, recursion_level, do_get, implicit, redo)
1547 1548 *
1548 1549 * Adds a record on the running list for a pending target
1549 1550 * (waiting for its dependents to finish running).
1550 1551 *
1551 1552 * Parameters:
1552 1553 * target Target being built
1553 1554 * recursion_level Debug indentation level
1554 1555 * do_get Sccs get flag
1555 1556 * implicit Implicit flag
1556 1557 * redo True if this target is being redone
1557 1558 *
1558 1559 * Static variables used:
1559 1560 * running_tail Tail of running list
1560 1561 */
1561 1562 void
1562 1563 add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo)
1563 1564 {
1564 1565 Running rp;
1565 1566 rp = new_running_struct();
1566 1567 rp->state = build_pending;
1567 1568 rp->target = target;
1568 1569 rp->recursion_level = recursion_level;
1569 1570 rp->do_get = do_get;
1570 1571 rp->implicit = implicit;
1571 1572 rp->redo = redo;
1572 1573 store_conditionals(rp);
1573 1574 *running_tail = rp;
1574 1575 running_tail = &rp->next;
1575 1576 }
1576 1577
1577 1578 /*
1578 1579 * add_serial(target, recursion_level, do_get, implicit)
1579 1580 *
1580 1581 * Adds a record on the running list for a target which must be
1581 1582 * executed in serial after others have finished.
1582 1583 *
1583 1584 * Parameters:
1584 1585 * target Target being built
1585 1586 * recursion_level Debug indentation level
1586 1587 * do_get Sccs get flag
1587 1588 * implicit Implicit flag
1588 1589 *
1589 1590 * Static variables used:
1590 1591 * running_tail Tail of running list
1591 1592 */
1592 1593 void
1593 1594 add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1594 1595 {
1595 1596 Running rp;
1596 1597
1597 1598 rp = new_running_struct();
1598 1599 rp->target = target;
1599 1600 rp->recursion_level = recursion_level;
1600 1601 rp->do_get = do_get;
1601 1602 rp->implicit = implicit;
1602 1603 rp->state = build_serial;
1603 1604 rp->redo = false;
1604 1605 store_conditionals(rp);
1605 1606 *running_tail = rp;
1606 1607 running_tail = &rp->next;
1607 1608 }
1608 1609
1609 1610 /*
1610 1611 * add_subtree(target, recursion_level, do_get, implicit)
1611 1612 *
1612 1613 * Adds a record on the running list for a target which must be
1613 1614 * executed in isolation after others have finished.
1614 1615 *
1615 1616 * Parameters:
1616 1617 * target Target being built
1617 1618 * recursion_level Debug indentation level
1618 1619 * do_get Sccs get flag
1619 1620 * implicit Implicit flag
1620 1621 *
1621 1622 * Static variables used:
1622 1623 * running_tail Tail of running list
1623 1624 */
1624 1625 void
1625 1626 add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1626 1627 {
1627 1628 Running rp;
1628 1629
1629 1630 rp = new_running_struct();
1630 1631 rp->target = target;
1631 1632 rp->recursion_level = recursion_level;
1632 1633 rp->do_get = do_get;
1633 1634 rp->implicit = implicit;
1634 1635 rp->state = build_subtree;
1635 1636 rp->redo = false;
1636 1637 store_conditionals(rp);
1637 1638 *running_tail = rp;
1638 1639 running_tail = &rp->next;
1639 1640 }
1640 1641
1641 1642 /*
1642 1643 * store_conditionals(rp)
1643 1644 *
1644 1645 * Creates an array of the currently active targets with conditional
1645 1646 * macros (found in the chain conditional_targets) and puts that
1646 1647 * array in the Running struct.
1647 1648 *
1648 1649 * Parameters:
1649 1650 * rp Running struct for storing chain
1650 1651 *
1651 1652 * Global variables used:
1652 1653 * conditional_targets Chain of current dynamic conditionals
1653 1654 */
1654 1655 static void
1655 1656 store_conditionals(Running rp)
1656 1657 {
1657 1658 int cnt;
1658 1659 Chain cond_name;
1659 1660
1660 1661 if (conditional_targets == NULL) {
1661 1662 rp->conditional_cnt = 0;
1662 1663 rp->conditional_targets = NULL;
1663 1664 return;
1664 1665 }
1665 1666 cnt = 0;
1666 1667 for (cond_name = conditional_targets;
1667 1668 cond_name != NULL;
1668 1669 cond_name = cond_name->next) {
1669 1670 cnt++;
1670 1671 }
1671 1672 rp->conditional_cnt = cnt;
1672 1673 rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name));
1673 1674 for (cond_name = conditional_targets;
1674 1675 cond_name != NULL;
1675 1676 cond_name = cond_name->next) {
1676 1677 rp->conditional_targets[--cnt] = cond_name->name;
1677 1678 }
1678 1679 }
1679 1680
1680 1681 /*
1681 1682 * parallel_ok(target, line_prop_must_exists)
1682 1683 *
1683 1684 * Returns true if the target can be run in parallel
1684 1685 *
1685 1686 * Return value:
1686 1687 * True if can run in parallel
1687 1688 *
1688 1689 * Parameters:
1689 1690 * target Target being tested
1690 1691 *
1691 1692 * Global variables used:
1692 1693 * all_parallel True if all targets default to parallel
1693 1694 * only_parallel True if no targets default to parallel
1694 1695 */
1695 1696 Boolean
1696 1697 parallel_ok(Name target, Boolean line_prop_must_exists)
1697 1698 {
1698 1699 Boolean assign;
1699 1700 Boolean make_refd;
1700 1701 Property line;
1701 1702 Cmd_line rule;
1702 1703
1703 1704 assign = make_refd = false;
1704 1705 if (((line = get_prop(target->prop, line_prop)) == NULL) &&
1705 1706 line_prop_must_exists) {
1706 1707 return false;
1707 1708 }
1708 1709 if (line != NULL) {
1709 1710 for (rule = line->body.line.command_used;
1710 1711 rule != NULL;
1711 1712 rule = rule->next) {
1712 1713 if (rule->assign) {
1713 1714 assign = true;
1714 1715 } else if (rule->make_refd) {
1715 1716 make_refd = true;
1716 1717 }
1717 1718 }
1718 1719 }
1719 1720 if (assign) {
1720 1721 return false;
1721 1722 } else if (target->parallel) {
1722 1723 return true;
1723 1724 } else if (target->no_parallel) {
1724 1725 return false;
1725 1726 } else if (all_parallel) {
1726 1727 return true;
1727 1728 } else if (only_parallel) {
1728 1729 return false;
1729 1730 } else if (make_refd) {
1730 1731 return false;
1731 1732 } else {
1732 1733 return true;
1733 1734 }
1734 1735 }
1735 1736
1736 1737 /*
1737 1738 * is_running(target)
1738 1739 *
1739 1740 * Returns true if the target is running.
1740 1741 *
1741 1742 * Return value:
1742 1743 * True if target is running
1743 1744 *
1744 1745 * Parameters:
1745 1746 * target Target to check
1746 1747 *
1747 1748 * Global variables used:
1748 1749 * running_list List of running processes
1749 1750 */
1750 1751 Boolean
1751 1752 is_running(Name target)
1752 1753 {
1753 1754 Running rp;
1754 1755
1755 1756 if (target->state != build_running) {
1756 1757 return false;
1757 1758 }
1758 1759 for (rp = running_list;
1759 1760 rp != NULL && target != rp->target;
1760 1761 rp = rp->next);
1761 1762 if (rp == NULL) {
1762 1763 return false;
1763 1764 } else {
1764 1765 return (rp->state == build_running) ? true : false;
1765 1766 }
1766 1767 }
1767 1768
1768 1769 /*
1769 1770 * This function replaces the makesh binary.
1770 1771 */
1771 1772
1772 1773
1773 1774 static pid_t
1774 1775 run_rule_commands(char *host, char **commands)
1775 1776 {
1776 1777 Boolean always_exec;
↓ open down ↓ |
347 lines elided |
↑ open up ↑ |
1777 1778 Name command;
1778 1779 Boolean ignore;
1779 1780 int length;
1780 1781 Doname result;
1781 1782 Boolean silent_flag;
1782 1783 wchar_t *tmp_wcs_buffer;
1783 1784
1784 1785 childPid = fork();
1785 1786 switch (childPid) {
1786 1787 case -1: /* Error */
1787 - fatal(catgets(catd, 1, 337, "Could not fork child process for dmake job: %s"),
1788 + fatal(gettext("Could not fork child process for dmake job: %s"),
1788 1789 errmsg(errno));
1789 1790 break;
1790 1791 case 0: /* Child */
1791 1792 /* To control the processed targets list is not the child's business */
1792 1793 running_list = NULL;
1793 1794 if(out_err_same) {
1794 1795 redirect_io(stdout_file, (char*)NULL);
1795 1796 } else {
1796 1797 redirect_io(stdout_file, stderr_file);
1797 1798 }
1798 1799 for (commands = commands;
1799 1800 (*commands != (char *)NULL);
1800 1801 commands++) {
1801 1802 silent_flag = silent;
1802 1803 ignore = false;
1803 1804 always_exec = false;
1804 1805 while ((**commands == (int) at_char) ||
1805 1806 (**commands == (int) hyphen_char) ||
1806 1807 (**commands == (int) plus_char)) {
1807 1808 if (**commands == (int) at_char) {
1808 1809 silent_flag = true;
1809 1810 }
1810 1811 if (**commands == (int) hyphen_char) {
1811 1812 ignore = true;
1812 1813 }
1813 1814 if (**commands == (int) plus_char) {
1814 1815 always_exec = true;
1815 1816 }
1816 1817 (*commands)++;
1817 1818 }
1818 1819 if ((length = strlen(*commands)) >= MAXPATHLEN) {
1819 1820 tmp_wcs_buffer = ALLOC_WC(length + 1);
1820 1821 (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
1821 1822 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
1822 1823 retmem(tmp_wcs_buffer);
1823 1824 } else {
1824 1825 MBSTOWCS(wcs_buffer, *commands);
1825 1826 command = GETNAME(wcs_buffer, FIND_LENGTH);
1826 1827 }
1827 1828 if ((command->hash.length > 0) &&
1828 1829 !silent_flag) {
1829 1830 (void) printf("%s\n", command->string_mb);
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
1830 1831 }
1831 1832 result = dosys(command,
1832 1833 ignore,
1833 1834 false,
1834 1835 false, /* bugs #4085164 & #4990057 */
1835 1836 /* BOOLEAN(silent_flag && ignore), */
1836 1837 always_exec,
1837 1838 (Name) NULL);
1838 1839 if (result == build_failed) {
1839 1840 if (silent_flag) {
1840 - (void) printf(catgets(catd, 1, 152, "The following command caused the error:\n%s\n"), command->string_mb);
1841 + (void) printf(gettext("The following command caused the error:\n%s\n"), command->string_mb);
1841 1842 }
1842 1843 if (!ignore) {
1843 1844 _exit(1);
1844 1845 }
1845 1846 }
1846 1847 }
1847 1848 _exit(0);
1848 1849 break;
1849 1850 default:
1850 1851 break;
1851 1852 }
1852 1853 return childPid;
1853 1854 }
1854 1855
1855 1856 static void
1856 1857 maybe_reread_make_state(void)
1857 1858 {
1858 1859 /* Copying dosys()... */
1859 1860 if (report_dependencies_level == 0) {
1860 1861 make_state->stat.time = file_no_time;
1861 1862 (void) exists(make_state);
1862 1863 if (make_state_before == make_state->stat.time) {
1863 1864 return;
1864 1865 }
1865 1866 makefile_type = reading_statefile;
1866 1867 if (read_trace_level > 1) {
1867 1868 trace_reader = true;
1868 1869 }
1869 1870 temp_file_number++;
1870 1871 (void) read_simple_file(make_state,
1871 1872 false,
1872 1873 false,
1873 1874 false,
1874 1875 false,
1875 1876 false,
1876 1877 true);
1877 1878 trace_reader = false;
1878 1879 }
1879 1880 }
1880 1881
1881 1882
1882 1883 static void
1883 1884 delete_running_struct(Running rp)
1884 1885 {
1885 1886 if ((rp->conditional_cnt > 0) &&
1886 1887 (rp->conditional_targets != NULL)) {
1887 1888 retmem_mb((char *) rp->conditional_targets);
1888 1889 }
1889 1890 /**/
1890 1891 if ((rp->auto_count > 0) &&
1891 1892 (rp->automatics != NULL)) {
1892 1893 retmem_mb((char *) rp->automatics);
1893 1894 }
1894 1895 /**/
1895 1896 if(rp->sprodep_value) {
1896 1897 free_name(rp->sprodep_value);
1897 1898 }
1898 1899 if(rp->sprodep_env) {
1899 1900 retmem_mb(rp->sprodep_env);
1900 1901 }
1901 1902 retmem_mb((char *) rp);
1902 1903
1903 1904 }
1904 1905
1905 1906
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX