Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 08:27 27 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Routines for a Config File

Author Message
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 01:57am 07 Mar 2013
Copy link to clipboard 
Print this post

Here's a set of routines with stubs to create, open and read configuration files for your programs.

The code assumes that the configuration file will have the same name as the calling program, but with a .cfg extension instead of a .bas extension. For example, if you have a program called GPS.BAS the code will look for a configuration file called GPS.CFG.

The code works under both DOS and normal MMBasic.

I haven't added any code to read in the configuration parameters or to create the file and parameters if it doesn't exist. That's up to you.

If an error occurs while accessing the SD card, the code will look up the description of the error and display it. That code could be useful in other programs that access the SD card.

James


False = 0: True = NOT False ' you need these defined!

ReadConfigFile() ' as it would appear in your main code
END

'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''''
' Subroutine
' This subroutine reads the user preferences from the configuration
' file. If the file does not exist, it is created.
'
' We need two different ways of testing for the file's existance
' because MMBasic only returns valid Error Numbers for files on the
' A: or B: drives. It does not return a useful error number if
' the file does not exist in DOS.
'
' The Config file is the name of the calling program -.BAS +.CFG
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''''
'
Sub ReadConfigFile()

Local ConfFile$, In$

' As at the version this was written for, V4.3, the user has to specify
' the name of the program when it is run - ie RUN CONFIG or RUN CONFIG.BAS
' If no program name is specified, MM.FNAME$ returns an empty string.

if MM.FNAME$ = "" then
? "You must provide the program name when you type RUN - eg RUN CONFIG"
? "Otherwise this program will not be able to work out the name of "
? "of the associated .cfg file."
END
ENDIF

' Open the Config file if it exists. If it doesn't exist, create it.
ConfFile$ = LEFT$(MM.FNAME$, LEN(MM.FNAME$) - 4) + ".cfg" ' replace .bas with .cfg
if FileExists(ConfFile$) then

' Read in the values - allocate to global variables
? "File ";ConfFile$; " exists"
Open ConfFile$ for input as #8


Close #8
else

? "File ";ConfFile$; " does NOT exist"
Open ConfFile$ for output as #8
' Prompt for the values and create the config file. Allocate to global variables.


Close #8
endif


End Sub ' ReadConfigFile

'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Function
' Check whether a file exists.
' Returns a Boolean True or False.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Uses two different methods to check for a file's existence,
' depending on whether the code is run under DOS, or on a
' Maximite.
' I've submitted a bug report about MM.DEVICE$ returning ""
' under DOS MMBasic 4.3, and I've used a workaround that
' assumes that "" is only returned if running under DOS.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
Function fileExists(FileName$)

Local Answer$, bFileExists

if (MM.DEVICE$ = "DOS") OR (MM.DEVICE$ = "") then ' workaround for bug - see comment above.
open "exist.bat" for output as #8
Print #8, "if exist " + chr$(34) + FileName$ + chr$(34) + " ( "
Print #8, " echo YES> exist.tmp"
Print #8, ") Else ("
Print #8, " echo NO> exist.tmp"
Print #8, ")"
Print #8, "Exit"
Close #8

' Run batch that redirects DIR results to exist.tmp file.
' Redirect all messages from the batch file to nul (ie, not displayed)
SYSTEM "exist.bat > nul"

' Read the single line from exist.tmp for the answer as to whether the file exists.
Open "exist.tmp" for input as #8
Line Input #8, Answer$
bFileExists = (Answer$ <> "YES")
Close #8
KILL "exist.bat" ' and clean up
KILL "exist.tmp"
else ' running on a Maximite or similar hardware
' Turn off Abort on Error so we can capture the Error Number
Option Error Continue
Open FileName$ for Input as #8

If MM.ERRNO = 6 then ' can't find file
bFileExists = False
elseif MM.ERRNO = 0 then
bFileExists = True
CLOSE #8
else
? "ERROR: the Existence Check for file "; ConfFile$; " returned MM.ERRNO "; MM.ERRNO
? "The description of MM.ERRNO"; MM.ERRNO; " is: "; ErrNoDesc$(MM.ERRNO)
' Close #8
Option Error Abort
END
Endif
Option Error Abort
Endif

