Exemplo n.º 1
0
int main(int parameter_count, String * parameter_values){
	
	set_numeric_locale(BRAZILIAN_LOCALE);
	
	if(are_valid_parameters(parameter_count, parameter_values)){
		set_environment_configuration_from_parameters(parameter_count, parameter_values);
		execute_stress_test();
	} else {
		printf("ERROR : INVALID PARAMETERS\n\n");
		return ERROR;
	}
	
	return SUCCESS_END_OF_PROGRAM;
}
Exemplo n.º 2
0
/* EAM July 2004  (revised to dynamic buffer July 2005)
 * There are probably an infinite number of things that can
 * go wrong if the user mis-matches arguments and format strings
 * in the call to sprintf, but I hope none will do worse than
 * result in a garbage output string.
 */
void
f_sprintf(union argument *arg)
{
    struct value a[10], *args;
    struct value num_params;
    struct value result;
    char *buffer;
    int bufsize;
    char *next_start, *outpos, tempchar;
    int next_length;
    char *prev_start;
    int prev_pos;
    int i, remaining;
    int nargs = 0;
    enum DATA_TYPES spec_type;

    /* Retrieve number of parameters from top of stack */
    pop(&num_params);
    nargs = num_params.v.int_val;
    if (nargs > 10) {	/* Fall back to slow but sure allocation */
	args = gp_alloc(sizeof(struct value)*nargs, "sprintf args");
    } else
	args = a;

    for (i=0; i<nargs; i++)
	pop(&args[i]);  /* pop next argument */

    /* Make sure we got a format string of some sort */
    if (args[nargs-1].type != STRING)
	int_error(NO_CARET,"First parameter to sprintf must be a format string");

    /* Allocate space for the output string. If this isn't */
    /* long enough we can reallocate a larger space later. */
    bufsize = 80 + strlen(args[nargs-1].v.string_val);
    buffer = gp_alloc(bufsize, "f_sprintf");

    /* Copy leading fragment of format into output buffer */
    outpos = buffer;
    next_start  = args[nargs-1].v.string_val;
    next_length = strcspn(next_start,"%");
    strncpy(outpos, next_start, next_length);

    next_start += next_length;
    outpos += next_length;

    /* Format the remaining sprintf() parameters one by one */
    prev_start = next_start;
    prev_pos = next_length;
    remaining = nargs - 1;

    /* If the user has set an explicit LC_NUMERIC locale, apply it */
    /* to sprintf calls during expression evaluation.              */
    set_numeric_locale();

    /* Each time we start this loop we are pointing to a % character */
    while (remaining-->0 && next_start[0] && next_start[1]) {
	struct value *next_param = &args[remaining];

	/* Check for %%; print as literal and don't consume a parameter */
	if (!strncmp(next_start,"%%",2)) {
	    next_start++;
	    do {
		*outpos++ = *next_start++;
	    } while(*next_start && *next_start != '%');
	    remaining++;
	    continue;
	}

	next_length = strcspn(next_start+1,"%") + 1;
	tempchar = next_start[next_length];
	next_start[next_length] = '\0';

	spec_type = sprintf_specifier(next_start);

	/* string value <-> numerical value check */
	if ( spec_type == STRING && next_param->type != STRING )
	    int_error(NO_CARET,"f_sprintf: attempt to print numeric value with string format");
	if ( spec_type != STRING && next_param->type == STRING )
	    int_error(NO_CARET,"f_sprintf: attempt to print string value with numeric format");

#ifdef HAVE_SNPRINTF
	/* Use the format to print next arg */
	switch(spec_type) {
	case INTGR:
	    snprintf(outpos,bufsize-(outpos-buffer),
		     next_start, (int)real(next_param));
	    break;
	case CMPLX:
	    snprintf(outpos,bufsize-(outpos-buffer),
		     next_start, real(next_param));
	    break;
	case STRING:
	    snprintf(outpos,bufsize-(outpos-buffer),
		next_start, next_param->v.string_val);
	    break;
	default:
	    int_error(NO_CARET,"internal error: invalid spec_type");
	}
#else
	/* FIXME - this is bad; we should dummy up an snprintf equivalent */
	switch(spec_type) {
	case INTGR:
	    sprintf(outpos, next_start, (int)real(next_param));
	    break;
	case CMPLX:
	    sprintf(outpos, next_start, real(next_param));
	    break;
	case STRING:
	    sprintf(outpos, next_start, next_param->v.string_val);
	    break;
	default:
	    int_error(NO_CARET,"internal error: invalid spec_type");
	}
#endif

	next_start[next_length] = tempchar;
	next_start += next_length;
	outpos = &buffer[strlen(buffer)];

	/* Check whether previous parameter output hit the end of the buffer */
	/* If so, reallocate a larger buffer, go back and try it again.      */
	if (strlen(buffer) >= bufsize-2) {
	    bufsize *= 2;
	    buffer = gp_realloc(buffer, bufsize, "f_sprintf");
	    next_start = prev_start;
	    outpos = buffer + prev_pos;
	    remaining++;
	    continue;
	} else {
	    prev_start = next_start;
	    prev_pos = outpos - buffer;
	}

    }

    /* Copy the trailing portion of the format, if any */
    /* We could just call snprintf(), but it doesn't check for */
    /* whether there really are more variables to handle.      */
    i = bufsize - (outpos-buffer);
    while (*next_start && --i > 0) {
	if (*next_start == '%' && *(next_start+1) == '%')
	    next_start++;
	*outpos++ = *next_start++;
    }
    *outpos = '\0';

    FPRINTF((stderr," snprintf result = \"%s\"\n",buffer));
    push(Gstring(&result, buffer));
    free(buffer);

    /* Free any strings from parameters we have now used */
    for (i=0; i<nargs; i++)
	gpfree_string(&args[i]);

    if (args != a)
	free(args);

    /* Return to C locale for internal use */
    reset_numeric_locale();

}
Exemplo n.º 3
0
/* HBB 20010121: added code to maintain consistency between mantissa
 * and exponent across sprintf() calls.  The problem: format string
 * '%t*10^%T' will display 9.99 as '10.0*10^0', but 10.01 as
 * '1.0*10^1'.  This causes problems for people using the %T part,
 * only, with logscaled axes, in combination with the occasional
 * round-off error. */
