2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -32,6 +32,7 @@ The task is to manipulate the configuration file as follows:
* Change the numberofbananas parameter to 1024
* Enable (or create if it does not exist in the file) a parameter for numberofstrawberries with a value of 62000
<br>
Note that configuration option names are not case sensitive. This means that changes should be effected, regardless of the case.
Options should always be disabled by prefixing them with a semicolon.
@ -44,9 +45,11 @@ For the purpose of this task, the revised file should contain appropriate entrie
The update should rewrite configuration option names in capital letters. However lines beginning with hashes and any parameter data must not be altered (eg the banana for favourite fruit must not become capitalized). The update process should also replace double semicolon prefixes with just a single semicolon (unless it is uncommenting the option, in which case it should remove all leading semicolons).
Any lines beginning with a semicolon or groups of semicolons, but no following option should be removed, as should any leading or trailing whitespace on the lines. Whitespace between the option and paramters should consist only of a single
space, and any non ascii extended characters, tabs characters, or control codes
Any lines beginning with a semicolon or groups of semicolons, but no following option should be removed, as should any leading or trailing whitespace on the lines. Whitespace between the option and parameters should consist only of a single
space, and any non-ASCII extended characters, tabs characters, or control codes
(other than end of line markers), should also be removed.
'''See also:'''
;Related tasks
* [[Read a configuration file]]
<br><br>

View file

