Print this page
make: remove SCCS ident stuff
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/make/common/state.cc
+++ new/usr/src/cmd/make/bin/make/common/state.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.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 2004 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 -/*
26 - * @(#)state.cc 1.27 06/12/12
27 - */
28 -
29 -#pragma ident "@(#)state.cc 1.27 06/12/12"
30 25
31 26 /*
32 27 * state.c
33 28 *
34 29 * This file contains the routines that write the .make.state file
35 30 */
36 31
37 32 /*
38 33 * Included files
39 34 */
40 35 #include <mk/defs.h>
41 36 #include <mksh/misc.h> /* errmsg() */
42 37 #include <setjmp.h> /* setjmp() */
43 38 #include <unistd.h> /* getpid() */
44 39 #include <errno.h> /* errno */
45 40 #include <locale.h> /* MB_CUR_MAX */
46 41
47 42 /*
48 43 * Defined macros
49 44 */
50 45 #define LONGJUMP_VALUE 17
51 46 #define XFWRITE(string, length, fd) {if (fwrite(string, 1, length, fd) == 0) \
52 47 longjmp(long_jump, LONGJUMP_VALUE);}
53 48 #define XPUTC(ch, fd) { \
54 49 if (putc((int) ch, fd) == EOF) \
55 50 longjmp(long_jump, LONGJUMP_VALUE); \
56 51 }
57 52 #define XFPUTS(string, fd) fputs(string, fd)
58 53
59 54 /*
60 55 * typedefs & structs
61 56 */
62 57
63 58 /*
64 59 * Static variables
65 60 */
66 61
67 62 /*
68 63 * File table of contents
69 64 */
70 65 static char * escape_target_name(Name np)
71 66 {
72 67 if(np->dollar) {
73 68 int len = strlen(np->string_mb);
74 69 char * buff = (char*)malloc(2 * len);
75 70 int pos = 0;
76 71 wchar_t wc;
77 72 int pp = 0;
78 73 while(pos < len) {
79 74 int n = mbtowc(&wc, np->string_mb + pos, MB_CUR_MAX);
80 75 if(n < 0) { // error - this shouldn't happen
81 76 (void)free(buff);
82 77 return strdup(np->string_mb);
83 78 }
84 79 if(wc == dollar_char) {
85 80 buff[pp] = '\\'; pp++;
86 81 buff[pp] = '$'; pp++;
87 82 } else {
88 83 for(int j=0;j<n;j++) {
89 84 buff[pp] = np->string_mb[pos+j]; pp++;
90 85 }
91 86 }
92 87 pos += n;
93 88 }
94 89 buff[pp] = '\0';
95 90 return buff;
96 91 } else {
97 92 return strdup(np->string_mb);
98 93 }
99 94 }
100 95
101 96 static void print_auto_depes(register Dependency dependency, register FILE *fd, register Boolean built_this_run, register int *line_length, register char *target_name, jmp_buf long_jump);
102 97
103 98 /*
104 99 * write_state_file(report_recursive, exiting)
105 100 *
106 101 * Write a new version of .make.state
107 102 *
108 103 * Parameters:
109 104 * report_recursive Should only be done at end of run
110 105 * exiting true if called from the exit handler
111 106 *
112 107 * Global variables used:
113 108 * built_last_make_run The Name ".BUILT_LAST_MAKE_RUN", written
114 109 * command_changed If no command changed we do not need to write
115 110 * current_make_version The Name "<current version>", written
116 111 * do_not_exec_rule If -n is on we do not write statefile
117 112 * hashtab The hashtable that contains all names
118 113 * keep_state If .KEEP_STATE is no on we do not write file
119 114 * make_state The Name ".make.state", used for opening file
120 115 * make_version The Name ".MAKE_VERSION", written
121 116 * recursive_name The Name ".RECURSIVE", written
122 117 * rewrite_statefile Indicates that something changed
123 118 */
124 119
125 120 void
126 121 #ifdef NSE
127 122 write_state_file(int report_recursive, Boolean exiting)
128 123 #else
129 124 write_state_file(int, Boolean exiting)
130 125 #endif
131 126 {
132 127 register FILE *fd;
133 128 int lock_err;
134 129 char buffer[MAXPATHLEN];
135 130 char make_state_tempfile[MAXPATHLEN];
136 131 jmp_buf long_jump;
137 132 register int attempts = 0;
138 133 Name_set::iterator np, e;
139 134 register Property lines;
140 135 register int m;
141 136 Dependency dependency;
142 137 register Boolean name_printed;
143 138 Boolean built_this_run = false;
144 139 char *target_name;
145 140 int line_length;
146 141 register Cmd_line cp;
147 142
148 143
149 144 if (!rewrite_statefile ||
150 145 !command_changed ||
151 146 !keep_state ||
152 147 do_not_exec_rule ||
153 148 (report_dependencies_level > 0)) {
154 149 return;
155 150 }
156 151 /* Lock the file for writing. */
157 152 make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(NOCATGETS(".lock")) + 1);
158 153 (void) sprintf(make_state_lockfile,
159 154 NOCATGETS("%s.lock"),
160 155 make_state->string_mb);
161 156 if (lock_err = file_lock(make_state->string_mb,
162 157 make_state_lockfile,
163 158 (int *) &make_state_locked, 0)) {
164 159 retmem_mb(make_state_lockfile);
165 160 make_state_lockfile = NULL;
166 161
167 162 /*
168 163 * We need to make sure that we are not being
169 164 * called by the exit handler so we don't call
170 165 * it again.
171 166 */
172 167
173 168 if (exiting) {
174 169 (void) sprintf(buffer, NOCATGETS("%s/.make.state.%d.XXXXXX"), tmpdir, getpid());
175 170 report_pwd = true;
176 171 warning(catgets(catd, 1, 60, "Writing to %s"), buffer);
177 172 int fdes = mkstemp(buffer);
178 173 if ((fdes < 0) || (fd = fdopen(fdes, "w")) == NULL) {
179 174 fprintf(stderr,
180 175 catgets(catd, 1, 61, "Could not open statefile `%s': %s"),
181 176 buffer,
182 177 errmsg(errno));
183 178 return;
184 179 }
185 180 } else {
186 181 report_pwd = true;
187 182 fatal(catgets(catd, 1, 62, "Can't lock .make.state"));
188 183 }
189 184 }
190 185
191 186 (void) sprintf(make_state_tempfile,
192 187 NOCATGETS("%s.tmp"),
193 188 make_state->string_mb);
194 189 /* Delete old temporary statefile (in case it exists) */
195 190 (void) unlink(make_state_tempfile);
196 191 if ((fd = fopen(make_state_tempfile, "w")) == NULL) {
197 192 lock_err = errno; /* Save it! unlink() can change errno */
198 193 (void) unlink(make_state_lockfile);
199 194 retmem_mb(make_state_lockfile);
200 195 make_state_lockfile = NULL;
201 196 make_state_locked = false;
202 197 fatal(catgets(catd, 1, 59, "Could not open temporary statefile `%s': %s"),
203 198 make_state_tempfile,
204 199 errmsg(lock_err));
205 200 }
206 201 #ifdef NSE
207 202 if (nse) {
208 203 (void) fchmod(fileno(fd), 0666);
209 204 }
210 205 #endif
211 206 /*
212 207 * Set a trap for failed writes. If a write fails, the routine
213 208 * will try saving the .make.state file under another name in /tmp.
214 209 */
215 210 if (setjmp(long_jump)) {
216 211 (void) fclose(fd);
217 212 if (attempts++ > 5) {
218 213 if ((make_state_lockfile != NULL) &&
219 214 make_state_locked) {
220 215 (void) unlink(make_state_lockfile);
221 216 retmem_mb(make_state_lockfile);
222 217 make_state_lockfile = NULL;
223 218 make_state_locked = false;
224 219 }
225 220 fatal(catgets(catd, 1, 63, "Giving up on writing statefile"));
226 221 }
227 222 sleep(10);
228 223 (void) sprintf(buffer, NOCATGETS("%s/.make.state.%d.XXXXXX"), tmpdir, getpid());
229 224 int fdes = mkstemp(buffer);
230 225 if ((fdes < 0) || (fd = fdopen(fdes, "w")) == NULL) {
231 226 fatal(catgets(catd, 1, 64, "Could not open statefile `%s': %s"),
232 227 buffer,
233 228 errmsg(errno));
234 229 }
235 230 warning(catgets(catd, 1, 65, "Initial write of statefile failed. Trying again on %s"),
236 231 buffer);
237 232 }
238 233
239 234 /* Write the version stamp. */
240 235 XFWRITE(make_version->string_mb,
241 236 strlen(make_version->string_mb),
242 237 fd);
243 238 XPUTC(colon_char, fd);
244 239 XPUTC(tab_char, fd);
245 240 XFWRITE(current_make_version->string_mb,
246 241 strlen(current_make_version->string_mb),
247 242 fd);
248 243 XPUTC(newline_char, fd);
249 244
250 245 /*
251 246 * Go through all the targets, dump their dependencies and
252 247 * command used.
253 248 */
254 249 for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
255 250 /*
256 251 * If the target has no command used nor dependencies,
257 252 * we can go to the next one.
258 253 */
259 254 if ((lines = get_prop(np->prop, line_prop)) == NULL) {
260 255 continue;
261 256 }
262 257 /* If this target is a special target, don't print. */
263 258 if (np->special_reader != no_special) {
264 259 continue;
265 260 }
266 261 /*
267 262 * Find out if any of the targets dependencies should
268 263 * be written to .make.state.
269 264 */
270 265 for (m = 0, dependency = lines->body.line.dependencies;
271 266 dependency != NULL;
272 267 dependency = dependency->next) {
273 268 if (m = !dependency->stale
274 269 && (dependency->name != force)
275 270 #ifndef PRINT_EXPLICIT_DEPEN
276 271 && dependency->automatic
277 272 #endif
278 273 ) {
279 274 break;
280 275 }
281 276 }
282 277 /* Only print if dependencies listed. */
283 278 if (m || (lines->body.line.command_used != NULL)) {
284 279 name_printed = false;
285 280 /*
286 281 * If this target was built during this make run,
287 282 * we mark it.
288 283 */
289 284 built_this_run = false;
290 285 if (np->has_built) {
291 286 built_this_run = true;
292 287 XFWRITE(built_last_make_run->string_mb,
293 288 strlen(built_last_make_run->string_mb),
294 289 fd);
295 290 XPUTC(colon_char, fd);
296 291 XPUTC(newline_char, fd);
297 292 }
298 293 /* If the target has dependencies, we dump them. */
299 294 target_name = escape_target_name(np);
300 295 if (np->has_long_member_name) {
301 296 target_name =
302 297 get_prop(np->prop, long_member_name_prop)
303 298 ->body.long_member_name.member_name->
304 299 string_mb;
305 300 }
306 301 if (m) {
307 302 XFPUTS(target_name, fd);
308 303 XPUTC(colon_char, fd);
309 304 XFPUTS("\t", fd);
310 305 name_printed = true;
311 306 line_length = 0;
312 307 for (dependency =
313 308 lines->body.line.dependencies;
314 309 dependency != NULL;
315 310 dependency = dependency->next) {
316 311 print_auto_depes(dependency,
317 312 fd,
318 313 built_this_run,
319 314 &line_length,
320 315 target_name,
321 316 long_jump);
322 317 }
323 318 XFPUTS("\n", fd);
324 319 }
325 320 /* If there is a command used, we dump it. */
326 321 if (lines->body.line.command_used != NULL) {
327 322 /*
328 323 * Only write the target name if it
329 324 * wasn't done for the dependencies.
330 325 */
331 326 if (!name_printed) {
332 327 XFPUTS(target_name, fd);
333 328 XPUTC(colon_char, fd);
334 329 XPUTC(newline_char, fd);
335 330 }
336 331 /*
337 332 * Write the command lines.
338 333 * Prefix each textual line with a tab.
339 334 */
340 335 for (cp = lines->body.line.command_used;
341 336 cp != NULL;
342 337 cp = cp->next) {
343 338 char *csp;
344 339 int n;
345 340
346 341 XPUTC(tab_char, fd);
347 342 if (cp->command_line != NULL) {
348 343 for (csp = cp->
349 344 command_line->
350 345 string_mb,
351 346 n = strlen(cp->
352 347 command_line->
353 348 string_mb);
354 349 n > 0;
355 350 n--, csp++) {
356 351 XPUTC(*csp, fd);
357 352 if (*csp ==
358 353 (int) newline_char) {
359 354 XPUTC(tab_char,
360 355 fd);
361 356 }
362 357 }
363 358 }
364 359 XPUTC(newline_char, fd);
365 360 }
366 361 }
367 362 (void)free(target_name);
368 363 }
369 364 }
370 365 if (fclose(fd) == EOF) {
371 366 longjmp(long_jump, LONGJUMP_VALUE);
372 367 }
373 368 if (attempts == 0) {
374 369 if (unlink(make_state->string_mb) != 0 && errno != ENOENT) {
375 370 lock_err = errno; /* Save it! unlink() can change errno */
376 371 /* Delete temporary statefile */
377 372 (void) unlink(make_state_tempfile);
378 373 (void) unlink(make_state_lockfile);
379 374 retmem_mb(make_state_lockfile);
380 375 make_state_lockfile = NULL;
381 376 make_state_locked = false;
382 377 fatal(catgets(catd, 1, 356, "Could not delete old statefile `%s': %s"),
383 378 make_state->string_mb,
384 379 errmsg(lock_err));
385 380 }
386 381 if (rename(make_state_tempfile, make_state->string_mb) != 0) {
387 382 lock_err = errno; /* Save it! unlink() can change errno */
388 383 /* Delete temporary statefile */
389 384 (void) unlink(make_state_tempfile);
390 385 (void) unlink(make_state_lockfile);
391 386 retmem_mb(make_state_lockfile);
392 387 make_state_lockfile = NULL;
393 388 make_state_locked = false;
394 389 fatal(catgets(catd, 1, 357, "Could not rename `%s' to `%s': %s"),
395 390 make_state_tempfile,
396 391 make_state->string_mb,
397 392 errmsg(lock_err));
398 393 }
399 394 }
400 395 if ((make_state_lockfile != NULL) && make_state_locked) {
401 396 (void) unlink(make_state_lockfile);
402 397 retmem_mb(make_state_lockfile);
403 398 make_state_lockfile = NULL;
404 399 make_state_locked = false;
405 400 }
406 401 #ifdef NSE
407 402 if (report_recursive) {
408 403 report_recursive_done();
409 404 }
410 405 #endif
411 406 }
412 407
413 408 /*
414 409 * print_auto_depes(dependency, fd, built_this_run,
415 410 * line_length, target_name, long_jump)
416 411 *
417 412 * Will print a dependency list for automatic entries.
418 413 *
419 414 * Parameters:
420 415 * dependency The dependency to print
421 416 * fd The file to print it to
422 417 * built_this_run If on we prefix each line with .BUILT_THIS...
423 418 * line_length Pointer to line length var that we update
424 419 * target_name We need this when we restart line
425 420 * long_jump setjmp/longjmp buffer used for IO error action
426 421 *
427 422 * Global variables used:
428 423 * built_last_make_run The Name ".BUILT_LAST_MAKE_RUN", written
429 424 * force The Name " FORCE", compared against
430 425 */
431 426 static void
432 427 print_auto_depes(register Dependency dependency, register FILE *fd, register Boolean built_this_run, register int *line_length, register char *target_name, jmp_buf long_jump)
433 428 {
434 429 if (!dependency->automatic ||
435 430 dependency->stale ||
436 431 (dependency->name == force)) {
437 432 return;
438 433 }
439 434 XFWRITE(dependency->name->string_mb,
440 435 strlen(dependency->name->string_mb),
441 436 fd);
442 437 /*
443 438 * Check if the dependency line is too long.
444 439 * If so, break it and start a new one.
445 440 */
446 441 if ((*line_length += (int) strlen(dependency->name->string_mb) + 1) > 450) {
447 442 *line_length = 0;
448 443 XPUTC(newline_char, fd);
449 444 if (built_this_run) {
450 445 XFPUTS(built_last_make_run->string_mb, fd);
451 446 XPUTC(colon_char, fd);
452 447 XPUTC(newline_char, fd);
453 448 }
454 449 XFPUTS(target_name, fd);
455 450 XPUTC(colon_char, fd);
456 451 XPUTC(tab_char, fd);
457 452 } else {
458 453 XFPUTS(" ", fd);
459 454 }
460 455 return;
461 456 }
462 457
463 458
↓ open down ↓ |
424 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX