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
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)
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);
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);
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);
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");
00291
00292 if (fp==NULL)
00293 {
00294
00295 return (*printerr)("TEST: %s\n",buffer);
00296 }
00297
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);
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);
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);
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);
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);
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
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 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
00516
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