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: AustraliaPosts: 265 |
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: AustraliaPosts: 447 |
Excellent work Exactly what was needed. Will help eliminate all usages of the DATA statement in programs. VK4MU MicroController Units |
||||
shoebuckle Senior Member Joined: 21/01/2012 Location: AustraliaPosts: 189 |
James, Is this sufficiently mature to go in MMLib? Hugh |
||||
James_From_Canb Senior Member Joined: 19/06/2011 Location: AustraliaPosts: 265 |
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: ThailandPosts: 2209 |
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: AustraliaPosts: 265 |
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 |