core/output.c

Go to the documentation of this file.
00001 
00032 #include <stdlib.h>
00033 #include <stdarg.h>
00034 #include <stdio.h>
00035 #include <errno.h>
00036 #include <string.h>
00037 #include "output.h"
00038 #include "globals.h"
00039 #include "exception.h"
00040 
00041 static char buffer[65536];
00042 #define CHECK 0xcdcd
00043 int overflow=CHECK;
00044 
00048 static struct s_redirection {
00049     FILE *output;
00050     FILE *error;
00051     FILE *warning;
00052     FILE *debug;
00053     FILE *verbose;
00054     FILE *profile;
00055     FILE *progress;
00056 } redirect;
00057 FILE* output_redirect_stream(char *name, FILE *fp)
00058 {
00059     struct {
00060         char *name;
00061         FILE **file;
00062         char *defaultfile;
00063     } map[] = {
00064         {"output",&redirect.output,"gridlabd.out"},
00065         {"error",&redirect.error,"gridlabd.err"},
00066         {"warning",&redirect.warning,"gridlabd.wrn"},
00067         {"debug",&redirect.debug,"gridlabd.dbg"},
00068         {"verbose",&redirect.verbose,"gridlabd.inf"},
00069         {"profile",&redirect.profile,"gridlabd.pro"},
00070         {"progress",&redirect.progress,"gridlabd.prg"},
00071     };
00072     int i;
00073     for (i=0; i<sizeof(map)/sizeof(map[0]); i++) 
00074     {
00075         if (strcmp(name,map[i].name)==0)
00076         {
00077             char *mode = "w";
00078             FILE *oldfp = *(map[i].file);
00079             *(map[i].file) = fp;
00080 #ifndef WIN32
00081             if (*(map[i].file))
00082                 setlinebuf(*(map[i].file));
00083 #endif
00084             return oldfp;
00085         }
00086     }
00087     return NULL;
00088 }
00089 
00090 void (*notify_error)(void) = NULL;
00091 int output_notify_error(void (*notify)(void))
00092 {
00093     notify_error = notify;
00094     return 0;
00095 }
00096 
00097 FILE* output_redirect(char *name, char *path)
00098 {
00099     struct {
00100         char *name;
00101         FILE **file;
00102         char *defaultfile;
00103     } map[] = {
00104         {"output",&redirect.output,"gridlabd.out"},
00105         {"error",&redirect.error,"gridlabd.err"},
00106         {"warning",&redirect.warning,"gridlabd.wrn"},
00107         {"debug",&redirect.debug,"gridlabd.dbg"},
00108         {"verbose",&redirect.verbose,"gridlabd.inf"},
00109         {"profile",&redirect.profile,"gridlabd.pro"},
00110         {"progress",&redirect.progress,"gridlabd.prg"},
00111     };
00112     int i;
00113     for (i=0; i<sizeof(map)/sizeof(map[0]); i++) 
00114     {
00115         if (strcmp(name,map[i].name)==0)
00116         {
00117             char *mode = "w";
00118             if (*(map[i].file)!=NULL)
00119                 fclose(*(map[i].file));
00120             
00121             /* test for append mode, path led with + */
00122             if (path != NULL && path[0]=='+')
00123             {   mode = "a";
00124                 path++;
00125             }
00126             *(map[i].file) = fopen(path?path:map[i].defaultfile,"w");
00127 #ifndef WIN32
00128             if (*(map[i].file))
00129                 setlinebuf(*(map[i].file));
00130 #endif
00131             return *(map[i].file);
00132         }
00133     }
00134     return NULL;
00135 }
00136 
00140 static FILE *curr_stream[3] = {NULL, NULL, NULL};
00141 static int stream_prep = 0;
00142 static void prep_stream(){
00143     if(stream_prep)
00144         return;
00145     stream_prep = 1;
00146     if(curr_stream[FS_IN] == NULL){
00147         curr_stream[FS_IN] = stdin;
00148 #ifdef DEBUG
00149         if (global_verbose_mode) printf("    ... prep_stream() set FS_IN to stdin\n");
00150 #endif
00151     }
00152     if(curr_stream[FS_STD] == NULL){
00153         curr_stream[FS_STD] = stdout;
00154 #ifdef DEBUG
00155         if (global_verbose_mode) printf("    ... prep_stream() set FS_STD to stdout\n");
00156 #endif
00157     }
00158     if(curr_stream[FS_ERR] == NULL){
00159         curr_stream[FS_ERR] = stderr;
00160 #ifdef DEBUG
00161         if (global_verbose_mode) printf("    ... prep_stream() set FS_ERR to stderr\n");
00162 #endif
00163     }
00164     return;
00165 }
00166 
00167 static int default_printstd(char *format,...)
00168 {
00169     int count;
00170     va_list ptr;
00171     prep_stream();
00172     va_start(ptr,format);
00173     count = vfprintf(curr_stream[FS_STD],format,ptr);
00174     va_end(ptr);
00175     return count;
00176 }
00177 
00178 static int default_printerr(char *format,...)
00179 {
00180     int count;
00181     va_list ptr;
00182     prep_stream();
00183     va_start(ptr,format);
00184     count = vfprintf(curr_stream[FS_ERR],format,ptr);
00185     va_end(ptr);
00186     fflush(curr_stream[FS_ERR]);
00187     return count;
00188 }
00189 
00190 FILE *output_set_stream(FILESTREAM fs, FILE *newfp){
00191     FILE *oldfp = curr_stream[fs];
00192     if(fs > FS_ERR) /* input check */
00193         return NULL;
00194     if(newfp == NULL)
00195         return NULL;
00196     curr_stream[fs] = newfp;
00197     return oldfp;
00198 }
00199 
00200 static PRINTFUNCTION printstd=default_printstd, printerr=default_printerr;
00201 
00208 PRINTFUNCTION output_set_stdout(PRINTFUNCTION call) 
00209 {
00210     PRINTFUNCTION old = printstd;
00211     printstd = call;
00212     return old;
00213 }
00214 
00221 PRINTFUNCTION output_set_stderr(PRINTFUNCTION call) 
00222 {
00223     PRINTFUNCTION old = printerr;
00224     printerr = call;
00225     return old;
00226 }
00227 
00234 int output_fatal(char *format,...) 
00235 {
00236     va_list ptr;
00237 
00238     va_start(ptr,format);
00239     vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00240     va_end(ptr);
00241 
00242     if (redirect.error)
00243         return fprintf(redirect.error,"FATAL: %s\n",buffer);
00244     else
00245         return (*printerr)("FATAL: %s\n",buffer);
00246 }
00247 
00254 int output_error(char *format,...) 
00255 {
00256     va_list ptr;
00257 
00258     va_start(ptr,format);
00259     vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00260     va_end(ptr);
00261 
00262     if (notify_error!=NULL)
00263         (*notify_error)();
00264 
00265     if (redirect.error)
00266         return fprintf(redirect.error,"ERROR: %s\n",buffer);
00267     else
00268         return (*printerr)("ERROR: %s\n",buffer);
00269 }
00270 
00277 int output_test(char *format,...) 
00278 {
00279     static FILE *fp = NULL;
00280     char minor_b[32], major_b[32];
00281     va_list ptr;
00282 
00283     va_start(ptr,format);
00284     vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00285     va_end(ptr);
00286 
00287     if (fp==NULL)
00288     {
00289         time_t now = time(NULL);
00290         fp = fopen(global_getvar("testoutputfile", NULL, 0), "w"); /* new style - mh*/
00291         /* fp = fopen(global_testoutputfile,"w"); */ /* old style -mh */
00292         if (fp==NULL)
00293         {
00294             /* can't write to output file, write to stderr instead */
00295             return (*printerr)("TEST: %s\n",buffer);
00296         }
00297         /* fprintf(fp,"GridLAB-D Version %d.%d\n", global_version_major, global_version_minor); */
00298         fprintf(fp,"GridLAB-D Version %s.%s\n", global_getvar("version.major", major_b, 32), global_getvar("version.minor", minor_b, 32));
00299         fprintf(fp,"Test results from run started %s", asctime(localtime(&now)));
00300         fprintf(fp,"Command line: %s\n", global_getvar("command_line", NULL, 0));
00301     }
00302 
00303     return fprintf(fp,"%s\n", buffer);
00304 }
00305 
00312 int output_warning(char *format,...) 
00313 {
00314     if (global_warn_mode)
00315     {
00316         va_list ptr;
00317 
00318         va_start(ptr,format);
00319         vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00320         va_end(ptr);
00321 
00322         if (redirect.warning)
00323             return fprintf(redirect.warning,"WARNING: %s\n",buffer);
00324         else
00325             return (*printerr)("WARNING: %s\n",buffer);
00326     }
00327     return 0;
00328 }
00329 
00336 int output_debug(char *format,...) 
00337 {
00338     if (global_debug_output)
00339     {
00340         va_list ptr;
00341 
00342         va_start(ptr,format);
00343         vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00344         va_end(ptr);
00345 
00346         if (redirect.debug)
00347             return fprintf(redirect.debug,"DEBUG: %s\n",buffer);
00348         else
00349             return (*printerr)("DEBUG: %s\n",buffer);
00350     }
00351     return 0;
00352 }
00353 
00361 int output_verbose(char *format,...) 
00362 {
00363     if (global_verbose_mode)
00364     {
00365         va_list ptr;
00366 
00367         va_start(ptr,format);
00368         vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00369         va_end(ptr);
00370 
00371         if (redirect.verbose)
00372             return fprintf(redirect.verbose,"   ... %s\n",buffer);
00373         else
00374             return (*printerr)("    ... %s\n",buffer);
00375     }
00376     return 0;
00377 }
00383 int output_message(char *format,...) 
00384 {
00385     if (!global_quiet_mode)
00386     {
00387         va_list ptr;
00388 
00389         va_start(ptr,format);
00390         vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00391         va_end(ptr);
00392 
00393             if (redirect.output)
00394                 return fprintf(redirect.output,"%s\n",buffer);
00395             else
00396                 return (*printstd)("%s\n",buffer);
00397     }
00398     return 0;
00399 }
00400 
00403 int output_profile(char *format, ...) 
00404 {
00405     char tmp[1024];
00406     va_list ptr;
00407 
00408     va_start(ptr,format);
00409     vsprintf(tmp,format,ptr);
00410     va_end(ptr);
00411 
00412     if (redirect.profile!=NULL)
00413         return fprintf(redirect.profile,"%s\n",tmp);
00414     else
00415         return output_message("%s",tmp);
00416 }
00417 
00420 int output_progress()
00421 {
00422     char buffer[64];
00423     int res = 0;
00424     char *ts = convert_from_timestamp(global_clock,buffer,sizeof(buffer))>0?buffer:"(invalid)";
00425     if (redirect.progress)
00426     {
00427         res = fprintf(redirect.progress,"%s\n",ts);
00428         fflush(redirect.progress);
00429     }
00430     else if (global_keep_progress)
00431         res = output_message("Processing %s...", ts);
00432     else
00433     {
00434         static int len=0;
00435         int i=len, slen = (int)strlen(ts)+15;
00436         while (i--) putchar(' ');
00437         putchar('\r');
00438         if (slen>len) len=slen;
00439         res = output_raw("Processing %s...\r", ts);
00440     }
00441     return res;
00442 }
00443 
00449 int output_raw(char *format,...) 
00450 {
00451     if (!global_quiet_mode)
00452     {
00453         va_list ptr;
00454 
00455         va_start(ptr,format);
00456         vsprintf(buffer,format,ptr); /* note the lack of check on buffer overrun */
00457         va_end(ptr);
00458 
00459             if (redirect.output)
00460             {   int len = fprintf(redirect.output,"%s",buffer);
00461                 fflush(redirect.output);
00462                 return len;
00463             }
00464             else
00465                 return (*printerr)("%s",buffer);
00466     }
00467     return 0;
00468 }
00469 
00470 #include "module.h"
00471 
00473 int output_xsd(char *spec)
00474 {
00475     MODULE *mod = NULL;
00476     CLASS *oclass = NULL;
00477     char modulename[1024], classname[1024];
00478     char buffer[65536];
00479     /*if(sscanf(spec, "%[A-Za-z_0-9]::%[A-Za-z_0-9]:%s",modulename, submodulename, classname) == 3)
00480     {
00481         sprintf(jointname, "%s::%s", modulename, submodulename);
00482         mod = module_load(jointname, 0, NULL);
00483         if(mod == NULL){
00484             output_error("unable to load parent module %s", modulename);
00485             return 0;
00486         }
00487         
00488     }
00489     else if(sscanf(spec, "%[A-Za-z_0-9]::%[A-Za-z_0-9]",modulename, submodulename) == 2)
00490     {
00491         sprintf(jointname, "%s::%s", modulename, submodulename);
00492         mod = module_load(jointname, 0, NULL);
00493         if(mod == NULL){
00494             output_error("unable to load parent module %s", modulename);
00495             return 0;
00496         }
00497     }
00498     else */if (sscanf(spec,"%[A-Za-z_0-9]:%s",modulename,classname)<1)
00499     {
00500         output_error("improperly formatted XSD dump specification");
00501         return 0;
00502     }
00503     if (mod == NULL)
00504         mod = module_load(modulename,0,NULL);
00505     if (mod==NULL)
00506     {
00507         output_error("unable to find module '%s'", spec);
00508         return 0;
00509     }
00510     if (classname[0]!='\0' && (oclass=class_get_class_from_classname(classname))==NULL)
00511     {
00512         output_error("unable to find class '%s' in module '%s'", classname, modulename);
00513         return 0;
00514     }
00515     //if ((strlen(submodulename) > 1))
00516     //  strcpy(modulename, submodulename);
00517     output_message("<?xml version=\"1.0\" encoding=\"utf-%d\"?>",global_xml_encoding);
00518     output_message("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://www.w3.org/\" xmlns=\"http://www.w3.org/\" elementFormDefalt=\"qualified\">\n");
00519     for (oclass=(classname[0]!='\0'?oclass:class_get_first_class()); oclass!=NULL; oclass=oclass->next) 
00520     {
00521         if (class_get_xsd(oclass,buffer,sizeof(buffer))<=0)
00522         {
00523             output_error("unable to convert class '%s' to XSD", oclass->name);
00524             return 0;
00525         }
00526         output_message(buffer);
00527         if (classname[0]!='\0') 
00528             break;
00529     }
00530     output_message("</xs:schema>\n");
00531     return 0;
00532 }
00533 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy