strerror should not turn us recursive here ... -- Peter Stamfest <peter@stamfest.at>
[rrdtool.git] / src / rrd_graph.c
index b895225..715f0dc 100644 (file)
@@ -677,9 +677,9 @@ for (col=0;col<row_cnt;col++) {
    relevant rrds ... */
 
 int
-data_fetch( image_desc_t *im )
+data_fetch(image_desc_t *im )
 {
-    int                i,ii;
+    unsigned int i,ii;
     int                skip;
 
     /* pull the data from the log files ... */
@@ -1008,7 +1008,7 @@ data_proc( image_desc_t *im ){
                        paintval = 0.0;
                case GF_STACK:
                    value = im->gdes[ii].yrule;
-                   if (isnan(value)) { /* not a number or VDEF */
+                   if (isnan(value) || (im->gdes[ii].gf == GF_TICK)) {
                        /* The time of the data doesn't necessarily match
                        ** the time of the graph. Beware.
                        */
@@ -1096,7 +1096,7 @@ find_first_time(
     )
 {
     struct tm tm;
-    tm = *localtime(&start);
+    localtime_r(&start, &tm);
     switch(baseint){
     case TMT_SECOND:
        tm.tm_sec -= tm.tm_sec % basestep; break;
@@ -1149,7 +1149,7 @@ find_next_time(
 {
     struct tm tm;
     time_t madetime;
-    tm = *localtime(&current);
+    localtime_r(&current, &tm);
     do {
        switch(baseint){
        case TMT_SECOND:
@@ -1254,14 +1254,15 @@ print_calc(image_desc_t *im, char ***prdata)
            } /* prepare printval */
 
            if (!strcmp(im->gdes[i].format,"%c")) { /* VDEF time print */
+               char ctime_buf[128]; /* PS: for ctime_r, must be >= 26 chars */
                if (im->gdes[i].gf == GF_PRINT){
                    (*prdata)[prlines-2] = malloc((FMT_LEG_LEN+2)*sizeof(char));
                    sprintf((*prdata)[prlines-2],"%s (%lu)",
-                                       ctime(&printtime),printtime);
+                                       ctime_r(&printtime,ctime_buf),printtime);
                    (*prdata)[prlines-1] = NULL;
                } else {
                    sprintf(im->gdes[i].legend,"%s (%lu)",
-                                       ctime(&printtime),printtime);
+                                       ctime_r(&printtime,ctime_buf),printtime);
                    graphelement = 1;
                }
            } else {
@@ -1357,6 +1358,16 @@ leg_place(image_desc_t *im)
 
     for(i=0;i<im->gdes_c;i++){
        fill_last = fill;
+        
+        /* hid legends for rules which are not displayed */
+        
+       if (im->gdes[i].gf == GF_HRULE &&
+           (im->gdes[i].yrule < im->minval || im->gdes[i].yrule > im->maxval))
+           im->gdes[i].legend[0] = '\0';
+
+       if (im->gdes[i].gf == GF_VRULE &&
+           (im->gdes[i].xrule < im->start || im->gdes[i].xrule > im->end))
+           im->gdes[i].legend[0] = '\0';
 
        leg_cc = strlen(im->gdes[i].legend);
        
@@ -1591,7 +1602,7 @@ int draw_horizontal_grid(image_desc_t *im)
                              MGRIDWIDTH, im->graph_col[GRC_MGRID],
                              im->grid_dash_on, im->grid_dash_off);            
               
-           } else {            
+           } else if (!(im->extra_flags & NOMINOR)) {          
               gfx_new_dashed_line ( im->canvas,
                              X0-1,Y0,
                              X1+1,Y0,
@@ -1694,7 +1705,7 @@ vertical_grid(
     long factor;
     char graph_label[100];
     double X0,Y0,Y1; /* points for filled graph and more*/
-   
+    struct tm tm;
 
     /* the type of time grid is determined by finding
        the number of seconds per pixel in the graph */
@@ -1721,27 +1732,30 @@ vertical_grid(
    
 
     /* paint the minor grid */
-    for(ti = find_first_time(im->start,
-                           im->xlab_user.gridtm,
-                           im->xlab_user.gridst),
-        timajor = find_first_time(im->start,
-                           im->xlab_user.mgridtm,
-                           im->xlab_user.mgridst);
-       ti < im->end; 
-       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) {
-           timajor = find_next_time(timajor,
-                   im->xlab_user.mgridtm, im->xlab_user.mgridst);
-       }
-       if (ti == timajor) continue; /* skip as falls on major grid line */
-       X0 = xtr(im,ti);       
-       gfx_new_dashed_line(im->canvas,X0,Y0+1, X0,Y1-1,GRIDWIDTH,
-          im->graph_col[GRC_GRID],
-          im->grid_dash_on, im->grid_dash_off);
-       
+    if (!(im->extra_flags & NOMINOR))
+    {
+        for(ti = find_first_time(im->start,
+                                im->xlab_user.gridtm,
+                                im->xlab_user.gridst),
+            timajor = find_first_time(im->start,
+                                im->xlab_user.mgridtm,
+                                im->xlab_user.mgridst);
+            ti < im->end; 
+            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) {
+                timajor = find_next_time(timajor,
+                        im->xlab_user.mgridtm, im->xlab_user.mgridst);
+            }
+            if (ti == timajor) continue; /* skip as falls on major grid line */
+           X0 = xtr(im,ti);       
+           gfx_new_dashed_line(im->canvas,X0,Y0+1, X0,Y1-1,GRIDWIDTH,
+               im->graph_col[GRC_GRID],
+               im->grid_dash_on, im->grid_dash_off);
+           
+        }
     }
 
     /* paint the major grid */
@@ -1771,7 +1785,8 @@ vertical_grid(
        if (ti < im->start || ti > im->end) continue;
 
 #if HAVE_STRFTIME
-       strftime(graph_label,99,im->xlab_user.stst,localtime(&tilab));
+       localtime_r(&tilab, &tm);
+       strftime(graph_label,99,im->xlab_user.stst, &tm);
 #else
 # error "your libc has no strftime I guess we'll abort the exercise here."
 #endif
@@ -2192,15 +2207,15 @@ graph_paint(image_desc_t *im, char ***calcpr)
   double areazero = 0.0;
   enum gf_en stack_gf = GF_PRINT;
   graph_desc_t *lastgdes = NULL;    
-  
+
   /* if we are lazy and there is nothing to PRINT ... quit now */
   if (lazy && im->prt_c==0) return 0;
-  
+
   /* pull the data from the rrd files ... */
   
   if(data_fetch(im)==-1)
     return -1;
-  
+
   /* evaluate VDEF and CDEF operations ... */
   if(data_calc(im)==-1)
     return -1;
@@ -2396,14 +2411,11 @@ graph_paint(image_desc_t *im, char ***calcpr)
       /* make sure we do not run into trouble when stacking on NaN */
       for(ii=0;ii<im->xsize;ii++){
         if (isnan(im->gdes[i].p_data[ii])) {
-          double ybase = 0.0;
-          if (lastgdes) {
-            ybase = ytr(im,lastgdes->p_data[ii-1]);
-          };
-          if (isnan(ybase) || !lastgdes ){
-            ybase =  ytr(im,areazero);
+          if (lastgdes && (im->gdes[i].gf == GF_STACK)) {
+            im->gdes[i].p_data[ii] = lastgdes->p_data[ii];
+          } else {
+            im->gdes[i].p_data[ii] =  ytr(im,areazero);
           }
-          im->gdes[i].p_data[ii] = ybase;
         }
       } 
       lastgdes = &(im->gdes[i]);                         
@@ -2470,7 +2482,7 @@ graph_paint(image_desc_t *im, char ***calcpr)
   } else {
     if ((fo = fopen(im->graphfile,"wb")) == NULL) {
       rrd_set_error("Opening '%s' for write: %s",im->graphfile,
-                    strerror(errno));
+                    rrd_strerror(errno));
       return (-1);
     }
   }
@@ -2488,7 +2500,7 @@ graph_paint(image_desc_t *im, char ***calcpr)
 int
 gdes_alloc(image_desc_t *im){
 
-    long def_step = (im->end-im->start)/im->xsize;
+    unsigned long def_step = (im->end-im->start)/im->xsize;
     
     if (im->step > def_step) /* step can be increassed ... no decreassed */
       def_step = im->step;
@@ -2623,7 +2635,7 @@ rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize)
 void
 rrd_graph_init(image_desc_t *im)
 {
-    int i;
+    unsigned int i;
 
 #ifdef HAVE_TZSET
     tzset();
@@ -2707,41 +2719,45 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
            {"lazy",       no_argument,       0,  'z'},
             {"zoom",       required_argument, 0,  'm'},
            {"no-legend",  no_argument,       0,  'g'},
-           {"alt-y-grid", no_argument,       0,   257 },
-           {"alt-autoscale", no_argument,    0,   258 },
-           {"alt-autoscale-max", no_argument,    0,   259 },
-           {"units-exponent",required_argument, 0,  260},
-           {"step",       required_argument, 0,   261},
-           {"no-gridfit", no_argument,       0,   262},
+           {"alt-y-grid", no_argument,       0,  'Y'},
+            {"no-minor",   no_argument,       0,  'I'},
+           {"alt-autoscale", no_argument,    0,  'A'},
+           {"alt-autoscale-max", no_argument, 0, 'M'},
+           {"units-exponent",required_argument, 0, 'X'},
+           {"step",       required_argument, 0,    'S'},
+           {"no-gridfit", no_argument,       0,   'N'},
            {0,0,0,0}};
        int option_index = 0;
        int opt;
 
 
        opt = getopt_long(argc, argv, 
-                         "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:zg",
+                         "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:I:zgYAMX:S:N",
                          long_options, &option_index);
 
        if (opt == EOF)
            break;
        
        switch(opt) {
-       case 257:
+        case 'I':
+            im->extra_flags |= NOMINOR;
+            break;
+       case 'Y':
            im->extra_flags |= ALTYGRID;
            break;
-       case 258:
+       case 'A':
            im->extra_flags |= ALTAUTOSCALE;
            break;
-       case 259:
+       case 'M':
            im->extra_flags |= ALTAUTOSCALE_MAX;
            break;
        case 'g':
            im->extra_flags |= NOLEGEND;
            break;
-       case 260:
+       case 'X':
            im->unitsexponent = atoi(optarg);
            break;
-       case 261:
+       case 'S':
            im->step =  atoi(optarg);
            break;
        case 262: