Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
3
Task/Read-a-configuration-file/00-META.yaml
Normal file
3
Task/Read-a-configuration-file/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Read_a_configuration_file
|
||||
note: File handling
|
||||
53
Task/Read-a-configuration-file/00-TASK.txt
Normal file
53
Task/Read-a-configuration-file/00-TASK.txt
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
The task is to read a configuration file in standard configuration file format,
|
||||
and set variables accordingly.
|
||||
|
||||
For this task, we have a configuration file as follows:
|
||||
|
||||
# This is a configuration file in standard configuration file format
|
||||
#
|
||||
# Lines beginning with a hash or a semicolon are ignored by the application
|
||||
# program. Blank lines are also ignored by the application program.
|
||||
|
||||
# This is the fullname parameter
|
||||
FULLNAME Foo Barber
|
||||
|
||||
# This is a favourite fruit
|
||||
FAVOURITEFRUIT banana
|
||||
|
||||
# This is a boolean that should be set
|
||||
NEEDSPEELING
|
||||
|
||||
# This boolean is commented out
|
||||
; SEEDSREMOVED
|
||||
|
||||
# Configuration option names are not case sensitive, but configuration parameter
|
||||
# data is case sensitive and may be preserved by the application program.
|
||||
|
||||
# An optional equals sign can be used to separate configuration parameter data
|
||||
# from the option name. This is dropped by the parser.
|
||||
|
||||
# A configuration option may take multiple parameters separated by commas.
|
||||
# Leading and trailing whitespace around parameter names and parameter data fields
|
||||
# are ignored by the application program.
|
||||
|
||||
OTHERFAMILY Rhu Barber, Harry Barber
|
||||
|
||||
|
||||
For the task we need to set four variables according to the configuration entries as follows:
|
||||
|
||||
*fullname = Foo Barber
|
||||
*favouritefruit = banana
|
||||
*needspeeling = true
|
||||
*seedsremoved = false
|
||||
|
||||
|
||||
We also have an option that contains multiple parameters. These may be stored in an array.
|
||||
|
||||
* otherfamily(1) = Rhu Barber
|
||||
* otherfamily(2) = Harry Barber
|
||||
|
||||
|
||||
;Related tasks
|
||||
* [[Update a configuration file]]
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
F readconf(fname)
|
||||
[String = String] ret
|
||||
L(=line) File(fname).read_lines()
|
||||
line = line.trim((‘ ’, "\t", "\r", "\n"))
|
||||
I line == ‘’ | line.starts_with(‘#’)
|
||||
L.continue
|
||||
|
||||
V boolval = 1B
|
||||
I line.starts_with(‘;’)
|
||||
line = line.ltrim(‘;’)
|
||||
|
||||
I line.split_py().len != 1
|
||||
L.continue
|
||||
boolval = 0B
|
||||
|
||||
V bits = line.split(‘ ’, 2, group_delimiters' 1B)
|
||||
String k, v
|
||||
I bits.len == 1
|
||||
k = bits[0]
|
||||
v = String(boolval)
|
||||
E
|
||||
(k, v) = bits
|
||||
ret[k.lowercase()] = v
|
||||
R ret
|
||||
|
||||
V conf = readconf(‘config.txt’)
|
||||
L(k, v) sorted(conf.items())
|
||||
print(k‘ = ’v)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# syntax: GAWK -f READ_A_CONFIGURATION_FILE.AWK
|
||||
BEGIN {
|
||||
fullname = favouritefruit = ""
|
||||
needspeeling = seedsremoved = "false"
|
||||
fn = "READ_A_CONFIGURATION_FILE.INI"
|
||||
while (getline rec <fn > 0) {
|
||||
tmp = tolower(rec)
|
||||
if (tmp ~ /^ *fullname/) { fullname = extract(rec) }
|
||||
else if (tmp ~ /^ *favouritefruit/) { favouritefruit = extract(rec) }
|
||||
else if (tmp ~ /^ *needspeeling/) { needspeeling = "true" }
|
||||
else if (tmp ~ /^ *seedsremoved/) { seedsremoved = "true" }
|
||||
else if (tmp ~ /^ *otherfamily/) { split(extract(rec),otherfamily,",") }
|
||||
}
|
||||
close(fn)
|
||||
printf("fullname=%s\n",fullname)
|
||||
printf("favouritefruit=%s\n",favouritefruit)
|
||||
printf("needspeeling=%s\n",needspeeling)
|
||||
printf("seedsremoved=%s\n",seedsremoved)
|
||||
for (i=1; i<=length(otherfamily); i++) {
|
||||
sub(/^ +/,"",otherfamily[i]) # remove leading spaces
|
||||
sub(/ +$/,"",otherfamily[i]) # remove trailing spaces
|
||||
printf("otherfamily(%d)=%s\n",i,otherfamily[i])
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
function extract(rec, pos,str) {
|
||||
sub(/^ +/,"",rec) # remove leading spaces before parameter name
|
||||
pos = match(rec,/[= ]/) # determine where data begins
|
||||
str = substr(rec,pos) # extract the data
|
||||
gsub(/^[= ]+/,"",str) # remove leading "=" and spaces
|
||||
sub(/ +$/,"",str) # remove trailing spaces
|
||||
return(str)
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
with Config; use Config;
|
||||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
|
||||
procedure Rosetta_Read_Cfg is
|
||||
cfg: Configuration:= Init("rosetta_read.cfg", Case_Sensitive => False, Variable_Terminator => ' ');
|
||||
fullname : String := cfg.Value_Of("*", "fullname");
|
||||
favouritefruit : String := cfg.Value_Of("*", "favouritefruit");
|
||||
needspeeling : Boolean := cfg.Is_Set("*", "needspeeling");
|
||||
seedsremoved : Boolean := cfg.Is_Set("*", "seedsremoved");
|
||||
otherfamily : String := cfg.Value_Of("*", "otherfamily");
|
||||
begin
|
||||
Put_Line("fullname = " & fullname);
|
||||
Put_Line("favouritefruit = " & favouritefruit);
|
||||
Put_Line("needspeeling = " & Boolean'Image(needspeeling));
|
||||
Put_Line("seedsremoved = " & Boolean'Image(seedsremoved));
|
||||
Put_Line("otherfamily = " & otherfamily);
|
||||
end;
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
record r, s;
|
||||
integer c;
|
||||
file f;
|
||||
list l;
|
||||
text an, d, k;
|
||||
|
||||
an = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
f.affix("tmp/config");
|
||||
|
||||
while ((c = f.peek) ^ -1) {
|
||||
integer removed;
|
||||
|
||||
f.side(" \t\r");
|
||||
c = f.peek;
|
||||
removed = c == ';';
|
||||
if (removed) {
|
||||
f.pick;
|
||||
f.side(" \t\r");
|
||||
c = f.peek;
|
||||
}
|
||||
c = place(an, c);
|
||||
if (-1 < c && c < 52) {
|
||||
f.near(an, k);
|
||||
if (removed) {
|
||||
r[k] = "false";
|
||||
} else {
|
||||
f.side(" \t\r");
|
||||
if (f.peek == '=') {
|
||||
f.pick;
|
||||
f.side(" \t\r");
|
||||
}
|
||||
f.ever(",#\n", d);
|
||||
d = bb_drop(d, " \r\t");
|
||||
if (f.peek != ',') {
|
||||
r[k] = ~d ? d : "true";
|
||||
} else {
|
||||
f.news(l, 0, 0, ",");
|
||||
lf_push(l, d);
|
||||
for (c, d in l) {
|
||||
l[c] = bb_drop(d, " \r\t").bf_drop(" \r\t").string;
|
||||
}
|
||||
s.put(k, l);
|
||||
f.seek(-1, SEEK_CURRENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f.slip;
|
||||
}
|
||||
|
||||
r.wcall(o_, 0, 2, ": ", "\n");
|
||||
|
||||
for (k, l in s) {
|
||||
o_(k, ": ");
|
||||
l.ucall(o_, 0, ", ");
|
||||
o_("\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
parseConfig: function [f][
|
||||
lines: split.lines read f
|
||||
lines: select map lines 'line [strip replace line {/[#;].*/} ""]
|
||||
'line [not? empty? line]
|
||||
result: #[]
|
||||
|
||||
fields: loop lines 'line [
|
||||
field: first match line {/^[A-Z]+/}
|
||||
rest: strip replace line field ""
|
||||
parts: select map split.by:"," rest => strip 'part -> not? empty? part
|
||||
|
||||
val: null
|
||||
case [(size parts)]
|
||||
when? [= 0] -> val: true
|
||||
when? [= 1] -> val: first parts
|
||||
else -> val: parts
|
||||
|
||||
result\[lower field]: val
|
||||
]
|
||||
|
||||
return result
|
||||
]
|
||||
|
||||
loop parseConfig relative "config.file" [k,v][
|
||||
if? block? v -> print [k "->" join.with:", " v]
|
||||
else -> print [k "->" v]
|
||||
]
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
; Author: AlephX, Aug 18 2011
|
||||
data = %A_scriptdir%\rosettaconfig.txt
|
||||
comma := ","
|
||||
|
||||
Loop, Read, %data%
|
||||
{
|
||||
if NOT (instr(A_LoopReadLine, "#") == 1 OR A_LoopReadLine == "")
|
||||
|
||||
{
|
||||
if instr(A_LoopReadLine, ";") == 1
|
||||
{
|
||||
parameter := RegExReplace(Substr(A_LoopReadLine,2), "^[ \s]+|[ \s]+$", "")
|
||||
%parameter% = "1"
|
||||
}
|
||||
else
|
||||
{
|
||||
parameter := RegExReplace(A_LoopReadLine, "^[ \s]+|[ \s]+$", "")
|
||||
|
||||
if instr(parameter, A_Space)
|
||||
{
|
||||
value := substr(parameter, instr(parameter, A_Space)+1,999)
|
||||
parameter := substr(parameter, 1, instr(parameter, A_Space)-1)
|
||||
|
||||
if (instr(value, ",") <> 0)
|
||||
{
|
||||
Loop, Parse, value, %comma% ,%A_Space%
|
||||
%parameter%%A_Index% := A_Loopfield
|
||||
}
|
||||
else
|
||||
%parameter% = %value%
|
||||
}
|
||||
else
|
||||
%parameter% = "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
msgbox, FULLNAME %fullname%`nFAVOURITEFRUIT %FAVOURITEFRUIT%`nNEEDSPEELING %NEEDSPEELING%`nSEEDSREMOVED %SEEDSREMOVED%`nOTHERFAMILY %OTHERFAMILY1% + %OTHERFAMILY2%
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
|
||||
' 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 FUNCTION ErrorMessage$ (WhichError AS INTEGER)
|
||||
DECLARE FUNCTION YorN$ ()
|
||||
DECLARE FUNCTION FileExists% (WhichFile AS STRING)
|
||||
DECLARE FUNCTION ReadConfFile% (NameOfConfFile AS STRING)
|
||||
DECLARE FUNCTION getVariable$ (WhichVariable AS STRING)
|
||||
DECLARE FUNCTION getArrayVariable$ (WhichVariable AS STRING, WhichIndex AS INTEGER)
|
||||
|
||||
' Register for values located
|
||||
TYPE regVarValue
|
||||
VarName AS STRING * 20
|
||||
VarType AS INTEGER ' 1=String, 2=Integer, 3=Real
|
||||
VarValue AS STRING * 30
|
||||
END TYPE
|
||||
|
||||
' Var
|
||||
DIM rVarValue() AS regVarValue, iErr AS INTEGER, i AS INTEGER, iHMV AS INTEGER
|
||||
DIM otherfamily(1 TO 2) AS STRING
|
||||
DIM fullname AS STRING, favouritefruit AS STRING, needspeeling AS INTEGER, seedsremoved AS INTEGER
|
||||
CONST ConfFileName = "config.fil"
|
||||
|
||||
' ------------------- Main Program ------------------------
|
||||
CLS
|
||||
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";
|
||||
END SELECT
|
||||
PRINT ")"
|
||||
NEXT i
|
||||
PRINT
|
||||
|
||||
' Sets required variables
|
||||
fullname = getVariable$("FullName")
|
||||
favouritefruit = getVariable$("FavouriteFruit")
|
||||
needspeeling = VAL(getVariable$("NeedSpeeling"))
|
||||
seedsremoved = VAL(getVariable$("SeedsRemoved"))
|
||||
FOR i = 1 TO 2
|
||||
otherfamily(i) = getArrayVariable$("OtherFamily", i)
|
||||
NEXT i
|
||||
PRINT "Variables requested to set values:"
|
||||
PRINT "fullname = "; fullname
|
||||
PRINT "favouritefruit = "; favouritefruit
|
||||
PRINT "needspeeling = ";
|
||||
IF needspeeling = 0 THEN PRINT "false" ELSE PRINT "true"
|
||||
PRINT "seedsremoved = ";
|
||||
IF seedsremoved = 0 THEN PRINT "false" ELSE PRINT "true"
|
||||
FOR i = 1 TO 2
|
||||
PRINT "otherfamily("; i; ") = "; otherfamily(i)
|
||||
NEXT i
|
||||
ELSE
|
||||
PRINT ErrorMessage$(iErr)
|
||||
END IF
|
||||
' --------- End of Main Program -----------------------
|
||||
|
||||
END
|
||||
|
||||
FileError:
|
||||
iErr = ERR
|
||||
RESUME NEXT
|
||||
|
||||
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 getArrayVariable$ (WhichVariable AS STRING, WhichIndex AS INTEGER)
|
||||
' Var
|
||||
DIM i AS INTEGER, iHMV AS INTEGER, iCount 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 = ""
|
||||
DO
|
||||
i = i + 1
|
||||
sVar = UCASE$(RTRIM$(rVarValue(i).VarName))
|
||||
IF sVar = sWV THEN
|
||||
iCount = iCount + 1
|
||||
IF iCount = WhichIndex THEN
|
||||
sVal = LTRIM$(RTRIM$(rVarValue(i).VarValue))
|
||||
END IF
|
||||
END IF
|
||||
LOOP UNTIL i >= iHMV OR sVal <> ""
|
||||
|
||||
' 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 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 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
|
||||
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?
|
||||
IF LEFT$(sLine,1) = ";" 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
|
||||
|
||||
' Determine the variable type of each variable found in this step
|
||||
FOR i = iCurVar TO iHMV
|
||||
GOSUB DetermineVariableType
|
||||
NEXT i
|
||||
END IF
|
||||
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 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
|
||||
RETURN
|
||||
|
||||
END FUNCTION
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
BOOL = 1
|
||||
NAME = 2
|
||||
ARRAY = 3
|
||||
|
||||
optfile$ = "options.cfg"
|
||||
|
||||
fullname$ = FNoption(optfile$, "FULLNAME", NAME)
|
||||
favouritefruit$ = FNoption(optfile$, "FAVOURITEFRUIT", NAME)
|
||||
needspeeling% = FNoption(optfile$, "NEEDSPEELING", BOOL)
|
||||
seedsremoved% = FNoption(optfile$, "SEEDSREMOVED", BOOL)
|
||||
!^otherfamily$() = FNoption(optfile$, "OTHERFAMILY", ARRAY)
|
||||
|
||||
PRINT "fullname = " fullname$
|
||||
PRINT "favouritefruit = " favouritefruit$
|
||||
PRINT "needspeeling = "; : IF needspeeling% PRINT "true" ELSE PRINT "false"
|
||||
PRINT "seedsremoved = "; : IF seedsremoved% PRINT "true" ELSE PRINT "false"
|
||||
PRINT "otherfamily(1) = " otherfamily$(1)
|
||||
PRINT "otherfamily(2) = " otherfamily$(2)
|
||||
END
|
||||
|
||||
DEF FNoption(file$, key$, type%)
|
||||
LOCAL file%, opt$, comma%, bool%, name$, size%, !^array$()
|
||||
file% = OPENIN(file$)
|
||||
IF file% = 0 THEN = 0
|
||||
WHILE NOT EOF#file%
|
||||
opt$ = GET$#file%
|
||||
WHILE RIGHT$(opt$) = " " opt$ = LEFT$(opt$) : ENDWHILE
|
||||
IF opt$ = key$ OR LEFT$(opt$, LEN(key$)+1) = key$ + " " THEN
|
||||
opt$ = MID$(opt$, LEN(key$) + 1)
|
||||
WHILE LEFT$(opt$,1) = " " opt$ = MID$(opt$,2) : ENDWHILE
|
||||
CASE type% OF
|
||||
WHEN BOOL: bool% = TRUE : EXIT WHILE
|
||||
WHEN NAME: name$ = opt$ : EXIT WHILE
|
||||
WHEN ARRAY:
|
||||
REPEAT
|
||||
comma% = INSTR(opt$, ",", comma%+1)
|
||||
IF comma% size% += 1
|
||||
UNTIL comma% = 0
|
||||
DIM array$(size% + 1)
|
||||
size% = 0
|
||||
REPEAT
|
||||
comma% = INSTR(opt$, ",")
|
||||
IF comma% THEN
|
||||
size% += 1
|
||||
array$(size%) = LEFT$(opt$, comma%-1)
|
||||
opt$ = MID$(opt$, comma%+1)
|
||||
WHILE LEFT$(opt$,1) = " " opt$ = MID$(opt$,2) : ENDWHILE
|
||||
ENDIF
|
||||
UNTIL comma% = 0
|
||||
array$(size% + 1) = opt$
|
||||
EXIT WHILE
|
||||
ENDCASE
|
||||
ENDIF
|
||||
ENDWHILE
|
||||
CLOSE #file%
|
||||
CASE type% OF
|
||||
WHEN BOOL: = bool%
|
||||
WHEN NAME: = name$
|
||||
WHEN ARRAY: = !^array$()
|
||||
ENDCASE
|
||||
= 0
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
|
||||
static const char_separator<char> sep(" ","#;,");
|
||||
|
||||
//Assume that the config file represent a struct containing all the parameters to load
|
||||
struct configs{
|
||||
string fullname;
|
||||
string favoritefruit;
|
||||
bool needspelling;
|
||||
bool seedsremoved;
|
||||
vector<string> otherfamily;
|
||||
} conf;
|
||||
|
||||
void parseLine(const string &line, configs &conf)
|
||||
{
|
||||
if (line[0] == '#' || line.empty())
|
||||
return;
|
||||
Tokenizer tokenizer(line, sep);
|
||||
vector<string> tokens;
|
||||
for (Tokenizer::iterator iter = tokenizer.begin(); iter != tokenizer.end(); iter++)
|
||||
tokens.push_back(*iter);
|
||||
if (tokens[0] == ";"){
|
||||
algorithm::to_lower(tokens[1]);
|
||||
if (tokens[1] == "needspeeling")
|
||||
conf.needspelling = false;
|
||||
if (tokens[1] == "seedsremoved")
|
||||
conf.seedsremoved = false;
|
||||
}
|
||||
algorithm::to_lower(tokens[0]);
|
||||
if (tokens[0] == "needspeeling")
|
||||
conf.needspelling = true;
|
||||
if (tokens[0] == "seedsremoved")
|
||||
conf.seedsremoved = true;
|
||||
if (tokens[0] == "fullname"){
|
||||
for (unsigned int i=1; i<tokens.size(); i++)
|
||||
conf.fullname += tokens[i] + " ";
|
||||
conf.fullname.erase(conf.fullname.size() -1, 1);
|
||||
}
|
||||
if (tokens[0] == "favouritefruit")
|
||||
for (unsigned int i=1; i<tokens.size(); i++)
|
||||
conf.favoritefruit += tokens[i];
|
||||
if (tokens[0] == "otherfamily"){
|
||||
unsigned int i=1;
|
||||
string tmp;
|
||||
while (i<=tokens.size()){
|
||||
if ( i == tokens.size() || tokens[i] ==","){
|
||||
tmp.erase(tmp.size()-1, 1);
|
||||
conf.otherfamily.push_back(tmp);
|
||||
tmp = "";
|
||||
i++;
|
||||
}
|
||||
else{
|
||||
tmp += tokens[i];
|
||||
tmp += " ";
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int _tmain(int argc, TCHAR* argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
wstring tmp = argv[0];
|
||||
wcout << L"Usage: " << tmp << L" <configfile.ini>" << endl;
|
||||
return -1;
|
||||
}
|
||||
ifstream file (argv[1]);
|
||||
|
||||
if (file.is_open())
|
||||
while(file.good())
|
||||
{
|
||||
char line[255];
|
||||
file.getline(line, 255);
|
||||
string linestring(line);
|
||||
parseLine(linestring, conf);
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Unable to open the file" << endl;
|
||||
return -2;
|
||||
}
|
||||
|
||||
cout << "Fullname= " << conf.fullname << endl;
|
||||
cout << "Favorite Fruit= " << conf.favoritefruit << endl;
|
||||
cout << "Need Spelling= " << (conf.needspelling?"True":"False") << endl;
|
||||
cout << "Seed Removed= " << (conf.seedsremoved?"True":"False") << endl;
|
||||
string otherFamily;
|
||||
for (unsigned int i = 0; i < conf.otherfamily.size(); i++)
|
||||
otherFamily += conf.otherfamily[i] + ", ";
|
||||
otherFamily.erase(otherFamily.size()-2, 2);
|
||||
cout << "Other Family= " << otherFamily << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
struct confi {
|
||||
std::string fullname;
|
||||
std::string favouritefruit;
|
||||
bool needspeeling;
|
||||
bool seedsremoved;
|
||||
std::vector<std::string> otherfamily;
|
||||
};
|
||||
|
||||
void read_config(std::ifstream& in, confi& out) {
|
||||
in.open("Config.txt");
|
||||
std::string str;
|
||||
out.needspeeling = false;
|
||||
out.seedsremoved = false;
|
||||
while(!in.eof()) {
|
||||
while(getline(in,str)) {
|
||||
std::string::size_type begin = str.find_first_not_of(" \f\t\v");
|
||||
//Skips blank lines
|
||||
if(begin == std::string::npos)
|
||||
continue;
|
||||
//Skips #
|
||||
if(std::string("#").find(str[begin]) != std::string::npos)
|
||||
continue;
|
||||
std::string firstWord;
|
||||
try {
|
||||
firstWord = str.substr(0,str.find(" "));
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
firstWord = str.erase(str.find_first_of(" "),str.find_first_not_of(" "));
|
||||
}
|
||||
std::transform(firstWord.begin(),firstWord.end(),firstWord.begin(), ::toupper);
|
||||
if(firstWord == "FULLNAME")
|
||||
out.fullname = str.substr(str.find(" ")+1,str.length());
|
||||
if(firstWord == "FAVOURITEFRUIT")
|
||||
out.favouritefruit = str.substr(str.find(" ")+1,str.length());
|
||||
if(firstWord == "NEEDSPEELING")
|
||||
out.needspeeling = true;
|
||||
if(firstWord == "SEEDSREMOVED")
|
||||
out.seedsremoved = true;
|
||||
if(firstWord == "OTHERFAMILY") {
|
||||
size_t found = str.find(",");
|
||||
if(found != std::string::npos) {
|
||||
out.otherfamily.push_back(str.substr(str.find_first_of(" ")+1,found-str.find_first_of(" ")-1));
|
||||
out.otherfamily.push_back(str.substr(found+2,str.length()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
std::cout << "Full Name: " << out.fullname << std::endl;
|
||||
std::cout << "Favourite Fruit: " << out.favouritefruit << std::endl;
|
||||
std::cout << "Needs peeling?: ";
|
||||
if(out.needspeeling == true)
|
||||
std::cout << "True" << std::endl;
|
||||
else
|
||||
std::cout << "False" << std::endl;
|
||||
std::cout << "Seeds removed?: ";
|
||||
if(out.seedsremoved == true)
|
||||
std::cout << "True" << std::endl;
|
||||
else
|
||||
std::cout << "False" << std::endl;
|
||||
std::cout << "Other family members: " << out.otherfamily[0] << ", " << out.otherfamily[1] << std::endl;
|
||||
}
|
||||
int main() {
|
||||
std::ifstream inp;
|
||||
confi outp;
|
||||
read_config(inp,outp);
|
||||
}
|
||||
171
Task/Read-a-configuration-file/C/read-a-configuration-file.c
Normal file
171
Task/Read-a-configuration-file/C/read-a-configuration-file.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <confini.h>
|
||||
|
||||
#define rosetta_uint8_t unsigned char
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define CONFIGS_TO_READ 5
|
||||
#define INI_ARRAY_DELIMITER ','
|
||||
|
||||
/* Assume that the config file represent a struct containing all the parameters to load */
|
||||
struct configs {
|
||||
char *fullname;
|
||||
char *favouritefruit;
|
||||
rosetta_uint8_t needspeeling;
|
||||
rosetta_uint8_t seedsremoved;
|
||||
char **otherfamily;
|
||||
size_t otherfamily_len;
|
||||
size_t _configs_left_;
|
||||
};
|
||||
|
||||
static char ** make_array (size_t * arrlen, const char * src, const size_t buffsize, IniFormat ini_format) {
|
||||
|
||||
/* Allocate a new array of strings and populate it from the stringified source */
|
||||
*arrlen = ini_array_get_length(src, INI_ARRAY_DELIMITER, ini_format);
|
||||
char ** const dest = *arrlen ? (char **) malloc(*arrlen * sizeof(char *) + buffsize) : NULL;
|
||||
if (!dest) { return NULL; }
|
||||
memcpy(dest + *arrlen, src, buffsize);
|
||||
char * iter = (char *) (dest + *arrlen);
|
||||
for (size_t idx = 0; idx < *arrlen; idx++) {
|
||||
dest[idx] = ini_array_release(&iter, INI_ARRAY_DELIMITER, ini_format);
|
||||
ini_string_parse(dest[idx], ini_format);
|
||||
}
|
||||
return dest;
|
||||
|
||||
}
|
||||
|
||||
static int configs_member_handler (IniDispatch *this, void *v_confs) {
|
||||
|
||||
struct configs *confs = (struct configs *) v_confs;
|
||||
|
||||
if (this->type != INI_KEY) {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
if (ini_string_match_si("FULLNAME", this->data, this->format)) {
|
||||
|
||||
if (confs->fullname) { return 0; }
|
||||
this->v_len = ini_string_parse(this->value, this->format); /* Remove all quotes, if any */
|
||||
confs->fullname = strndup(this->value, this->v_len);
|
||||
confs->_configs_left_--;
|
||||
|
||||
} else if (ini_string_match_si("FAVOURITEFRUIT", this->data, this->format)) {
|
||||
|
||||
if (confs->favouritefruit) { return 0; }
|
||||
this->v_len = ini_string_parse(this->value, this->format); /* Remove all quotes, if any */
|
||||
confs->favouritefruit = strndup(this->value, this->v_len);
|
||||
confs->_configs_left_--;
|
||||
|
||||
} else if (ini_string_match_si("NEEDSPEELING", this->data, this->format)) {
|
||||
|
||||
if (~confs->needspeeling & 0x80) { return 0; }
|
||||
confs->needspeeling = ini_get_bool(this->value, TRUE);
|
||||
confs->_configs_left_--;
|
||||
|
||||
} else if (ini_string_match_si("SEEDSREMOVED", this->data, this->format)) {
|
||||
|
||||
if (~confs->seedsremoved & 0x80) { return 0; }
|
||||
confs->seedsremoved = ini_get_bool(this->value, TRUE);
|
||||
confs->_configs_left_--;
|
||||
|
||||
} else if (!confs->otherfamily && ini_string_match_si("OTHERFAMILY", this->data, this->format)) {
|
||||
|
||||
if (confs->otherfamily) { return 0; }
|
||||
this->v_len = ini_array_collapse(this->value, INI_ARRAY_DELIMITER, this->format); /* Save memory (not strictly needed) */
|
||||
confs->otherfamily = make_array(&confs->otherfamily_len, this->value, this->v_len + 1, this->format);
|
||||
confs->_configs_left_--;
|
||||
|
||||
}
|
||||
|
||||
/* Optimization: stop reading the INI file when we have all we need */
|
||||
return !confs->_configs_left_;
|
||||
|
||||
}
|
||||
|
||||
static int populate_configs (struct configs * confs) {
|
||||
|
||||
/* Define the format of the configuration file */
|
||||
IniFormat config_format = {
|
||||
.delimiter_symbol = INI_ANY_SPACE,
|
||||
.case_sensitive = FALSE,
|
||||
.semicolon_marker = INI_IGNORE,
|
||||
.hash_marker = INI_IGNORE,
|
||||
.multiline_nodes = INI_NO_MULTILINE,
|
||||
.section_paths = INI_NO_SECTIONS,
|
||||
.no_single_quotes = FALSE,
|
||||
.no_double_quotes = FALSE,
|
||||
.no_spaces_in_names = TRUE,
|
||||
.implicit_is_not_empty = TRUE,
|
||||
.do_not_collapse_values = FALSE,
|
||||
.preserve_empty_quotes = FALSE,
|
||||
.disabled_after_space = TRUE,
|
||||
.disabled_can_be_implicit = FALSE
|
||||
};
|
||||
|
||||
*confs = (struct configs) { NULL, NULL, 0x80, 0x80, NULL, 0, CONFIGS_TO_READ };
|
||||
|
||||
if (load_ini_path("rosetta.conf", config_format, NULL, configs_member_handler, confs) & CONFINI_ERROR) {
|
||||
|
||||
fprintf(stderr, "Sorry, something went wrong :-(\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
confs->needspeeling &= 0x7F;
|
||||
confs->seedsremoved &= 0x7F;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main () {
|
||||
|
||||
struct configs confs;
|
||||
|
||||
ini_global_set_implicit_value("YES", 0);
|
||||
|
||||
if (populate_configs(&confs)) {
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* Print the configurations parsed */
|
||||
|
||||
printf(
|
||||
|
||||
"Full name: %s\n"
|
||||
"Favorite fruit: %s\n"
|
||||
"Need spelling: %s\n"
|
||||
"Seeds removed: %s\n",
|
||||
|
||||
confs.fullname,
|
||||
confs.favouritefruit,
|
||||
confs.needspeeling ? "True" : "False",
|
||||
confs.seedsremoved ? "True" : "False"
|
||||
|
||||
);
|
||||
|
||||
for (size_t idx = 0; idx < confs.otherfamily_len; idx++) {
|
||||
|
||||
printf("Other family[%d]: %s\n", idx, confs.otherfamily[idx]);
|
||||
|
||||
}
|
||||
|
||||
/* Free the allocated memory */
|
||||
|
||||
#define FREE_NON_NULL(PTR) if (PTR) { free(PTR); }
|
||||
|
||||
FREE_NON_NULL(confs.fullname);
|
||||
FREE_NON_NULL(confs.favouritefruit);
|
||||
FREE_NON_NULL(confs.otherfamily);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
identification division.
|
||||
program-id. ReadConfiguration.
|
||||
|
||||
environment division.
|
||||
configuration section.
|
||||
repository.
|
||||
function all intrinsic.
|
||||
|
||||
input-output section.
|
||||
file-control.
|
||||
select config-file assign to "Configuration.txt"
|
||||
organization line sequential.
|
||||
data division.
|
||||
file section.
|
||||
|
||||
fd config-file.
|
||||
01 config-record pic is x(128).
|
||||
|
||||
working-storage section.
|
||||
77 idx pic 9(3).
|
||||
77 pos pic 9(3).
|
||||
77 last-pos pic 9(3).
|
||||
77 config-key pic x(32).
|
||||
77 config-value pic x(64).
|
||||
77 multi-value pic x(64).
|
||||
77 full-name pic x(64).
|
||||
77 favourite-fruit pic x(64).
|
||||
77 other-family pic x(64) occurs 10.
|
||||
77 need-speeling pic x(5) value "false".
|
||||
77 seeds-removed pic x(5) value "false".
|
||||
|
||||
procedure division.
|
||||
main.
|
||||
open input config-file
|
||||
perform until exit
|
||||
read config-file
|
||||
at end
|
||||
exit perform
|
||||
end-read
|
||||
move trim(config-record) to config-record
|
||||
if config-record(1:1) = "#" or ";" or spaces
|
||||
exit perform cycle
|
||||
end-if
|
||||
unstring config-record delimited by spaces into config-key
|
||||
move trim(config-record(length(trim(config-key)) + 1:)) to config-value
|
||||
if config-value(1:1) = "="
|
||||
move trim(config-value(2:)) to config-value
|
||||
end-if
|
||||
evaluate upper-case(config-key)
|
||||
when "FULLNAME"
|
||||
move config-value to full-name
|
||||
when "FAVOURITEFRUIT"
|
||||
move config-value to favourite-fruit
|
||||
when "NEEDSPEELING"
|
||||
if config-value = spaces
|
||||
move "true" to config-value
|
||||
end-if
|
||||
if config-value = "true" or "false"
|
||||
move config-value to need-speeling
|
||||
end-if
|
||||
when "SEEDSREMOVED"
|
||||
if config-value = spaces
|
||||
move "true" to config-value
|
||||
end-if,
|
||||
if config-value = "true" or "false"
|
||||
move config-value to seeds-removed
|
||||
end-if
|
||||
when "OTHERFAMILY"
|
||||
move 1 to idx, pos
|
||||
perform until exit
|
||||
unstring config-value delimited by "," into multi-value with pointer pos
|
||||
on overflow
|
||||
move trim(multi-value) to other-family(idx)
|
||||
move pos to last-pos
|
||||
not on overflow
|
||||
if config-value(last-pos:) <> spaces
|
||||
move trim(config-value(last-pos:)) to other-family(idx)
|
||||
end-if,
|
||||
exit perform
|
||||
end-unstring
|
||||
add 1 to idx
|
||||
end-perform
|
||||
end-evaluate
|
||||
end-perform
|
||||
close config-file
|
||||
|
||||
display "fullname = " full-name
|
||||
display "favouritefruit = " favourite-fruit
|
||||
display "needspeeling = " need-speeling
|
||||
display "seedsremoved = " seeds-removed
|
||||
perform varying idx from 1 by 1 until idx > 10
|
||||
if other-family(idx) <> low-values
|
||||
display "otherfamily(" idx ") = " other-family(idx)
|
||||
end-if
|
||||
end-perform
|
||||
.
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
(ns read-conf-file.core
|
||||
(:require [clojure.java.io :as io]
|
||||
[clojure.string :as str])
|
||||
(:gen-class))
|
||||
|
||||
(def conf-keys ["fullname"
|
||||
"favouritefruit"
|
||||
"needspeeling"
|
||||
"seedsremoved"
|
||||
"otherfamily"])
|
||||
|
||||
(defn get-lines
|
||||
"Read file returning vec of lines."
|
||||
[file]
|
||||
(try
|
||||
(with-open [rdr (io/reader file)]
|
||||
(into [] (line-seq rdr)))
|
||||
(catch Exception e (.getMessage e))))
|
||||
|
||||
(defn parse-line
|
||||
"Parse passed line returning vec: token, vec of values."
|
||||
[line]
|
||||
(if-let [[_ k v] (re-matches #"(?i)^\s*([a-z]+)(?:\s+|=)?(.+)?$" line)]
|
||||
(let [k (str/lower-case k)]
|
||||
(if v
|
||||
[k (str/split v #",\s*")]
|
||||
[k [true]]))))
|
||||
|
||||
(defn mk-conf
|
||||
"Build configuration map from lines."
|
||||
[lines]
|
||||
(->> (map parse-line lines)
|
||||
(filter (comp not nil?))
|
||||
(reduce (fn
|
||||
[m [k v]]
|
||||
(assoc m k v)) {})))
|
||||
|
||||
(defn output
|
||||
[conf-keys conf]
|
||||
(doseq [k conf-keys]
|
||||
(let [v (get conf k)]
|
||||
(if v
|
||||
(println (format "%s = %s" k (str/join ", " v)))
|
||||
(println (format "%s = %s" k "false"))))))
|
||||
|
||||
(defn -main
|
||||
[filename]
|
||||
(output conf-keys (mk-conf (get-lines filename))))
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
(ql:quickload :parser-combinators)
|
||||
|
||||
(defpackage :read-config
|
||||
(:use :cl :parser-combinators))
|
||||
|
||||
(in-package :read-config)
|
||||
|
||||
(defun trim-space (string)
|
||||
(string-trim '(#\space #\tab) string))
|
||||
|
||||
(defun any-but1? (except)
|
||||
(named-seq? (<- res (many1? (except? (item) except)))
|
||||
(coerce res 'string)))
|
||||
|
||||
(defun values? ()
|
||||
(named-seq? (<- values (sepby? (any-but1? #\,) #\,))
|
||||
(mapcar 'trim-space values)))
|
||||
|
||||
(defun key-values? ()
|
||||
(named-seq? (<- key (word?))
|
||||
(opt? (many? (whitespace?)))
|
||||
(opt? #\=)
|
||||
(<- values (values?))
|
||||
(cons key (or (if (cdr values) values (car values)) t))))
|
||||
|
||||
(defun parse-line (line)
|
||||
(setf line (trim-space line))
|
||||
(if (or (string= line "") (member (char line 0) '(#\# #\;)))
|
||||
:comment
|
||||
(parse-string* (key-values?) line)))
|
||||
|
||||
(defun parse-config (stream)
|
||||
(let ((hash (make-hash-table :test 'equal)))
|
||||
(loop for line = (read-line stream nil nil)
|
||||
while line
|
||||
do (let ((parsed (parse-line line)))
|
||||
(cond ((eq parsed :comment))
|
||||
((eq parsed nil) (error "config parser error: ~a" line))
|
||||
(t (setf (gethash (car parsed) hash) (cdr parsed))))))
|
||||
hash))
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
READ-CONFIG> (with-open-file (s "test.cfg") (parse-config s))
|
||||
#<HASH-TABLE :TEST EQUAL :COUNT 4 {100BD25B43}>
|
||||
READ-CONFIG> (maphash (lambda (k v) (print (list k v))) *)
|
||||
|
||||
("FULLNAME" "Foo Barber")
|
||||
("FAVOURITEFRUIT" "banana")
|
||||
("NEEDSPEELING" T)
|
||||
("OTHERFAMILY" ("Rhu Barber" "Harry Barber"))
|
||||
NIL
|
||||
READ-CONFIG> (gethash "SEEDSREMOVED" **)
|
||||
NIL
|
||||
NIL
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import std.stdio, std.string, std.conv, std.regex, std.getopt;
|
||||
|
||||
enum VarName(alias var) = var.stringof;
|
||||
|
||||
void setOpt(alias Var)(in string line) {
|
||||
auto m = match(line, regex(`^(?i)` ~ VarName!Var ~ `(?-i)(\s*=?\s+(.*))?`));
|
||||
|
||||
if (!m.empty) {
|
||||
static if (is(typeof(Var) == string[]))
|
||||
Var = m.captures.length > 2 ? m.captures[2].split(regex(`\s*,\s*`)) : [""];
|
||||
static if (is(typeof(Var) == string))
|
||||
Var = m.captures.length > 2 ? m.captures[2] : "";
|
||||
static if (is(typeof(Var) == bool))
|
||||
Var = true;
|
||||
static if (is(typeof(Var) == int))
|
||||
Var = m.captures.length > 2 ? to!int(m.captures[2]) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void main(in string[] args) {
|
||||
string fullName, favouriteFruit;
|
||||
string[] otherFamily;
|
||||
bool needsPeeling, seedsRemoved; // Default false.
|
||||
|
||||
auto f = "readcfg.conf".File;
|
||||
|
||||
foreach (line; f.byLine) {
|
||||
auto opt = line.strip.idup;
|
||||
|
||||
setOpt!fullName(opt);
|
||||
setOpt!favouriteFruit(opt);
|
||||
setOpt!needsPeeling(opt);
|
||||
setOpt!seedsRemoved(opt);
|
||||
setOpt!otherFamily(opt);
|
||||
}
|
||||
|
||||
writefln("%s = %s", VarName!fullName, fullName);
|
||||
writefln("%s = %s", VarName!favouriteFruit, favouriteFruit);
|
||||
writefln("%s = %s", VarName!needsPeeling, needsPeeling);
|
||||
writefln("%s = %s", VarName!seedsRemoved, seedsRemoved);
|
||||
writefln("%s = %s", VarName!otherFamily, otherFamily);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import std.stdio, std.string, std.conv, std.regex, std.algorithm;
|
||||
|
||||
auto reNameValue = ctRegex!(`^(\w+)\s*=?\s*(\S.*)?`);// ctRegex creates regexp parser at compile time
|
||||
|
||||
// print Config members w/o hardcoding names
|
||||
void PrintMembers(Config c)
|
||||
{
|
||||
foreach(M; __traits(derivedMembers, Config))
|
||||
writeln(M ~ ` = `, __traits(getMember, c, M));
|
||||
}
|
||||
|
||||
void main(in string[] args /* arg[0] is EXE name */) {
|
||||
|
||||
auto cfg = new Config;
|
||||
auto f = args[1].File;// open config given in command line
|
||||
foreach (line; f.byLineCopy.map!(s => s.strip).filter!(s => !s.empty && s[0] != '#' && s[0] != ';')) {// free loop from unnecessary lines
|
||||
auto m = matchFirst(line, reNameValue);
|
||||
if (m.empty) { writeln(`Wrong config line: ` ~ line); continue; }
|
||||
|
||||
switch(m[1].toUpper) {
|
||||
case `FULLNAME`: cfg.FullName = m[2]; break;
|
||||
case `FAVOURITEFRUIT`: cfg.FavouriteFruit = m[2]; break;
|
||||
case `NEEDSPEELING`: cfg.needsPeeling = (m[2].toUpper != `FALSE`); break;
|
||||
case `SEEDSREMOVED`: cfg.seedsRemoved = (m[2].toUpper != `FALSE`); break;
|
||||
case `OTHERFAMILY`: cfg.otherFamily = split(m[2], regex(`\s*,\s*`)); break;// regex allows to avoid 'strip' step
|
||||
default:
|
||||
writeln(`Unknown config variable: ` ~ m[1]);
|
||||
}
|
||||
}
|
||||
PrintMembers(cfg);
|
||||
}
|
||||
|
||||
class Config
|
||||
{
|
||||
string FullName;
|
||||
string FavouriteFruit;
|
||||
bool needsPeeling;
|
||||
bool seedsRemoved;
|
||||
string[] otherFamily;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
$ open input config.ini
|
||||
$ loop:
|
||||
$ read /end_of_file = done input line
|
||||
$ line = f$edit( line, "trim" ) ! removes leading and trailing spaces or tabs
|
||||
$ if f$length( line ) .eq. 0 then $ goto loop
|
||||
$ first_character = f$extract( 0, 1, line )
|
||||
$ if first_character .eqs. "#" .or. first_character .eqs. ";" then $ goto loop
|
||||
$ equal_sign_offset = f$locate( "=", line )
|
||||
$ length_of_line = f$length( line )
|
||||
$ if equal_sign_offset .ne. length_of_line then $ line = f$extract( 0, equal_sign_offset, line ) + " " + f$extract( equal_sign_offset + 1, length_of_line, line )
|
||||
$ option_name = f$element( 0, " ", line )
|
||||
$ parameter_data = line - option_name - " "
|
||||
$ if parameter_data .eqs. "" then $ parameter_data = "true"
|
||||
$ 'option_name = parameter_data
|
||||
$ show symbol 'option_name
|
||||
$ goto loop
|
||||
$ done:
|
||||
$ close input
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
unit uSettings;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils, System.IoUtils, System.Generics.Collections, System.Variants;
|
||||
|
||||
type
|
||||
TVariable = record
|
||||
value: variant;
|
||||
function ToString: string;
|
||||
class operator Implicit(a: variant): TVariable;
|
||||
class operator Implicit(a: TVariable): TArray<string>;
|
||||
class operator Implicit(a: TVariable): string;
|
||||
end;
|
||||
|
||||
TSettings = class(TDictionary<string, TVariable>)
|
||||
private
|
||||
function GetVariable(key: string): TVariable;
|
||||
procedure SetVariable(key: string; const Value: TVariable);
|
||||
function GetKey(line: string; var key: string; var value: variant; var
|
||||
disable: boolean): boolean;
|
||||
function GetAllKeys: TList<string>;
|
||||
public
|
||||
procedure LoadFromFile(Filename: TfileName);
|
||||
procedure SaveToFile(Filename: TfileName);
|
||||
property Variable[key: string]: TVariable read GetVariable write SetVariable; default;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TVariable }
|
||||
|
||||
class operator TVariable.Implicit(a: variant): TVariable;
|
||||
begin
|
||||
Result.value := a;
|
||||
end;
|
||||
|
||||
class operator TVariable.Implicit(a: TVariable): TArray<string>;
|
||||
begin
|
||||
if VarIsType(a.value, varArray or varOleStr) then
|
||||
Result := a.value
|
||||
else
|
||||
raise Exception.Create('Error: can''t convert this type data in array');
|
||||
end;
|
||||
|
||||
class operator TVariable.Implicit(a: TVariable): string;
|
||||
begin
|
||||
Result := a.ToString;
|
||||
end;
|
||||
|
||||
function TVariable.ToString: string;
|
||||
var
|
||||
arr: TArray<string>;
|
||||
begin
|
||||
if VarIsType(value, varArray or varOleStr) then
|
||||
begin
|
||||
arr := value;
|
||||
Result := string.Join(', ', arr).Trim;
|
||||
end
|
||||
else
|
||||
Result := value;
|
||||
Result := Result.Trim;
|
||||
end;
|
||||
|
||||
{ TSettings }
|
||||
|
||||
function TSettings.GetAllKeys: TList<string>;
|
||||
var
|
||||
key: string;
|
||||
begin
|
||||
Result := TList<string>.Create;
|
||||
for key in Keys do
|
||||
Result.Add(key);
|
||||
end;
|
||||
|
||||
function TSettings.GetKey(line: string; var key: string; var value: variant; var
|
||||
disable: boolean): boolean;
|
||||
var
|
||||
line_: string;
|
||||
j: integer;
|
||||
begin
|
||||
line_ := line.Trim;
|
||||
Result := not (line_.IsEmpty or (line_[1] = '#'));
|
||||
if not Result then
|
||||
exit;
|
||||
|
||||
disable := (line_[1] = ';');
|
||||
if disable then
|
||||
delete(line_, 1, 1);
|
||||
|
||||
var data := line_.Split([' '], TStringSplitOptions.ExcludeEmpty);
|
||||
case length(data) of
|
||||
1: //Boolean
|
||||
begin
|
||||
key := data[0].ToUpper;
|
||||
value := True;
|
||||
end;
|
||||
|
||||
2: //Single String
|
||||
begin
|
||||
key := data[0].ToUpper;
|
||||
value := data[1].Trim;
|
||||
end;
|
||||
|
||||
else // Mult String value or Array of value
|
||||
begin
|
||||
key := data[0];
|
||||
delete(line_, 1, key.Length);
|
||||
if line_.IndexOf(',') > -1 then
|
||||
begin
|
||||
data := line_.Trim.Split([','], TStringSplitOptions.ExcludeEmpty);
|
||||
for j := 0 to High(data) do
|
||||
data[j] := data[j].Trim;
|
||||
value := data;
|
||||
end
|
||||
else
|
||||
value := line_.Trim;
|
||||
end;
|
||||
end;
|
||||
Result := true;
|
||||
end;
|
||||
|
||||
function TSettings.GetVariable(key: string): TVariable;
|
||||
begin
|
||||
key := key.Trim.ToUpper;
|
||||
if not ContainsKey(key) then
|
||||
add(key, false);
|
||||
|
||||
result := Items[key];
|
||||
end;
|
||||
|
||||
procedure TSettings.LoadFromFile(Filename: TfileName);
|
||||
var
|
||||
key, line: string;
|
||||
value: variant;
|
||||
disabled: boolean;
|
||||
Lines: TArray<string>;
|
||||
begin
|
||||
if not FileExists(Filename) then
|
||||
exit;
|
||||
|
||||
Clear;
|
||||
Lines := TFile.ReadAllLines(Filename);
|
||||
for line in Lines do
|
||||
begin
|
||||
if GetKey(line, key, value, disabled) then
|
||||
begin
|
||||
if disabled then
|
||||
AddOrSetValue(key, False)
|
||||
else
|
||||
AddOrSetValue(key, value)
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSettings.SaveToFile(Filename: TfileName);
|
||||
var
|
||||
key, line: string;
|
||||
value: variant;
|
||||
disabled: boolean;
|
||||
Lines: TArray<string>;
|
||||
i: Integer;
|
||||
All_kyes: TList<string>;
|
||||
begin
|
||||
All_kyes := GetAllKeys();
|
||||
SetLength(Lines, 0);
|
||||
i := 0;
|
||||
if FileExists(Filename) then
|
||||
begin
|
||||
Lines := TFile.ReadAllLines(Filename);
|
||||
for i := high(Lines) downto 0 do
|
||||
begin
|
||||
if GetKey(Lines[i], key, value, disabled) then
|
||||
begin
|
||||
if not ContainsKey(key) then
|
||||
begin
|
||||
Lines[i] := '; ' + Lines[i];
|
||||
Continue;
|
||||
end;
|
||||
|
||||
All_kyes.Remove(key);
|
||||
|
||||
disabled := VarIsType(Variable[key].value, varBoolean) and (Variable[key].value
|
||||
= false);
|
||||
if not disabled then
|
||||
begin
|
||||
if VarIsType(Variable[key].value, varBoolean) then
|
||||
Lines[i] := key
|
||||
else
|
||||
Lines[i] := format('%s %s', [key, Variable[key].ToString])
|
||||
end
|
||||
else
|
||||
Lines[i] := '; ' + key;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
// new keys
|
||||
i := high(Lines) + 1;
|
||||
SetLength(Lines, Length(Lines) + All_kyes.Count);
|
||||
for key in All_kyes do
|
||||
begin
|
||||
Lines[i] := format('%s %s', [key, Variable[key].ToString]);
|
||||
inc(i);
|
||||
end;
|
||||
|
||||
Tfile.WriteAllLines(Filename, Lines);
|
||||
|
||||
All_kyes.Free;
|
||||
end;
|
||||
|
||||
procedure TSettings.SetVariable(key: string; const Value: TVariable);
|
||||
begin
|
||||
AddOrSetValue(key.Trim.ToUpper, Value);
|
||||
end;
|
||||
end.
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
program ReadAConfigFile;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
uSettings;
|
||||
|
||||
const
|
||||
FileName = 'Config.txt';
|
||||
|
||||
var
|
||||
Settings: TSettings;
|
||||
|
||||
procedure show(key: string; value: string);
|
||||
begin
|
||||
writeln(format('%14s = %s', [key, value]));
|
||||
end;
|
||||
|
||||
begin
|
||||
Settings := TSettings.Create;
|
||||
Settings.LoadFromFile(FileName);
|
||||
|
||||
for var k in Settings.Keys do
|
||||
show(k, Settings[k]);
|
||||
|
||||
Settings.Free;
|
||||
Readln;
|
||||
end.
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
(edit 'preferences)
|
||||
;; current contents to edit is displayed in the input box
|
||||
(define (preferences)
|
||||
(define-syntax-rule (++ n) (begin (set! n (1+ n)) n))
|
||||
(define-syntax-rule (% a b) (modulo a b))
|
||||
;; (lib 'gloops)
|
||||
(lib 'timer))
|
||||
|
||||
;; enter new preferences
|
||||
(define (preferences)
|
||||
(define FULLNAME "Foo Barber")
|
||||
(define FAVOURITEFRUIT 'banana)
|
||||
(define NEEDSPELLING #t)
|
||||
; SEEDSREMOVED
|
||||
(define OTHERFAMILY '("Rhu Barber" "Harry Barber")))
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
;; press F5 or COMMAND-R to reload
|
||||
EchoLisp - 2.13.12
|
||||
📗 local-db: db.version: 13
|
||||
|
||||
;; enter parameters names :
|
||||
NEEDSPELLING → #t
|
||||
FAVOURITEFRUIT → banana
|
||||
SEEDSREMOVED
|
||||
😡 error: #|user| : unbound variable : SEEDSREMOVED
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
defmodule Configuration_file do
|
||||
def read(file) do
|
||||
File.read!(file)
|
||||
|> String.split(~r/\n|\r\n|\r/, trim: true)
|
||||
|> Enum.reject(fn line -> String.starts_with?(line, ["#", ";"]) end)
|
||||
|> Enum.map(fn line ->
|
||||
case String.split(line, ~r/\s/, parts: 2) do
|
||||
[option] -> {to_atom(option), true}
|
||||
[option, values] -> {to_atom(option), separate(values)}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def task do
|
||||
defaults = [fullname: "Kalle", favouritefruit: "apple", needspeeling: false, seedsremoved: false]
|
||||
options = read("configuration_file") ++ defaults
|
||||
[:fullname, :favouritefruit, :needspeeling, :seedsremoved, :otherfamily]
|
||||
|> Enum.each(fn x ->
|
||||
values = options[x]
|
||||
if is_boolean(values) or length(values)==1 do
|
||||
IO.puts "#{x} = #{values}"
|
||||
else
|
||||
Enum.with_index(values) |> Enum.each(fn {value,i} ->
|
||||
IO.puts "#{x}(#{i+1}) = #{value}"
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
defp to_atom(option), do: String.downcase(option) |> String.to_atom
|
||||
|
||||
defp separate(values), do: String.split(values, ",") |> Enum.map(&String.strip/1)
|
||||
end
|
||||
|
||||
Configuration_file.task
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
-module( configuration_file ).
|
||||
|
||||
-export( [read/1, task/0] ).
|
||||
|
||||
read( File ) ->
|
||||
{ok, Binary} = file:read_file( File ),
|
||||
Lines = [X || <<First:8, _T/binary>> = X <- binary:split(Binary, <<"\n">>, [global]), First =/= $#, First =/= $;],
|
||||
[option_from_binaries(binary:split(X, <<" ">>)) || X <- Lines].
|
||||
|
||||
task() ->
|
||||
Defaults = [{fullname, "Kalle"}, {favouritefruit, "apple"}, {needspeeling, false}, {seedsremoved, false}],
|
||||
Options = read( "configuration_file" ) ++ Defaults,
|
||||
[io:fwrite("~p = ~p~n", [X, proplists:get_value(X, Options)]) || X <- [fullname, favouritefruit, needspeeling, seedsremoved, otherfamily]].
|
||||
|
||||
|
||||
|
||||
option_from_binaries( [Option] ) -> {erlang:list_to_atom(string:to_lower(erlang:binary_to_list(Option))), true};
|
||||
option_from_binaries( [Option, Values] ) -> {erlang:list_to_atom(string:to_lower(erlang:binary_to_list(Option))), option_from_binaries_value(binary:split(Values, <<", ">>))}.
|
||||
|
||||
option_from_binaries_value( [Value] ) -> erlang:binary_to_list(Value);
|
||||
option_from_binaries_value( Values ) -> [erlang:binary_to_list(X) || X <- Values].
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
class Main
|
||||
{
|
||||
// remove the given key and an optional '=' from start of line
|
||||
Str removeKey (Str key, Str line)
|
||||
{
|
||||
remainder := line[key.size..-1].trim
|
||||
if (remainder.startsWith("="))
|
||||
{
|
||||
remainder = remainder.replace("=", "").trim
|
||||
}
|
||||
return remainder
|
||||
}
|
||||
|
||||
Void main ()
|
||||
{
|
||||
// define the variables which need configuring
|
||||
fullname := ""
|
||||
favouritefruit := ""
|
||||
needspeeling := false
|
||||
seedsremoved := false
|
||||
Str[] otherfamily := [,]
|
||||
|
||||
// loop through the file, setting variables as needed
|
||||
File(`config.dat`).eachLine |Str line|
|
||||
{
|
||||
line = line.trim
|
||||
if (line.isEmpty || line.startsWith("#") || line.startsWith(";"))
|
||||
{
|
||||
// do nothing for empty and comment lines
|
||||
}
|
||||
else if (line.upper.startsWith("FULLNAME"))
|
||||
{
|
||||
fullname = removeKey("FULLNAME", line)
|
||||
}
|
||||
else if (line.upper.startsWith("FAVOURITEFRUIT"))
|
||||
{
|
||||
favouritefruit = removeKey("FAVOURITEFRUIT", line)
|
||||
}
|
||||
else if (line.upper.startsWith("NEEDSPEELING"))
|
||||
{
|
||||
needspeeling = true
|
||||
}
|
||||
else if (line.upper.startsWith("SEEDSREMOVED"))
|
||||
{
|
||||
seedsremoved = true
|
||||
}
|
||||
else if (line.upper.startsWith("OTHERFAMILY"))
|
||||
{
|
||||
otherfamily = removeKey("OTHERFAMILY", line).split(',')
|
||||
}
|
||||
}
|
||||
|
||||
// report results
|
||||
echo ("Full name is $fullname")
|
||||
echo ("Favourite fruit is $favouritefruit")
|
||||
echo ("Needs peeling is $needspeeling")
|
||||
echo ("Seeds removed is $seedsremoved")
|
||||
echo ("Other family is " + otherfamily.join(", "))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
\ declare the configuration variables in the FORTH app
|
||||
FORTH DEFINITIONS
|
||||
|
||||
32 CONSTANT $SIZE
|
||||
|
||||
VARIABLE FULLNAME $SIZE ALLOT
|
||||
VARIABLE FAVOURITEFRUIT $SIZE ALLOT
|
||||
VARIABLE NEEDSPEELING
|
||||
VARIABLE SEEDSREMOVED
|
||||
VARIABLE OTHERFAMILY(1) $SIZE ALLOT
|
||||
VARIABLE OTHERFAMILY(2) $SIZE ALLOT
|
||||
|
||||
: -leading ( addr len -- addr' len' )
|
||||
begin over c@ bl = while 1 /string repeat ; \ remove leading blanks
|
||||
|
||||
: trim ( addr len -- addr len) -leading -trailing ; \ remove blanks both ends
|
||||
|
||||
\ create the config file interpreter -------
|
||||
VOCABULARY CONFIG \ create a namespace
|
||||
CONFIG DEFINITIONS \ put things in the namespace
|
||||
: SET ( addr --) true swap ! ;
|
||||
: RESET ( addr --) false swap ! ;
|
||||
: # ( -- ) 1 PARSE 2DROP ; \ parse line and throw away
|
||||
: = ( addr --) 1 PARSE trim ROT PLACE ; \ string assignment operator
|
||||
synonym ; # \ 2nd comment operator is simple
|
||||
|
||||
FORTH DEFINITIONS
|
||||
\ this command reads and interprets the config.txt file
|
||||
: CONFIGURE ( -- ) CONFIG s" CONFIG.TXT" INCLUDED FORTH ;
|
||||
\ config file interpreter ends ------
|
||||
|
||||
\ tools to validate the CONFIG interpreter
|
||||
: $. ( str --) count type ;
|
||||
: BOOL. ( ? --) @ IF ." ON" ELSE ." OFF" THEN ;
|
||||
|
||||
: .CONFIG CR ." Fullname : " FULLNAME $.
|
||||
CR ." Favourite fruit: " FAVOURITEFRUIT $.
|
||||
CR ." Needs peeling : " NEEDSPEELING bool.
|
||||
CR ." Seeds removed : " SEEDSREMOVED bool.
|
||||
CR ." Family:"
|
||||
CR otherfamily(1) $.
|
||||
CR otherfamily(2) $. ;
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
program readconfig
|
||||
implicit none
|
||||
integer, parameter :: strlen = 100
|
||||
logical :: needspeeling = .false., seedsremoved =.false.
|
||||
character(len=strlen) :: favouritefruit = "", fullname = "", fst, snd
|
||||
character(len=strlen), allocatable :: otherfamily(:), tmp(:)
|
||||
character(len=1000) :: line
|
||||
integer :: lun, stat, j, j0, j1, ii = 1, z
|
||||
integer, parameter :: state_begin=1, state_in_fst=2, state_in_sep=3
|
||||
|
||||
open(newunit=lun, file="config.ini", status="old")
|
||||
|
||||
do
|
||||
read(lun, "(a)", iostat=stat) line
|
||||
if (stat<0) exit
|
||||
if ((line(1:1) == "#") .or. &
|
||||
(line(1:1) == ";") .or. &
|
||||
(len_trim(line)==0)) then
|
||||
cycle
|
||||
end if
|
||||
z = state_begin
|
||||
do j = 1, len_trim(line)
|
||||
if (z == state_begin) then
|
||||
if (line(j:j)/=" ") then
|
||||
j0 = j
|
||||
z = state_in_fst
|
||||
end if
|
||||
elseif (z == state_in_fst) then
|
||||
if (index("= ",line(j:j))>0) then
|
||||
fst = lower(line(j0:j-1))
|
||||
z = state_in_sep
|
||||
end if
|
||||
elseif (z == state_in_sep) then
|
||||
if (index(" =",line(j:j)) == 0) then
|
||||
snd = line(j:)
|
||||
exit
|
||||
end if
|
||||
else
|
||||
stop "not possible to be here"
|
||||
end if
|
||||
end do
|
||||
if (z == state_in_fst) then
|
||||
fst = lower(line(j0:))
|
||||
elseif (z == state_begin) then
|
||||
cycle
|
||||
end if
|
||||
|
||||
if (fst=="fullname") then
|
||||
read(snd,"(a)") fullname
|
||||
elseif (fst=="favouritefruit") then
|
||||
read(snd,"(a)") favouritefruit
|
||||
elseif (fst=="seedsremoved") then
|
||||
seedsremoved = .true.
|
||||
elseif (fst=="needspeeling") then
|
||||
needspeeling = .true.
|
||||
elseif (fst=="otherfamily") then
|
||||
j = 1; ii = 1
|
||||
do while (len_trim(snd(j:)) >0)
|
||||
j1 = index(snd(j:),",")
|
||||
if (j1==0) then
|
||||
j1 = len_trim(snd)
|
||||
else
|
||||
j1 = j + j1 - 2
|
||||
end if
|
||||
do
|
||||
if (j>len_trim(snd)) exit
|
||||
if (snd(j:j) /= " ") exit
|
||||
j = j +1
|
||||
end do
|
||||
allocate(tmp(ii))
|
||||
tmp(1:ii-1) = otherfamily
|
||||
call move_alloc(tmp, otherfamily)
|
||||
read(snd(j:j1),"(a)"), otherfamily(ii)
|
||||
j = j1 + 2
|
||||
ii = ii + 1
|
||||
end do
|
||||
else
|
||||
print *, "unknown option '"//trim(fst)//"'"; stop
|
||||
end if
|
||||
end do
|
||||
close(lun)
|
||||
|
||||
print "(a,a)","fullname = ", trim(fullname)
|
||||
print "(a,a)","favouritefruit = ", trim(favouritefruit)
|
||||
print "(a,l)","needspeeling = ", needspeeling
|
||||
print "(a,l)","seedsremoved = ", seedsremoved
|
||||
print "(a,*(a,:,', '))", "otherfamily = ", &
|
||||
(trim(otherfamily(j)), j=1,size(otherfamily))
|
||||
|
||||
contains
|
||||
|
||||
pure function lower (str) result (string)
|
||||
implicit none
|
||||
character(*), intent(In) :: str
|
||||
character(len(str)) :: string
|
||||
Integer :: ic, i
|
||||
|
||||
character(26), parameter :: cap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
character(26), parameter :: low = 'abcdefghijklmnopqrstuvwxyz'
|
||||
|
||||
string = str
|
||||
do i = 1, len_trim(str)
|
||||
ic = index(cap, str(i:i))
|
||||
if (ic > 0) string(i:i) = low(ic:ic)
|
||||
end do
|
||||
end function
|
||||
|
||||
end program
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
' FB 1.05.0 Win64
|
||||
|
||||
Sub split (s As Const String, sepList As Const String, result() As String)
|
||||
If s = "" OrElse sepList = "" Then
|
||||
Redim result(0)
|
||||
result(0) = s
|
||||
Return
|
||||
End If
|
||||
Dim As Integer i, j, count = 0, empty = 0, length
|
||||
Dim As Integer position(Len(s) + 1)
|
||||
position(0) = 0
|
||||
|
||||
For i = 0 To len(s) - 1
|
||||
For j = 0 to Len(sepList) - 1
|
||||
If s[i] = sepList[j] Then
|
||||
count += 1
|
||||
position(count) = i + 1
|
||||
End If
|
||||
Next j
|
||||
Next i
|
||||
|
||||
Redim result(count)
|
||||
If count = 0 Then
|
||||
result(0) = s
|
||||
Return
|
||||
End If
|
||||
|
||||
position(count + 1) = len(s) + 1
|
||||
|
||||
For i = 1 To count + 1
|
||||
length = position(i) - position(i - 1) - 1
|
||||
result(i - 1) = Mid(s, position(i - 1) + 1, length)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
Type ConfigData
|
||||
fullName As String
|
||||
favouriteFruit As String
|
||||
needsPeeling As Boolean
|
||||
seedsRemoved As Boolean
|
||||
otherFamily(Any) As String
|
||||
End Type
|
||||
|
||||
Sub readConfigData(fileName As String, cData As ConfigData)
|
||||
Dim fileNum As Integer = FreeFile
|
||||
Open fileName For Input As #fileNum
|
||||
If err > 0 Then
|
||||
Print "File could not be opened"
|
||||
Sleep
|
||||
End
|
||||
End If
|
||||
Dim ln As String
|
||||
While Not Eof(fileNum)
|
||||
Line Input #fileNum, ln
|
||||
If ln = "" OrElse Left(ln, 1) = "#" OrElse Left(ln, 1) = ";" Then Continue While
|
||||
If UCase(Left(ln, 8)) = "FULLNAME" Then
|
||||
cData.fullName = Trim(Mid(ln, 9), Any " =")
|
||||
ElseIf UCase(Left(ln, 14)) = "FAVOURITEFRUIT" Then
|
||||
cData.favouriteFruit = Trim(Mid(ln, 15), Any " =")
|
||||
ElseIf UCase(Left(ln, 12)) = "NEEDSPEELING" Then
|
||||
Dim s As String = Trim(Mid(ln, 13), Any " =")
|
||||
If s = "" OrElse UCase(s) = "TRUE" Then
|
||||
cData.needsPeeling = True
|
||||
Else
|
||||
cData.needsPeeling = False
|
||||
End If
|
||||
ElseIf UCase(Left(ln, 12)) = "SEEDSREMOVED" Then
|
||||
Dim s As String = Trim(Mid(ln, 13), Any " =")
|
||||
If s = "" OrElse UCase(s) = "TRUE" Then
|
||||
cData.seedsRemoved = True
|
||||
Else
|
||||
cData.seedsRemoved = False
|
||||
End If
|
||||
ElseIf UCase(Left(ln, 11)) = "OTHERFAMILY" Then
|
||||
split Mid(ln, 12), ",", cData.otherFamily()
|
||||
For i As Integer = LBound(cData.otherFamily) To UBound(cData.otherFamily)
|
||||
cData.otherFamily(i) = Trim(cData.otherFamily(i), Any " =")
|
||||
Next
|
||||
End If
|
||||
Wend
|
||||
Close #fileNum
|
||||
End Sub
|
||||
|
||||
Dim fileName As String = "config.txt"
|
||||
Dim cData As ConfigData
|
||||
readConfigData fileName, cData
|
||||
Print "Full name = "; cData.fullName
|
||||
Print "Favourite fruit = "; cData.favouriteFruit
|
||||
Print "Needs peeling = "; cData.needsPeeling
|
||||
Print "Seeds removed = "; cData.seedsRemoved
|
||||
For i As Integer = LBound(cData.otherFamily) To UBound(cData.otherFamily)
|
||||
Print "Other family("; Str(i); ") = "; cData.otherFamily(i)
|
||||
Next
|
||||
Print
|
||||
Print "Press any key to quit"
|
||||
Sleep
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
local fn SaveConfiguration
|
||||
CFDictionaryRef defaults = @{¬
|
||||
@"FULLNAME" : @"Foo Barber",¬
|
||||
@"FAVOURITEFRUIT" : @"banana",¬
|
||||
@"NEEDSPEELING" : @YES,¬
|
||||
@"SEEDSREMOVED" : @NO,¬
|
||||
@"OTHERFAMILY" : @[@"Rhu Barber", @"Harry Barber"]}
|
||||
|
||||
UserDefaultsRegisterDefaults( defaults )
|
||||
end fn
|
||||
|
||||
local fn ReadConfiguration
|
||||
CFStringRef tempStr
|
||||
|
||||
CFStringRef fullname = fn UserDefaultsString( @"FULLNAME" )
|
||||
CFStringRef favouritefruit = fn UserDefaultsString( @"FAVOURITEFRUIT" )
|
||||
BOOL needspeeling = fn UserDefaultsBool( @"NEEDSPEELING" )
|
||||
BOOL seedsremoved = fn UserDefaultsBool( @"SEEDSREMOVED" )
|
||||
CFArrayRef otherfamily = fn UserDefaultsArray( @"OTHERFAMILY" )
|
||||
|
||||
printf @"Saved configuration:\n"
|
||||
printf @"FULLNAME: %@", fullname
|
||||
printf @"FAVOURITEFRUIT: %@", favouritefruit
|
||||
if needspeeling == YES then tempStr = @"TRUE" else tempStr = @"FALSE"
|
||||
printf @"NEEDSPEELING: %@", tempStr
|
||||
if seedsremoved == YES then tempStr = @"TRUE" else tempStr = @"FALSE"
|
||||
printf @"SEEDSREMOVED: %@", @"(undefined)"
|
||||
printf @"OTHERFAMILY: %@, %@", otherfamily[0], otherfamily[1]
|
||||
end fn
|
||||
|
||||
fn SaveConfiguration
|
||||
fn ReadConfiguration
|
||||
|
||||
HandleEvents
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
Public Sub Form_Open()
|
||||
Dim fullname As String = Settings["fullname", "Foo Barber"] 'If fullname is empty then use the default "Foo Barber"
|
||||
Dim favouritefruit As String = Settings["favouritefruit", "banana"]
|
||||
Dim needspeeling As String = Settings["needspeling", True]
|
||||
Dim seedsremoved As String = Settings["seedsremoved", False]
|
||||
Dim otherfamily As String[] = Settings["otherfamily", ["Rhu Barber", "Harry Barber"]]
|
||||
|
||||
Print fullname
|
||||
|
||||
'To save
|
||||
Settings["fullname"] = "John Smith"
|
||||
fullname = Settings["fullname"]
|
||||
|
||||
Print fullname
|
||||
|
||||
End
|
||||
160
Task/Read-a-configuration-file/Go/read-a-configuration-file-1.go
Normal file
160
Task/Read-a-configuration-file/Go/read-a-configuration-file-1.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"fmt"
|
||||
"bytes"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var (
|
||||
ENONE = errors.New("Requested value does not exist")
|
||||
EBADTYPE = errors.New("Requested type and actual type do not match")
|
||||
EBADVAL = errors.New("Value and type do not match")
|
||||
)
|
||||
|
||||
type varError struct {
|
||||
err error
|
||||
n string
|
||||
t VarType
|
||||
}
|
||||
|
||||
func (err *varError) Error() string {
|
||||
return fmt.Sprintf("%v: (%q, %v)", err.err, err.n, err.t)
|
||||
}
|
||||
|
||||
type VarType int
|
||||
|
||||
const (
|
||||
Bool VarType = 1 + iota
|
||||
Array
|
||||
String
|
||||
)
|
||||
|
||||
func (t VarType) String() string {
|
||||
switch t {
|
||||
case Bool:
|
||||
return "Bool"
|
||||
case Array:
|
||||
return "Array"
|
||||
case String:
|
||||
return "String"
|
||||
}
|
||||
|
||||
panic("Unknown VarType")
|
||||
}
|
||||
|
||||
type confvar struct {
|
||||
Type VarType
|
||||
Val interface{}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
m map[string]confvar
|
||||
}
|
||||
|
||||
func Parse(r io.Reader) (c *Config, err error) {
|
||||
c = new(Config)
|
||||
c.m = make(map[string]confvar)
|
||||
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
lines := bytes.Split(buf, []byte{'\n'})
|
||||
|
||||
for _, line := range lines {
|
||||
line = bytes.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
switch line[0] {
|
||||
case '#', ';':
|
||||
continue
|
||||
}
|
||||
|
||||
parts := bytes.SplitN(line, []byte{' '}, 2)
|
||||
nam := string(bytes.ToLower(parts[0]))
|
||||
|
||||
if len(parts) == 1 {
|
||||
c.m[nam] = confvar{Bool, true}
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(string(parts[1]), ",") {
|
||||
tmpB := bytes.Split(parts[1], []byte{','})
|
||||
for i := range tmpB {
|
||||
tmpB[i] = bytes.TrimSpace(tmpB[i])
|
||||
}
|
||||
tmpS := make([]string, 0, len(tmpB))
|
||||
for i := range tmpB {
|
||||
tmpS = append(tmpS, string(tmpB[i]))
|
||||
}
|
||||
|
||||
c.m[nam] = confvar{Array, tmpS}
|
||||
continue
|
||||
}
|
||||
|
||||
c.m[nam] = confvar{String, string(bytes.TrimSpace(parts[1]))}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Config) Bool(name string) (bool, error) {
|
||||
name = strings.ToLower(name)
|
||||
|
||||
if _, ok := c.m[name]; !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if c.m[name].Type != Bool {
|
||||
return false, &varError{EBADTYPE, name, Bool}
|
||||
}
|
||||
|
||||
v, ok := c.m[name].Val.(bool)
|
||||
if !ok {
|
||||
return false, &varError{EBADVAL, name, Bool}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (c *Config) Array(name string) ([]string, error) {
|
||||
name = strings.ToLower(name)
|
||||
|
||||
if _, ok := c.m[name]; !ok {
|
||||
return nil, &varError{ENONE, name, Array}
|
||||
}
|
||||
|
||||
if c.m[name].Type != Array {
|
||||
return nil, &varError{EBADTYPE, name, Array}
|
||||
}
|
||||
|
||||
v, ok := c.m[name].Val.([]string)
|
||||
if !ok {
|
||||
return nil, &varError{EBADVAL, name, Array}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (c *Config) String(name string) (string, error) {
|
||||
name = strings.ToLower(name)
|
||||
|
||||
if _, ok := c.m[name]; !ok {
|
||||
return "", &varError{ENONE, name, String}
|
||||
}
|
||||
|
||||
if c.m[name].Type != String {
|
||||
return "", &varError{EBADTYPE, name, String}
|
||||
}
|
||||
|
||||
v, ok := c.m[name].Val.(string)
|
||||
if !ok {
|
||||
return "", &varError{EBADVAL, name, String}
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Printf("Usage: %v <configfile>\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
conf, err := config.Parse(file)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fullname, err := conf.String("fullname")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
favouritefruit, err := conf.String("favouritefruit")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
needspeeling, err := conf.Bool("needspeeling")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
seedsremoved, err := conf.Bool("seedsremoved")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
otherfamily, err := conf.Array("otherfamily")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("FULLNAME: %q\n", fullname)
|
||||
fmt.Printf("FAVOURITEFRUIT: %q\n", favouritefruit)
|
||||
fmt.Printf("NEEDSPEELING: %q\n", needspeeling)
|
||||
fmt.Printf("SEEDSREMOVED: %q\n", seedsremoved)
|
||||
fmt.Printf("OTHERFAMILY: %q\n", otherfamily)
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
def config = [:]
|
||||
def loadConfig = { File file ->
|
||||
String regex = /^(;{0,1})\s*(\S+)\s*(.*)$/
|
||||
file.eachLine { line ->
|
||||
(line =~ regex).each { matcher, invert, key, value ->
|
||||
if (key == '' || key.startsWith("#")) return
|
||||
parts = value ? value.split(/\s*,\s*/) : (invert ? [false] : [true])
|
||||
if (parts.size() > 1) {
|
||||
parts.eachWithIndex{ part, int i -> config["$key(${i + 1})"] = part}
|
||||
} else {
|
||||
config[key] = parts[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
loadConfig new File('config.ini')
|
||||
config.each { println it }
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import Data.Char
|
||||
import Data.List
|
||||
import Data.List.Split
|
||||
|
||||
main :: IO ()
|
||||
main = readFile "config" >>= (print . parseConfig)
|
||||
|
||||
parseConfig :: String -> Config
|
||||
parseConfig = foldr addConfigValue defaultConfig . clean . lines
|
||||
where clean = filter (not . flip any ["#", ";", "", " "] . (==) . take 1)
|
||||
|
||||
addConfigValue :: String -> Config -> Config
|
||||
addConfigValue raw config = case key of
|
||||
"fullname" -> config {fullName = values}
|
||||
"favouritefruit" -> config {favoriteFruit = values}
|
||||
"needspeeling" -> config {needsPeeling = True}
|
||||
"seedsremoved" -> config {seedsRemoved = True}
|
||||
"otherfamily" -> config {otherFamily = splitOn "," values}
|
||||
_ -> config
|
||||
where (k, vs) = span (/= ' ') raw
|
||||
key = map toLower k
|
||||
values = tail vs
|
||||
|
||||
data Config = Config
|
||||
{ fullName :: String
|
||||
, favoriteFruit :: String
|
||||
, needsPeeling :: Bool
|
||||
, seedsRemoved :: Bool
|
||||
, otherFamily :: [String]
|
||||
} deriving (Show)
|
||||
|
||||
defaultConfig :: Config
|
||||
defaultConfig = Config "" "" False False []
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import Data.ConfigFile
|
||||
import Data.Either.Utils
|
||||
|
||||
getSetting cp x = forceEither $ get cp "Default" x
|
||||
|
||||
cp <- return . forceEither =<< readfile emptyCP "name_of_configuration_file"
|
||||
let username = getSetting cp "username"
|
||||
password = getSetting cp "password"
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
procedure main(A)
|
||||
ws := ' \t'
|
||||
vars := table()
|
||||
every line := !&input do {
|
||||
line ? {
|
||||
tab(many(ws))
|
||||
if any('#;') | pos(0) then next
|
||||
vars[map(tab(upto(ws)\1|0))] := getValue()
|
||||
}
|
||||
}
|
||||
show(vars)
|
||||
end
|
||||
|
||||
procedure getValue()
|
||||
ws := ' \t'
|
||||
a := []
|
||||
while not pos(0) do {
|
||||
tab(many(ws))
|
||||
put(a, trim(tab(upto(',')|0)))
|
||||
move(1)
|
||||
}
|
||||
return a
|
||||
end
|
||||
|
||||
procedure show(t)
|
||||
every pair := !sort(t) do {
|
||||
every (s := pair[1]||" = ") ||:= !pair[2] || ", "
|
||||
write(s[1:-2])
|
||||
}
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
require'regex'
|
||||
set=:4 :'(x)=:y'
|
||||
|
||||
cfgString=:4 :0
|
||||
y set ''
|
||||
(1;&,~'(?i:',y,')\s*(.*)') y&set rxapply x
|
||||
)
|
||||
|
||||
cfgBoolean=:4 :0
|
||||
y set 0
|
||||
(1;&,~'(?i:',y,')\s*(.*)') y&set rxapply x
|
||||
if.-.0-:y do.y set 1 end.
|
||||
)
|
||||
|
||||
taskCfg=:3 :0
|
||||
cfg=: ('[#;].*';'') rxrplc 1!:1<y
|
||||
cfg cfgString 'fullname'
|
||||
cfg cfgString 'favouritefruit'
|
||||
cfg cfgBoolean 'needspeeling'
|
||||
cfg cfgBoolean 'seedsremoved'
|
||||
i.0 0
|
||||
)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
taskCfg 'fruit.conf'
|
||||
(,' = ',]&.do)&>;: 'fullname favouritefruit needspeeling seedsremoved'
|
||||
fullname = Foo Barber
|
||||
favouritefruit = banana
|
||||
needspeeling = 1
|
||||
seedsremoved = 0
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ConfigReader {
|
||||
private static final Pattern LINE_PATTERN = Pattern.compile( "([^ =]+)[ =]?(.*)" );
|
||||
private static final Map<String, Object> DEFAULTS = new HashMap<String, Object>() {{
|
||||
put( "needspeeling", false );
|
||||
put( "seedsremoved", false );
|
||||
}};
|
||||
|
||||
public static void main( final String[] args ) {
|
||||
System.out.println( parseFile( args[ 0 ] ) );
|
||||
}
|
||||
|
||||
public static Map<String, Object> parseFile( final String fileName ) {
|
||||
final Map<String, Object> result = new HashMap<String, Object>( DEFAULTS );
|
||||
/*v*/ BufferedReader reader = null;
|
||||
|
||||
try {
|
||||
reader = new BufferedReader( new FileReader( fileName ) );
|
||||
for ( String line; null != ( line = reader.readLine() ); ) {
|
||||
parseLine( line, result );
|
||||
}
|
||||
} catch ( final IOException x ) {
|
||||
throw new RuntimeException( "Oops: " + x, x );
|
||||
} finally {
|
||||
if ( null != reader ) try {
|
||||
reader.close();
|
||||
} catch ( final IOException x2 ) {
|
||||
System.err.println( "Could not close " + fileName + " - " + x2 );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void parseLine( final String line, final Map<String, Object> map ) {
|
||||
if ( "".equals( line.trim() ) || line.startsWith( "#" ) || line.startsWith( ";" ) )
|
||||
return;
|
||||
|
||||
final Matcher matcher = LINE_PATTERN.matcher( line );
|
||||
|
||||
if ( ! matcher.matches() ) {
|
||||
System.err.println( "Bad config line: " + line );
|
||||
return;
|
||||
}
|
||||
|
||||
final String key = matcher.group( 1 ).trim().toLowerCase();
|
||||
final String value = matcher.group( 2 ).trim();
|
||||
|
||||
if ( "".equals( value ) ) {
|
||||
map.put( key, true );
|
||||
} else if ( -1 == value.indexOf( ',' ) ) {
|
||||
map.put( key, value );
|
||||
} else {
|
||||
final String[] values = value.split( "," );
|
||||
|
||||
for ( int i = 0; i < values.length; i++ ) {
|
||||
values[ i ] = values[ i ].trim();
|
||||
}
|
||||
map.put( key, Arrays.asList( values ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ConfigReader {
|
||||
private static final Pattern LINE_PATTERN = Pattern.compile("([^ =]+)[ =]?(.*)");
|
||||
|
||||
public static void main(final String[] args) throws IOException {
|
||||
System.out.println(parseFile(args[0]));
|
||||
}
|
||||
|
||||
public static Map<String, Object> parseFile(final String fileName) throws IOException {
|
||||
final Map<String, Object> result = new HashMap<>();
|
||||
result.put("needspeeling", false);
|
||||
result.put("seedsremoved", false);
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
|
||||
result.putAll(reader.lines()
|
||||
.filter(line -> !"".equals(line.trim()) && !line.startsWith("#") && !line.startsWith(";"))
|
||||
.map(LINE_PATTERN::matcher)
|
||||
.filter(Matcher::matches)
|
||||
.collect(Collectors.toMap(matcher -> matcher.group(1).trim().toLowerCase(), matcher -> {
|
||||
final String value = matcher.group(2).trim();
|
||||
if ("".equals(value)) {
|
||||
return true;
|
||||
} else if (-1 == value.indexOf(',')) {
|
||||
return value;
|
||||
}
|
||||
return Arrays.asList(value.split(",")).stream().map(String::trim).collect(Collectors.toList());
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
function parseConfig(config) {
|
||||
// this expression matches a line starting with an all capital word,
|
||||
// and anything after it
|
||||
var regex = /^([A-Z]+)(.*)$/mg;
|
||||
var configObject = {};
|
||||
|
||||
// loop until regex.exec returns null
|
||||
var match;
|
||||
while (match = regex.exec(config)) {
|
||||
// values will typically be an array with one element
|
||||
// unless we want an array
|
||||
// match[0] is the whole match, match[1] is the first group (all caps word),
|
||||
// and match[2] is the second (everything through the end of line)
|
||||
var key = match[1], values = match[2].split(",");
|
||||
if (values.length === 1) {
|
||||
configObject[key] = values[0];
|
||||
}
|
||||
else {
|
||||
configObject[key] = values.map(function(value){
|
||||
return value.trim();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return configObject;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"FULLNAME": " Foo Barber",
|
||||
"FAVOURITEFRUIT": " banana",
|
||||
"NEEDSPEELING": "",
|
||||
"OTHERFAMILY": [
|
||||
"Rhu Barber",
|
||||
"Harry Barber"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
def parse:
|
||||
|
||||
def uc: .name | ascii_upcase;
|
||||
|
||||
def parse_boolean:
|
||||
capture( "(?<name>^[^ ] *$)" )
|
||||
| { (uc) : true };
|
||||
|
||||
def parse_var_value:
|
||||
capture( "(?<name>^[^ ]+)[ =] *(?<value>[^,]+ *$)" )
|
||||
| { (uc) : .value };
|
||||
|
||||
def parse_var_array:
|
||||
capture( "(?<name>^[^ ]+)[ =] *(?<value>.*)" )
|
||||
| { (uc) : (.value | sub(" +$";"") | [splits(", *")]) };
|
||||
|
||||
reduce inputs as $i ({};
|
||||
if $i|length == 0 or test("^[#;]") then .
|
||||
else . + ($i | ( parse_boolean // parse_var_value // parse_var_array // {} ))
|
||||
end);
|
||||
|
||||
parse
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
function readconf(file)
|
||||
vars = Dict()
|
||||
for line in eachline(file)
|
||||
line = strip(line)
|
||||
if !isempty(line) && !startswith(line, '#') && !startswith(line, ';')
|
||||
fspace = searchindex(line, " ")
|
||||
if fspace == 0
|
||||
vars[Symbol(lowercase(line))] = true
|
||||
else
|
||||
vname, line = Symbol(lowercase(line[1:fspace-1])), line[fspace+1:end]
|
||||
value = ',' ∈ line ? strip.(split(line, ',')) : line
|
||||
vars[vname] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
for (vname, value) in vars
|
||||
eval(:($vname = $value))
|
||||
end
|
||||
return vars
|
||||
end
|
||||
|
||||
readconf("test.conf")
|
||||
|
||||
@show fullname favouritefruit needspeeling otherfamily
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
data class Configuration(val map: Map<String, Any?>) {
|
||||
val fullName: String by map
|
||||
val favoriteFruit: String by map
|
||||
val needsPeeling: Boolean by map
|
||||
val otherFamily: List<String> by map
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val lines = Files.readAllLines(Paths.get("src/configuration.txt"), StandardCharsets.UTF_8)
|
||||
val keyValuePairs = lines.map{ it.trim() }
|
||||
.filterNot { it.isEmpty() }
|
||||
.filterNot(::commentedOut)
|
||||
.map(::toKeyValuePair)
|
||||
|
||||
val configurationMap = hashMapOf<String, Any>("needsPeeling" to false)
|
||||
for (pair in keyValuePairs) {
|
||||
val (key, value) = pair
|
||||
when (key) {
|
||||
"FULLNAME" -> configurationMap.put("fullName", value)
|
||||
"FAVOURITEFRUIT" -> configurationMap.put("favoriteFruit", value)
|
||||
"NEEDSPEELING" -> configurationMap.put("needsPeeling", true)
|
||||
"OTHERFAMILY" -> configurationMap.put("otherFamily", value.split(" , ").map { it.trim() })
|
||||
else -> println("Encountered unexpected key $key=$value")
|
||||
}
|
||||
}
|
||||
println(Configuration(configurationMap))
|
||||
}
|
||||
|
||||
private fun commentedOut(line: String) = line.startsWith("#") || line.startsWith(";")
|
||||
|
||||
private fun toKeyValuePair(line: String) = line.split(Regex(" "), 2).let {
|
||||
Pair(it[0], if (it.size == 1) "" else it[1])
|
||||
}
|
||||
133
Task/Read-a-configuration-file/Ksh/read-a-configuration-file.ksh
Normal file
133
Task/Read-a-configuration-file/Ksh/read-a-configuration-file.ksh
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
#!/bin/ksh
|
||||
|
||||
# Read a configuration file
|
||||
|
||||
# # Variables:
|
||||
#
|
||||
|
||||
# # The configuration file (below) could be read in from a file
|
||||
# But this method keeps everything together.
|
||||
# e.g. config=$(< /path/to/config_file)
|
||||
|
||||
integer config_num=0
|
||||
config='# This is a configuration file in standard configuration file format
|
||||
#
|
||||
# Lines beginning with a hash or a semicolon are ignored by the application
|
||||
# program. Blank lines are also ignored by the application program.
|
||||
|
||||
# This is the fullname parameter
|
||||
FULLNAME Foo Barber
|
||||
|
||||
# This is a favourite fruit
|
||||
FAVOURITEFRUIT banana
|
||||
|
||||
# This is a boolean that should be set
|
||||
NEEDSPEELING
|
||||
|
||||
# This boolean is commented out
|
||||
; SEEDSREMOVED
|
||||
|
||||
# Configuration option names are not case sensitive, but configuration parameter
|
||||
# data is case sensitive and may be preserved by the application program.
|
||||
|
||||
# An optional equals sign can be used to separate configuration parameter data
|
||||
# from the option name. This is dropped by the parser.
|
||||
|
||||
# A configuration option may take multiple parameters separated by commas.
|
||||
# Leading and trailing whitespace around parameter names and parameter data fields
|
||||
# are ignored by the application program.
|
||||
|
||||
OTHERFAMILY Rhu Barber, Harry Barber'
|
||||
|
||||
isComment='#|;'
|
||||
paraDelim=' |='
|
||||
boolean="SEEDSREMOVED|NEEDSPEELING"
|
||||
|
||||
typeset -T Config_t=(
|
||||
typeset -h 'Full name' fullname
|
||||
typeset -h 'Favorite fruit' favouritefruit
|
||||
typeset -h 'Boolean NEEDSPEELING' needspeeling=false
|
||||
typeset -h 'Boolean SEEDSREMOVED' seedsremoved=false
|
||||
typeset -a -h 'Other family' otherfamily
|
||||
|
||||
function set_name {
|
||||
typeset fn ; fn=$(echo $1) # Strip any leading/trailing white space
|
||||
_.fullname="${fn}"
|
||||
}
|
||||
|
||||
function set_fruit {
|
||||
typeset fruit ; fruit=$(echo $1)
|
||||
_.favouritefruit="${fruit}"
|
||||
}
|
||||
|
||||
function set_bool {
|
||||
typeset bool ; typeset -u bool=$1
|
||||
|
||||
case ${bool} in
|
||||
NEEDSPEELING) _.needspeeling=true ;;
|
||||
SEEDSREMOVED) _.seedsremoved=true ;;
|
||||
esac
|
||||
}
|
||||
|
||||
function set_family {
|
||||
typeset ofam ; ofam=$(echo $1)
|
||||
typeset farr i ; typeset -a farr ; integer i
|
||||
|
||||
oldIFS="$IFS" ; IFS=',' ; farr=( ${ofam} ) ; IFS="${oldIFS}"
|
||||
for ((i=0; i<${#farr[*]}; i++)); do
|
||||
_.otherfamily[i]=$(echo ${farr[i]})
|
||||
done
|
||||
}
|
||||
)
|
||||
|
||||
# # Functions:
|
||||
#
|
||||
|
||||
# # Function _parseconf(config) - Parse uncommented lines
|
||||
#
|
||||
function _parseconf {
|
||||
typeset _cfg ; _cfg="$1"
|
||||
typeset _conf ; nameref _conf="$2"
|
||||
|
||||
echo "${_cfg}" | \
|
||||
while read; do
|
||||
[[ $REPLY == @(${isComment})* ]] || [[ $REPLY == '' ]] && continue
|
||||
_parseline "$REPLY" _conf
|
||||
done
|
||||
}
|
||||
|
||||
function _parseline {
|
||||
typeset _line ; _line=$(echo $1)
|
||||
typeset _conf ; nameref _conf="$2"
|
||||
typeset _param _value ; typeset -u _param
|
||||
|
||||
_param=${_line%%+(${paraDelim})*}
|
||||
_value=${_line#*+(${paraDelim})}
|
||||
|
||||
if [[ ${_param} == @(${boolean}) ]]; then
|
||||
_conf.set_bool ${_param}
|
||||
else
|
||||
case ${_param} in
|
||||
FULLNAME) _conf.set_name "${_value}" ;;
|
||||
FAVOURITEFRUIT) _conf.set_fruit ${_value} ;;
|
||||
OTHERFAMILY) _conf.set_family "${_value}" ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
######
|
||||
# main #
|
||||
######
|
||||
|
||||
typeset -a configuration # Indexed array of configurations
|
||||
Config_t configuration[config_num]
|
||||
_parseconf "${config}" configuration[config_num]
|
||||
|
||||
for cnum in ${!configuration[*]}; do
|
||||
printf "fullname = %s\n" "${configuration[cnum].fullname}"
|
||||
printf "favouritefruit = %s\n" ${configuration[cnum].favouritefruit}
|
||||
printf "needspeeling = %s\n" ${configuration[cnum].needspeeling}
|
||||
printf "seedsremoved = %s\n" ${configuration[cnum].seedsremoved}
|
||||
for ((i=0; i<${#configuration[cnum].otherfamily[*]}; i++)); do
|
||||
print "otherfamily($((i+1))) = ${configuration[cnum].otherfamily[i]}"
|
||||
done
|
||||
done
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
local(config = '# This is a configuration file in standard configuration file format
|
||||
#
|
||||
# Lines beginning with a hash or a semicolon are ignored by the application
|
||||
# program. Blank lines are also ignored by the application program.
|
||||
|
||||
# This is the fullname parameter
|
||||
|
||||
FULLNAME Foo Barber
|
||||
|
||||
# This is a favourite fruit
|
||||
FAVOURITEFRUIT = banana
|
||||
|
||||
# This is a boolean that should be set
|
||||
NEEDSPEELING
|
||||
|
||||
# This boolean is commented out
|
||||
; SEEDSREMOVED
|
||||
|
||||
# Configuration option names are not case sensitive, but configuration parameter
|
||||
# data is case sensitive and may be preserved by the application program.
|
||||
|
||||
# An optional equals sign can be used to separate configuration parameter data
|
||||
# from the option name. This is dropped by the parser.
|
||||
|
||||
# A configuration option may take multiple parameters separated by commas.
|
||||
# Leading and trailing whitespace around parameter names and parameter data fields
|
||||
# are ignored by the application program.
|
||||
|
||||
OTHERFAMILY Rhu Barber, Harry Barber
|
||||
')
|
||||
// if config is in a file collect it like this
|
||||
//local(config = file('path/and/file.name') -> readstring)
|
||||
|
||||
define getconfig(term::string, config::string) => {
|
||||
|
||||
local(
|
||||
regexp = regexp(-find = `(?m)^` + #term + `($|\s*=\s*|\s+)(.*)$`, -input = #config, -ignorecase),
|
||||
result
|
||||
)
|
||||
|
||||
while(#regexp -> find) => {
|
||||
#result = (#regexp -> groupcount > 1 ? (#regexp -> matchString(2) -> trim& || true))
|
||||
if(#result -> asstring >> ',') => {
|
||||
#result = #result -> split(',')
|
||||
#result -> foreach => {#1 -> trim}
|
||||
}
|
||||
return #result
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
local(
|
||||
fullname = getconfig('FULLNAME', #config),
|
||||
favorite = getconfig('FAVOURITEFRUIT', #config),
|
||||
sedsremoved = getconfig('SEEDSREMOVED', #config),
|
||||
needspeel = getconfig('NEEDSPEELING', #config),
|
||||
otherfamily = getconfig('OTHERFAMILY', #config)
|
||||
)
|
||||
|
||||
#fullname
|
||||
'<br />'
|
||||
#favorite
|
||||
'<br />'
|
||||
#sedsremoved
|
||||
'<br />'
|
||||
#needspeel
|
||||
'<br />'
|
||||
#otherfamily
|
||||
'<br />'
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
dim confKeys$(100)
|
||||
dim confValues$(100)
|
||||
|
||||
optionCount = ParseConfiguration("a.txt")
|
||||
|
||||
fullName$ = GetOption$( "FULLNAME", optionCount)
|
||||
favouriteFruit$ = GetOption$( "FAVOURITEFRUIT", optionCount)
|
||||
needsPeeling = HasOption("NEEDSPEELING", optionCount)
|
||||
seedsRemoved = HasOption("SEEDSREMOVED", optionCount)
|
||||
otherFamily$ = GetOption$( "OTHERFAMILY", optionCount) 'it's easier to keep the comma-separated list as a string
|
||||
|
||||
print "Full name: "; fullName$
|
||||
print "likes: "; favouriteFruit$
|
||||
print "needs peeling: "; needsPeeling
|
||||
print "seeds removed: "; seedsRemoved
|
||||
|
||||
print "other family:"
|
||||
otherFamily$ = GetOption$( "OTHERFAMILY", optionCount)
|
||||
counter = 1
|
||||
while word$(otherFamily$, counter, ",") <> ""
|
||||
print counter; ". "; trim$(word$(otherFamily$, counter, ","))
|
||||
counter = counter + 1
|
||||
wend
|
||||
end
|
||||
|
||||
'parses the configuration file, stores the uppercase keys in array confKeys$ and corresponding values in confValues$
|
||||
'returns the number of key-value pairs found
|
||||
function ParseConfiguration(fileName$)
|
||||
count = 0
|
||||
open fileName$ for input as #f
|
||||
while not(eof(#f))
|
||||
line input #f, s$
|
||||
if not(Left$(s$,1) = "#" or Left$( s$,1) = ";" or trim$(s$) = "") then 'ignore empty and comment lines
|
||||
s$ = trim$(s$)
|
||||
key$ = ParseKey$(s$)
|
||||
value$ = trim$(Mid$(s$,len(key$) + 1))
|
||||
if Left$( value$,1) = "=" then value$ = trim$(Mid$(value$,2)) 'optional =
|
||||
count = count + 1
|
||||
confKeys$(count) = upper$(key$)
|
||||
confValues$(count) = value$
|
||||
end if
|
||||
wend
|
||||
close #f
|
||||
ParseConfiguration = count
|
||||
end function
|
||||
|
||||
function ParseKey$(s$)
|
||||
'key is the first word in s$, delimited by whitespace or =
|
||||
s$ = word$(s$, 1)
|
||||
ParseKey$ = trim$(word$(s$, 1, "="))
|
||||
end function
|
||||
|
||||
|
||||
function GetOption$( key$, optionCount)
|
||||
index = Find.confKeys( 1, optionCount, key$)
|
||||
if index > 0 then GetOption$ =(confValues$(index))
|
||||
end function
|
||||
|
||||
|
||||
function HasOption(key$, optionCount)
|
||||
HasOption = Find.confKeys( 1, optionCount, key$) > 0
|
||||
end function
|
||||
|
||||
function Find.confKeys( Start, Finish, value$)
|
||||
Find.confKeys = -1
|
||||
for i = Start to Finish
|
||||
if confKeys$(i) = value$ then Find.confKeys = i : exit for
|
||||
next i
|
||||
end function
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
conf = {}
|
||||
|
||||
fp = io.open( "conf.txt", "r" )
|
||||
|
||||
for line in fp:lines() do
|
||||
line = line:match( "%s*(.+)" )
|
||||
if line and line:sub( 1, 1 ) ~= "#" and line:sub( 1, 1 ) ~= ";" then
|
||||
option = line:match( "%S+" ):lower()
|
||||
value = line:match( "%S*%s*(.*)" )
|
||||
|
||||
if not value then
|
||||
conf[option] = true
|
||||
else
|
||||
if not value:find( "," ) then
|
||||
conf[option] = value
|
||||
else
|
||||
value = value .. ","
|
||||
conf[option] = {}
|
||||
for entry in value:gmatch( "%s*(.-)," ) do
|
||||
conf[option][#conf[option]+1] = entry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
fp:close()
|
||||
|
||||
|
||||
print( "fullname = ", conf["fullname"] )
|
||||
print( "favouritefruit = ", conf["favouritefruit"] )
|
||||
if conf["needspeeling"] then print( "needspeeling = true" ) else print( "needspeeling = false" ) end
|
||||
if conf["seedsremoved"] then print( "seedsremoved = true" ) else print( "seedsremoved = false" ) end
|
||||
if conf["otherfamily"] then
|
||||
print "otherfamily:"
|
||||
for _, entry in pairs( conf["otherfamily"] ) do
|
||||
print( "", entry )
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Declare zip compressor
|
||||
a$=str$(a$)
|
||||
Method zip, "AddFromMemory",a$, "configuration.txt" as ok
|
||||
Method zip,"CreateZipBuffer" as buf1
|
||||
clipboard String$(eval$(buf1) as Encode64)
|
||||
|
||||
//where a$ defined (before)
|
||||
a$={text here from first line
|
||||
until last line
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
module check(a$, id as list){
|
||||
Document Export$
|
||||
nl$={
|
||||
}
|
||||
dim L$() : L$()=piece$(a$,nl$)
|
||||
if len(L$())=0 then exit
|
||||
for i=0 to len(L$())-1
|
||||
a$=trim$(L$(i))
|
||||
b$=left$(a$, 1)
|
||||
select case b$
|
||||
case ";"
|
||||
examineValue(true)
|
||||
case >"#"
|
||||
examineValue(false)
|
||||
end select
|
||||
next
|
||||
Report Export$ // result or Clipboard Export$
|
||||
Sub examineValue(NotUsed as boolean)
|
||||
local i
|
||||
if NotUsed then
|
||||
a$=trim$(mid$(a$,2))+" "
|
||||
b$=leftpart$(a$," ")
|
||||
else
|
||||
a$+=" "
|
||||
b$=leftpart$(a$," ")
|
||||
end if
|
||||
a$=trim$(rightpart$(a$," "))
|
||||
// optional = removed
|
||||
if left$(a$,1)="=" then a$=trim$(mid$(a$,2))
|
||||
// if not exist ignore it
|
||||
if exist(id,ucase$(b$)) then
|
||||
if len(a$)=0 then // we have a boolean
|
||||
Export$=b$+" = "+if$(NotUsed->"false", "true")+nl$
|
||||
else.if instr(a$,",")>0 then // multiple value
|
||||
local a$()
|
||||
a$()=piece$(a$,",")
|
||||
for i=0 to len(a$())-1
|
||||
Export$=format$("{0}({1}) = {2}",b$,i+1, trim$(a$(i)))+nl$
|
||||
next
|
||||
else
|
||||
Export$=b$+" = "+a$+nl$
|
||||
end if
|
||||
end if
|
||||
End Sub
|
||||
}
|
||||
valid=list:="FULLNAME", "FAVOURITEFRUIT", "NEEDSPEELING", "SEEDSREMOVED", "OTHERFAMILY"
|
||||
binary{
|
||||
UEsDBBQAAAgIAO8FflU2rdfqSAIAANQDAAARAAAAY29uZmlndXJhdGlvbi50eHRT
|
||||
VgjJyCxWyCxWSFRIzs9Ly0wvLUosyczPU0jLzElVyMxTKC5JzEtJLErBJp2WX5Sb
|
||||
WMLLpczLpazgk5mXWqyQlJqemZeXmZeuUJ5ZkqGQqJCRWJyhkF+kkKhQnJqbmZyf
|
||||
k5+nkFiUqpCZnpdflJqikFSpUJKRqpBYUJCTmQw2G2RYQVF+elFirp6CU05iXrZC
|
||||
DthskLbEnOJ8PHrhGnm5QMbAPAdSlVaak5OXmJuqUJBYlJibWpJaxMvlFurj4+fo
|
||||
66rglp+v4JRYlAQSRNaYqJCWWJZfWpRZkqqQVlSaWcLL5eYY5h8a5Bni6hYU6hmi
|
||||
kJSYl5iXiK4rKT8/JzUxT6EkI7FEoTgjvzQnRSEpVaE4tYSXy8/V1SU4wNXVx9PP
|
||||
HUkfTEtmsUJyfm5ual5JaopCfmkJL5e1QjBIS5Crr3+YqwtEizNKbOQXgCmQ9yDB
|
||||
lJdfopCcWAyyMa84sySzLFVHIam0BC0SkUJCWSElsSQRbDmKNoXEvBSF3MRKkOsL
|
||||
ilKLU4vKiAl4R5ibEnMUUgtLE3OKFYoz0/MUkhPzQCaVFqemKJTkKxSngpxQkorL
|
||||
XWBHgcxLK8rPBVuJ5FM9eHinFOUXFCCcVZBYVJxapKcAdQqa4VATQH4qScxOVcgt
|
||||
zSnJLMhBShfFcHeBjQTFRmKxHjiNpyamgNI2KFBKihIzc8AJPSOzJLW4IDE5VSGx
|
||||
KL80LwXJ/dAYQREDB3RaZmpOSjHITPyZASVc/UM8XIPcHH09fSIVgjJKoSlWR8Ej
|
||||
saioEp5+AVBLAQItABQAAAgIAO8FflU2rdfqSAIAANQDAAARAAAAAAAAAAAAIAAA
|
||||
AAAAAABjb25maWd1cmF0aW9uLnR4dFBLBQYAAAAAAQABAD8AAAB3AgAAAAA=} as zip1
|
||||
Declare zip compressor
|
||||
method zip,"OpenZipBuf", zip1
|
||||
method zip, "ExtractOneToBuffer", "configuration.txt" as buf
|
||||
If true then
|
||||
// save buf to file, the load to document as ANSI 1033
|
||||
open "configuration.txt" for output as #f
|
||||
put #f,buf, 1
|
||||
close #f
|
||||
document b$ : Load.doc b$, "configuration.txt", 1033
|
||||
check b$, valid
|
||||
else
|
||||
check chr$(eval$(buf)), valid
|
||||
end if
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
function R = readconf(configfile)
|
||||
% READCONF reads configuration file.
|
||||
%
|
||||
% The value of boolean parameters can be tested with
|
||||
% exist(parameter,'var')
|
||||
|
||||
if nargin<1,
|
||||
configfile = 'q.conf';
|
||||
end;
|
||||
|
||||
fid = fopen(configfile);
|
||||
if fid<0, error('cannot open file %s\n',a); end;
|
||||
|
||||
while ~feof(fid)
|
||||
line = strtrim(fgetl(fid));
|
||||
if isempty(line) || all(isspace(line)) || strncmp(line,'#',1) || strncmp(line,';',1),
|
||||
; % no operation
|
||||
else
|
||||
[var,tok] = strtok(line,' \t=');
|
||||
var = upper(var);
|
||||
if any(tok==','),
|
||||
k = 1;
|
||||
while (1)
|
||||
[val, tok]=strtok(tok,',');
|
||||
R.(var){k} = strtrim(val); % return value of function
|
||||
eval(sprintf('%s{%i}=''%s'';',var,k,strtrim(val))); % stores variable in local workspace
|
||||
if isempty(tok), break; end;
|
||||
k=k+1;
|
||||
end;
|
||||
else
|
||||
tok = strtrim(tok);
|
||||
R.(var) = tok; % return value of function
|
||||
eval(sprintf('%s=''%s''; ',var,tok)); % stores variable in local workspace
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
fclose(fid);
|
||||
whos, % shows the parameter in the local workspace
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
ClearAll[CreateVar, ImportConfig];
|
||||
CreateVar[x_, y_String: "True"] := Module[{},
|
||||
If[StringFreeQ[y, ","]
|
||||
,
|
||||
ToExpression[x <> "=" <> y]
|
||||
,
|
||||
ToExpression[x <> "={" <> StringJoin@Riffle[StringSplit[y, ","], ","] <> "}"]
|
||||
]
|
||||
]
|
||||
ImportConfig[configfile_String] := Module[{data},
|
||||
(*data = ImportString[configfile, "List", "Numeric" -> False];*)
|
||||
data=Import[configfile,"List","Numeric"\[Rule]False];
|
||||
|
||||
data = StringTrim /@ data;
|
||||
data = Select[data, # =!= "" &];
|
||||
data = Select[data, ! StringMatchQ[#, "#" | ";" ~~ ___] &];
|
||||
data = If[! StringFreeQ[#, " "], StringSplit[#, " ", 2], {#}] & /@ data;
|
||||
|
||||
CreateVar @@@ data;
|
||||
]
|
||||
ImportConfig[file]
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import Nanoquery.IO
|
||||
import dict
|
||||
|
||||
def get_config(fname)
|
||||
f = new(File).open(fname)
|
||||
lines = split(f.readAll(), "\n")
|
||||
|
||||
values = new(Dict)
|
||||
for line in lines
|
||||
line = trim(line)
|
||||
if len(line) > 0
|
||||
if not (line .startswith. "#") or (line .startswith. ";")
|
||||
tokens = split(line, " ")
|
||||
|
||||
if len(tokens) = 1
|
||||
values.add(upper(tokens[0]), true)
|
||||
else
|
||||
parameters = list()
|
||||
parameter = ""
|
||||
for i in range(1, len(tokens) - 1)
|
||||
parameter += tokens[i] + " "
|
||||
if parameter .endswith. ", "
|
||||
parameter = parameter.substring(0, len(parameter) - 2)
|
||||
parameters.append(trim(parameter))
|
||||
parameter = ""
|
||||
end
|
||||
end
|
||||
parameters.append(trim(parameter))
|
||||
if len(parameters) > 1
|
||||
values.add(upper(tokens[0]), parameters)
|
||||
else
|
||||
values.add(upper(tokens[0]), parameters[0])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return values
|
||||
end
|
||||
|
||||
println get_config(args[2])
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import re, strformat, strutils, tables
|
||||
|
||||
var configs: OrderedTable[string, seq[string]]
|
||||
var parsed: seq[string]
|
||||
|
||||
for line in "demo.config".lines():
|
||||
let line = line.strip()
|
||||
if line != "" and not line.startswith(re"#|;"):
|
||||
parsed = line.split(re"\s*=\s*|\s+", 1)
|
||||
configs[parsed[0].toLower()] = if len(parsed) > 1: parsed[1].split(re"\s*,\s*") else: @[]
|
||||
|
||||
for key in ["fullname", "favouritefruit", "needspeeling", "seedsremoved", "otherfamily"]:
|
||||
if not configs.hasKey(key):
|
||||
echo(&"{key} = false")
|
||||
else:
|
||||
case len(configs[key])
|
||||
of 0:
|
||||
echo(&"{key} = true")
|
||||
of 1:
|
||||
echo(&"{key} = {configs[key][0]}")
|
||||
else:
|
||||
for i, v in configs[key].pairs():
|
||||
echo(&"{key}({i+1}) = {v}")
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#use "topfind"
|
||||
#require "inifiles"
|
||||
open Inifiles
|
||||
|
||||
let print_field ini (label, field) =
|
||||
try
|
||||
let v = ini#getval "params" field in
|
||||
Printf.printf "%s: %s\n" label v
|
||||
with Invalid_element _ ->
|
||||
Printf.printf "%s: not defined\n" label
|
||||
|
||||
let () =
|
||||
let ini = new inifile "./conf.ini" in
|
||||
let lst = [
|
||||
"Full name", "FULLNAME";
|
||||
"likes", "FAVOURITEFRUIT";
|
||||
"needs peeling", "NEEDSPEELING";
|
||||
"seeds removed", "SEEDSREMOVED";
|
||||
] in
|
||||
List.iter (print_field ini) lst;
|
||||
|
||||
let v = ini#getaval "params" "OTHERFAMILY" in
|
||||
print_endline "other family:";
|
||||
List.iter (Printf.printf "- %s\n") v;
|
||||
;;
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
#!/usr/bin/rexx
|
||||
/*.----------------------------------------------------------------------.*/
|
||||
/*|readconfig: Read keyword value pairs from a configuration file into |*/
|
||||
/*| Rexx variables. |*/
|
||||
/*| |*/
|
||||
/*|Usage: |*/
|
||||
/*| .-~/rosetta.conf-. |*/
|
||||
/*|>>-readconfig-+----------------+------------------------------------><|*/
|
||||
/*| |-configfilename-| |*/
|
||||
/*| |-- -? ----------| |*/
|
||||
/*| |-- -h ----------| |*/
|
||||
/*| '- --help -------' |*/
|
||||
/*| |*/
|
||||
/*|where |*/
|
||||
/*| configfilename |*/
|
||||
/*| is the name of the configuration file to be processed. if not|*/
|
||||
/*| specified, ~/rosetta.conf is used. |*/
|
||||
/*| |*/
|
||||
/*|All values retrieved from the configuration file are stored in |*/
|
||||
/*|compound variables with the stem config. Variables with multiple |*/
|
||||
/*|values have a numeric index appended, and the highest index number |*/
|
||||
/*|is stored in the variable with index 0; e.g. if CONFIG.OTHERFAMILY.1 |*/
|
||||
/*|and CONFIG.OTHERFAMILY.2 have values assigned, CONFIG.OTHERFAMILY.0 = |*/
|
||||
/*|2. |*/
|
||||
/*|-?, -h or --help all cause this documentation to be displayed. |*/
|
||||
/*| |*/
|
||||
/*|This program was tested using Open Object Rexx 4.1.1. It should work |*/
|
||||
/*|with most other dialects as well. |*/
|
||||
/*'----------------------------------------------------------------------'*/
|
||||
call usage arg(1)
|
||||
trace normal
|
||||
signal on any name error
|
||||
|
||||
/* Prepare for processing the configuration file. */
|
||||
keywords = 'FULLNAME FAVOURITEFRUIT NEEDSPEELING SEEDSREMOVED OTHERFAMILY'
|
||||
|
||||
/* Set default values for configuration variables here */
|
||||
config_single?. = 1
|
||||
config. = ''
|
||||
config.NEEDSPEELING = 0
|
||||
config.SEEDSREMOVED = 1
|
||||
|
||||
/* Validate command line inputs. */
|
||||
parse arg configfilename
|
||||
|
||||
if length(configfilename) = 0 then
|
||||
configfilename = '~/rosetta.conf'
|
||||
|
||||
configfile = stream(configfilename,'COMMAND','QUERY EXISTS')
|
||||
|
||||
if length(configfile) = 0 then
|
||||
do
|
||||
say configfilename 'was not found.'
|
||||
exit 28
|
||||
end
|
||||
|
||||
signal on notready /* if an I/O error occurs. */
|
||||
|
||||
/* Open the configuration file. */
|
||||
response = stream(configfile,'COMMAND','OPEN READ SHARED')
|
||||
|
||||
/* Parse the contents of the configuration file into variables. */
|
||||
do while lines(configfile) > 0
|
||||
statement = linein(configfile)
|
||||
|
||||
select
|
||||
when left(statement,1) = '#',
|
||||
| left(statement,1) = ';',
|
||||
| length(strip(statement)) = 0,
|
||||
then /* a comment or a blank line. */
|
||||
nop /* skip it. */
|
||||
|
||||
otherwise
|
||||
do
|
||||
if pos('=',word(statement,1)) > 0,
|
||||
| left(word(statement,2),1) = '=',
|
||||
then /* a keyword/value pair with = between. */
|
||||
parse var statement keyword '=' value
|
||||
|
||||
else /* a keyword/value pair with no =. */
|
||||
parse var statement keyword value
|
||||
|
||||
keyword = translate(strip(keyword)) /* make it uppercase. */
|
||||
single? = pos(',',value) = 0 /* a single value, or multiple values? */
|
||||
call value 'CONFIG_single?.'keyword,single? /* remember. */
|
||||
|
||||
if single? then
|
||||
do
|
||||
if length(value) > 0 then
|
||||
call value 'CONFIG.'keyword,strip(value)
|
||||
end /* strip keeps internal whitespace only. */
|
||||
|
||||
else /* store each value with its index. */
|
||||
do v = 1 by 1 while length(value) > 0
|
||||
parse var value value1 ',' value
|
||||
|
||||
if length(value1) > 0 then
|
||||
do
|
||||
call value 'CONFIG.'keyword'.'v,strip(value1)
|
||||
call value 'CONFIG.'keyword'.0',v /* remember this. */
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
/* Display the values of the configuration variables. */
|
||||
say 'Values associated with configuration file' configfilename':'
|
||||
say
|
||||
|
||||
do while words(keywords) > 0
|
||||
parse var keywords keyword keywords
|
||||
|
||||
if value('CONFIG_single?.'keyword) then
|
||||
say right(keyword,20) '= "'value('CONFIG.'keyword)'"'
|
||||
|
||||
else
|
||||
do
|
||||
lastv = value('CONFIG.'keyword'.0')
|
||||
|
||||
do v = 1 to lastv
|
||||
say right(keyword,20-(length(v)+2))'['v'] = "'value('CONFIG.'keyword'.'v)'"'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
say
|
||||
|
||||
notready: /* I/O errors come here. */
|
||||
filestatus = stream(configfile,'STATE')
|
||||
|
||||
if filestatus \= 'READY' then
|
||||
say 'An I/O error occurred; the file status is' filestatus'.'
|
||||
|
||||
response = stream(configfile,'COMMAND','CLOSE')
|
||||
|
||||
error:
|
||||
/*? = sysdumpvariables() */ /* see everything Rexx used. */
|
||||
exit
|
||||
|
||||
usage: procedure
|
||||
trace normal
|
||||
|
||||
if arg(1) = '-h',
|
||||
| arg(1) = '-?',
|
||||
| arg(1) = '--help'
|
||||
then
|
||||
do
|
||||
line = '/*|'
|
||||
say
|
||||
|
||||
do l = 3 by 1 while line~left(3) = '/*|'
|
||||
line = sourceline(l)
|
||||
parse var line . '/*|' text '|*/' .
|
||||
say text
|
||||
end
|
||||
|
||||
say
|
||||
exit 0
|
||||
end
|
||||
return
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
$conf = file_get_contents('parse-conf-file.txt');
|
||||
|
||||
// Add an "=" after entry name
|
||||
$conf = preg_replace('/^([a-z]+)/mi', '$1 =', $conf);
|
||||
|
||||
// Replace multiple parameters separated by commas :
|
||||
// name = value1, value2
|
||||
// by multiple lines :
|
||||
// name[] = value1
|
||||
// name[] = value2
|
||||
$conf = preg_replace_callback(
|
||||
'/^([a-z]+)\s*=((?=.*\,.*).*)$/mi',
|
||||
function ($matches) {
|
||||
$r = '';
|
||||
foreach (explode(',', $matches[2]) AS $val) {
|
||||
$r .= $matches[1] . '[] = ' . trim($val) . PHP_EOL;
|
||||
}
|
||||
return $r;
|
||||
},
|
||||
$conf
|
||||
);
|
||||
|
||||
// Replace empty values by "true"
|
||||
$conf = preg_replace('/^([a-z]+)\s*=$/mi', '$1 = true', $conf);
|
||||
|
||||
// Parse configuration file
|
||||
$ini = parse_ini_string($conf);
|
||||
|
||||
echo 'Full name = ', $ini['FULLNAME'], PHP_EOL;
|
||||
echo 'Favourite fruit = ', $ini['FAVOURITEFRUIT'], PHP_EOL;
|
||||
echo 'Need spelling = ', (empty($ini['NEEDSPEELING']) ? 'false' : 'true'), PHP_EOL;
|
||||
echo 'Seeds removed = ', (empty($ini['SEEDSREMOVED']) ? 'false' : 'true'), PHP_EOL;
|
||||
echo 'Other family = ', print_r($ini['OTHERFAMILY'], true), PHP_EOL;
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
set: procedure options (main);
|
||||
declare text character (100) varying;
|
||||
declare (fullname, favouritefruit) character (100) varying initial ('');
|
||||
declare needspeeling bit (1) static initial ('0'b);
|
||||
declare seedsremoved bit (1) static initial ('0'b);
|
||||
declare otherfamily(10) character (100) varying;
|
||||
declare (i, j) fixed binary;
|
||||
declare in file;
|
||||
|
||||
open file (in) title ( '/RD-CON.DAT,TYPE(TEXT),RECSIZE(200)' );
|
||||
|
||||
on endfile (in) go to variables;
|
||||
|
||||
otherfamily = ''; j = 0;
|
||||
|
||||
do forever;
|
||||
get file (in) edit (text) (L);
|
||||
text = trim(text);
|
||||
|
||||
if length(text) = 0 then iterate;
|
||||
if substr(text, 1, 1) = ';' then iterate;
|
||||
if substr(text, 1, 1) = '#' then iterate;
|
||||
if length(text) >= 9 then
|
||||
if substr(text, 1, 9) = 'FULLNAME ' then
|
||||
fullname = trim( substr(text, 9) );
|
||||
if length(text) >= 15 then
|
||||
if substr(text, 1, 15) = 'FAVOURITEFRUIT ' then
|
||||
favouritefruit = trim( substr(text, 15) );
|
||||
if length(text) >= 12 then
|
||||
if text = 'NEEDSPEELING' then needspeeling = '1'b;
|
||||
if length(text) >= 12 then
|
||||
if text = 'SEEDSREMOVED' then seedsremoved = '1'b;
|
||||
if length(text) >= 12 then
|
||||
if substr(text, 1, 12) = 'OTHERFAMILY ' then
|
||||
do;
|
||||
text = trim(substr(text, 12) );
|
||||
i = index(text, ',');
|
||||
do while (i > 0);
|
||||
j = j + 1;
|
||||
otherfamily(j) = substr(text, 1, i-1);
|
||||
text = trim(substr(text, i+1));
|
||||
i = index(text, ',');
|
||||
end;
|
||||
j = j + 1;
|
||||
otherfamily(j) = trim(text);
|
||||
end;
|
||||
end;
|
||||
|
||||
variables:
|
||||
put skip data (fullname);
|
||||
put skip data (favouritefruit);
|
||||
put skip data (needspeeling);
|
||||
put skip data (seedsremoved);
|
||||
do i = 1 to j;
|
||||
put skip data (otherfamily(i));
|
||||
end;
|
||||
|
||||
end set;
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/instantfpc
|
||||
|
||||
{$if not defined(fpc) or (fpc_fullversion < 20600)}
|
||||
{$error FPC 2.6.0 or greater required}
|
||||
{$endif}
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
Classes,SysUtils,gvector,ghashmap;
|
||||
|
||||
type
|
||||
TStrHashCaseInsensitive = class
|
||||
class function hash(s: String; n: Integer): Integer;
|
||||
end;
|
||||
|
||||
class function TStrHashCaseInsensitive.hash(s: String; n: Integer): Integer;
|
||||
var
|
||||
x: Integer;
|
||||
c: Char;
|
||||
begin
|
||||
x := 0;
|
||||
for c in UpCase(s) do Inc(x,Ord(c));
|
||||
Result := x mod n;
|
||||
end;
|
||||
|
||||
type
|
||||
TConfigValues = specialize TVector<String>;
|
||||
TConfigStorage = class(specialize THashMap<String,TConfigValues,TStrHashCaseInsensitive>)
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
destructor TConfigStorage.Destroy;
|
||||
var
|
||||
It: TIterator;
|
||||
begin
|
||||
if Size > 0 then begin
|
||||
It := Iterator;
|
||||
repeat
|
||||
It.Value.Free;
|
||||
until not It.Next;
|
||||
It.Free;
|
||||
end;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
var
|
||||
ConfigStrings,ConfigValues: TStrings;
|
||||
ConfigStorage: TConfigStorage;
|
||||
ConfigLine,ConfigName,ConfigValue: String;
|
||||
SeparatorPos: Integer;
|
||||
begin
|
||||
ConfigStrings := TStringList.Create;
|
||||
ConfigValues := TStringList.Create;
|
||||
ConfigValues.Delimiter := ',';
|
||||
ConfigValues.StrictDelimiter := true;
|
||||
ConfigStorage := TConfigStorage.Create;
|
||||
|
||||
ConfigStrings.LoadFromFile('config.test');
|
||||
for ConfigLine in ConfigStrings do begin
|
||||
if Length(ConfigLine) > 0 then begin
|
||||
case ConfigLine[1] of
|
||||
'#',';': ; // ignore
|
||||
else begin
|
||||
// look for = first
|
||||
SeparatorPos := Pos('=',ConfigLine);
|
||||
// if not found, then look for space
|
||||
if SeparatorPos = 0 then begin
|
||||
SeparatorPos := Pos(' ',ConfigLine);
|
||||
end;
|
||||
// found space
|
||||
if SeparatorPos <> 0 then begin
|
||||
ConfigName := UpCase(Copy(ConfigLine,1,SeparatorPos - 1));
|
||||
ConfigValues.DelimitedText := Copy(ConfigLine,SeparatorPos + 1,Length(ConfigLine) - SeparatorPos);
|
||||
// no = or space found, take the whole line as a key name
|
||||
end else begin
|
||||
ConfigName := UpCase(Trim(ConfigLine));
|
||||
end;
|
||||
if not ConfigStorage.Contains(ConfigName) then begin
|
||||
ConfigStorage[ConfigName] := TConfigValues.Create;
|
||||
end;
|
||||
for ConfigValue in ConfigValues do begin
|
||||
ConfigStorage[ConfigName].PushBack(Trim(ConfigValue));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
WriteLn('FULLNAME = ' + ConfigStorage['FULLNAME'][0]);
|
||||
WriteLn('FAVOURITEFRUIT = ' + ConfigStorage['FAVOURITEFRUIT'][0]);
|
||||
WriteLn('NEEDSPEELING = ' + BoolToStr(ConfigStorage.Contains('NEEDSPEELING'),true));
|
||||
WriteLn('SEEDSREMOVED = ' + BoolToStr(ConfigStorage.Contains('SEEDSREMOVED'),true));
|
||||
WriteLn('OTHERFAMILY(1) = ' + ConfigStorage['OTHERFAMILY'][0]);
|
||||
WriteLn('OTHERFAMILY(2) = ' + ConfigStorage['OTHERFAMILY'][1]);
|
||||
|
||||
ConfigStorage.Free;
|
||||
ConfigValues.Free;
|
||||
ConfigStrings.Free;
|
||||
end.
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<@ DEFUDRLIT>__ReadConfigurationFile|
|
||||
<@ LETSCPPNTPARSRC>Data|1</@><@ OMT> read file into locally scope variable</@>
|
||||
<@ LETCGDLSTLLOSCP>List|Data</@><@ OMT> split Data into a list of lines </@>
|
||||
<@ OMT> Remove comment lines, and blank lines </@>
|
||||
<@ ACTOVRBEFLSTLIT>List|;</@>
|
||||
<@ ACTOVRBEFLSTLIT>List|#</@>
|
||||
<@ ACTRMELST>List</@>
|
||||
<@ OMT> Iterate over the lines of the list </@>
|
||||
<@ ITEENULSTLit>List|
|
||||
<@ LETVARUPTVALLSTLIT>key|...| </@>
|
||||
<@ LETVARAFTVALLSTLIT>val|...| </@>
|
||||
<@ OMT> test for an empty key (in the case of a boolean) </@>
|
||||
<@ TSTVARLIT>key|</@>
|
||||
<@ IFE><@ LETPNTVARVARLIT>val|__True</@></@>
|
||||
<@ ELS>
|
||||
<@ TSTGT0ATBVARLIT>val|,</@>
|
||||
<@ IFE><@ ACTEXEEMMCAP><&prot; LETCNDLSTLITLIT>&key;&pipe;&val;&pipe;, </&prot;></@></@>
|
||||
<@ ELS><@ LETPNTVARVARVAR>key|val</@></@>
|
||||
</@>
|
||||
</@>
|
||||
</@>
|
||||
|
||||
<@ ACTUDRLIT>__ReadConfigurationFile|c:\rosetta.config</@>
|
||||
<@ SAYVAR>FAVOURITEFRUIT</@>
|
||||
<@ SAYVAR>FULLNAME</@>
|
||||
<@ SAYVAR>NEEDSPEELING</@>
|
||||
<@ SAYDMPLST>OTHERFAMILY</@>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
my $fullname;
|
||||
my $favouritefruit;
|
||||
my $needspeeling;
|
||||
my $seedsremoved;
|
||||
my @otherfamily;
|
||||
|
||||
# configuration file definition. See read_conf_file below for explanation.
|
||||
my $conf_definition = {
|
||||
'fullname' => [ 'string', \$fullname ],
|
||||
'favouritefruit' => [ 'string', \$favouritefruit ],
|
||||
'needspeeling' => [ 'boolean', \$needspeeling ],
|
||||
'seedsremoved' => [ 'boolean', \$seedsremoved ],
|
||||
'otherfamily' => [ 'array', \@otherfamily ],
|
||||
};
|
||||
|
||||
my $arg = shift; # take the configuration file name from the command line
|
||||
# (or first subroutine argument if this were in a sub)
|
||||
my $file; # this is going to be a file handle reference
|
||||
open $file, $arg or die "Can't open configuration file '$arg': $!";
|
||||
|
||||
read_conf_file($file, $conf_definition);
|
||||
|
||||
print "fullname = $fullname\n";
|
||||
print "favouritefruit = $favouritefruit\n";
|
||||
print "needspeeling = ", ($needspeeling ? 'true' : 'false'), "\n";
|
||||
print "seedsremoved = ", ($seedsremoved ? 'true' : 'false'), "\n";
|
||||
for (my $i = 0; $i < @otherfamily; ++$i) {
|
||||
print "otherfamily(", $i + 1, ") = ", $otherfamily[$i], "\n";
|
||||
}
|
||||
|
||||
# read_conf_file: Given a file handle opened for reading and a configuration definition,
|
||||
# read the file.
|
||||
# If the configuration file doesn't match the definition, raise an exception with "die".
|
||||
# The configuration definition is (a reference to) an associative array
|
||||
# where the keys are the configuration variable names in all lower case
|
||||
# and the values are references to arrays.
|
||||
# The first element of each of these arrays is the expected type: 'boolean', 'string', or 'array';
|
||||
# the second element is a reference to the variable that should be assigned the data.
|
||||
sub read_conf_file {
|
||||
my ($fh, $def) = @_; # copy parameters
|
||||
|
||||
local $_; # avoid interfering with use of $_ in main program
|
||||
while (<$fh>) { # read a line from $fh into $_ until end of file
|
||||
next if /^#/; # skip "#" comments
|
||||
next if /^;/; # skip ";" comments
|
||||
next if /^$/; # skip blank lines
|
||||
chomp; # strip final newline
|
||||
|
||||
$_ =~ /^\s*(\w+)\s*(.*)$/i or die "Syntax error";
|
||||
my $key = $1;
|
||||
my $rest = $2;
|
||||
$key =~ tr/[A-Z]/[a-z]/; # convert keyword to lower case
|
||||
|
||||
if (!exists $def->{$key}) {
|
||||
die "Unknown keyword: '$key'";
|
||||
}
|
||||
|
||||
if ($def->{$key}[0] eq 'boolean') {
|
||||
if ($rest) {
|
||||
die "Syntax error: extra data following boolean '$key'";
|
||||
}
|
||||
${$def->{$key}[1]} = 1;
|
||||
next; # done with this line, go back to "while"
|
||||
}
|
||||
|
||||
$rest =~ s/\s*$//; # drop trailing whitespace
|
||||
$rest =~ s/^=\s*//; # drop equals sign if present
|
||||
|
||||
if ($def->{$key}[0] eq 'string') {
|
||||
${$def->{$key}[1]} = $rest;
|
||||
} elsif ($def->{$key}[0] eq 'array') {
|
||||
@{$def->{$key}[1]} = split /\s*,\s*/, $rest;
|
||||
} else {
|
||||
die "Internal error (unknown type in configuration definition)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
-->
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"RCTEST.INI"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"r"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #004600;">GT_LF_STRIPPED</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">dini</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">li</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"#;"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">li</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">rest</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">li</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$]</span>
|
||||
<span style="color: #000000;">li</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">li</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #000080;font-style:italic;">-- (may want upper())</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">','</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rest</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rest</span><span style="color: #0000FF;">,</span><span style="color: #008000;">','</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]=</span><span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #7060A8;">putd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dini</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #7060A8;">putd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dini</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #7060A8;">putd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dini</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ""</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">visitor</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000080;font-style:italic;">/*user_data*/</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">?{</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">data</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
<span style="color: #7060A8;">traverse_dict</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"visitor"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dini</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"FAVOURITEFRUIT"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dini</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
def optionValue
|
||||
2 get "," find
|
||||
if
|
||||
" " "-" subst "," " " subst split
|
||||
len for
|
||||
var i
|
||||
i get "-" " " subst
|
||||
rot 1 get "(" chain print i print ") = " print swap trim print nl swap
|
||||
endfor
|
||||
drop drop
|
||||
else
|
||||
swap 1 get print " = " print swap print nl
|
||||
endif
|
||||
enddef
|
||||
|
||||
0 tolist
|
||||
|
||||
"rosetta_read.cfg" "r" fopen var file
|
||||
|
||||
file 0 > if
|
||||
true
|
||||
while
|
||||
file fgets
|
||||
dup -1 != if
|
||||
trim
|
||||
len 0 > if
|
||||
1 get '#' != if
|
||||
" " find var pos
|
||||
pos if
|
||||
1 pos 1 - slice
|
||||
swap len pos - pos 1 + swap slice
|
||||
nip 2 tolist
|
||||
else
|
||||
"" 2 tolist
|
||||
endif
|
||||
0 put
|
||||
else
|
||||
drop
|
||||
endif
|
||||
else
|
||||
drop
|
||||
endif
|
||||
true
|
||||
else
|
||||
drop
|
||||
file fclose
|
||||
false
|
||||
endif
|
||||
endwhile
|
||||
|
||||
len for
|
||||
get
|
||||
1 get ";" == if 2 get print " = false" print nl
|
||||
else 2 get "" == if 1 get print " = true" print nl
|
||||
else optionValue
|
||||
endif
|
||||
endif
|
||||
drop
|
||||
endfor
|
||||
endif
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
go =>
|
||||
Vars = ["fullname","favouritefruit","needspeeling","seedsremoved","otherfamily"],
|
||||
Config = read_config("read_a_configuration_file_config.cfg"),
|
||||
foreach(Key in Vars)
|
||||
printf("%w = %w\n", Key, Config.get(Key,false))
|
||||
end,
|
||||
nl.
|
||||
|
||||
% Read configuration file
|
||||
read_config(File) = Config =>
|
||||
Config = new_map(),
|
||||
Lines = [Line : Line in read_file_lines(File), Line != [], not membchk(Line[1],"#;")],
|
||||
foreach(Line in Lines)
|
||||
Line := strip(Line),
|
||||
once( append(Key,[' '|Value],Line) ; Key = Line, Value = true),
|
||||
if find(Value,",",_,_) then
|
||||
Value := [strip(Val) : Val in split(Value,",")]
|
||||
end,
|
||||
Key := strip(to_lowercase(Key)),
|
||||
Config.put(Key,Value)
|
||||
end.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
(de rdConf (File)
|
||||
(in File
|
||||
(while (read)
|
||||
(set @ (or (pack (clip (line))) T)) ) ) )
|
||||
|
||||
(rdConf "conf.txt")
|
||||
(println FULLNAME FAVOURITEFRUIT NEEDSPEELING SEEDSREMOVED OTHERFAMILY)
|
||||
(bye)
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
function Read-ConfigurationFile
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
# Path to the configuration file. Default is "C:\ConfigurationFile.cfg"
|
||||
[Parameter(Mandatory=$false, Position=0)]
|
||||
[string]
|
||||
$Path = "C:\ConfigurationFile.cfg"
|
||||
)
|
||||
|
||||
[string]$script:fullName = ""
|
||||
[string]$script:favouriteFruit = ""
|
||||
[bool]$script:needsPeeling = $false
|
||||
[bool]$script:seedsRemoved = $false
|
||||
[string[]]$script:otherFamily = @()
|
||||
|
||||
function Get-Value ([string]$Line)
|
||||
{
|
||||
if ($Line -match "=")
|
||||
{
|
||||
[string]$value = $Line.Split("=",2).Trim()[1]
|
||||
}
|
||||
elseif ($Line -match " ")
|
||||
{
|
||||
[string]$value = $Line.Split(" ",2).Trim()[1]
|
||||
}
|
||||
|
||||
$value
|
||||
}
|
||||
|
||||
# Process each line in file that is not a comment.
|
||||
Get-Content $Path | Select-String -Pattern "^[^#;]" | ForEach-Object {
|
||||
|
||||
[string]$line = $_.Line.Trim()
|
||||
|
||||
if ($line -eq [String]::Empty)
|
||||
{
|
||||
# do nothing for empty lines
|
||||
}
|
||||
elseif ($line.ToUpper().StartsWith("FULLNAME"))
|
||||
{
|
||||
$script:fullName = Get-Value $line
|
||||
}
|
||||
elseif ($line.ToUpper().StartsWith("FAVOURITEFRUIT"))
|
||||
{
|
||||
$script:favouriteFruit = Get-Value $line
|
||||
}
|
||||
elseif ($line.ToUpper().StartsWith("NEEDSPEELING"))
|
||||
{
|
||||
$script:needsPeeling = $true
|
||||
}
|
||||
elseif ($line.ToUpper().StartsWith("SEEDSREMOVED"))
|
||||
{
|
||||
$script:seedsRemoved = $true
|
||||
}
|
||||
elseif ($line.ToUpper().StartsWith("OTHERFAMILY"))
|
||||
{
|
||||
$script:otherFamily = (Get-Value $line).Split(',').Trim()
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose -Message ("{0,-15}= {1}" -f "FULLNAME", $script:fullName)
|
||||
Write-Verbose -Message ("{0,-15}= {1}" -f "FAVOURITEFRUIT", $script:favouriteFruit)
|
||||
Write-Verbose -Message ("{0,-15}= {1}" -f "NEEDSPEELING", $script:needsPeeling)
|
||||
Write-Verbose -Message ("{0,-15}= {1}" -f "SEEDSREMOVED", $script:seedsRemoved)
|
||||
Write-Verbose -Message ("{0,-15}= {1}" -f "OTHERFAMILY", ($script:otherFamily -join ", "))
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Read-ConfigurationFile -Path .\temp.txt -Verbose
|
||||
|
|
@ -0,0 +1 @@
|
|||
Get-Variable -Name fullName, favouriteFruit, needsPeeling, seedsRemoved, otherFamily
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
Function Read-ConfigurationFile {
|
||||
[CmdletBinding()]
|
||||
[OutputType([Collections.Specialized.OrderedDictionary])]
|
||||
Param (
|
||||
[Parameter(
|
||||
Mandatory=$true,
|
||||
Position=0
|
||||
)
|
||||
]
|
||||
[Alias('LiteralPath')]
|
||||
[ValidateScript({
|
||||
Test-Path -LiteralPath $PSItem -PathType 'Leaf'
|
||||
})
|
||||
]
|
||||
[String]
|
||||
$_LiteralPath
|
||||
)
|
||||
|
||||
Begin {
|
||||
Function Houdini-Value ([String]$_Text) {
|
||||
$__Aux = $_Text.Trim()
|
||||
If ($__Aux.Length -eq 0) {
|
||||
$__Aux = $true
|
||||
} ElseIf ($__Aux.Contains(',')) {
|
||||
$__Aux = $__Aux.Split(',') |
|
||||
ForEach-Object {
|
||||
If ($PSItem.Trim().Length -ne 0) {
|
||||
$PSItem.Trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
Return $__Aux
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
$__Configuration = [Ordered]@{}
|
||||
# Config equivalent pattern
|
||||
# Select-String -Pattern '^\s*[^\s;#=]+.*\s*$' -LiteralPath '.\filename.cfg'
|
||||
Switch -Regex -File $_LiteralPath {
|
||||
|
||||
'^\s*[;#=]|^\s*$' {
|
||||
Write-Verbose -Message "v$(' '*20)ignored"
|
||||
Write-Verbose -Message $Matches[0]
|
||||
Continue
|
||||
}
|
||||
|
||||
'^([^=]+)=(.*)$' {
|
||||
Write-Verbose -Message '↓← ← ← ← ← ← ← ← ← ← equal pattern'
|
||||
Write-Verbose -Message $Matches[0]
|
||||
$__Name,$__Value = $Matches[1..2]
|
||||
$__Configuration[$__Name.Trim()] = Houdini-Value($__Value)
|
||||
Continue
|
||||
}
|
||||
|
||||
'^\s*([^\s;#=]+)(.*)(\s*)$' {
|
||||
Write-Verbose -Message '↓← ← ← ← ← ← ← ← ← ← space or tab pattern or only name'
|
||||
Write-Verbose -Message $Matches[0]
|
||||
$__Name,$__Value = $Matches[1..2]
|
||||
$__Configuration[$__Name.Trim()] = Houdini-Value($__Value)
|
||||
Continue
|
||||
}
|
||||
|
||||
}
|
||||
Return $__Configuration
|
||||
}
|
||||
}
|
||||
|
||||
Function Show-Value ([Collections.Specialized.OrderedDictionary]$_Dictionary, $_Index, $_SubIndex) {
|
||||
$__Aux = $_Index + ' = '
|
||||
If ($_Dictionary[$_Index] -eq $null) {
|
||||
$__Aux += $false
|
||||
} ElseIf ($_Dictionary[$_Index].Count -gt 1) {
|
||||
If ($_SubIndex -eq $null) {
|
||||
$__Aux += $_Dictionary[$_Index] -join ','
|
||||
} Else {
|
||||
$__Aux = $_Index + '(' + $_SubIndex + ') = '
|
||||
If ($_Dictionary[$_Index][$_SubIndex] -eq $null) {
|
||||
$__Aux += $false
|
||||
} Else {
|
||||
$__Aux += $_Dictionary[$_Index][$_SubIndex]
|
||||
}
|
||||
}
|
||||
} Else {
|
||||
$__Aux += $_Dictionary[$_Index]
|
||||
}
|
||||
Return $__Aux
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
$Configuration = Read-ConfigurationFile -LiteralPath '.\config.cfg'
|
||||
|
|
@ -0,0 +1 @@
|
|||
$Configuration
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
Show-Value $Configuration 'fullname'
|
||||
Show-Value $Configuration 'favouritefruit'
|
||||
Show-Value $Configuration 'needspeeling'
|
||||
Show-Value $Configuration 'seedsremoved'
|
||||
Show-Value $Configuration 'otherfamily'
|
||||
Show-Value $Configuration 'otherfamily' 0
|
||||
Show-Value $Configuration 'otherfamily' 1
|
||||
Show-Value $Configuration 'otherfamily' 2
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
'$Configuration[''fullname'']'
|
||||
$Configuration['fullname']
|
||||
'$Configuration.''fullname'''
|
||||
$Configuration.'fullname'
|
||||
'$Configuration.Item(''fullname'')'
|
||||
$Configuration.Item('fullname')
|
||||
'$Configuration[0]'
|
||||
$Configuration[0]
|
||||
'$Configuration.Item(0)'
|
||||
$Configuration.Item(0)
|
||||
' '
|
||||
'=== $Configuration[''otherfamily''] ==='
|
||||
$Configuration['otherfamily']
|
||||
'=== $Configuration[''otherfamily''][0] ==='
|
||||
$Configuration['otherfamily'][0]
|
||||
'=== $Configuration[''otherfamily''][1] ==='
|
||||
$Configuration['otherfamily'][1]
|
||||
' '
|
||||
'=== $Configuration.''otherfamily'' ==='
|
||||
$Configuration.'otherfamily'
|
||||
'=== $Configuration.''otherfamily''[0] ==='
|
||||
$Configuration.'otherfamily'[0]
|
||||
'=== $Configuration.''otherfamily''[1] ==='
|
||||
$Configuration.'otherfamily'[1]
|
||||
' '
|
||||
'=== $Configuration.Item(''otherfamily'') ==='
|
||||
$Configuration.Item('otherfamily')
|
||||
'=== $Configuration.Item(''otherfamily'')[0] ==='
|
||||
$Configuration.Item('otherfamily')[0]
|
||||
'=== $Configuration.Item(''otherfamily'')[1] ==='
|
||||
$Configuration.Item('otherfamily')[1]
|
||||
' '
|
||||
'=== $Configuration[3] ==='
|
||||
$Configuration[3]
|
||||
'=== $Configuration[3][0] ==='
|
||||
$Configuration[3][0]
|
||||
'=== $Configuration[3][1] ==='
|
||||
$Configuration[3][1]
|
||||
' '
|
||||
'=== $Configuration.Item(3) ==='
|
||||
$Configuration.Item(3)
|
||||
'=== $Configuration.Item(3).Item(0) ==='
|
||||
$Configuration.Item(3).Item(0)
|
||||
'=== $Configuration.Item(3).Item(1) ==='
|
||||
$Configuration.Item(3).Item(1)
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
def readconf(fn):
|
||||
ret = {}
|
||||
with file(fn) as fp:
|
||||
for line in fp:
|
||||
# Assume whitespace is ignorable
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'): continue
|
||||
|
||||
boolval = True
|
||||
# Assume leading ";" means a false boolean
|
||||
if line.startswith(';'):
|
||||
# Remove one or more leading semicolons
|
||||
line = line.lstrip(';')
|
||||
# If more than just one word, not a valid boolean
|
||||
if len(line.split()) != 1: continue
|
||||
boolval = False
|
||||
|
||||
bits = line.split(None, 1)
|
||||
if len(bits) == 1:
|
||||
# Assume booleans are just one standalone word
|
||||
k = bits[0]
|
||||
v = boolval
|
||||
else:
|
||||
# Assume more than one word is a string value
|
||||
k, v = bits
|
||||
ret[k.lower()] = v
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
conf = readconf(sys.argv[1])
|
||||
for k, v in sorted(conf.items()):
|
||||
print k, '=', v
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*REXX program reads a config (configuration) file and assigns VARs as found within. */
|
||||
signal on syntax; signal on novalue /*handle REXX source program errors. */
|
||||
parse arg cFID _ . /*cFID: is the CONFIG file to be read.*/
|
||||
if cFID=='' then cFID='CONFIG.DAT' /*Not specified? Then use the default.*/
|
||||
bad= /*this will contain all the bad VARs. */
|
||||
varList= /* " " " " " good " */
|
||||
maxLenV=0; blanks=0; hashes=0; semics=0; badVar=0 /*zero all these variables.*/
|
||||
|
||||
do j=0 while lines(cFID)\==0 /*J: it counts the lines in the file.*/
|
||||
txt=strip(linein(cFID)) /*read a line (record) from the file, */
|
||||
/* ··· & strip leading/trailing blanks*/
|
||||
if txt ='' then do; blanks=blanks+1; iterate; end /*count # blank lines.*/
|
||||
if left(txt,1)=='#' then do; hashes=hashes+1; iterate; end /* " " lines with #*/
|
||||
if left(txt,1)==';' then do; semics=semics+1; iterate; end /* " " " " ;*/
|
||||
eqS=pos('=',txt) /*we can't use the TRANSLATE BIF. */
|
||||
if eqS\==0 then txt=overlay(' ',txt,eqS) /*replace the first '=' with a blank.*/
|
||||
parse var txt xxx value; upper xxx /*get the variable name and it's value.*/
|
||||
value=strip(value) /*strip leading and trailing blanks. */
|
||||
if value='' then value='true' /*if no value, then use "true". */
|
||||
if symbol(xxx)=='BAD' then do /*can REXX utilize the variable name ? */
|
||||
badVar=badVar+1; bad=bad xxx; iterate /*append to list*/
|
||||
end
|
||||
varList=varList xxx /*add it to the list of good variables.*/
|
||||
call value xxx,value /*now, use VALUE to set the variable. */
|
||||
maxLenV=max(maxLenV,length(value)) /*maxLen of varNames, pretty display. */
|
||||
end /*j*/
|
||||
|
||||
vars=words(varList); @ig= 'ignored that began with a'
|
||||
say #(j) 'record's(j) "were read from file: " cFID
|
||||
if blanks\==0 then say #(blanks) 'blank record's(blanks) "were read."
|
||||
if hashes\==0 then say #(hashes) 'record's(hashes) @ig "# (hash)."
|
||||
if semics\==0 then say #(semics) 'record's(semics) @ig "; (semicolon)."
|
||||
if badVar\==0 then say #(badVar) 'bad variable name's(badVar) 'detected:' bad
|
||||
say; say 'The list of' vars "variable"s(vars) 'and' s(vars,'their',"it's"),
|
||||
"value"s(vars) 'follows:'
|
||||
say; do k=1 for vars
|
||||
v=word(varList,k)
|
||||
say right(v,maxLenV) '=' value(v)
|
||||
end /*k*/
|
||||
say; exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1)
|
||||
#: return right(arg(1),length(j)+11) /*right justify a number & also indent.*/
|
||||
err: do j=1 for arg(); say '***error*** ' arg(j); say; end /*j*/; exit 13
|
||||
novalue: syntax: call err 'REXX program' condition('C') "error",,
|
||||
condition('D'),'REXX source statement (line' sigl"):",sourceline(sigl)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#lang racket
|
||||
|
||||
(require "options.rkt")
|
||||
|
||||
(read-options "options-file")
|
||||
(define-options fullname favouritefruit needspeeling seedsremoved otherfamily)
|
||||
(printf "fullname = ~s\n" fullname)
|
||||
(printf "favouritefruit = ~s\n" favouritefruit)
|
||||
(printf "needspeeling = ~s\n" needspeeling)
|
||||
(printf "seedsremoved = ~s\n" seedsremoved)
|
||||
(printf "otherfamily = ~s\n" otherfamily)
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
my $fullname;
|
||||
my $favouritefruit;
|
||||
my $needspeeling = False;
|
||||
my $seedsremoved = False;
|
||||
my @otherfamily;
|
||||
|
||||
grammar ConfFile {
|
||||
token TOP {
|
||||
:my $*linenum = 0;
|
||||
^ <fullline>* [$ || (\N*) { die "Parse failed at $0" } ]
|
||||
}
|
||||
|
||||
token fullline {
|
||||
<?before .>
|
||||
{ ++$*linenum }
|
||||
<line>
|
||||
[ \n || { die "Parse failed at line $*linenum" } ]
|
||||
}
|
||||
|
||||
proto token line() {*}
|
||||
|
||||
token line:misc { {} (\S+) { die "Unrecognized word: $0" } }
|
||||
|
||||
token line:sym<comment> { ^^ [ ';' | '#' ] \N* }
|
||||
token line:sym<blank> { ^^ \h* $$ }
|
||||
|
||||
token line:sym<fullname> {:i fullname» <rest> { $fullname = $<rest>.trim } }
|
||||
token line:sym<favouritefruit> {:i favouritefruit» <rest> { $favouritefruit = $<rest>.trim } }
|
||||
token line:sym<needspeeling> {:i needspeeling» <yes> { $needspeeling = defined $<yes> } }
|
||||
token rest { \h* '='? (\N*) }
|
||||
token yes { :i \h* '='? \h*
|
||||
[
|
||||
|| ([yes|true|1])
|
||||
|| [no|false|0]
|
||||
|| (<?>)
|
||||
] \h*
|
||||
}
|
||||
}
|
||||
|
||||
grammar MyConfFile is ConfFile {
|
||||
token line:sym<otherfamily> {:i otherfamily» <rest> { @otherfamily = $<rest>.split(',')».trim } }
|
||||
}
|
||||
|
||||
MyConfFile.parsefile('file.cfg');
|
||||
|
||||
say "fullname: $fullname";
|
||||
say "favouritefruit: $favouritefruit";
|
||||
say "needspeeling: $needspeeling";
|
||||
say "seedsremoved: $seedsremoved";
|
||||
print "otherfamily: "; say @otherfamily.raku;
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
type TSettings extends QObject
|
||||
FullName as string
|
||||
FavouriteFruit as string
|
||||
NeedSpelling as integer
|
||||
SeedsRemoved as integer
|
||||
OtherFamily as QStringlist
|
||||
|
||||
Constructor
|
||||
FullName = ""
|
||||
FavouriteFruit = ""
|
||||
NeedSpelling = 0
|
||||
SeedsRemoved = 0
|
||||
OtherFamily.clear
|
||||
end constructor
|
||||
end type
|
||||
|
||||
Dim Settings as TSettings
|
||||
dim ConfigList as QStringList
|
||||
dim x as integer
|
||||
dim StrLine as string
|
||||
dim StrPara as string
|
||||
dim StrData as string
|
||||
|
||||
function Trim$(Expr as string) as string
|
||||
Result = Rtrim$(Ltrim$(Expr))
|
||||
end function
|
||||
|
||||
Sub ConfigOption(PData as string)
|
||||
dim x as integer
|
||||
for x = 1 to tally(PData, ",") +1
|
||||
Settings.OtherFamily.AddItems Trim$(field$(PData, "," ,x))
|
||||
next
|
||||
end sub
|
||||
|
||||
Function ConfigBoolean(PData as string) as integer
|
||||
PData = Trim$(PData)
|
||||
Result = iif(lcase$(PData)="true" or PData="1" or PData="", 1, 0)
|
||||
end function
|
||||
|
||||
sub ReadSettings
|
||||
ConfigList.LoadFromFile("Rosetta.cfg")
|
||||
ConfigList.text = REPLACESUBSTR$(ConfigList.text,"="," ")
|
||||
|
||||
for x = 0 to ConfigList.ItemCount -1
|
||||
StrLine = Trim$(ConfigList.item(x))
|
||||
StrPara = Trim$(field$(StrLine," ",1))
|
||||
StrData = Trim$(lTrim$(StrLine - StrPara))
|
||||
|
||||
Select case UCase$(StrPara)
|
||||
case "FULLNAME" : Settings.FullName = StrData
|
||||
case "FAVOURITEFRUIT" : Settings.FavouriteFruit = StrData
|
||||
case "NEEDSPEELING" : Settings.NeedSpelling = ConfigBoolean(StrData)
|
||||
case "SEEDSREMOVED" : Settings.SeedsRemoved = ConfigBoolean(StrData)
|
||||
case "OTHERFAMILY" : Call ConfigOption(StrData)
|
||||
end select
|
||||
next
|
||||
end sub
|
||||
|
||||
Call ReadSettings
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
Red ["Read a config file"]
|
||||
|
||||
remove-each l lines: read/lines %file.conf [any [empty? l #"#" = l/1]]
|
||||
foreach line lines [
|
||||
foo: parse line [collect [keep to [" " | end] skip keep to end]]
|
||||
either foo/1 = #";" [set to-word foo/2 false][
|
||||
set to-word foo/1 any [
|
||||
all [find foo/2 #"," split foo/2 ", "]
|
||||
foo/2
|
||||
true
|
||||
]
|
||||
]
|
||||
]
|
||||
foreach w [fullname favouritefruit needspeeling seedsremoved otherfamily][
|
||||
prin [pad w 15 ": "] probe get w
|
||||
]
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
fullname = favouritefruit = ""
|
||||
needspeeling = seedsremoved = false
|
||||
otherfamily = []
|
||||
|
||||
IO.foreach("config.file") do |line|
|
||||
line.chomp!
|
||||
key, value = line.split(nil, 2)
|
||||
case key
|
||||
when /^([#;]|$)/; # ignore line
|
||||
when "FULLNAME"; fullname = value
|
||||
when "FAVOURITEFRUIT"; favouritefruit = value
|
||||
when "NEEDSPEELING"; needspeeling = true
|
||||
when "SEEDSREMOVED"; seedsremoved = true
|
||||
when "OTHERFAMILY"; otherfamily = value.split(",").map(&:strip)
|
||||
when /^./; puts "#{key}: unknown key"
|
||||
end
|
||||
end
|
||||
|
||||
puts "fullname = #{fullname}"
|
||||
puts "favouritefruit = #{favouritefruit}"
|
||||
puts "needspeeling = #{needspeeling}"
|
||||
puts "seedsremoved = #{seedsremoved}"
|
||||
otherfamily.each_with_index do |name, i|
|
||||
puts "otherfamily(#{i+1}) = #{name}"
|
||||
end
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
dim param$(6)
|
||||
dim paramVal$(6)
|
||||
param$(1) = "fullname"
|
||||
param$(2) = "favouritefruit"
|
||||
param$(3) = "needspeeling"
|
||||
param$(4) = "seedsremoved"
|
||||
param$(5) = "otherfamily"
|
||||
for i = 1 to 6
|
||||
paramVal$(i) = "false"
|
||||
next i
|
||||
|
||||
open DefaultDir$ + "\public\a.txt" for binary as #f
|
||||
while not(eof(#f))
|
||||
line input #f, a$
|
||||
a$ = trim$(a$)
|
||||
if instr("#;",left$(a$,1)) = 0 and a$ <> "" then
|
||||
thisParam$ = lower$(word$(a$,1," "))
|
||||
for i = 1 to 5
|
||||
if param$(i) = thisParam$ then
|
||||
paramVal$(i) = "true"
|
||||
aa$ = trim$(mid$(a$,len(thisParam$)+2))
|
||||
if aa$ <> "" then paramVal$(i) = aa$
|
||||
end if
|
||||
next i
|
||||
end if
|
||||
wend
|
||||
close #f
|
||||
for i = 1 to 5
|
||||
if instr(paramVal$(i),",") > 0 then
|
||||
for j = 1 to 2
|
||||
print param$(i);"(";j;")";chr$(9);trim$(word$(paramVal$(i),j,","))
|
||||
next j
|
||||
else
|
||||
print param$(i);chr$(9);paramVal$(i)
|
||||
end if
|
||||
next i
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
use std::fs::File;
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
let path = String::from("file.conf");
|
||||
let cfg = config_from_file(path);
|
||||
println!("{:?}", cfg);
|
||||
}
|
||||
|
||||
fn config_from_file(path: String) -> Config {
|
||||
let path = Path::new(&path);
|
||||
let file = File::open(path).expect("File not found or cannot be opened");
|
||||
let content = BufReader::new(&file);
|
||||
let mut cfg = Config::new();
|
||||
|
||||
for line in content.lines() {
|
||||
let line = line.expect("Could not read the line");
|
||||
// Remove whitespaces at the beginning and end
|
||||
let line = line.trim();
|
||||
|
||||
// Ignore comments and empty lines
|
||||
if line.starts_with("#") || line.starts_with(";") || line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Split line into parameter name and rest tokens
|
||||
let tokens = Vec::from_iter(line.split_whitespace());
|
||||
let name = tokens.first().unwrap();
|
||||
let tokens = tokens.get(1..).unwrap();
|
||||
|
||||
// Remove the equal signs
|
||||
let tokens = tokens.iter().filter(|t| !t.starts_with("="));
|
||||
// Remove comment after the parameters
|
||||
let tokens = tokens.take_while(|t| !t.starts_with("#") && !t.starts_with(";"));
|
||||
|
||||
// Concat back the parameters into one string to split for separated parameters
|
||||
let mut parameters = String::new();
|
||||
tokens.for_each(|t| { parameters.push_str(t); parameters.push(' '); });
|
||||
// Splits the parameters and trims
|
||||
let parameters = parameters.split(',').map(|s| s.trim());
|
||||
// Converts them from Vec<&str> into Vec<String>
|
||||
let parameters: Vec<String> = parameters.map(|s| s.to_string()).collect();
|
||||
|
||||
// Setting the config parameters
|
||||
match name.to_lowercase().as_str() {
|
||||
"fullname" => cfg.full_name = parameters.get(0).cloned(),
|
||||
"favouritefruit" => cfg.favourite_fruit = parameters.get(0).cloned(),
|
||||
"needspeeling" => cfg.needs_peeling = true,
|
||||
"seedsremoved" => cfg.seeds_removed = true,
|
||||
"otherfamily" => cfg.other_family = Some(parameters),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
cfg
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Config {
|
||||
full_name: Option<String>,
|
||||
favourite_fruit: Option<String>,
|
||||
needs_peeling: bool,
|
||||
seeds_removed: bool,
|
||||
other_family: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn new() -> Config {
|
||||
Config {
|
||||
full_name: None,
|
||||
favourite_fruit: None,
|
||||
needs_peeling: false,
|
||||
seeds_removed: false,
|
||||
other_family: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
val conf = scala.io.Source.fromFile("config.file").
|
||||
getLines.
|
||||
toList.
|
||||
filter(_.trim.size > 0).
|
||||
filterNot("#;" contains _(0)).
|
||||
map(_ split(" ", 2) toList).
|
||||
map(_ :+ "true" take 2).
|
||||
map {
|
||||
s:List[String] => (s(0).toLowerCase, s(1).split(",").map(_.trim).toList)
|
||||
}.toMap
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
for ((k,v) <- conf) {
|
||||
if (v.size == 1)
|
||||
println("%s: %s" format (k, v(0)))
|
||||
else
|
||||
for (i <- 0 until v.size)
|
||||
println("%s(%s): %s" format (k, i+1, v(i)))
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "scanfile.s7i";
|
||||
|
||||
var string: fullname is "";
|
||||
var string: favouritefruit is "";
|
||||
var boolean: needspeeling is FALSE;
|
||||
var boolean: seedsremoved is FALSE;
|
||||
var array string: otherfamily is 0 times "";
|
||||
|
||||
const proc: main is func
|
||||
local
|
||||
var file: configFile is STD_NULL;
|
||||
var string: symbol is "";
|
||||
var integer: index is 0;
|
||||
begin
|
||||
configFile := open("readcfg.txt", "r");
|
||||
configFile.bufferChar := getc(configFile);
|
||||
symbol := lower(getWord(configFile));
|
||||
while symbol <> "" do
|
||||
skipSpace(configFile);
|
||||
if symbol = "#" or symbol = ";" then
|
||||
skipLine(configFile);
|
||||
elsif symbol = "fullname" then
|
||||
fullname := getLine(configFile);
|
||||
elsif symbol = "favouritefruit" then
|
||||
favouritefruit := getLine(configFile);
|
||||
elsif symbol = "needspeeling" then
|
||||
needspeeling := TRUE;
|
||||
elsif symbol = "seedsremoved" then
|
||||
seedsremoved := TRUE;
|
||||
elsif symbol = "otherfamily" then
|
||||
otherfamily := split(getLine(configFile), ",");
|
||||
for key index range otherfamily do
|
||||
otherfamily[index] := trim(otherfamily[index]);
|
||||
end for;
|
||||
else
|
||||
writeln(" *** Illegal line " <& literal(getLine(configFile)));
|
||||
end if;
|
||||
symbol := lower(getWord(configFile));
|
||||
end while;
|
||||
close(configFile);
|
||||
writeln("fullname: " <& fullname);
|
||||
writeln("favouritefruit: " <& favouritefruit);
|
||||
writeln("needspeeling: " <& needspeeling);
|
||||
writeln("seedsremoved: " <& seedsremoved);
|
||||
for key index range otherfamily do
|
||||
writeln(("otherfamily[" <& index <& "]:") rpad 16 <& otherfamily[index]);
|
||||
end for;
|
||||
end func;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// read the configuration file and get a list of just the interesting lines
|
||||
set lines to each line of file "config.txt" where char 1 of each isn't in ("#", ";", "")
|
||||
|
||||
set the listFormat's quotes to quote -- be sure to quote values for evaluating
|
||||
|
||||
repeat with each configLine in lines
|
||||
put word 1 of configLine into varName
|
||||
insert varName into variableNames -- make a list of all config variables
|
||||
|
||||
put (words 2 to last of configLine) split by comma into values
|
||||
put trim of each item of values into values -- trim any leading/trailing spaces
|
||||
if values is empty then set values to true -- no value means boolean true
|
||||
do "set" && varName && "to" && values -- assign value to variable
|
||||
end repeat
|
||||
|
||||
repeat with each name in variableNames
|
||||
put "Variable" && name && "is" && value(name)
|
||||
end repeat
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Variable FULLNAME is Foo Barber
|
||||
Variable FAVOURITEFRUIT is banana
|
||||
Variable NEEDSPEELING is True
|
||||
Variable OTHERFAMILY is ("Rhu Barber","Harry Barber")
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
var fullname = (var favouritefruit = "");
|
||||
var needspeeling = (var seedsremoved = false);
|
||||
var otherfamily = [];
|
||||
|
||||
ARGF.each { |line|
|
||||
var(key, value) = line.strip.split(/\h+/, 2)...;
|
||||
|
||||
given(key) {
|
||||
when (nil) { }
|
||||
when (/^([#;]|\h*$)/) { }
|
||||
when ("FULLNAME") { fullname = value }
|
||||
when ("FAVOURITEFRUIT") { favouritefruit = value }
|
||||
when ("NEEDSPEELING") { needspeeling = true }
|
||||
when ("SEEDSREMOVED") { seedsremoved = true }
|
||||
when ("OTHERFAMILY") { otherfamily = value.split(',')»strip»() }
|
||||
default { say "#{key}: unknown key" }
|
||||
}
|
||||
}
|
||||
|
||||
say "fullname = #{fullname}";
|
||||
say "favouritefruit = #{favouritefruit}";
|
||||
say "needspeeling = #{needspeeling}";
|
||||
say "seedsremoved = #{seedsremoved}";
|
||||
|
||||
otherfamily.each_kv {|i, name|
|
||||
say "otherfamily(#{i+1}) = #{name}";
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
dict := Dictionary new.
|
||||
configFile asFilename readingLinesDo:[:line |
|
||||
(line isEmpty or:[ line startsWithAnyOf:#('#' ';') ]) ifFalse:[
|
||||
s := line readStream.
|
||||
(s skipSeparators; atEnd) ifFalse:[
|
||||
|optionName values|
|
||||
optionName := s upToSeparator.
|
||||
values := (s upToEnd asCollectionOfSubstringsSeparatedBy:$,)
|
||||
collect:[:each | each withoutSeparators]
|
||||
thenSelect:[:vals | vals notEmpty].
|
||||
dict at:optionName asLowercase put:(values isEmpty
|
||||
ifTrue:[true]
|
||||
ifFalse:[
|
||||
values size == 1
|
||||
ifTrue:[values first]
|
||||
ifFalse:[values]]).
|
||||
]
|
||||
].
|
||||
]
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
dict keysAndValuesDo:[:eachOption :eachValue |
|
||||
someObject
|
||||
perform:(eachOption,':') asSymbol with:eachValue
|
||||
ifNotUnderstood: [ self error: 'unknown option: ', eachOption ]
|
||||
]
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
fullname := dict at: 'fullname' ifAbsent:false.
|
||||
needspeeling := dict at: 'needspeeling' ifAbsent:false.
|
||||
favouritefruit := dict at: 'favouritefruit' ifAbsent:false.
|
||||
otherfamily := dict at: 'otherfamily' ifAbsent:false.
|
||||
seedsremoved := dict at: 'seedsremoved' ifAbsent:false.
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
@(collect)
|
||||
@ (cases)
|
||||
#@/.*/
|
||||
@ (or)
|
||||
;@/.*/
|
||||
@ (or)
|
||||
@{IDENT /[A-Z_][A-Z_0-9]+/}@/ */
|
||||
@(bind VAL ("true"))
|
||||
@ (or)
|
||||
@{IDENT /[A-Z_][A-Z_0-9]+/}@(coll)@/ */@{VAL /[^,]+/}@/ */@(end)
|
||||
@ (or)
|
||||
@{IDENT /[A-Z_][A-Z_0-9]+/}@(coll)@/ */@{VAL /[^, ]+/}@/,? */@(end)
|
||||
@(flatten VAL)
|
||||
@ (or)
|
||||
@/ */
|
||||
@ (or)
|
||||
@ (throw error "bad configuration syntax")
|
||||
@ (end)
|
||||
@(end)
|
||||
@(output)
|
||||
@ (repeat)
|
||||
@IDENT = @(rep)@VAL, @(first){ @VAL, @(last)@VAL };@(single)@VAL;@(end)
|
||||
@ (end)
|
||||
@(end)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
proc readConfig {filename {defaults {}}} {
|
||||
global cfg
|
||||
# Read the file in
|
||||
set f [open $filename]
|
||||
set contents [read $f]
|
||||
close $f
|
||||
# Set up the defaults, if supplied
|
||||
foreach {var defaultValue} $defaults {
|
||||
set cfg($var) $defaultValue
|
||||
}
|
||||
# Parse the file's contents
|
||||
foreach line [split $contents "\n"] {
|
||||
set line [string trim $line]
|
||||
# Skip comments
|
||||
if {[string match "#*" $line] || [string match ";*" $line]} continue
|
||||
# Skip blanks
|
||||
if {$line eq ""} continue
|
||||
|
||||
if {[regexp {^\w+$} $line]} {
|
||||
# Boolean case
|
||||
set cfg([string tolower $line]) true
|
||||
} elseif {[regexp {^(\w+)\s+([^,]+)$} $line -> var value]} {
|
||||
# Simple value case
|
||||
set cfg([string tolower $var]) $value
|
||||
} elseif {[regexp {^(\w+)\s+(.+)$} $line -> var listValue]} {
|
||||
# List value case
|
||||
set cfg([string tolower $var]) {}
|
||||
foreach value [split $listValue ","] {
|
||||
lappend cfg([string tolower $var]) [string trim $value]
|
||||
}
|
||||
} else {
|
||||
error "malformatted config file: $filename"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Need to supply some default values due to config file grammar ambiguities
|
||||
readConfig "fruit.cfg" {
|
||||
needspeeling false
|
||||
seedsremoved false
|
||||
}
|
||||
puts "Full name: $cfg(fullname)"
|
||||
puts "Favourite: $cfg(favouritefruit)"
|
||||
puts "Peeling? $cfg(needspeeling)"
|
||||
puts "Unseeded? $cfg(seedsremoved)"
|
||||
puts "Family: $cfg(otherfamily)"
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
readconfig() (
|
||||
# redirect stdin to read from the given filename
|
||||
exec 0<"$1"
|
||||
|
||||
declare -l varname
|
||||
while IFS=$' =\t' read -ra words; do
|
||||
# is it a comment or blank line?
|
||||
if [[ ${#words[@]} -eq 0 || ${words[0]} == ["#;"]* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# get the variable name
|
||||
varname=${words[0]}
|
||||
|
||||
# split all the other words by comma
|
||||
value="${words[*]:1}"
|
||||
oldIFS=$IFS IFS=,
|
||||
values=( $value )
|
||||
IFS=$oldIFS
|
||||
|
||||
# assign the other words to a "scalar" variable or array
|
||||
case ${#values[@]} in
|
||||
0) printf '%s=true\n' "$varname" ;;
|
||||
1) printf '%s=%q\n' "$varname" "${values[0]}" ;;
|
||||
*) n=0
|
||||
for value in "${values[@]}"; do
|
||||
value=${value# }
|
||||
printf '%s[%d]=%q\n' "$varname" $((n++)) "${value% }"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
)
|
||||
|
||||
# parse the config file and evaluate the output in the current shell
|
||||
source <( readconfig config.file )
|
||||
|
||||
echo "fullname = $fullname"
|
||||
echo "favouritefruit = $favouritefruit"
|
||||
echo "needspeeling = $needspeeling"
|
||||
echo "seedsremoved = $seedsremoved"
|
||||
for i in "${!otherfamily[@]}"; do
|
||||
echo "otherfamily[$i] = ${otherfamily[i]}"
|
||||
done
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
Set ofso = CreateObject("Scripting.FileSystemObject")
|
||||
Set config = ofso.OpenTextFile(ofso.GetParentFolderName(WScript.ScriptFullName)&"\config.txt",1)
|
||||
|
||||
config_out = ""
|
||||
|
||||
Do Until config.AtEndOfStream
|
||||
line = config.ReadLine
|
||||
If Left(line,1) <> "#" And Len(line) <> 0 Then
|
||||
config_out = config_out & parse_var(line) & vbCrLf
|
||||
End If
|
||||
Loop
|
||||
|
||||
WScript.Echo config_out
|
||||
|
||||
Function parse_var(s)
|
||||
'boolean false
|
||||
If InStr(s,";") Then
|
||||
parse_var = Mid(s,InStr(1,s,";")+2,Len(s)-InStr(1,s,";")+2) & " = FALSE"
|
||||
'boolean true
|
||||
ElseIf UBound(Split(s," ")) = 0 Then
|
||||
parse_var = s & " = TRUE"
|
||||
'multiple parameters
|
||||
ElseIf InStr(s,",") Then
|
||||
var = Left(s,InStr(1,s," ")-1)
|
||||
params = Split(Mid(s,InStr(1,s," ")+1,Len(s)-InStr(1,s," ")+1),",")
|
||||
n = 1 : tmp = ""
|
||||
For i = 0 To UBound(params)
|
||||
parse_var = parse_var & var & "(" & n & ") = " & LTrim(params(i)) & vbCrLf
|
||||
n = n + 1
|
||||
Next
|
||||
'single var and paramater
|
||||
Else
|
||||
parse_var = Left(s,InStr(1,s," ")-1) & " = " & Mid(s,InStr(1,s," ")+1,Len(s)-InStr(1,s," ")+1)
|
||||
End If
|
||||
End Function
|
||||
|
||||
config.Close
|
||||
Set ofso = Nothing
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#11 = 0 // needspeeling = FALSE
|
||||
#12 = 0 // seedsremoved = FALSE
|
||||
Reg_Empty(21) // fullname
|
||||
Reg_Empty(22) // favouritefruit
|
||||
Reg_Empty(23) // otherfamily
|
||||
|
||||
File_Open("|(PATH_ONLY)\example.cfg")
|
||||
|
||||
if (Search("|<FULLNAME|s", BEGIN+ADVANCE+NOERR)) {
|
||||
Match("=", ADVANCE) // skip optional '='
|
||||
Reg_Copy_Block(21, CP, EOL_pos)
|
||||
}
|
||||
if (Search("|<FAVOURITEFRUIT|s", BEGIN+ADVANCE+NOERR)) {
|
||||
Match("=", ADVANCE)
|
||||
Reg_Copy_Block(22, CP, EOL_pos)
|
||||
}
|
||||
if (Search("|<OTHERFAMILY|s", BEGIN+ADVANCE+NOERR)) {
|
||||
Match("=", ADVANCE)
|
||||
Reg_Copy_Block(23, CP, EOL_pos)
|
||||
}
|
||||
if (Search("|<NEEDSPEELING|s", BEGIN+ADVANCE+NOERR)) {
|
||||
#11 = 1
|
||||
}
|
||||
if (Search("|<SEEDSREMOVED|s", BEGIN+ADVANCE+NOERR)) {
|
||||
#12 = 1
|
||||
}
|
||||
|
||||
Buf_Quit(OK) // close .cfg file
|
||||
|
||||
// Display the variables
|
||||
Message("needspeeling = ") Num_Type(#11, LEFT)
|
||||
Message("seedsremoved = ") Num_Type(#12, LEFT)
|
||||
Message("fullname = ") Reg_Type(21) TN
|
||||
Message("favouritefruit = ") Reg_Type(22) TN
|
||||
Message("otherfamily = ") Reg_Type(23) TN
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue