- Timestamp:
- Oct 5, 2007, 10:22:50 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/read.c
r1173 r1181 477 477 use the normal eval routine but does all the parsing itself. This isn't, 478 478 as much work as it sounds, because the necessary feature set is very 479 limited. */ 479 limited. 480 481 eval_include_dep groks: 482 483 define var 484 endef 485 486 var [|:|?|>]= value [\] 487 488 [\] 489 file: [deps] [\] 490 491 */ 480 492 void 481 493 eval_include_dep (const char *name, struct floc *f) … … 556 568 } 557 569 558 /* define var ... endef for command tracking. */ 570 /* define var 571 ... 572 endef */ 559 573 if (strneq (cur, "define ", 7)) 560 574 { … … 652 666 NULL /* global set */, f); 653 667 } 654 /* file: deps */ 668 669 /* file: deps 670 OR 671 variable [:]= value */ 655 672 else 656 673 { 657 struct nameseq *filenames = 0; 658 struct dep *deps = 0; 659 struct dep **nextdep = &deps; 660 struct dep *dep; 661 int next_line = 1; 662 char *colonp; 663 664 /* look for a colon, ASSUME it's on the same line. */ 674 const char *colonp; 675 const char *equalp; 676 677 /* Look for a colon and an equal sign, optimize for colon. 678 Only one file is support and the colon / equal must be on 679 the same line. */ 665 680 colonp = memchr (cur, ':', file_end - cur); 666 681 #ifdef HAVE_DOS_PATHS 667 682 while ( colonp 683 && colonp + 1 < file_end 668 684 && (colonp[1] == '/' || colonp[1] == '\\') 669 685 && colonp > cur … … 673 689 colonp = memchr (colonp + 1, ':', file_end - (colonp + 1)); 674 690 #endif 675 if (!colonp || memchr (cur, '\n', colonp - cur)) 691 endp = NULL; 692 if ( !colonp 693 || (endp = memchr (cur, '\n', colonp - cur))) 676 694 { 677 error (f, "%s(%d): no colon.", name, line_no); 678 break; 679 } 680 681 /* extract the filename, ASSUME a single one. */ 682 endp = colonp; 683 while (endp > cur && isblank ((unsigned char)endp[-1])) 684 --endp; 685 if (cur == endp) 686 { 687 error (f, "%s(%d): empty filename.", name, line_no); 688 break; 689 } 690 filenames = xmalloc (sizeof (struct nameseq)); 691 memset (filenames, 0, sizeof (*filenames)); 692 filenames->name = strcache_add_len (cur, endp - cur); 693 694 /* parse any dependencies. */ 695 cur = colonp + 1; 696 while (cur < file_end) 697 { 698 /* skip blanks and count lines. */ 699 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n') 700 ++cur; 701 if (cur >= file_end) 702 break; 703 if (*cur == '\n') 695 colonp = NULL; 696 equalp = memchr (cur, '=', (endp ? endp : file_end) - cur); 697 if ( !equalp 698 || (!endp && memchr (cur, '\n', equalp - cur))) 704 699 { 705 cur++; 706 line_no++; 700 error (f, "%s(%d): no colon.", name, line_no); 707 701 break; 708 702 } 709 710 /* continuation + eol? */ 711 if (*cur == '\\') 703 } 704 else 705 equalp = memchr (cur, '=', (colonp + 2 <= file_end 706 ? colonp + 2 : file_end) - cur); 707 if (equalp) 708 { 709 /* An assignment of some sort. */ 710 const char *var; 711 unsigned var_len; 712 const char *value_start; 713 const char *value_end; 714 char *value; 715 unsigned value_len; 716 unsigned multi_line = 0; 717 enum variable_flavor flavor; 718 719 /* figure the flavor first. */ 720 flavor = f_recursive; 721 if (equalp > cur) 712 722 { 713 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2 714 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3 715 : (file_end - cur == 1) ? 1 : 0; 716 if (eol_len) 723 if (equalp[-1] == ':') 724 flavor = f_simple; 725 else if (equalp[-1] == '?') 726 flavor = f_conditional; 727 else if (equalp[-1] == '+') 728 flavor = f_append; 729 else if (equalp[-1] == '>') 730 flavor = f_prepend; 731 } 732 733 /* extract the variable name. */ 734 endp = flavor == f_recursive ? equalp : equalp - 1; 735 while (endp > cur && isblank ((unsigned char)endp[-1])) 736 --endp; 737 var_len = endp - cur; 738 if (!var_len) 739 { 740 error (f, "%s(%d): empty variable. (includedep)", name, line_no); 741 break; 742 } 743 if ( memchr (cur, '$', var_len) 744 || memchr (cur, ' ', var_len) 745 || memchr (cur, '\t', var_len)) 746 { 747 error (f, "%s(%d): fancy variable name. (includedep)", name, line_no); 748 break; 749 } 750 var = strcache_add_len (cur, var_len); 751 752 /* find the start of the value. */ 753 cur = equalp + 1; 754 while (cur < file_end && isblank ((unsigned char)*cur)) 755 cur++; 756 value_start = cur; 757 758 /* find the end of the value / line (this isn't 101% correct). */ 759 value_end = cur; 760 while (cur < file_end) 761 { 762 endp = value_end = memchr (cur, '\n', file_end - cur); 763 if (!value_end) 764 value_end = file_end; 765 if (value_end - 1 >= cur && value_end[-1] == '\r') 766 --value_end; 767 if (value_end - 1 < cur || value_end[-1] != '\\') 717 768 { 718 cur += eol_len; 769 cur = endp ? endp + 1 : file_end; 770 break; 771 } 772 --value_end; 773 if (value_end - 1 >= cur && value_end[-1] == '\\') 774 { 775 error (f, "%s(%d): fancy escaping! (includedep)", name, line_no); 776 cur = NULL; 777 break; 778 } 779 if (!endp) 780 { 781 cur = file_end; 782 break; 783 } 784 785 cur = endp + 1; 786 ++multi_line; 787 ++line_no; 788 } 789 if (!cur) 790 break; 791 ++line_no; 792 793 /* make a copy of the value, converting \r\n to \n, and define it. */ 794 value_len = value_end - value_start; 795 value = xmalloc (value_len + 1); 796 if (!multi_line) 797 memcpy (value, value_start, value_len); 798 else 799 { 800 /* unescape it */ 801 const char *src = value_start; 802 char *dst = value; 803 while (src < value_end) 804 { 805 const char *nextp; 806 807 endp = memchr (src, '\n', value_end - src); 808 if (!endp) 809 nextp = endp = value_end; 810 else 811 nextp = endp + 1; 812 if (endp > src && endp[-1] == '\r') 813 --endp; 814 if (endp > src && endp[-1] == '\\') 815 --endp; 816 817 if (src != value_start) 818 *dst++ = '\n'; 819 memcpy (dst, src, endp - src); 820 dst += endp - src; 821 src = nextp; 822 } 823 value_len = dst - value; 824 } 825 value [value_len] = '\0'; 826 827 /* do the definition */ 828 if (flavor == f_recursive 829 || ( flavor == f_simple 830 && !memchr (value, '$', value_len))) 831 define_variable_in_set (var, var_len, value, value_len, 832 0 /* don't duplicate */, o_file, 833 flavor == f_recursive /* recursive */, 834 NULL /* global set */, f); 835 else 836 { 837 do_variable_definition (f, var, value, o_file, flavor, 838 0 /* not target var */); 839 free (value); 840 } 841 } 842 else 843 { 844 /* file: dependencies */ 845 846 struct nameseq *filenames = 0; 847 struct dep *deps = 0; 848 struct dep **nextdep = &deps; 849 struct dep *dep; 850 int next_line = 1; 851 852 /* extract the filename, ASSUME a single one. */ 853 endp = colonp; 854 while (endp > cur && isblank ((unsigned char)endp[-1])) 855 --endp; 856 if (cur == endp) 857 { 858 error (f, "%s(%d): empty filename.", name, line_no); 859 break; 860 } 861 if ( memchr (cur, '$', endp - cur) 862 || memchr (cur, ' ', endp - cur) 863 || memchr (cur, '\t', endp - cur)) 864 { 865 error (f, "%s(%d): multiple / fancy file name. (includedep)", name, line_no); 866 break; 867 } 868 filenames = xmalloc (sizeof (struct nameseq)); 869 memset (filenames, 0, sizeof (*filenames)); 870 filenames->name = strcache_add_len (cur, endp - cur); 871 872 /* parse any dependencies. */ 873 cur = colonp + 1; 874 while (cur < file_end) 875 { 876 /* skip blanks and count lines. */ 877 while (cur < file_end && isspace ((unsigned char)*cur) && *cur != '\n') 878 ++cur; 879 if (cur >= file_end) 880 break; 881 if (*cur == '\n') 882 { 883 cur++; 719 884 line_no++; 720 continue;885 break; 721 886 } 887 888 /* continuation + eol? */ 889 if (*cur == '\\') 890 { 891 unsigned eol_len = (file_end - cur > 1 && cur[1] == '\n') ? 2 892 : (file_end - cur > 2 && cur[1] == '\r' && cur[2] == '\n') ? 3 893 : (file_end - cur == 1) ? 1 : 0; 894 if (eol_len) 895 { 896 cur += eol_len; 897 line_no++; 898 continue; 899 } 900 } 901 902 /* find the end of the filename */ 903 endp = cur; 904 while (endp < file_end && !isspace ((unsigned char)*endp)) 905 ++endp; 906 907 /* add it to the list. */ 908 *nextdep = dep = alloc_dep (); 909 dep->name = strcache_add_len (cur, endp - cur); 910 nextdep = &dep->next; 911 912 cur = endp; 722 913 } 723 914 724 /* find the end of the filename */ 725 endp = cur; 726 while (endp < file_end && !isspace ((unsigned char)*endp)) 727 ++endp; 728 729 /* add it to the list. */ 730 *nextdep = dep = alloc_dep (); 731 dep->name = strcache_add_len (cur, endp - cur); 732 nextdep = &dep->next; 733 734 cur = endp; 915 /* enter the file with its dependencies. */ 916 record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f); 735 917 } 736 737 /* enter the file with its dependencies. */738 record_files (filenames, NULL, NULL, deps, 0, NULL, 0, 0, f);739 918 } 740 919 }
Note:
See TracChangeset
for help on using the changeset viewer.