void
gprintf(
    char *dest,
    size_t count,
    char *format,
    double log10_base,
    double x)
{
    char temp[MAX_LINE_LEN + 1];
    char *t;
    TBOOLEAN seen_mantissa = FALSE; /* memorize if mantissa has been
                                       output, already */
    int stored_power = 0;	/* power that matches the mantissa
                                   output earlier */

    set_numeric_locale();

    for (;;) {
	/*{{{  copy to dest until % */
	while (*format != '%')
	    if (!(*dest++ = *format++)) {
		reset_numeric_locale();
		return;		/* end of format */
	    }
	/*}}} */

	/*{{{  check for %% */
	if (format[1] == '%') {
	    *dest++ = '%';
	    format += 2;
	    continue;
	}
	/*}}} */

	/*{{{  copy format part to temp, excluding conversion character */
	t = temp;
	*t++ = '%';
	/* dont put isdigit first since sideeffect in macro is bad */
	while (*++format == '.' || isdigit((unsigned char) *format)
	       || *format == '-' || *format == '+' || *format == ' '
	       || *format == '\'')
	    *t++ = *format;
	/*}}} */

	/*{{{  convert conversion character */
	switch (*format) {
	    /*{{{  x and o */
	case 'x':
	case 'X':
	case 'o':
	case 'O':
	    t[0] = *format;
	    t[1] = 0;
	    sprintf(dest, temp, (int) x);
	    break;
	    /*}}} */
	    /*{{{  e, f and g */
	case 'e':
	case 'E':
	case 'f':
	case 'F':
	case 'g':
	case 'G':
	    t[0] = *format;
	    t[1] = 0;
	    sprintf(dest, temp, x);
	    break;
	    /*}}} */
	    /*{{{  l --- mantissa to current log base */
	case 'l':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		mant_exp(log10_base, x, FALSE, &mantissa, &stored_power, temp);
		seen_mantissa = TRUE;
		sprintf(dest, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  t --- base-10 mantissa */
	case 't':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		mant_exp(1.0, x, FALSE, &mantissa, &stored_power, temp);
		seen_mantissa = TRUE;
		sprintf(dest, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  s --- base-1000 / 'scientific' mantissa */
	case 's':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		mant_exp(1.0, x, TRUE, &mantissa, &stored_power, temp);
		seen_mantissa = TRUE;
		sprintf(dest, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  L --- power to current log base */
	case 'L':
	    {
		int power;

		t[0] = 'd';
		t[1] = 0;
		if (seen_mantissa)
		    power = stored_power;
		else
		    mant_exp(log10_base, x, FALSE, NULL, &power, "%.0f");
		sprintf(dest, temp, power);
		break;
	    }
	    /*}}} */
	    /*{{{  T --- power of ten */
	case 'T':
	    {
		int power;

		t[0] = 'd';
		t[1] = 0;
		if (seen_mantissa)
		    power = stored_power;
		else
		    mant_exp(1.0, x, FALSE, NULL, &power, "%.0f");
		sprintf(dest, temp, power);
		break;
	    }
	    /*}}} */
	    /*{{{  S --- power of 1000 / 'scientific' */
	case 'S':
	    {
		int power;

		t[0] = 'd';
		t[1] = 0;
		if (seen_mantissa)
		    power = stored_power;
		else
		    mant_exp(1.0, x, TRUE, NULL, &power, "%.0f");
		sprintf(dest, temp, power);
		break;
	    }
	    /*}}} */
	    /*{{{  c --- ISO decimal unit prefix letters */
	case 'c':
	    {
		int power;

		t[0] = 'c';
		t[1] = 0;
		if (seen_mantissa)
		    power = stored_power;
		else
		    mant_exp(1.0, x, TRUE, NULL, &power, "%.0f");

		if (power >= -18 && power <= 18) {
		    /* -18 -> 0, 0 -> 6, +18 -> 12, ... */
		    /* HBB 20010121: avoid division of -ve ints! */
		    power = (power + 18) / 3;
		    sprintf(dest, temp, "afpnum kMGTPE"[power]);
		} else {
		    /* please extend the range ! */
		    /* name  power   name  power
		       -------------------------
		       atto   -18    Exa    18
		       femto  -15    Peta   15
		       pico   -12    Tera   12
		       nano    -9    Giga    9
		       micro   -6    Mega    6
		       milli   -3    kilo    3   */

		    /* for the moment, print e+21 for example */
		    sprintf(dest, "e%+02d", (power - 6) * 3);
		}

		break;
	    }
	    /*}}} */
	    /*{{{  P --- multiple of pi */
	case 'P':
	    {
		t[0] = 'f';
		t[1] = 0;
		sprintf(dest, temp, x / M_PI);
		break;
	    }
	    /*}}} */
	default:
	   reset_numeric_locale();
	   int_error(NO_CARET, "Bad format character");
	} /* switch */
	/*}}} */

    /* change decimal `.' to the actual entry in decimalsign */
	if (decimalsign != NULL) {
	    char *dotpos1 = dest, *dotpos2;
	    size_t newlength = strlen(decimalsign);
	    int dot;

	    /* dot is the default decimalsign we will be replacing */
	    dot = *get_decimal_locale();

	    /* replace every dot by the contents of decimalsign */
	    while ((dotpos2 = strchr(dotpos1,dot)) != NULL) {
		size_t taillength = strlen(dotpos2);

		dotpos1 = dotpos2 + newlength;
		/* test if the new value for dest would be too long */
		if (dotpos1 - dest + taillength > count)
		    int_error(NO_CARET,
			      "format too long due to long decimalsign string");
		/* move tail end of string out of the way */
		memmove(dotpos1, dotpos2 + 1, taillength);
		/* insert decimalsign */
		memcpy(dotpos2, decimalsign, newlength);
	    }
	    /* clear temporary variables for safety */
	    dotpos1=NULL;
	    dotpos2=NULL;
	}

	/* this was at the end of every single case, before: */
	dest += strlen(dest);
	++format;
    } /* for ever */

    reset_numeric_locale();
}
Exemplo n.º 4
0
/* EAM Nov 2012:
 * Unbelievably, the count parameter has been silently ignored or
 * improperly applied ever since this routine was introduced back
 * in version 3.7.  Now fixed to prevent buffer overflow.
 */
void
gprintf(
    char *outstring,
    size_t count,
    char *format,
    double log10_base,
    double x)
{
    char tempdest[MAX_LINE_LEN + 1];
    char temp[MAX_LINE_LEN + 1];
    char *t;
    TBOOLEAN seen_mantissa = FALSE; /* remember if mantissa was already output */
    double stored_power_base = 0;   /* base for the last mantissa output*/
    int stored_power = 0;	/* power matching the mantissa output earlier */
    TBOOLEAN got_hash = FALSE;

    char *dest  = &tempdest[0];
    char *limit = &tempdest[MAX_LINE_LEN];
    static double log10_of_1024; /* to avoid excess precision comparison in check of connection %b -- %B */

    log10_of_1024 = log10(1024);

#define remaining_space (size_t)(limit-dest)

    *dest = '\0';

    set_numeric_locale();

    /* Oct 2013 - default format is now expected to be "%h" */
    if (((term->flags & TERM_IS_LATEX)) && !strcmp(format, DEF_FORMAT))
        format = DEF_FORMAT_LATEX;

    for (;;) {
        /*{{{  copy to dest until % */
        while (*format != '%')
            if (!(*dest++ = *format++) || (remaining_space == 0)) {
                goto done;
            }
        /*}}} */

        /*{{{  check for %% */
        if (format[1] == '%') {
            *dest++ = '%';
            format += 2;
            continue;
        }
        /*}}} */

        /*{{{  copy format part to temp, excluding conversion character */
        t = temp;
        *t++ = '%';
        if (format[1] == '#') {
            *t++ = '#';
            format++;
            got_hash = TRUE;
        }
        /* dont put isdigit first since side effect in macro is bad */
        while (*++format == '.' || isdigit((unsigned char) *format)
                || *format == '-' || *format == '+' || *format == ' '
                || *format == '\'')
            *t++ = *format;
        /*}}} */

        /*{{{  convert conversion character */
        switch (*format) {
        /*{{{  x and o */
        case 'x':
        case 'X':
        case 'o':
        case 'O':
            if (fabs(x) >= (double)INT_MAX) {
                t[0] = 'l';
                t[1] = 'l';
                t[2] = *format;
                t[3] = '\0';
                snprintf(dest, remaining_space, temp, (long long) x);
            } else {
                t[0] = *format;
                t[1] = '\0';
                snprintf(dest, remaining_space, temp, (int) x);
            }
            break;
        /*}}} */
        /*{{{  e, f and g */
        case 'e':
        case 'E':
        case 'f':
        case 'F':
        case 'g':
        case 'G':
            t[0] = *format;
            t[1] = 0;
            snprintf(dest, remaining_space, temp, x);
            break;
        case 'h':
        case 'H':
            /* g/G with enhanced formating (if applicable) */
            t[0] = (*format == 'h') ? 'g' : 'G';
            t[1] = 0;

            if ((term->flags & (TERM_ENHANCED_TEXT | TERM_IS_LATEX)) == 0) {
                /* Not enhanced, not latex, just print it */
                snprintf(dest, remaining_space, temp, x);

            } else if (table_mode) {
                /* Tabular output should contain no markup */
                snprintf(dest, remaining_space, temp, x);

            } else {
                /* in enhanced mode -- convert E/e to x10^{foo} or *10^{foo} */
#define LOCAL_BUFFER_SIZE 256
                char tmp[LOCAL_BUFFER_SIZE];
                char tmp2[LOCAL_BUFFER_SIZE];
                int i,j;
                TBOOLEAN bracket_flag = FALSE;
                snprintf(tmp, 240, temp, x); /* magic number alert: why 240? */
                for (i=j=0; tmp[i] && (i < LOCAL_BUFFER_SIZE); i++) {
                    if (tmp[i]=='E' || tmp[i]=='e') {
                        if ((term-> flags & TERM_IS_LATEX)) {
                            if (*format == 'h') {
                                strcpy(&tmp2[j], "\\times");
                                j+= 6;
                            } else {
                                strcpy(&tmp2[j], "\\cdot");
                                j+= 5;
                            }
                        } else switch (encoding) {
                            case S_ENC_UTF8:
                                strcpy(&tmp2[j], "\xc3\x97"); /* UTF character '×' */
                                j+= 2;
                                break;
                            case S_ENC_CP1252:
                                tmp2[j++] = (*format=='h') ? 0xd7 : 0xb7;
                                break;
                            case S_ENC_ISO8859_1:
                            case S_ENC_ISO8859_2:
                            case S_ENC_ISO8859_9:
                            case S_ENC_ISO8859_15:
                                tmp2[j++] = (*format=='h') ? 0xd7 : '*';
                                break;
                            default:
                                tmp2[j++] = (*format=='h') ? 'x' : '*';
                                break;
                            }

                        strcpy(&tmp2[j], "10^{");
                        j += 4;
                        bracket_flag = TRUE;

                        /* Skip + and leading 0 in exponent */
                        i++; /* skip E */
                        if (tmp[i] == '+')
                            i++;
                        else if (tmp[i] == '-') /* copy sign */
                            tmp2[j++] = tmp[i++];
                        while (tmp[i] == '0')
                            i++;
                        i--; /* undo following loop increment */
                    } else {
                        tmp2[j++] = tmp[i];
                    }
                }
                if (bracket_flag)
                    tmp2[j++] = '}';
                tmp2[j] = '\0';
                strncpy(dest, tmp2, remaining_space);
#undef LOCAL_BUFFER_SIZE
            }

            break;

        /*}}} */
        /*{{{  l --- mantissa to current log base */
        case 'l':
        {
            double mantissa;

            t[0] = 'f';
            t[1] = 0;
            stored_power_base = log10_base;
            mant_exp(stored_power_base, x, FALSE, &mantissa,
                     &stored_power, temp);
            seen_mantissa = TRUE;
            snprintf(dest, remaining_space, temp, mantissa);
            break;
        }
        /*}}} */
        /*{{{  t --- base-10 mantissa */
        case 't':
        {
            double mantissa;

            t[0] = 'f';
            t[1] = 0;
            stored_power_base = 1.0;
            mant_exp(stored_power_base, x, FALSE, &mantissa,
                     &stored_power, temp);
            seen_mantissa = TRUE;
            snprintf(dest, remaining_space, temp, mantissa);
            break;
        }
        /*}}} */
        /*{{{  s --- base-1000 / 'scientific' mantissa */
        case 's':
        {
            double mantissa;

            t[0] = 'f';
            t[1] = 0;
            stored_power_base = 1.0;
            mant_exp(stored_power_base, x, TRUE, &mantissa,
                     &stored_power, temp);
            seen_mantissa = TRUE;
            snprintf(dest, remaining_space, temp, mantissa);
            break;
        }
        /*}}} */
        /*{{{  b --- base-1024 mantissa */
        case 'b':
        {
            double mantissa;

            t[0] = 'f';
            t[1] = 0;
            stored_power_base = log10_of_1024;
            mant_exp(stored_power_base, x, FALSE, &mantissa,
                     &stored_power, temp);
            seen_mantissa = TRUE;
            snprintf(dest, remaining_space, temp, mantissa);
            break;
        }
        /*}}} */
        /*{{{  L --- power to current log base */
        case 'L':
        {
            int power;

            t[0] = 'd';
            t[1] = 0;
            if (seen_mantissa) {
                if (stored_power_base == log10_base) {
                    power = stored_power;
                } else {
                    int_error(NO_CARET, "Format character mismatch: %%L is only valid with %%l");
                }
            } else {
                stored_power_base = log10_base;
                mant_exp(log10_base, x, FALSE, NULL, &power, "%.0f");
            }
            snprintf(dest, remaining_space, temp, power);
            break;
        }
        /*}}} */
        /*{{{  T --- power of ten */
        case 'T':
        {
            int power;

            t[0] = 'd';
            t[1] = 0;
            if (seen_mantissa) {
                if (stored_power_base == 1.0) {
                    power = stored_power;
                } else {
                    int_error(NO_CARET, "Format character mismatch: %%T is only valid with %%t");
                }
            } else {
                mant_exp(1.0, x, FALSE, NULL, &power, "%.0f");
            }
            snprintf(dest, remaining_space, temp, power);
            break;
        }
        /*}}} */
        /*{{{  S --- power of 1000 / 'scientific' */
        case 'S':
        {
            int power;

            t[0] = 'd';
            t[1] = 0;
            if (seen_mantissa) {
                if (stored_power_base == 1.0) {
                    power = stored_power;
                } else {
                    int_error(NO_CARET, "Format character mismatch: %%S is only valid with %%s");
                }
            } else {
                mant_exp(1.0, x, TRUE, NULL, &power, "%.0f");
            }
            snprintf(dest, remaining_space, temp, power);
            break;
        }
        /*}}} */
        /*{{{  c --- ISO decimal unit prefix letters */
        case 'c':
        {
            int power;

            t[0] = 'c';
            t[1] = 0;
            if (seen_mantissa) {
                if (stored_power_base == 1.0) {
                    power = stored_power;
                } else {
                    int_error(NO_CARET, "Format character mismatch: %%c is only valid with %%s");
                }
            } else {
                mant_exp(1.0, x, TRUE, NULL, &power, "%.0f");
            }

            if (power >= -24 && power <= 24) {
                /* name  power   name  power
                   -------------------------
                   yocto  -24    yotta  24
                   zepto  -21    zetta  21
                   atto   -18    Exa    18
                   femto  -15    Peta   15
                   pico   -12    Tera   12
                   nano    -9    Giga    9
                   micro   -6    Mega    6
                   milli   -3    kilo    3   */
                /* -18 -> 0, 0 -> 6, +18 -> 12, ... */
                /* HBB 20010121: avoid division of -ve ints! */
                power = (power + 24) / 3;
                snprintf(dest, remaining_space, temp, "yzafpnum kMGTPEZY"[power]);
            } else {
                /* please extend the range ! */
                /* fall back to simple exponential */
                snprintf(dest, remaining_space, "e%+02d", power);
            }
            break;
        }
        /*}}} */
        /*{{{  B --- IEC 60027-2 A.2 / ISO/IEC 80000 binary unit prefix letters */
        case 'B':
        {
            int power;

            t[0] = 'c';
            t[1] = 'i';
            t[2] = '\0';
            if (seen_mantissa) {
                if (stored_power_base == log10_of_1024) {
                    power = stored_power;
                } else {
                    int_error(NO_CARET, "Format character mismatch: %%B is only valid with %%b");
                }
            } else {
                mant_exp(log10_of_1024, x, FALSE, NULL, &power, "%.0f");
            }

            if (power > 0 && power <= 8) {
                /* name  power
                   -----------
                   Yobi   8
                   Zebi   7
                   Exbi   9
                   Pebi   5
                   Tebi   4
                   Gibi   3
                   Mebi   2
                   kibi   1   */
                snprintf(dest, remaining_space, temp, " kMGTPEZY"[power]);
            } else if (power > 8) {
                /* for the larger values, print x2^{10}Gi for example */
                snprintf(dest, remaining_space, "x2^{%d}Yi", power-8);
            } else if (power < 0) {
                snprintf(dest, remaining_space, "x2^{%d}", power*10);
            } else {
                snprintf(dest, remaining_space, "  ");
            }

            break;
        }
        /*}}} */
        /*{{{  P --- multiple of pi */
        case 'P':
        {
            t[0] = 'f';
            t[1] = 0;
            snprintf(dest, remaining_space, temp, x / M_PI);
            break;
        }
        /*}}} */
        default:
            reset_numeric_locale();
            int_error(NO_CARET, "Bad format character");
        } /* switch */
        /*}}} */

        if (got_hash && (format != strpbrk(format,"oeEfFgG"))) {
            reset_numeric_locale();
            int_error(NO_CARET, "Bad format character");
        }

        /* change decimal '.' to the actual entry in decimalsign */
        if (decimalsign != NULL) {
            char *dotpos1 = dest;
            char *dotpos2;
            size_t newlength = strlen(decimalsign);

            /* dot is the default decimalsign we will be replacing */
            int dot = *get_decimal_locale();

            /* replace every dot by the contents of decimalsign */
            while ((dotpos2 = strchr(dotpos1,dot)) != NULL) {
                if (newlength == 1) {	/* The normal case */
                    *dotpos2 = *decimalsign;
                    dotpos1++;
                } else {		/* Some multi-byte decimal marker */
                    size_t taillength = strlen(dotpos2);
                    dotpos1 = dotpos2 + newlength;
                    if (dotpos1 + taillength > limit)
                        int_error(NO_CARET,
                                  "format too long due to decimalsign string");
                    /* move tail end of string out of the way */
                    memmove(dotpos1, dotpos2 + 1, taillength);
                    /* insert decimalsign */
                    memcpy(dotpos2, decimalsign, newlength);
                }
            }
        }

        /* this was at the end of every single case, before: */
        dest += strlen(dest);
        ++format;
    } /* for ever */

done:

#if (0)
    /* Oct 2013 - Not safe because it fails to recognize LaTeX macros.	*/
    /* For LaTeX terminals, if the user has not already provided a   	*/
    /* format in math mode, wrap whatever we got by default in $...$ 	*/
    if (((term->flags & TERM_IS_LATEX)) && !strchr(tempdest, '$')) {
        *(outstring++) = '$';
        strcat(tempdest, "$");
        count -= 2;
    }
#endif

    /* Copy as much as fits */
    safe_strncpy(outstring, tempdest, count);

    reset_numeric_locale();
}
Exemplo n.º 5
0
/* EAM Nov 2012:
 * Unbelievably, the count parameter has been silently ignored or
 * improperly applied ever since this routine was introduced back
 * in version 3.7.  Now fixed to prevent buffer overflow.
 */
void
gprintf(
    char *outstring,
    size_t count,
    char *format,
    double log10_base,
    double x)
{
    char tempdest[MAX_LINE_LEN + 1];
    char temp[MAX_LINE_LEN + 1];
    char *t;
    TBOOLEAN seen_mantissa = FALSE; /* remember if mantissa was already output */
    double stored_power_base = 0;   /* base for the last mantissa output*/
    int stored_power = 0;	/* power matching the mantissa output earlier */
    TBOOLEAN got_hash = FALSE;				   

    char *dest = &tempdest[0];
    char *limit = &tempdest[MAX_LINE_LEN];
#define remaining_space (size_t)(limit-dest)

    *dest = '\0';

    set_numeric_locale();

    for (;;) {
	/*{{{  copy to dest until % */
	while (*format != '%')
	    if (!(*dest++ = *format++) || (remaining_space == 0)) {
		safe_strncpy(outstring,tempdest,count);
		reset_numeric_locale();
		return;		/* end of format */
	    }
	/*}}} */

	/*{{{  check for %% */
	if (format[1] == '%') {
	    *dest++ = '%';
	    format += 2;
	    continue;
	}
	/*}}} */

	/*{{{  copy format part to temp, excluding conversion character */
	t = temp;
	*t++ = '%';
	if (format[1] == '#') {
	    *t++ = '#';
	    format++;
	    got_hash = TRUE;
	}
	/* dont put isdigit first since sideeffect in macro is bad */
	while (*++format == '.' || isdigit((unsigned char) *format)
	       || *format == '-' || *format == '+' || *format == ' '
	       || *format == '\'')
	    *t++ = *format;
	/*}}} */

	/*{{{  convert conversion character */
	switch (*format) {
	    /*{{{  x and o */
	case 'x':
	case 'X':
	case 'o':
	case 'O':
	    if (fabs(x) >= (double)INT_MAX) {
		t[0] = 'l';
		t[1] = 'l';
		t[2] = *format;
		t[3] = '\0';
		snprintf(dest, remaining_space, temp, (long long) x);
	    } else {
		t[0] = *format;
		t[1] = '\0';
		snprintf(dest, remaining_space, temp, (int) x);
	    }
	    break;
	    /*}}} */
	    /*{{{  e, f and g */
	case 'e':
	case 'E':
	case 'f':
	case 'F':
	case 'g':
	case 'G':
	    t[0] = *format;
	    t[1] = 0;
	    snprintf(dest, remaining_space, temp, x);
	    break;
	    /*}}} */
	    /*{{{  l --- mantissa to current log base */
	case 'l':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		stored_power_base = log10_base;
		mant_exp(stored_power_base, x, FALSE, &mantissa,
				&stored_power, temp);
		seen_mantissa = TRUE;
		snprintf(dest, remaining_space, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  t --- base-10 mantissa */
	case 't':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		stored_power_base = 1.0;
		mant_exp(stored_power_base, x, FALSE, &mantissa,
				&stored_power, temp);
		seen_mantissa = TRUE;
		snprintf(dest, remaining_space, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  s --- base-1000 / 'scientific' mantissa */
	case 's':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		stored_power_base = 1.0;
		mant_exp(stored_power_base, x, TRUE, &mantissa,
				&stored_power, temp);
		seen_mantissa = TRUE;
		snprintf(dest, remaining_space, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  b --- base-1024 mantissa */
	case 'b':
	    {
		double mantissa;

		t[0] = 'f';
		t[1] = 0;
		stored_power_base = log10(1024);
		mant_exp(stored_power_base, x, FALSE, &mantissa,
				&stored_power, temp);
		seen_mantissa = TRUE;
		snprintf(dest, remaining_space, temp, mantissa);
		break;
	    }
	    /*}}} */
	    /*{{{  L --- power to current log base */
	case 'L':
	    {
		int power;

		t[0] = 'd';
		t[1] = 0;
		if (seen_mantissa)
		    if (stored_power_base == log10_base)
			power = stored_power;
		    else
			int_error(NO_CARET, "Format character mismatch: %%L is only valid with %%l");
		else
		    stored_power_base = log10_base;
		    mant_exp(log10_base, x, FALSE, NULL, &power, "%.0f");
		snprintf(dest, remaining_space, temp, power);
		break;
	    }
	    /*}}} */
	    /*{{{  T --- power of ten */
	case 'T':
	    {
		int power;

		t[0] = 'd';
		t[1] = 0;
		if (seen_mantissa)
		    if (stored_power_base == 1.0)
			power = stored_power;
		    else
			int_error(NO_CARET, "Format character mismatch: %%T is only valid with %%t");
		else
		    mant_exp(1.0, x, FALSE, NULL, &power, "%.0f");
		snprintf(dest, remaining_space, temp, power);
		break;
	    }
	    /*}}} */
	    /*{{{  S --- power of 1000 / 'scientific' */
	case 'S':
	    {
		int power;

		t[0] = 'd';
		t[1] = 0;
		if (seen_mantissa)
		    if (stored_power_base == 1.0)
			power = stored_power;
		    else
			int_error(NO_CARET, "Format character mismatch: %%S is only valid with %%s");
		else
		    mant_exp(1.0, x, TRUE, NULL, &power, "%.0f");
		snprintf(dest, remaining_space, temp, power);
		break;
	    }
	    /*}}} */
	    /*{{{  c --- ISO decimal unit prefix letters */
	case 'c':
	    {
		int power;

		t[0] = 'c';
		t[1] = 0;
		if (seen_mantissa)
		    if (stored_power_base == 1.0)
			power = stored_power;
		    else
			int_error(NO_CARET, "Format character mismatch: %%c is only valid with %%s");
		else
		    mant_exp(1.0, x, TRUE, NULL, &power, "%.0f");

		if (power >= -24 && power <= 24) {
		    /* -18 -> 0, 0 -> 6, +18 -> 12, ... */
		    /* HBB 20010121: avoid division of -ve ints! */
		    power = (power + 24) / 3;
		    snprintf(dest, remaining_space, temp, "yzafpnum kMGTPEZY"[power]);
		} else {
		    /* please extend the range ! */
		    /* name  power   name  power
		       -------------------------
		       yocto  -24    yotta  24
		       zepto  -21    zetta  21
		       atto   -18    Exa    18
		       femto  -15    Peta   15
		       pico   -12    Tera   12
		       nano    -9    Giga    9
		       micro   -6    Mega    6
		       milli   -3    kilo    3   */

		    /* fall back to simple exponential */
		    snprintf(dest, remaining_space, "e%+02d", power);
		}
		break;
	    }
	    /*}}} */
	    /*{{{  B --- IEC 60027-2 A.2 / ISO/IEC 80000 binary unit prefix letters */
	case 'B':
	    {
		int power;

		t[0] = 'c';
		t[1] = 'i';
		t[2] = 0;
		if (seen_mantissa)
		    if (stored_power_base == log10(1024))
			power = stored_power;
		    else
			int_error(NO_CARET, "Format character mismatch: %%B is only valid with %%b");
		else
			mant_exp(log10(1024), x, FALSE, NULL, &power, "%.0f");

		if (power > 0 && power <= 8) {
		    /* name  power
		       -----------
		       Yobi   8
		       Zebi   7
		       Exbi   9
		       Pebi   5
		       Tebi   4
		       Gibi   3
		       Mebi   2
		       kibi   1   */
		    snprintf(dest, remaining_space, temp, " kMGTPEZY"[power]);
		} else if (power > 8) {
		    /* for the larger values, print x2^{10}Gi for example */
		    snprintf(dest, remaining_space, "x2^{%d}Yi", power-8);
		} else if (power < 0) {
		    snprintf(dest, remaining_space, "x2^{%d}", power*10);
		}

		break;
	    }
	    /*}}} */
	    /*{{{  P --- multiple of pi */
	case 'P':
	    {
		t[0] = 'f';
		t[1] = 0;
		snprintf(dest, remaining_space, temp, x / M_PI);
		break;
	    }
	    /*}}} */
	default:
	   reset_numeric_locale();
	   int_error(NO_CARET, "Bad format character");
	} /* switch */
	/*}}} */
	
	if (got_hash && (format != strpbrk(format,"oeEfFgG"))) {
	   reset_numeric_locale();
	   int_error(NO_CARET, "Bad format character");
	}

    /* change decimal `.' to the actual entry in decimalsign */
	if (decimalsign != NULL) {
	    char *dotpos1 = dest, *dotpos2;
	    size_t newlength = strlen(decimalsign);
	    int dot;

	    /* dot is the default decimalsign we will be replacing */
	    dot = *get_decimal_locale();

	    /* replace every dot by the contents of decimalsign */
	    while ((dotpos2 = strchr(dotpos1,dot)) != NULL) {
		size_t taillength = strlen(dotpos2);

		dotpos1 = dotpos2 + newlength;
		/* test if the new value for dest would be too long */
		if (dotpos1 - dest + taillength > count)
		    int_error(NO_CARET,
			      "format too long due to long decimalsign string");
		/* move tail end of string out of the way */
		memmove(dotpos1, dotpos2 + 1, taillength);
		/* insert decimalsign */
		memcpy(dotpos2, decimalsign, newlength);
	    }
	    /* clear temporary variables for safety */
	    dotpos1=NULL;
	    dotpos2=NULL;
	}

	/* this was at the end of every single case, before: */
	dest += strlen(dest);
	++format;
    } /* for ever */

    /* Copy as much as fits */
    safe_strncpy(outstring, tempdest, count);

    reset_numeric_locale();
}
Exemplo n.º 6
0
void 
statsrequest(void)
{ 
    int i;
    int columns;
    int columnsread;
    double v[2];
    static char *file_name = NULL;

    /* Vars to hold data and results */
    long n;                /* number of records retained */
    long max_n;

    static double *data_x = NULL;
    static double *data_y = NULL;   /* values read from file */
    long invalid;          /* number of missing/invalid records */
    long blanks;           /* number of blank lines */
    long doubleblanks;     /* number of repeated blank lines */
    long out_of_range;     /* number pts rejected, because out of range */

    struct file_stats res_file;
    struct sgl_column_stats res_x, res_y;
    struct two_column_stats res_xy;
    
    float *matrix;            /* matrix data. This must be float. */
    int nc, nr;               /* matrix dimensions. */
    int index;

    /* Vars for variable handling */
    static char *prefix = NULL;       /* prefix for user-defined vars names */

    /* Vars that control output */
    TBOOLEAN do_output = TRUE;     /* Generate formatted output */ 
    
    c_token++;

    /* Parse ranges */
    AXIS_INIT2D(FIRST_X_AXIS, 0);
    AXIS_INIT2D(FIRST_Y_AXIS, 0);
    parse_range(FIRST_X_AXIS);
    parse_range(FIRST_Y_AXIS);

    /* Initialize */
    columnsread = 2;
    invalid = 0;          /* number of missing/invalid records */
    blanks = 0;           /* number of blank lines */
    doubleblanks = 0;     /* number of repeated blank lines */
    out_of_range = 0;     /* number pts rejected, because out of range */
    n = 0;                /* number of records retained */
    nr = 0;               /* Matrix dimensions */
    nc = 0;
    max_n = INITIAL_DATA_SIZE;
    
    free(data_x);
    free(data_y);
    data_x = vec(max_n);       /* start with max. value */
    data_y = vec(max_n);

    if ( !data_x || !data_y )
      int_error( NO_CARET, "Internal error: out of memory in stats" );

    n = invalid = blanks = doubleblanks = out_of_range = nr = 0;

    /* Get filename */
    free ( file_name );
    file_name = try_to_get_string();

    if ( !file_name )
	int_error(c_token, "missing filename");

    /* ===========================================================
    v923z: insertion for treating matrices 
      EAM: only handles ascii matrix with uniform grid,
           and fails to apply any input data transforms
      =========================================================== */
    if ( almost_equals(c_token, "mat$rix") ) {
	df_open(file_name, 3, NULL);
	index = df_num_bin_records - 1;
	
	/* We take these values as set by df_determine_matrix_info
	See line 1996 in datafile.c */
	nc = df_bin_record[index].scan_dim[0];
	nr = df_bin_record[index].scan_dim[1];
	n = nc * nr;
	
	matrix = (float *)df_bin_record[index].memory_data;
	
	/* Fill up a vector, so that we can use the existing code. */
	if ( !redim_vec(&data_x, n ) ) {
	    int_error( NO_CARET, 
		   "Out of memory in stats: too many datapoints (%d)?", n );
	}
	for( i=0; i < n; i++ ) {
	    data_y[i] = (double)matrix[i];  
	}
	/* We can close the file here, there is nothing else to do */
	df_close();
	/* We will invoke single column statistics for the matrix */
	columns = 1;

    } else { /* Not a matrix */
	columns = df_open(file_name, 2, NULL); /* up to 2 using specs allowed */

	if (columns < 0)
	    int_error(NO_CARET, "Can't read data file"); 

	if (columns > 2 )
	    int_error(c_token, "Need 0 to 2 using specs for stats command");

	/* If the user has set an explicit locale for numeric input, apply it
	   here so that it affects data fields read from the input file. */
	/* v923z: where exactly should this be? here or before the matrix case? 
	 * I think, we should move everything here to before trying to open the file. 
	 * There is no point in trying to read anything, if the axis is logarithmic, e.g.
	 */
	set_numeric_locale();   

	/* For all these below: we could save the state, switch off, then restore */
	if ( axis_array[FIRST_X_AXIS].log || axis_array[FIRST_Y_AXIS].log )
	    int_error( NO_CARET, "Stats command not available with logscale active");

	if ( axis_array[FIRST_X_AXIS].datatype == DT_TIMEDATE || axis_array[FIRST_Y_AXIS].datatype == DT_TIMEDATE )
	    int_error( NO_CARET, "Stats command not available in timedata mode");

	if ( polar )
	    int_error( NO_CARET, "Stats command not available in polar mode" );

	if ( parametric )
	    int_error( NO_CARET, "Stats command not available in parametric mode" );

	/* The way readline and friends work is as follows:
	 - df_open will return the number of columns requested in the using spec
	   so that "columns" will be 0, 1, or 2 (no using, using 1, using 1:2)
	 - readline always returns the same number of columns (for us: 1 or 2)
	 - using 1:2 = return two columns, skipping lines w/ bad data
	 - using 1   = return sgl column (supply zeros (0) for the second col)
	 - no using  = return two columns (first two), fail on bad data 

	 We need to know how many columns to process. If columns==1 or ==2
	 (that is, if there was a using spec), all is clear and we use the
	 value of columns. 
	 But: if columns is 0, then we need to figure out the number of cols
	 read from the return value of readline. If readline ever returns
	 1, we take that; only if it always returns 2 do we assume two cols.
	 */
  
	while( (i = df_readline(v, 2)) != DF_EOF ) {
	    columnsread = ( i > columnsread ? i : columnsread );

	    if ( n >= max_n ) {
		max_n = (max_n * 3) / 2; /* increase max_n by factor of 1.5 */
	  
		/* Some of the reallocations went bad: */
		if ( 0 || !redim_vec(&data_x, max_n) || !redim_vec(&data_y, max_n) ) {
		    df_close();
		    int_error( NO_CARET, 
		       "Out of memory in stats: too many datapoints (%d)?",
		       max_n );
		} 
	    } /* if (need to extend storage space) */

	    switch (i) {
	    case DF_MISSING:
	    case DF_UNDEFINED:
	      /* Invalids are only recognized if the syntax is like this:
		     stats "file" using ($1):($2)
		 If the syntax is simply:
		     stats "file" using 1:2
		 then df_readline simply skips invalid records (does not
		 return anything!) Status: 2009-11-02 */
	      invalid += 1;
	      continue;
	      
	    case DF_FIRST_BLANK: 
	      blanks += 1;
	      continue;

	    case DF_SECOND_BLANK:      
	      blanks += 1;
	      doubleblanks += 1;
	      continue;
	      
	    case 0:
	      int_error( NO_CARET, "bad data on line %d of file %s",
	  		df_line_number, df_filename ? df_filename : "" );
	      break;

	    case 1: /* Read single column successfully  */
	      if ( validate_data(v[0], FIRST_Y_AXIS) )  {
		data_y[n] = v[0];
		n++;
	      } else {
		out_of_range++;
	      }
	      break;

	    case 2: /* Read two columns successfully  */
	      if ( validate_data(v[0], FIRST_X_AXIS) &&
		  validate_data(v[1], FIRST_Y_AXIS) ) {
		data_x[n] = v[0];
		data_y[n] = v[1];
		n++;
	      } else {
		out_of_range++;
	      }
	      break;
	    }
	} /* end-while : done reading file */
	df_close();

	/* now resize fields to actual length: */
	redim_vec(&data_x, n);
	redim_vec(&data_y, n);

	/* figure out how many columns where really read... */
	if ( columns == 0 )
	    columns = columnsread;

    }  /* end of case when the data file is not a matrix */

    /* Now finished reading user input; return to C locale for internal use*/
    reset_numeric_locale();

    /* PKJ - TODO: similar for logscale, polar/parametric, timedata */

    /* No data! Try to explain why. */
    if ( n == 0 ) {
	if ( out_of_range > 0 )
	    int_error( NO_CARET, "All points out of range" );
	else 
	    int_error( NO_CARET, "No valid data points found in file" );
    }

    /* Parse the remainder of the command line: 0 to 2 tokens possible */
    while( !(END_OF_COMMAND) ) {
	if ( almost_equals( c_token, "out$put" ) ) {
		do_output = TRUE;
		c_token++;

	} else if ( almost_equals( c_token, "noout$put" ) ) {
		do_output = FALSE;
		c_token++;

	} else if ( almost_equals(c_token, "pre$fix") 
	       ||   equals(c_token, "name")) {
	    c_token++;
	    free ( prefix );
	    prefix = try_to_get_string();
	    if (!legal_identifier(prefix) || !strcmp ("GPVAL_", prefix))
		int_error( --c_token, "illegal prefix" );

	}  else {
	    int_error( c_token, "Expecting [no]output or prefix");
	}

    }

    /* Set defaults if not explicitly set by user */
    if (!prefix)
	prefix = gp_strdup("STATS_");
    i = strlen(prefix);
    if (prefix[i-1] != '_') {
	prefix = gp_realloc(prefix, i+2, "prefix");
	strcat(prefix,"_");
    }

    /* Do the actual analysis */
    res_file = analyze_file( n, out_of_range, invalid, blanks, doubleblanks );
    if ( columns == 1 ) {
	res_y = analyze_sgl_column( data_y, n, nr );
    }

    if ( columns == 2 ) {
	/* If there are two columns, then the data file is not a matrix */
	res_x = analyze_sgl_column( data_x, n, 0 );
	res_y = analyze_sgl_column( data_y, n, 0 );
	res_xy = analyze_two_columns( data_x, data_y, res_x, res_y, n );
    }

    /* Store results in user-accessible variables */
    /* Clear out any previous use of these variables */
    del_udv_by_name( prefix, TRUE );

    file_variables( res_file, prefix );

    if ( columns == 1 ) {
	sgl_column_variables( res_y, prefix, "" );
    }
    
    if ( columns == 2 ) {
	sgl_column_variables( res_x, prefix, "_x" );
	sgl_column_variables( res_y, prefix, "_y" );
	two_column_variables( res_xy, prefix );
    }

    /* Output */
    if ( do_output ) {
	file_output( res_file );
	if ( columns == 1 )
	    sgl_column_output( res_y, res_file.records );
	else
	    two_column_output( res_x, res_y, res_xy, res_file.records );
    }

    /* Cleanup */
      
    free(data_x);
    free(data_y);

    data_x = NULL;
    data_y = NULL;
    
    free( file_name );
    file_name = NULL;
    
    free( prefix );
    prefix = NULL;
}