tclMain.cpp

Go to the documentation of this file.
00001 /* 
00002  * tclMain.c --
00003  *
00004  *      Main program for Tcl shells and other Tcl-based applications.
00005  *
00006  * Copyright (c) 1988-1994 The Regents of the University of California.
00007  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
00008  *
00009  * See the file "license.terms" for information on usage and redistribution
00010  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00011  *
00012  * RCS: @(#) $Id: tclMain.cpp,v 1.39 2006/09/05 19:38:17 mhscott Exp $
00013  */
00014 
00015 /*                       MODIFIED   FOR                              */
00016 
00017 /* ****************************************************************** **
00018 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00019 **          Pacific Earthquake Engineering Research Center            **
00020 ** ****************************************************************** */
00021 
00022 #include <string.h>
00023 
00024 #ifndef _WIN32
00025 #include <unistd.h>
00026 #endif
00027 
00028 extern "C" {
00029 #include <tcl.h>
00030 #include <tclDecls.h>
00031 EXTERN int              TclFormatInt _ANSI_ARGS_((char *buffer, long n));
00032 EXTERN int              TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj *cmdPtr));
00033 }
00034 
00035 #include <OPS_Globals.h>
00036 
00037 int             Tcl_AppInit _ANSI_ARGS_((Tcl_Interp *interp));
00038 
00039 
00040 # undef TCL_STORAGE_CLASS
00041 # define TCL_STORAGE_CLASS DLLEXPORT
00042 
00043 /*
00044  * The following code ensures that tclLink.c is linked whenever
00045  * Tcl is linked.  Without this code there's no reference to the
00046  * code in that file from anywhere in Tcl, so it may not be
00047  * linked into the application.
00048  */
00049 
00050 #ifdef _TCL84
00051 int (*tclDummyLinkVarPtr)(Tcl_Interp *interp, const char *a,
00052                           char *b, int c) = Tcl_LinkVar;
00053 #else
00054 int (*tclDummyLinkVarPtr)(Tcl_Interp *interp, char *a,
00055                           char *b, int c) = Tcl_LinkVar;
00056 #endif
00057 
00058 /*
00059  * Declarations for various library procedures and variables (don't want
00060  * to include tclPort.h here, because people might copy this file out of
00061  * the Tcl source directory to make their own modified versions).
00062  * Note:  "exit" should really be declared here, but there's no way to
00063  * declare it without causing conflicts with other definitions elsewher
00064  * on some systems, so it's better just to leave it out.
00065  */
00066 
00067 
00068 typedef struct parameterValues {
00069   char *value;
00070   struct parameterValues *next;
00071 } OpenSeesTcl_ParameterValues;
00072 
00073 typedef struct parameter {
00074   char *name;
00075   OpenSeesTcl_ParameterValues *values;
00076   struct parameter *next;
00077 } OpenSeesTcl_Parameter;
00078 
00079 
00080 #ifdef _WIN32
00081 extern "C" int  isatty _ANSI_ARGS_((int fd));
00082 extern "C" char * strcpy _ANSI_ARGS_((char *dst, CONST char *src)) throw();
00083 #endif
00084 static char *tclStartupScriptFileName = NULL;
00085 
00086 
00087 #include <FileStream.h>
00088 #include <SimulationInformation.h>
00089 SimulationInformation simulationInfo;
00090 
00091 char *simulationInfoOutputFilename = 0;
00092 
00093 
00094 /*
00095  *----------------------------------------------------------------------
00096  *
00097  * TclSetStartupScriptFileName --
00098  *
00099  *      Primes the startup script file name, used to override the
00100  *      command line processing.
00101  *
00102  * Results:
00103  *      None. 
00104  *
00105  * Side effects:
00106  *      This procedure initializes the file name of the Tcl script to
00107  *      run at startup.
00108  *
00109  *----------------------------------------------------------------------
00110  */
00111 void TclSetStartupScriptFileName(char *fileName)
00112 {
00113     tclStartupScriptFileName = fileName;
00114 }
00115 
00116 
00117 /*
00118  *----------------------------------------------------------------------
00119  *
00120  * TclGetStartupScriptFileName --
00121  *
00122  *      Gets the startup script file name, used to override the
00123  *      command line processing.
00124  *
00125  * Results:
00126  *      The startup script file name, NULL if none has been set.
00127  *
00128  * Side effects:
00129  *      None.
00130  *
00131  *----------------------------------------------------------------------
00132  */
00133 char *TclGetStartupScriptFileName()
00134 {
00135     return tclStartupScriptFileName;
00136 }
00137 
00138 int
00139 EvalFileWithParameters(Tcl_Interp *interp, 
00140                        char *tclStartupFileScript, 
00141                        OpenSeesTcl_Parameter *theParameters, 
00142                        char **paramNames, 
00143                        char **paramValues, 
00144                        int numParam, 
00145                        int currentParam, 
00146                        int rank, 
00147                        int np)
00148 {
00149   if (currentParam < numParam) {
00150     OpenSeesTcl_Parameter *theCurrentParam = theParameters;
00151     OpenSeesTcl_Parameter *theNextParam = theParameters->next;
00152     char *paramName = theCurrentParam->name;
00153     paramNames[currentParam] = paramName;
00154 
00155     OpenSeesTcl_ParameterValues *theValue = theCurrentParam->values;
00156     int nextParam = currentParam+1;
00157     while (theValue != 0) {
00158       char *paramValue = theValue->value;
00159       paramValues[currentParam] = paramValue;
00160       EvalFileWithParameters(interp, 
00161                              tclStartupFileScript, 
00162                              theNextParam, 
00163                              paramNames, 
00164                              paramValues, 
00165                              numParam, 
00166                              nextParam, 
00167                              rank, 
00168                              np);
00169 
00170       theValue=theValue->next;
00171     } 
00172   } else {
00173     
00174     simulationInfo.start();
00175     static int count = 0;
00176     
00177     if ((count % np) == rank) {
00178       Tcl_Eval(interp, "wipe");
00179      
00180           
00181       for (int i=0; i<numParam; i++) {
00182                   
00183         Tcl_SetVar(interp, paramNames[i], paramValues[i], TCL_GLOBAL_ONLY);         
00184         simulationInfo.addParameter(paramNames[i], paramValues[i]); 
00185      }
00186 
00187       count++;
00188       
00189    simulationInfo.addReadFile(tclStartupScriptFileName);
00190 
00191       int ok = Tcl_EvalFile(interp, tclStartupScriptFileName);
00192 
00193      simulationInfo.end();
00194       
00195       return ok;
00196     }
00197     else
00198       count++;
00199   }
00200 
00201   return 0;
00202 }
00203 
00204 
00205 
00206 /*
00207  *----------------------------------------------------------------------
00208  *
00209  * Tcl_Main --
00210  *
00211  *      Main program for tclsh and most other Tcl-based applications.
00212  *
00213  * Results:
00214  *      None. This procedure never returns (it exits the process when
00215  *      it's done.
00216  *
00217  * Side effects:
00218  *      This procedure initializes the Tcl world and then starts
00219  *      interpreting commands;  almost anything could happen, depending
00220  *      on the script being interpreted.
00221  *
00222  *----------------------------------------------------------------------
00223  */
00224 
00226 //#include <fstream.h>
00228 
00229 
00230 void
00231 g3TclMain(int argc, char **argv, Tcl_AppInitProc * appInitProc, int rank, int np)
00232 { 
00233     Tcl_Obj *resultPtr;
00234     Tcl_Obj *commandPtr = NULL;
00235     char buffer[1000], *args;
00236     int code, gotPartial, tty, length;
00237     int exitCode = 0;
00238     Tcl_Channel inChannel, outChannel, errChannel;
00239     Tcl_Interp *interp;
00240     Tcl_DString argString;
00241 
00242 
00243     /* fmk - beginning of modifications for OpenSees */
00244     fprintf(stderr,"\n\n\t OpenSees -- Open System For Earthquake Engineering Simulation");
00245     fprintf(stderr,"\n\tPacific Earthquake Engineering Research Center -- %s\n\n", OPS_VERSION);
00246     
00247     fprintf(stderr,"\t    (c) Copyright 1999,2000 The Regents of the University of California");
00248     fprintf(stderr,"\n\t\t\t\t All Rights Reserved\n");    
00249     fprintf(stderr,"    (Copyright and Disclaimer @ http://www.berkeley.edu/OpenSees/copyright.html)\n\n\n");
00250 
00251     /* fmk - end of modifications for OpenSees */
00252     // Boris Jeremic additions
00253 # ifdef _UNIX
00254     //   #include "version.txt"
00255     //   fprintf(stderr,"\n %s \n\n\n", version);    
00256 # endif
00257 // Boris Jeremic additions
00258 
00259 
00260     Tcl_FindExecutable(argv[0]);
00261     interp = Tcl_CreateInterp();
00262 #ifdef TCL_MEM_DEBUG
00263     Tcl_InitMemory(interp);
00264 #endif
00265 
00266     /*
00267      * Make command-line arguments available in the Tcl variables "argc"
00268      * and "argv".  If the first argument doesn't start with a "-" then
00269      * strip it off and use it as the name of a script file to process.
00270      */
00271 
00272     if (tclStartupScriptFileName == NULL) {
00273         if ((argc > 1) && (argv[1][0] != '-')) {
00274             tclStartupScriptFileName = argv[1];
00275             argc--;
00276             argv++;
00277         }
00278     }
00279 
00280     args = Tcl_Merge(argc-1, argv+1);
00281     Tcl_ExternalToUtfDString(NULL, args, -1, &argString);
00282     Tcl_SetVar(interp, "argv", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);
00283     Tcl_DStringFree(&argString);
00284     ckfree(args);
00285 
00286 
00287     if (tclStartupScriptFileName == NULL) {
00288         Tcl_ExternalToUtfDString(NULL, argv[0], -1, &argString);
00289     } else {
00290         tclStartupScriptFileName = Tcl_ExternalToUtfDString(NULL,
00291                 tclStartupScriptFileName, -1, &argString);
00292     }
00293 
00294     TclFormatInt(buffer, argc-1);
00295     Tcl_SetVar(interp, "argc", buffer, TCL_GLOBAL_ONLY);
00296     Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);
00297 
00298     /*
00299      * Set the "tcl_interactive" variable.
00300      */
00301 
00302     tty = isatty(0);
00303     char one[2] = "1";
00304     char zero[2] = "0";
00305 
00306     Tcl_SetVar(interp, "tcl_interactive",
00307             ((tclStartupScriptFileName == NULL) && tty) ? one : zero,
00308             TCL_GLOBAL_ONLY);
00309     
00310     /*
00311      * Invoke application-specific initialization.
00312      */
00313 
00314     if ((*appInitProc)(interp) != TCL_OK) {
00315         errChannel = Tcl_GetStdChannel(TCL_STDERR);
00316         if (errChannel) {
00317             Tcl_WriteChars(errChannel,
00318                     "application-specific initialization failed: ", -1);
00319             Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
00320             Tcl_WriteChars(errChannel, "\n", 1);
00321         }
00322     }
00323 
00324     /*
00325      * If a script file was specified then just source that file
00326      * and quit.
00327      */
00328 
00329     if (tclStartupScriptFileName != NULL) {
00330       OpenSeesTcl_Parameter *theParameters = 0;
00331       OpenSeesTcl_Parameter *endParameters = 0;
00332       int numParam = 0;
00333 
00334       if (argc > 1) {
00335         int currentArg = 1;
00336         while (currentArg < argc && argv[currentArg] != NULL) {
00337 
00338           if ((strcmp(argv[currentArg], "-par") == 0) || (strcmp(argv[currentArg], "-Par") == 0)) {
00339             
00340             if (argc > (currentArg+2)) {
00341               
00342               char *parName = argv[currentArg+1];
00343               char *parValue = argv[currentArg+2];
00344               
00345               // add a OpenSeesTcl_Parameter to end of list of parameters
00346               OpenSeesTcl_Parameter *nextParam = new OpenSeesTcl_Parameter;
00347               nextParam->name = new char [strlen(parName)+1];
00348               strcpy(nextParam->name, parName);
00349               nextParam->values = 0;
00350               
00351               if (theParameters == 0)
00352                 theParameters = nextParam;
00353               if (endParameters != 0)
00354                 endParameters->next = nextParam;
00355               nextParam->next = 0;
00356               endParameters = nextParam;
00357               
00358               // now open par values files to create the values
00359               char nextLine[1000];
00360               FILE *valueFP = fopen(parValue,"r");
00361               if (valueFP != 0) {
00362                 OpenSeesTcl_ParameterValues *endValues = 0;
00363                 
00364                 while (fscanf(valueFP, "%s", nextLine) != EOF) {
00365                   
00366                   OpenSeesTcl_ParameterValues *nextValue = new OpenSeesTcl_ParameterValues;
00367                   nextValue->value = new char [strlen(nextLine)+1];
00368                   strcpy(nextValue->value, nextLine);
00369                   
00370                   if (nextParam->values == 0) {
00371                     nextParam->values = nextValue;
00372                   }
00373                 if (endValues != 0)
00374                   endValues->next = nextValue;
00375                 endValues = nextValue;
00376                 nextValue->next = 0;          
00377                 }
00378                 fclose(valueFP);
00379               } else {
00380                 
00381                 OpenSeesTcl_ParameterValues *nextValue = new OpenSeesTcl_ParameterValues;               
00382                 nextValue->value = new char [strlen(parValue)+1];
00383                 
00384                 strcpy(nextValue->value, parValue);
00385                 
00386                 nextParam->values = nextValue;
00387                 nextValue->next = 0;
00388                 
00389               }
00390               numParam++;
00391             }
00392             currentArg += 3;
00393           } else if ((strcmp(argv[currentArg], "-info") == 0) || (strcmp(argv[currentArg], "-INFO") == 0)) {
00394             if (argc > (currentArg+1)) {
00395               
00396               simulationInfoOutputFilename = argv[currentArg+1];            
00397             }                      
00398             currentArg+=2;
00399           } else 
00400             currentArg++;
00401         }
00402 
00403         if (numParam != 0) {
00404           char **paramNames = new char *[numParam];
00405           char **paramValues = new char *[numParam];
00406           code = EvalFileWithParameters(interp, tclStartupScriptFileName, theParameters, paramNames, paramValues, numParam, 0, rank, np);
00407 
00408           if (code != TCL_OK) {
00409             errChannel = Tcl_GetStdChannel(TCL_STDERR);
00410             if (errChannel) {
00411               /*
00412                * The following statement guarantees that the errorInfo
00413                * variable is set properly.
00414                */
00415               
00416               Tcl_AddErrorInfo(interp, "");
00417               Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, "errorInfo",
00418                                                      NULL, TCL_GLOBAL_ONLY));
00419               Tcl_WriteChars(errChannel, "\n", 1);
00420             }
00421             exitCode = 1;
00422           }
00423           goto done;
00424         }
00425       }
00426 
00427       if (simulationInfoOutputFilename != 0) {
00428         simulationInfo.start();
00429         simulationInfo.addReadFile(tclStartupScriptFileName);
00430       }
00431 
00432       code = Tcl_EvalFile(interp, tclStartupScriptFileName);
00433 
00434       if (code != TCL_OK) {
00435         errChannel = Tcl_GetStdChannel(TCL_STDERR);
00436         if (errChannel) {
00437           /*
00438            * The following statement guarantees that the errorInfo
00439            * variable is set properly.
00440            */
00441           
00442           Tcl_AddErrorInfo(interp, "");
00443           Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, "errorInfo",
00444                                                  NULL, TCL_GLOBAL_ONLY));
00445           Tcl_WriteChars(errChannel, "\n", 1);
00446         }
00447         exitCode = 1;
00448       }
00449       goto done;
00450 
00451     } else {
00452 
00453     /*
00454      * We're running interactively.  Source a user-specific startup
00455      * file if the application specified one and if the file exists.
00456      */
00457 
00458       Tcl_DStringFree(&argString);
00459       
00460       int currentArg = 1;
00461       while (currentArg < argc && argv[currentArg] != NULL) {
00462         if ((strcmp(argv[currentArg], "-info") == 0) || (strcmp(argv[currentArg], "-INFO") == 0)) {
00463           if (argc > (currentArg+1)) {
00464             
00465                 simulationInfoOutputFilename = argv[currentArg+1];          
00466           }                        
00467           currentArg+=2;
00468         } else  
00469           currentArg++;
00470       }
00471 
00472       Tcl_SourceRCFile(interp);
00473       
00474       /*
00475        * Process commands from stdin until there's an end-of-file.  Note
00476        * that we need to fetch the standard channels again after every
00477        * eval, since they may have been changed.
00478        */
00479      
00480       if (simulationInfoOutputFilename != 0) {
00481         simulationInfo.start();
00482       }
00483      
00484       commandPtr = Tcl_NewObj();
00485       Tcl_IncrRefCount(commandPtr);
00486       
00487       inChannel = Tcl_GetStdChannel(TCL_STDIN);
00488       outChannel = Tcl_GetStdChannel(TCL_STDOUT);
00489       gotPartial = 0;
00490       while (1) {
00491         if (tty) {
00492           Tcl_Obj *promptCmdPtr;
00493           
00494           char one[12] = "tcl_prompt1";
00495           char two[12] = "tcl_prompt2";
00496           promptCmdPtr = Tcl_GetVar2Ex(interp,
00497                                        (gotPartial ? one : two),
00498                                        NULL, TCL_GLOBAL_ONLY);
00499           if (promptCmdPtr == NULL) {
00500           defaultPrompt:
00501             if (!gotPartial && outChannel) {
00502               Tcl_WriteChars(outChannel, "OpenSees > ", 11);
00503             }
00504           } else {
00505             
00506             code = Tcl_EvalObjEx(interp, promptCmdPtr, 0);
00507             
00508             inChannel = Tcl_GetStdChannel(TCL_STDIN);
00509             outChannel = Tcl_GetStdChannel(TCL_STDOUT);
00510             errChannel = Tcl_GetStdChannel(TCL_STDERR);
00511             if (code != TCL_OK) {
00512               if (errChannel) {
00513                 Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
00514                 Tcl_WriteChars(errChannel, "\n", 1);
00515               }
00516               Tcl_AddErrorInfo(interp,
00517                                "\n    (script that generates prompt)");
00518               goto defaultPrompt;
00519             }
00520           }
00521           if (outChannel) {
00522             Tcl_Flush(outChannel);
00523             }
00524         }
00525         if (!inChannel) {
00526           goto done;
00527         }
00528         length = Tcl_GetsObj(inChannel, commandPtr);
00529         if (length < 0) {
00530           goto done;
00531         }
00532         if ((length == 0) && Tcl_Eof(inChannel) && (!gotPartial)) {
00533           goto done;
00534         }
00535         
00536         /*
00537          * Add the newline removed by Tcl_GetsObj back to the string.
00538          */
00539         
00540         Tcl_AppendToObj(commandPtr, "\n", 1);
00541         if (!TclObjCommandComplete(commandPtr)) {
00542           gotPartial = 1;
00543           continue;
00544         }
00545         
00546         gotPartial = 0;
00547         code = Tcl_RecordAndEvalObj(interp, commandPtr, 0);
00548         inChannel = Tcl_GetStdChannel(TCL_STDIN);
00549         outChannel = Tcl_GetStdChannel(TCL_STDOUT);
00550         errChannel = Tcl_GetStdChannel(TCL_STDERR);
00551         Tcl_DecrRefCount(commandPtr);
00552         commandPtr = Tcl_NewObj();
00553         Tcl_IncrRefCount(commandPtr);
00554         if (code != TCL_OK) {
00555           if (errChannel) {
00556             Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
00557             Tcl_WriteChars(errChannel, "\n", 1);
00558           }
00559         } else if (tty) {
00560           resultPtr = Tcl_GetObjResult(interp);
00561           Tcl_GetStringFromObj(resultPtr, &length);
00562           if ((length > 0) && outChannel) {
00563             Tcl_WriteObj(outChannel, resultPtr);
00564             Tcl_WriteChars(outChannel, "\n", 1);
00565           }
00566         }
00567 #ifdef TCL_MEM_DEBUG
00568         if (tclMemDumpFileName != NULL) {
00569           Tcl_DecrRefCount(commandPtr);
00570           Tcl_DeleteInterp(interp);
00571           Tcl_Exit(0);
00572         }
00573 #endif
00574       }
00575     }
00576       
00577 
00578  done:
00579     
00580     if (commandPtr != NULL) {
00581       Tcl_DecrRefCount(commandPtr);
00582     }
00583     
00584     
00585 #ifdef _PARALLEL_PROCESSING
00586     return;
00587 #endif
00588     
00589 #ifdef _PARALLEL_INTERPRETERS
00590     return;
00591 #endif
00592     
00593     /*
00594      * Rather than calling exit, invoke the "exit" command so that
00595      * users can replace "exit" with some other command to do additional
00596      * cleanup on exit.  The Tcl_Eval call should never return.
00597      */
00598     
00599     sprintf(buffer, "exit %d", exitCode);
00600     Tcl_Eval(interp, buffer);
00601     
00602     return;
00603 }
00604 
00605 
00606 /*
00607 
00608 int OpenSeesExit(ClientData clientData, Tcl_Interp *interp, int argc, TCL_Char **argv)
00609 {
00610         
00611   if (simulationInfoOutputFilename != 0) {
00612     simulationInfo.end();
00613     FileStream simulationInfoOutputFile;
00614     simulationInfoOutputFile.setFile(simulationInfoOutputFilename);
00615     simulationInfoOutputFile.open();
00616     simulationInfoOutputFile << simulationInfo;
00617     simulationInfoOutputFile.close();
00618   }
00619 
00620   Tcl_Exit(0);
00621   return 0;
00622 }
00623 
00624 */    

Generated on Mon Oct 23 15:05:31 2006 for OpenSees by doxygen 1.5.0