1 %{ 2 3 /* 4 * Copyright (c) 1988 Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms are permitted 8 * provided that the above copyright notice and this paragraph are 9 * duplicated in all such forms and that any documentation, 10 * advertising materials, and other materials related to such 11 * distribution and use acknowledge that the software was developed 12 * by the University of California, Berkeley. The name of the 13 * University may not be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * @(#)mkmake.y 4.1 (Berkeley) 12/04/88 20 */ 21 22 typedef struct string { 23 int 24 hashval, 25 length; 26 char 27 *string; 28 struct string 29 *next; 30 } string_t; 31 32 /* 33 * The deal with these is that they exist on various lists. 34 * 35 * First off, they are on a temporary list during the time they 36 * are in the active focus of the parser. 37 * 38 * Secondly, they live on one of three queues: 39 * 1. Variables 40 * 2. Targets 41 * 3. Actions 42 * (and, we restrict any given one to live on one and only one such list) 43 * 44 * Also, they may live on the list of values for someone else's variable, 45 * or as someone's dependancy. 46 */ 47 48 typedef struct same { 49 string_t 50 *string; /* My name */ 51 struct same 52 *nexttoken, /* Next pointer */ 53 *lasttoken, /* Back pointer */ 54 *depend_list, /* If target, dependancies */ 55 *action_list, /* If target, actions */ 56 *value_list, /* If variable, value list */ 57 *shell_item; /* If a shell variable, current value */ 58 } same_t; 59 60 %} 61 62 %union { 63 string_t *string; 64 same_t *same; 65 int intval; 66 } 67 68 %start makefile 69 %token <string> TOKEN QUOTED_STRING 70 %token <intval> FOR IN DO DONE 71 %token <intval> MACRO_CHAR NL WHITE_SPACE 72 %token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t' 73 %type <same> target target1 assignment assign1 actions action 74 %type <same> command_list list list_element 75 %type <same> for_statement maybe_at_minus tokens token 76 %type <same> maybe_white_space 77 %type <intval> white_space macro_char 78 %% 79 80 makefile : lines; 81 82 lines : line 83 | lines line 84 ; 85 86 line : NL 87 | assignment 88 | target_action 89 ; 90 91 assignment : assign1 tokens NL 92 { 93 assign($1, $2); 94 } 95 | assign1 NL 96 { 97 assign($1, same_copy(null)); 98 } 99 ; 100 101 assign1: token maybe_white_space '=' maybe_white_space 102 ; 103 104 target_action: target actions 105 { 106 add_targets_actions($1, $2); 107 } 108 | target 109 { 110 add_targets_actions($1, 0); 111 } 112 ; 113 114 target : target1 tokens NL 115 { 116 $$ = add_depends($1, $2); 117 } 118 | target1 NL 119 { 120 $$ = add_depends($1, same_copy(null)); 121 } 122 ; 123 124 target1: tokens maybe_white_space ':' maybe_white_space 125 { 126 $$ = ws_merge($1); 127 } 128 ; 129 130 actions: action 131 | actions action 132 { 133 $$ = same_cat(same_cat($1, same_copy(newline)), $2); 134 } 135 ; 136 137 action: white_space command_list NL 138 { 139 $$ = $2; 140 } 141 | white_space for_statement do command_list semi_colon done NL 142 { 143 $$ = do_command($2, $4); 144 } 145 ; 146 147 for_statement: maybe_at_minus FOR white_space token 148 in tokens semi_colon 149 { 150 $$ = for_statement($1, $4, ws_merge(expand_variables($6, 0))); 151 } 152 ; 153 154 in: white_space IN white_space 155 do: white_space DO white_space 156 ; 157 158 done: white_space DONE 159 ; 160 161 semi_colon: ';' 162 ; 163 164 command_list: list 165 | '(' list maybe_white_space ')' 166 { 167 $$ = same_cat($2, same_copy(cwd_line)); 168 } 169 ; 170 171 list: token 172 | list list_element 173 { 174 $$ = same_cat($1, $2); 175 } 176 | list white_space list_element 177 { 178 $$ = same_cat($1, same_cat(same_copy(blank), $3)); 179 } 180 ; 181 182 list_element: token 183 | semi_colon 184 { 185 $$ = same_copy(newline); 186 } 187 ; 188 189 maybe_at_minus: /* empty */ 190 { 191 $$ = same_copy(null); 192 } 193 | '@' 194 { 195 char buffer[2]; 196 197 buffer[0] = $1; 198 buffer[1] = 0; 199 $$ = same_item(string_lookup(buffer)); 200 } 201 | '-' 202 { 203 char buffer[2]; 204 205 buffer[0] = $1; 206 buffer[1] = 0; 207 $$ = same_item(string_lookup(buffer)); 208 } 209 ; 210 211 tokens : token 212 | tokens maybe_white_space token 213 { 214 $$ = same_cat($1, same_cat($2, $3)); 215 } 216 ; 217 218 token: TOKEN 219 { 220 $$ = same_item($1); 221 } 222 | QUOTED_STRING 223 { 224 $$ = same_item($1); 225 } 226 | '$' macro_char 227 { 228 char buffer[3]; 229 230 buffer[0] = '$'; 231 buffer[1] = $2; 232 buffer[2] = 0; 233 234 $$ = same_item(string_lookup(buffer)); 235 } 236 | '$' '$' TOKEN 237 { 238 $$ = shell_variable(same_item($3)); 239 } 240 | MACRO_CHAR 241 { 242 $$ = same_char($1); 243 } 244 | '$' '{' TOKEN '}' 245 { 246 $$ = variable(same_item($3)); 247 } 248 | '$' '(' TOKEN ')' 249 { 250 $$ = variable(same_item($3)); 251 } 252 | '$' TOKEN 253 { 254 $$ = variable(same_item($2)); 255 } 256 | '-' 257 { 258 $$ = same_char('-'); 259 } 260 | '@' 261 { 262 $$ = same_char('@'); 263 } 264 ; 265 266 macro_char: MACRO_CHAR 267 | '@' 268 ; 269 270 maybe_white_space: 271 { 272 $$ = same_copy(null); 273 } 274 | white_space 275 { 276 $$ = same_char($1); 277 } 278 ; 279 280 white_space : WHITE_SPACE 281 | white_space WHITE_SPACE 282 ; 283 %% 284 #include <stdio.h> 285 #include <ctype.h> 286 287 static int last_char, last_saved = 0; 288 static int column = 0, lineno = 1; 289 290 291 static string_t 292 *strings = 0; 293 294 static same_t 295 *shell_variables = 0, 296 *shell_special = 0, 297 *variables = 0, 298 *targets = 0, 299 *actions = 0; 300 301 static same_t 302 *null, 303 *blank, 304 *cwd_line, 305 *newline; 306 307 extern char *malloc(); 308 309 static unsigned int 310 clock = -1; 311 312 struct { 313 same_t *first; 314 int next; 315 } visit_stack[20]; /* 20 maximum */ 316 317 #define visit(what,via) \ 318 (visit_stack[++clock].next = 0, visit_stack[clock].first = via = what) 319 #define visited(via) (visitcheck(via) || ((via) == 0) \ 320 || (visit_stack[clock].next && (via == visit_stack[clock].first))) 321 #define visit_next(via) (visit_stack[clock].next = 1, (via) = (via)->nexttoken) 322 #define visit_end() (clock--) 323 324 yyerror(s) 325 char *s; 326 { 327 fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s); 328 do_dump(); 329 } 330 331 int 332 visitcheck(same) 333 same_t *same; 334 { 335 if (same->string == 0) { 336 yyerror("BUG - freed 'same' in use..."); 337 exit(1); 338 } 339 return 0; 340 } 341 342 int 343 string_hashof(string, length) 344 char *string; 345 int length; 346 { 347 register int i = 0; 348 349 while (length--) { 350 i = (i<<3) + *string ^ ((i>>28)&0x7); 351 } 352 return i; 353 } 354 355 int 356 string_same(s1, s2) 357 string_t 358 *s1, *s2; 359 { 360 if ((s1->hashval == s2->hashval) && (s1->length == s2->length) 361 && (memcmp(s1->string, s2->string, s1->length) == 0)) { 362 return 1; 363 } else { 364 return 0; 365 } 366 } 367 368 string_t * 369 string_lookup(string) 370 char *string; 371 { 372 string_t ours; 373 string_t *ptr; 374 375 ours.length = strlen(string); 376 ours.hashval = string_hashof(string, ours.length); 377 ours.string = string; 378 379 for (ptr = strings; ptr; ptr = ptr->next) { 380 if (string_same(&ours, ptr)) { 381 return ptr; 382 } 383 } 384 if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) { 385 fprintf(stderr, "No space to add string *%s*!\n", string); 386 exit(1); 387 } 388 ptr->hashval = ours.hashval; 389 ptr->length = ours.length; 390 if ((ptr->string = malloc(ours.length+1)) == 0) { 391 fprintf(stderr, "No space to add literal *%s*!\n", string); 392 exit(1); 393 } 394 memcpy(ptr->string, string, ours.length+1); 395 ptr->next = strings; 396 strings = ptr; 397 return ptr; 398 } 399 400 #define same_singleton(s) ((s)->nexttoken == (s)) 401 402 same_t * 403 same_search(list, token) 404 same_t 405 *list, 406 *token; 407 { 408 same_t *ptr; 409 410 ptr = list; 411 for (visit(list, ptr); !visited(ptr); visit_next(ptr)) { 412 string_t *string; 413 414 string = ptr->string; 415 if (string_same(string, token->string)) { 416 visit_end(); 417 return ptr; 418 } 419 } 420 visit_end(); 421 return 0; 422 } 423 424 same_t * 425 same_cat(list, tokens) 426 same_t 427 *list, 428 *tokens; 429 { 430 same_t *last; 431 432 if (tokens == 0) { 433 return list; 434 } 435 if (list) { 436 last = tokens->lasttoken; 437 tokens->lasttoken = list->lasttoken; 438 list->lasttoken = last; 439 tokens->lasttoken->nexttoken = tokens; 440 last->nexttoken = list; 441 return list; 442 } else { 443 return tokens; 444 } 445 } 446 447 same_t * 448 same_item(string) 449 string_t *string; 450 { 451 same_t *ptr; 452 453 if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) { 454 fprintf(stderr, "No more space for tokens!\n"); 455 exit(1); 456 } 457 memset((char *)ptr, 0, sizeof *ptr); 458 ptr->nexttoken = ptr->lasttoken = ptr; 459 ptr->string = string; 460 return ptr; 461 } 462 463 same_t * 464 same_copy(same) 465 same_t *same; 466 { 467 same_t *head, *copy; 468 469 head = 0; 470 for (visit(same, copy); !visited(copy); visit_next(copy)) { 471 same_t *ptr; 472 473 ptr = same_item(copy->string); 474 head = same_cat(head, ptr); 475 } 476 visit_end(); 477 return head; 478 } 479 480 481 same_t * 482 same_merge(t1, t2) 483 same_t 484 *t1, 485 *t2; 486 { 487 if (same_singleton(t1) && same_singleton(t2)) { 488 int length = strlen(t1->string->string)+strlen(t2->string->string); 489 char *buffer = malloc(length+1); 490 same_t *value; 491 492 if (buffer == 0) { 493 yyerror("No space to merge strings in same_merge!"); 494 exit(1); 495 } 496 strcpy(buffer, t1->string->string); 497 strcat(buffer, t2->string->string); 498 value = same_item(string_lookup(buffer)); 499 free(buffer); 500 return value; 501 } else { 502 yyerror("Internal error - same_merge with non-singletons"); 503 exit(1); 504 } 505 } 506 507 508 void 509 same_free(list) 510 same_t *list; 511 { 512 same_t *token, *ptr; 513 514 if (list == 0) { 515 return; 516 } 517 518 token = list; 519 do { 520 ptr = token->nexttoken; 521 token->string = 0; 522 (void) free((char *)token); 523 token = ptr; 524 } while (token != list); 525 } 526 527 same_t * 528 same_unlink(token) 529 same_t 530 *token; 531 { 532 same_t *tmp; 533 534 if (token == 0) { 535 return 0; 536 } 537 if ((tmp = token->nexttoken) == token) { 538 tmp = 0; 539 } 540 token->lasttoken->nexttoken = token->nexttoken; 541 token->nexttoken->lasttoken = token->lasttoken; 542 token->nexttoken = token->lasttoken = token; 543 return tmp; 544 } 545 546 void 547 same_replace(old, new) 548 same_t 549 *old, 550 *new; 551 { 552 new->lasttoken->nexttoken = old->nexttoken; 553 old->nexttoken->lasttoken = new->lasttoken; 554 new->lasttoken = old->lasttoken; 555 /* rather than 556 * old->lasttoken->nexttoken = new 557 * we update in place (for the case where there isn't anything else) 558 */ 559 *old = *new; 560 } 561 562 563 same_t * 564 same_char(ch) 565 char ch; 566 { 567 char buffer[2]; 568 569 buffer[0] = ch; 570 buffer[1] = 0; 571 572 return same_item(string_lookup(buffer)); 573 } 574 575 576 void 577 add_target(target, actions) 578 same_t 579 *target, 580 *actions; 581 { 582 same_t *ptr; 583 584 if ((ptr = same_search(targets, target)) == 0) { 585 targets = same_cat(targets, target); 586 ptr = target; 587 } else { 588 ptr->depend_list = same_cat(ptr->depend_list, target->depend_list); 589 } 590 if (actions) { 591 if (ptr->action_list) { 592 same_free(ptr->action_list); 593 } 594 ptr->action_list = same_copy(actions); 595 } 596 } 597 598 599 same_t * 600 add_targets_actions(target, actions) 601 same_t 602 *target, 603 *actions; 604 { 605 same_t *ptr; 606 607 if (target == 0) { 608 return 0; 609 } 610 do { 611 ptr = same_unlink(target); 612 add_target(target, actions); 613 target = ptr; 614 } while (target); 615 616 same_free(actions); 617 return 0; 618 } 619 620 same_t * 621 add_depends(target, depends) 622 same_t 623 *target, 624 *depends; 625 { 626 same_t *original = target; 627 628 depends = same_cat(depends, same_copy(blank)); /* Separator */ 629 630 for (visit(original, target); !visited(target); visit_next(target)) { 631 target->depend_list = same_cat(target->depend_list, same_copy(depends)); 632 } 633 visit_end(); 634 same_free(depends); 635 636 return original; 637 } 638 639 640 /* 641 * We know that variable is a singleton 642 */ 643 644 void 645 assign(variable, value) 646 same_t 647 *variable, 648 *value; 649 { 650 same_t *ptr; 651 652 if ((ptr = same_search(variables, variable)) != 0) { 653 same_free(ptr->value_list); 654 variables = same_unlink(ptr); 655 same_free(ptr); 656 } 657 variable->value_list = value; 658 variables = same_cat(variables, variable); 659 } 660 661 same_t * 662 value_of(variable) 663 same_t *variable; 664 { 665 same_t *ptr = same_search(variables, variable); 666 667 if (ptr == 0) { 668 return same_copy(null); 669 } else { 670 return same_copy(ptr->value_list); 671 } 672 } 673 674 675 same_t * 676 expand_variables(token, free) 677 same_t *token; 678 int free; 679 { 680 same_t *head = 0; 681 682 if (!free) { 683 token = same_copy(token); /* Get our private copy */ 684 } 685 686 while (token) { 687 char *string = token->string->string; 688 same_t *tmp = same_unlink(token); 689 690 if ((string[0] == '$') && (string[1] == '{')) { /* Expand time */ 691 int len = strlen(string); 692 693 string[len-1] = 0; 694 head = same_cat(head, expand_variables( 695 value_of(same_item(string_lookup(string+2))), 1)); 696 string[len-1] = '}'; 697 } else { 698 head = same_cat(head, token); 699 } 700 token = tmp; 701 } 702 return head; 703 } 704 705 706 same_t * 707 ws_merge(list) 708 same_t *list; 709 { 710 same_t *newlist = 0, *item; 711 int what = 0; 712 713 while (list) { 714 switch (what) { 715 case 0: 716 if (isspace(list->string->string[0])) { 717 ; 718 } else { 719 item = same_item(list->string); 720 what = 1; 721 } 722 break; 723 case 1: 724 if (isspace(list->string->string[0])) { 725 newlist = same_cat(newlist, item); 726 item = 0; 727 what = 0; 728 } else { 729 item = same_merge(item, same_item(list->string)); 730 what = 1; 731 } 732 break; 733 } 734 list = same_unlink(list); 735 } 736 return same_cat(newlist, item); 737 } 738 739 740 same_t * 741 variable(var_name) 742 same_t *var_name; 743 { 744 int length = strlen(var_name->string->string); 745 same_t *resolved; 746 char *newname; 747 748 if ((newname = malloc(length+1+3)) == 0) { 749 fprintf("Out of space for a variable name.\n"); 750 exit(1); 751 } 752 newname[0] = '$'; 753 newname[1] = '{'; 754 strcpy(newname+2, var_name->string->string); 755 strcat(newname, "}"); 756 resolved = same_item(string_lookup(newname)); 757 free(newname); 758 759 return resolved; 760 } 761 762 763 same_t * 764 shell_variable(var_name) 765 same_t *var_name; 766 { 767 int length = strlen(var_name->string->string); 768 same_t *resolved; 769 char *newname; 770 771 if ((newname = malloc(length+1+2)) == 0) { 772 fprintf("Out of space for a variable name.\n"); 773 exit(1); 774 } 775 newname[0] = '$'; 776 newname[1] = '$'; 777 strcpy(newname+2, var_name->string->string); 778 resolved = same_item(string_lookup(newname)); 779 free(newname); 780 781 return resolved; 782 } 783 784 same_t * 785 for_statement(special, variable, list) 786 same_t 787 *special, 788 *variable, 789 *list; 790 { 791 variable->shell_item = special; 792 variable->value_list = list; 793 return variable; 794 } 795 796 same_t * 797 do_command(forlist, commands) 798 same_t 799 *forlist, 800 *commands; 801 { 802 same_t 803 *special, 804 *command_list = 0, 805 *new_commands, 806 *tmp, 807 *shell_item, 808 *value_list = forlist->value_list; 809 char 810 *tmpstr, 811 *variable_name = forlist->string->string; 812 813 special = forlist->shell_item; 814 if (same_unlink(forlist->shell_item) != 0) { 815 yyerror("Unexpected second item in special part of do_command"); 816 exit(1); 817 } 818 819 while ((shell_item = value_list) != 0) { 820 value_list = same_unlink(shell_item); 821 /* Visit each item in commands. For each shell variable which 822 * matches ours, replace it with ours. 823 */ 824 new_commands = same_copy(commands); 825 for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) { 826 tmpstr = tmp->string->string; 827 if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) { 828 if (strcmp(tmpstr+2, variable_name) == 0) { 829 same_replace(tmp, same_copy(shell_item)); 830 } 831 } 832 } 833 visit_end(); 834 command_list = same_cat(command_list, new_commands); 835 } 836 return same_cat(command_list, same_copy(newline)); 837 } 838 839 840 int 841 Getchar() 842 { 843 if (last_saved) { 844 last_saved = 0; 845 return last_char; 846 } else { 847 int c; 848 c = getchar(); 849 switch (c) { 850 case '\n': 851 lineno++; 852 column = 0; 853 break; 854 default: 855 column++; 856 } 857 return c; 858 } 859 } 860 861 862 int 863 token_type(string) 864 char *string; 865 { 866 switch (string[0]) { 867 case 'f': 868 if (strcmp(string, "for") == 0) { 869 return FOR; 870 } 871 break; 872 case 'd': 873 if (string[1] == 'o') { 874 if (strcmp(string, "do") == 0) { 875 return DO; 876 } else if (strcmp(string, "done") == 0) { 877 return DONE; 878 } 879 } 880 break; 881 case 'i': 882 if (strcmp(string, "in") == 0) { 883 return IN; 884 } 885 break; 886 default: 887 break; 888 } 889 return TOKEN; 890 } 891 892 893 yylex() 894 { 895 #define ret_token(c) if (bufptr != buffer) { \ 896 save(c); \ 897 *bufptr = 0; \ 898 bufptr = buffer; \ 899 yylval.string = string_lookup(buffer); \ 900 return token_type(buffer); \ 901 } 902 #define save(c) { last_char = c; last_saved = 1; } 903 #if defined(YYDEBUG) 904 #define Return(c) if (yydebug) { \ 905 printf("[%d]", c); \ 906 fflush(stdout); \ 907 } \ 908 yyval.intval = c; \ 909 return c; 910 #else /* defined(YYDEBUG) */ 911 #define Return(y,c) { yylval.intval = c; return y; } 912 #endif /* defined(YYDEBUG) */ 913 914 915 static char buffer[500], *bufptr = buffer; 916 static int eof_found = 0; 917 int c; 918 919 if (eof_found != 0) { 920 eof_found++; 921 if (eof_found > 2) { 922 fprintf(stderr, "End of file ignored.\n"); 923 exit(1); 924 } 925 Return(EOF,0); 926 } 927 while ((c = Getchar()) != EOF) { 928 switch (c) { 929 case '#': 930 ret_token(c); 931 while (((c = Getchar()) != EOF) && (c != '\n')) { 932 ; 933 } 934 save(c); 935 break; 936 case '<': 937 case '?': 938 ret_token(c); 939 Return(MACRO_CHAR, c); 940 case '\t': 941 case ' ': 942 ret_token(c); 943 Return(WHITE_SPACE, c); 944 case '-': 945 case '@': 946 case ':': 947 case ';': 948 case '=': 949 case '$': 950 case '{': 951 case '}': 952 case '(': 953 case ')': 954 ret_token(c); 955 Return(c,c); 956 case '\'': 957 case '"': 958 if (bufptr != buffer) { 959 if (bufptr[-1] == '\\') { 960 bufptr[-1] = c; 961 } 962 break; 963 } else { 964 int newc; 965 966 ret_token(c); 967 *bufptr++ = c; 968 while (((newc = Getchar()) != EOF) && (newc != c)) { 969 *bufptr++ = newc; 970 } 971 *bufptr++ = c; 972 *bufptr = 0; 973 bufptr = buffer; 974 yylval.string = string_lookup(buffer); 975 return QUOTED_STRING; 976 } 977 case '\n': 978 if (bufptr != buffer) { 979 if (bufptr[-1] == '\\') { 980 bufptr--; 981 if ((c = Getchar()) != '\t') { 982 yyerror("continuation line doesn't begin with a tab"); 983 save(c); 984 } 985 ret_token(c); 986 Return(WHITE_SPACE, c); 987 } 988 } 989 ret_token(c); 990 Return(NL, 0); 991 default: 992 *bufptr++ = c; 993 break; 994 } 995 } 996 997 eof_found = 1; 998 999 ret_token(' '); 1000 Return(EOF, 0); 1001 } 1002 1003 #ifndef lint 1004 static char sccsid[] = "@(#)mkmake.y 4.1 (Berkeley) 12/04/88"; 1005 #endif /* not lint */ 1006 1007 main() 1008 { 1009 #define YYDEBUG 1010 extern int yydebug; 1011 1012 null = same_item(string_lookup("")); 1013 newline = same_item(string_lookup("\n")); 1014 blank = same_item(string_lookup(" ")); 1015 cwd_line = same_cat(same_copy(newline), 1016 same_cat(same_item(string_lookup("cd ${CWD}")), 1017 same_copy(newline))); 1018 1019 yyparse(); 1020 1021 do_dump(); 1022 1023 return 0; 1024 } 1025 1026 #if defined(YYDEBUG) 1027 dump_same(same) 1028 same_t *same; 1029 { 1030 same_t *same2; 1031 1032 for (visit(same, same2); !visited(same2); visit_next(same2)) { 1033 printf(same2->string->string); 1034 } 1035 visit_end(); 1036 } 1037 #endif /* YYDEBUG */ 1038 1039 do_dump() 1040 { 1041 string_t *string; 1042 same_t *same, *same2; 1043 1044 if (yydebug > 1) { 1045 printf("strings...\n"); 1046 for (string = strings; string; string = string->next) { 1047 printf("\t%s\n", string->string); 1048 } 1049 } 1050 1051 printf("# variables...\n"); 1052 for (visit(variables, same); !visited(same); visit_next(same)) { 1053 printf("%s =\t", same->string->string); 1054 for (visit(same->value_list, same2); !visited(same2); 1055 visit_next(same2)) { 1056 printf(same2->string->string); 1057 } 1058 visit_end(); 1059 printf("\n"); 1060 } 1061 visit_end(); 1062 1063 printf("\n\n#targets...\n"); 1064 for (visit(targets, same); !visited(same); visit_next(same)) { 1065 printf("\n%s:\t", same->string->string); 1066 for (visit(same->depend_list, same2); !visited(same2); 1067 visit_next(same2)) { 1068 printf(same2->string->string); 1069 } 1070 visit_end(); 1071 printf("\n\t"); 1072 for (visit(same->action_list, same2); !visited(same2); 1073 visit_next(same2)) { 1074 printf(same2->string->string); 1075 if (same2->string->string[0] == '\n') { 1076 printf("\t"); 1077 } 1078 } 1079 visit_end(); 1080 printf("\n"); 1081 } 1082 visit_end(); 1083 } 1084