fileExists = bFileExists

End Function ' fileExists

'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Function
' Return the matching Description for an MMBasic
' Error Number.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' The descriptions were taken from the V4.3 manual.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
Function ErrNoDesc$(ErrNo)

Local Desc$

if ErrNo = 0 then
Desc$ = "No error"
elseif ErrNo = 1 then
Desc$ = "No SD card found"
elseif ErrNo = 2 then
Desc$ = "SD card is write protected"
elseif ErrNo = 3 then
Desc$ = "Not enough space"
elseif ErrNo = 4 then
Desc$ = "All root directory entries are taken"
elseif ErrNo = 5 then
Desc$ = "Invalid filename"
elseif ErrNo = 6 then
Desc$ = "Cannot find file"
elseif ErrNo = 7 then
Desc$ = "Cannot find directory"
elseif ErrNo = 8 then
Desc$ = "File is read only"
elseif ErrNo = 9 then
Desc$ = "Cannot open file"
elseif ErrNo = 10 then
Desc$ = "Error reading from file"
elseif ErrNo = 11 then
Desc$ = "Error writing to file"
elseif ErrNo = 12 then
Desc$ = "Not a file"
elseif ErrNo = 13 then
Desc$ = "Not a directory"
elseif ErrNo = 14 then
Desc$ = "Directory not empty"
elseif ErrNo = 15 then
Desc$ = "Hardware error accessing the storage media"
elseif ErrNo = 16 then
Desc$ = "Flash memory write failure"
else
Desc$ = "******** " + ErrNo + " is an invalid Error Number iaw V4.3 manual **********"
endif

ErrNoDesc$ = Desc$

End Function ' ErrNoDesc$


My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
djuqa

Guru

Joined: 23/11/2011
Location: Australia
Posts: 447
Posted: 11:41am 07 Mar 2013
Copy link to clipboard 
Print this post

Excellent work
Exactly what was needed.
Will help eliminate all usages of the DATA statement in programs.Edited by djuqa 2013-03-08
VK4MU MicroController Units

 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 12:08pm 07 Mar 2013
Copy link to clipboard 
Print this post

James,
Is this sufficiently mature to go in MMLib?
Hugh
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 01:47pm 07 Mar 2013
Copy link to clipboard 
Print this post

Hugh,

I'd like to wait a bit to see if anyone has any comments on how it could be improved, and to see if any of the workarounds are resolved in MMBasic version 4.3a. Also, I just noticed that I have the word 'of' twice in a row in warning message. So much for my proof reading.

I'll provide two versions - one with comments (maybe as a .txt file) and one without.

David,

I wrote it because of your comments about the need for a config file in my LCD.LIB. I also got tired of typing the same replies into renum.bas when I was testing it.


James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 03:16pm 07 Mar 2013
Copy link to clipboard 
Print this post

Maybe change the routine to accept a filename.
Then the routine does not require a run with a filename.
It will also allow for several config files to be used, especially handy when testing and/or have multiple valid configurations.

The change is minimal, just add a Filename$ parameter to the subroutine.
Sub ReadConfigFile(Filename$)

When Filename$ = "" then the program name can be used as a default value.

Maybe include a sample how to store configuration values.

It could be a CSV style:
[code]
Bangkok,10110
[/code]

or a key=value format which is my favorite
[code]
City=Bangkok
Postalcode=10110
[/code]

Both formats are easy to process. The key=value format adds clarity.
Processing those would be done by opening the file, reading line by line, split the line at the = position. The first part would then hold the key the second part the value.
An IF statement for each key to assign the value to the right variable.


Microblocks. Build with logic.
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 05:34am 08 Mar 2013
Copy link to clipboard 
Print this post

Thanks for the suggestions.

It's not fully tested, but I've added code to implement your suggestions. I'll wait for any further suggestions and for V4.3a to be released before I finalise it.

It's bloated out a bit - well, a lot really, but it has as many error traps as I can think of, and a fair few comments.

Further comments and suggestions welcomed.

James

2013-03-08_153259_Config.zip
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024