Changeset 763 for trunk/src


Ignore:
Timestamp:
Jan 19, 2007, 2:29:43 AM (19 years ago)
Author:
bird
Message:

integer math functions.

Location:
trunk/src/gmake
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gmake/Makefile.kmk

    r750 r763  
    4040        CONFIG_WITH_COMPARE \
    4141        CONFIG_WITH_STACK \
     42        CONFIG_WITH_MATH \
    4243        EXPERIMENTAL \
    4344        \
     
    290291        CONFIG_WITH_TOUPPER_TOLOWER \
    291292        EXPERIMENTAL
    292        
     293
    293294kmk_gmake_SOURCES = \
    294295        main.c \
     
    341342include $(PATH_KBUILD)/footer.kmk
    342343
    343                        
     344
    344345#
    345346# Use checked in config.h instead of running ./Configure for it.
    346 #                       
     347#
    347348config.h.$(BUILD_TARGET) := config.h.$(BUILD_TARGET)
    348349config.h.win   := config.h.W32
     
    407408test_stack:
    408409        $(MAKE) -f testcase-stack.kmk
     410
     411test_math:
     412        $(MAKE) -f testcase-math.kmk
     413
     414
     415test_all:       test_math test_stack test_shell
  • trunk/src/gmake/function.c

    r750 r763  
    1919#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
    2020# include <assert.h>
    21 #endif 
     21#endif
    2222#include "make.h"
    2323#include "filedef.h"
     
    3838#ifdef KMK_HELPERS
    3939# include "kbuild.h"
    40 #endif 
     40#endif
    4141
    4242
     
    268268
    269269#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
    270 /* The maximum length of a function, once reached there is 
     270/* The maximum length of a function, once reached there is
    271271   it can't be function and we can skip the hash lookup drop out. */
    272272
     
    275275#else
    276276# define MAX_FUNCTION_LENGTH 10
    277 #endif 
     277#endif
    278278
    279279/* Look up a function by name.  */
     
    905905        p[len] = save;
    906906      }
    907 #endif 
     907#endif
    908908
    909909      result = allocated_variable_expand (body);
     
    14331433  if (v)
    14341434#ifdef CONFIG_WITH_VALUE_LENGTH
    1435     o = variable_buffer_output (o, v->value, 
     1435    o = variable_buffer_output (o, v->value,
    14361436                                v->value_length >= 0 ? v->value_length : strlen(v->value));
    14371437#else
    14381438    o = variable_buffer_output (o, v->value, strlen(v->value));
    1439 #endif 
     1439#endif
    14401440
    14411441  return o;
     
    19371937#else
    19381938static char *
    1939 #endif 
     1939#endif
    19401940abspath (const char *name, char *apath)
    19411941{
     
    21472147#else
    21482148          if (path[0] != '/' && cwd)
    2149 #endif 
     2149#endif
    21502150            {
    21512151              /* relative path, prefix with cwd. */
     
    21812181 return o;
    21822182}
    2183 #endif 
     2183#endif
    21842184
    21852185#ifdef CONFIG_WITH_TOUPPER_TOLOWER
     
    22272227
    22282228/* Worker for func_comp_vars() which is called if the comparision failed.
    2229    It will do the slow command by command comparision of the commands 
     2229   It will do the slow command by command comparision of the commands
    22302230   when there invoked as comp-cmds. */
    2231 static char * 
    2232 comp_vars_ne (char *o, const char *s1, const char *e1, const char *s2, const char *e2, 
     2231static char *
     2232comp_vars_ne (char *o, const char *s1, const char *e1, const char *s2, const char *e2,
    22332233              char *ne_retval, const char *funcname)
    22342234{
     
    22532253              break;
    22542254
    2255             /* 
     2255            /*
    22562256             * Inner compare loop which compares one line.
    22572257             * FIXME: parse quoting!
     
    22762276
    22772277            /*
    2278              * If we exited because of a difference try to end-of-command 
     2278             * If we exited because of a difference try to end-of-command
    22792279             * comparision, e.g. ignore trailing spaces.
    22802280             */
     
    23282328}
    23292329
    2330 /* 
     2330/*
    23312331    $(comp-vars var1,var2,not-equal-return)
    2332   or 
     2332  or
    23332333    $(comp-cmds cmd-var1,cmd-var2,not-equal-return)
    23342334
    2335   Compares the two variables (that's given by name to avoid unnecessary 
     2335  Compares the two variables (that's given by name to avoid unnecessary
    23362336  expanding) and return the string in the third argument if not equal.
    23372337  If equal, nothing is returned.
    23382338
    2339   comp-vars will to an exact comparision only stripping leading and 
     2339  comp-vars will to an exact comparision only stripping leading and
    23402340  trailing spaces.
    23412341
    2342   comp-cmds will compare command by command, ignoring not only leading 
     2342  comp-cmds will compare command by command, ignoring not only leading
    23432343  and trailing spaces on each line but also leading one leading '@' and '-'.
    23442344*/
     
    24632463  return o;
    24642464}
    2465 #endif 
     2465#endif
    24662466
    24672467
     
    25072507#ifdef CONFIG_WITH_VALUE_LENGTH
    25082508                stack_var->value_length = lastitem - stack_var->value;
    2509 #endif 
     2509#endif
    25102510              }
    25112511          }
     
    25142514}
    25152515#endif /* CONFIG_WITH_STACK */
     2516
     2517#ifdef CONFIG_WITH_MATH
     2518
     2519#include <ctype.h>
     2520#ifdef _MSC_VER
     2521typedef __int64 math_int;
     2522#else
     2523# include <stdint.h>
     2524typedef int64_t math_int;
     2525#endif
     2526
     2527/* Converts a string to an integer, causes an error if the format is invalid. */
     2528static math_int
     2529math_int_from_string (const char *str)
     2530{
     2531    const char *start;
     2532    unsigned base = 0;
     2533    int      negative = 0;
     2534    math_int num = 0;
     2535
     2536    /* strip spaces */
     2537    while (isspace (*str))
     2538      str++;
     2539    if (!*str)
     2540      {
     2541        error (NILF, _("bad number: empty\n"));
     2542        return 0;
     2543      }
     2544    start = str;
     2545
     2546    /* check for +/- */
     2547    while (*str == '+' || *str == '-' || isspace (*str))
     2548        if (*str++ == '-')
     2549          negative = !negative;
     2550
     2551    /* check for prefix - we do not accept octal numbers, sorry. */
     2552    if (*str == '0' && (str[1] == 'x' || str[1] == 'X'))
     2553      {
     2554        base = 16;
     2555        str += 2;
     2556      }
     2557    else
     2558      {
     2559        /* look for a hex digit, if not found treat it as decimal */
     2560        const char *p2 = str;
     2561        for ( ; *p2; p2++)
     2562          if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) )
     2563            {
     2564              base = 16;
     2565              break;
     2566            }
     2567        if (base == 0)
     2568          base = 10;
     2569      }
     2570
     2571    /* must have at least one digit! */
     2572    if (    !isascii (*str)
     2573        ||  !(base == 16 ? isxdigit (*str) : isdigit (*str)) )
     2574      {
     2575        error (NILF, _("bad number: '%s'\n"), start);
     2576        return 0;
     2577      }
     2578
     2579    /* convert it! */
     2580    while (*str && !isspace (*str))
     2581      {
     2582        int ch = *str++;
     2583        if (ch >= '0' && ch <= '9')
     2584          ch -= '0';
     2585        else if (base == 16 && ch >= 'a' && ch <= 'f')
     2586          ch -= 'a' - 10;
     2587        else if (base == 16 && ch >= 'A' && ch <= 'F')
     2588          ch -= 'A' - 10;
     2589        else
     2590          {
     2591            error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);
     2592            return 0;
     2593          }
     2594        num *= base;
     2595        num += ch;
     2596      }
     2597
     2598    /* check trailing spaces. */
     2599    while (isspace (*str))
     2600      str++;
     2601    if (*str)
     2602      {
     2603        error (NILF, _("bad number: '%s'\n"), start);
     2604        return 0;
     2605      }
     2606
     2607    return negative ? -num : num;
     2608}
     2609
     2610/* outputs the number (as a string) into the variable buffer. */
     2611static char *
     2612math_int_to_variable_buffer (char *o, math_int num)
     2613{
     2614    static const char xdigits[17] = "0123456789abcdef";
     2615    int negative;
     2616    char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20 */
     2617    char *str = &strbuf[sizeof (strbuf) - 1];
     2618
     2619    negative = num < 0;
     2620    if (negative)
     2621      num = -num;
     2622
     2623    *str-- = '\0';
     2624
     2625    do
     2626      {
     2627        *str-- = xdigits[num & 0xf];
     2628        num >>= 4;
     2629      }
     2630    while (num);
     2631
     2632    *str-- = 'x';
     2633    *str = '0';
     2634
     2635    if (negative)
     2636        *--str = '-';
     2637
     2638    return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str);
     2639}
     2640
     2641/* Add two or more integer numbers. */
     2642static char *
     2643func_int_add (char *o, char **argv, const char *funcname)
     2644{
     2645    math_int num;
     2646    int i;
     2647
     2648    num = math_int_from_string (argv[0]);
     2649    for (i = 1; argv[i]; i++)
     2650      num += math_int_from_string (argv[i]);
     2651
     2652    return math_int_to_variable_buffer (o, num);
     2653}
     2654
     2655/* Subtract two or more integer numbers. */
     2656static char *
     2657func_int_sub (char *o, char **argv, const char *funcname)
     2658{
     2659    math_int num;
     2660    int i;
     2661
     2662    num = math_int_from_string (argv[0]);
     2663    for (i = 1; argv[i]; i++)
     2664      num -= math_int_from_string (argv[i]);
     2665
     2666    return math_int_to_variable_buffer (o, num);
     2667}
     2668
     2669/* Multiply two or more integer numbers. */
     2670static char *
     2671func_int_mul (char *o, char **argv, const char *funcname)
     2672{
     2673    math_int num;
     2674    int i;
     2675
     2676    num = math_int_from_string (argv[0]);
     2677    for (i = 1; argv[i]; i++)
     2678      num *= math_int_from_string (argv[i]);
     2679
     2680    return math_int_to_variable_buffer (o, num);
     2681}
     2682
     2683/* Divide an integer number by one or more divisors. */
     2684static char *
     2685func_int_div (char *o, char **argv, const char *funcname)
     2686{
     2687    math_int num;
     2688    math_int divisor;
     2689    int i;
     2690
     2691    num = math_int_from_string (argv[0]);
     2692    for (i = 1; argv[i]; i++)
     2693      {
     2694        divisor = math_int_from_string (argv[i]);
     2695        if (!divisor)
     2696          {
     2697            error (NILF, _("divide by zero ('%s')\n"), argv[i]);
     2698            return math_int_to_variable_buffer (o, 0);
     2699          }
     2700        num /= divisor;
     2701      }
     2702
     2703    return math_int_to_variable_buffer (o, num);
     2704}
     2705
     2706
     2707/* Divide and return the remainder. */
     2708static char *
     2709func_int_mod (char *o, char **argv, const char *funcname)
     2710{
     2711    math_int num;
     2712    math_int divisor;
     2713
     2714    num = math_int_from_string (argv[0]);
     2715    divisor = math_int_from_string (argv[1]);
     2716    if (!divisor)
     2717      {
     2718        error (NILF, _("divide by zero ('%s')\n"), argv[1]);
     2719        return math_int_to_variable_buffer (o, 0);
     2720      }
     2721    num %= divisor;
     2722
     2723    return math_int_to_variable_buffer (o, num);
     2724}
     2725
     2726/* 2-complement. */
     2727static char *
     2728func_int_not (char *o, char **argv, const char *funcname)
     2729{
     2730    math_int num;
     2731
     2732    num = math_int_from_string (argv[0]);
     2733    num = ~num;
     2734
     2735    return math_int_to_variable_buffer (o, num);
     2736}
     2737
     2738/* Bitwise AND (two or more numbers). */
     2739static char *
     2740func_int_and (char *o, char **argv, const char *funcname)
     2741{
     2742    math_int num;
     2743    int i;
     2744
     2745    num = math_int_from_string (argv[0]);
     2746    for (i = 1; argv[i]; i++)
     2747      num &= math_int_from_string (argv[i]);
     2748
     2749    return math_int_to_variable_buffer (o, num);
     2750}
     2751
     2752/* Bitwise OR (two or more numbers). */
     2753static char *
     2754func_int_or (char *o, char **argv, const char *funcname)
     2755{
     2756    math_int num;
     2757    int i;
     2758
     2759    num = math_int_from_string (argv[0]);
     2760    for (i = 1; argv[i]; i++)
     2761      num |= math_int_from_string (argv[i]);
     2762
     2763    return math_int_to_variable_buffer (o, num);
     2764}
     2765
     2766/* Bitwise XOR (two or more numbers). */
     2767static char *
     2768func_int_xor (char *o, char **argv, const char *funcname)
     2769{
     2770    math_int num;
     2771    int i;
     2772
     2773    num = math_int_from_string (argv[0]);
     2774    for (i = 1; argv[i]; i++)
     2775      num ^= math_int_from_string (argv[i]);
     2776
     2777    return math_int_to_variable_buffer (o, num);
     2778}
     2779
     2780/* Compare two integer numbers. Returns make boolean (true="1"; false=""). */
     2781static char *
     2782func_int_cmp (char *o, char **argv, const char *funcname)
     2783{
     2784    math_int num1;
     2785    math_int num2;
     2786    int rc;
     2787
     2788    num1 = math_int_from_string (argv[0]);
     2789    num2 = math_int_from_string (argv[1]);
     2790
     2791    funcname += sizeof ("int-") - 1;
     2792    if (!strcmp (funcname, "eq"))
     2793      rc = num1 == num2;
     2794    else if (!strcmp (funcname, "ne"))
     2795      rc = num1 != num2;
     2796    else if (!strcmp (funcname, "gt"))
     2797      rc = num1 > num2;
     2798    else if (!strcmp (funcname, "ge"))
     2799      rc = num1 >= num2;
     2800    else if (!strcmp (funcname, "lt"))
     2801      rc = num1 < num2;
     2802    else /*if (!strcmp (funcname, "le"))*/
     2803      rc = num1 <= num2;
     2804
     2805    return variable_buffer_output (o, rc ? "1" : "", rc);
     2806}
     2807
     2808
     2809#endif /* CONFIG_WITH_MATH */
    25162810
    25172811/* Lookup table for builtin functions.
     
    25782872#ifdef CONFIG_WITH_ABSPATHEX
    25792873  { STRING_SIZE_TUPLE("abspathex"),     0,  2,  1,  func_abspathex},
    2580 #endif 
     2874#endif
    25812875#if defined(CONFIG_WITH_VALUE_LENGTH) && defined(CONFIG_WITH_COMPARE)
    25822876  { STRING_SIZE_TUPLE("comp-vars"),     3,  3,  1,  func_comp_vars},
     
    25882882  { STRING_SIZE_TUPLE("stack-popv"),    1,  1,  1,  func_stack_pop_top},
    25892883  { STRING_SIZE_TUPLE("stack-top"),     1,  1,  1,  func_stack_pop_top},
     2884#endif
     2885#ifdef CONFIG_WITH_MATH
     2886  { STRING_SIZE_TUPLE("int-add"),       2,  0,  1,  func_int_add},
     2887  { STRING_SIZE_TUPLE("int-sub"),       2,  0,  1,  func_int_sub},
     2888  { STRING_SIZE_TUPLE("int-mul"),       2,  0,  1,  func_int_mul},
     2889  { STRING_SIZE_TUPLE("int-div"),       2,  0,  1,  func_int_div},
     2890  { STRING_SIZE_TUPLE("int-mod"),       2,  2,  1,  func_int_mod},
     2891  { STRING_SIZE_TUPLE("int-not"),       1,  1,  1,  func_int_not},
     2892  { STRING_SIZE_TUPLE("int-and"),       2,  0,  1,  func_int_and},
     2893  { STRING_SIZE_TUPLE("int-or"),        2,  0,  1,  func_int_or},
     2894  { STRING_SIZE_TUPLE("int-xor"),       2,  0,  1,  func_int_xor},
     2895  { STRING_SIZE_TUPLE("int-eq"),        2,  2,  1,  func_int_cmp},
     2896  { STRING_SIZE_TUPLE("int-ne"),        2,  2,  1,  func_int_cmp},
     2897  { STRING_SIZE_TUPLE("int-gt"),        2,  2,  1,  func_int_cmp},
     2898  { STRING_SIZE_TUPLE("int-ge"),        2,  2,  1,  func_int_cmp},
     2899  { STRING_SIZE_TUPLE("int-lt"),        2,  2,  1,  func_int_cmp},
     2900  { STRING_SIZE_TUPLE("int-le"),        2,  2,  1,  func_int_cmp},
    25902901#endif
    25912902#ifdef KMK_HELPERS
     
    25952906  { STRING_SIZE_TUPLE("kb-src-prop"),   4,  4,  0,  func_kbuild_source_prop},
    25962907  { STRING_SIZE_TUPLE("kb-src-one"),    0,  1,  0,  func_kbuild_source_one},
    2597 #endif 
     2908#endif
    25982909};
    25992910
     
    28593170        assert(function_table_init[i].len <= MAX_FUNCTION_LENGTH);
    28603171  }
    2861 #endif 
    2862 }
     3172#endif
     3173}
Note: See TracChangeset for help on using the changeset viewer.