LB Booster
Programming >> Liberty BASIC language >> Random Access Procedures
http://lbb.conforums.com/index.cgi?board=lblang&action=display&num=1445371698

Random Access Procedures
Post by joker on Oct 20th, 2015, 8:08pm

Relating to my effort at creating my library of procedures relative to random access files, this question comes to mind.

Does one procedure (SUB, GOSUB, or FUNCTION) have precedence over another?

I tend to lean towards a procedure that doesn't surrender control until it is finished for file operations, but I don't know much about how Windows handles those processes.
Re: Random Access Procedures
Post by Richard Russell on Oct 20th, 2015, 8:48pm

on Oct 20th, 2015, 8:08pm, pnlawrence wrote:
Does one procedure (SUB, GOSUB, or FUNCTION) have precedence over another?

I'm not sure what you mean by 'precedence' in this context, can you give an example? GOSUBs should probably be avoided in a 'modern' program.

Richard.
Re: Random Access Procedures
Post by joker on Oct 20th, 2015, 9:08pm

Sorry, I'm thinking "preference" and write "precedence."

I'm thinking something like FileExists is a function where as OpenFile is a sub.
Re: Random Access Procedures
Post by Richard Russell on Oct 20th, 2015, 9:31pm

on Oct 20th, 2015, 9:08pm, pnlawrence wrote:
I'm thinking something like FileExists is a function where as OpenFile is a sub.

Because LB/LBB supports byref parameters, that is to say that both SUBs and FUNCTIONs can return values to the calling code, the choice of which to use is not always clear cut. A common recommendation is that if a single value (numeric or string) is returned then a FUNCTION is the best choice, but when zero or two or more values are returned then use a SUB.

But there can be circumstances when it makes sense to ignore that recommendation. SUBs and FUNCTIONs are substantially identical 'under the hood'; use whichever makes the program easier to write and easier to understand.

Richard.
Re: Random Access Procedures
Post by joker on Oct 20th, 2015, 9:59pm

I always liked the form ... n = function(a,b) .



I'm going to keep busy with this list:

Code:
' Random Access File Library Procedures
'From "somewhere"
'Verify ODBC Version
'Create DB
'Create Table
'Delete Table
'Verify DB / Table Existance (and count number / verify name so that they can be re-created if missing)
'Add record
'Delete Record
'Previous Record
'Next Record
'Compact Records (DB)
'Insert Field
'Delete Field
'Cross Reference Records Between Tables
'Query (and or Search) Tables
'Back Up DB
'Restore DB (from back up)
'Then there are activities such as:
'Read data from table
'Save data to table
'Edit data in field
'Save edited field
'Delete data from field 

'From justbasic.wikispaces.com "UncleBen" Random access files with arrays
'OpenRAF sub
'CloseRAF sub
'PutRAFrecord function
'GetRAFrecord function
'FindRAFrecord function
'GetRAFfield function
'PutRAFfield function
'EraseRAFrecord function
'FindEmptyRAFrecord function
'FitFieldRAFrecord function
 

Re: Random Access Procedures
Post by joker on Oct 21st, 2015, 02:34am

Now I know why no one has built a "standard" library for RAF.

Code:
OPEN "HeadsOfState.dat" for RANDOM as #1 LEN = 70 


"LEN" has to be fed a literal value. :-/

Stymied before starting.

Not completely, but on with the next one.
Re: Random Access Procedures
Post by Richard Russell on Oct 21st, 2015, 08:32am

on Oct 21st, 2015, 02:34am, pnlawrence wrote:
"LEN" has to be fed a literal value. :-/

I don't believe that's true (in LBB). I tried this code in LBB v3.03 and it appears to work correctly as far as I can tell:

Code:
    reclen = 70
    OPEN "HeadsOfState.dat" for RANDOM as #1 LEN = reclen 

