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

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 
00005 #include "../../getopt.h"
00006 #include "../../report.h"
00007 #include "../../lexer.h"
00008 #include "../../sym.h"
00009 #include "../../expression.h"
00010 #include "../../syntax.h"
00011 #include "../../reader.h"
00012 #include "../../myalloc.h"
00013 #include "../../builder.h"
00014 #include "../../memory.h"
00015 #include "../../execute.h"
00016 #include "../../buildnum.h"
00017 #include "../../conftree.h"
00018 #include "../../filesys.h"
00019 #include "../../errcodes.h"
00020 #include "../../testalloc.h"
00021 #include "../../basext.h"
00022 #include "../../epreproc.h"
00023 #include "../../uniqfnam.h"
00024 
00025 int GetC(void *f){ return getc((FILE *)f); }
00026 
00027 #if BCC32
00028 char *_pgmptr;
00029 #endif
00030 
00031 #ifdef WIN32
00032 main(int argc, char *argv[]){
00033 #else
00034 char **_environ;
00035 main(int argc, char *argv[], char *env[]){
00036 #endif
00037   int OptionIndex;
00038   LexObject MyLEX;
00039   ReadObject MyREAD;
00040   BuildObject MyBUILD;
00041   tConfigTree MyCONF;
00042   char *pszForcedConfigurationFileName;
00043   void *pMEM;
00044   eXobject MyEX;
00045   ExecuteObject MyEXE;
00046   peNODE_l CommandList;
00047   int iError,iErrorCounter;
00048   unsigned long fErrorFlags;
00049   char *szInputFile,
00050        *szOutputFile;
00051   char *optarg,opt;
00052   /* the maximal number of preprocessors that are applied in chain */
00053 #define MAXPREPROC 100
00054   char *pszEPreproc[MAXPREPROC],*pszPreprocessedFileName;
00055   int iPreprocIndex;
00056   int giveusage,binarycode,nocache,iscgi,isCoutput;
00057   int execute;
00058 #define FULL_PATH_BUFFER_LENGTH 256
00059   char CmdLinBuffer[FULL_PATH_BUFFER_LENGTH],*szCache,*s,*q;
00060   char Argv0[FULL_PATH_BUFFER_LENGTH];
00061   char CachedFileName[FULL_PATH_BUFFER_LENGTH];
00062   unsigned long FileTime,CacheTime;
00063 #ifndef WIN32
00064   _environ = env;
00065 #if BCC32
00066   _pgptr = argv[0];
00067 #endif
00068 #endif
00069 
00070 #ifdef _DEBUG
00071 #define malloc testa_Alloc
00072 #define free testa_Free
00073   testa_InitSegment();
00074 #endif
00075 
00076   /* default values for command line options */
00077   szInputFile = NULL;
00078   szOutputFile = NULL;
00079   iPreprocIndex = 0; /* no external preprocessor by default */
00080   pszPreprocessedFileName = NULL;
00081   *pszEPreproc = NULL; 
00082   giveusage  = 0; /* assume the command line is correct, we need not display usage and stop */
00083   binarycode = 0; /* input is not binary by default */
00084   execute    = 0; /* do not execute by default after binary format save */
00085   nocache   = 0; /* we use cached code if it exists */
00086   OptionIndex = 0;
00087   iscgi = 0; /* by default this is not a cgi script, not HTTP/1.0 ... when error message is sent */
00088   isCoutput = 0;
00089   pszForcedConfigurationFileName = NULL;
00090 
00091   while( (opt = getoptt(argc, argv, "f:pCcnvebo:",&optarg,&OptionIndex)) != ':'){
00092     switch( opt ){
00093       case 'p' :
00094         if( iPreprocIndex >= MAXPREPROC-1 )
00095           giveusage = 1;
00096         else{
00097           pszEPreproc[iPreprocIndex ++ ] = optarg;
00098           pszEPreproc[iPreprocIndex] = NULL;
00099           }
00100          break;
00101       case 'C' :
00102         if( isCoutput )giveusage = 1;
00103         isCoutput = 1;
00104         break;
00105       case 'c' :
00106         if( iscgi )giveusage = 1;
00107         iscgi = 1;
00108         break;
00109       case 'n' :
00110         if( nocache )giveusage = 1;
00111         nocache = 1;
00112         break;
00113       case 'e' :
00114         if( execute )giveusage = 1;
00115         execute = 1;
00116         break;
00117       case 'f' :
00118         if( pszForcedConfigurationFileName )giveusage = 1;
00119         pszForcedConfigurationFileName = optarg;
00120         break;
00121       case 'o' :
00122         if( szOutputFile || binarycode )giveusage = 1;
00123         szOutputFile = optarg;
00124         break;
00125       case 'b':
00126         if( szOutputFile || binarycode )giveusage = 1;
00127         binarycode =1;
00128         break;
00129       case 'v':
00130 #define S fprintf(stderr,
00131 #define E );
00132                    S "ScriptBasic v%ld.%ld\n",VERSION_HIGH,VERSION_LOW E
00133                    S "Variation >>%s<< build %ld\n",VARIATION,SCRIPTBASIC_BUILD E
00134                    S "Magic value %lu\n",build_MagicCode(NULL) E
00135                    S "Node size is %d\n", sizeof(cNODE) E
00136                    S "Extension interface version is %d\n",INTERFACE_VERSION E
00137                    S "Compilation: %s %s\n", __DATE__,__TIME__ E
00138         exit(0);
00139       case '!' :
00140         giveusage = 1;
00141         break;
00142       case '?':
00143         if( szInputFile )giveusage = 1;
00144         szInputFile = optarg;
00145         CmdLinBuffer[0] = (char)0;
00146         while( OptionIndex < argc ){
00147           strcat(CmdLinBuffer,argv[OptionIndex++]);
00148           if( OptionIndex < argc )
00149             strcat(CmdLinBuffer," ");
00150           }
00151         goto CmdLineFinished;
00152       }
00153     }
00154 
00155 CmdLineFinished:
00156   if( execute && binarycode )giveusage=1;
00157   if( isCoutput && !szOutputFile )giveusage=1;
00158 
00159   if( szInputFile == NULL || giveusage ){
00160 #define U(x) fprintf(stderr,"%s\n",(x));
00161     U("Usage: basic [options] program.bas")
00162     U("")
00163     U("options: -o file_name")
00164     U("            save binary format to file but don't execute")
00165     U("         -b file_name")
00166     U("            load binary format from file and execute")
00167     U("         -n")
00168     U("            do not use cache (no save, no load)")
00169     U("         -e")
00170     U("            execute after binary format was saved")
00171     U("         -v")
00172     U("            print version info and stop")
00173     U("         -c")
00174     U("            inform scriba that this is a CGI script.")
00175     U("         -C");
00176     U("            save C program output.");
00177     U("         -p preprocessor");
00178     U("            specify preprocessor.");
00179     U("         -f configurationfile");
00180     U("            specify configuration file");
00181     exit(1);
00182     }
00183 
00184   pMEM = alloc_InitSegment(malloc,free);
00185   if( pMEM == NULL ){
00186     fprintf(stderr,"No memory\n");
00187     exit(1);
00188     }
00189 
00190   cft_start(&MyCONF,alloc_Alloc,alloc_Free,pMEM,
00191 #ifdef WIN32
00192             "Software\\ScriptBasic\\config",
00193             "WINNT\\SCRIBA.INI",
00194 #else
00195             "SCRIBACONF",
00196             "/etc/scriba/basic.conf",
00197 #endif
00198             pszForcedConfigurationFileName);
00199 
00200   szCache = nocache ? NULL : cft_GetString(&MyCONF,"cache");
00201   if( szCache ){
00202     strcpy(CachedFileName,szCache);
00203     s = CachedFileName + strlen(CachedFileName); /* point to the end of the cache directory */
00204 
00205 #ifdef WIN32
00206 /* under Win32 we convert the argv[0] to the full path file name */
00207     if( GetFullPathName(szInputFile,
00208                         FULL_PATH_BUFFER_LENGTH-strlen(CachedFileName),s,&q)==0 )
00209       goto UseNoCache;
00210 #else
00211 /* under UNIX we can not convert, but it usually contains the full path */
00212     strcpy(s,szInputFile);
00213 #endif
00214     strcpy(Argv0,s);
00215     uniqfnam(s,s);
00216     FileTime  = file_time_modified(szInputFile);
00217     CacheTime = file_time_modified(CachedFileName);
00218     if( FileTime && CacheTime && CacheTime > FileTime ){
00219       szInputFile = CachedFileName;
00220       /* Check that the cache file is in correct format.
00221          This call will help upgrade without deleting the cache
00222          files. Former versions tried to load the binary code created by
00223          a previous version of scriba and resulted error messages
00224          complaining about corrupt binary file whe trying to execute
00225          a syntactically correct BASIC program.      */
00226       binarycode = build_IsFileBinaryFormat(szInputFile);
00227       }
00228     }else{/* if no cache is configured */
00229 #ifdef WIN32
00230     if( GetFullPathName(szInputFile,
00231                       FULL_PATH_BUFFER_LENGTH,Argv0,&q) == 0 )
00232 #endif
00233     strcpy(Argv0,szInputFile);
00234     }
00235 UseNoCache:
00236 
00237 
00238   if( binarycode || build_IsFileBinaryFormat(szInputFile) ){
00239     /* the code is given as a compiled code */
00240     MyBUILD.memory_allocating_function = malloc;
00241     MyBUILD.memory_releasing_function  = free;
00242     MyBUILD.iErrorCounter = 0;
00243     MyBUILD.reportptr = (void *)stderr;
00244     MyBUILD.report   = report_report;
00245     MyBUILD.fErrorFlags = iscgi ? REPORT_F_CGI : 0;
00246     build_LoadCode(&MyBUILD,szInputFile);
00247     if( MyBUILD.iErrorCounter ){
00248 #ifdef _DEBUG
00249       getchar();
00250 #endif
00251       exit(1);
00252       }
00253         binarycode = 1;
00254     }else{
00255         binarycode = 0;/* this signals that we are reading non binary code */
00256     /* the code is source code basic text format */
00257     fErrorFlags = iscgi ? REPORT_F_CGI : 0;
00258     iErrorCounter = 0;
00259     iError = epreproc(&MyCONF,szInputFile,&pszPreprocessedFileName,pszEPreproc,malloc,free);
00260     if( iError ){
00261       report_report(stderr,"",0,iError,REPORT_ERROR,&iErrorCounter,NULL,&fErrorFlags);
00262 #ifdef _DEBUG
00263       getchar();
00264 #endif
00265       /* there were errors during preprocess */
00266       exit(1);
00267       }
00268 
00269     /* read the lines of the program */
00270     reader_InitStructure(&MyREAD);
00271     MyREAD.memory_allocating_function = alloc_Alloc;
00272     MyREAD.memory_releasing_function = alloc_Free;
00273     MyREAD.pMemorySegment = alloc_InitSegment(malloc,free);
00274     MyREAD.report = report_report;
00275     MyREAD.reportptr = (void *)stderr;
00276     MyREAD.iErrorCounter = 0;
00277     MyREAD.fErrorFlags = iscgi ? REPORT_F_CGI : 0;
00278     MyREAD.pConfig = &MyCONF;
00279     if( pszPreprocessedFileName )
00280       reader_ReadLines(&MyREAD,pszPreprocessedFileName);
00281     else
00282       reader_ReadLines(&MyREAD,szInputFile);
00283 
00284 /*    reader_DumpLines(&MyREAD,stderr); */
00285 
00286     if( MyREAD.iErrorCounter ){
00287 #ifdef _DEBUG
00288       getchar();
00289 #endif
00290       /* there were errors during lexical analisys */
00291       exit(1);
00292       }
00293 
00294     reader_StartIteration(&MyREAD);
00295 
00296     MyLEX.memory_allocating_function = alloc_Alloc;
00297     MyLEX.memory_releasing_function = alloc_Free;
00298     MyLEX.pMemorySegment = alloc_InitSegment(malloc,free);
00299     lex_InitStructure(&MyLEX);
00300 
00301     MyLEX.pfGetCharacter = reader_NextCharacter;
00302     MyLEX.pfFileName = reader_FileName;
00303     MyLEX.pfLineNumber = reader_LineNumber;
00304 
00305     MyLEX.pNASymbols = NASYMBOLS;
00306     MyLEX.pASymbols  = ASYMBOLS;
00307     MyLEX.pCSymbols  = CSYMBOLS;
00308     MyLEX.report = report_report;
00309     MyLEX.reportptr = (void *)stderr;
00310     MyLEX.fErrorFlags = MyREAD.fErrorFlags;
00311     MyLEX.iErrorCounter = 0;
00312     MyLEX.pLexResult = (void *)stderr;
00313 
00314 
00315     MyLEX.pvInput = (void *)&MyREAD;
00316     lex_ReadInput(&MyLEX);
00317 
00318     if( MyLEX.iErrorCounter ){
00319 #ifdef _DEBUG
00320       getchar();
00321 #endif
00322       /* there were errors during lexical analisys */
00323       exit(1);
00324       }
00325 
00326     lex_RemoveComments(&MyLEX);
00327     lex_HandleContinuationLines(&MyLEX);
00328 
00329     MyEX.memory_allocating_function = malloc;
00330     MyEX.memory_releasing_function = free;
00331     MyEX.cbBuffer = 1024; /* init will allocate the space of this number of characters */
00332     MyEX.cbCurrentNameSpace = 1024; /* init will allocate the space of this number of characters */
00333     MyEX.pLex = &MyLEX;
00334 
00335     MyEX.Unaries  = UNARIES;
00336     MyEX.Binaries = BINARIES;
00337     MyEX.BuiltInFunctions = INTERNALFUNCTIONS;
00338     MyEX.MAXPREC  = MAX_BINARY_OPERATOR_PRECEDENCE;
00339     MyEX.PredeclaredLongConstants = PREDLCONSTS;
00340     MyEX.reportptr = (void *)stderr;
00341     MyEX.report   = report_report;
00342     MyEX.fErrorFlags = MyLEX.fErrorFlags;
00343     MyEX.iErrorCounter = 0;
00344 
00345     MyEX.Command = COMMANDS;
00346 
00347     ex_init(&MyEX);
00348 
00349     ex_Command_l(&MyEX,&CommandList);
00350 
00351     if( MyEX.iErrorCounter ){
00352 #ifdef _DEBUG
00353       getchar();
00354 #endif
00355       exit(1);
00356       }
00357 
00358     MyEX.pCommandList = CommandList;
00359 
00360     MyBUILD.memory_allocating_function = malloc;
00361     MyBUILD.memory_releasing_function  = free;
00362     MyBUILD.pEx = &MyEX;
00363     MyBUILD.iErrorCounter = 0;
00364     MyBUILD.fErrorFlags = MyEX.fErrorFlags;
00365     MyBUILD.FirstUNIXline = MyREAD.FirstUNIXline;
00366 
00367     build_Build(&MyBUILD);
00368 
00369 /*
00370 #ifdef _DEBUG
00371     build_pprint(&MyBUILD,stdout);
00372     getchar();
00373 #endif
00374 */
00375     if( MyBUILD.iErrorCounter ){
00376 #ifdef _DEBUG
00377       getchar();
00378 #endif
00379       exit(1);
00380       }
00381 
00382     /* This is the very first place where we can relase the reader memory
00383        because syntax error messages point to the file name strings that are reserved
00384        by the reader. */
00385     alloc_FinishSegment(MyLEX.pMemorySegment);
00386     ex_free(&MyEX);
00387 
00388     if( szOutputFile ){
00389       if( isCoutput )
00390         build_SaveCCode(&MyBUILD,szOutputFile);
00391       else
00392         build_SaveCode(&MyBUILD,szOutputFile);
00393       if( !execute )exit(0);
00394       }
00395     if( szCache ){
00396       build_SaveCode(&MyBUILD,CachedFileName);
00397       }
00398     /* Reader memory segment is needed up to here, because FirstUNIXline still
00399        belons to this segment and is used by save code. */
00400     alloc_FinishSegment(MyREAD.pMemorySegment);
00401     }/* non binary code */
00402 
00403   MyEXE.memory_allocating_function = malloc;
00404   MyEXE.memory_releasing_function = free;
00405   MyEXE.reportptr = (void *)stderr;
00406   MyEXE.report   = report_report;
00407   if( binarycode )
00408         MyEXE.fErrorFlags = iscgi ? REPORT_F_CGI : 0;
00409   else
00410     MyEXE.fErrorFlags = MyEX.fErrorFlags;
00411 
00412   MyEXE.pConfig = &MyCONF;
00413 /*  MyEXE.Argv0 = Argv0; */
00414   build_MagicCode(&(MyEXE.Ver));
00415   if( execute_InitStructure(&MyEXE,&MyBUILD) ){
00416     MyEXE.report(MyEXE.reportptr,
00417                  "",
00418                  0,
00419                  COMMAND_ERROR_MEMORY_LOW,
00420                  REPORT_ERROR,
00421                  &iError,
00422                  "",
00423                  &(MyEXE.fErrorFlags));
00424 #ifdef _DEBUG
00425     getchar();
00426 #endif
00427     exit(1);
00428     }
00429 /*
00430   We could alter the standard input, standard output, the environment
00431   function and command arguments here . We do only the command
00432   arguments here in this variation.
00433 */
00434   MyEXE.CmdLineArgument = CmdLinBuffer;  
00435 
00436   execute_Execute(&MyEXE,&iError);
00437   alloc_FinishSegment(MyEXE.pMo->pMemorySegment);
00438   alloc_FinishSegment(MyEXE.pMemorySegment);
00439   alloc_FinishSegment(MyBUILD.pMemorySegment);
00440   alloc_FinishSegment(MyCONF.pMemorySegment);
00441   if( pszPreprocessedFileName )free(pszPreprocessedFileName);
00442 
00443 #ifdef _DEBUG
00444   testa_AssertLeak();
00445   printf("Press any key to continue...\n");
00446   getchar();
00447 #endif
00448   if( iError )exit(1); else exit(0);
00449   }
00450 

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