STATUS load_module_list(FILE *fd,int* test_mod_num) { /* sprintf(mod_test,"mod_test%d=%s",test_mod_num++,*++argv); if (global_setvar(mod_test)==SUCCESS) */ char mod_test[100]; char line[100]; while(fscanf(fd,"%s",line) != EOF) { printf("Line: %s",line); sprintf(mod_test,"mod_test%d=%s",(*test_mod_num)++,line); if (global_setvar(mod_test)!=SUCCESS) { output_fatal("Unable to store module name"); /* TROUBLESHOOT This error is caused by a failure to set up a module test, which requires that the name module being tested be stored in a global variable called mod_test<num>. The root cause will be identified by determining what error in the global_setvar call occurred. */ return FAILED; } } return SUCCESS; }
STATUS test_start(int argc, char *argv[]) { int mod_test_num = 1; char mod_test[100]; char *mod_name; int test_result = 0; sprintf(mod_test,"mod_test%d",mod_test_num++); mod_name = global_getvar(mod_test, NULL, 0); module_load("tape",argc,argv); while(mod_name != NULL) { MODULE *mod = module_load(mod_name,argc,argv); if(mod == NULL) { output_fatal("Invalid module name"); /* TROUBLESHOOT The test_start procedure was given an invalid module name. Check the command line argument and/or the unit test sequence to be sure the test is requested properly. */ return FAILED; } if (mod->module_test==NULL) { output_fatal("Module %s does not implement cppunit test", mod->name); /* TROUBLESHOOT The test_start procedure was given the name of a module that doesn't implement unit testing. Check the command line argument and/or the test configuration file to be sure the test is requested properly. */ return FAILED; } test_result = mod->module_test(&callbacks,argc,argv); if(test_result == 0) return FAILED; sprintf(mod_test,"mod_test%d",mod_test_num++); mod_name = global_getvar(mod_test, NULL, 0); } return SUCCESS; }
/** Creates an exception handler for use in a try block @return a pointer to an EXCEPTIONHANDLER structure **/ EXCEPTIONHANDLER *create_exception_handler(void) { EXCEPTIONHANDLER *ptr = malloc(sizeof(EXCEPTIONHANDLER)); if(ptr == NULL){ output_fatal("create_exception_handler(): malloc failure"); return NULL; } ptr->next = handlers; ptr->id = (handlers==NULL?0:handlers->id)+1; memset(ptr->msg,0,sizeof(ptr->msg)); handlers = ptr; return ptr; }
/** Deletes an exception handler from the handler list **/ void delete_exception_handler(EXCEPTIONHANDLER *ptr) /**< a pointer to the exception handler */ { EXCEPTIONHANDLER *target; if(ptr == NULL){ output_fatal("delete_exception_handler(): ending an exception handler block where no exception handler was present"); return; } target = ptr->next; while (handlers!=target) { ptr = handlers; handlers=ptr->next; free(ptr); ptr = NULL; /* if(handlers == NULL) break; */ } }
/** The main entry point of GridLAB-D Exit codes - \b 0 run completed ok - \b 1 command-line processor stopped - \b 2 environment startup failed - \b 3 test procedure failed - \b 4 user rejects conditions of use - \b 5 simulation stopped before completing - \b 6 initialization failed **/ int main(int argc, /**< the number entries on command-line argument list \p argv */ char *argv[]) /**< a list of pointers to the command-line arguments */ { int rv = 0; time_t t_load = time(NULL); global_process_id = getpid(); #if defined WIN32 && _DEBUG atexit(pause_at_exit); #endif /* main initialization */ if (!output_init(argc,argv) || !exec_init()) exit(6); /* process command line arguments */ if (cmdarg_load(argc,argv)==FAILED) { output_fatal("shutdown after command line rejected"); /* TROUBLESHOOT The command line is not valid and the system did not complete its startup procedure. Correct the problem with the command line and try again. */ exit(1); } /* setup the random number generator */ random_init(); /* pidfile */ if (strcmp(global_pidfile,"")!=0) { FILE *fp = fopen(global_pidfile,"w"); if (fp==NULL) { output_fatal("unable to create pidfile '%s'", global_pidfile); /* TROUBLESHOOT The system must allow creation of the process id file at the location indicated in the message. Create and/or modify access rights to the path for that file and try again. */ exit(1); } #ifdef WIN32 #define getpid _getpid #endif fprintf(fp,"%d\n",getpid()); output_verbose("process id %d written to %s", getpid(), global_pidfile); fclose(fp); atexit(delete_pidfile); } /* do legal stuff */ #ifdef LEGAL_NOTICE if (strcmp(global_pidfile,"")==0 && legal_notice()==FAILED) exit(4); #endif /* set up the test */ if (global_test_mode) { #ifndef _NO_CPPUNIT output_message("Entering test mode"); if (test_start(argc,argv)==FAILED) { output_fatal("shutdown after startup test failed"); /* TROUBLESHOOT A self-test procedure failed and the system stopped. Check the output of the test stream and correct the indicated problem. If the test stream is not redirected so as to save the output, try using the <b>--redirect</b> command line option. */ exit(3); } exit(0); /* There is no environment to speak of, so exit. */ #else output_message("Unit Tests not enabled. Recompile with _NO_CPPUNIT unset"); #endif } /* start the processing environment */ output_verbose("load time: %d sec", time(NULL) - t_load); output_verbose("starting up %s environment", global_environment); if (environment_start(argc,argv)==FAILED) { output_fatal("environment startup failed: %s", strerror(errno)); /* TROUBLESHOOT The requested environment could not be started. This usually follows a more specific message regarding the startup problem. Follow the recommendation for the indicated problem. */ rv = 2; } /* post process the test */ if (global_test_mode) { #ifndef _NO_CPPUNIT output_message("Exiting test mode"); if (test_end(argc,argv)==FAILED) { output_error("shutdown after end test failed"); exit(3); } #endif } /* save the model */ if (strcmp(global_savefile,"")!=0) { if (saveall(global_savefile)==FAILED) output_error("save to '%s' failed", global_savefile); } /* do module dumps */ if (global_dumpall!=FALSE) { output_verbose("dumping module data"); module_dumpall(); } /* KML output */ if (strcmp(global_kmlfile,"")!=0) kml_dump(global_kmlfile); /* wrap up */ output_verbose("shutdown complete"); /* profile results */ if (global_profiler) class_profiles(); /* restore locale */ locale_pop(); /* compute elapsed runtime */ output_verbose("elapsed runtime %d seconds", realtime_runtime()); exit(rv); }
/** Load and process the command-line arguments @return a STATUS value Arguments are processed immediately as they are seen. This means that models are loaded when they are encountered, and in relation to the other flags. Thus @code gridlabd --warn model1 --warn model2 @endcode will load \p model1 with warnings on, and \p model2 with warnings off. **/ STATUS cmdarg_load(int argc, /**< the number of arguments in \p argv */ char *argv[]) /**< a list pointers to the argument string */ { int test_mod_num = 1; unsigned int pos=0; int i; char *pd1, *pd2; /* capture the execdir */ strcpy(global_execname,argv[0]); strcpy(global_execdir,argv[0]); pd1 = strrchr(global_execdir,'/'); pd2 = strrchr(global_execdir,'\\'); if (pd1>pd2) *pd1='\0'; else if (pd2>pd1) *pd2='\0'; /* capture the command line */ for (i=0; i<argc; i++) { if (pos<sizeof(global_command_line)-strlen(argv[i])) pos += sprintf(global_command_line+pos,"%s%s",pos>0?" ":"",argv[i]); } while (argv++,--argc>0) { if (strcmp(*argv,"--copyright")==0) legal_notice(); else if (strcmp(*argv,"-w")==0 || strcmp(*argv,"--warn")==0) global_warn_mode=!global_warn_mode; else if (strcmp(*argv,"--bothstdout")==0) output_both_stdout(); else if (strcmp(*argv,"-c")==0 || strcmp(*argv,"--check")==0) global_runchecks=!global_runchecks; else if (strcmp(*argv,"--debug")==0) global_debug_output=!global_debug_output; else if (strcmp(*argv,"--debugger")==0){ global_debug_mode=1; global_debug_output=!global_debug_output; } else if (strcmp(*argv,"--dumpall")==0) global_dumpall=!global_dumpall; else if (strcmp(*argv,"-q")==0 || strcmp(*argv,"--quiet")==0) global_quiet_mode=!global_quiet_mode; else if (strcmp(*argv,"-v")==0 || strcmp(*argv,"--verbose")==0){ global_verbose_mode=!global_verbose_mode; } else if (strcmp(*argv,"--profile")==0) global_profiler=!global_profiler; else if (strcmp(*argv,"--pause")==0) global_pauseatexit=!global_pauseatexit; else if (strcmp(*argv,"--compile")==0) global_compileonly = !global_compileonly; else if (strcmp(*argv,"--license")==0) legal_license(); else if (strcmp(*argv,"--server_portnum")==0 || strcmp(*argv,"-P")==0) { if (argc-1>0) global_server_portnum = (argc--,atoi(*++argv)); else { output_fatal("missing server port number"); /* TROUBLESHOOT The <b>-P</b> or <b>--server_portnum</b> command line directive was not followed by a valid number. The correct syntax is <b>-P <i>number</i></b> or <b>--server_portnum <i>number</i></b>. */ } } else if (strcmp(*argv, "-V")==0 ||strcmp(*argv, "--version")==0) { char *buildinfo = strstr(BUILD,":"); int build = buildinfo ? atoi(strstr(BUILD,":")+1) : 0; output_message("Revision major: %d", REV_MAJOR); output_message("Revision minor: %d", REV_MINOR); output_message("Patch number : %d", REV_PATCH); output_message("Branch name : %s", BRANCH); if (build>0) output_message("Build number : %d", build); else output_message("Build number : %s", #ifdef WIN32 #ifdef _DEBUG #ifdef _M_X64 "WIN64-DEBUG" #else "WIN32-DEBUG" #endif #else #ifdef _M_X64 "WIN64-RELEASE" #else "WIN32-RELEASE" #endif #endif #else "DEV" #endif ); } else if (strcmp(*argv,"--dsttest")==0) timestamp_test(); else if (strcmp(*argv,"--randtest")==0) random_test(); else if (strcmp(*argv,"--unitstest")==0) unit_test(); else if (strcmp(*argv,"--scheduletest")==0) schedule_test(); else if (strcmp(*argv,"--loadshapetest")==0) loadshape_test(); else if (strcmp(*argv,"--endusetest")==0) enduse_test(); else if (strcmp(*argv,"--xmlstrict")==0) global_xmlstrict = !global_xmlstrict; else if (strcmp(*argv,"--globaldump")==0) { global_dump(); exit(0); } else if (strcmp(*argv,"--relax")==0) global_strictnames = FALSE; else if (strncmp(*argv,"--pidfile",9)==0) { char *filename = strchr(*argv,'='); if (filename==NULL) strcpy(global_pidfile,"gridlabd.pid"); else strcpy(global_pidfile,filename+1); } else if (strncmp(*argv,"--kml",5)==0) { char *filename = strchr(*argv,'='); if (filename) strcpy(global_kmlfile,filename+1); else strcpy(global_kmlfile,"gridlabd.kml"); } else if (strcmp(*argv, "--avlbalance") == 0){ global_no_balance = !global_no_balance; } else if (strcmp(*argv,"--testall")==0){ FILE *fd = NULL; if(*++argv != NULL) fd = fopen(*argv,"r"); else { output_fatal("no filename for testall"); /* TROUBLESHOOT The --testall parameter was found on the command line, but if was not followed by a filename containing the test description file. */ return FAILED; } argc--; global_test_mode=TRUE; if(fd == NULL) { output_fatal("incorrect module list file name"); /* TROUBLESHOOT The --testall parameter was found on the command line, but if was not followed by a valid filename containing the test description file. */ return FAILED; } if(load_module_list(fd,&test_mod_num) == FAILED) return FAILED; } else if (strcmp(*argv,"--modhelp")==0) { if(argc-1 > 0){ MODULE *mod = NULL; CLASS *oclass = NULL; argv++; argc--; if(strchr(argv[0], ':') == 0){ // no class mod = module_load(argv[0],0,NULL); } else { GLOBALVAR *var=NULL; char *cname; cname = strchr(argv[0], ':')+1; mod = module_load(strtok(argv[0],":"),0,NULL); oclass = class_get_class_from_classname(cname); if(oclass == NULL){ output_fatal("Unable to find class '%s' in module '%s'", cname, argv[0]); /* TROUBLESHOOT The <b>--modhelp</b> parameter was found on the command line, but if was followed by a class specification that isn't valid. Verify that the class exists in the module you specified. */ return FAILED; } /* dump module globals */ printf("module %s {\n", mod->name); while ((var=global_getnext(var))!=NULL) { PROPERTY *prop = var->prop; char *proptype = class_get_property_typename(prop->ptype); if (strncmp(var->prop->name,mod->name,strlen(mod->name))!=0) continue; if (proptype!=NULL){ if(prop->unit != NULL) { printf("\t%s %s[%s];", proptype, strrchr(prop->name,':')+1, prop->unit->name); } else if (prop->ptype==PT_set || prop->ptype==PT_enumeration) { KEYWORD *key; printf("\t%s {", proptype); for (key=prop->keywords; key!=NULL; key=key->next) printf("%s=%"FMT_INT64"u%s", key->name, (int64)key->value, key->next==NULL?"":", "); printf("} %s;", strrchr(prop->name,':')+1); } else { printf("\t%s %s;", proptype, strrchr(prop->name,':')+1); } if (prop->description!=NULL) printf(" // %s%s",prop->flags&PF_DEPRECATED?"(DEPRECATED) ":"",prop->description); printf("\n"); } } printf("}\n"); } if(mod == NULL){ output_fatal("module %s is not found",*argv); /* TROUBLESHOOT The <b>--modhelp</b> parameter was found on the command line, but if was followed by a module specification that isn't valid. Verify that the module exists in GridLAB-D's <b>lib</b> folder. */ return FAILED; } if(oclass != NULL) { print_class(oclass); } else { CLASS *oclass; pntree *ctree; /* lexographically sort all elements from class_get_first_class & oclass->next */ oclass=class_get_first_class(); ctree = (pntree *)malloc(sizeof(pntree)); if(ctree == NULL){ throw_exception("--modhelp: malloc failure"); /* TROUBLESHOOT The memory allocation needed for module help to function has failed. Try freeing up system memory and try again. */ } ctree->name = oclass->name; ctree->oclass = oclass; ctree->left = ctree->right = 0; for(; oclass != NULL; oclass = oclass->next){ modhelp_alpha(&ctree, oclass); //print_class(oclass); } /* flatten tree */ print_modhelp_tree(ctree); } } } else if (strcmp(*argv,"--modtest")==0) { if (argc-1>0) { MODULE *mod = module_load(argv[1],0,NULL); if (mod==NULL) output_fatal("module %s is not found",argv[1]); /* TROUBLESHOOT The <b>--modtest</b> parameter was found on the command line, but if was followed by a module specification that isn't valid. Verify that the module exists in GridLAB-D's <b>lib</b> folder. */ else { argv++;argc--; if (mod->test==NULL) output_fatal("module %s does not implement a test routine", argv[0]); /* TROUBLESHOOT The <b>--modtest</b> parameter was found on the command line, but if was followed by a specification for a module that doesn't implement any test procedures. See the <b>--libinfo</b> command line parameter for information on which procedures the module supports. */ else { output_test("*** modtest of %s beginning ***", argv[0]); mod->test(0,NULL); output_test("*** modtest of %s ended ***", argv[0]); } } } else { output_fatal("definition is missing"); /* TROUBLESHOOT The <b>--modtest</b> parameter was found on the command line, but if was not followed by a module specification. The correct syntax is <b>gridlabd --modtest <i>module_name</i></b>. */ return FAILED; } } else if (strcmp(*argv,"--test")==0){ global_test_mode=TRUE; global_strictnames = FALSE; output_debug("disabling strict naming for tests"); if (argc-1>0) { char mod_test[100]; sprintf(mod_test,"mod_test%d=%s",test_mod_num++,*++argv); if (global_setvar(mod_test)==SUCCESS) argc--; } else { output_fatal("test module name is missing"); /* TROUBLESHOOT The <b>--test</b> parameter was found on the command line, but if was not followed by a module specification that is valid. The correct syntax is <b>gridlabd --test <i>module_name</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-D")==0 || strcmp(*argv,"--define")==0) { if (argc-1>0) { bool namestate = global_strictnames; global_strictnames = FALSE; if (global_setvar(*++argv,NULL)==SUCCESS){ argc--; } global_strictnames = namestate; } else { output_fatal("definition is missing"); /* TROUBLESHOOT The <b>-D</b> or <b>--define</b> command line parameters was given, but it was not followed by a variable definition. The correct syntax <b>-D </i>variable</i>=<i>value</i></b> or <b>--define </i>variable</i>=<i>value</i></b> */ return FAILED; } } else if (strcmp(*argv,"--globals")==0) { char *list[65536]; int i, n=0; GLOBALVAR *var = NULL; /* load the list into the array */ while ((var=global_getnext(var))!=NULL) { if (n<sizeof(list)/sizeof(list[0])) list[n++] = var->prop->name; else { output_fatal("--globals has insufficient buffer space to sort globals list"); return FAILED; } } /* sort the array */ qsort(list,n,sizeof(list[0]),compare); /* output sorted array */ for (i=0; i<n; i++) { char buffer[1024]; var = global_find(list[i]); printf("%s=%s;",var->prop->name,global_getvar(var->prop->name,buffer,sizeof(buffer))?buffer:"(error)"); if (var->prop->description || var->prop->flags&PF_DEPRECATED) printf(" // %s%s", (var->prop->flags&PF_DEPRECATED)?"DEPRECATED ":"", var->prop->description?var->prop->description:""); printf("\n"); } } else if (strcmp(*argv,"--redirect")==0) { if (argc-1>0) { char buffer[1024]; char *p; strcpy(buffer,*++argv); argc--; if (strcmp(buffer,"all")==0) { if (output_redirect("output",NULL)==NULL || output_redirect("error",NULL)==NULL || output_redirect("warning",NULL)==NULL || output_redirect("debug",NULL)==NULL || output_redirect("verbose",NULL)==NULL || output_redirect("profile",NULL)==NULL || output_redirect("progress",NULL)==NULL) { output_fatal("redirection of all failed"); /* TROUBLESHOOT An attempt to close all standard stream from the command line using <b>--redirect all</b> has failed. One of the streams cannot be closed. Try redirecting each stream separately until the problem stream is identified and the correct the problem with that stream. */ return FAILED; } } else if ((p=strchr(buffer,':'))!=NULL) { *p++='\0'; if (output_redirect(buffer,p)==NULL) { output_fatal("redirection of %s to '%s' failed: %s",buffer,p, strerror(errno)); /* TROUBLESHOOT An attempt to redirect a standard stream from the command line using <b>--redirect <i>stream</i>:<i>destination</i></b> has failed. The message should provide an indication of why the attempt failed. The remedy will depend on the nature of the problem. */ return FAILED; } } else if (output_redirect(buffer,NULL)==NULL) { output_fatal("default redirection of %s failed: %s",buffer, strerror(errno)); /* TROUBLESHOOT An attempt to close a standard stream from the command line using <b>--redirect <i>stream</i></b> has failed. The message should provide an indication of why the attempt failed. The remedy will depend on the nature of the problem. */ return FAILED; } } else { output_fatal("redirection is missing"); /* TROUBLESHOOT A <b>--redirect</b> directive on the command line is missing its redirection specification. The correct syntax is <b>--redirect <i>stream</i>[:<i>destination</i>]</b>. */ return FAILED; } } else if (strcmp(*argv,"-L")==0 || strcmp(*argv,"--libinfo")==0) { if (argc-1>0) { argc--; module_libinfo(*++argv); exit(0); } else { output_fatal("missing library name"); /* TROUBLESHOOT The <b>-L</b> or <b>--libinfo</b> command line directive was not followed by a module name. The correct syntax is <b>-L <i>module_name</i></b> or <b>--libinfo <i>module_name</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-T")==0 || strcmp(*argv,"--threadcount")==0) { if (argc-1>0) global_threadcount = (argc--,atoi(*++argv)); else { output_fatal("missing thread count"); /* TROUBLESHOOT The <b>-T</b> or <b>--threadcount</b> command line directive was not followed by a valid number. The correct syntax is <b>-T <i>number</i></b> or <b>--threadcount <i>number</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-o")==0 || strcmp(*argv,"--output")==0) { if (argc-1>0) strcpy(global_savefile,(argc--,*++argv)); else { output_fatal("missing output file"); /* TROUBLESHOOT The <b>-o</b> or <b>--output</b> command line directive was not followed by a valid filename. The correct syntax is <b>-o <i>file</i></b> or <b>--output <i>file</i></b>. */ return FAILED; } } else if (strcmp(*argv,"-e")==0 || strcmp(*argv,"--environment")==0) { if (argc-1>0) strcpy(global_environment,(argc--,*++argv)); else { output_fatal("environment not specified"); /* TROUBLESHOOT The <b>-e</b> or <b>--environment</b> command line directive was not followed by a valid environment specification. The correct syntax is <b>-e <i>keyword</i></b> or <b>--environment <i>keyword</i></b>. */ return FAILED; } } else if (strcmp(*argv,"--xmlencoding")==0) { if (argc-1>0) { global_xml_encoding = atoi(*++argv); argc--; } else { output_fatal("xml encoding not specified"); /* TROUBLESHOOT The <b>--xmlencoding</b> command line directive was not followed by a encoding specification. The correct syntax is <b>--xmlencoding <i>keyword</i></b>. */ return FAILED; } } else if (strcmp(*argv,"--xsd")==0) { if (argc-1>0) { argc--; exit(output_xsd(*++argv)); } else { MODULE *mod; for (mod=module_get_first(); mod!=NULL; mod=mod->next) output_xsd(mod->name); return SUCCESS; } } else if (strcmp(*argv,"--xsl")==0) { if (argc-1>0) { char fname[1024]; char *p_arg = *++argv; char n_args=1; char **p_args; argc--; while (*p_arg++!='\0') if (*p_arg==',') n_args++; p_args = (char**)malloc(sizeof(char*)*n_args); p_arg = strtok(*argv,","); n_args=0; while (p_arg!=NULL) { p_args[n_args++] = p_arg; p_arg = strtok(NULL,","); } sprintf(fname,"gridlabd-%d_%d.xsl",global_version_major,global_version_minor); exit(output_xsl(fname,n_args,p_args)); } else { output_fatal("module list not specified"); /* TROUBLESHOOT The <b>--xsl</b> command line directive was not followed by a validlist of modules. The correct syntax is <b>--xsl <i>module1</i>[,<i>module2</i>[,...]]</b>. */ return FAILED; } } else if (strcmp(*argv,"--stream")==0) global_streaming_io_enabled = !global_streaming_io_enabled; else if (strcmp(*argv,"--server")==0) strcpy(global_environment,"server"); else if (strcmp(*argv,"-h")==0 || strcmp(*argv,"--help")==0) { printf("Syntax: gridlabd [OPTIONS ...] <file> ... \nOptions:\n" " --avlbalance toggles AVL tree balancing\n" " -c|--check toggles module checks after model loads\n" " -D|--define <def> defines a macro value\n" " --debug toggles debug output (prints internal messages)\n" " --debugger toggles debugger mode (generates internal messages)\n" " --dumpall toggles module data dump after run completes\n" " -e|--environment <name> specifies user environment (default none)\n" " --license print license information\n" " -L|--libinfo <module> print module library information\n" " -o|--output <file> specifies model should be output after run\n" " --profile toggles profilers\n" " -q|--quiet toggles quiet mode (suppresses startup banner)\n" " --test toggles test mode (activate testing procedures)\n" " -T|--threadcount <n> specifies the number of processor threads to use\n" " -v|--verbose toggles verbose mode (active verbose messages)\n" " -V|--version prints the GridlabD version information\n" " -w|--warn toggles warning mode (generates warning messages)\n" " --xmlencoding <num> set the XML encoding (8, 16, or 32)\n" " --xmlstrict toggles XML encoding to be strict\n" " --xsd <module>[:<object>] prints the xsd of an object\n" " --xsl <modlist> prints the xsl for the modules listed\n" ); exit(0); } else if (**argv!='-') { if (global_test_mode) output_warning("file '%s' ignored in test mode", *argv); /* TROUBLESHOOT This warning is caused by an attempt to read an input file in self-test mode. The use of self-test model precludes reading model files. Try running the system in normal more or leaving off the model file name. */ else { if (!loadall(*argv)) return FAILED; /* preserve name of first model only */ if (strcmp(global_modelname,"")==0) strcpy(global_modelname,*argv); } } else { int n = module_cmdargs(argc,argv); if (n==0) { output_error("command line option '%s' is not recognized",*argv); /* TROUBLESHOOT The command line option given is not valid where it was found. Check the command line for correct syntax and order of options. */ return FAILED; } } } /*debug_traverse_tree(NULL);*/ /* for checking the name tree & getting a test file. -mh */ return SUCCESS; }
STATUS original_test_start(int argc, char *argv[]) { OBJECT *obj[6]; MODULE *network; CLASS *node, *link; MODULE *tape; CLASS *player, *recorder, *collector; network = module_load("network",argc,argv); if (network==NULL) { #ifndef WIN32 fprintf(stderr,"%s\n",dlerror()); #else perror("network module load failed"); #endif return FAILED; } output_verbose("network module loaded ok"); node = class_get_class_from_classname("node"); if (node==NULL) { output_fatal("network module does not implement class node"); /* TROUBLESHOOT The <b>network</b> module test can't find the <b>node</b> class definition. This is probably caused by either an internal system error or a version of the network module that doesn't implement node object as expected (or at all). */ return FAILED; } output_verbose("class node implementation loaded ok"); link = class_get_class_from_classname("link"); if (node==NULL || link==NULL) { output_fatal("network module does not implement class link"); /* TROUBLESHOOT The <b>network</b> module test can't find the <b>link</b> class definition. This is probably caused by either an internal system error or a version of the network module that doesn't implement link object as expected (or at all). */ return FAILED; } output_verbose("class link implementation loaded ok"); tape = module_load("tape",argc,argv); if (tape==NULL) { #ifndef WIN32 fprintf(stderr,"%s\n",dlerror()); #else perror("tape module load failed"); #endif return FAILED; } player = class_get_class_from_classname("player"); if (player==NULL) { output_fatal("tape module does not implement class player"); /* TROUBLESHOOT The <b>tape</b> module test can't find the <b>player</b> class definition. This is probably caused by either an internal system error or a version of the tape module that doesn't implement player object as expected (or at all). */ return FAILED; } recorder = class_get_class_from_classname("recorder"); if (recorder==NULL) { output_fatal("tape module does not implement class recorder"); /* TROUBLESHOOT The <b>tape</b> module test can't find the <b>recorder</b> class definition. This is probably caused by either an internal system error or a version of the tape module that doesn't implement recorder object as expected (or at all). */ return FAILED; } collector = class_get_class_from_classname("collector"); if (collector==NULL) { output_fatal("tape module does not implement class collector"); /* TROUBLESHOOT The <b>tape</b> module test can't find the <b>collector</b> class definition. This is probably caused by either an internal system error or a version of the tape module that doesn't implement collector object as expected (or at all). */ return FAILED; } if (module_import(network,"../test/pnnl2bus.cdf")<=0) return FAILED; /* tape player */ if ((*player->create)(&obj[3],object_get_first())==FAILED) { output_fatal("player creation failed"); /* TROUBLESHOOT The <b>tape</b> module test can't create a <b>player</b> object. This is probably caused by either an internal system error or a version of the tape module that doesn't implement player object as expected (or at all). */ return FAILED; } object_set_value_by_name(obj[3],"loop","3600"); /* 18000 is about 12y at 1h steps */ object_set_value_by_name(obj[3],"property","S"); /* tape recorder */ if ((*recorder->create)(&obj[4],object_get_first())==FAILED) { output_fatal("recorder creation failed"); /* TROUBLESHOOT The <b>tape</b> module test can't create a <b>recorder</b> object. This is probably caused by either an internal system error or a version of the tape module that doesn't implement recorder object as expected (or at all). */ return FAILED; } object_set_value_by_name(obj[4],"property","V,S"); object_set_value_by_name(obj[4],"interval","0"); object_set_value_by_name(obj[4],"limit","1000"); /* tape collector */ if ((*collector->create)(&obj[5],NULL)==FAILED) { output_fatal("collector creation failed"); /* TROUBLESHOOT The <b>tape</b> module test can't create a <b>collector</b> object. This is probably caused by either an internal system error or a version of the tape module that doesn't implement collector object as expected (or at all). */ return FAILED; } object_set_value_by_name(obj[5],"property","count(V.mag),min(V.mag),avg(V.mag),std(V.mag),max(V.mag),min(V.ang),avg(V.ang),std(V.ang),max(V.ang)"); object_set_value_by_name(obj[5],"interval","0"); object_set_value_by_name(obj[5],"limit","1000"); object_set_value_by_name(obj[5],"group","class=node;"); module_check(network); return SUCCESS; }
MODULE *module_load(const char *file, /**< module filename, searches \p PATH */ int argc, /**< count of arguments in \p argv */ char *argv[]) /**< arguments passed from the command line */ { /* check for already loaded */ MODULE *mod = module_find((char *)file); char buffer[FILENAME_MAX+1]; char *fmod; bool isforeign = false; char pathname[1024]; char *tpath = NULL; #ifdef WIN32 char from='/', to='\\'; #else char from='\\', to='/'; #endif char *p = NULL; void *hLib = NULL; LIBINIT init = NULL; int *pMajor = NULL, *pMinor = NULL; CLASS *previous = NULL; CLASS *c; #ifdef NEVER /* this shouldn't ever be necessary but sometimes for debugging purposes it is helpful */ /* if LD_LIBRARY_PATH is not set, default to current directory */ if (getenv("LD_LIBRARY_PATH")==NULL) { putenv("LD_LIBRARY_PATH=."); output_verbose("Setting default LD_LIBRARY_DEFAULT to current directory"); } #endif if (mod!=NULL) { output_verbose("%s(%d): module '%s' already loaded", __FILE__, __LINE__, file); return mod; } else { output_verbose("%s(%d): module '%s' not yet loaded", __FILE__, __LINE__, file); } /* check for foreign modules */ strcpy(buffer,file); fmod = strtok(buffer,"::"); if (fmod!=NULL && strcmp(fmod, file) != 0) { char *modname = strtok(NULL,"::"); MODULE *parent_mod = module_find(fmod); if(parent_mod == NULL) parent_mod = module_load(fmod, 0, NULL); previous = class_get_last_class(); if(parent_mod != NULL && parent_mod->subload != NULL) { /* if we've defined a subload routine and already loaded the parent module*/ MODULE *child_mod; if(module_find(fmod) == NULL) module_load(fmod, 0, NULL); child_mod = parent_mod->subload(modname, &mod, (previous ? &(previous->next) : &previous), argc, argv); if(child_mod == NULL) { /* failure */ output_error("module_load(file='%s::%s'): subload failed", fmod, modname); return NULL; } if (mod != NULL) { /* if we want to register another module */ last_module->next = mod; last_module = mod; mod->oclass = previous ? previous->next : class_get_first_class(); } return last_module; } else { struct { char *name; LOADER loader; } fmap[] = { {"matlab",NULL}, {"java",load_java_module}, {"python",load_python_module}, {NULL,NULL} /* DO NOT DELETE THIS TERMINATOR ENTRY */ }, *p; for (p=fmap; p->name!=NULL; p++) { if (strcmp(p->name, fmod)==0) { static char *args[1]; isforeign = true; if (p->loader!=NULL) /* use external loader */ return p->loader(modname,argc,argv); /* use a module with command args */ argv = args; argc=1; argv[0] = modname; file=buffer; break; } } if (p==NULL) { output_error("module_load(file='%s',...): foreign module type %s not recognized or supported", fmod); return NULL; } } } /* create a new module entry */ mod = (MODULE *)malloc(sizeof(MODULE)); if (mod==NULL) { output_verbose("%s(%d): module '%s' memory allocation failed", __FILE__, __LINE__, file); errno=ENOMEM; return NULL; } else output_verbose("%s(%d): module '%s' memory allocated", __FILE__, __LINE__, file); /* locate the module */ snprintf(pathname, 1024, "%s" DLEXT, file); tpath = find_file(pathname, NULL, X_OK|R_OK); if(tpath == NULL) { output_verbose("unable to locate %s in GLPATH, using library loader instead", pathname); tpath=pathname; } else { #ifndef WIN32 /* if the path is a relative path */ struct stat buf; if (tpath[0]!='/' && stat(tpath,&buf)==0) { char buffer[1024]; /* add ./ to the beginning of the path */ sprintf(buffer,"./%s", tpath); strcpy(tpath,buffer); } #endif output_verbose("full path to library '%s' is '%s'", file, tpath); } /* convert path delims based on OS preference */ for (p=strchr(tpath,from); p!=NULL; p=strchr(p,from)) *p=to; /* ok, let's do it */ hLib = DLLOAD(tpath); if (hLib==NULL) { #if defined WIN32 && ! defined MINGW output_error("%s(%d): module '%s' load failed - %s (error code %d)", __FILE__, __LINE__, file, strerror(errno), GetLastError()); #else output_error("%s(%d): module '%s' load failed - %s", __FILE__, __LINE__, file, dlerror()); output_debug("%s(%d): path to module is '%s'", __FILE__, __LINE__, tpath); #endif dlload_error(pathname); errno = ENOENT; free(mod); return NULL; } else output_verbose("%s(%d): module '%s' loaded ok", __FILE__, __LINE__, file); /* get the initialization function */ init = (LIBINIT)DLSYM(hLib,"init"); if (init==NULL) { output_error("%s(%d): module '%s' does not export init()", __FILE__, __LINE__, file); dlload_error(pathname); errno = ENOEXEC; free(mod); return NULL; } else output_verbose("%s(%d): module '%s' exports init()", __FILE__, __LINE__, file); /* connect the module's exported data & functions */ mod->hLib = (void*)hLib; pMajor = (int*)DLSYM(hLib, "major"); pMinor = (int*)DLSYM(hLib, "minor"); mod->major = pMajor?*pMajor:0; mod->minor = pMinor?*pMinor:0; mod->import_file = (int(*)(char*))DLSYM(hLib,"import_file"); mod->export_file = (int(*)(char*))DLSYM(hLib,"export_file"); mod->setvar = (int(*)(char*,char*))DLSYM(hLib,"setvar"); mod->getvar = (void*(*)(char*,char*,unsigned int))DLSYM(hLib,"getvar"); mod->check = (int(*)())DLSYM(hLib,"check"); #ifndef _NO_CPPUNIT mod->module_test = (int(*)(TEST_CALLBACKS*,int,char*[]))DLSYM(hLib,"module_test"); #endif mod->cmdargs = (int(*)(int,char**))DLSYM(hLib,"cmdargs"); mod->kmldump = (int(*)(FILE*,OBJECT*))DLSYM(hLib,"kmldump"); mod->subload = (MODULE *(*)(char *, MODULE **, CLASS **, int, char **))DLSYM(hLib, "subload"); mod->test = (void(*)(int,char*[]))DLSYM(hLib,"test"); mod->globals = NULL; strcpy(mod->name,file); mod->next = NULL; /* call the initialization function */ mod->oclass = (*init)(&callbacks,(void*)mod,argc,argv); if (mod->oclass==NULL) return NULL; /* connect intrinsic functions */ for (c=mod->oclass; c!=NULL; c=c->next) { char fname[1024]; struct { FUNCTIONADDR *func; char *name; int optional; } map[] = { {&c->create,"create",FALSE}, {&c->init,"init",TRUE}, {&c->sync,"sync",TRUE}, {&c->commit,"commit",TRUE}, {&c->notify,"notify",TRUE}, {&c->isa,"isa",TRUE}, {&c->plc,"plc",TRUE}, {&c->recalc,"recalc",TRUE}, }; int i; for (i=0; i<sizeof(map)/sizeof(map[0]); i++) { snprintf(fname, 1024,"%s_%s",map[i].name,isforeign?fmod:c->name); if ((*(map[i].func) = (FUNCTIONADDR)DLSYM(hLib,fname))==NULL && !map[i].optional) { output_fatal("intrinsic %s is not defined in class %s", fname,file); /* TROUBLESHOOT A required intrinsic function was not found. Please review and modify the class definition. */ errno=EINVAL; return NULL; } else if(!map[i].optional) output_verbose("%s(%d): module '%s' intrinsic %s found", __FILE__, __LINE__, file, fname); } } /* attach to list of known modules */ if (first_module==NULL) first_module = mod; else last_module->next = mod; last_module = mod; return last_module; }
/** The main entry point of GridLAB-D @returns Exit codes XC_SUCCESS, etc. (see gridlabd.h) **/ int main(int argc, /**< the number entries on command-line argument list \p argv */ char *argv[]) /**< a list of pointers to the command-line arguments */ { char *pd1, *pd2; int i, pos=0; char *browser = getenv("GLBROWSER"); /* set the default timezone */ timestamp_set_tz(NULL); exec_clock(); /* initialize the wall clock */ realtime_starttime(); /* mark start */ /* set the process info */ global_process_id = getpid(); /* specify the default browser */ if ( browser!= NULL ) strncpy(global_browser,browser,sizeof(global_browser)-1); #if defined WIN32 && _DEBUG atexit(pause_at_exit); #endif #ifdef WIN32 kill_starthandler(); atexit(kill_stophandler); #endif /* capture the execdir */ strcpy(global_execname,argv[0]); strcpy(global_execdir,argv[0]); pd1 = strrchr(global_execdir,'/'); pd2 = strrchr(global_execdir,'\\'); if (pd1>pd2) *pd1='\0'; else if (pd2>pd1) *pd2='\0'; /* determine current working directory */ getcwd(global_workdir,1024); /* capture the command line */ for (i=0; i<argc; i++) { if (pos < (int)(sizeof(global_command_line)-strlen(argv[i]))) pos += sprintf(global_command_line+pos,"%s%s",pos>0?" ":"",argv[i]); } /* main initialization */ if (!output_init(argc,argv) || !exec_init()) exit(XC_INIERR); /* set thread count equal to processor count if not passed on command-line */ if (global_threadcount == 0) global_threadcount = processor_count(); output_verbose("detected %d processor(s)", processor_count()); output_verbose("using %d helper thread(s)", global_threadcount); /* process command line arguments */ if (cmdarg_load(argc,argv)==FAILED) { output_fatal("shutdown after command line rejected"); /* TROUBLESHOOT The command line is not valid and the system did not complete its startup procedure. Correct the problem with the command line and try again. */ exit(XC_ARGERR); } /* stitch clock */ global_clock = global_starttime; /* initialize scheduler */ sched_init(0); /* recheck threadcount in case user set it 0 */ if (global_threadcount == 0) { global_threadcount = processor_count(); output_verbose("using %d helper thread(s)", global_threadcount); } /* see if newer version is available */ if ( global_check_version ) check_version(1); /* setup the random number generator */ random_init(); /* pidfile */ if (strcmp(global_pidfile,"")!=0) { FILE *fp = fopen(global_pidfile,"w"); if (fp==NULL) { output_fatal("unable to create pidfile '%s'", global_pidfile); /* TROUBLESHOOT The system must allow creation of the process id file at the location indicated in the message. Create and/or modify access rights to the path for that file and try again. */ exit(XC_PRCERR); } #ifdef WIN32 #define getpid _getpid #endif fprintf(fp,"%d\n",getpid()); output_verbose("process id %d written to %s", getpid(), global_pidfile); fclose(fp); atexit(delete_pidfile); } /* do legal stuff */ #ifdef LEGAL_NOTICE if (strcmp(global_pidfile,"")==0 && legal_notice()==FAILED) exit(XC_USRERR); #endif /* start the processing environment */ output_verbose("load time: %d sec", realtime_runtime()); output_verbose("starting up %s environment", global_environment); if (environment_start(argc,argv)==FAILED) { output_fatal("environment startup failed: %s", strerror(errno)); /* TROUBLESHOOT The requested environment could not be started. This usually follows a more specific message regarding the startup problem. Follow the recommendation for the indicated problem. */ if ( exec_getexitcode()==XC_SUCCESS ) exec_setexitcode(XC_ENVERR); } /* save the model */ if (strcmp(global_savefile,"")!=0) { if (saveall(global_savefile)==FAILED) output_error("save to '%s' failed", global_savefile); } /* do module dumps */ if (global_dumpall!=FALSE) { output_verbose("dumping module data"); module_dumpall(); } /* KML output */ if (strcmp(global_kmlfile,"")!=0) kml_dump(global_kmlfile); /* terminate */ module_termall(); /* wrap up */ output_verbose("shutdown complete"); /* profile results */ if (global_profiler) { class_profiles(); module_profiles(); } #ifdef DUMP_SCHEDULES /* dump a copy of the schedules for reference */ schedule_dumpall("schedules.txt"); #endif /* restore locale */ locale_pop(); /* if pause enabled */ #ifndef WIN32 if (global_pauseatexit) { output_verbose("pausing at exit"); while (true) { sleep(5); } } #endif /* compute elapsed runtime */ output_verbose("elapsed runtime %d seconds", realtime_runtime()); output_verbose("exit code %d", exec_getexitcode()); exit(exec_getexitcode()); }
/** Insert an item into an index @return STATUS on SUCCESS, FAILED otherwise **/ STATUS index_insert(INDEX *index, /**< the index to which the item is added */ void *data, /**< a pointer to the item to be added */ int ordinal) /**< the ordinal to which the item belongs */ { int pos = ordinal - index->first_ordinal; if (ordinal<index->first_ordinal) /* grow on bottom end */ { /** @todo allow resizing indexes when ordinal is before first (ticket #28) */ /* (this is very unusual and shouldn't happen the way things are now) */ output_fatal("ordinal %d is too small (first is %d)",ordinal, index->first_ordinal); /* TROUBLESHOOT This is an internal error caused by an attempt to index something improperly. Because the indexing system start at index 0, this means a negative index number was attempting, which is most likely a bug. This usually occurs during object initialization and might be caused by invalid object numbers, either negative or greater than about 2 billion. If your model is using a the <b><i>class</i>:<i>id</i></b> naming convention, check the object id numbers to make sure they are correct. */ errno = EINVAL; return FAILED; } else if (ordinal>=index->last_ordinal) /* grow on to end */ { int oldsize = index->last_ordinal - index->first_ordinal; int newsize = oldsize; GLLIST **newblock = NULL; while (ordinal >= index->first_ordinal + newsize) newsize *= 2; /* double until it fits */ newblock = malloc(sizeof(GLLIST*)*newsize); if (newblock==NULL) { output_fatal("unable to grow index %d: %s",index->id, strerror(errno)); /* TROUBLESHOOT An internal memory allocation error cause an index operation to fail. The message will usually include some explanation as to what cause the failure. Remedy the indicated memory problem to fix the indexing problem. */ return FAILED; } output_verbose("growing index %d to %d ordinals", index->id, newsize); memset(newblock,0,sizeof(GLLIST*)*newsize); memcpy(newblock,index->ordinal,sizeof(GLLIST*)*oldsize); free(index->ordinal); index->ordinal = newblock; index->last_ordinal = index->first_ordinal + newsize; } if (index->ordinal[pos]==NULL) /* new list at ordinal */ { index->ordinal[pos] = list_create(); if (index->ordinal[pos]==NULL) return FAILED; } if (list_append(index->ordinal[pos],data)==NULL) return FAILED; if (ordinal<index->first_used) index->first_used=ordinal; if (ordinal>index->last_used) index->last_used=ordinal; return SUCCESS; }
/** Convert a datetime struct into a GMT timestamp **/ TIMESTAMP mkdatetime(DATETIME *dt) { TIMESTAMP ts; int n; if(dt == NULL){ return TS_INVALID; } /* start with year */ timestamp_year(0,NULL); /* initializes tszero */ if(dt->year < YEAR0 || dt->year >= YEAR0 + sizeof(tszero) / sizeof(tszero[0]) ){ return TS_INVALID; } ts = tszero[dt->year-YEAR0]; if(dt->month > 12 || dt->month < 1) { output_fatal("Invalid month provided in datetime"); return TS_INVALID; } else if(dt->day > daysinmonth[dt->month-1] || dt->day < 1) { if(ISLEAPYEAR(dt->year) && dt->month == 2 && dt->day == 29){ ; } else { output_fatal("Invalid day provided in datetime"); return TS_INVALID; } } /* add month */ for (n=1; n<dt->month; n++){ if(ISLEAPYEAR(dt->year) && n == 2){ ts += (daysinmonth[n - 1] + 1) * DAY; } else { ts += (daysinmonth[n - 1]) * DAY; } // ts += (daysinmonth[n - 1] + (n == 2 && ISLEAPYEAR(dt->year) ? 1 : 0)) * DAY; } if(dt->hour < 0 || dt->hour > 23 || dt->minute < 0 || dt->minute > 60 || dt->second < 0 || dt->second > 62){ output_fatal("Invalid time of day provided in datetime"); return ts; } /* add day, hour, minute, second, usecs */ ts += (dt->day - 1) * DAY + dt->hour * HOUR + dt->minute * MINUTE + dt->second * SECOND + dt->nanosecond/1.0e9; if(dt->tz[0] == 0){ strcpy(dt->tz, (isdst(ts) ? tzdst : tzstd)); } /* adjust for GMT (or unspecified) */ if (strcmp(dt->tz, "GMT") == 0){ return ts; } else if(strcmp(dt->tz, tzstd) == 0 || ((strcmp(dt->tz, "")==0 && !isdst(ts) && (ts < dststart[dt->year - YEAR0] || ts >= dstend[dt->year - YEAR0])))){ /* adjust to standard local time */ return ts + tzoffset; } else if(strcmp(dt->tz, tzdst) == 0 || ((strcmp(dt->tz, "")==0 && !isdst(ts) && ts >= dststart[dt->year - YEAR0] && ts < dstend[dt->year - YEAR0]))){ /* adjust to daylight local time */ return ts + tzoffset - HOUR; } else { /* not a valid timezone */ return TS_INVALID; } return TS_INVALID; // heading off 'no return path' warnings }
/** Converts a GMT timestamp to local datetime struct Adjusts to TZ if possible **/ int local_datetime(TIMESTAMP ts, DATETIME *dt) { int64 n; TIMESTAMP rem = 0; TIMESTAMP local; int tsyear; #ifdef USE_TS_CACHE /* allow caching */ static TIMESTAMP old_ts =0; static DATETIME old_dt; #endif if( ts == TS_NEVER || ts==TS_ZERO ) return 0; if( dt==NULL || ts<TS_ZERO || ts>TS_MAX ) /* no buffer or timestamp out of range */ { output_error("local_datetime(ts=%lli,...): invalid local_datetime request",ts); return 0; } #ifdef USE_TS_CACHE /* check cache */ if (old_ts == ts && old_ts!=0) memcpy(dt,&old_dt,sizeof(DATETIME)); else old_ts = 0; #endif local = LOCALTIME(ts); tsyear = timestamp_year(local, &rem); if (rem < 0) { // DPC: note that as of 3.0, the clock is initialized by default, so this error can only // occur when an invalid timestamp is being converted to local time. It should no // longer occur as a result of a missing clock directive. //THROW("local_datetime(ts=%lli, ...): invalid timestamp cannot be converted to local time", ts); /* TROUBLESHOOT This is the result of an internal core or module coding error which resulted in an invalid UTC clock time being converted to local time. */ output_error("local_datetime(ts=%lli,...): invalid local_datetime request",ts); return 0; } if(ts < TS_ZERO && ts > TS_MAX){ /* timestamp out of range */ return 0; } if(ts == TS_NEVER){ return 0; } /* ts is valid */ dt->timestamp = ts; /* DST? */ dt->is_dst = (tzvalid && isdst(ts)); /* compute year */ dt->year = tsyear; /* yearday and weekday */ dt->yearday = (unsigned short)(rem / DAY); dt->weekday = (unsigned short)((local / DAY + DOW0 + 7) % 7); /* compute month */ dt->month = 0; n = daysinmonth[0] * DAY; while(rem >= n){ rem -= n; /* subtract n ticks from ts */ dt->month++; /* add to month */ if(dt->month == 12){ dt->month = 0; ++dt->year; } n = (daysinmonth[dt->month] + ((dt->month == 1 && ISLEAPYEAR(dt->year)) ? 1:0)) * 86400 * TS_SECOND; if(n < 86400 * 28){ /**/ output_fatal("Breaking an infinite loop in local_datetime! (ts = %"FMT_INT64"ds", ts); /* TROUBLESHOOT An internal protection against infinite loops in the time calculation module has encountered a critical problem. This is often caused by an incorrectly initialized timezone system, a missing timezone specification before a timestamp was used, or a missing timezone localization in your system. Correct the timezone problem and try again. */ return 0; } } dt->month++; /* Jan=1 */ /* compute day */ dt->day = (unsigned short)(rem / DAY + 1); rem %= DAY; /* compute hour */ dt->hour = (unsigned short)(rem / HOUR); rem %= HOUR; /* compute minute */ dt->minute = (unsigned short)(rem / MINUTE); rem %= MINUTE; /* compute second */ dt->second = (unsigned short)rem / TS_SECOND; rem %= SECOND; /* compute nanosecond */ dt->nanosecond = (unsigned int)(rem * 1e9); /* determine timezone */ strncpy(dt->tz, tzvalid ? (dt->is_dst ? tzdst : tzstd) : "GMT", sizeof(dt->tz)); /* timezone offset in seconds */ dt->tzoffset = tzoffset - (isdst(dt->timestamp)?3600:0); #ifdef USE_TS_CACHE /* cache result */ old_ts = ts; memcpy(&old_dt,dt,sizeof(old_dt)); #endif return 1; }