I entirely agree that accepting only a literal value as the length (LB 4.04 and LB 4.5.0: I'm looking at you!) would make it very difficult to write a library routine for opening a RAF database. Another LB shortcoming fixed in LBB!

Richard.

Re: Random Access Procedures
Post by joker on Oct 21st, 2015, 09:22am

As the cartoon guy says, "WooHoo!" smiley

I learned a valuable lesson. Test with the whole package. Never forget to test with LBB!
Re: Random Access Procedures
Post by Richard Russell on Oct 21st, 2015, 1:25pm

on Oct 21st, 2015, 08:32am, Richard Russell wrote:
Another LB shortcoming fixed in LBB!

A quick test indicates that not only does LB require a literal value for the record length in the OPEN statement, but has the same restriction for the individual field lengths in the FIELD statement. Again, LBB has no such limitation:

Code:
    reclen = 70
    OPEN "HeadsOfState.dat" for RANDOM as #1 LEN = reclen 
    FIELD #1, reclen/2 AS Field1$, reclen/2 AS Field2$ 

(In all fairness it has to be admitted that LBB imposes a limit of 8 concurrently open random files, whereas LB has no such restriction, so it's not entirely one-sided).

Richard.

Re: Random Access Procedures
Post by joker on Oct 22nd, 2015, 2:40pm

So, am I barking up the wrong tree and going to find out after I build a lot of stuff? I'd like to know the chances of success now! ;D

Code:
function(OpenRAF path$, filename$, fileHandle$, recordLen)
    ' file must exist?
    open filename$ for random as #fileHandle$ len = recordLen ' open and define record
end function
 
sub CloseRAF fileHandle$
    close #fileHandle$
end sub

function fileExists(path$, filename$)
    'dimension the array info$( at the beginning of your program
    'dim info$(10, 10)
    'if fileExists(DefaultDir$, "users.dat") then
    files path$, filename$, info$()
    fileExists = val(info$(0, 0)) 'non zero is true
end function

function SetRAFfields(fileHandle$, recordLen)
    'field lengths and field names have to be modified per program
    'call after OpenRAF
    'set the fields in RAF
    if (1+2+3+4) = recordLen then ' something to make one think about field lengths
        field #fileHandle$,_
            1 as field1$,_
            2 as field2$,_
            3 as field3$,_
            4 as field4$
        SetRAFfields = 0
    else
        SetRAFfields = 1 ' error condition
    endif
end function     
 

Re: Random Access Procedures
Post by Richard Russell on Oct 22nd, 2015, 10:10pm

on Oct 22nd, 2015, 2:40pm, pnlawrence wrote:
Code:
    open filename$ for random as #fileHandle$ len = recordLen 

That doesn't work (even in LBB!), you must use MAPHANDLE:

Code:
    open filename$ for random as #1 len = recordLen
    maphandle #1, fileHandle$ 

Richard.

Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 10:45am

Funny how the brain works! "#fileHandle$" has shown up in some of my searches, but not in that form.

I should have used/assumed the form fileHandle$ = "#" + {path} + fileName$.

Being generic is getting more difficult. I'm starting to wonder if its worth the time for my project.
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 11:04am

Curses! That won't work either. Missing "#" in OPEN.
Re: Random Access Procedures
Post by Richard Russell on Oct 23rd, 2015, 11:21am

on Oct 23rd, 2015, 11:04am, pnlawrence wrote:
Curses! That won't work either. Missing "#" in OPEN.

The code I listed does work - I tested it before posting as I always try to do. Here's the entire earlier demo from the 'Numeric field length RAF' thread modified to use a handle variable to prove that it can be done (in LBB):

Code:
    handle$ = "#MyFileHandle" ' the handle variable

    field1 = 1/3
    field2 = 1/3

    open "test.raf" for random as #1 len = 20
    maphandle #1, handle$
    field #handle$, 6 as field1, 14 as field2
    put #handle$, 1
    close #handle$

    open "test.raf" for random as #2 len = 20
    maphandle #2, handle$
    field #handle$, 6 as field1$, 14 as field2$
    get #handle$, 1
    close #handle$

    print chr$(34);field1$;chr$(34)
    print chr$(34);field2$;chr$(34) 

This doesn't work in LB 4.04 or 4.5.0 so without LBB you really would be screwed.

Richard.
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 11:29am

Thanks, Richard. I am studying every word you write.

This "library" seems to pass the RUN test (no program), but with an "incompatibility" error message.

EDIT: Well, of course it doesn't "RUN", because it has an "ERROR". The error message implies that it was somehow corrected, but there's no output.

Code:
function OpenRAF(path$, filename$, fileHandle$, recordLen)
    ' file must exist?
    open filename$ for random as #fileHandle$ len = recordLen ' open and define record
end function
 
sub CloseRAF fileHandle$
    close #fileHandle$
end sub

function fileExists(path$, filename$)
    'dimension the array info$( at the beginning of your program
    'dim info$(10, 10)
    'if fileExists(DefaultDir$, "users.dat") then
    files path$, filename$, info$()
    fileExists = val(info$(0, 0)) 'non zero is true
end function

function setRAFfields(fileHandle$, recordLen)
    'field lengths and field names have to be modified per program
    'call after OpenRAF
    'set the fields in RAF
    if (1+2+3+4) = recordLen then ' something to make one think about field lengths
        field #fileHandle$,_
            1 as field1$,_
            2 as field2$,_
            3 as field3$,_
            4 as field4$
        SetRAFfields = 0
    else
        SetRAFfields = 1 ' error condition
    endif
end function                    
 

Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 11:32am

Let me paraphrase your comment ...

Quote:
... without LBB you really would be screwed.


Without LBB you really are screwed!
Re: Random Access Procedures
Post by Richard Russell on Oct 23rd, 2015, 1:07pm

on Oct 23rd, 2015, 11:29am, pnlawrence wrote:
I am studying every word you write.

Apparently not acting upon however! :-)

Quote:
This "library" seems to pass the RUN test (no program), but with an "incompatibility" error message.

It still includes the line that doesn't work (either in LB or LBB):

Code:
    open filename$ for random as #fileHandle$ len = recordLen ' open and define record 

I have twice listed the correct code, but for some reason you have failed to incorporate it.

You also have an endif where you meant end if.

Richard.

Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 7:19pm

At the risk of antagonizing Richard even further ... :D ... I do like to find the edges of proper operation.

LB reports a syntax error in the open line and LBB just says "Mistake!"

EDIT: Adding the "result =" bit-bucket for the FUNCTION makes the compilers happy.


Code:
path$ = ""
fileName$ = "myfile.txt"
fileHandle$ = "#file1"
recordLen = 10
field1$ = "1234"
field2$ = "1234"
field3$ = "1234"
field4$ = "1234"

' EDIT: openRAF(path$,fileName$,fileHandle$,recordLen)
result = openRAF(path$,fileName$,fileHandle$,recordLen)

put #fileHandle$, 1

call closeRAF fileHandle$

field1$ = ""
field2$ = ""
field3$ = ""
field4$ = ""

'EDIT: openRAF(path$,fileName$,fileHandle$,recordLen)
result = openRAF(path$,fileName$,fileHandle$,recordLen)

get #fileHandle$, 1

call closeRAF fileHandle$

print "1:  "; field1$
print "2:  "; field2$
print "3:  "; field3$
print "4:  "; field4$

end

sub closeRAF fileHandle$
    close #fileHandle$
end sub

function fileExists(path$, filename$)
    ' dimension the array info$( at beginning of program
    ' dim info$(10, 10)
    ' e.g. if fileExists(DefaultDir$, "users.dat") then
    files path$, filename$, info$()
    fileExists = val(info$(0, 0)) 'non zero is true
end function

function openRAF(path$, filename$, fileHandle$, recordLen)
    ' file must exist?
    ' fileExists(path$, filename$)
    ' fileHandle$ = "#yourFileHandle"
    open filename$ for random as #1 len = recordLen ' open and define record
    maphandle #1, fileHandle$
    openRAF = setRAFfields(fileHandle$, recordLen)
end function

function setRAFfields(fileHandle$, recordLen)
    'field lengths and field names have to be modified per program
    'call after openRAF
    'set the fields in RAF
    if (1+2+3+4) = recordLen then ' something to make one think about field lengths
        field #fileHandle$,_
            1 as field1$,_
            2 as field2$,_
            3 as field3$,_
            4 as field4$
        setRAFfields = 0
    else
        setRAFfields = 1 ' error condition
    end if
end function        
 

Re: Random Access Procedures
Post by Richard Russell on Oct 23rd, 2015, 9:32pm

on Oct 23rd, 2015, 7:19pm, pnlawrence wrote:
LB reports a syntax error in the open line and LBB just says "Mistake!"

It may be that you have previously used another language which allows a function to be called without assigning the returned value to anything, but Liberty BASIC doesn't. If you want to call a function, but ignore the value it returns, you must assign it to something, for example:

Code:
    ignoreThis = openRAF(path$,fileName$,fileHandle$,recordLen) 

Richard.

Re: Random Access Procedures
Post by joker on Oct 24th, 2015, 09:51am

Now, there's a difference between SUB and FUNCTION that I missed. Thanks!
Re: Random Access Procedures
Post by Richard Russell on Oct 24th, 2015, 10:40am

on Oct 23rd, 2015, 9:32pm, Richard Russell wrote:
If you want to call a function, but ignore the value it returns, you must assign it to something

I occasionally use this construction, to avoid creating a dummy variable, but it's a bit ugly (and relies on a 'feature' of LB/LBB that rem and ' are not always equivalent):

Code:
    if openRAF(path$,fileName$,fileHandle$,recordLen) then rem 

Richard.