A SuperBASIC OPEN_OVER() Function Working with TKII Default Directory

Anything QL Software or Programming Related.
Post Reply
User avatar
ql_freak
Gold Card
Posts: 479
Joined: Sun Jan 18, 2015 1:29 am

A SuperBASIC OPEN_OVER() Function Working with TKII Default Directory

Post by ql_freak »

The TKII defaults are the horror of horrors for a programmer (but of course superb when using SB as command shell).

I wanted a function which "opens over" a file. If it's not yet existing create it, else delete it (e.g. UQLX does not support overwriting files) and open it new.

It's not so easy, as I first have thought, because of the defaults (DATAD$) of SuperToolkit II. Albeit the following function has only 3 real lines of code, it took me a few hours of making it bullet proof. At least if only one program runs. If it runs in multitasking it still may go wrong, cause the QDOS sheduler may interrupt a BASIC program at any time and if another program creates the just deleted fnam$ after line 20220 (EDIT: Was2020) and creates a new one, the function will (of course) fail. Well live is full of risk and always ends with death.

This function ignores DATAD$. If not a fully qualified pathname, e.g. 'FLP1_filename' ('filename' alone is not a fully qualified filename) this function returns "bad parameter" (-15).

Albeit my function seems to work as expected, I think I will write a SuperBASIC Open-function, which will always ignore the TKII default directories. I wonder, why no one else has yet written such a function (and test function if pathname exists, and if it exists, is it a file or a directory [file type 255]). As I have now detected George Gwilts excellent Assembler gass, this would be a good chance to test it (I normally use QMAC, the Quanta version).

Code: Select all

