G:/ScriptBasic/source/variations/standard/scribacmd.c

Go to the documentation of this file.
00001 /* 
00002 
00003 FILE:   scribacmd.c
00004 HEADER: scribacmd.h
00005 
00006 --GNU LGPL
00007 This library is free software; you can redistribute it and/or
00008 modify it under the terms of the GNU Lesser General Public
00009 License as published by the Free Software Foundation; either
00010 version 2.1 of the License, or (at your option) any later version.
00011 
00012 This library is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 Lesser General Public License for more details.
00016 
00017 You should have received a copy of the GNU Lesser General Public
00018 License along with this library; if not, write to the Free Software
00019 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021 TO_HEADER:
00022 
00023 */
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 
00028 #include "../../getopt.h"
00029 #include "../../scriba.h"
00030 #include "../../basext.h"
00031 #include "../../confpile.h"
00032 
00033 #if BCC32 || CYGWIN
00034 char *_pgmptr;
00035 #endif
00036 
00037 
00038 int GetC(void *f){ return getc((FILE *)f); }
00039 
00040 #ifdef _DEBUG
00041 #define ERREXIT do{getchar();scriba_destroy(pProgram);exit(iError);}while(0)
00042 #else
00043 #define ERREXIT exit(iError)
00044 #endif
00045 
00046 #ifdef WIN32
00047 main(int argc, char *argv[]){
00048 #else
00049   char **_environ;
00050 main(int argc, char *argv[], char *env[]){
00051 #endif
00052   int iError;
00053   int iErrorCounter;
00054   int OptionIndex;
00055   pSbProgram pProgram;
00056   char *pszForcedConfigurationFileName;
00057   unsigned long fErrorFlags;
00058   char *szInputFile,
00059        *szOutputFile;
00060   char *optarg,opt;
00061   /* the maximal number of preprocessors that are applied in chain */
00062 #define MAXPREPROC 100
00063   char *pszEPreproc[MAXPREPROC],*pszPreprocessedFileName;
00064   char *pszIPreproc[MAXPREPROC];
00065   int iEPreprocIndex,iIPreprocIndex;
00066   int giveusage,binarycode,nocache,iscgi,isCoutput,isEoutput;
00067   int execute,ConfCompile,ConfDump;
00068 #define FULL_PATH_BUFFER_LENGTH 256
00069   char CmdLinBuffer[FULL_PATH_BUFFER_LENGTH];
00070   extern int GlobalDebugDisplayFlag;
00071   long lOffset,lEOFfset;
00072   char *realArgv0;
00073 
00074 #ifdef __MACOS__
00075   argc = ccommand(&argv);
00076 #endif
00077 
00078 /*pSbData p,psb;
00079 SbData RetVale;*/
00080 #ifndef WIN32
00081   _environ = env;
00082 #endif
00083 
00084 #if BCC32 || CYGWIN
00085   _pgmptr = argv[0];
00086 #endif
00087 
00088 #ifdef _DEBUG
00089 #define malloc testa_Alloc
00090 #define free testa_Free
00091   testa_InitSegment();
00092 #endif
00093   /* default values for command line options */
00094   szInputFile = NULL;
00095   szOutputFile = NULL;
00096   ConfCompile = 0; /* the default action is to run BASIC program and not configuration file compilation */
00097   ConfDump    = 0; /* the default action is to run BASIC program and not configuration file dump */
00098   iEPreprocIndex = 0; /* no external preprocessor by default */
00099   iIPreprocIndex = 0; /* no internal preprocessor by default */
00100   pszPreprocessedFileName = NULL;
00101   *pszEPreproc = NULL; 
00102   *pszIPreproc = NULL;
00103   giveusage  = 0; /* assume the command line is correct, we need not display usage and stop */
00104   binarycode = 0; /* input is not binary by default */
00105   execute    = 0; /* do not execute by default after binary format save */
00106   nocache   = 0; /* we use cached code if it exists */
00107   OptionIndex = 0;
00108   iscgi = 0; /* by default this is not a cgi script, not HTTP/1.0 ... when error message is sent */
00109   isCoutput = 0;
00110   isEoutput = 0;
00111   pszForcedConfigurationFileName = NULL;
00112   GlobalDebugDisplayFlag = 0;
00113 
00114 #ifdef WIN32
00115   realArgv0 = _pgmptr;
00116 #else
00117   realArgv0 = argv[0];
00118 #endif
00119 
00120   /* if this exe contains the code itself then jump over it */
00121   if( build_GetExeCodeOffset(realArgv0,&lOffset,&lEOFfset) ){
00122     OptionIndex = 1;
00123     CmdLinBuffer[0] = (char)0;
00124     while( OptionIndex < argc ){
00125       strcat(CmdLinBuffer,argv[OptionIndex++]);
00126       if( OptionIndex < argc )
00127         strcat(CmdLinBuffer," ");
00128         }
00129     goto CmdLineFinished;
00130     }
00131 #define W(X) fprintf(stderr,"%s\n",X);
00132   while( (opt = getoptt(argc, argv, "Dkdf:p:i:CEcnvebo:",&optarg,&OptionIndex)) != ':'){
00133     switch( opt ){
00134       case 'k':
00135         if( ConfCompile ){
00136           giveusage = 1;
00137           W("Option -k was specified more than once.")
00138           }
00139         if( ConfDump ){
00140           giveusage = 1;
00141           W("Option -k can not be used together with -D")
00142           }
00143         ConfCompile = 1;
00144         break;
00145       case 'D':
00146         if( ConfCompile ){
00147           giveusage = 1;
00148           W("Option -k can not be used together with -D")
00149           }
00150         if( ConfDump ){
00151           giveusage = 1;
00152           W("Option -D was specified more than once.")
00153           }
00154         ConfDump = 1;
00155         break;
00156       case 'd' :
00157         if( GlobalDebugDisplayFlag ){
00158           giveusage = 1;
00159           W("Option -d was specified more than once.")
00160           }
00161         GlobalDebugDisplayFlag = 1;
00162         break;
00163       case 'p' :
00164         if( iEPreprocIndex >= MAXPREPROC-1 ){
00165           fprintf(stderr,"The maximum number of external preprocessors allowed on the command line is %d\nIt is exceeded.\n",MAXPREPROC);
00166           giveusage = 1;
00167           }else{
00168           pszEPreproc[iEPreprocIndex ++ ] = optarg;
00169           pszEPreproc[iEPreprocIndex] = NULL;
00170           }
00171          break;
00172       case 'i' :
00173         if( iIPreprocIndex >= MAXPREPROC-1 ){
00174           fprintf(stderr,"The maximum number of internal preprocessors allowed on the command line is %d\nIt is exceeded.\n",MAXPREPROC);
00175           giveusage = 1;
00176           }else{
00177           pszIPreproc[iIPreprocIndex ++ ] = optarg;
00178           pszIPreproc[iIPreprocIndex] = NULL;
00179           }
00180          break;
00181       case 'C' :
00182         if( isCoutput ){
00183           giveusage = 1;
00184           W("Option -C was specified more than once.")
00185           }
00186         isCoutput = 1;
00187         break;
00188       case 'E' :
00189         if( isEoutput ){
00190           giveusage = 1;
00191           W("Option -E was specified more than once.")
00192           }
00193         isEoutput = 1;
00194         break;
00195       case 'c' :
00196         if( iscgi ){
00197           giveusage = 1;
00198           W("Option -c was specified more than once.")
00199           }
00200         iscgi = 1;
00201         break;
00202       case 'n' :
00203         if( nocache ){
00204           giveusage = 1;
00205           W("Option -n was specified more than once.")
00206           }
00207         nocache = 1;
00208         break;
00209       case 'e' :
00210         if( execute ){
00211           giveusage = 1;
00212           W("Option -e was specified more than once.")
00213           }
00214         execute = 1;
00215         break;
00216       case 'f' :
00217         if( execute ){
00218           giveusage = 1;
00219           W("Option -f was specified more than once.")
00220           }
00221         pszForcedConfigurationFileName = optarg;
00222         break;
00223       case 'o' :
00224         if( szOutputFile || binarycode ){
00225           W("Using the option -o is invalid when the program is already binary.")
00226           giveusage = 1;
00227           }
00228         szOutputFile = optarg;
00229         break;
00230       case 'b':
00231         if( szOutputFile || binarycode ){
00232           W("Binary input file can not be used to produce output file.");
00233           giveusage = 1;
00234           }
00235         binarycode =1;
00236         break;
00237       case 'v':
00238 #define S fprintf(stderr,
00239 #define E );
00240                    S "ScriptBasic v%ld.%ld\n",VERSION_HIGH,VERSION_LOW E
00241                    S "Variation >>%s<< build %ld\n",VARIATION,SCRIPTBASIC_BUILD E
00242                    S "Magic value %lu\n",build_MagicCode(NULL) E
00243                    S "Node size is %d\n", sizeof(cNODE) E
00244                    S "Extension interface version is %d\n",INTERFACE_VERSION E
00245                    S "Compilation: %s %s\n", __DATE__,__TIME__ E
00246 #ifdef WIN32
00247                    S "Executable: %s\n", _pgmptr E
00248 #endif
00249         exit(0);
00250       case '!' :
00251         W("Invalid option.");
00252         giveusage = 1;
00253         break;
00254       case '?':
00255         if( szInputFile ){
00256           W("Only one input file can be specified. YOu should not see this error message.");
00257           giveusage = 1;
00258           }
00259         szInputFile = optarg;
00260         CmdLinBuffer[0] = (char)0;
00261         while( OptionIndex < argc ){
00262           strcat(CmdLinBuffer,argv[OptionIndex++]);
00263           if( OptionIndex < argc )
00264             strcat(CmdLinBuffer," ");
00265           }
00266         goto CmdLineFinished;
00267       }
00268     }
00269 
00270 CmdLineFinished:
00271   if( execute && binarycode ){
00272     W("The option -e and binary input file can not be used together.");
00273     giveusage=1;
00274     }
00275   if( isCoutput && !szOutputFile ){
00276     W("To generate C file an output file has to be specified.");
00277     giveusage=1;
00278     }
00279   if( isEoutput && !szOutputFile ){
00280     W("To generate executable file an output file has to be specified.");
00281     giveusage=1;
00282     }
00283   /* This is to be a bit more safe with include files changed. Be sure to compile the final version of the BASIC program. */
00284   if( isEoutput || isCoutput )nocache = 1;
00285   if( iIPreprocIndex )nocache = 1;
00286 /* NOTE: that external preprocessor effects can be cached!
00287   if( iEPreprocIndex )nocache = 1;
00288    On the other hand internal preprocessor provided on the
00289    command-line (and not in the source 'use' commands)
00290    is most probably a debugger or profiler, thus no caching
00291    should be done, because if we use the cache the program
00292    runs without having the preprocessor in effect.
00293 */
00294   if( (!lOffset) && (!ConfDump) && (!ConfCompile) && szInputFile == NULL || giveusage ){
00295 #define U(x) fprintf(stderr,"%s\n",(x));
00296     U("Usage: basic [options] program.bas")
00297     U("")
00298     U("options: -o file_name")
00299     U("            specify output file, save binary format to file but don't execute")
00300     U("         -b file_name")
00301     U("            load binary format from file and execute")
00302     U("         -n")
00303     U("            do not use cache (no save, no load)")
00304     U("         -e")
00305     U("            execute after binary format was saved")
00306     U("         -v")
00307     U("            print version info and stop")
00308     U("         -c")
00309     U("            inform scriba that this is a CGI script.")
00310     U("         -C");
00311     U("            save C program output.");
00312     U("         -E");
00313     U("            save executable output. (may not work under some OS)");
00314     U("         -p preprocessor");
00315     U("            specify external preprocessor.");
00316     U("         -i preprocessor");
00317     U("            specify internal preprocessor.");
00318     U("         -f configurationfile");
00319     U("            specify configuration file");
00320     U("         -d");
00321     U("            debug module error (UNIX only)");
00322     U("         -k text_config_file");
00323     U("            compile the configuration file to binary");
00324     U("         -D");
00325     U("            dump the configuration file in text format");
00326     exit(1);
00327     }
00328   pProgram = scriba_new(malloc,free);
00329   if( pProgram == NULL ){
00330     iError = COMMAND_ERROR_MEMORY_LOW;
00331     ERREXIT;
00332     }
00333   /* if the user has specified the option -D then the input file is the compiled configuration file.
00334       */
00335   if( ConfDump ){
00336     /* the output file has to be specified, because that is where we dump the tex format config file */
00337     if( szOutputFile == NULL )
00338       szOutputFile = "STDOUT";
00339 
00340     pProgram->pCONF = alloc_Alloc(sizeof(tConfigTree),pProgram->pMEM);
00341     if( pProgram->pCONF == NULL ){
00342       iError = COMMAND_ERROR_MEMORY_LOW;
00343       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00344       exit(1);
00345       }
00346     iError = cft_init(pProgram->pCONF,NULL,NULL,NULL);
00347     if( iError ){
00348       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00349       exit(1);
00350       }
00351     if( pszForcedConfigurationFileName == NULL ){
00352       iError = scriba_GetConfigFileName(pProgram,&pszForcedConfigurationFileName);
00353       if( iError ){
00354         report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00355         exit(1);
00356         }
00357       }
00358     iError = cft_ReadConfig(pProgram->pCONF,pszForcedConfigurationFileName);
00359     if( iError != 0 ){
00360       fprintf(stderr,"Configuration file %s can not be processed.\n",pszForcedConfigurationFileName);
00361       exit(1);
00362       }
00363     iError = cft_DumpConfig(pProgram->pCONF,szOutputFile);
00364     if( iError != 0 ){
00365       fprintf(stderr,"Output file %s can not be processed.\n",szOutputFile);
00366       exit(iError);
00367       }
00368     exit(0);
00369     }
00370   /* If the user has specified the option -k then the input file is the configuration file.
00371      Now we compile the configuration file and do not run any program. This is more convenient
00372      then the older version using the external program cftc because cftc required two arguments:
00373 
00374      configuration file in text format
00375      compiled output configuration file name
00376 
00377      scriba -k on the other hand requires only the text configuration file name and saves
00378      the configuration file into the file name, where it will search for the configuration file
00379      when it runs a BASIC program.   */
00380   if( ConfCompile ){
00381     if( NULL == szInputFile ){
00382       fprintf(stderr,"The option '-k' needs argument (the name of the config text file)\n");
00383       exit(1);
00384       }
00385     pProgram->pCONF = alloc_Alloc(sizeof(tConfigTree),pProgram->pMEM);
00386     if( pProgram->pCONF == NULL ){
00387       iError = COMMAND_ERROR_MEMORY_LOW;
00388       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00389       ERREXIT;
00390       }
00391     iError = cft_init(pProgram->pCONF,NULL,NULL,NULL);
00392     if( iError ){
00393       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00394       ERREXIT;
00395       }
00396     if( pszForcedConfigurationFileName == NULL ){
00397       iError = scriba_GetConfigFileName(pProgram,&pszForcedConfigurationFileName);
00398       if( iError ){
00399         report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00400         ERREXIT;
00401         }
00402       }
00403     iError = cft_ReadTextConfig(pProgram->pCONF,szInputFile);
00404     switch( iError ){
00405       case CFT_ERROR_FILE:
00406         fprintf(stderr,"The file %s can not be read.\n",szInputFile);
00407         exit(1);
00408       case CFT_ERROR_EMPTY:
00409         fprintf(stderr,"The file %s contains no configuration information.\n",szInputFile);
00410         exit(1);
00411       case CFT_ERROR_SYNTAX:
00412         fprintf(stderr,"The file %s has syntax error in it.\n",szInputFile);
00413         exit(1);
00414       case CFT_ERROR_MEMORY:
00415         fprintf(stderr,"Memory exhausted while processing the file %s\n",szInputFile);
00416         exit(1);
00417       }
00418     iError = cft_WriteConfig(pProgram->pCONF,pszForcedConfigurationFileName);
00419     switch( iError ){
00420       case CFT_ERROR_FILE:
00421         fprintf(stderr,"The file %s can not be written\n",pszForcedConfigurationFileName);
00422         exit(1);
00423       case CFT_ERROR_MEMORY:
00424         fprintf(stderr,"Memory exhausted while writing the file %s\n",pszForcedConfigurationFileName);
00425         exit(1);
00426       }
00427     fprintf(stderr,"The configuration file '%s' was created.\n",pszForcedConfigurationFileName);
00428     exit(0);
00429     }
00430 
00431   scriba_LoadConfiguration(pProgram,pszForcedConfigurationFileName);
00432 
00433 #if _DEBUG
00434 testa_Assert0x80();
00435 #endif
00436   iError = scriba_LoadInternalPreprocessor(pProgram,pszIPreproc);
00437 #if _DEBUG
00438 testa_Assert0x80();
00439 #endif
00440   if( iError ){
00441     report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00442     ERREXIT;
00443     }
00444 
00445   if( iscgi )scriba_SetCgiFlag(pProgram);
00446 #if _DEBUG
00447 testa_Assert0x80();
00448 #endif
00449   if( lOffset )
00450     scriba_SetFileName(pProgram,realArgv0);
00451   else
00452     scriba_SetFileName(pProgram,szInputFile);
00453 #if _DEBUG
00454 testa_Assert0x80();
00455 #endif
00456 
00457   if( (!nocache) && scriba_UseCacheFile(pProgram) == SCRIBA_ERROR_SUCCESS )binarycode = 1;
00458   if( lOffset )binarycode = 1;
00459   if( binarycode || scriba_IsFileBinaryFormat(pProgram) ){
00460     if( (iError = scriba_LoadBinaryProgramWithOffset(pProgram,lOffset,lEOFfset)) != 0 ){
00461       ERREXIT;
00462       }
00463     }else{
00464     if( iError=scriba_RunExternalPreprocessor(pProgram,pszEPreproc) ){
00465       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00466       ERREXIT;
00467       }
00468     if( scriba_LoadSourceProgram(pProgram) )ERREXIT;
00469     if( szOutputFile ){
00470       if( isCoutput )
00471         scriba_SaveCCode(pProgram,szOutputFile);
00472       else
00473       if( isEoutput )
00474         scriba_SaveECode(pProgram,realArgv0,szOutputFile);
00475       else
00476         scriba_SaveCode(pProgram,szOutputFile);
00477       if( !execute )exit(0);
00478       }
00479      if( ! nocache )scriba_SaveCacheFile(pProgram);
00480     }
00481 /*
00482   {FILE *fb; fb = fopen("dumpcode.txt","w");
00483   build_pprint(pProgram->pBUILD,fb);fclose(fb);}
00484 */
00485 /*#define PRGSTR "print \"hello\\n\"\n\
00486 include \"test.bas\"\
00487 "
00488   scriba_LoadProgramString(pProgram,PRGSTR,strlen(PRGSTR));
00489 */
00490   if( iError=scriba_Run(pProgram,CmdLinBuffer) ){
00491 #if _DEBUG
00492 testa_Assert0x80();
00493 #endif
00494     if( iError > 0 )
00495       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00496     else
00497       iError = -iError;
00498     ERREXIT;
00499     }
00500 #if _DEBUG
00501 testa_Assert0x80();
00502 #endif
00503 
00504 /*
00505 {
00506 unsigned long i=0;
00507 unsigned long min,max,act;
00508 pSbData pRetVale;
00509   while( 1 ){
00510     i++;
00511     if( i%10000 == 0 ){
00512       testa_ReportLeak();
00513 #define PRSEG(X)      alloc_GetStat(X,&min,&max,&act);printf("Segment %s is %d\n",#X,act);
00514       PRSEG(pProgram->pMEM);
00515       PRSEG(pProgram->pEXE->pMo);
00516       PRSEG(pProgram->pEXE->pMemorySegment);
00517       printf("kukk %d\n",i/10000);
00518       getchar();
00519       }
00520     pRetVale = scriba_NewSbData(pProgram);
00521     scriba_CallArgEx(pProgram,scriba_LookupFunctionByName(pProgram,"main::pred_1"),pRetVale,0,NULL);
00522     scriba_DestroySbData(pProgram,pRetVale);
00523     }
00524 }
00525 
00526   printf("testvar type is %d\n",scriba_GetVariableType(pProgram,
00527   scriba_LookupVariableByName(pProgram,"main::testvar")));
00528   scriba_GetVariable(pProgram,
00529                      scriba_LookupVariableByName(pProgram,"main::testvar"),
00530                      &psb
00531     );
00532   printf("testvar from C is %s\n",scriba_GetString(pProgram,*psb));
00533 
00534   scriba_SetVariable(pProgram,scriba_LookupVariableByName(pProgram,"main::testvar"),
00535                      SBT_ZCHAR,1,2.2,"kukac",4);
00536   scriba_CallArgEx(pProgram,scriba_LookupFunctionByName(pProgram,"main::thatfunc"),&RetVale,4,p);
00537 */
00538   scriba_destroy(pProgram);
00539 
00540 #ifdef _DEBUG
00541   testa_AssertLeak();
00542   if( ! iscgi ){
00543     printf("\nPress any key to continue...\n");
00544     getchar();
00545     }
00546 #endif
00547   exit(iError);
00548   }
00549 

Generated on Sun Mar 12 23:56:32 2006 for ScriptBasic by  doxygen 1.4.6-NO