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

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