reset optind opterr inside the function calls ...
[rrdtool.git] / bindings / perl-shared / RRDs.xs
1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8
9 #ifdef __cplusplus
10 }
11 #endif
12
13 #include "../../src/rrd_tool.h"
14
15 /* perl 5.004 compatibility */
16 #if PERLPATCHLEVEL < 5 
17 #define PL_sv_undef sv_undef
18 #endif
19
20
21 #define rrdcode(name) \
22                 argv = (char **) malloc((items+1)*sizeof(char *));\
23                 argv[0] = "dummy";\
24                 for (i = 0; i < items; i++) { \
25                     STRLEN len; \
26                     char *handle= SvPV(ST(i),len);\
27                     /* actually copy the data to make sure possible modifications \
28                        on the argv data does not backfire into perl */ \
29                     argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); \
30                     strcpy(argv[i+1],handle); \
31                 } \
32                 rrd_clear_error();\
33                 RETVAL=name(items+1,argv); \
34                 for (i=0; i < items; i++) {\
35                     free(argv[i+1]);\
36                 } \
37                 free(argv);\
38                 \
39                 if (rrd_test_error()) XSRETURN_UNDEF;
40
41 #define hvs(VAL) hv_store_ent(hash, sv_2mortal(newSVpv(data->key,0)),VAL,0)                 
42
43 #define rrdinfocode(name) \
44                 /* prepare argument list */ \
45                 argv = (char **) malloc((items+1)*sizeof(char *)); \
46                 argv[0] = "dummy"; \
47                 for (i = 0; i < items; i++) { \
48                     STRLEN len; \
49                     char *handle= SvPV(ST(i),len); \
50                     /* actually copy the data to make sure possible modifications \
51                        on the argv data does not backfire into perl */ \
52                     argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); \
53                     strcpy(argv[i+1],handle); \
54                 } \
55                 rrd_clear_error(); \
56                 data=name(items+1, argv); \
57                 for (i=0; i < items; i++) { \
58                     free(argv[i+1]); \
59                 } \
60                 free(argv); \
61                 if (rrd_test_error()) XSRETURN_UNDEF; \
62                 hash = newHV(); \
63                 while (data) { \
64                     save=data; \
65                 /* the newSV will get copied by hv so we create it as a mortal \
66            to make sure it does not keep hanging round after the fact */ \
67                     switch (data->type) { \
68                     case RD_I_VAL: \
69                         if (isnan(data->value.u_val)) \
70                             hvs(&PL_sv_undef); \
71                         else \
72                             hvs(newSVnv(data->value.u_val)); \
73                         break; \
74                         case RD_I_INT: \
75                         hvs(newSViv(data->value.u_int)); \
76                         break; \
77                     case RD_I_CNT: \
78                         hvs(newSViv(data->value.u_cnt)); \
79                         break; \
80                     case RD_I_STR: \
81                         hvs(newSVpv(data->value.u_str,0)); \
82                         rrd_freemem(data->value.u_str); \
83                         break; \
84                     } \
85                     rrd_freemem(data->key); \
86                     data = data->next; \
87                     rrd_freemem(save); \
88                     } \
89             rrd_freemem(data); \
90             RETVAL = newRV_noinc((SV*)hash);
91
92 /*
93  * should not be needed if libc is linked (see ntmake.pl)
94 #ifdef WIN32
95  #define free free
96  #define malloc malloc
97  #define realloc realloc
98 #endif
99 */
100
101
102 MODULE = RRDs   PACKAGE = RRDs  PREFIX = rrd_
103
104 BOOT:
105 #ifdef MUST_DISABLE_SIGFPE
106         signal(SIGFPE,SIG_IGN);
107 #endif
108 #ifdef MUST_DISABLE_FPMASK
109         fpsetmask(0);
110 #endif 
111         
112
113 SV*
114 rrd_error()
115         CODE:
116                 if (! rrd_test_error()) XSRETURN_UNDEF;
117                 RETVAL = newSVpv(rrd_get_error(),0);
118         OUTPUT:
119                 RETVAL
120
121         
122 int
123 rrd_last(...)
124       PROTOTYPE: @
125       PREINIT:
126       int i;
127       char **argv;
128       CODE:
129               rrdcode(rrd_last);
130       OUTPUT:
131             RETVAL
132
133 int
134 rrd_first(...)
135       PROTOTYPE: @
136       PREINIT:
137       int i;
138       char **argv;
139       CODE:
140               rrdcode(rrd_first);
141       OUTPUT:
142             RETVAL
143
144
145 int
146 rrd_create(...)
147         PROTOTYPE: @    
148         PREINIT:
149         int i;
150         char **argv;
151         CODE:
152                 rrdcode(rrd_create);
153                 RETVAL = 1;
154         OUTPUT:
155                 RETVAL
156
157
158 int
159 rrd_update(...)
160         PROTOTYPE: @    
161         PREINIT:
162         int i;
163         char **argv;
164         CODE:
165                 rrdcode(rrd_update);
166                 RETVAL = 1;
167         OUTPUT:
168                 RETVAL
169
170
171 int
172 rrd_tune(...)
173         PROTOTYPE: @    
174         PREINIT:
175         int i;
176         char **argv;
177         CODE:
178                 rrdcode(rrd_tune);
179                 RETVAL = 1;
180         OUTPUT:
181                 RETVAL
182
183
184 void
185 rrd_graph(...)
186         PROTOTYPE: @    
187         PREINIT:
188         char **calcpr=NULL;
189         int i,xsize,ysize;
190         double ymin,ymax;
191         char **argv;
192         AV *retar;
193         PPCODE:
194                 argv = (char **) malloc((items+1)*sizeof(char *));
195                 argv[0] = "dummy";
196                 for (i = 0; i < items; i++) { 
197                     STRLEN len;
198                     char *handle = SvPV(ST(i),len);
199                     /* actually copy the data to make sure possible modifications
200                        on the argv data does not backfire into perl */ 
201                     argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
202                     strcpy(argv[i+1],handle);
203                 }
204                 rrd_clear_error();
205                 rrd_graph(items+1,argv,&calcpr,&xsize,&ysize,NULL,&ymin,&ymax); 
206                 for (i=0; i < items; i++) {
207                     free(argv[i+1]);
208                 }
209                 free(argv);
210
211                 if (rrd_test_error()) {
212                         if(calcpr)
213                            for(i=0;calcpr[i];i++)
214                                 rrd_freemem(calcpr[i]);
215                         XSRETURN_UNDEF;
216                 }
217                 retar=newAV();
218                 if(calcpr){
219                         for(i=0;calcpr[i];i++){
220                                  av_push(retar,newSVpv(calcpr[i],0));
221                                  rrd_freemem(calcpr[i]);
222                         }
223                         rrd_freemem(calcpr);
224                 }
225                 EXTEND(sp,4);
226                 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
227                 PUSHs(sv_2mortal(newSViv(xsize)));
228                 PUSHs(sv_2mortal(newSViv(ysize)));
229
230 void
231 rrd_fetch(...)
232         PROTOTYPE: @    
233         PREINIT:
234                 time_t        start,end;                
235                 unsigned long step, ds_cnt,i,ii;
236                 rrd_value_t   *data,*datai;
237                 char **argv;
238                 char **ds_namv;
239                 AV *retar,*line,*names;
240         PPCODE:
241                 argv = (char **) malloc((items+1)*sizeof(char *));
242                 argv[0] = "dummy";
243                 for (i = 0; i < items; i++) { 
244                     STRLEN len;
245                     char *handle= SvPV(ST(i),len);
246                     /* actually copy the data to make sure possible modifications
247                        on the argv data does not backfire into perl */ 
248                     argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
249                     strcpy(argv[i+1],handle);
250                 }
251                 rrd_clear_error();
252                 rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data); 
253                 for (i=0; i < items; i++) {
254                     free(argv[i+1]);
255                 }
256                 free(argv);
257                 if (rrd_test_error()) XSRETURN_UNDEF;
258                 /* convert the ds_namv into perl format */
259                 names=newAV();
260                 for (ii = 0; ii < ds_cnt; ii++){
261                     av_push(names,newSVpv(ds_namv[ii],0));
262                     rrd_freemem(ds_namv[ii]);
263                 }
264                 rrd_freemem(ds_namv);                   
265                 /* convert the data array into perl format */
266                 datai=data;
267                 retar=newAV();
268                 for (i = start+step; i <= end; i += step){
269                         line = newAV();
270                         for (ii = 0; ii < ds_cnt; ii++){
271                           av_push(line,(isnan(*datai) ? &PL_sv_undef : newSVnv(*datai)));
272                           datai++;
273                         }
274                         av_push(retar,newRV_noinc((SV*)line));
275                 }
276                 rrd_freemem(data);
277                 EXTEND(sp,5);
278                 PUSHs(sv_2mortal(newSViv(start+step)));
279                 PUSHs(sv_2mortal(newSViv(step)));
280                 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
281                 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
282
283 void
284 rrd_times(start, end)
285           char *start
286           char *end
287         PREINIT:
288                 struct  rrd_time_value start_tv, end_tv;
289                 char    *parsetime_error = NULL;
290                 time_t  start_tmp, end_tmp;
291         PPCODE:
292                 rrd_clear_error();
293                 if( (parsetime_error = parsetime( start, &start_tv))) {
294                         rrd_set_error( "start time: %s", parsetime_error);
295                         XSRETURN_UNDEF;
296                 }
297                 if( (parsetime_error = parsetime( end, &end_tv))) {
298                         rrd_set_error( "end time: %s", parsetime_error);
299                         XSRETURN_UNDEF;
300                 }
301                 if( proc_start_end( &start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
302                         XSRETURN_UNDEF;
303                 }
304                 EXTEND(sp,2);
305                 PUSHs(sv_2mortal(newSVuv(start_tmp)));
306                 PUSHs(sv_2mortal(newSVuv(end_tmp)));
307
308 int
309 rrd_xport(...)
310         PROTOTYPE: @    
311         PREINIT:
312                 time_t start,end;               
313                 int xsize;
314                 unsigned long step, col_cnt,row_cnt,i,ii;
315                 rrd_value_t *data,*ptr;
316                 char **argv,**legend_v;
317                 AV *retar,*line,*names;
318         PPCODE:
319                 argv = (char **) malloc((items+1)*sizeof(char *));
320                 argv[0] = "dummy";
321                 for (i = 0; i < items; i++) { 
322                     STRLEN len;
323                     char *handle = SvPV(ST(i),len);
324                     /* actually copy the data to make sure possible modifications
325                        on the argv data does not backfire into perl */ 
326                     argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
327                     strcpy(argv[i+1],handle);
328                 }
329                 rrd_clear_error();
330                 rrd_xport(items+1,argv,&xsize,&start,&end,&step,&col_cnt,&legend_v,&data); 
331                 for (i=0; i < items; i++) {
332                     free(argv[i+1]);
333                 }
334                 free(argv);
335                 if (rrd_test_error()) XSRETURN_UNDEF;
336
337                 /* convert the legend_v into perl format */
338                 names=newAV();
339                 for (ii = 0; ii < col_cnt; ii++){
340                     av_push(names,newSVpv(legend_v[ii],0));
341                     rrd_freemem(legend_v[ii]);
342                 }
343                 rrd_freemem(legend_v);                  
344
345                 /* convert the data array into perl format */
346                 ptr=data;
347                 retar=newAV();
348                 for (i = start+step; i <= end; i += step){
349                         line = newAV();
350                         for (ii = 0; ii < col_cnt; ii++){
351                           av_push(line,(isnan(*ptr) ? &PL_sv_undef : newSVnv(*ptr)));
352                           ptr++;
353                         }
354                         av_push(retar,newRV_noinc((SV*)line));
355                 }
356                 rrd_freemem(data);
357
358                 EXTEND(sp,7);
359                 PUSHs(sv_2mortal(newSViv(start+step)));
360                 PUSHs(sv_2mortal(newSViv(end)));
361                 PUSHs(sv_2mortal(newSViv(step)));
362                 PUSHs(sv_2mortal(newSViv(col_cnt)));
363                 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
364                 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
365
366 SV*
367 rrd_info(...)
368         PROTOTYPE: @    
369         PREINIT:
370                 info_t *data,*save;
371                 int i;
372                 char **argv;
373                 HV *hash;
374         CODE:
375                 rrdinfocode(rrd_info);  
376     OUTPUT:
377            RETVAL
378
379 SV*
380 rrd_updatev(...)
381         PROTOTYPE: @    
382         PREINIT:
383                 info_t *data,*save;
384                 int i;
385                 char **argv;
386                 HV *hash;
387         CODE:
388                 rrdinfocode(rrd_update_v);      
389     OUTPUT:
390            RETVAL
391
392 int
393 rrd_dump(...)
394        PROTOTYPE: @
395        PREINIT:
396         int i;
397        char **argv;
398        CODE:
399                rrdcode(rrd_dump);
400                        RETVAL = 1;
401        OUTPUT:
402                RETVAL
403
404 int
405 rrd_restore(...)
406        PROTOTYPE: @
407        PREINIT:
408         int i;
409        char **argv;
410        CODE:
411                rrdcode(rrd_restore);
412                        RETVAL = 1;
413        OUTPUT:
414                RETVAL
415