@ -0,0 +1,680 @@
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
' Read a Configuration File V1.0 '
' '
' Developed by A. David Garza Marín in VB-DOS for '
' RosettaCode. December 2, 2016. '
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
' OPTION EXPLICIT ' For VB-DOS, PDS 7.1
' OPTION _EXPLICIT ' For QB64
' SUBs and FUNCTIONs
DECLARE SUB AppendCommentToConfFile (WhichFile AS STRING, WhichComment AS STRING, LeaveALine AS INTEGER)
DECLARE SUB setNValToVarArr (WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS DOUBLE)
DECLARE SUB setSValToVar (WhichVariable AS STRING, WhatValue AS STRING)
DECLARE SUB setSValToVarArr (WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS STRING)
DECLARE SUB doModifyArrValueFromConfFile (WhichFile AS STRING, WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS STRING, Separator AS STRING, ToComment AS INTEGER)
DECLARE SUB doModifyValueFromConfFile (WhichFile AS STRING, WhichVariable AS STRING, WhatValue AS STRING, Separator AS STRING, ToComment AS INTEGER)
DECLARE FUNCTION CreateConfFile% (WhichFile AS STRING)
DECLARE FUNCTION ErrorMessage$ (WhichError AS INTEGER)
DECLARE FUNCTION FileExists% (WhichFile AS STRING)
DECLARE FUNCTION FindVarPos% (WhichVariable AS STRING)
DECLARE FUNCTION FindVarPosArr% (WhichVariable AS STRING, WhichIndex AS INTEGER)
DECLARE FUNCTION getArrayVariable$ (WhichVariable AS STRING, WhichIndex AS INTEGER)
DECLARE FUNCTION getVariable$ (WhichVariable AS STRING)
DECLARE FUNCTION getVarType% (WhatValue AS STRING)
DECLARE FUNCTION GetDummyFile$ (WhichFile AS STRING)
DECLARE FUNCTION HowManyElementsInTheArray% (WhichVariable AS STRING)
DECLARE FUNCTION IsItAnArray% (WhichVariable AS STRING)
DECLARE FUNCTION IsItTheVariableImLookingFor% (TextToAnalyze AS STRING, WhichVariable AS STRING)
DECLARE FUNCTION NewValueForTheVariable$ (WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS STRING, Separator AS STRING)
DECLARE FUNCTION ReadConfFile% (NameOfConfFile AS STRING)
DECLARE FUNCTION YorN$ ()
' Register for values located
TYPE regVarValue
VarName AS STRING * 20
VarType AS INTEGER ' 1=String, 2=Integer, 3=Real, 4=Comment
VarValue AS STRING * 30
END TYPE
' Var
DIM rVarValue() AS regVarValue, iErr AS INTEGER, i AS INTEGER, iHMV AS INTEGER
DIM iArrayElements AS INTEGER, iWhichElement AS INTEGER, iCommentStat AS INTEGER
DIM iAnArray AS INTEGER, iSave AS INTEGER
DIM otherfamily(1 TO 2) AS STRING
DIM sVar AS STRING, sVal AS STRING, sComment AS STRING
CONST ConfFileName = "config2.fil"
CONST False = 0, True = NOT False
' ------------------- Main Program ------------------------
DO
CLS
ERASE rVarValue
PRINT "This program reads a configuration file and shows the result."
PRINT
PRINT "Default file name: "; ConfFileName
PRINT
iErr = ReadConfFile(ConfFileName)
IF iErr = 0 THEN
iHMV = UBOUND(rVarValue)
PRINT "Variables found in file:"
FOR i = 1 TO iHMV
PRINT RTRIM$(rVarValue(i).VarName); " = "; RTRIM$(rVarValue(i).VarValue); " (";
SELECT CASE rVarValue(i).VarType
CASE 0: PRINT "Undefined";
CASE 1: PRINT "String";
CASE 2: PRINT "Integer";
CASE 3: PRINT "Real";
CASE 4: PRINT "Is a commented variable";
END SELECT
PRINT ")"
NEXT i
PRINT
INPUT "Type the variable name to modify (Blank=End)"; sVar
sVar = RTRIM$(LTRIM$(sVar))
IF LEN(sVar) > 0 THEN
i = FindVarPos%(sVar)
IF i > 0 THEN ' Variable found
iAnArray = IsItAnArray%(sVar)
IF iAnArray THEN
iArrayElements = HowManyElementsInTheArray%(sVar)
PRINT "This is an array of"; iArrayElements; " elements."
INPUT "Which one do you want to modify (Default=1)"; iWhichElement
IF iWhichElement = 0 THEN iWhichElement = 1
ELSE
iArrayElements = 1
iWhichElement = 1
END IF
PRINT "The current value of the variable is: "
IF iAnArray THEN
PRINT sVar; "("; iWhichElement; ") = "; RTRIM$(rVarValue(i + (iWhichElement - 1)).VarValue)
ELSE
PRINT sVar; " = "; RTRIM$(rVarValue(i + (iWhichElement - 1)).VarValue)
END IF
ELSE
PRINT "The variable was not found. It will be added."
END IF
PRINT
INPUT "Please, set the new value for the variable (Blank=Unmodified)"; sVal
sVal = RTRIM$(LTRIM$(sVal))
IF i > 0 THEN
IF rVarValue(i + (iWhichElement - 1)).VarType = 4 THEN
PRINT "Do you want to remove the comment status to the variable? (Y/N)"
iCommentStat = NOT (YorN = "Y")
iCommentStat = ABS(iCommentStat) ' Gets 0 (Toggle) or 1 (Leave unmodified)
iSave = (iCommentStat = 0)
ELSE
PRINT "Do you want to toggle the variable as a comment? (Y/N)"
iCommentStat = (YorN = "Y") ' Gets 0 (Uncommented) or -1 (Toggle as a Comment)
iSave = iCommentStat
END IF
END IF
' Now, update or add the variable to the conf file
IF i > 0 THEN
IF sVal = "" THEN
sVal = RTRIM$(rVarValue(i).VarValue)
END IF
ELSE
PRINT "The variable will be added to the configuration file."
PRINT "Do you want to add a remark for it? (Y/N)"
IF YorN$ = "Y" THEN
LINE INPUT "Please, write your remark: ", sComment
sComment = LTRIM$(RTRIM$(sComment))
IF sComment <> "" THEN
AppendCommentToConfFile ConfFileName, sComment, True
END IF
END IF
END IF
' Verifies if the variable will be modified, and applies the modification
IF sVal <> "" OR iSave THEN
IF iWhichElement > 1 THEN
setSValToVarArr sVar, iWhichElement, sVal
doModifyArrValueFromConfFile ConfFileName, sVar, iWhichElement, sVal, " ", iCommentStat
ELSE
setSValToVar sVar, sVal
doModifyValueFromConfFile ConfFileName, sVar, sVal, " ", iCommentStat
END IF
END IF
END IF
ELSE
PRINT ErrorMessage$(iErr)
END IF
PRINT
PRINT "Do you want to add or modify another variable? (Y/N)"
LOOP UNTIL YorN$ = "N"
' --------- End of Main Program -----------------------
PRINT
PRINT "End of program."
END
FileError:
iErr = ERR
RESUME NEXT
SUB AppendCommentToConfFile (WhichFile AS STRING, WhichComment AS STRING, LeaveALine AS INTEGER)
' Parameters:
' WhichFile: Name of the file where a comment will be appended.
' WhichComment: A comment. It is suggested to add a comment no larger than 75 characters.
' This procedure adds a # at the beginning of the string if there is no #
' sign on it in order to ensure it will be added as a comment.
' Var
DIM iFil AS INTEGER
iFil = FileExists%(WhichFile)
IF NOT iFil THEN
iFil = CreateConfFile%(WhichFile) ' Here, iFil is used as dummy to save memory
END IF
IF iFil THEN ' Everything is Ok
iFil = FREEFILE ' Now, iFil is used to be the ID of the file
WhichComment = LTRIM$(RTRIM$(WhichComment))
IF LEFT$(WhichComment, 1) <> "#" THEN ' Is it in comment format?
WhichComment = "# " + WhichComment
END IF
' Append the comment to the file
OPEN WhichFile FOR APPEND AS #iFil
IF LeaveALine THEN
PRINT #iFil, ""
END IF
PRINT #iFil, WhichComment
CLOSE #iFil
END IF
END SUB
FUNCTION CreateConfFile% (WhichFile AS STRING)
' Var
DIM iFile AS INTEGER
ON ERROR GOTO FileError
iFile = FREEFILE
OPEN WhichFile FOR OUTPUT AS #iFile
CLOSE iFile
ON ERROR GOTO 0
CreateConfFile = FileExists%(WhichFile)
END FUNCTION
SUB doModifyArrValueFromConfFile (WhichFile AS STRING, WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS STRING, Separator AS STRING, ToComment AS INTEGER)
' Parameters:
' WhichFile: The name of the Configuration File. It can include the full path.
' WhichVariable: The name of the variable to be modified or added to the conf file.
' WhichIndex: The index number of the element to be modified in a matrix (Default=1)
' WhatValue: The new value to set in the variable specified in WhichVariable.
' Separator: The separator between the variable name and its value in the conf file. Defaults to a space " ".
' ToComment: A value to set or remove the comment mode of a variable: -1=Toggle to Comment, 0=Toggle to not comment, 1=Leave as it is.
' Var
DIM iFile AS INTEGER, iFile2 AS INTEGER, iError AS INTEGER
DIM iMod AS INTEGER, iIsComment AS INTEGER
DIM sLine AS STRING, sDummyFile AS STRING, sChar AS STRING
' If conf file doesn't exists, create one.
iError = 0
iMod = 0
IF NOT FileExists%(WhichFile) THEN
iError = CreateConfFile%(WhichFile)
END IF
IF NOT iError THEN ' File exists or it was created
Separator = RTRIM$(LTRIM$(Separator))
IF Separator = "" THEN
Separator = " " ' Defaults to Space
END IF
sDummyFile = GetDummyFile$(WhichFile)
' It is assumed a text file
iFile = FREEFILE
OPEN WhichFile FOR INPUT AS #iFile
iFile2 = FREEFILE
OPEN sDummyFile FOR OUTPUT AS #iFile2
' Goes through the file to find the variable
DO WHILE NOT EOF(iFile)
LINE INPUT #iFile, sLine
sLine = RTRIM$(LTRIM$(sLine))
sChar = LEFT$(sLine, 1)
iIsComment = (sChar = ";")
IF iIsComment THEN ' Variable is commented
sLine = LTRIM$(MID$(sLine, 2))
END IF
IF sChar <> "#" AND LEN(sLine) > 0 THEN ' Is not a comment?
IF IsItTheVariableImLookingFor%(sLine, WhichVariable) THEN
sLine = NewValueForTheVariable$(WhichVariable, WhichIndex, WhatValue, Separator)
iMod = True
IF ToComment = True THEN
sLine = "; " + sLine
END IF
ELSEIF iIsComment THEN
sLine = "; " + sLine
END IF
END IF
PRINT #iFile2, sLine
LOOP
' Reviews if a modification was done, if not, then it will
' add the variable to the file.
IF NOT iMod THEN
sLine = NewValueForTheVariable$(WhichVariable, 1, WhatValue, Separator)
PRINT #iFile2, sLine
END IF
CLOSE iFile2, iFile
' Removes the conf file and sets the dummy file as the conf file
KILL WhichFile
NAME sDummyFile AS WhichFile
END IF
END SUB
SUB doModifyValueFromConfFile (WhichFile AS STRING, WhichVariable AS STRING, WhatValue AS STRING, Separator AS STRING, ToComment AS INTEGER)
' To see details of parameters, please see doModifyArrValueFromConfFile
doModifyArrValueFromConfFile WhichFile, WhichVariable, 1, WhatValue, Separator, ToComment
END SUB
FUNCTION ErrorMessage$ (WhichError AS INTEGER)
' Var
DIM sError AS STRING
SELECT CASE WhichError
CASE 0: sError = "Everything went ok."
CASE 1: sError = "Configuration file doesn't exist."
CASE 2: sError = "There are no variables in the given file."
END SELECT
ErrorMessage$ = sError
END FUNCTION
FUNCTION FileExists% (WhichFile AS STRING)
' Var
DIM iFile AS INTEGER
DIM iItExists AS INTEGER
SHARED iErr AS INTEGER
ON ERROR GOTO FileError
iFile = FREEFILE
iErr = 0
OPEN WhichFile FOR BINARY AS #iFile
IF iErr = 0 THEN
iItExists = LOF(iFile) > 0
CLOSE #iFile
IF NOT iItExists THEN
KILL WhichFile
END IF
END IF
ON ERROR GOTO 0
FileExists% = iItExists
END FUNCTION
FUNCTION FindVarPos% (WhichVariable AS STRING)
' Will find the position of the variable
FindVarPos% = FindVarPosArr%(WhichVariable, 1)
END FUNCTION
FUNCTION FindVarPosArr% (WhichVariable AS STRING, WhichIndex AS INTEGER)
' Var
DIM i AS INTEGER, iHMV AS INTEGER, iCount AS INTEGER, iPos AS INTEGER
DIM sVar AS STRING, sVal AS STRING, sWV AS STRING
SHARED rVarValue() AS regVarValue
' Looks for a variable name and returns its position
iHMV = UBOUND(rVarValue)
sWV = UCASE$(LTRIM$(RTRIM$(WhichVariable)))
sVal = ""
iCount = 0
DO
i = i + 1
sVar = UCASE$(RTRIM$(rVarValue(i).VarName))
IF sVar = sWV THEN
iCount = iCount + 1
IF iCount = WhichIndex THEN
iPos = i
END IF
END IF
LOOP UNTIL i >= iHMV OR iPos > 0
FindVarPosArr% = iPos
END FUNCTION
FUNCTION getArrayVariable$ (WhichVariable AS STRING, WhichIndex AS INTEGER)
' Var
DIM i AS INTEGER
DIM sVal AS STRING
SHARED rVarValue() AS regVarValue
i = FindVarPosArr%(WhichVariable, WhichIndex)
sVal = ""
IF i > 0 THEN
sVal = RTRIM$(rVarValue(i).VarValue)
END IF
' Found it or not, it will return the result.
' If the result is "" then it didn't found the requested variable.
getArrayVariable$ = sVal
END FUNCTION
FUNCTION GetDummyFile$ (WhichFile AS STRING)
' Var
DIM i AS INTEGER, j AS INTEGER
' Gets the path specified in WhichFile
i = 1
DO
j = INSTR(i, WhichFile, "\")
IF j > 0 THEN i = j + 1
LOOP UNTIL j = 0
GetDummyFile$ = LEFT$(WhichFile, i - 1) + "$dummyf$.tmp"
END FUNCTION
FUNCTION getVariable$ (WhichVariable AS STRING)
' Var
DIM i AS INTEGER, iHMV AS INTEGER
DIM sVal AS STRING
' For a single variable, looks in the first (and only)
' element of the array that contains the name requested.
sVal = getArrayVariable$(WhichVariable, 1)
getVariable$ = sVal
END FUNCTION
FUNCTION getVarType% (WhatValue AS STRING)
' Var
DIM sValue AS STRING, dValue AS DOUBLE, iType AS INTEGER
sValue = RTRIM$(WhatValue)
iType = 0
IF LEN(sValue) > 0 THEN
IF ASC(LEFT$(sValue, 1)) < 48 OR ASC(LEFT$(sValue, 1)) > 57 THEN
iType = 1 ' String
ELSE
dValue = VAL(sValue)
IF CLNG(dValue) = dValue THEN
iType = 2 ' Integer
ELSE
iType = 3 ' Real
END IF
END IF
END IF
getVarType% = iType
END FUNCTION
FUNCTION HowManyElementsInTheArray% (WhichVariable AS STRING)
' Var
DIM i AS INTEGER, iHMV AS INTEGER, iCount AS INTEGER, iPos AS INTEGER, iQuit AS INTEGER
DIM sVar AS STRING, sVal AS STRING, sWV AS STRING
SHARED rVarValue() AS regVarValue
' Looks for a variable name and returns its value
iHMV = UBOUND(rVarValue)
sWV = UCASE$(LTRIM$(RTRIM$(WhichVariable)))
sVal = ""
' Look for all instances of WhichVariable in the
' list. This is because elements of an array will not alwasy
' be one after another, but alternate.
FOR i = 1 TO iHMV
sVar = UCASE$(RTRIM$(rVarValue(i).VarName))
IF sVar = sWV THEN
iCount = iCount + 1
END IF
NEXT i
HowManyElementsInTheArray = iCount
END FUNCTION
FUNCTION IsItAnArray% (WhichVariable AS STRING)
' Returns if a Variable is an Array
IsItAnArray% = (HowManyElementsInTheArray%(WhichVariable) > 1)
END FUNCTION
FUNCTION IsItTheVariableImLookingFor% (TextToAnalyze AS STRING, WhichVariable AS STRING)
' Var
DIM sVar AS STRING, sDT AS STRING, sDV AS STRING
DIM iSep AS INTEGER
sDT = UCASE$(RTRIM$(LTRIM$(TextToAnalyze)))
sDV = UCASE$(RTRIM$(LTRIM$(WhichVariable)))
iSep = INSTR(sDT, "=")
IF iSep = 0 THEN iSep = INSTR(sDT, " ")
IF iSep > 0 THEN
sVar = RTRIM$(LEFT$(sDT, iSep - 1))
ELSE
sVar = sDT
END IF
' It will return True or False
IsItTheVariableImLookingFor% = (sVar = sDV)
END FUNCTION
FUNCTION NewValueForTheVariable$ (WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS STRING, Separator AS STRING)
' Var
DIM iItem AS INTEGER, iItems AS INTEGER, iFirstItem AS INTEGER
DIM i AS INTEGER, iCount AS INTEGER, iHMV AS INTEGER
DIM sLine AS STRING, sVar AS STRING, sVar2 AS STRING
SHARED rVarValue() AS regVarValue
IF IsItAnArray%(WhichVariable) THEN
iItems = HowManyElementsInTheArray(WhichVariable)
iFirstItem = FindVarPosArr%(WhichVariable, 1)
ELSE
iItems = 1
iFirstItem = FindVarPos%(WhichVariable)
END IF
iItem = FindVarPosArr%(WhichVariable, WhichIndex)
sLine = ""
sVar = UCASE$(WhichVariable)
iHMV = UBOUND(rVarValue)
IF iItem > 0 THEN
i = iFirstItem
DO
sVar2 = UCASE$(RTRIM$(rVarValue(i).VarName))
IF sVar = sVar2 THEN ' Does it found an element of the array?
iCount = iCount + 1
IF LEN(sLine) > 0 THEN ' Add a comma
sLine = sLine + ", "
END IF
IF i = iItem THEN
sLine = sLine + WhatValue
ELSE
sLine = sLine + RTRIM$(rVarValue(i).VarValue)
END IF
END IF
i = i + 1
LOOP UNTIL i > iHMV OR iCount = iItems
sLine = WhichVariable + Separator + sLine
ELSE
sLine = WhichVariable + Separator + WhatValue
END IF
NewValueForTheVariable$ = sLine
END FUNCTION
FUNCTION ReadConfFile% (NameOfConfFile AS STRING)
' Var
DIM iFile AS INTEGER, iType AS INTEGER, iVar AS INTEGER, iHMV AS INTEGER
DIM iVal AS INTEGER, iCurVar AS INTEGER, i AS INTEGER, iErr AS INTEGER
DIM dValue AS DOUBLE, iIsComment AS INTEGER
DIM sLine AS STRING, sVar AS STRING, sValue AS STRING
SHARED rVarValue() AS regVarValue
' This procedure reads a configuration file with variables
' and values separated by the equal sign (=) or a space.
' It needs the FileExists% function.
' Lines begining with # or blank will be ignored.
IF FileExists%(NameOfConfFile) THEN
iFile = FREEFILE
REDIM rVarValue(1 TO 10) AS regVarValue
OPEN NameOfConfFile FOR INPUT AS #iFile
WHILE NOT EOF(iFile)
LINE INPUT #iFile, sLine
sLine = RTRIM$(LTRIM$(sLine))
IF LEN(sLine) > 0 THEN ' Does it have any content?
IF LEFT$(sLine, 1) <> "#" THEN ' Is not a comment?
iIsComment = (LEFT$(sLine, 1) = ";")
IF iIsComment THEN ' It is a commented variable
sLine = LTRIM$(MID$(sLine, 2))
END IF
iVar = INSTR(sLine, "=") ' Is there an equal sign?
IF iVar = 0 THEN iVar = INSTR(sLine, " ") ' if not then is there a space?
GOSUB AddASpaceForAVariable
iCurVar = iHMV
IF iVar > 0 THEN ' Is a variable and a value
rVarValue(iHMV).VarName = LEFT$(sLine, iVar - 1)
ELSE ' Is just a variable name
rVarValue(iHMV).VarName = sLine
rVarValue(iHMV).VarValue = ""
END IF
IF iVar > 0 THEN ' Get the value(s)
sLine = LTRIM$(MID$(sLine, iVar + 1))
DO ' Look for commas
iVal = INSTR(sLine, ",")
IF iVal > 0 THEN ' There is a comma
rVarValue(iHMV).VarValue = RTRIM$(LEFT$(sLine, iVal - 1))
GOSUB AddASpaceForAVariable
rVarValue(iHMV).VarName = rVarValue(iHMV - 1).VarName ' Repeats the variable name
sLine = LTRIM$(MID$(sLine, iVal + 1))
END IF
LOOP UNTIL iVal = 0
rVarValue(iHMV).VarValue = sLine
END IF
' Determine the variable type of each variable found in this step
FOR i = iCurVar TO iHMV
IF iIsComment THEN
rVarValue(i).VarType = 4 ' Is a comment
ELSE
GOSUB DetermineVariableType
END IF
NEXT i
END IF
END IF
WEND
CLOSE iFile
IF iHMV > 0 THEN
REDIM PRESERVE rVarValue(1 TO iHMV) AS regVarValue
iErr = 0 ' Everything ran ok.
ELSE
REDIM rVarValue(1 TO 1) AS regVarValue
iErr = 2 ' No variables found in configuration file
END IF
ELSE
iErr = 1 ' File doesn't exist
END IF
ReadConfFile = iErr
EXIT FUNCTION
AddASpaceForAVariable:
iHMV = iHMV + 1
IF UBOUND(rVarValue) < iHMV THEN ' Are there space for a new one?
REDIM PRESERVE rVarValue(1 TO iHMV + 9) AS regVarValue
END IF
RETURN
DetermineVariableType:
sValue = RTRIM$(rVarValue(i).VarValue)
IF LEN(sValue) > 0 THEN
IF ASC(LEFT$(sValue, 1)) < 48 OR ASC(LEFT$(sValue, 1)) > 57 THEN
rVarValue(i).VarType = 1 ' String
ELSE
dValue = VAL(sValue)
IF CLNG(dValue) = dValue THEN
rVarValue(i).VarType = 2 ' Integer
ELSE
rVarValue(i).VarType = 3 ' Real
END IF
END IF
END IF
RETURN
END FUNCTION
SUB setNValToVar (WhichVariable AS STRING, WhatValue AS DOUBLE)
' Sets a numeric value to a variable
setNValToVarArr WhichVariable, 1, WhatValue
END SUB
SUB setNValToVarArr (WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS DOUBLE)
' Sets a numeric value to a variable array
' Var
DIM sVal AS STRING
sVal = FORMAT$(WhatValue)
setSValToVarArr WhichVariable, WhichIndex, sVal
END SUB
SUB setSValToVar (WhichVariable AS STRING, WhatValue AS STRING)
' Sets a string value to a variable
setSValToVarArr WhichVariable, 1, WhatValue
END SUB
SUB setSValToVarArr (WhichVariable AS STRING, WhichIndex AS INTEGER, WhatValue AS STRING)
' Sets a string value to a variable array
' Var
DIM i AS INTEGER
DIM sVar AS STRING
SHARED rVarValue() AS regVarValue
i = FindVarPosArr%(WhichVariable, WhichIndex)
IF i = 0 THEN ' Should add the variable
IF UBOUND(rVarValue) > 0 THEN
sVar = RTRIM$(rVarValue(1).VarName)
IF sVar <> "" THEN
i = UBOUND(rVarValue) + 1
REDIM PRESERVE rVarValue(1 TO i) AS regVarValue
ELSE
i = 1
END IF
ELSE
REDIM rVarValue(1 TO i) AS regVarValue
END IF
rVarValue(i).VarName = WhichVariable
END IF
' Sets the new value to the variable
rVarValue(i).VarValue = WhatValue
rVarValue(i).VarType = getVarType%(WhatValue)
END SUB
FUNCTION YorN$ ()
' Var
DIM sYorN AS STRING
DO
sYorN = UCASE$(INPUT$(1))
IF INSTR("YN", sYorN) = 0 THEN
BEEP
END IF
LOOP UNTIL sYorN = "Y" OR sYorN = "N"
YorN$ = sYorN
END FUNCTION

View file

@ -0,0 +1,25 @@
PROGRAM TEST !Define some data aggregates, then write and read them.
CHARACTER*28 FAVOURITEFRUIT
LOGICAL NEEDSPEELING
LOGICAL SEEDSREMOVED
INTEGER NUMBEROFBANANAS
NAMELIST /FRUIT/ FAVOURITEFRUIT,NEEDSPEELING,SEEDSREMOVED,
1 NUMBEROFBANANAS
INTEGER F !An I/O unit number.
F = 10 !This will do.
Create an example file to show its format.
OPEN(F,FILE="Basket.txt",STATUS="REPLACE",ACTION="WRITE", !First, prepare a recipient file.
1 DELIM="QUOTE") !CHARACTER variables will be enquoted.
FAVOURITEFRUIT = "Banana"
NEEDSPEELING = .TRUE.
SEEDSREMOVED = .FALSE.
NUMBEROFBANANAS = 48
WRITE (F,FRUIT) !Write the lot in one go.
CLOSE (F) !Finished with output.
Can now read from the file.
OPEN(F,FILE="Basket.txt",STATUS="OLD",ACTION="READ", !Get it back.
1 DELIM="QUOTE")
READ (F,FRUIT) !Read who knows what.
WRITE (6,FRUIT)
END

View file

@ -0,0 +1,33 @@
MODULE MONKEYFODDER
INTEGER FIELD !An I/O unit number.
CHARACTER*28 FAVOURITEFRUIT
LOGICAL NEEDSPEELING
INTEGER NUMBEROFBANANAS
CONTAINS
SUBROUTINE GETVALS(FNAME) !Reads values from some file.
CHARACTER*(*) FNAME !The file name.
LOGICAL SEEDSREMOVED !This variable is no longer wanted.
NAMELIST /FRUIT/ FAVOURITEFRUIT,NEEDSPEELING,SEEDSREMOVED, !But still appears in this list.
1 NUMBEROFBANANAS
OPEN(FIELD,FILE=FNAME,STATUS="OLD",ACTION="READ", !Hopefully, the file exists.
1 DELIM="QUOTE") !Expect quoting for CHARACTER variables.
READ (FIELD,FRUIT,ERR = 666) !Read who knows what.
666 CLOSE (FIELD) !Ignoring any misformats.
END SUBROUTINE GETVALS !A proper routine would offer error messages.
SUBROUTINE PUTVALS(FNAME) !Writes values to some file.
CHARACTER*(*) FNAME !The file name.
NAMELIST /FRUIT/ FAVOURITEFRUIT,NEEDSPEELING,NUMBEROFBANANAS
OPEN(FIELD,FILE=FNAME,STATUS="REPLACE",ACTION="WRITE", !Prepare a recipient file.
1 DELIM="QUOTE") !CHARACTER variables will be enquoted.
WRITE (FIELD,FRUIT) !Write however much is needed.
CLOSE (FIELD) !Finished for now.
END SUBROUTINE PUTVALS
END MODULE MONKEYFODDER
PROGRAM TEST !Updates the file created by an earlier version.
USE MONKEYFODDER
FIELD = 10 !This will do.
CALL GETVALS("Basket.txt") !Read the values, allowing for the previous version.
CALL PUTVALS("Basket.txt") !Save the values, as per the new version.
END

View file

@ -0,0 +1,2 @@
import Data.Char (toUpper)
import qualified System.IO.Strict as S

View file

@ -0,0 +1,27 @@
data INI = INI { entries :: [Entry] } deriving Show
data Entry = Comment String
| Field String String
| Flag String Bool
| EmptyLine
instance Show Entry where
show entry = case entry of
Comment text -> "# " ++ text
Field f v -> f ++ " " ++ v
Flag f True -> f
Flag f False -> "; " ++ f
EmptyLine -> ""
instance Read Entry where
readsPrec _ s = [(interprete (clean " " s), "")]
where
clean chs = dropWhile (`elem` chs)
interprete ('#' : text) = Comment text
interprete (';' : f)= flag (clean " ;" f) False
interprete entry = case words entry of
[] -> EmptyLine
[f] -> flag f True
f : v -> field f (unwords v)
field f = Field (toUpper <$> f)
flag f = Flag (toUpper <$> f)

View file

@ -0,0 +1,19 @@
setValue :: String -> String -> INI -> INI
setValue f v = INI . replaceOn (eqv f) (Field f v) . entries
setFlag :: String -> Bool -> INI -> INI
setFlag f v = INI . replaceOn (eqv f) (Flag f v) . entries
enable f = setFlag f True
disable f = setFlag f False
eqv f entry = (toUpper <$> f) == (toUpper <$> field entry)
where field (Field f _) = f
field (Flag f _) = f
field _ = ""
replaceOn p x lst = prev ++ x : post
where
(prev,post) = case break p lst of
(lst, []) -> (lst, [])
(lst, _:xs) -> (lst, xs)

View file

@ -0,0 +1,14 @@
readIni :: String -> IO INI
readIni file = INI . map read . lines <$> S.readFile file
writeIni :: String -> INI -> IO ()
writeIni file = writeFile file . unlines . map show . entries
updateIni :: String -> (INI -> INI) -> IO ()
updateIni file f = readIni file >>= writeIni file . f
main = updateIni "test.ini" $
disable "NeedsPeeling" .
enable "SeedsRemoved" .
setValue "NumberOfBananas" "1024" .
setValue "NumberOfStrawberries" "62000"

View file

@ -27,7 +27,7 @@ sub MAIN ($file, *%changes) {
say $out: format-line .key, |(.value ~~ Bool ?? (Nil, .value) !! (.value, True))
for %changes;
run 'mv', $tmpfile, $file; # work-around for NYI `move $tmpfile, $file;`
move $tmpfile, $file;
}
END { unlink $tmpfile if $tmpfile.IO.e }

View file

@ -0,0 +1,107 @@
function Update-ConfigurationFile
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$false,
Position=0)]
[ValidateScript({Test-Path $_})]
[string]
$Path = ".\config.txt",
[Parameter(Mandatory=$false)]
[string]
$FavouriteFruit,
[Parameter(Mandatory=$false)]
[int]
$NumberOfBananas,
[Parameter(Mandatory=$false)]
[int]
$NumberOfStrawberries,
[Parameter(Mandatory=$false)]
[ValidateSet("On", "Off")]
[string]
$NeedsPeeling,
[Parameter(Mandatory=$false)]
[ValidateSet("On", "Off")]
[string]
$SeedsRemoved
)
[string[]]$lines = Get-Content $Path
Clear-Content $Path
if (-not ($lines | Select-String -Pattern "^\s*NumberOfStrawberries" -Quiet))
{
"", "# How many strawberries we have", "NumberOfStrawberries 0" | ForEach-Object {$lines += $_}
}
foreach ($line in $lines)
{
$line = $line -replace "^\s*","" ## Strip leading whitespace
if ($line -match "[;].*\s*") {continue} ## Strip semicolons
switch -Regex ($line)
{
"(^$)|(^#\s.*)" ## Blank line or comment
{
$line = $line
}
"^FavouriteFruit\s*.*" ## Parameter FavouriteFruit
{
if ($FavouriteFruit)
{
$line = "FAVOURITEFRUIT $FavouriteFruit"
}
}
"^NumberOfBananas\s*.*" ## Parameter NumberOfBananas
{
if ($NumberOfBananas)
{
$line = "NUMBEROFBANANAS $NumberOfBananas"
}
}
"^NumberOfStrawberries\s*.*" ## Parameter NumberOfStrawberries
{
if ($NumberOfStrawberries)
{
$line = "NUMBEROFSTRAWBERRIES $NumberOfStrawberries"
}
}
".*NeedsPeeling\s*.*" ## Parameter NeedsPeeling
{
if ($NeedsPeeling -eq "On")
{
$line = "NEEDSPEELING"
}
elseif ($NeedsPeeling -eq "Off")
{
$line = "; NEEDSPEELING"
}
}
".*SeedsRemoved\s*.*" ## Parameter SeedsRemoved
{
if ($SeedsRemoved -eq "On")
{
$line = "SEEDSREMOVED"
}
elseif ($SeedsRemoved -eq "Off")
{
$line = "; SEEDSREMOVED"
}
}
Default ## Whatever...
{
$line = $line
}
}
Add-Content $Path -Value $line -Force
}
}

