diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index c6805450e68d0733b45d232a978dd37daeab1750..3f8ee1bff143af2dc004eb0e83ffaac4200b8e9f 100644 (file)
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
{5.5, RRD_DEFAULT_FONT,NULL} /* watermark */
};
{5.5, RRD_DEFAULT_FONT,NULL} /* watermark */
};
+char week_fmt[128] = "Week %V";
+
xlab_t xlab[] = {
{0, 0, TMT_SECOND, 30, TMT_MINUTE, 5, TMT_MINUTE, 5, 0, "%H:%M"}
,
xlab_t xlab[] = {
{0, 0, TMT_SECOND, 30, TMT_MINUTE, 5, TMT_MINUTE, 5, 0, "%H:%M"}
,
,
{2400, 0, TMT_HOUR, 12, TMT_DAY, 1, TMT_DAY, 2, 24 * 3600, "%a"}
,
,
{2400, 0, TMT_HOUR, 12, TMT_DAY, 1, TMT_DAY, 2, 24 * 3600, "%a"}
,
- {3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, "Week %V"}
+ {3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, week_fmt}
,
{3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600,
,
{3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600,
- "Week %V"}
+ week_fmt}
,
{6 * 3600, 0, TMT_MONTH, 1, TMT_MONTH, 1, TMT_MONTH, 1, 30 * 24 * 3600,
"%b"}
,
{6 * 3600, 0, TMT_MONTH, 1, TMT_MONTH, 1, TMT_MONTH, 1, 30 * 24 * 3600,
"%b"}
free(im->gdes[i].rpnp);
}
free(im->gdes);
free(im->gdes[i].rpnp);
}
free(im->gdes);
+
+ for (i = 0; i < DIM(text_prop);i++){
+ pango_font_description_free(im->text_prop[i].font_desc);
+ im->text_prop[i].font_desc = NULL;
+ }
+
if (im->font_options)
cairo_font_options_destroy(im->font_options);
if (im->font_options)
cairo_font_options_destroy(im->font_options);
status = cairo_status(im->cr);
cairo_destroy(im->cr);
}
status = cairo_status(im->cr);
cairo_destroy(im->cr);
}
+
+
if (im->rendered_image) {
free(im->rendered_image);
}
if (im->rendered_image) {
free(im->rendered_image);
}
&im->gdes[i].ds_cnt,
&im->gdes[i].ds_namv,
&im->gdes[i].data)) == -1) {
&im->gdes[i].ds_cnt,
&im->gdes[i].ds_namv,
&im->gdes[i].data)) == -1) {
- return -1;
- }
+ return -1;
+ }
}
im->gdes[i].data_first = 1;
}
im->gdes[i].data_first = 1;
+ /* must reduce to at least im->step
+ otherwhise we end up with more data than we can handle in the
+ chart and visibility of data will be random */
+ im->gdes[i].step = max(im->gdes[i].step,im->step);
if (ft_step < im->gdes[i].step) {
reduce_data(im->gdes[i].cf_reduce,
ft_step,
if (ft_step < im->gdes[i].step) {
reduce_data(im->gdes[i].cf_reduce,
ft_step,
localtime_r(¤t, &tm);
localtime_r(¤t, &tm);
+ int limit = 2;
+ switch (baseint) {
+ case TMT_SECOND: limit = 7200; break;
+ case TMT_MINUTE: limit = 120; break;
+ case TMT_HOUR: limit = 2; break;
+ default: limit = 2; break;
+ }
do {
switch (baseint) {
case TMT_SECOND:
do {
switch (baseint) {
case TMT_SECOND:
tm. tm_year += basestep;
}
madetime = mktime(&tm);
tm. tm_year += basestep;
}
madetime = mktime(&tm);
- } while (madetime == -1); /* this is necessary to skip impssible times
+ } while (madetime == -1 && limit-- >= 0); /* this is necessary to skip impossible times
like the daylight saving time skips */
return madetime;
like the daylight saving time skips */
return madetime;
}
} /* prepare printval */
}
} /* prepare printval */
- if ((percent_s = strstr(im->gdes[i].format, "%S")) != NULL) {
+ if (!im->gdes[i].strftm && (percent_s = strstr(im->gdes[i].format, "%S")) != NULL) {
/* Magfact is set to -1 upon entry to print_calc. If it
* is still less than 0, then we need to run auto_scale.
* Otherwise, put the value into the correct units. If
/* Magfact is set to -1 upon entry to print_calc. If it
* is still less than 0, then we need to run auto_scale.
* Otherwise, put the value into the correct units. If
printval /= magfact;
}
*(++percent_s) = 's';
printval /= magfact;
}
*(++percent_s) = 's';
- } else if (strstr(im->gdes[i].format, "%s") != NULL) {
+ } else if (!im->gdes[i].strftm && strstr(im->gdes[i].format, "%s") != NULL) {
auto_scale(im, &printval, &si_symb, &magfact);
}
auto_scale(im, &printval, &si_symb, &magfact);
}
if (im->gdes[i].strftm) {
prline.u_str = (char*)malloc((FMT_LEG_LEN + 2) * sizeof(char));
if (im->gdes[i].strftm) {
prline.u_str = (char*)malloc((FMT_LEG_LEN + 2) * sizeof(char));
- strftime(prline.u_str,
- FMT_LEG_LEN, im->gdes[i].format, &tmvdef);
+ if (im->gdes[vidx].vf.never == 1) {
+ time_clean(prline.u_str, im->gdes[i].format);
+ } else {
+ strftime(prline.u_str,
+ FMT_LEG_LEN, im->gdes[i].format, &tmvdef);
+ }
} else if (bad_format(im->gdes[i].format)) {
rrd_set_error
("bad format for PRINT in '%s'", im->gdes[i].format);
} else if (bad_format(im->gdes[i].format)) {
rrd_set_error
("bad format for PRINT in '%s'", im->gdes[i].format);
/* GF_GPRINT */
if (im->gdes[i].strftm) {
/* GF_GPRINT */
if (im->gdes[i].strftm) {
- strftime(im->gdes[i].legend,
- FMT_LEG_LEN, im->gdes[i].format, &tmvdef);
+ if (im->gdes[vidx].vf.never == 1) {
+ time_clean(im->gdes[i].legend, im->gdes[i].format);
+ } else {
+ strftime(im->gdes[i].legend,
+ FMT_LEG_LEN, im->gdes[i].format, &tmvdef);
+ }
} else {
if (bad_format(im->gdes[i].format)) {
rrd_set_error
} else {
if (bad_format(im->gdes[i].format)) {
rrd_set_error
glue = 0;
}
if (prt_fctn == 'c')
glue = 0;
}
if (prt_fctn == 'c')
- leg_x = (double)(legendwidth - fill) / 2.0;
+ leg_x = border + (double)(legendwidth - fill) / 2.0;
if (prt_fctn == 'r')
leg_x = legendwidth - fill + border;
for (ii = mark; ii <= i; ii++) {
if (prt_fctn == 'r')
leg_x = legendwidth - fill + border;
for (ii = mark; ii <= i; ii++) {
}
}
else {
}
}
else {
- sprintf(graph_label_right,im->second_axis_format,sval);
+ sprintf(graph_label_right,im->second_axis_format,sval,"");
}
gfx_text ( im,
}
gfx_text ( im,
mgridtm,
im->xlab_user.
mgridst);
mgridtm,
im->xlab_user.
mgridst);
- ti < im->end;
+ ti < im->end && ti != -1;
ti =
find_next_time(ti, im->xlab_user.gridtm, im->xlab_user.gridst)
) {
/* are we inside the graph ? */
if (ti < im->start || ti > im->end)
continue;
ti =
find_next_time(ti, im->xlab_user.gridtm, im->xlab_user.gridst)
) {
/* are we inside the graph ? */
if (ti < im->start || ti > im->end)
continue;
- while (timajor < ti) {
+ while (timajor < ti && timajor != -1) {
timajor = find_next_time(timajor,
im->
xlab_user.
mgridtm, im->xlab_user.mgridst);
}
timajor = find_next_time(timajor,
im->
xlab_user.
mgridtm, im->xlab_user.mgridst);
}
+ if (timajor == -1) break; /* fail in case of problems with time increments */
if (ti == timajor)
continue; /* skip as falls on major grid line */
X0 = xtr(im, ti);
if (ti == timajor)
continue; /* skip as falls on major grid line */
X0 = xtr(im, ti);
im->
xlab_user.
mgridst);
im->
xlab_user.
mgridst);
- ti < im->end;
+ ti < im->end && ti != -1;
ti = find_next_time(ti, im->xlab_user.mgridtm, im->xlab_user.mgridst)
) {
/* are we inside the graph ? */
ti = find_next_time(ti, im->xlab_user.mgridtm, im->xlab_user.mgridst)
) {
/* are we inside the graph ? */
labtm,
im->xlab_user.
labst);
labtm,
im->xlab_user.
labst);
- ti <=
+ (ti <=
im->end -
im->end -
- im->xlab_user.precis / 2;
+ im->xlab_user.precis / 2) && ti != -1;
ti = find_next_time(ti, im->xlab_user.labtm, im->xlab_user.labst)
) {
tilab = ti + im->xlab_user.precis / 2; /* correct time for the label */
ti = find_next_time(ti, im->xlab_user.labtm, im->xlab_user.labst)
) {
tilab = ti + im->xlab_user.precis / 2; /* correct time for the label */
}
else{
// we have no title; get a little clearing from the top
}
else{
// we have no title; get a little clearing from the top
- Ytitle = 1.5 * Yspacing;
+ Ytitle = Yspacing;
}
if (elements) {
}
if (elements) {
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
- Ymain -= Yspacing;
+ Ymain -= 0.5*Yspacing;
}
if (im->watermark[0] != '\0') {
}
if (im->watermark[0] != '\0') {
}
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
}
/* reserve space for padding below the graph */
if (im->extra_flags & NOLEGEND) {
- im->yimg += Yspacing;
+ im->yimg += 0.5*Yspacing;
}
if (im->watermark[0] != '\0') {
}
if (im->watermark[0] != '\0') {
*/
switch(im->legendposition){
case NORTH:
*/
switch(im->legendposition){
case NORTH:
- im->xOriginTitle = Xvertical + Xylabel + (im->xsize / 2);
+ im->xOriginTitle = (im->ximg / 2);
im->yOriginTitle = 0;
im->xOriginLegend = 0;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case WEST:
break;
case WEST:
- im->xOriginTitle = im->legendwidth + Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->legendwidth + im->xsize / 2;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case SOUTH:
break;
case SOUTH:
- im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->ximg / 2;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
im->yOriginTitle = 0;
im->xOriginLegend = 0;
break;
case EAST:
break;
case EAST:
- im->xOriginTitle = Xvertical + Xylabel + im->xsize / 2;
+ im->xOriginTitle = im->xsize / 2;
im->yOriginTitle = 0;
im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2;
im->yOriginTitle = 0;
im->xOriginLegend = Xvertical + Xylabel + Xmain + Xvertical2;
break;
case GF_LINE:
case GF_AREA:
break;
case GF_LINE:
case GF_AREA:
- case GF_GRAD:
- /* fix data points at oo and -oo */
+ case GF_GRAD: {
+ rrd_value_t diffval = im->maxval - im->minval;
+ rrd_value_t maxlimit = im->maxval + 9 * diffval;
+ rrd_value_t minlimit = im->minval - 9 * diffval;
for (ii = 0; ii < im->xsize; ii++) {
for (ii = 0; ii < im->xsize; ii++) {
+ /* fix data points at oo and -oo */
if (isinf(im->gdes[i].p_data[ii])) {
if (im->gdes[i].p_data[ii] > 0) {
im->gdes[i].p_data[ii] = im->maxval;
} else {
im->gdes[i].p_data[ii] = im->minval;
}
if (isinf(im->gdes[i].p_data[ii])) {
if (im->gdes[i].p_data[ii] > 0) {
im->gdes[i].p_data[ii] = im->maxval;
} else {
im->gdes[i].p_data[ii] = im->minval;
}
-
}
}
+ /* some versions of cairo go unstable when trying
+ to draw way out of the canvas ... lets not even try */
+ if (im->gdes[i].p_data[ii] > maxlimit) {
+ im->gdes[i].p_data[ii] = maxlimit;
+ }
+ if (im->gdes[i].p_data[ii] < minlimit) {
+ im->gdes[i].p_data[ii] = minlimit;
+ }
} /* for */
/* *******************************************************
} /* for */
/* *******************************************************
}
lastgdes = &(im->gdes[i]);
break;
}
lastgdes = &(im->gdes[i]);
break;
+ } /* GF_AREA, GF_LINE, GF_GRAD */
case GF_STACK:
rrd_set_error
("STACK should already be turned into LINE or AREA here");
case GF_STACK:
rrd_set_error
("STACK should already be turned into LINE or AREA here");
char *old_locale;
rrd_graph_init(&im);
/* a dummy surface so that we can measure text sizes for placements */
char *old_locale;
rrd_graph_init(&im);
/* a dummy surface so that we can measure text sizes for placements */
- old_locale = setlocale(LC_NUMERIC, "C");
+ old_locale = setlocale(LC_NUMERIC, NULL);
+ setlocale(LC_NUMERIC, "C");
rrd_graph_options(argc, argv, &im);
if (rrd_test_error()) {
rrd_graph_options(argc, argv, &im);
if (rrd_test_error()) {
+ setlocale(LC_NUMERIC, old_locale); /* reenable locale */
rrd_info_free(im.grinfo);
im_free(&im);
return NULL;
}
if (optind >= argc) {
rrd_info_free(im.grinfo);
im_free(&im);
return NULL;
}
if (optind >= argc) {
+ setlocale(LC_NUMERIC, old_locale); /* reenable locale */
rrd_info_free(im.grinfo);
im_free(&im);
rrd_set_error("missing filename");
rrd_info_free(im.grinfo);
im_free(&im);
rrd_set_error("missing filename");
}
if (strlen(argv[optind]) >= MAXPATH) {
}
if (strlen(argv[optind]) >= MAXPATH) {
+ setlocale(LC_NUMERIC, old_locale); /* reenable locale */
rrd_set_error("filename (including path) too long");
rrd_info_free(im.grinfo);
im_free(&im);
rrd_set_error("filename (including path) too long");
rrd_info_free(im.grinfo);
im_free(&im);
if (font){
strncpy(im->text_prop[prop].font, font, sizeof(text_prop[prop].font) - 1);
im->text_prop[prop].font[sizeof(text_prop[prop].font) - 1] = '\0';
if (font){
strncpy(im->text_prop[prop].font, font, sizeof(text_prop[prop].font) - 1);
im->text_prop[prop].font[sizeof(text_prop[prop].font) - 1] = '\0';
+ /* if we already got one, drop it first */
+ pango_font_description_free(im->text_prop[prop].font_desc);
im->text_prop[prop].font_desc = pango_font_description_from_string( font );
};
if (size > 0){
im->text_prop[prop].font_desc = pango_font_description_from_string( font );
};
if (size > 0){
for (i = 0; i < DIM(text_prop); i++) {
im->text_prop[i].size = -1;
for (i = 0; i < DIM(text_prop); i++) {
im->text_prop[i].size = -1;
+ im->text_prop[i].font_desc = NULL;
rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size);
}
rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size);
}
pango_cairo_update_context(im->cr,context);
im->layout = pango_layout_new(context);
pango_cairo_update_context(im->cr,context);
im->layout = pango_layout_new(context);
+ g_object_unref (context);
// im->layout = pango_cairo_create_layout(im->cr);
// im->layout = pango_cairo_create_layout(im->cr);
{ "border", required_argument, 0, 1007},
{ "grid-dash", required_argument, 0, 1008},
{ "dynamic-labels", no_argument, 0, 1009},
{ "border", required_argument, 0, 1007},
{ "grid-dash", required_argument, 0, 1008},
{ "dynamic-labels", no_argument, 0, 1009},
+ { "week-fmt", required_argument, 0, 1010},
{ 0, 0, 0, 0}
};
/* *INDENT-ON* */
{ 0, 0, 0, 0}
};
/* *INDENT-ON* */
case 1009: /* enable dynamic labels */
im->dynamic_labels = 1;
break;
case 1009: /* enable dynamic labels */
im->dynamic_labels = 1;
break;
+ case 1010:
+ strncpy(week_fmt,optarg,sizeof week_fmt);
+ week_fmt[(sizeof week_fmt)-1]='\0';
+ break;
case 1002: /* right y axis */
if(sscanf(optarg,
case 1002: /* right y axis */
if(sscanf(optarg,
gdes->vf.param = param;
gdes->vf.val = DNAN; /* undefined */
gdes->vf.when = 0; /* undefined */
gdes->vf.param = param;
gdes->vf.val = DNAN; /* undefined */
gdes->vf.when = 0; /* undefined */
+ gdes->vf.never = 1;
} else {
rrd_set_error
("Parameter '%f' out of range in VDEF '%s'\n",
} else {
rrd_set_error
("Parameter '%f' out of range in VDEF '%s'\n",
gdes->vf.param = DNAN;
gdes->vf.val = DNAN;
gdes->vf.when = 0;
gdes->vf.param = DNAN;
gdes->vf.val = DNAN;
gdes->vf.when = 0;
+ gdes->vf.never = 1;
} else {
rrd_set_error
("Function '%s' needs no parameter in VDEF '%s'\n",
} else {
rrd_set_error
("Function '%s' needs no parameter in VDEF '%s'\n",
field = round((dst->vf.param * (double)(steps - 1)) / 100.0);
dst->vf.val = array[field];
dst->vf.when = 0; /* no time component */
field = round((dst->vf.param * (double)(steps - 1)) / 100.0);
dst->vf.val = array[field];
dst->vf.when = 0; /* no time component */
+ dst->vf.never = 1;
free(array);
#if 0
for (step = 0; step < steps; step++)
free(array);
#if 0
for (step = 0; step < steps; step++)
field = round( dst->vf.param * (double)(nancount - 1) / 100.0);
dst->vf.val = array[field];
dst->vf.when = 0; /* no time component */
field = round( dst->vf.param * (double)(nancount - 1) / 100.0);
dst->vf.val = array[field];
dst->vf.when = 0; /* no time component */
+ dst->vf.never = 1;
free(array);
}
break;
free(array);
}
break;
if (step == steps) {
dst->vf.val = DNAN;
dst->vf.when = 0;
if (step == steps) {
dst->vf.val = DNAN;
dst->vf.when = 0;
+ dst->vf.never = 1;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
+ dst->vf.never = 0;
}
while (step != steps) {
if (finite(data[step * src->ds_cnt])) {
if (data[step * src->ds_cnt] > dst->vf.val) {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
}
while (step != steps) {
if (finite(data[step * src->ds_cnt])) {
if (data[step * src->ds_cnt] > dst->vf.val) {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
+ dst->vf.never = 0;
}
}
step++;
}
}
step++;
if (dst->vf.op == VDEF_TOTAL) {
dst->vf.val = sum * src->step;
dst->vf.when = 0; /* no time component */
if (dst->vf.op == VDEF_TOTAL) {
dst->vf.val = sum * src->step;
dst->vf.when = 0; /* no time component */
+ dst->vf.never = 1;
} else if (dst->vf.op == VDEF_AVERAGE) {
dst->vf.val = sum / cnt;
dst->vf.when = 0; /* no time component */
} else if (dst->vf.op == VDEF_AVERAGE) {
dst->vf.val = sum / cnt;
dst->vf.when = 0; /* no time component */
+ dst->vf.never = 1;
} else {
average = sum / cnt;
sum = 0.0;
} else {
average = sum / cnt;
sum = 0.0;
}
dst->vf.val = pow(sum / cnt, 0.5);
dst->vf.when = 0; /* no time component */
}
dst->vf.val = pow(sum / cnt, 0.5);
dst->vf.when = 0; /* no time component */
+ dst->vf.never = 1;
};
} else {
dst->vf.val = DNAN;
dst->vf.when = 0;
};
} else {
dst->vf.val = DNAN;
dst->vf.when = 0;
+ dst->vf.never = 1;
}
}
break;
}
}
break;
if (step == steps) {
dst->vf.val = DNAN;
dst->vf.when = 0;
if (step == steps) {
dst->vf.val = DNAN;
dst->vf.when = 0;
+ dst->vf.never = 1;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
+ dst->vf.never = 0;
}
while (step != steps) {
if (finite(data[step * src->ds_cnt])) {
if (data[step * src->ds_cnt] < dst->vf.val) {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
}
while (step != steps) {
if (finite(data[step * src->ds_cnt])) {
if (data[step * src->ds_cnt] < dst->vf.val) {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
+ dst->vf.never = 0;
}
}
step++;
}
}
step++;
if (step == steps) { /* all entries were NaN */
dst->vf.val = DNAN;
dst->vf.when = 0;
if (step == steps) { /* all entries were NaN */
dst->vf.val = DNAN;
dst->vf.when = 0;
+ dst->vf.never = 1;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + step * src->step;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + step * src->step;
+ dst->vf.never = 0;
}
break;
case VDEF_LAST:
}
break;
case VDEF_LAST:
if (step < 0) { /* all entries were NaN */
dst->vf.val = DNAN;
dst->vf.when = 0;
if (step < 0) { /* all entries were NaN */
dst->vf.val = DNAN;
dst->vf.when = 0;
+ dst->vf.never = 1;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
} else {
dst->vf.val = data[step * src->ds_cnt];
dst->vf.when = src->start + (step + 1) * src->step;
+ dst->vf.never = 0;
}
break;
case VDEF_LSLSLOPE:
}
break;
case VDEF_LSLSLOPE:
if (dst->vf.op == VDEF_LSLSLOPE) {
dst->vf.val = slope;
dst->vf.when = 0;
if (dst->vf.op == VDEF_LSLSLOPE) {
dst->vf.val = slope;
dst->vf.when = 0;
+ dst->vf.never = 1;
} else if (dst->vf.op == VDEF_LSLINT) {
dst->vf.val = y_intercept;
dst->vf.when = 0;
} else if (dst->vf.op == VDEF_LSLINT) {
dst->vf.val = y_intercept;
dst->vf.when = 0;
+ dst->vf.never = 1;
} else if (dst->vf.op == VDEF_LSLCORREL) {
dst->vf.val = correl;
dst->vf.when = 0;
} else if (dst->vf.op == VDEF_LSLCORREL) {
dst->vf.val = correl;
dst->vf.when = 0;
+ dst->vf.never = 1;
};
} else {
dst->vf.val = DNAN;
dst->vf.when = 0;
};
} else {
dst->vf.val = DNAN;
dst->vf.when = 0;
+ dst->vf.never = 1;
}
}
break;
}
}
break;
im->grinfo = im->grinfo_current;
}
}
im->grinfo = im->grinfo_current;
}
}
+
+
+void time_clean(
+ char *result,
+ char *format)
+{
+ int j, jj;
+
+/* Handling based on
+ - ANSI C99 Specifications http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
+ - Single UNIX Specification version 2 http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html
+ - POSIX:2001/Single UNIX Specification version 3 http://www.opengroup.org/onlinepubs/009695399/functions/strftime.html
+ - POSIX:2008 Specifications http://www.opengroup.org/onlinepubs/9699919799/functions/strftime.html
+ Specifications tells
+ "If a conversion specifier is not one of the above, the behavior is undefined."
+
+ C99 tells
+ "A conversion specifier consists of a % character, possibly followed by an E or O modifier character (described below), followed by a character that determines the behavior of the conversion specifier.
+
+ POSIX:2001 tells
+ "A conversion specification consists of a '%' character, possibly followed by an E or O modifier, and a terminating conversion specifier character that determines the conversion specification's behavior."
+
+ POSIX:2008 introduce more complexe behavior that are not handled here.
+
+ According to this, this code will replace:
+ - % followed by @ by a %@
+ - % followed by by a %SPACE
+ - % followed by . by a %.
+ - % followed by % by a %
+ - % followed by t by a TAB
+ - % followed by E then anything by '-'
+ - % followed by O then anything by '-'
+ - % followed by anything else by at least one '-'. More characters may be added to better fit expected output length
+*/
+
+ jj = 0;
+ for(j = 0; (j < FMT_LEG_LEN - 1) && (jj < FMT_LEG_LEN); j++) { /* we don't need to parse the last char */
+ if (format[j] == '%') {
+ if ((format[j+1] == 'E') || (format[j+1] == 'O')) {
+ result[jj++] = '-';
+ j+=2; /* We skip next 2 following char */
+ } else if ((format[j+1] == 'C') || (format[j+1] == 'd') ||
+ (format[j+1] == 'g') || (format[j+1] == 'H') ||
+ (format[j+1] == 'I') || (format[j+1] == 'm') ||
+ (format[j+1] == 'M') || (format[j+1] == 'S') ||
+ (format[j+1] == 'U') || (format[j+1] == 'V') ||
+ (format[j+1] == 'W') || (format[j+1] == 'y')) {
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN) {
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 'j') {
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN - 1) {
+ result[jj++] = '-';
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if ((format[j+1] == 'G') || (format[j+1] == 'Y')) {
+ /* Assuming Year on 4 digit */
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN - 2) {
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 'R') {
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN - 3) {
+ result[jj++] = '-';
+ result[jj++] = ':';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 'T') {
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN - 6) {
+ result[jj++] = '-';
+ result[jj++] = ':';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = ':';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 'F') {
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN - 8) {
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 'D') {
+ result[jj++] = '-';
+ if (jj < FMT_LEG_LEN - 6) {
+ result[jj++] = '-';
+ result[jj++] = '/';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ result[jj++] = '/';
+ result[jj++] = '-';
+ result[jj++] = '-';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 'n') {
+ result[jj++] = '\r';
+ result[jj++] = '\n';
+ j++; /* We skip the following char */
+ } else if (format[j+1] == 't') {
+ result[jj++] = '\t';
+ j++; /* We skip the following char */
+ } else if (format[j+1] == '%') {
+ result[jj++] = '%';
+ j++; /* We skip the following char */
+ } else if (format[j+1] == ' ') {
+ if (jj < FMT_LEG_LEN - 1) {
+ result[jj++] = '%';
+ result[jj++] = ' ';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == '.') {
+ if (jj < FMT_LEG_LEN - 1) {
+ result[jj++] = '%';
+ result[jj++] = '.';
+ }
+ j++; /* We skip the following char */
+ } else if (format[j+1] == '@') {
+ if (jj < FMT_LEG_LEN - 1) {
+ result[jj++] = '%';
+ result[jj++] = '@';
+ }
+ j++; /* We skip the following char */
+ } else {
+ result[jj++] = '-';
+ j++; /* We skip the following char */
+ }
+ } else {
+ result[jj++] = format[j];
+ }
+ }
+ result[jj] = '\0'; /* We must force the end of the string */
+}