* script.prg * by Dave Leigh * copyright September 1996 * * This script tool is obviously limited in that it doesn't compile files and * do the usual loops and scans, etc. After all, it's designed to run uncompiled * source files from a simulated command prompt. (*C'mon* haven't you ever * needed to be able to write a quick and dirty script while at a client who * didn't have the compiler?) * * Syntax: * =script("filename") * OR * DO script WITH "filename" * IF no parameter is given then it calls the getfile dialog. * * * SCRIPT.PRG does allow multiple lines ending in semicolons and two branching * keywords: *JUMP and *LABEL. These are both expected to be followed by a single * space followed by a string label(it's picky about that format, too!) Although * these are unconditional and so not extremely useful, I included them so * I could quickly disable blocks of code from a script. * * It also allows a rudimentary FOR...NEXT that supports LOOP and STEP, but not * EXIT. To simulate SCAN...ENDSCAN, store the number of records to a variable, * then use FOR...NEXT to execute the loop. Remember to put the SKIP prior to the * NEXT (after SELECTing the proper workspace). * LPARAMETER cScriptFile #INCLUDE code\include\strings.h LOCAL nFileHandle, ; cTemp1, ; cTemp2, ; cCommand, ; cSaveEscape ON ERROR DO scripterror cSaveEscape = SET("ESCAPE") SET ESCAPE ON IF PARAMETERS() = 0 cScriptFile = GETFILE("PRG|SCR|TXT", "Script File:") ENDIF IF FILE(cScriptFile) * open the file nFileHandle=FOPEN(cScriptFile) * Read the file one line at a time and execute. DO WHILE NOT FEOF(nFileHandle) * extract the next line. cCommand = ALLTRIM(FGETS(nFileHandle)) * if the command spans multiple lines then concatenate them, removing the semicolons. DO WHILE RIGHT(cCommand, 1) = ";" cTemp1 = "" cTemp2 = "" * i didn't use STRTRAN below because I wanted to allow semicolons in strings cTemp1 = cCommand cTemp1 = LEFT(cTemp1, LEN(cTemp1) - 1) IF NOT FEOF(nFileHandle) cTemp2 = ALLTRIM(FGETS(nFileHandle)) ENDIF cCommand = cTemp1 + " " + cTemp2 ENDDO * process the command. DO CASE CASE LEFT(cCommand, 4) = "FOR " =ScriptBeginFor(cCommand, nFileHandle) CASE LEFT(cCommand, 4) $ "NEXT~ENDF~LOOP" =ScriptEndFor(cCommand, nFileHandle) CASE LEFT(cCommand, 5) = "*JUMP" * if the *JUMP directive is in here, then process it =ScriptJump(cCommand, nFileHandle) CASE LEFT(cCommand, 6) = "*LABEL" * skip these without comment CASE LEFT(cCommand, 4) $ "SCAN~ENDS" WAIT WINDOW "Feature not supported by SCRIPT.PRG" TIMEOUT 4 OTHERWISE * macro that line in as the next line of the script. &cCommand. ENDCASE ENDDO =FCLOSE(nFileHandle) ELSE =MESSAGEBOX("Script aborted.", MB_OK + MB_ICONEXCLAMATION, "Script Processor") ENDIF * set up to exit ON ERROR SET ESCAPE &cSaveEscape RELEASE nFOR_Position, ; nFOR_Begin, ; nFOR_End, ; nFOR_Step, ; cFOR_Variable, ; &cFOR_Variable. RETURN *------------------------------------------------------------------------------------------- PROCEDURE scripterror IF TYPE("nFileHandle") <> "U" =FCLOSE(nFileHandle) ENDIF =MESSAGEBOX("Fatal Error! " + MESSAGE() , MB_OK + MB_ICONEXCLAMATION, "Script Processor") CANCEL RETURN *------------------------------------------------------------------------------------------- FUNCTION scriptjump LPARAMETERS cLabel, nFileHandle LOCAL cTemp, ; nSavePosition * parse the label first: cLabel = ALLTRIM(STRTRAN(cLabel, "*JUMP", "")) cLabel = "*LABEL " + cLabel cLabel = UPPER(cLabel) * go to the beginning of the file and save the current location * in case of failure nSavePosition = FSEEK(nFileHandle,0,1) =FSEEK(nFileHandle, 0, 0) * now search for the Label you specified cTemp = ALLTRIM(FGETS(nFileHandle)) DO WHILE UPPER(ALLTRIM(cTemp)) <> cLabel AND NOT FEOF(nFileHandle) cTemp = ALLTRIM(FGETS(nFileHandle)) ENDDO IF FEOF(nFileHandle) * Couldn't find the label, go back to where we were... WAIT WINDOW TIMEOUT 2 "LABEL NOT FOUND" =FSEEK(nFileHandle, nSavePosition, 0) ELSE * otherwise, there's nothing really to do. Just return ENDIF RETURN *------------------------------------------------------------------------------------------- FUNCTION scriptbeginfor * this one has to initialize a public variable for the loop, and store the * ending condition. NOTE THAT IT DOESN'T CHECK THE CONDITION UNTIL THE END! * This means that at least one pass will be made through the script, as in * Apple Integer BASIC. It also saves the offset of command itself into a public variable, * so it can be located later in the loop. PARAMETERS cCommand, nFileHandle cCommand = UPPER(cCommand) LOCAL cTemp, ; c1stArg, ; c2ndArg, ; c3rdArg * save the ForPosition for the Loop. PUBLIC nFOR_Position, ; nFOR_Begin, ; nFOR_End, ; nFOR_Step, ; cFOR_Variable nFOR_Position = FSEEK(nFileHandle, 0, 1) * Parse the argument into BeginVariable, EndVariable, and StepVariable * The First Argument is from the FOR to the TO and includes the statement needed to initialize * the variable! c1stArg = STRTRAN(cCommand, "FOR ", "") && drop the FOR c1stArg = LEFT(c1stArg, AT(" TO ", c1stArg) - 1) cFOR_Variable = ALLTRIM(LEFT(c1stArg, AT("=", c1stArg) - 1)) cTemp = RIGHT(c1stArg, LEN(c1stArg) - AT("=", c1stArg)) nFOR_Begin = VAL(ALLTRIM(cTemp)) ? cCommand * Isolate the 3rd argument (everything to the right of STEP IF AT("STEP", cCommand) > 0 c3rdArg = RIGHT(cCommand, LEN(cCommand) - AT(" STEP", cCommand)) cFOR_Step = ALLTRIM(STRTRAN(c3rdArg, "STEP", "")) nFOR_Step = VAL(ALLTRIM(cFOR_Step)) ELSE c3rdArg = " " nFOR_STEP = 1 ENDIF * Isolate the 2nd argument (everything left over) c2ndArg = STRTRAN(cCommand, "FOR ", "") c2ndArg = STRTRAN(c2ndArg, c1stArg, "") c2ndArg = STRTRAN(c2ndArg, " TO ", "") c2ndArg = STRTRAN(c2ndArg, c3rdArg, "") nFOR_End = VAL(ALLTRIM(c2ndArg)) PUBLIC &cFOR_variable &cFOR_variable. = nFor_Begin RETURN *------------------------------------------------------------------------------------------- FUNCTION scriptendfor * this one has to check the condition, increment the variable according to the STEP * and perform the LOOP back to the FOR statement. LPARAMETERS cArgument, nFileHandle * These were set up before, and should be available now: * PUBLIC nFOR_Position, ; * nFOR_Begin, ; * nFOR_End, ; * nFOR_Step, ; * cFOR_Variable * * in addition, the variable represented by cFOR_variable was * declared PUBLIC. We'll need to keep it up for any * calculations done in the loop. * OK, put the file pointer to the saved position. IF &cFOR_Variable. + nFOR_STEP > nFOR_END * you've finished the loop. do nothing ELSE &cFOR_Variable. = &cFOR_Variable. + nFOR_STEP =FSEEK(nFileHandle, nFOR_Position, 0) ENDIF RETURN