~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to builtin.c

  • Committer: Juergen Kahrs
  • Date: 2013-12-23 17:26:45 UTC
  • mfrom: (408.2.218)
  • Revision ID: git-v1:ee9707cc44eea3ca64cb71666ac3e8ed26a3bb7f
Merge remote-tracking branch 'origin/master' into cmake

Show diffs side-by-side

added added

removed removed

Lines of Context:
125
125
        return;
126
126
 
127
127
wrerror:
 
128
        /* die silently on EPIPE to stdout */
 
129
        if (fp == stdout && errno == EPIPE)
 
130
                gawk_exit(EXIT_FATAL);
 
131
 
 
132
        /* otherwise die verbosely */
128
133
        fatal(_("%s to \"%s\" failed (%s)"), from,
129
134
                rp ? rp->value : _("standard output"),
130
135
                errno ? strerror(errno) : _("reason unknown"));
464
469
double_to_int(double d)
465
470
{
466
471
        if (d >= 0)
467
 
                d = Floor(d);
 
472
                d = floor(d);
468
473
        else
469
 
                d = Ceil(d);
 
474
                d = ceil(d);
470
475
        return d;
471
476
}
472
477
 
1097
1102
                         * used to work? 6/2003.)
1098
1103
                         */
1099
1104
                        cp = arg->stptr;
 
1105
                        prec = 1;
1100
1106
#if MBS_SUPPORT
1101
1107
                        /*
1102
1108
                         * First character can be multiple bytes if
1108
1114
 
1109
1115
                                memset(& state, 0, sizeof(state));
1110
1116
                                count = mbrlen(cp, arg->stlen, & state);
1111
 
                                if (count == 0
1112
 
                                    || count == (size_t)-1
1113
 
                                    || count == (size_t)-2)
1114
 
                                        goto out2;
1115
 
                                prec = count;
1116
 
                                goto pr_tail;
 
1117
                                if (count > 0) {
 
1118
                                        prec = count;
 
1119
                                        /* may need to increase fw so that padding happens, see pr_tail code */
 
1120
                                        if (fw > 0)
 
1121
                                                fw += count - 1;
 
1122
                                }
1117
1123
                        }
1118
 
out2:
1119
 
                        ;
1120
1124
#endif
1121
 
                        prec = 1;
1122
1125
                        goto pr_tail;
1123
1126
                case 's':
1124
1127
                        need_format = false;
1421
1424
                        copy_count = prec;
1422
1425
                        if (fw == 0 && ! have_prec)
1423
1426
                                ;
