static void set_degreesign(char *locale) { #if defined(HAVE_ICONV) && !(defined _WIN32) char degree_utf8[3] = {'\302', '\260', '\0'}; size_t lengthin = 3; size_t lengthout = 8; char *in = degree_utf8; char *out = degree_sign; iconv_t cd; if (locale) { /* This should work even if gnuplot doesn't understand the encoding */ #ifdef HAVE_LANGINFO_H char *cencoding = nl_langinfo(CODESET); #else char *cencoding = strchr(locale, '.'); if (cencoding) cencoding++; /* Step past the dot in, e.g., ja_JP.EUC-JP */ #endif if (cencoding) { if (strcmp(cencoding,"UTF-8") == 0) strcpy(degree_sign,degree_utf8); else if ((cd = iconv_open(cencoding, "UTF-8")) == (iconv_t)(-1)) int_warn(NO_CARET, "iconv_open failed for %s", cencoding); else { if (iconv(cd, &in, &lengthin, &out, &lengthout) == (size_t)(-1)) int_warn(NO_CARET, "iconv failed to convert degree sign"); iconv_close(cd); } } return; } #else (void)locale; /* -Wunused argument */ #endif /* These are the internally-known encodings */ memset(degree_sign, 0, sizeof(degree_sign)); switch (encoding) { case S_ENC_UTF8: degree_sign[0] = '\302'; degree_sign[1] = '\260'; break; case S_ENC_KOI8_R: case S_ENC_KOI8_U: degree_sign[0] = '\234'; break; case S_ENC_CP437: case S_ENC_CP850: case S_ENC_CP852: degree_sign[0] = '\370'; break; case S_ENC_SJIS: break; /* should be 0x818B */ case S_ENC_CP950: break; /* should be 0xA258 */ /* default applies at least to: ISO8859-1, -2, -9, -15, CP1250, CP1251, CP1252, CP1254 */ default: degree_sign[0] = '\260'; break; } }
/* find or add function at index <t_num>, and return pointer */ struct udft_entry * add_udf(int t_num) { struct udft_entry **udf_ptr = &first_udf; int i; while (*udf_ptr) { if (equals(t_num, (*udf_ptr)->udf_name)) return (*udf_ptr); udf_ptr = &((*udf_ptr)->next_udf); } /* get here => not found. udf_ptr points at first_udf or * next_udf field of last udf */ if (is_builtin_function(t_num)) int_warn(t_num, "Warning : udf shadowed by built-in function of the same name"); /* create and return a new udf slot */ *udf_ptr = (struct udft_entry *) gp_alloc(sizeof(struct udft_entry), "function"); (*udf_ptr)->next_udf = (struct udft_entry *) NULL; (*udf_ptr)->definition = NULL; (*udf_ptr)->at = NULL; (*udf_ptr)->udf_name = gp_alloc (token_len(t_num)+1, "user func"); copy_str((*udf_ptr)->udf_name, t_num, token_len(t_num)+1); for (i = 0; i < MAX_NUM_VAR; i++) (void) Ginteger(&((*udf_ptr)->dummy_values[i]), 0); return (*udf_ptr); }
/* FIXME HH 20020915: This function does nothing if dirent.h and windows.h * not available. */ TBOOLEAN existdir (const char *name) { #ifdef HAVE_DIRENT_H DIR *dp; if (! (dp = opendir(name) ) ) return FALSE; closedir(dp); return TRUE; #elif defined(_Windows) HANDLE FileHandle; WIN32_FIND_DATA finddata; FileHandle = FindFirstFile(name, &finddata); if (FileHandle != INVALID_HANDLE_VALUE) { if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return TRUE; } return FALSE; #elif defined(VMS) return FALSE; #else int_warn(NO_CARET, "Test on directory existence not supported\n\t('%s!')", name); return FALSE; #endif }
void get_user_env() { if (user_homedir == NULL) { const char *env_home; if ((env_home = getenv(HOME)) #ifdef WIN32 || (env_home = appdata_directory()) || (env_home = getenv("USERPROFILE")) #endif #ifndef VMS || (env_home = getenv("HOME")) #endif ) user_homedir = (const char *) gp_strdup(env_home); else if (interactive) int_warn(NO_CARET, "no HOME found"); } /* Hhm ... what about VMS? */ if (user_shell == NULL) { const char *env_shell; if ((env_shell = getenv("SHELL")) == NULL) #if defined(MSDOS) || defined(_Windows) || defined(OS2) if ((env_shell = getenv("COMSPEC")) == NULL) #endif env_shell = SHELL; user_shell = (const char *) gp_strdup(env_shell); } }
/* Geometrical mean = pow( prod(x_i > 0) x_i, 1/N ) * Sign of the result: result is positive if 3 or 4 x_i are positive, * it is negative if 3 or all 4 x_i are negative. Helps to splot surface * with all color coordinates negative. */ static double geomean4 (double x1, double x2, double x3, double x4) { #if 0 /* return 0 if any of the number is negative */ if (x1 <= 0) x1 = 1; if (x2 > 0) x1 *= x2; if (x3 > 0) x1 *= x3; if (x4 > 0) x1 *= x4; return pow(x1, 0.25); #else /* honor signess, i.e. sign(geomean) = sign(prod(x_i)) */ int neg = (x1 < 0) + (x2 < 0) + (x3 < 0) + (x4 < 0); x1 *= x2 * x3 * x4; if (x1 == 0) return 0; /* pow(x, 0.25) is slightly faster than sqrt(sqrt(x)) */ x1 = sqrt(sqrt(fabs(x1))); #if 0 /* such a warning could be helpful, but under normal usage it is just an overhead */ if (neg > 1 && interactive && notwarned) { int notwarned = 1; ... to be set on every new splot if (notwarned) int_warn(NO_CARET, "corners2color geomean with negative data points"); notwarned = 0; }
int ggmtime(struct tm *tm, double l_clock) { /* l_clock is relative to ZERO_YEAR, jan 1, 00:00:00,defined in plot.h */ int i, days; /* dodgy way of doing wday - i hope it works ! */ int wday = JAN_FIRST_WDAY; /* eg 6 for 2000 */ FPRINTF((stderr, "%g seconds = ", l_clock)); if (fabs(l_clock) > 1.e12) { /* Some time in the year 33688 */ int_warn(NO_CARET, "time value out of range"); return(-1); } tm->tm_year = ZERO_YEAR; tm->tm_mday = tm->tm_yday = tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0; if (l_clock < 0) { while (l_clock < 0) { int days_in_year = gdysize(--tm->tm_year); l_clock += days_in_year * DAY_SEC; /* 24*3600 */ /* adding 371 is noop in modulo 7 arithmetic, but keeps wday +ve */ wday += 371 - days_in_year; } } else { for (;;) { int days_in_year = gdysize(tm->tm_year); if (l_clock < days_in_year * DAY_SEC) break; l_clock -= days_in_year * DAY_SEC; tm->tm_year++; /* only interested in result modulo 7, but %7 is expensive */ wday += (days_in_year - 364); } } tm->tm_yday = (int) (l_clock / DAY_SEC); l_clock -= tm->tm_yday * DAY_SEC; tm->tm_hour = (int) l_clock / 3600; l_clock -= tm->tm_hour * 3600; tm->tm_min = (int) l_clock / 60; l_clock -= tm->tm_min * 60; tm->tm_sec = (int) l_clock; days = tm->tm_yday; /* wday%7 should be day of week of first day of year */ tm->tm_wday = (wday + days) % 7; while (days >= (i = mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365)))) { days -= i; tm->tm_mon++; } tm->tm_mday = days + 1; FPRINTF((stderr, "broken-down 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)); return (0); }
void write_history_list(const int num, const char *const filename, const char *mode) { const HIST_ENTRY *list_entry; FILE *out = stdout; int is_pipe = 0; int is_file = 0; int is_quiet = 0; int i, istart; if (filename && filename[0] ) { /* good filename given and not quiet */ #ifdef PIPES if (filename[0]=='|') { restrict_popen(); out = popen(filename+1, "w"); is_pipe = 1; } else { #endif if (! (out = fopen(filename, mode) ) ) { /* Fall back to 'stdout' */ int_warn(NO_CARET, "Cannot open file to save history, using standard output.\n"); out = stdout; } else is_file = 1; #ifdef PIPES } #endif } else if (filename && !filename[0]) is_quiet = 1; /* Determine starting point and output in loop. * For some reason the readline functions append_history() * and write_history() do not work they way I thought they did... */ if (num > 0) { istart = history_length - num; if (istart <= 0 || istart > history_length) istart = 1; } else istart = 1; for (i = istart; (list_entry = history_get(i)); i++) { /* don't add line numbers when writing to file to make file loadable */ if (is_file) fprintf(out, "%s\n", list_entry->line); else { if (!is_quiet) fprintf(out, "%5i", i + history_base - 1); fprintf(out, " %s\n", list_entry->line); } } /* close if something was opened */ #ifdef PIPES if (is_pipe) pclose(out); #endif if (is_file) fclose(out); }
static int get_num(char str[]) { int count = 0; char *endptr; token[t_num].is_token = FALSE; token[t_num].l_val.type = INTGR; /* assume unless . or E found */ while (isdigit((unsigned char) str[count])) count++; if (str[count] == '.') { token[t_num].l_val.type = CMPLX; /* swallow up digits until non-digit */ while (isdigit((unsigned char) str[++count])); /* now str[count] is other than a digit */ } if (str[count] == 'e' || str[count] == 'E') { token[t_num].l_val.type = CMPLX; count++; if (str[count] == '-' || str[count] == '+') count++; if (!isdigit((unsigned char) str[count])) { token[t_num].start_index += count; int_error(t_num, "expecting exponent"); } while (isdigit((unsigned char) str[++count])); } if (token[t_num].l_val.type == INTGR) { long long lval; errno = 0; lval = strtoll(str, &endptr, 0); if (!errno) { count = endptr - str; /* Linux and Windows implementations of POSIX function strtoll() differ.*/ /* I don't know which is "correct" but returning 0 causes an infinite */ /* loop on input "0x" as the scanner fails to progress. */ if (count == 0) count++; if ((token[t_num].l_val.v.int_val = lval) == lval) return(count); if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { if ((long long unsigned int)lval == (long long unsigned int)token[t_num].l_val.v.int_val) return(count); } } int_warn(t_num, "integer overflow; changing to floating point"); token[t_num].l_val.type = CMPLX; /* Fall through */ } token[t_num].l_val.v.cmplx_val.imag = 0.0; token[t_num].l_val.v.cmplx_val.real = strtod(str, &endptr); count = endptr - str; return (count); }
static int get_num(char str[]) { int count = 0; token[t_num].is_token = FALSE; token[t_num].l_val.type = INTGR; /* assume unless . or E found */ while (isdigit((unsigned char) str[count])) count++; if (str[count] == '.') { token[t_num].l_val.type = CMPLX; /* swallow up digits until non-digit */ while (isdigit((unsigned char) str[++count])); /* now str[count] is other than a digit */ } if (str[count] == 'e' || str[count] == 'E') { token[t_num].l_val.type = CMPLX; count++; if (str[count] == '-' || str[count] == '+') count++; if (!isdigit((unsigned char) str[count])) { token[t_num].start_index += count; int_error(t_num, "expecting exponent"); } while (isdigit((unsigned char) str[++count])); } if (token[t_num].l_val.type == INTGR) { long long lval; char *endptr; errno = 0; lval = strtoll(str, &endptr, 0); if (!errno) { count = endptr - str; if ((token[t_num].l_val.v.int_val = lval) == lval) return(count); if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { if ((unsigned long)(token[t_num].l_val.v.int_val & 0xffffffff) == lval) return(count); } } int_warn(t_num, "integer overflow; changing to floating point"); token[t_num].l_val.type = CMPLX; /* Fall through */ } token[t_num].l_val.v.cmplx_val.imag = 0.0; token[t_num].l_val.v.cmplx_val.real = atof(str); return (count); }
/* expand tilde in path * path cannot be a static array! * tilde must be the first character in *pathp; * we may change that later */ void gp_expand_tilde(char **pathp) { if (!*pathp) int_error(NO_CARET, "Cannot expand empty path"); if ((*pathp)[0] == '~' && (*pathp)[1] == DIRSEP1) { if (user_homedir) { size_t n = strlen(*pathp); *pathp = gp_realloc(*pathp, n + strlen(user_homedir), "tilde expansion"); /* include null at the end ... */ memmove(*pathp + strlen(user_homedir) - 1, *pathp, n + 1); memcpy(*pathp, user_homedir, strlen(user_homedir)); } else int_warn(NO_CARET, "HOME not set - cannot expand tilde"); } }
/* FIXME HH 20020915: This function does nothing if dirent.h and windows.h * not available. */ TBOOLEAN existdir(const char *name) { #if defined(HAVE_DIRENT_H ) || defined(_WIN32) DIR *dp; if ((dp = opendir(name)) == NULL) return FALSE; closedir(dp); return TRUE; #elif defined(VMS) return FALSE; #else int_warn(NO_CARET, "Test on directory existence not supported\n\t('%s!')", name); return FALSE; #endif }
void arrow_use_properties(struct arrow_style_type *arrow, int tag) { /* This function looks for an arrowstyle defined by 'tag' and * copies its data into the structure 'ap'. */ struct arrowstyle_def *this; this = first_arrowstyle; while (this != NULL) { if (this->tag == tag) { *arrow = this->arrow_properties; return; } else { this = this->next; } } /* tag not found: */ default_arrow_style(arrow); int_warn(NO_CARET,"arrowstyle %d not found", tag); }
/* * Binned histogram of input values. * * plot FOO using N:(1) bins{=<nbins>} {binrange=[binlow:binhigh]} * {binwidth=<width>} with boxes * * This option is EXPERIMENTAL, details may change before inclusion in a stable * gnuplot release. * * If no binrange is given, binlow and binhigh are taken from the x range of the data. * In either of these cases binlow is the midpoint x-coordinate of the first bin * and binhigh is the midpoint x-coordinate of the last bin. * Points that lie exactly on a bin boundary are assigned to the upper bin. * Bin assignments are not affected by "set xrange". * Notes: * binwidth = (binhigh-binlow) / (nbins-1) * xmin = binlow - binwidth/2 * xmax = binhigh + binwidth/2 * first bin holds points with (xmin =< x < xmin + binwidth) * last bin holds points with (xmax-binwidth =< x < binhigh + binwidth) */ void make_bins(struct curve_points *plot, int nbins, double binlow, double binhigh, double binwidth) { int i, binno; double *bin; double bottom, top, range; struct axis *xaxis = &axis_array[plot->x_axis]; struct axis *yaxis = &axis_array[plot->y_axis]; double ymax = 0; int N = plot->p_count; /* Find the range of points to be binned */ if (binlow != binhigh) { /* Explicit binrange [min:max] in the plot command */ bottom = binlow; top = binhigh; } else { /* Take binrange from the data itself */ bottom = VERYLARGE; top = -VERYLARGE; for (i=0; i<N; i++) { if (bottom > plot->points[i].x) bottom = plot->points[i].x; if (top < plot->points[i].x) top = plot->points[i].x; } if (top <= bottom) int_warn(NO_CARET, "invalid bin range [%g:%g]", bottom, top); } /* If a fixed binwidth was provided, find total number of bins */ if (binwidth > 0) { double temp; nbins = 1 + (top - bottom) / binwidth; temp = nbins * binwidth - (top - bottom); bottom -= temp/2.; top += temp/2.; } /* otherwise we use (N-1) intervals between midpoints of bin 1 and bin N */ else { binwidth = (top - bottom) / (nbins - 1); bottom -= binwidth/2.; top += binwidth/2.; } range = top - bottom; FPRINTF((stderr,"make_bins: %d bins from %g to %g, binwidth %g\n", nbins, bottom, top, binwidth)); bin = gp_alloc(nbins*sizeof(double), "bins"); for (i=0; i<nbins; i++) bin[i] = 0; for (i=0; i<N; i++) { if (plot->points[i].type == UNDEFINED) continue; binno = floor(nbins * (plot->points[i].x - bottom) / range); if (0 <= binno && binno < nbins) bin[binno] += plot->points[i].y; } if (xaxis->autoscale & AUTOSCALE_MIN) { if (xaxis->min > bottom) xaxis->min = bottom; } if (xaxis->autoscale & AUTOSCALE_MAX) { if (xaxis->max < top) xaxis->max = top; } /* Replace the original data with one entry per bin. * new x = midpoint of bin * new y = number of points in the bin */ plot->p_count = nbins; plot->points = gp_realloc( plot->points, nbins * sizeof(struct coordinate), "curve_points"); for (i=0; i<nbins; i++) { double bincent = bottom + (0.5 + (double)i) * binwidth; plot->points[i].type = INRANGE; plot->points[i].x = bincent; plot->points[i].xlow = bincent - binwidth/2.; plot->points[i].xhigh = bincent + binwidth/2.; plot->points[i].y = bin[i]; plot->points[i].ylow = plot->points[i].y; plot->points[i].yhigh = plot->points[i].y; plot->points[i].z = 0; /* FIXME: leave it alone? */ if (inrange(bincent, xaxis->min, xaxis->max)) { if (ymax < bin[i]) ymax = bin[i]; } else { plot->points[i].type = OUTRANGE; } FPRINTF((stderr, "bin[%d] %g %g\n", i, plot->points[i].x, plot->points[i].y)); } if (yaxis->autoscale & AUTOSCALE_MIN) { if (yaxis->min > 0) yaxis->min = 0; } if (yaxis->autoscale & AUTOSCALE_MAX) { if (yaxis->max < ymax) yaxis->max = ymax; } /* Clean up */ free(bin); }
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); }
/* * allow_ls controls whether we are allowed to accept linestyle in * the current context [ie not when doing a set linestyle command] * allow_point is whether we accept a point command * allow any order of options - pm 24.11.2001 * EAM Oct 2005 - Require that default values have been placed in lp by the caller */ void lp_parse(struct lp_style_type *lp, TBOOLEAN allow_ls, TBOOLEAN allow_point) { /* avoid duplicating options */ int set_lt = 0, set_pal = 0, set_lw = 0, set_pt = 0, set_ps = 0; if (allow_ls && (almost_equals(c_token, "lines$tyle") || equals(c_token, "ls"))) { c_token++; lp_use_properties(lp, int_expression()); } while (!END_OF_COMMAND) { if (almost_equals(c_token, "linet$ype") || equals(c_token, "lt")) { if (set_lt++) break; c_token++; if (almost_equals(c_token, "rgb$color")) { if (set_pal++) break; c_token--; parse_colorspec(&lp->pm3d_color, TC_RGB); lp->use_palette = 1; } else /* both syntaxes allowed: 'with lt pal' as well as 'with pal' */ if (almost_equals(c_token, "pal$ette")) { if (set_pal++) break; c_token--; parse_colorspec(&lp->pm3d_color, TC_Z); lp->use_palette = 1; #ifdef KEYWORD_BGND } else if (equals(c_token,"bgnd")) { lp->l_type = LT_BACKGROUND; c_token++; #endif } else { int lt = int_expression(); lp->l_type = lt - 1; /* user may prefer explicit line styles */ if (prefer_line_styles && allow_ls) lp_use_properties(lp, lt); } } /* linetype, lt */ /* both syntaxes allowed: 'with lt pal' as well as 'with pal' */ if (almost_equals(c_token, "pal$ette")) { if (set_pal++) break; c_token--; parse_colorspec(&lp->pm3d_color, TC_Z); lp->use_palette = 1; continue; } if (equals(c_token,"lc") || almost_equals(c_token,"linec$olor")) { lp->use_palette = 1; if (set_pal++) break; c_token++; if (almost_equals(c_token, "rgb$color")) { c_token--; parse_colorspec(&lp->pm3d_color, TC_RGB); } else if (almost_equals(c_token, "pal$ette")) { c_token--; parse_colorspec(&lp->pm3d_color, TC_Z); #ifdef KEYWORD_BGND } else if (equals(c_token,"bgnd")) { lp->pm3d_color.type = TC_LT; lp->pm3d_color.lt = LT_BACKGROUND; c_token++; #endif } else if (almost_equals(c_token, "var$iable")) { c_token++; lp->l_type = LT_COLORFROMCOLUMN; lp->pm3d_color.type = TC_LINESTYLE; } else { lp->pm3d_color.type = TC_LT; lp->pm3d_color.lt = int_expression() - 1; } continue; } if (almost_equals(c_token, "linew$idth") || equals(c_token, "lw")) { if (set_lw++) break; c_token++; lp->l_width = real_expression(); if (lp->l_width < 0) lp->l_width = 0; continue; } if (equals(c_token,"bgnd")) { lp->l_type = LT_BACKGROUND; lp->use_palette = 0; c_token++; continue; } if (almost_equals(c_token, "pointt$ype") || equals(c_token, "pt")) { if (allow_point) { if (set_pt++) break; c_token++; lp->p_type = int_expression() - 1; } else { int_warn(c_token, "No pointtype specifier allowed, here"); c_token += 2; } continue; } if (almost_equals(c_token, "points$ize") || equals(c_token, "ps")) { if (allow_point) { if (set_ps++) break; c_token++; if (almost_equals(c_token, "var$iable")) { lp->p_size = PTSZ_VARIABLE; c_token++; } else if (almost_equals(c_token, "def$ault")) { lp->p_size = PTSZ_DEFAULT; c_token++; } else { lp->p_size = real_expression(); if (lp->p_size < 0) lp->p_size = 0; } } else { int_warn(c_token, "No pointsize specifier allowed, here"); c_token += 2; } continue; } if (almost_equals(c_token, "pointi$nterval") || equals(c_token, "pi")) { c_token++; if (allow_point) { lp->p_interval = int_expression(); } else { int_warn(c_token, "No pointinterval specifier allowed, here"); int_expression(); } continue; } /* unknown option catched -> quit the while(1) loop */ break; } if (set_lt > 1 || set_pal > 1 || set_lw > 1 || set_pt > 1 || set_ps > 1) int_error(c_token, "duplicated arguments in style specification"); }
/* * Parse the sub-options of text color specification * { def$ault | lt <linetype> | pal$ette { cb <val> | frac$tion <val> | z } * The ordering of alternatives shown in the line above is kept in the symbol definitions * TC_DEFAULT TC_LT TC_RGB TC_CB TC_FRAC TC_Z (0 1 2 3 4 5) * and the "options" parameter to parse_colorspec limits legal input to the * corresponding point in the series. So TC_LT allows only default or linetype * coloring, while TC_Z allows all coloring options up to and including pal z */ void parse_colorspec(struct t_colorspec *tc, int options) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expected colorspec"); if (almost_equals(c_token,"def$ault")) { c_token++; tc->type = TC_DEFAULT; #ifdef KEYWORD_BGND } else if (equals(c_token,"bgnd")) { c_token++; tc->type = TC_LT; tc->lt = LT_BACKGROUND; #endif } else if (equals(c_token,"lt")) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expected linetype"); tc->type = TC_LT; tc->lt = int_expression()-1; if (tc->lt < LT_BACKGROUND) { tc->type = TC_DEFAULT; int_warn(c_token,"illegal linetype"); } } else if (options <= TC_LT) { tc->type = TC_DEFAULT; int_error(c_token, "only tc lt <n> possible here"); } else if (equals(c_token,"ls") || almost_equals(c_token,"lines$tyle")) { c_token++; tc->type = TC_LINESTYLE; tc->lt = real_expression(); } else if (almost_equals(c_token,"rgb$color")) { char *color; int rgbtriple; c_token++; tc->type = TC_RGB; if (almost_equals(c_token, "var$iable")) { tc->value = -1.0; c_token++; return; } else tc->value = 0.0; if (!(color = try_to_get_string())) int_error(c_token, "expected a color name or a string of form \"#RRGGBB\""); if ((rgbtriple = lookup_table_nth(pm3d_color_names_tbl, color)) >= 0) rgbtriple = pm3d_color_names_tbl[rgbtriple].value; else sscanf(color,"#%x",&rgbtriple); free(color); if (rgbtriple < 0) int_error(c_token, "expected a known color name or a string of form \"#RRGGBB\""); tc->type = TC_RGB; tc->lt = rgbtriple; } else if (almost_equals(c_token,"pal$ette")) { c_token++; if (equals(c_token,"z")) { /* The actual z value is not yet known, fill it in later */ if (options >= TC_Z) { tc->type = TC_Z; } else { tc->type = TC_DEFAULT; int_error(c_token, "palette z not possible here"); } c_token++; } else if (equals(c_token,"cb")) { tc->type = TC_CB; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected cb value"); tc->value = real_expression(); } else if (almost_equals(c_token,"frac$tion")) { tc->type = TC_FRAC; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected palette fraction"); tc->value = real_expression(); if (tc->value < 0. || tc->value > 1.0) int_error(c_token, "palette fraction out of range"); } else { /* END_OF_COMMAND or palette <blank> */ if (options >= TC_Z) tc->type = TC_Z; } } else { int_error(c_token, "colorspec option not recognized"); } }
/******** The 'unset' command ********/ void unset_command() { int found_token; int save_token; int i; c_token++; set_iterator = check_for_iteration(); found_token = lookup_table(&set_tbl[0],c_token); /* HBB 20000506: rationalize occurences of c_token++ ... */ if (found_token != S_INVALID) c_token++; save_token = c_token; ITERATE: switch(found_token) { case S_ANGLES: unset_angles(); break; case S_ARROW: unset_arrow(); break; case S_AUTOSCALE: unset_autoscale(); break; case S_BARS: unset_bars(); break; case S_BORDER: unset_border(); break; case S_BOXWIDTH: unset_boxwidth(); break; case S_CLIP: unset_clip(); break; case S_CNTRPARAM: unset_cntrparam(); break; case S_CNTRLABEL: unset_cntrlabel(); break; case S_CLABEL: /* deprecated command */ clabel_onecolor = TRUE; break; case S_CONTOUR: unset_contour(); break; case S_DASHTYPE: unset_dashtype(); break; case S_DGRID3D: unset_dgrid3d(); break; case S_DUMMY: unset_dummy(); break; case S_ENCODING: unset_encoding(); break; case S_DECIMALSIGN: unset_decimalsign(); break; case S_FIT: unset_fit(); break; case S_FORMAT: c_token--; set_format(); break; case S_GRID: unset_grid(); break; case S_HIDDEN3D: unset_hidden3d(); break; case S_HISTORY: break; /* FIXME: reset to default values? */ case S_HISTORYSIZE: /* Deprecated */ unset_historysize(); break; case S_ISOSAMPLES: unset_isosamples(); break; case S_KEY: unset_key(); break; case S_LABEL: unset_label(); break; case S_LINETYPE: unset_linetype(); break; case S_LINK: c_token--; link_command(); break; case S_LOADPATH: unset_loadpath(); break; case S_LOCALE: unset_locale(); break; case S_LOGSCALE: unset_logscale(); break; case S_MACROS: /* Aug 2013 - macros are always enabled */ break; case S_MAPPING: unset_mapping(); break; case S_BMARGIN: unset_margin(&bmargin); break; case S_LMARGIN: unset_margin(&lmargin); break; case S_RMARGIN: unset_margin(&rmargin); break; case S_TMARGIN: unset_margin(&tmargin); break; case S_DATAFILE: if (almost_equals(c_token,"fort$ran")) { df_fortran_constants = FALSE; c_token++; break; } else if (almost_equals(c_token,"miss$ing")) { unset_missing(); c_token++; break; } else if (almost_equals(c_token,"sep$arators")) { free(df_separators); df_separators = NULL; c_token++; break; } else if (almost_equals(c_token,"com$mentschars")) { free(df_commentschars); df_commentschars = gp_strdup(DEFAULT_COMMENTS_CHARS); c_token++; break; } else if (almost_equals(c_token,"bin$ary")) { df_unset_datafile_binary(); c_token++; break; } else if (almost_equals(c_token,"nofpe_trap")) { df_nofpe_trap = FALSE; c_token++; break; } df_fortran_constants = FALSE; unset_missing(); free(df_separators); df_separators = NULL; free(df_commentschars); df_commentschars = gp_strdup(DEFAULT_COMMENTS_CHARS); df_unset_datafile_binary(); break; #ifdef USE_MOUSE case S_MOUSE: unset_mouse(); break; #endif case S_MULTIPLOT: term_end_multiplot(); break; case S_OFFSETS: unset_offsets(); break; case S_ORIGIN: unset_origin(); break; case SET_OUTPUT: unset_output(); break; case S_PARAMETRIC: unset_parametric(); break; case S_PM3D: unset_pm3d(); break; case S_PALETTE: unset_palette(); break; case S_COLORBOX: unset_colorbox(); break; case S_POINTINTERVALBOX: unset_pointintervalbox(); break; case S_POINTSIZE: unset_pointsize(); break; case S_POLAR: unset_polar(); break; case S_PRINT: unset_print(); break; case S_PSDIR: unset_psdir(); break; #ifdef EAM_OBJECTS case S_OBJECT: unset_object(); break; #endif case S_RTICS: unset_tics(POLAR_AXIS); break; case S_PAXIS: i = int_expression(); if (i <= 0 || i > MAX_PARALLEL_AXES) int_error(c_token, "expecting parallel axis number"); if (almost_equals(c_token, "tic$s")) { unset_tics(PARALLEL_AXES+i-1); c_token++; } break; case S_SAMPLES: unset_samples(); break; case S_SIZE: unset_size(); break; case S_STYLE: unset_style(); break; case S_SURFACE: unset_surface(); break; case S_TABLE: unset_table(); break; case S_TERMINAL: unset_terminal(); break; case S_TICS: unset_tics(ALL_AXES); break; case S_TICSCALE: int_warn(c_token, "Deprecated syntax - use 'set tics scale default'"); break; case S_TICSLEVEL: case S_XYPLANE: unset_ticslevel(); break; case S_TIMEFMT: unset_timefmt(); break; case S_TIMESTAMP: unset_timestamp(); break; case S_TITLE: unset_axislabel_or_title(&title); break; case S_VIEW: unset_view(); break; case S_ZERO: unset_zero(); break; /* FIXME - are the tics correct? */ case S_MXTICS: unset_minitics(FIRST_X_AXIS); break; case S_XTICS: unset_tics(FIRST_X_AXIS); break; case S_XDTICS: case S_XMTICS: unset_month_day_tics(FIRST_X_AXIS); break; case S_MYTICS: unset_minitics(FIRST_Y_AXIS); break; case S_YTICS: unset_tics(FIRST_Y_AXIS); break; case S_YDTICS: case S_YMTICS: unset_month_day_tics(FIRST_X_AXIS); break; case S_MX2TICS: unset_minitics(SECOND_X_AXIS); break; case S_X2TICS: unset_tics(SECOND_X_AXIS); break; case S_X2DTICS: case S_X2MTICS: unset_month_day_tics(FIRST_X_AXIS); break; case S_MY2TICS: unset_minitics(SECOND_Y_AXIS); break; case S_Y2TICS: unset_tics(SECOND_Y_AXIS); break; case S_Y2DTICS: case S_Y2MTICS: unset_month_day_tics(FIRST_X_AXIS); break; case S_MZTICS: unset_minitics(FIRST_Z_AXIS); break; case S_ZTICS: unset_tics(FIRST_Z_AXIS); break; case S_ZDTICS: case S_ZMTICS: unset_month_day_tics(FIRST_X_AXIS); break; case S_MCBTICS: unset_minitics(COLOR_AXIS); break; case S_CBTICS: unset_tics(COLOR_AXIS); break; case S_CBDTICS: case S_CBMTICS: unset_month_day_tics(FIRST_X_AXIS); break; case S_MRTICS: unset_minitics(POLAR_AXIS); break; case S_XDATA: unset_timedata(FIRST_X_AXIS); break; case S_YDATA: unset_timedata(FIRST_Y_AXIS); break; case S_ZDATA: unset_timedata(FIRST_Z_AXIS); break; case S_CBDATA: unset_timedata(COLOR_AXIS); break; case S_X2DATA: unset_timedata(SECOND_X_AXIS); break; case S_Y2DATA: unset_timedata(SECOND_Y_AXIS); break; case S_XLABEL: unset_axislabel(FIRST_X_AXIS); break; case S_YLABEL: unset_axislabel(FIRST_Y_AXIS); break; case S_ZLABEL: unset_axislabel(FIRST_Z_AXIS); break; case S_CBLABEL: unset_axislabel(COLOR_AXIS); break; case S_X2LABEL: unset_axislabel(SECOND_X_AXIS); break; case S_Y2LABEL: unset_axislabel(SECOND_Y_AXIS); break; case S_XRANGE: unset_range(FIRST_X_AXIS); break; case S_X2RANGE: unset_range(SECOND_X_AXIS); break; case S_YRANGE: unset_range(FIRST_Y_AXIS); break; case S_Y2RANGE: unset_range(SECOND_Y_AXIS); break; case S_ZRANGE: unset_range(FIRST_Z_AXIS); break; case S_CBRANGE: unset_range(COLOR_AXIS); break; case S_RRANGE: unset_range(POLAR_AXIS); break; case S_TRANGE: unset_range(T_AXIS); break; case S_URANGE: unset_range(U_AXIS); break; case S_VRANGE: unset_range(V_AXIS); break; case S_RAXIS: raxis = FALSE; c_token++; break; case S_XZEROAXIS: unset_zeroaxis(FIRST_X_AXIS); break; case S_YZEROAXIS: unset_zeroaxis(FIRST_Y_AXIS); break; case S_ZZEROAXIS: unset_zeroaxis(FIRST_Z_AXIS); break; case S_X2ZEROAXIS: unset_zeroaxis(SECOND_X_AXIS); break; case S_Y2ZEROAXIS: unset_zeroaxis(SECOND_Y_AXIS); break; case S_ZEROAXIS: unset_all_zeroaxes(); break; case S_INVALID: default: int_error(c_token, "Unrecognized option. See 'help unset'."); break; } if (next_iteration(set_iterator)) { c_token = save_token; goto ITERATE; } update_gpval_variables(0); set_iterator = cleanup_iteration(set_iterator); }
/* * Parse the sub-options of text color specification * { def$ault | lt <linetype> | pal$ette { cb <val> | frac$tion <val> | z } * The ordering of alternatives shown in the line above is kept in the symbol definitions * TC_DEFAULT TC_LT TC_LINESTYLE TC_RGB TC_CB TC_FRAC TC_Z TC_VARIABLE (0 1 2 3 4 5 6 7) * and the "options" parameter to parse_colorspec limits legal input to the * corresponding point in the series. So TC_LT allows only default or linetype * coloring, while TC_Z allows all coloring options up to and including pal z */ void parse_colorspec(struct t_colorspec *tc, int options) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expected colorspec"); if (almost_equals(c_token,"def$ault")) { c_token++; tc->type = TC_DEFAULT; } else if (equals(c_token,"bgnd")) { c_token++; tc->type = TC_LT; tc->lt = LT_BACKGROUND; } else if (equals(c_token,"black")) { c_token++; tc->type = TC_LT; tc->lt = LT_BLACK; } else if (equals(c_token,"lt")) { struct lp_style_type lptemp; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected linetype"); tc->type = TC_LT; tc->lt = int_expression()-1; if (tc->lt < LT_BACKGROUND) { tc->type = TC_DEFAULT; int_warn(c_token,"illegal linetype"); } /* * July 2014 - translate linetype into user-defined linetype color. * This is a CHANGE! * FIXME: calling load_linetype here may obviate the need to call it * many places in the higher level code. They could be removed. */ load_linetype(&lptemp, tc->lt + 1); *tc = lptemp.pm3d_color; } else if (options <= TC_LT) { tc->type = TC_DEFAULT; int_error(c_token, "only tc lt <n> possible here"); } else if (equals(c_token,"ls") || almost_equals(c_token,"lines$tyle")) { c_token++; tc->type = TC_LINESTYLE; tc->lt = real_expression(); } else if (almost_equals(c_token,"rgb$color")) { c_token++; tc->type = TC_RGB; if (almost_equals(c_token, "var$iable")) { tc->value = -1.0; c_token++; } else { tc->value = 0.0; tc->lt = parse_color_name(); } } else if (almost_equals(c_token,"pal$ette")) { c_token++; if (equals(c_token,"z")) { /* The actual z value is not yet known, fill it in later */ if (options >= TC_Z) { tc->type = TC_Z; } else { tc->type = TC_DEFAULT; int_error(c_token, "palette z not possible here"); } c_token++; } else if (equals(c_token,"cb")) { tc->type = TC_CB; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected cb value"); tc->value = real_expression(); } else if (almost_equals(c_token,"frac$tion")) { tc->type = TC_FRAC; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected palette fraction"); tc->value = real_expression(); if (tc->value < 0. || tc->value > 1.0) int_error(c_token, "palette fraction out of range"); } else { /* END_OF_COMMAND or palette <blank> */ if (options >= TC_Z) tc->type = TC_Z; } } else if (options >= TC_VARIABLE && almost_equals(c_token,"var$iable")) { tc->type = TC_VARIABLE; c_token++; /* New: allow to skip the rgb keyword, as in 'plot $foo lc "blue"' */ } else if (isstring(c_token)) { tc->type = TC_RGB; tc->lt = parse_color_name(); } else { int_error(c_token, "colorspec option not recognized"); } }
void multiplot_start() { TBOOLEAN set_spacing = FALSE; TBOOLEAN set_margins = FALSE; c_token++; /* Only a few options are possible if we are already in multiplot mode */ /* So far we have "next". Maybe also "previous", "clear"? */ if (multiplot) { if (equals(c_token, "next")) { c_token++; if (!mp_layout.auto_layout) int_error(c_token, "only valid inside an auto-layout multiplot"); multiplot_next(); return; } else if (almost_equals(c_token, "prev$ious")) { c_token++; if (!mp_layout.auto_layout) int_error(c_token, "only valid inside an auto-layout multiplot"); multiplot_previous(); return; } else { term_end_multiplot(); } } /* FIXME: more options should be reset/initialized each time */ mp_layout.auto_layout = FALSE; mp_layout.auto_layout_margins = FALSE; mp_layout.current_panel = 0; mp_layout.title.noenhanced = FALSE; free(mp_layout.title.text); mp_layout.title.text = NULL; free(mp_layout.title.font); mp_layout.title.font = NULL; /* Parse options */ while (!END_OF_COMMAND) { if (almost_equals(c_token, "ti$tle")) { c_token++; mp_layout.title.text = try_to_get_string(); continue; } if (equals(c_token, "font")) { c_token++; mp_layout.title.font = try_to_get_string(); continue; } if (almost_equals(c_token,"enh$anced")) { mp_layout.title.noenhanced = FALSE; c_token++; continue; } if (almost_equals(c_token,"noenh$anced")) { mp_layout.title.noenhanced = TRUE; c_token++; continue; } if (almost_equals(c_token, "lay$out")) { if (mp_layout.auto_layout) int_error(c_token, "too many layout commands"); else mp_layout.auto_layout = TRUE; c_token++; if (END_OF_COMMAND) { int_error(c_token,"expecting '<num_cols>,<num_rows>'"); } /* read row,col */ mp_layout.num_rows = int_expression(); if (END_OF_COMMAND || !equals(c_token,",") ) int_error(c_token, "expecting ', <num_cols>'"); c_token++; if (END_OF_COMMAND) int_error(c_token, "expecting <num_cols>"); mp_layout.num_cols = int_expression(); /* remember current values of the plot size and the margins */ mp_layout.prev_xsize = xsize; mp_layout.prev_ysize = ysize; mp_layout.prev_xoffset = xoffset; mp_layout.prev_yoffset = yoffset; mp_layout.prev_lmargin = lmargin; mp_layout.prev_rmargin = rmargin; mp_layout.prev_bmargin = bmargin; mp_layout.prev_tmargin = tmargin; mp_layout.act_row = 0; mp_layout.act_col = 0; continue; } /* The remaining options are only valid for auto-layout mode */ if (!mp_layout.auto_layout) int_error(c_token, "only valid in the context of an auto-layout command"); switch(lookup_table(&set_multiplot_tbl[0],c_token)) { case S_MULTIPLOT_COLUMNSFIRST: mp_layout.row_major = TRUE; c_token++; break; case S_MULTIPLOT_ROWSFIRST: mp_layout.row_major = FALSE; c_token++; break; case S_MULTIPLOT_DOWNWARDS: mp_layout.downwards = TRUE; c_token++; break; case S_MULTIPLOT_UPWARDS: mp_layout.downwards = FALSE; c_token++; break; case S_MULTIPLOT_SCALE: c_token++; mp_layout.xscale = real_expression(); mp_layout.yscale = mp_layout.xscale; if (!END_OF_COMMAND && equals(c_token,",") ) { c_token++; if (END_OF_COMMAND) { int_error(c_token, "expecting <yscale>"); } mp_layout.yscale = real_expression(); } break; case S_MULTIPLOT_OFFSET: c_token++; mp_layout.xoffset = real_expression(); mp_layout.yoffset = mp_layout.xoffset; if (!END_OF_COMMAND && equals(c_token,",") ) { c_token++; if (END_OF_COMMAND) { int_error(c_token, "expecting <yoffset>"); } mp_layout.yoffset = real_expression(); } break; case S_MULTIPLOT_MARGINS: c_token++; if (END_OF_COMMAND) int_error(c_token,"expecting '<left>,<right>,<bottom>,<top>'"); mp_layout.lmargin.scalex = screen; mp_layout_set_margin_or_spacing(&(mp_layout.lmargin)); if (!END_OF_COMMAND && equals(c_token,",") ) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expecting <right>"); mp_layout.rmargin.scalex = mp_layout.lmargin.scalex; mp_layout_set_margin_or_spacing(&(mp_layout.rmargin)); } else { int_error(c_token, "expecting <right>"); } if (!END_OF_COMMAND && equals(c_token,",") ) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expecting <top>"); mp_layout.bmargin.scalex = mp_layout.rmargin.scalex; mp_layout_set_margin_or_spacing(&(mp_layout.bmargin)); } else { int_error(c_token, "expecting <bottom>"); } if (!END_OF_COMMAND && equals(c_token,",") ) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expecting <bottom>"); mp_layout.tmargin.scalex = mp_layout.bmargin.scalex; mp_layout_set_margin_or_spacing(&(mp_layout.tmargin)); } else { int_error(c_token, "expection <top>"); } set_margins = TRUE; break; case S_MULTIPLOT_SPACING: c_token++; if (END_OF_COMMAND) int_error(c_token,"expecting '<xspacing>,<yspacing>'"); mp_layout.xspacing.scalex = screen; mp_layout_set_margin_or_spacing(&(mp_layout.xspacing)); mp_layout.yspacing = mp_layout.xspacing; if (!END_OF_COMMAND && equals(c_token, ",")) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expecting <yspacing>"); mp_layout_set_margin_or_spacing(&(mp_layout.yspacing)); } set_spacing = TRUE; break; default: int_error(c_token,"invalid or duplicate option"); break; } } if (set_spacing || set_margins) { if (set_spacing && set_margins) { if (mp_layout.lmargin.x >= 0 && mp_layout.rmargin.x >= 0 && mp_layout.tmargin.x >= 0 && mp_layout.bmargin.x >= 0 && mp_layout.xspacing.x >= 0 && mp_layout.yspacing.x >= 0) mp_layout.auto_layout_margins = TRUE; else int_error(NO_CARET, "must give positive margin and spacing values"); } else if (set_spacing) { int_warn(NO_CARET, "must give margins and spacing, continue with auto margins."); } else if (set_margins) { mp_layout.auto_layout_margins = TRUE; mp_layout.xspacing.scalex = screen; mp_layout.xspacing.x = 0.05; mp_layout.yspacing.scalex = screen; mp_layout.yspacing.x = 0.05; int_warn(NO_CARET, "must give margins and spacing, continue with spacing of 0.05"); } /* Sanity check that screen tmargin is > screen bmargin */ if (mp_layout.bmargin.scalex == screen && mp_layout.tmargin.scalex == screen) if (mp_layout.bmargin.x > mp_layout.tmargin.x) { double tmp = mp_layout.bmargin.x; mp_layout.bmargin.x = mp_layout.tmargin.x; mp_layout.tmargin.x = tmp; } } /* If we reach here, then the command has been successfully parsed. * Aug 2013: call term_start_plot() before setting multiplot so that * the wxt and qt terminals will reset the plot count to 0 before * ignoring subsequent TERM_LAYER_RESET requests. */ term_start_plot(); multiplot = TRUE; fill_gpval_integer("GPVAL_MULTIPLOT", 1); /* Place overall title before doing anything else */ if (mp_layout.title.text) { double tmpx, tmpy; unsigned int x, y; char *p = mp_layout.title.text; map_position_r(&(mp_layout.title.offset), &tmpx, &tmpy, "mp title"); x = term->xmax / 2 + tmpx; y = term->ymax - term->v_char + tmpy;; ignore_enhanced(mp_layout.title.noenhanced); apply_pm3dcolor(&(mp_layout.title.textcolor)); write_multiline(x, y, mp_layout.title.text, CENTRE, JUST_TOP, 0, mp_layout.title.font); reset_textcolor(&(mp_layout.title.textcolor)); ignore_enhanced(FALSE); /* Calculate fractional height of title compared to entire page */ /* If it would fill the whole page, forget it! */ for (y=1; *p; p++) if (*p == '\n') y++; /* Oct 2012 - v_char depends on the font used */ if (mp_layout.title.font && *mp_layout.title.font) term->set_font(mp_layout.title.font); mp_layout.title_height = (double)(y * term->v_char) / (double)term->ymax; if (mp_layout.title.font && *mp_layout.title.font) term->set_font(""); if (mp_layout.title_height > 0.9) mp_layout.title_height = 0.05; } else { mp_layout.title_height = 0.0; } if (mp_layout.auto_layout_margins) mp_layout_margins_and_spacing(); else mp_layout_size_and_offset(); }
/* * allow_ls controls whether we are allowed to accept linestyle in * the current context [ie not when doing a set linestyle command] * allow_point is whether we accept a point command */ int lp_parse(struct lp_style_type *lp, TBOOLEAN allow_ls, TBOOLEAN allow_point) { /* keep track of which options were set during this call */ int set_lt = 0, set_pal = 0, set_lw = 0, set_pt = 0, set_ps = 0, set_pi = 0; int new_lt = 0; /* EAM Mar 2010 - We don't want properties from a user-defined default * linetype to override properties explicitly set here. So fill in a * local lp_style_type as we go and then copy over the specifically * requested properties on top of the default ones. */ struct lp_style_type newlp = *lp; if (allow_ls && (almost_equals(c_token, "lines$tyle") || equals(c_token, "ls"))) { c_token++; lp_use_properties(lp, int_expression()); } while (!END_OF_COMMAND) { if (almost_equals(c_token, "linet$ype") || equals(c_token, "lt")) { if (set_lt++) break; c_token++; if (almost_equals(c_token, "rgb$color")) { if (set_pal++) break; c_token--; parse_colorspec(&(newlp.pm3d_color), TC_RGB); newlp.use_palette = 1; } else /* both syntaxes allowed: 'with lt pal' as well as 'with pal' */ if (almost_equals(c_token, "pal$ette")) { if (set_pal++) break; c_token--; parse_colorspec(&(newlp.pm3d_color), TC_Z); newlp.use_palette = 1; } else if (equals(c_token,"bgnd")) { *lp = background_lp; c_token++; } else { /* These replace the base style */ new_lt = int_expression(); lp->l_type = new_lt - 1; /* user may prefer explicit line styles */ if (prefer_line_styles && allow_ls) lp_use_properties(lp, new_lt); else load_linetype(lp, new_lt); } } /* linetype, lt */ /* both syntaxes allowed: 'with lt pal' as well as 'with pal' */ if (almost_equals(c_token, "pal$ette")) { if (set_pal++) break; c_token--; parse_colorspec(&(newlp.pm3d_color), TC_Z); newlp.use_palette = 1; continue; } if (equals(c_token,"lc") || almost_equals(c_token,"linec$olor") || equals(c_token,"fc") || almost_equals(c_token,"fillc$olor")) { newlp.use_palette = 1; if (set_pal++) break; c_token++; if (almost_equals(c_token, "rgb$color")) { c_token--; parse_colorspec(&(newlp.pm3d_color), TC_RGB); } else if (almost_equals(c_token, "pal$ette")) { c_token--; parse_colorspec(&(newlp.pm3d_color), TC_Z); } else if (equals(c_token,"bgnd")) { newlp.pm3d_color.type = TC_LT; newlp.pm3d_color.lt = LT_BACKGROUND; c_token++; } else if (almost_equals(c_token, "var$iable")) { c_token++; newlp.l_type = LT_COLORFROMCOLUMN; newlp.pm3d_color.type = TC_LINESTYLE; } else { /* Pull the line colour from a default linetype, but */ /* only if we are not in the middle of defining one! */ if (allow_ls) { struct lp_style_type temp; load_linetype(&temp, int_expression()); newlp.pm3d_color = temp.pm3d_color; } else { newlp.pm3d_color.type = TC_LT; newlp.pm3d_color.lt = int_expression() - 1; } } continue; } if (almost_equals(c_token, "linew$idth") || equals(c_token, "lw")) { if (set_lw++) break; c_token++; newlp.l_width = real_expression(); if (newlp.l_width < 0) newlp.l_width = 0; continue; } if (equals(c_token,"bgnd")) { if (set_lt++) break;; c_token++; *lp = background_lp; continue; } if (almost_equals(c_token, "pointt$ype") || equals(c_token, "pt")) { if (allow_point) { if (set_pt++) break; c_token++; newlp.p_type = int_expression() - 1; } else { int_warn(c_token, "No pointtype specifier allowed, here"); c_token += 2; } continue; } if (almost_equals(c_token, "points$ize") || equals(c_token, "ps")) { if (allow_point) { if (set_ps++) break; c_token++; if (almost_equals(c_token, "var$iable")) { newlp.p_size = PTSZ_VARIABLE; c_token++; } else if (almost_equals(c_token, "def$ault")) { newlp.p_size = PTSZ_DEFAULT; c_token++; } else { newlp.p_size = real_expression(); if (newlp.p_size < 0) newlp.p_size = 0; } } else { int_warn(c_token, "No pointsize specifier allowed, here"); c_token += 2; } continue; } if (almost_equals(c_token, "pointi$nterval") || equals(c_token, "pi")) { c_token++; if (allow_point) { newlp.p_interval = int_expression(); set_pi = 1; } else { int_warn(c_token, "No pointinterval specifier allowed, here"); int_expression(); } continue; } /* caught unknown option -> quit the while(1) loop */ break; } if (set_lt > 1 || set_pal > 1 || set_lw > 1 || set_pt > 1 || set_ps > 1) int_error(c_token, "duplicated arguments in style specification"); if (set_pal) { lp->pm3d_color = newlp.pm3d_color; lp->use_palette = newlp.use_palette; /* FIXME: This was used by hidden3d, but breaks contour coloring */ /* new_lt = LT_SINGLECOLOR; */ } if (set_lw) lp->l_width = newlp.l_width; if (set_pt) lp->p_type = newlp.p_type; if (set_ps) lp->p_size = newlp.p_size; if (set_pi) lp->p_interval = newlp.p_interval; if (newlp.l_type == LT_COLORFROMCOLUMN) lp->l_type = LT_COLORFROMCOLUMN; return new_lt; }
/* Thanks to John Bollinger <*****@*****.**> who has tested the windows part */ static char * recursivefullname(const char *path, const char *filename, TBOOLEAN recursive) { char *fullname = NULL; FILE *fp; /* length of path, dir separator, filename, \0 */ fullname = gp_alloc(strlen(path) + 1 + strlen(filename) + 1, "recursivefullname"); strcpy(fullname, path); PATH_CONCAT(fullname, filename); if ((fp = fopen(fullname, "r")) != NULL) { fclose(fp); return fullname; } else { free(fullname); fullname = NULL; } if (recursive) { #ifdef HAVE_DIRENT_H DIR *dir; struct dirent *direntry; struct stat buf; dir = opendir(path); if (dir) { while ((direntry = readdir(dir)) != NULL) { char *fulldir = gp_alloc(strlen(path) + 1 + strlen(direntry->d_name) + 1, "fontpath_fullname"); strcpy(fulldir, path); # if defined(VMS) if (fulldir[strlen(fulldir) - 1] == ']') fulldir[strlen(fulldir) - 1] = '\0'; strcpy(&(fulldir[strlen(fulldir)]), "."); strcpy(&(fulldir[strlen(fulldir)]), direntry->d_name); strcpy(&(fulldir[strlen(fulldir)]), "]"); # else PATH_CONCAT(fulldir, direntry->d_name); # endif stat(fulldir, &buf); if ((S_ISDIR(buf.st_mode)) && (strcmp(direntry->d_name, ".") != 0) && (strcmp(direntry->d_name, "..") != 0)) { fullname = recursivefullname(fulldir, filename, TRUE); if (fullname != NULL) break; } free(fulldir); } closedir(dir); } #elif defined(_Windows) HANDLE filehandle; WIN32_FIND_DATA finddata; char *pathwildcard = gp_alloc(strlen(path) + 2, "fontpath_fullname"); strcpy(pathwildcard, path); PATH_CONCAT(pathwildcard, "*"); filehandle = FindFirstFile(pathwildcard, &finddata); free(pathwildcard); if (filehandle != INVALID_HANDLE_VALUE) do { if ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strcmp(finddata.cFileName, ".") != 0) && (strcmp(finddata.cFileName, "..") != 0)) { char *fulldir = gp_alloc(strlen(path) + 1 + strlen(finddata.cFileName) + 1, "fontpath_fullname"); strcpy(fulldir, path); PATH_CONCAT(fulldir, finddata.cFileName); fullname = recursivefullname(fulldir, filename, TRUE); free(fulldir); if (fullname != NULL) break; } } while (FindNextFile(filehandle, &finddata) != 0); FindClose(filehandle); #else int_warn(NO_CARET, "Recursive directory search not supported\n\t('%s!')", path); #endif } return fullname; }
/* * Parse the sub-options of text color specification * { def$ault | lt <linetype> | pal$ette { cb <val> | frac$tion <val> | z } * The ordering of alternatives shown in the line above is kept in the symbol definitions * TC_DEFAULT TC_LT TC_LINESTYLE TC_RGB TC_CB TC_FRAC TC_Z TC_VARIABLE (0 1 2 3 4 5 6 7) * and the "options" parameter to parse_colorspec limits legal input to the * corresponding point in the series. So TC_LT allows only default or linetype * coloring, while TC_Z allows all coloring options up to and including pal z */ void parse_colorspec(struct t_colorspec *tc, int options) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expected colorspec"); if (almost_equals(c_token,"def$ault")) { c_token++; tc->type = TC_DEFAULT; } else if (equals(c_token,"bgnd")) { c_token++; tc->type = TC_LT; tc->lt = LT_BACKGROUND; } else if (equals(c_token,"lt")) { c_token++; if (END_OF_COMMAND) int_error(c_token, "expected linetype"); tc->type = TC_LT; tc->lt = int_expression()-1; if (tc->lt < LT_BACKGROUND) { tc->type = TC_DEFAULT; int_warn(c_token,"illegal linetype"); } } else if (options <= TC_LT) { tc->type = TC_DEFAULT; int_error(c_token, "only tc lt <n> possible here"); } else if (equals(c_token,"ls") || almost_equals(c_token,"lines$tyle")) { c_token++; tc->type = TC_LINESTYLE; tc->lt = real_expression(); } else if (almost_equals(c_token,"rgb$color")) { c_token++; tc->type = TC_RGB; if (almost_equals(c_token, "var$iable")) { tc->value = -1.0; c_token++; } else { tc->value = 0.0; tc->lt = parse_color_name(); } } else if (almost_equals(c_token,"pal$ette")) { c_token++; if (equals(c_token,"z")) { /* The actual z value is not yet known, fill it in later */ if (options >= TC_Z) { tc->type = TC_Z; } else { tc->type = TC_DEFAULT; int_error(c_token, "palette z not possible here"); } c_token++; } else if (equals(c_token,"cb")) { tc->type = TC_CB; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected cb value"); tc->value = real_expression(); } else if (almost_equals(c_token,"frac$tion")) { tc->type = TC_FRAC; c_token++; if (END_OF_COMMAND) int_error(c_token, "expected palette fraction"); tc->value = real_expression(); if (tc->value < 0. || tc->value > 1.0) int_error(c_token, "palette fraction out of range"); } else { /* END_OF_COMMAND or palette <blank> */ if (options >= TC_Z) tc->type = TC_Z; } } else if (options >= TC_VARIABLE && almost_equals(c_token,"var$iable")) { tc->type = TC_VARIABLE; c_token++; } else { int_error(c_token, "colorspec option not recognized"); } }
/* * destination_class tells us whether we are filling in a line style ('set style line'), * a persistant linetype ('set linetype') or an ad hoc set of properties for a single * use ('plot ... lc foo lw baz'). * allow_point controls whether we accept a point attribute in this lp_style. */ int lp_parse(struct lp_style_type *lp, lp_class destination_class, TBOOLEAN allow_point) { /* keep track of which options were set during this call */ int set_lt = 0, set_pal = 0, set_lw = 0; int set_pt = 0, set_ps = 0, set_pi = 0; int set_dt = 0; int new_lt = 0; /* EAM Mar 2010 - We don't want properties from a user-defined default * linetype to override properties explicitly set here. So fill in a * local lp_style_type as we go and then copy over the specifically * requested properties on top of the default ones. */ struct lp_style_type newlp = *lp; if ((destination_class == LP_ADHOC) && (almost_equals(c_token, "lines$tyle") || equals(c_token, "ls"))) { c_token++; lp_use_properties(lp, int_expression()); } while (!END_OF_COMMAND) { /* This special case is to flag an attemp to "set object N lt <lt>", * which would otherwise be accepted but ignored, leading to confusion * FIXME: Couldn't this be handled at a higher level? */ if ((destination_class == LP_NOFILL) && (equals(c_token,"lt") || almost_equals(c_token,"linet$ype"))) { int_error(c_token, "object linecolor must be set using fillstyle border"); } if (almost_equals(c_token, "linet$ype") || equals(c_token, "lt")) { if (set_lt++) break; if (destination_class == LP_TYPE) int_error(c_token, "linetype definition cannot use linetype"); c_token++; if (almost_equals(c_token, "rgb$color")) { if (set_pal++) break; c_token--; parse_colorspec(&(newlp.pm3d_color), TC_RGB); } else /* both syntaxes allowed: 'with lt pal' as well as 'with pal' */ if (almost_equals(c_token, "pal$ette")) { if (set_pal++) break; c_token--; parse_colorspec(&(newlp.pm3d_color), TC_Z); } else if (equals(c_token,"bgnd")) { *lp = background_lp; c_token++; } else if (equals(c_token,"black")) { *lp = default_border_lp; c_token++; } else if (equals(c_token,"nodraw")) { lp->l_type = LT_NODRAW; c_token++; } else { /* These replace the base style */ new_lt = int_expression(); lp->l_type = new_lt - 1; /* user may prefer explicit line styles */ if (prefer_line_styles && (destination_class != LP_STYLE)) lp_use_properties(lp, new_lt); else load_linetype(lp, new_lt); } } /* linetype, lt */ /* both syntaxes allowed: 'with lt pal' as well as 'with pal' */ if (almost_equals(c_token, "pal$ette")) { if (set_pal++) break; c_token--; parse_colorspec(&(newlp.pm3d_color), TC_Z); continue; } /* This is so that "set obj ... lw N fc <colorspec>" doesn't eat up the * fc colorspec as a line property. We need to parse it later as a * _fill_ property. Also prevents "plot ... fc <col1> fs <foo> lw <baz>" * from generating an error claiming redundant line properties. */ if ((destination_class == LP_NOFILL || destination_class == LP_ADHOC) && (equals(c_token,"fc") || almost_equals(c_token,"fillc$olor"))) break; if (equals(c_token,"lc") || almost_equals(c_token,"linec$olor") || equals(c_token,"fc") || almost_equals(c_token,"fillc$olor") ) { if (set_pal++) break; c_token++; if (almost_equals(c_token, "rgb$color") || isstring(c_token)) { c_token--; parse_colorspec(&(newlp.pm3d_color), TC_RGB); } else if (almost_equals(c_token, "pal$ette")) { c_token--; parse_colorspec(&(newlp.pm3d_color), TC_Z); } else if (equals(c_token,"bgnd")) { newlp.pm3d_color.type = TC_LT; newlp.pm3d_color.lt = LT_BACKGROUND; c_token++; } else if (equals(c_token,"black")) { newlp.pm3d_color.type = TC_LT; newlp.pm3d_color.lt = LT_BLACK; c_token++; } else if (almost_equals(c_token, "var$iable")) { c_token++; newlp.l_type = LT_COLORFROMCOLUMN; newlp.pm3d_color.type = TC_LINESTYLE; } else { /* Pull the line colour from a default linetype, but */ /* only if we are not in the middle of defining one! */ if (destination_class != LP_STYLE) { struct lp_style_type temp; load_linetype(&temp, int_expression()); newlp.pm3d_color = temp.pm3d_color; } else { newlp.pm3d_color.type = TC_LT; newlp.pm3d_color.lt = int_expression() - 1; } } continue; } if (almost_equals(c_token, "linew$idth") || equals(c_token, "lw")) { if (set_lw++) break; c_token++; newlp.l_width = real_expression(); if (newlp.l_width < 0) newlp.l_width = 0; continue; } if (equals(c_token,"bgnd")) { if (set_lt++) break;; c_token++; *lp = background_lp; continue; } if (equals(c_token,"black")) { if (set_lt++) break;; c_token++; *lp = default_border_lp; continue; } if (almost_equals(c_token, "pointt$ype") || equals(c_token, "pt")) { if (allow_point) { char *symbol; if (set_pt++) break; c_token++; if ((symbol = try_to_get_string())) { newlp.p_type = PT_CHARACTER; /* An alternative mechanism would be to use * utf8toulong(&newlp.p_char, symbol); */ strncpy((char *)(&newlp.p_char), symbol, 3); /* Truncate ascii text to single character */ if ((((char *)&newlp.p_char)[0] & 0x80) == 0) ((char *)&newlp.p_char)[1] = '\0'; /* UTF-8 characters may use up to 3 bytes */ ((char *)&newlp.p_char)[3] = '\0'; free(symbol); } else { newlp.p_type = int_expression() - 1; } } else { int_warn(c_token, "No pointtype specifier allowed, here"); c_token += 2; } continue; } if (almost_equals(c_token, "points$ize") || equals(c_token, "ps")) { if (allow_point) { if (set_ps++) break; c_token++; if (almost_equals(c_token, "var$iable")) { newlp.p_size = PTSZ_VARIABLE; c_token++; } else if (almost_equals(c_token, "def$ault")) { newlp.p_size = PTSZ_DEFAULT; c_token++; } else { newlp.p_size = real_expression(); if (newlp.p_size < 0) newlp.p_size = 0; } } else { int_warn(c_token, "No pointsize specifier allowed, here"); c_token += 2; } continue; } if (almost_equals(c_token, "pointi$nterval") || equals(c_token, "pi")) { c_token++; if (allow_point) { newlp.p_interval = int_expression(); set_pi = 1; } else { int_warn(c_token, "No pointinterval specifier allowed, here"); int_expression(); } continue; } if (almost_equals(c_token, "dasht$ype") || equals(c_token, "dt")) { int tmp; if (set_dt++) break; c_token++; tmp = parse_dashtype(&newlp.custom_dash_pattern); /* Pull the dashtype from the list of already defined dashtypes, */ /* but only if it we didn't get an explicit one back from parse_dashtype */ if (tmp == DASHTYPE_AXIS) lp->l_type = LT_AXIS; if (tmp >= 0) tmp = load_dashtype(&newlp.custom_dash_pattern, tmp + 1); newlp.d_type = tmp; continue; } /* caught unknown option -> quit the while(1) loop */ break; } if (set_lt > 1 || set_pal > 1 || set_lw > 1 || set_pt > 1 || set_ps > 1 || set_dt > 1) int_error(c_token, "duplicated arguments in style specification"); if (set_pal) { lp->pm3d_color = newlp.pm3d_color; /* hidden3d uses this to decide that a single color surface is wanted */ lp->flags |= LP_EXPLICIT_COLOR; } else { lp->flags &= ~LP_EXPLICIT_COLOR; } if (set_lw) lp->l_width = newlp.l_width; if (set_pt) { lp->p_type = newlp.p_type; lp->p_char = newlp.p_char; } if (set_ps) lp->p_size = newlp.p_size; if (set_pi) lp->p_interval = newlp.p_interval; if (newlp.l_type == LT_COLORFROMCOLUMN) lp->l_type = LT_COLORFROMCOLUMN; if (set_dt) { lp->d_type = newlp.d_type; lp->custom_dash_pattern = newlp.custom_dash_pattern; } return new_lt; }
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); }