Exemple #1
0
size_t
gstrftime(char *s, size_t bsz, const char *fmt, double l_clock)
{
    struct tm tm;
    double usec;

    ggmtime(&tm, l_clock);

    usec = l_clock - (double)floor(l_clock);

    return xstrftime(s, bsz, fmt, &tm, usec, l_clock);
}
Exemple #2
0
size_t
gstrftime(char *s, size_t bsz, const char *fmt, double l_clock)
{
    struct tm tm;

    ggmtime(&tm, l_clock);
#if 0
    if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone) + 1)))
        strcpy(tm.tm_zone, xtm->tm_zone);
    /* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */
#endif

    return xstrftime(s, bsz, fmt, &tm);
}
Exemple #3
0
char *
gstrptime(char *s, char *fmt, struct tm *tm, double *usec)
{
    int yday = 0;
    TBOOLEAN sanity_check_date = FALSE;

    tm->tm_mday = 1;
    tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
    /* make relative times work (user-defined tic step) */
    tm->tm_year = ZERO_YEAR;

    /* Fractional seconds will be returned separately, since
     * there is no slot for the fraction in struct tm.
     */
    *usec = 0.0;

    /* we do not yet calculate wday or yday, so make them illegal
     * [but yday will be read by %j]
     */
    tm->tm_yday = tm->tm_wday = -1;

    /* If the format requests explicit day, month, or year, then we will
     * do sanity checking to make sure the input makes sense.
     * For backward compatibility with gnuplot versions through 4.6.6
     * hour, minute, seconds default to zero with no error return
     * if the corresponding field cannot be found or interpreted.
     */
    if (strstr(fmt,"%d")) {
        tm->tm_mday = -1;
        sanity_check_date = TRUE;
    }
    if (strstr(fmt,"%y") || strstr(fmt,"%Y")) {
        tm->tm_year = -1;
        sanity_check_date = TRUE;
    }
    if (strstr(fmt,"%m") || strstr(fmt,"%B") || strstr(fmt,"%b")) {
        tm->tm_mon = -1;
        sanity_check_date = TRUE;
    }


    while (*fmt) {
        if (*fmt != '%') {
            if (*fmt == ' ') {
                /* space in format means zero or more spaces in input */
                while (*s == ' ')
                    ++s;
                ++fmt;
                continue;
            } else if (*fmt == *s) {
                ++s;
                ++fmt;
                continue;
            } else
                break;		/* literal match has failed */
        }
        /* we are processing a percent escape */

        switch (*++fmt) {
        case 'b':		/* abbreviated month name */
        {
            int m;

            for (m = 0; m < 12; ++m)
                if (strncasecmp(s, abbrev_month_names[m],
                                strlen(abbrev_month_names[m])) == 0) {
                    s += strlen(abbrev_month_names[m]);
                    goto found_abbrev_mon;
                }
            /* get here => not found */
            int_warn(DATAFILE, "Bad abbreviated month name");
            m = 0;
found_abbrev_mon:
            tm->tm_mon = m;
            break;
        }

        case 'B':		/* full month name */
        {
            int m;

            for (m = 0; m < 12; ++m)
                if (strncasecmp(s, full_month_names[m],
                                strlen(full_month_names[m])) == 0) {
                    s += strlen(full_month_names[m]);
                    goto found_full_mon;
                }
            /* get here => not found */
            int_warn(DATAFILE, "Bad full month name");
            m = 0;
found_full_mon:
            tm->tm_mon = m;
            break;
        }

        case 'd':		/* read a day of month */
            s = read_int(s, 2, &tm->tm_mday);
            break;

        case 'm':		/* month number */
            s = read_int(s, 2, &tm->tm_mon);
            --tm->tm_mon;
            break;

        case 'y':		/* year number */
            s = read_int(s, 2, &tm->tm_year);
            /* In line with the current UNIX98 specification by
             * The Open Group and major Unix vendors,
             * two-digit years 69-99 refer to the 20th century, and
             * values in the range 00-68 refer to the 21st century.
             */
            if (tm->tm_year <= 68)
                tm->tm_year += 100;
            tm->tm_year += 1900;
            break;

        case 'Y':
            s = read_int(s, 4, &tm->tm_year);
            break;

        case 'j':
            s = read_int(s, 3, &tm->tm_yday);
            tm->tm_yday--;
            sanity_check_date = TRUE;
            yday++;
            break;

        case 'H':
            s = read_int(s, 2, &tm->tm_hour);
            break;

        case 'M':
            s = read_int(s, 2, &tm->tm_min);
            break;

        case 'S':
            s = read_int(s, 2, &tm->tm_sec);
            if (*s == '.' || (decimalsign && *s == *decimalsign))
                *usec = atof(s);
            break;


        case 's':
            /* read EPOCH data
             * EPOCH is the std. unix timeformat seconds since 01.01.1970 UTC
             */
        {
            char  *fraction = strchr(s, decimalsign ? *decimalsign : '.');
            double ufraction = 0;
            double when = strtod (s, &s) - SEC_OFFS_SYS;
            ggmtime(tm, when);
            if (fraction && fraction < s)
                ufraction = atof(fraction);
            if (ufraction < 1.)		/* Filter out e.g. 123.456e7 */
                *usec = ufraction;
            break;
        }

        default:
            int_warn(DATAFILE, "Bad time format in string");
        }
        fmt++;
    }

    FPRINTF((stderr, "read date-time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));

    /* now sanity check the date/time entered, normalising if necessary
     * read_int cannot read a -ve number, but can read %m=0 then decrement
     * it to -1
     */

#define S (tm->tm_sec)
#define M (tm->tm_min)
#define H (tm->tm_hour)

    if (S >= 60) {
        M += S / 60;
        S %= 60;
    }
    if (M >= 60) {
        H += M / 60;
        M %= 60;
    }
    if (H >= 24) {
        if (yday)
            tm->tm_yday += H / 24;
        tm->tm_mday += H / 24;
        H %= 24;
    }
#undef S
#undef M
#undef H

    FPRINTF((stderr, "normalised time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));

    if (sanity_check_date) {
        if (yday) {

            if (tm->tm_yday < 0) {
                // int_error(DATAFILE, "Illegal day of year");
                return (NULL);
            }

            /* we just set month to jan, day to yday, and let the
             * normalising code do the work.
             */

            tm->tm_mon = 0;
            /* yday is 0->365, day is 1->31 */
            tm->tm_mday = tm->tm_yday + 1;
        }
        if (tm->tm_mon < 0) {
            // int_error(DATAFILE, "illegal month");
            return (NULL);
        }
        if (tm->tm_mday < 1) {
            // int_error(DATAFILE, "illegal day of month");
            return (NULL);
        }
        if (tm->tm_mon > 11) {
            tm->tm_year += tm->tm_mon / 12;
            tm->tm_mon %= 12;
        } {
            int days_in_month;
            while (tm->tm_mday > (days_in_month = (mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365))))) {
                if (++tm->tm_mon == 12) {
                    ++tm->tm_year;
                    tm->tm_mon = 0;
                }
                tm->tm_mday -= days_in_month;
            }
        }
    }
    return (s);
}
Exemple #4
0
static int command()
{
    FILE *fp;
    int i;
    /* string holding name of save or load file */
    char sv_file[MAX_LINE_LEN + 1];

    for (i = 0; i < MAX_NUM_VAR; i++)
	c_dummy_var[i][0] = NUL;	/* no dummy variables */

    if (is_definition(c_token))
	define();
    else if (almost_equals(c_token, "h$elp") || equals(c_token, "?")) {
	c_token++;
	do_help(1);
    } else if (equals(c_token, "testtime")) {
	/* given a format and a time string, exercise the time code */
	char format[160], string[160];
	struct tm tm;
	double secs;
	if (isstring(++c_token)) {
	    quote_str(format, c_token, 159);
	    if (isstring(++c_token)) {
		quote_str(string, c_token++, 159);
		memset(&tm, 0, sizeof(tm));
		gstrptime(string, format, &tm);
		secs = gtimegm(&tm);
		fprintf(stderr, "internal = %f - %d/%d/%d::%d:%d:%d , wday=%d, yday=%d\n",
			secs, tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday, tm.tm_yday);
		memset(&tm, 0, sizeof(tm));
		ggmtime(&tm, secs);
		gstrftime(string, 159, format, secs);
		fprintf(stderr, "convert back \"%s\" - %d/%d/%d::%d:%d:%d , wday=%d, yday=%d\n",
			string, tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_wday, tm.tm_yday);
	    }
	}
    } else if (almost_equals(c_token, "test")) {
	c_token++;
	test_term();
    } else if (almost_equals(c_token, "scr$eendump")) {
	c_token++;
#ifdef _Windows
	screen_dump();
#else
	fputs("screendump not implemented\n", stderr);
#endif
    } else if (almost_equals(c_token, "pa$use")) {
	struct value a;
	int sleep_time, text = 0;
	char buf[MAX_LINE_LEN + 1];

	c_token++;
	sleep_time = (int) real(const_express(&a));
	buf[0] = NUL;
	if (!(END_OF_COMMAND)) {
	    if (!isstring(c_token))
		int_error("expecting string", c_token);
	    else {
		quote_str(buf, c_token, MAX_LINE_LEN);
		++c_token;
#ifdef _Windows
		if (sleep_time >= 0)
#else
# ifdef OS2
		if (strcmp(term->name, "pm") != 0 || sleep_time >= 0)
# else
#  ifdef MTOS
	        if (strcmp(term->name, "mtos") != 0 || sleep_time >= 0)
#  endif /* MTOS */
# endif /* OS2 */
#endif /* _Windows */
			fputs(buf, stderr);
		text = 1;
	    }
	}
	if (sleep_time < 0) {
#ifdef _Windows
	    if (!Pause(buf))
		bail_to_command_line();
#else
# ifdef OS2
	    if (strcmp(term->name, "pm") == 0 && sleep_time < 0) {
		int rc;
		if ((rc = PM_pause(buf)) == 0)
		    bail_to_command_line();
		else if (rc == 2) {
		    fputs(buf, stderr);
		    text = 1;
		    (void) fgets(buf, MAX_LINE_LEN, stdin);
		}
	    }
# else				/* !OS2 */
#  ifdef _Macintosh
	    if (strcmp(term->name, "macintosh") == 0 && sleep_time < 0)
		Pause(sleep_time);
#  else				/* !_Macintosh */
#   ifdef MTOS
	    if (strcmp(term->name, "mtos") == 0) {
		int MTOS_pause(char *buf);
		int rc;
		if ((rc = MTOS_pause(buf)) == 0)
		    bail_to_command_line();
		else if (rc == 2) {
		    fputs(buf, stderr);
		    text = 1;
		    (void) fgets(buf, MAX_LINE_LEN, stdin);
		}
	    } else if (strcmp(term->name, "atari") == 0) {
		char *readline(char *);
		char *line = readline("");
		if (line)
		    free(line);
	    } else
		(void) fgets(buf, MAX_LINE_LEN, stdin);
#   else			/* !MTOS */
#    ifdef ATARI
	    if (strcmp(term->name, "atari") == 0) {
		char *readline(char *);
		char *line = readline("");
		if (line)
		    free(line);
	    } else
		(void) fgets(buf, MAX_LINE_LEN, stdin);
#    else			/* !ATARI */
	    (void) fgets(buf, MAX_LINE_LEN, stdin);
	    /* Hold until CR hit. */
#    endif			/* !ATARI */
#   endif			/* !MTOS */
#  endif			/* !_Macintosh */
# endif				/* !OS2 */
#endif
	}
	if (sleep_time > 0)
	    GP_SLEEP(sleep_time);

	if (text != 0 && sleep_time >= 0)
	    fputc('\n', stderr);
	screen_ok = FALSE;
    } else if (almost_equals(c_token, "pr$int")) {
	int need_space = 0;	/* space printed between two expressions only */
	screen_ok = FALSE;
	do {
	    ++c_token;
	    if (isstring(c_token)) {
		char s[MAX_LINE_LEN];
		quote_str(s, c_token, MAX_LINE_LEN);
		fputs(s, stderr);
		need_space = 0;
		++c_token;
	    } else {
		struct value a;
		(void) const_express(&a);
		if (need_space)
		    putc(' ', stderr);
		need_space = 1;
		disp_value(stderr, &a);
	    }
	} while (!END_OF_COMMAND && equals(c_token, ","));

	(void) putc('\n', stderr);
    } else if (almost_equals(c_token, "fit")) {
	++c_token;
	do_fit();
    } else if (almost_equals(c_token, "up$date")) {
	char tmps[80];
	char tmps2[80];
	/* Have to initialise tmps2, otherwise
	 * update() cannot decide whether a valid
	 * filename was given. lh
	 */
	tmps2[0] = NUL;
	if (!isstring(++c_token))
	    int_error("Parameter filename expected", c_token);
	quote_str(tmps, c_token++, 80);
	if (!(END_OF_COMMAND)) {
	    if (!isstring(c_token))
		int_error("New parameter filename expected", c_token);
	    else
		quote_str(tmps2, c_token++, 80);
	}
	update(tmps, tmps2);
    } else if (almost_equals(c_token, "p$lot")) {
	plot_token = c_token++;
	SET_CURSOR_WAIT;
	plotrequest();
	SET_CURSOR_ARROW;
    } else if (almost_equals(c_token, "sp$lot")) {
	plot_token = c_token++;
	SET_CURSOR_WAIT;
	plot3drequest();
	SET_CURSOR_ARROW;
    } else if (almost_equals(c_token, "rep$lot")) {
	if (replot_line[0] == NUL)
	    int_error("no previous plot", c_token);
	c_token++;
	SET_CURSOR_WAIT;
	replotrequest();
	SET_CURSOR_ARROW;
    } else if (almost_equals(c_token, "se$t"))
	set_command();
    else if (almost_equals(c_token, "res$et"))
	reset_command();
    else if (almost_equals(c_token, "sh$ow"))
	show_command();
    else if (almost_equals(c_token, "cl$ear")) {
	term_start_plot();

	if (multiplot && term->fillbox) {
	    unsigned int x1 = (unsigned int) (xoffset * term->xmax);
	    unsigned int y1 = (unsigned int) (yoffset * term->ymax);
	    unsigned int width = (unsigned int) (xsize * term->xmax);
	    unsigned int height = (unsigned int) (ysize * term->ymax);
	    (*term->fillbox) (0, x1, y1, width, height);
	}
	term_end_plot();

	screen_ok = FALSE;
	c_token++;
    } else if (almost_equals(c_token, "she$ll")) {
	do_shell();
	screen_ok = FALSE;
	c_token++;
    } else if (almost_equals(c_token, "sa$ve")) {
	if (almost_equals(++c_token, "f$unctions")) {
	    if (!isstring(++c_token))
		int_error("expecting filename", c_token);
	    else {
		quote_str(sv_file, c_token, MAX_LINE_LEN);
		save_functions(fopen(sv_file, "w"));
	    }
	} else if (almost_equals(c_token, "v$ariables")) {
	    if (!isstring(++c_token))
		int_error("expecting filename", c_token);
	    else {
		quote_str(sv_file, c_token, MAX_LINE_LEN);
		save_variables(fopen(sv_file, "w"));
	    }
	} else if (almost_equals(c_token, "s$et")) {
	    if (!isstring(++c_token))
		int_error("expecting filename", c_token);
	    else {
		quote_str(sv_file, c_token, MAX_LINE_LEN);
		save_set(fopen(sv_file, "w"));
	    }
	} else if (isstring(c_token)) {
	    quote_str(sv_file, c_token, MAX_LINE_LEN);
	    save_all(fopen(sv_file, "w"));
	} else {
	    int_error("filename or keyword 'functions', 'variables', or 'set' expected", c_token);
	}
	c_token++;
    } else if (almost_equals(c_token, "l$oad")) {
	if (!isstring(++c_token))
	    int_error("expecting filename", c_token);
	else {
	    quote_str(sv_file, c_token, MAX_LINE_LEN);
	    /* load_file(fp=fopen(sv_file, "r"), sv_file, FALSE); OLD
	     * DBT 10/6/98 handle stdin as special case
	     * passes it on to load_file() so that it gets
	     * pushed on the stack and recusion will work, etc
	     */
	    fp = strcmp(sv_file, "-") ? fopen(sv_file, "r") : stdin; 
	    load_file(fp, sv_file, FALSE);
	    /* input_line[] and token[] now destroyed! */
	    c_token = num_tokens = 0;
	}
    } else if (almost_equals(c_token, "ca$ll")) {
	if (!isstring(++c_token))
	    int_error("expecting filename", c_token);
	else {
	    quote_str(sv_file, c_token, MAX_LINE_LEN);
	    load_file(fopen(sv_file, "r"), sv_file, TRUE);	/* Argument list follows filename */
	    /* input_line[] and token[] now destroyed! */
	    c_token = num_tokens = 0;
	}
    } else if (almost_equals(c_token, "if")) {
	double exprval;
	struct value t;
	if (!equals(++c_token, "("))	/* no expression */
	    int_error("expecting (expression)", c_token);
	exprval = real(const_express(&t));
	if (exprval != 0.0) {
	    /* fake the condition of a ';' between commands */
	    int eolpos = token[num_tokens - 1].start_index + token[num_tokens - 1].length;
	    --c_token;
	    token[c_token].length = 1;
	    token[c_token].start_index = eolpos + 2;
	    input_line[eolpos + 2] = ';';
	    input_line[eolpos + 3] = NUL;
	} else
	    c_token = num_tokens = 0;
    } else if (almost_equals(c_token, "rer$ead")) {
	fp = lf_top();
	if (fp != (FILE *) NULL)
	    rewind(fp);
	c_token++;
    } else if (almost_equals(c_token, "cd")) {
	if (!isstring(++c_token))
	    int_error("expecting directory name", c_token);
	else {
	    quote_str(sv_file, c_token, MAX_LINE_LEN);
	    if (changedir(sv_file)) {
		int_error("Can't change to this directory", c_token);
	    }
	    c_token++;
	}
    } else if (almost_equals(c_token, "pwd")) {
	GP_GETCWD(sv_file, sizeof(sv_file));
	fprintf(stderr, "%s\n", sv_file);
	c_token++;
    } else if (almost_equals(c_token, "ex$it") ||
	       almost_equals(c_token, "q$uit")) {
	/* graphics will be tidied up in main */
	return (1);
    } else if (!equals(c_token, ";")) {		/* null statement */
#ifdef OS2
	if (_osmode == OS2_MODE) {
	    if (token[c_token].is_token) {
		int rc;
		rc = ExecuteMacro(input_line + token[c_token].start_index,
				  token[c_token].length);
		if (rc == 0) {
		    c_token = num_tokens = 0;
		    return (0);
		}
	    }
	}
#endif
	int_error("invalid command", c_token);
    }
    return (0);
}
Exemple #5
0
char *
gstrptime(char *s, char *fmt, struct tm *tm)
{
    int yday, date;

    date = yday = 0;
    tm->tm_mday = 1;
    tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
    /* make relative times work (user-defined tic step) */
    tm->tm_year = ZERO_YEAR;

    /* we do not yet calculate wday or yday, so make them illegal
     * [but yday will be read by %j]
     */

    tm->tm_yday = tm->tm_wday = -1;

    while (*fmt) {
        if (*fmt != '%') {
            if (*fmt == ' ') {
                /* space in format means zero or more spaces in input */
                while (*s == ' ')
                    ++s;
                ++fmt;
                continue;
            } else if (*fmt == *s) {
                ++s;
                ++fmt;
                continue;
            } else
                break;		/* literal match has failed */
        }
        /* we are processing a percent escape */

        switch (*++fmt) {
        case 'b':		/* abbreviated month name */
        {
            int m;

            for (m = 0; m < 12; ++m)
                if (strncasecmp(s, abbrev_month_names[m],
                                strlen(abbrev_month_names[m])) == 0) {
                    s += strlen(abbrev_month_names[m]);
                    goto found_abbrev_mon;
                }
            /* get here => not found */
            int_warn(DATAFILE, "Bad abbreviated month name");
            m = 0;
found_abbrev_mon:
            tm->tm_mon = m;
            break;
        }

        case 'B':		/* full month name */
        {
            int m;

            for (m = 0; m < 12; ++m)
                if (strncasecmp(s, full_month_names[m],
                                strlen(full_month_names[m])) == 0) {
                    s += strlen(full_month_names[m]);
                    goto found_full_mon;
                }
            /* get here => not found */
            int_warn(DATAFILE, "Bad full month name");
            m = 0;
found_full_mon:
            tm->tm_mon = m;
            break;
        }

        case 'd':		/* read a day of month */
            s = read_int(s, 2, &tm->tm_mday);
            date++;
            break;

        case 'm':		/* month number */
            s = read_int(s, 2, &tm->tm_mon);
            date++;
            --tm->tm_mon;
            break;

        case 'y':		/* year number */
            s = read_int(s, 2, &tm->tm_year);
            /* In line with the current UNIX98 specification by
             * The Open Group and major Unix vendors,
             * two-digit years 69-99 refer to the 20th century, and
             * values in the range 00-68 refer to the 21st century.
             */
            if (tm->tm_year <= 68)
                tm->tm_year += 100;
            date++;
            tm->tm_year += 1900;
            break;

        case 'Y':
            s = read_int(s, 4, &tm->tm_year);
            date++;
            break;

        case 'j':
            s = read_int(s, 3, &tm->tm_yday);
            tm->tm_yday--;
            date++;
            yday++;
            break;

        case 'H':
            s = read_int(s, 2, &tm->tm_hour);
            break;

        case 'M':
            s = read_int(s, 2, &tm->tm_min);
            break;

        case 'S':
            s = read_int(s, 2, &tm->tm_sec);
            break;

        /* read EPOCH data
         * EPOCH is the std. unixtimeformat seconds since 01.01.1970 UTC
         * actualy i would need a read_long (or what time_t is else)
         *  aktualy this is not my idea       i got if from
         * AlunDa Penguin Jones (21.11.97)
         * but changed %t to %s because of strftime
         * and fixed the localtime() into gmtime()
         * maybe we should use ggmtime() ? but who choose double ????
         * Walter Harms <*****@*****.**> 26 Mar 2000
         */

        case 's':
#if 0 /* HBB 20040213: comment this out, but keep it around for now */
        {
            /* time_t when; */
            int when;
            struct tm *tmwhen;
            s = read_int(s, 10, &when);
            tmwhen = gmtime((time_t*)&when);
            tmwhen->tm_year += 1900;
            *tm = *tmwhen;
            break;
        }
#else
            /* HBB 20040213: New version of this.  64-bit proof and
             * more in line with the rest of this module than the
             * original one. */
        {
            double when;
            /* offset from UNIX epoch (1970) to gnuplot epoch */
            static const long epoch_offset
                = (long)((ZERO_YEAR - 1970) * 365.25) * DAY_SEC;

            when = strtod (s, &s) - epoch_offset;
            ggmtime(tm, when);
            break;
        }
#endif
        default:
            int_warn(DATAFILE, "Bad time format in string");
        }
        fmt++;
    }

    FPRINTF((stderr, "read date-time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));

    /* now check the date/time entered, normalising if necessary
     * read_int cannot read a -ve number, but can read %m=0 then decrement
     * it to -1
     */

#define S (tm->tm_sec)
#define M (tm->tm_min)
#define H (tm->tm_hour)

    if (S >= 60) {
        M += S / 60;
        S %= 60;
    }
    if (M >= 60) {
        H += M / 60;
        M %= 60;
    }
    if (H >= 24) {
        if (yday)
            tm->tm_yday += H / 24;
        tm->tm_mday += H / 24;
        H %= 24;
    }
#undef S
#undef M
#undef H

    FPRINTF((stderr, "normalised time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));

    if (date) {
        if (yday) {

            if (tm->tm_yday < 0)
                int_error(DATAFILE, "Illegal day of year");

            /* we just set month to jan, day to yday, and let the
             * normalising code do the work.
             */

            tm->tm_mon = 0;
            /* yday is 0->365, day is 1->31 */
            tm->tm_mday = tm->tm_yday + 1;
        }
        if (tm->tm_mon < 0) {
            int_error(DATAFILE, "illegal month");
            return (NULL);
        }
        if (tm->tm_mday < 1) {
            int_error(DATAFILE, "illegal day of month");
            return (NULL);
        }
        if (tm->tm_mon > 11) {
            tm->tm_year += tm->tm_mon / 12;
            tm->tm_mon %= 12;
        } {
            int days_in_month;
            while (tm->tm_mday > (days_in_month = (mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365))))) {
                if (++tm->tm_mon == 12) {
                    ++tm->tm_year;
                    tm->tm_mon = 0;
                }
                tm->tm_mday -= days_in_month;
            }
        }
    }
    return (s);
}