1424
 
                        else if (gawk_mb_cur_max > 1 && (cs1 == 's' || cs1 == 'c')) {
1425
 
                                assert(cp == arg->stptr || cp == cpbuf);
1426
 
                                copy_count = mbc_byte_count(arg->stptr, prec);
 
1427
                        else if (gawk_mb_cur_max > 1) {
 
1428
                                if (cs1 == 's') {
 
1429
                                        assert(cp == arg->stptr || cp == cpbuf);
 
1430
                                        copy_count = mbc_byte_count(arg->stptr, prec);
 
1431
                                }
 
1432
                                /* prec was set by code for %c */
 
1433
                                /* else
 
1434
                                        copy_count = prec; */
1427
1435
                        }
1428
1436
                        bchunk(cp, copy_count);
1429
1437
                        while (fw > prec) {
2156
2164
 
2157
2165
        f0 = fields_arr[0];
2158
2166
 
2159
 
        if (do_lint && f0 == Nnull_string)
 
2167
        if (do_lint && (f0->flags & NULL_FIELD) != 0)
2160
2168
                lintwarn(_("reference to uninitialized field `$%d'"), 0);
2161
2169
 
2162
2170
        efwrite(f0->stptr, sizeof(char), f0->stlen, fp, "print", rp, false);
2369
2377
NODE *
2370
2378
do_rand(int nargs ATTRIBUTE_UNUSED)
2371
2379
{
 
2380
        double tmprand;
 
2381
#define RAND_DIVISOR ((double)GAWK_RANDOM_MAX+1.0)
2372
2382
        if (firstrand) {
2373
2383
                (void) initstate((unsigned) 1, state, SIZEOF_STATE);
2374
2384
                /* don't need to srandom(1), initstate() does it for us. */
2380
2390
         *
2381
2391
         *      0 <= n < 1
2382
2392
         */
2383
 
        return make_number((AWKNUM) (random() % GAWK_RANDOM_MAX) / GAWK_RANDOM_MAX);
 
2393
        /*
 
2394
         * Date: Wed, 28 Aug 2013 17:52:46 -0700
 
2395
         * From: Bob Jewett <jewett@bill.scs.agilent.com>
 
2396
         *
 
2397
         * Call random() twice to fill in more bits in the value
 
2398
         * of the double.  Also, there is a bug in random() such
 
2399
         * that when the values of successive values are combined
 
2400
         * like (rand1*rand2)^2, (rand3*rand4)^2,  ...  the
 
2401
         * resulting time series is not white noise.  The
 
2402
         * following also seems to fix that bug. 
 
2403
         *
 
2404
         * The add/subtract 0.5 keeps small bits from filling
 
2405
         * below 2^-53 in the double, not that anyone should be
 
2406
         * looking down there. 
 
2407
         *
 
2408
         * Date: Wed, 25 Sep 2013 10:45:38 -0600 (MDT)
 
2409
         * From: "Nelson H. F. Beebe" <beebe@math.utah.edu>
 
2410
         * (4) The code is typical of many published fragments for converting
 
2411
         *     from integer to floating-point, and I discuss the serious pitfalls
 
2412
         *     in my book, because it leads to platform-dependent behavior at the
 
2413
         *     end points of the interval [0,1]
 
2414
         * 
 
2415
         * (5) the documentation in the gawk info node says
 
2416
         * 
 
2417
         *     `rand()'
 
2418
         *       Return a random number.  The values of `rand()' are uniformly
 
2419
         *       distributed between zero and one.  The value could be zero but is
 
2420
         *       never one.(1)
 
2421
         * 
 
2422
         *     The division by RAND_DIVISOR may not guarantee that 1.0 is never
 
2423
         *     returned: the programmer forgot the platform-dependent issue of
 
2424
         *     rounding.
 
2425
         * 
 
2426
         * For points 4 and 5, the safe way is a loop:
 
2427
         * 
 
2428
         *         double 
 
2429
         *         rand(void)           // return value in [0.0, 1.0)
 
2430
         *         {
 
2431
         *          value = internal_rand();
 
2432
         *
 
2433
         *          while (value == 1.0) 
 
2434
         *                 value = internal_rand();
 
2435
         * 
 
2436
         *          return (value);
 
2437
         *         }
 
2438
         */
 
2439
 
 
2440
        do {
 
2441
                tmprand = 0.5 + ( (random()/RAND_DIVISOR + random())
 
2442
                                        / RAND_DIVISOR);
 
2443
                tmprand -= 0.5;
 
2444
        } while (tmprand == 1.0);
 
2445
 
 
2446
        return make_number((AWKNUM) tmprand);
2384
2447
}
2385
2448
 
2386
2449
/* do_srand --- seed the random number generator */
2952
3015
done:
2953
3016
        DEREF(s);
2954
3017
 
2955
 
        if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL)
 
3018
        if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL) {
2956
3019
                efree(buf); 
 
3020
                buf = NULL;
 
3021
        }
2957
3022
 
2958
3023
        if (flags & GENSUB) {
2959
3024
                if (matches > 0) {
2960
3025
                        /* return the result string */
2961
3026
                        DEREF(t);
 
3027
                        assert(buf != NULL);
2962
3028
                        return make_str_node(buf, textlen, ALREADY_MALLOCED);   
2963
3029
                }
2964
3030