View file

@ -0,0 +1,3 @@
Update-ConfigurationFile -NumberOfStrawberries 62000 -NumberOfBananas 1024 -SeedsRemoved On -NeedsPeeling Off
Invoke-Item -Path ".\config.txt"

View file

@ -1,45 +1,45 @@
/*REXX pgm shows how to update a configuration file (4 specific tasks).*/
parse arg iFID oFID . /*obtain optional input file─id. */
if iFID=='' | iFID==',' then iFID= 'UPDATECF.TXT' /*use default? */
if oFID=='' | oFID==',' then oFID='\TEMP\UPDATECF.$$$' /*use default? */
call lineout iFID; call lineout oFID /*close the input & output files.*/
$.=0 /*placeholder of options found. */
call dos 'ERASE' oFID /*erase a file (with no err MSGs)*/
changed=0 /*nothing changed in file so far.*/
/* [↓] read the entire cfg file.*/
do rec=0 while lines(iFID)\==0 /*read a record; bump record cnt.*/
z=linein(iFID); zz=space(z) /*get rec; del extraneous blanks.*/
say ' record:' z /*echo the record just read──►con*/
a=left(zz,1); _=space(translate(zz,,';')) /*_ is used to elide multi;*/
if zz=='' | a=='#' then do; call cpy z; iterate; end /*blank|comment*/
if _=='' then do; changed=1; iterate; end /*elide any ; empty records*/
parse upper var z op . /*obtain the option from the rec.*/
/* [↓] OP may have leading or */
if a==';' then do; parse upper var z 2 op . /*trailing blanks.*/
if op='SEEDSREMOVED' then call new space(substr(z,2))
call cpy z; $.op=1 /*write the Z record to output.*/
iterate /*rec*/ /*··· and go read the next record*/
/*REXX program demonstrates how to update a configuration file (four specific tasks).*/
parse arg iFID oFID . /*obtain optional arguments from the CL*/
if iFID=='' | iFID=="," then iFID= 'UPDATECF.TXT' /*Not given? Then use default.*/
if oFID=='' | oFID=="," then oFID='\TEMP\UPDATECF.$$$' /* " " " " " */
call lineout iFID; call lineout oFID /*close the input and the output files.*/
$.=0 /*placeholder of the options detected. */
call dos 'ERASE' oFID /*erase a file (with no error message).*/
changed=0 /*nothing changed in the file (so far).*/
/* [↓] read the entire config file. */
do rec=0 while lines(iFID)\==0 /*read a record; bump the record count.*/
z=linein(iFID); zz=space(z) /*get record; elide extraneous blanks.*/
say ' record:' z /*echo the record just read ──► console*/
a=left(zz,1); _=space( translate(zz, ,';') ) /*_: is used to elide multiple ";" */
if zz=='' | a=='#' then do; call cpy z; iterate; end /*blank or a comment.*/
if _=='' then do; changed=1; iterate; end /*elide any semicolons; empty records.*/
parse upper var z op . /*obtain the option from the record. */
/* [↓] option may have leading or ···*/
if a==';' then do; parse upper var z 2 op . /*trailing blanks.*/
if op='SEEDSREMOVED' then call new space( substr(z, 2) )
call cpy z; $.op=1 /*write the Z record to the output file*/
iterate /*rec*/ /* ··· and then go read the next record*/
end
if $.op then do; changed=1; iterate; end /*option already defined?*/
$.op=1 /* [↑] Yes? Delete it.*/
if op=='NEEDSPEELING' then call new ';' z
if op=='NUMBEROFBANANAS' then call new op 1024
if op=='NUMBEROFSTRAWBERRIES' then call new op 62000
call cpy z /*write the Z record to output.*/
if $.op then do; changed=1; iterate; end /*is the option already defined? */
$.op=1 /* [↑] Yes? Then delete it. */
if op=='NEEDSPEELING' then call new ";" z
if op=='NUMBEROFBANANAS' then call new op 1024
if op=='NUMBEROFSTRAWBERRIES' then call new op 62000
call cpy z /*write the Z record to the output file*/
end /*rec*/
nos='NUMBEROFSTRAWBERRIES' /* [↓] NOS option need updating?*/
if \$.nos then do; call new nos 62000; call cpy z; end /*update opt.*/
call lineout iFID; call lineout oFID /*close the input & output files.*/
if rec==0 then do; say "ERROR: input file wasn't found:" iFID; exit; end
if changed then do /*possibly overwrite input file. */
call dos 'XCOPY' oFID iFID '/y /q',">nul" /*quietly*/
say; say center('output file', 79, "") /*title. */
call dos 'TYPE' oFID /*display output file's content. */
nos='NUMBEROFSTRAWBERRIES' /* [↓] Does NOS option need updating? */
if \$.nos then do; call new nos 62000; call cpy z; end /*update option.*/
call lineout iFID; call lineout oFID /*close the input and the output files.*/
if rec==0 then do; say "ERROR: input file wasn't found:" iFID; exit; end
if changed then do /*possibly overwrite the input file. */
call dos 'XCOPY' oFID iFID '/y /q',">nul" /*quietly*/
say; say center('output file', 79, "") /*title. */
call dos 'TYPE' oFID /*display content of the output file. */
end
call dos 'ERASE' oFID /*erase a file (with no err msg)*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────one─line subroutines────────────────*/
cpy: call lineout oFID,arg(1); return /*write one line of text───►oFID.*/
dos: ''arg(1) word(arg(2) "2>nul",1); return /*execute a DOS command.*/
new: z=arg(1); changed=1; return /*use new Z, indicate changed rec*/
call dos 'ERASE' oFID /*erase a file (with no error message).*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
cpy: call lineout oFID, arg(1); return /*write one line of text ───► oFID. */
dos: ''arg(1) word(arg(2) "2>nul",1); return /*execute a DOS command (quietly). */
new: z=arg(1); changed=1; return /*use new Z, indicate changed record. */