- Timestamp:
- May 29, 2007 2:59:06 AM (18 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/Makefile.am
r937 r986 109 109 -DCONFIG_WITH_MATH \ 110 110 -DCONFIG_WITH_XARGS \ 111 -DCONFIG_WITH_NANOTS \ 111 112 -DCONFIG_PRETTY_COMMAND_PRINTING \ 112 113 \ -
trunk/src/kmk/Makefile.kmk
r953 r986 111 111 CONFIG_WITH_MATH \ 112 112 CONFIG_WITH_XARGS \ 113 CONFIG_WITH_NANOTS \ 113 114 CONFIG_PRETTY_COMMAND_PRINTING \ 114 115 \ -
trunk/src/kmk/function.c
r940 r986 42 42 #endif 43 43 #include <assert.h> /* bird */ 44 45 #if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) /* bird */ 46 # include <ctype.h> 47 # ifdef _MSC_VER 48 typedef __int64 math_int; 49 # else 50 # include <stdint.h> 51 typedef int64_t math_int; 52 # endif 53 #endif 54 55 #ifdef CONFIG_WITH_NANOTS /* bird */ 56 # ifdef WINDOWS32 57 # include <Windows.h> 58 # endif 59 #endif 44 60 45 61 … … 2664 2680 func_stack_push (char *o, char **argv, const char *funcname) 2665 2681 { 2666 2667 2682 do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */); 2683 return o; 2668 2684 } 2669 2685 … … 2673 2689 func_stack_pop_top (char *o, char **argv, const char *funcname) 2674 2690 { 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2691 struct variable *stack_var; 2692 const char *stack = argv[0]; 2693 const int return_item = argv[0][sizeof("stack-pop") - 1] == '\0'; 2694 2695 stack_var = lookup_variable (stack, strlen (stack) ); 2696 if (stack_var) 2697 { 2698 unsigned int len; 2699 const char *iterator = stack_var->value; 2700 char *lastitem = NULL; 2701 char *cur; 2702 2703 while ((cur = find_next_token (&iterator, &len))) 2704 lastitem = cur; 2705 2706 if (lastitem != NULL) 2707 { 2708 if (strcmp (funcname, "stack-popv") != 0) 2709 o = variable_buffer_output (o, lastitem, len); 2710 if (strcmp (funcname, "stack-top") != 0) 2711 { 2712 *lastitem = '\0'; 2713 while (lastitem > stack_var->value && isspace (lastitem[-1])) 2714 *--lastitem = '\0'; 2699 2715 #ifdef CONFIG_WITH_VALUE_LENGTH 2700 2701 #endif 2702 2703 2704 2705 2716 stack_var->value_length = lastitem - stack_var->value; 2717 #endif 2718 } 2719 } 2720 } 2721 return o; 2706 2722 } 2707 2723 #endif /* CONFIG_WITH_STACK */ 2708 2724 2725 #if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) 2726 /* outputs the number (as a string) into the variable buffer. */ 2727 static char * 2728 math_int_to_variable_buffer (char *o, math_int num) 2729 { 2730 static const char xdigits[17] = "0123456789abcdef"; 2731 int negative; 2732 char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20 2733 or 20 dec + sign + term => 22 */ 2734 char *str = &strbuf[sizeof (strbuf) - 1]; 2735 2736 negative = num < 0; 2737 if (negative) 2738 num = -num; 2739 2740 *str = '\0'; 2741 2742 do 2743 { 2744 #ifdef HEX_MATH_NUMBERS 2745 *--str = xdigits[num & 0xf]; 2746 num >>= 4; 2747 #else 2748 *--str = xdigits[num % 10]; 2749 num /= 10; 2750 #endif 2751 } 2752 while (num); 2753 2754 #ifdef HEX_MATH_NUMBERS 2755 *--str = 'x'; 2756 *--str = '0'; 2757 #endif 2758 2759 if (negative) 2760 *--str = '-'; 2761 2762 return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str); 2763 } 2764 #endif /* CONFIG_WITH_MATH || CONFIG_WITH_NANOTS */ 2765 2709 2766 #ifdef CONFIG_WITH_MATH 2710 2711 #include <ctype.h>2712 #ifdef _MSC_VER2713 typedef __int64 math_int;2714 #else2715 # include <stdint.h>2716 typedef int64_t math_int;2717 #endif2718 2767 2719 2768 /* Converts a string to an integer, causes an error if the format is invalid. */ … … 2721 2770 math_int_from_string (const char *str) 2722 2771 { 2723 const char *start; 2724 unsigned base = 0; 2725 int negative = 0; 2726 math_int num = 0; 2727 2728 /* strip spaces */ 2729 while (isspace (*str)) 2730 str++; 2731 if (!*str) 2732 { 2733 error (NILF, _("bad number: empty\n")); 2734 return 0; 2735 } 2736 start = str; 2737 2738 /* check for +/- */ 2739 while (*str == '+' || *str == '-' || isspace (*str)) 2740 if (*str++ == '-') 2741 negative = !negative; 2742 2743 /* check for prefix - we do not accept octal numbers, sorry. */ 2744 if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) 2745 { 2746 base = 16; 2747 str += 2; 2748 } 2749 else 2750 { 2751 /* look for a hex digit, if not found treat it as decimal */ 2752 const char *p2 = str; 2753 for ( ; *p2; p2++) 2754 if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) ) 2755 { 2756 base = 16; 2757 break; 2758 } 2759 if (base == 0) 2760 base = 10; 2761 } 2762 2763 /* must have at least one digit! */ 2764 if ( !isascii (*str) 2765 || !(base == 16 ? isxdigit (*str) : isdigit (*str)) ) 2766 { 2767 error (NILF, _("bad number: '%s'\n"), start); 2768 return 0; 2769 } 2770 2771 /* convert it! */ 2772 while (*str && !isspace (*str)) 2773 { 2774 int ch = *str++; 2775 if (ch >= '0' && ch <= '9') 2776 ch -= '0'; 2777 else if (base == 16 && ch >= 'a' && ch <= 'f') 2778 ch -= 'a' - 10; 2779 else if (base == 16 && ch >= 'A' && ch <= 'F') 2780 ch -= 'A' - 10; 2781 else 2772 const char *start; 2773 unsigned base = 0; 2774 int negative = 0; 2775 math_int num = 0; 2776 2777 /* strip spaces */ 2778 while (isspace (*str)) 2779 str++; 2780 if (!*str) 2781 { 2782 error (NILF, _("bad number: empty\n")); 2783 return 0; 2784 } 2785 start = str; 2786 2787 /* check for +/- */ 2788 while (*str == '+' || *str == '-' || isspace (*str)) 2789 if (*str++ == '-') 2790 negative = !negative; 2791 2792 /* check for prefix - we do not accept octal numbers, sorry. */ 2793 if (*str == '0' && (str[1] == 'x' || str[1] == 'X')) 2794 { 2795 base = 16; 2796 str += 2; 2797 } 2798 else 2799 { 2800 /* look for a hex digit, if not found treat it as decimal */ 2801 const char *p2 = str; 2802 for ( ; *p2; p2++) 2803 if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) ) 2782 2804 { 2783 error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);2784 return 0;2805 base = 16; 2806 break; 2785 2807 } 2786 num *= base; 2787 num += ch; 2788 } 2789 2790 /* check trailing spaces. */ 2791 while (isspace (*str)) 2792 str++; 2793 if (*str) 2794 { 2795 error (NILF, _("bad number: '%s'\n"), start); 2796 return 0; 2797 } 2798 2799 return negative ? -num : num; 2800 } 2801 2802 /* outputs the number (as a string) into the variable buffer. */ 2803 static char * 2804 math_int_to_variable_buffer (char *o, math_int num) 2805 { 2806 static const char xdigits[17] = "0123456789abcdef"; 2807 int negative; 2808 char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20 */ 2809 char *str = &strbuf[sizeof (strbuf) - 1]; 2810 2811 negative = num < 0; 2812 if (negative) 2813 num = -num; 2814 2815 *str-- = '\0'; 2816 2817 do 2818 { 2819 *str-- = xdigits[num & 0xf]; 2820 num >>= 4; 2821 } 2822 while (num); 2823 2824 *str-- = 'x'; 2825 *str = '0'; 2826 2827 if (negative) 2828 *--str = '-'; 2829 2830 return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str); 2808 if (base == 0) 2809 base = 10; 2810 } 2811 2812 /* must have at least one digit! */ 2813 if ( !isascii (*str) 2814 || !(base == 16 ? isxdigit (*str) : isdigit (*str)) ) 2815 { 2816 error (NILF, _("bad number: '%s'\n"), start); 2817 return 0; 2818 } 2819 2820 /* convert it! */ 2821 while (*str && !isspace (*str)) 2822 { 2823 int ch = *str++; 2824 if (ch >= '0' && ch <= '9') 2825 ch -= '0'; 2826 else if (base == 16 && ch >= 'a' && ch <= 'f') 2827 ch -= 'a' - 10; 2828 else if (base == 16 && ch >= 'A' && ch <= 'F') 2829 ch -= 'A' - 10; 2830 else 2831 { 2832 error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start); 2833 return 0; 2834 } 2835 num *= base; 2836 num += ch; 2837 } 2838 2839 /* check trailing spaces. */ 2840 while (isspace (*str)) 2841 str++; 2842 if (*str) 2843 { 2844 error (NILF, _("bad number: '%s'\n"), start); 2845 return 0; 2846 } 2847 2848 return negative ? -num : num; 2831 2849 } 2832 2850 … … 2835 2853 func_int_add (char *o, char **argv, const char *funcname) 2836 2854 { 2837 2838 2839 2840 2841 2842 2843 2844 2855 math_int num; 2856 int i; 2857 2858 num = math_int_from_string (argv[0]); 2859 for (i = 1; argv[i]; i++) 2860 num += math_int_from_string (argv[i]); 2861 2862 return math_int_to_variable_buffer (o, num); 2845 2863 } 2846 2864 … … 2849 2867 func_int_sub (char *o, char **argv, const char *funcname) 2850 2868 { 2851 2852 2853 2854 2855 2856 2857 2858 2869 math_int num; 2870 int i; 2871 2872 num = math_int_from_string (argv[0]); 2873 for (i = 1; argv[i]; i++) 2874 num -= math_int_from_string (argv[i]); 2875 2876 return math_int_to_variable_buffer (o, num); 2859 2877 } 2860 2878 … … 2863 2881 func_int_mul (char *o, char **argv, const char *funcname) 2864 2882 { 2865 2866 2867 2868 2869 2870 2871 2872 2883 math_int num; 2884 int i; 2885 2886 num = math_int_from_string (argv[0]); 2887 for (i = 1; argv[i]; i++) 2888 num *= math_int_from_string (argv[i]); 2889 2890 return math_int_to_variable_buffer (o, num); 2873 2891 } 2874 2892 … … 2877 2895 func_int_div (char *o, char **argv, const char *funcname) 2878 2896 { 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2897 math_int num; 2898 math_int divisor; 2899 int i; 2900 2901 num = math_int_from_string (argv[0]); 2902 for (i = 1; argv[i]; i++) 2903 { 2904 divisor = math_int_from_string (argv[i]); 2905 if (!divisor) 2906 { 2907 error (NILF, _("divide by zero ('%s')\n"), argv[i]); 2908 return math_int_to_variable_buffer (o, 0); 2909 } 2910 num /= divisor; 2911 } 2912 2913 return math_int_to_variable_buffer (o, num); 2896 2914 } 2897 2915 … … 2901 2919 func_int_mod (char *o, char **argv, const char *funcname) 2902 2920 { 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2921 math_int num; 2922 math_int divisor; 2923 2924 num = math_int_from_string (argv[0]); 2925 divisor = math_int_from_string (argv[1]); 2926 if (!divisor) 2927 { 2928 error (NILF, _("divide by zero ('%s')\n"), argv[1]); 2929 return math_int_to_variable_buffer (o, 0); 2930 } 2931 num %= divisor; 2932 2933 return math_int_to_variable_buffer (o, num); 2916 2934 } 2917 2935 … … 2920 2938 func_int_not (char *o, char **argv, const char *funcname) 2921 2939 { 2922 2923 2924 2925 2926 2927 2940 math_int num; 2941 2942 num = math_int_from_string (argv[0]); 2943 num = ~num; 2944 2945 return math_int_to_variable_buffer (o, num); 2928 2946 } 2929 2947 … … 2932 2950 func_int_and (char *o, char **argv, const char *funcname) 2933 2951 { 2934 2935 2936 2937 2938 2939 2940 2941 2952 math_int num; 2953 int i; 2954 2955 num = math_int_from_string (argv[0]); 2956 for (i = 1; argv[i]; i++) 2957 num &= math_int_from_string (argv[i]); 2958 2959 return math_int_to_variable_buffer (o, num); 2942 2960 } 2943 2961 … … 2946 2964 func_int_or (char *o, char **argv, const char *funcname) 2947 2965 { 2948 2949 2950 2951 2952 2953 2954 2955 2966 math_int num; 2967 int i; 2968 2969 num = math_int_from_string (argv[0]); 2970 for (i = 1; argv[i]; i++) 2971 num |= math_int_from_string (argv[i]); 2972 2973 return math_int_to_variable_buffer (o, num); 2956 2974 } 2957 2975 … … 2960 2978 func_int_xor (char *o, char **argv, const char *funcname) 2961 2979 { 2962 2963 2964 2965 2966 2967 2968 2969 2980 math_int num; 2981 int i; 2982 2983 num = math_int_from_string (argv[0]); 2984 for (i = 1; argv[i]; i++) 2985 num ^= math_int_from_string (argv[i]); 2986 2987 return math_int_to_variable_buffer (o, num); 2970 2988 } 2971 2989 … … 2999 3017 3000 3018 #endif /* CONFIG_WITH_MATH */ 3019 3020 #ifdef CONFIG_WITH_NANOTS 3021 /* Returns the current timestamp as nano seconds. The time 3022 source is a high res monotone one if the platform provides 3023 this (and we know about it). 3024 3025 Tip. Use this with int-sub to profile makefile reading 3026 and similar. */ 3027 static char * 3028 func_nanots (char *o, char **argv, const char *funcname) 3029 { 3030 math_int ts; 3031 3032 #if defined (WINDOWS32) 3033 static int s_state = -1; 3034 static LARGE_INTEGER s_freq; 3035 3036 if (s_state == -1) 3037 s_state = QueryPerformanceFrequency (&s_freq); 3038 if (s_state) 3039 { 3040 LARGE_INTEGER pc; 3041 if (!QueryPerformanceCounter (&pc)) 3042 { 3043 s_state = 0; 3044 return func_nanots (o, argv, funcname); 3045 } 3046 ts = (math_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000); 3047 } 3048 else 3049 { 3050 /* fall back to low resolution system time. */ 3051 LARGE_INTEGER bigint; 3052 FILETIME ft = {0,0}; 3053 GetSystemTimeAsFileTime (&ft); 3054 bigint.u.LowPart = ft.dwLowDateTime; 3055 bigint.u.HighPart = ft.dwLowDateTime; 3056 ts = bigint.QuadPart * 10000; 3057 } 3058 3059 /* FIXME: Linux and others has the realtime clock_* api, detect and use it. */ 3060 3061 #elif HAVE_GETTIMEOF_DAY 3062 struct timeval tv; 3063 if (!gettimeofday (&tv, NULL)) 3064 ts = (math_int)tv.tv_sec * 1000000000 3065 + tv.tv_usec * 1000; 3066 else 3067 { 3068 error (NILF, _("$(nanots): gettimeofday failed")); 3069 ts = 0; 3070 } 3071 3072 #else 3073 # error "PORTME" 3074 #endif 3075 3076 return math_int_to_variable_buffer (o, ts); 3077 } 3078 #endif 3001 3079 3002 3080 … … 3098 3176 { STRING_SIZE_TUPLE("int-le"), 2, 2, 1, func_int_cmp}, 3099 3177 #endif 3178 #ifdef CONFIG_WITH_NANOTS 3179 { STRING_SIZE_TUPLE("nanots"), 0, 0, 0, func_nanots}, 3180 #endif 3100 3181 #ifdef KMK_HELPERS 3101 3182 { STRING_SIZE_TUPLE("kb-src-tool"), 1, 1, 0, func_kbuild_source_tool},
Note:
See TracChangeset
for help on using the changeset viewer.