These functions dont physically move up or down a directory tree. They merely manipulate the directory string. The directory, or a file attached to the directory string, can then be opened at the desired level.
I had to make a small fix as it turns out SuperBASIC(?) barfs at the variable name sub$! I also took the oportunity to remove a reference to DMEDIUM_NAME$ as it didnt help much and made the routine incompatible with SuperBASIC.
Although the behaviour of truncating directory names to the first valid directory level is not documented anywhere (AFAIK) it has been the standard across all QL and SMSQ/E DDDs written by Tony Tebby, and has been adopted by most other implementors of such drivers, such as QPC2's DOS device and SMSQmulator's NFA and SFA devices. Q-emulator has had a recent update (V3.22) to ensure this quirk is replicated there too. So I think that by now, we could consider this behaviour a settled standard!
This version is a slight tweak on the previous DirUp/DirDn, and also adds the AddUnder$ routine. AddUnder$ is simple enough to do in-line, but I find myself re-writing it so often I thought I might as well just add it to the library.
10 CLS 12 d$ = 'abcdefghi': dir$ = 'ram1_' 14 : 16 FOR i = 1 TO LEN(d$) 18 dir$ = DirDn$(dir$, d$(i)) 20 PRINT 'Creating'! dir$ 22 MAKE_DIR dir$ 24 END FOR i 26 : 28 d$ = dir$ 30 dir$ = dir$ & 'test_bas' 32 PRINT 'Saving'! dir$ 34 SAVE dir$ 36 : 38 PRINT 'Press a key to coninue' 40 BEEP 1999, 2: PAUSE 42 : 44 dir$ = d$ & 'test_bas' 46 PRINT 'Deleting'! dir$ 48 DELETE dir$ 50 REPeat loop 52 dir$ = d$ 54 d$ = DirUp$(dir$) 56 PRINT 'Deleting'! dir$ 58 IF LEN(dir$) = 5: EXIT loop 60 DELETE dir$ 62 END REPeat loop 64 PRINT 'Done!' 66 : 68 : 100 rem + ------------------------------------------------------------------------ + 102 rem |< Dir Up >| 104 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 106 rem | "Move" up one directory level | 108 rem | | 110 rem | This routine requires dir$ to contain a valid, existing, directory. | 112 rem | It will ignore any file name appended to the given directory. | 114 rem | If dir$ is not a valid directory it is returned unchanged, ie a DATAD$ | 116 rem | fallback is not accepted. | 118 rem | | 120 rem | Note: Relies on an undocumented quirk of the filing system that, AFAIK, | 122 rem | is replicated across all mainstream systems. | 124 rem + ------------------------------------------------------------------------ + 126 rem | V0.01, pjw, 2001 Mar 04 | 128 rem | V0.04, pjw, 2019 Aug 04, SuperBASIC compatibility restored | 130 rem | V0.05, pjw, 2021 Jul 21, more granular error checking | 132 rem + ------------------------------------------------------------------------ + 134 : 136 DEFine FuNction DirUp$(dir$) 138 LOCal ch, l%, dr$(36), dv$(5) 140 l% = LEN(dir$) 142 SELect ON l% 144 = 0 TO 4: RETurn '': rem Not valid: Error 146 = 5: RETurn dir$: rem Top level: Doesnt move 148 END SELect 150 : 152 dv$ = dir$(1 TO 5) 154 ch = FOP_DIR(dir$): IF ch < 0: RETurn '': rem Invalid spec: Error 156 dr$ = FNAME$(#ch): CLOSE#ch 158 l% = LEN(dr$) - 1: IF l% < 0: RETurn dv$ 160 ch = FOP_DIR(dv$ & dr$(1 TO l%)) 162 dr$ = FNAME$(#ch): CLOSE#ch 164 IF LEN(dr$) = 0: RETurn dv$ 166 RETurn dv$ & dr$ & '_' 168 END DEFine DirUp$ 170 : 172 rem + ------------------------------------------------------------------------ + 174 rem |< Dir Down >| 176 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 178 rem | "Move" down one directory level | 180 rem | | 182 rem | Does not check whether directory exists or max name length exceeded. | 184 rem | Always returns trailing underscore. | 186 rem + ------------------------------------------------------------------------ + 188 rem | V0.01, pjw, 2019 Mar 28, Based on earlier models | 190 rem | V0.02, pjw, 2019 Aug 04, SuperBASIC (JS) doesnt like sub$? | 192 rem | V0.03, pjw, 2021 Jul 21, Dependency: AddUnder$ | 194 rem + ------------------------------------------------------------------------ + 196 : 198 DEFine FuNction DirDn$(dir$, subd$) 200 IF LEN(dir$) < 5: RETurn '' 202 IF LEN(subd$) = 0: RETurn AddUnder$(dir$) 204 RETurn AddUnder$(dir$) & AddUnder$(subd$) 206 END DEFine DirDn$ 208 : 210 : 212 rem + ------------------------------------------------------------------------ + 214 rem |< AddUnder$ >| 216 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 218 rem | Add an underscore to a directory string if it hasnt got one already | 220 rem | | 222 rem | No validity check on string! | 224 rem + ------------------------------------------------------------------------ + 226 rem | V0.01, pjw, 2021 Jul 21 | 228 rem + ------------------------------------------------------------------------ + 230 : 232 DEFine FuNction AddUnder$(dr$) 234 IF dr$(LEN(dr$)) = '_': RETurn dr$ 236 RETurn dr$ & '_' 238 END DEFine AddUnder$ 240 : 242 :