20000 REMark Library functions
20010 REMark Required: SuperToolkit II, TurboToolkit
20040 :
20080 DEFine FuNction hps_openOver%(c%,fnam$):REMark Opens device for writing
20090   REMark If it's a file (filename) which already exists it will first be
20100   REMark deleted before the file is opened new (with fop_new(). If the file
20110   REMark could not be opened for read/write, an error is returned
20120   REMark The arguments (parameters) are not altered by the function
20130   REMark W A R N I N G : fnam$ must be a fully qualified name (no default from
20140   REMark SuperToolkit II, e.g. DATAD$ is added before fnam$)! If not a fully
20150   REMark qualified filename, error "bad parameter" (-15) is returned.
20160   REMark Note: File is not really opened with FOP_OVER but it's deleted and
20170   REMark then opened with FOP_NEW(). This means it also will work on UQLX
20180   REMark which does NOT support OPEN_OVER
20190 :
20220   IF DEVICE_STATUS(0,fnam$)>=0:DELETE fnam$
20260   IF DEVICE_STATUS(1,DATAD$&fnam$)>=0:RETurn -15:REMark A fully qualified
20300   REMark filename must be passed to this function!
20340   RETurn FOP_NEW(#c%,fnam$)
20380 END DEFine :REMark hps_openOver()


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
tofro
Font of All Knowledge
Posts: 3071
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: A SuperBASIC OPEN_OVER() Function Working with TKII Default Directory

Post by tofro »

Note your code seems to ignore possible "IN USE" errors that might occur when the file exists but is currently open by another job. This could make your program fall over in the DELETE in line 20220. I don't see a way to catch this properly without a WHEN ERRor clause somewhere in your program.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Derek_Stewart
Font of All Knowledge
Posts: 4663
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: A SuperBASIC OPEN_OVER() Function Working with TKII Default Directory

Post by Derek_Stewart »

Hi,

I just use the Toolkit 2 or SMSQ/E, "FTEST" to see if there is an existing file and "FOP_OVER" function to a create new file when an existing file is already present in the default data DATAD$ directory, defined by DATA_USE.

For example:

IF FTEST("log_file_txt")=0 : chan = FOP_OVER("log_file_txt")

If not there:

IF FTEST("log_file_txt")=-7 : chan = FOP_NEW("log_file_txt")


Regards,

Derek
User avatar
RalfR
QL Wafer Drive
Posts: 1177
Joined: Fri Jun 15, 2018 8:58 pm

Re: A SuperBASIC OPEN_OVER() Function Working with TKII Default Directory

Post by RalfR »

After what feels like 40 years, Marcel has removed this strange feature of TK2 with the default directories.

Previously, if a file was not found, TK2 always put the default directory first and searched again. This then led to such strange names as "win1_flp1_test_bas" if "flp1_test_bas" was not found and "win1_" was the default directory.

Now it checks whether the search name contains an existing drive and if so, the search is aborted if the file does not exist.

In my opinion, this is the first time that "FTEST" can be used properly.


7000 4E75
User avatar
ql_freak
Gold Card
Posts: 479
Joined: Sun Jan 18, 2015 1:29 am

Re: A SuperBASIC OPEN_OVER() Function Working with TKII Default Directory

Post by ql_freak »

tofro wrote: Tue Feb 04, 2025 8:03 am Note your code seems to ignore possible "IN USE" errors that might occur when the file exists but is currently open by another job. This could make your program fall over in the DELETE in line 20220. I don't see a way to catch this properly without a WHEN ERRor clause somewhere in your program.
Nope, it seems (except of the multitasking problem) really bulletproof, see the test program at bottom of this message. Albeit it may be, that it opens a file, when a none fully qualified pathname was passed to the function. This (I think) could happen, if the filename passed, exists on the default (DATAD$) directory.

As I have written, I think I will write a machine code OPEN function for developers which ignores the defaults, and I think a DELETE function ignoring the defaults is also needed. This would IMHO make the life a lot easier for developers.
RalfR wrote: Tue Feb 04, 2025 1:27 pm After what feels like 40 years, Marcel has removed this strange feature of TK2 with the default directories.

Previously, if a file was not found, TK2 always put the default directory first and searched again. This then led to such strange names as "win1_flp1_test_bas" if "flp1_test_bas" was not found and "win1_" was the default directory.

Now it checks whether the search name contains an existing drive and if so, the search is aborted if the file does not exist.

In my opinion, this is the first time that "FTEST" can be used properly.
That's interesting. Is there a standalone version of TKII or is it just implemented in SMSQ/E? If there is a standalone version I could additionally use ftest to return a (bulletproof) error, if a none fully qualified pathname has been passed to the function.


Code: Select all

100 REMark GO TO 32759 is used instead of STOP, which may have problems on some VER$
990 :
1000 REMark Tests for SB-Function hps_openOver%()
1040 :
1050 long16_777_216$='16777216':l16777216=long16_777_216$
1080 DNAM$='RAM1_':REMark constant of pathname
1090 FNAM$=DNAM$&'DELETE_ME':REMark constant of pathname of file to test
1120 :
1160 c%=4:o%=1:REMark c%: channel no. for hps_openOver%(), o%: output channel
1170 t%=5:REMark Another test channel when opening FNAM$
1200 d%=2:REMark Channel for listing directory DNAM$
1210 CLS#o%:CLS#d%:CLOSE#c%:CLOSE#t%
1240 :
1260 PRINT#o%,"YOU MUST ENTER 'A' when prompted!":WDEL#o%,DNAM$:CLS#o%
1270 REMark rorre=DEVICE_STATUS(2,FNAM$):IF rorre<0:PRINT'FATAL'!'rorre='!rorre!', have you not typed A or a before?':GO TO 32759
1280 DIR#d%,DNAM$:err%=hps_openOver%(c%,FNAM$):CLOSE#c%
1320 IF err%<0:PRINT#o%,'Oops (1), file does not exist but open failed':ELSE DELETE FNAM$:PRINT#o%,'Test 1 passed'
1360 IF FOP_NEW(#t%,FNAM$):PRINT#o%,'FATAL: Cannot open ';FNAM$:GO TO 32759
1400 PRINT#t%,'Dummy test file, may be deleted':REMark FNAM$ now open for writing!
1440 DIR#d%,DNAM$:err%=hps_openOver%(c%,FNAM$)
1480 IF err%>=0:PRINT#o%,'Oops (2), "in use" file could be opened':CLOSE#c%
1520 IF err%<0:PRINT#o%,'(Expected!) Error'!err%!'opening'\'    ';FNAM$;'.'\'Test 2 passed'
1560 CLOSE#t%:IF err%>=0:GO TO 32759
1600 DIR#d%,DNAM$:err%=hps_openOver%(c%,FNAM$)
1640 IF err%<0
1650   PRINT#o%,'Cannot open'!FNAM$!'. Note:'!'This may be'\"OK if filename doesn't start with a device"\'Test 2 probably passed'
1660 ELSE
1720   CLOSE#c%
1760   IF FLEN(\FNAM$)<>0
1800     PRINT#o%,'Oops'!FNAM$!'is not empty'
1840   ELSE
1880     PRINT#o%,'Test 3 passed'
1920   END IF
1980 END IF
2020 DELETE FNAM$:err%=hps_openOver%(c%,FNAM$)
2060 IF err%<0
2100   PRINT#o%,'Oops (4), cannot open'!FNAM$
2140   IF DEVICE_STATUS(1,FNAM$)>=0 OR FTEST(FNAM$)<>-7:PRINT#o%,'NOTE: "';FNAM$;'" or "';DATAD$&FNAM$;'"'!"exists but it shouldn't"
2180 ELSE
2220   PRINT#o%,'Test 4 passed'
2260 END IF
2300 CLOSE#c%
9990 :
9999 CLOSE#c%:PRINT#o%,'DATAD$=';DATAD$:GO TO 32759
19980 :
19990 :
20000 REMark Library functions
20010 REMark Required: SuperToolkit II, TurboToolkit
20040 :
20080 DEFine FuNction hps_openOver%(c%,FNAM$):REMark Opens device for writing
20090   REMark If it's a file (filename) which already exists it will first be
20100   REMark deleted before the file is opened new (with fop_new(). If the file
20110   REMark could not be opened for read/write, an error is returned
20120   REMark The arguments (parameters) are not altered by the function
20130   REMark W A R N I N G : fnam$ must be a fully qualified name (no default from
20140   REMark SuperToolkit II, e.g. DATAD$ is added before fnam$)! If not a fully
20150   REMark qualified filename, error "bad parameter" (-15) is returned.
20160   REMark Note: File is not really opened with FOP_OVER but it's deleted and
20170   REMark then opened with FOP_NEW(). This means it also will work on UQLX
20180   REMark which does NOT support OPEN_OVER
20190 :
20220   IF DEVICE_STATUS(0,FNAM$)>=0:DELETE FNAM$
20260   IF DEVICE_STATUS(1,DATAD$&FNAM$)>=0:RETurn -15:REMark A fully qualified
20300   REMark filename must be passed to this function!
20340   RETurn FOP_NEW(#c%,FNAM$)
20380 END DEFine :REMark hps_openOver()
32757 :
32758 REMark Use GO TO 32759 instead of STOP. STOP may not work on all ROM versions!)
32759 REMark END OF PROGRAM (NO LINES MUST follow, some ROMs may not allow line numbers >= 32760!


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
Post Reply