Pathname translation
Usually a program does not, and should not, need to know what type of filenames the underlying filing system is using. The program should accept whatever filenames the user supplies, and pass them onto the filing system. However, there are some cases where the actual filename format is needed and the program needs to be able to translate filenames.
Examples would include:
- a zipfile handler, filenames within zipfiles are defined to be Unix filenames, with "/" as directory separators and "." as extension separators.
- a program generating or receiving URLs and needing to map them to/from the local filesystem. URLs are defined to be unix filenames, with "/" as directory separators and "." as extension separators.
- a server application serving files on one platform where the client is another platform, for instance a server running on DOS/Windows serving files to a BBC client.
- extracting or manipulating "foreign" disk images where the program wants to display file information in the format the foreign system would display it.
The Filename library provides platform-independant functions for converting filenames between BBC, DOS/Windows and Unix/Zip/URL formats.
If you know that you will only be dealing with leafnames or with simply full-canonicalised pathnames, then the simpler Filename translation code can be used.
Contents
- 1 FNfn_bbctodos(file$), FNfn_bbctounix(file$), FNfn_frombbc(file$), FNfn_tobbc(file$)
- 2 FNfn_dostobbc(file$), FNfn_dostounix(file$), FNfn_fromdos(file$), FNfn_todos(file$)
- 3 FNfn_unixtobbc(file$), FNfn_unixtodos(file$), FNfn_fromunix(file$), FNfn_tounix(file$)
- 4 Technical information
- 5 Code
- 6 Requirements and Dependancies
- 7 Notes
- 8 See also
FNfn_bbctodos(file$), FNfn_bbctounix(file$), FNfn_frombbc(file$), FNfn_tobbc(file$)
These functions convert BBC filenames to other formats. FNfn_frombbc()
converts a BBC filename to the format of the local platform, FNfn_tobbc()
converts a local filename to a BBC filename; both according to the setting
of os%
.
Examples include:
FNfn_bbctodos("$.docs.letters/cv") -> \docs\letters.cv FNfn_bbctodos("^.info##") -> ..\info?? FNfn_bbctodos(":A.text.why?") -> A:\text\why# FNfn_bbctounix("$.docs.letters/cv") -> /docs/letters.cv FNfn_bbctounix("^.info##") -> ../info?? FNfn_bbctounix(":A.text.why?") -> A:/text/why#
If running on BBC/RISC OS:
FNfn_frombbc("$.docs.letters/cv") -> $.docs.letters/cv FNfn_frombbc("^.info##") -> ^.info## FNfn_frombbc(":A.text.why?") -> :A.text.why? FNfn_tobbc("$.docs.letters/cv") -> $.docs.letters/cv FNfn_tobbc("^.info##") -> ^.info## FNfn_tobbc(":A.text.why?") -> :A.text.why?
If running on DOS/Windows:
FNfn_frombbc("$.docs.letters/cv") -> \docs\letters.cv FNfn_frombbc("^.info##") -> ..\info?? FNfn_frombbc(":A.text.why?") -> A:\text\why# FNfn_tobbc("\docs\letters.cv") -> $.docs.letters/cv FNfn_tobbc("..\info??") -> ^.info## FNfn_tobbc("A:\text\why#") -> :A.text.why?
If running on UNIX:
FNfn_frombbc("$.docs.letters/cv") -> /docs/letters.cv FNfn_frombbc("^.info##") -> ../info?? FNfn_frombbc(":A.text.why?") -> A:/text/why# FNfn_tobbc("/docs/letters.cv") -> $.docs.letters/cv FNfn_tobbc("../info??") -> ^.info## FNfn_tobbc("A:/text/why#") -> :A.text.why?
FNfn_dostobbc(file$), FNfn_dostounix(file$), FNfn_fromdos(file$), FNfn_todos(file$)
These functions convert DOS/Windows filenames to other formats.
FNfn_fromdos()
converts a DOS/Windows filename to the format of the local
platform, FNfn_todos()
converts a local filename to a DOS/Windows filename;
both according to the setting of os%
.
Examples include:
FNfn_dostobbc("\docs\letters.cv") -> $.docs.letters/cv FNfn_dostobbc("..\info??") -> ^.info## FNfn_dostobbc("A:\text\why#") -> :A.text.why? FNfn_dostounix("\docs\letters.cv") -> /docs/letters.cv FNfn_dostounix("..\info??") -> ../info?? FNfn_dostounix("A:\text\why#") -> A:/text/why#
If running on BBC/RISC OS:
FNfn_fromdos("\docs\letters.cv") -> $.docs.letters/cv FNfn_fromdos("..\info??") -> ^.info## FNfn_fromdos("A:\text\why#") -> :A.text.why? FNfn_todos("$.docs.letters/cv") -> \docs\letters.cv FNfn_todos("^.info##") -> ..\info?? FNfn_todos(":A.text.why?") -> A:\text\why#
If running on DOS/Windows:
FNfn_fromdos("\docs\letters.cv") -> \docs\letters/cv FNfn_fromdos("..\info??") -> ..\info?? FNfn_fromdos("A:\text\why#") -> A:\text\why? FNfn_todos("\docs\letters.cv") -> \docs\letters.cv FNfn_todos("..\info??") -> ..\info?? FNfn_todos("A:\text\why#") -> A:\text\why#
If running on UNIX:
FNfn_fromdos("\docs\letters.cv") -> /docs/letters.cv FNfn_fromdos("..\info??") -> ../info?? FNfn_fromdos("A:\text\why#") -> A:/text/why# FNfn_todos("/docs/letters.cv") -> \docs\letters.cv FNfn_todos("../info??") -> ..\info?? FNfn_todos("A:/text/why#") -> A:\text\why#
FNfn_unixtobbc(file$), FNfn_unixtodos(file$), FNfn_fromunix(file$), FNfn_tounix(file$)
These functions convert UNIX/ZIP/URL filenames to other formats.
FNfn_fromunix()
converts a UNIX/ZIP/URL filename to the format of the local
platform, FNfn_tounix()
converts a local filename to a UNIX/ZIP/URL
filename; both according to the setting of os%
.
Examples include:
FNfn_unixtobbc("/docs/letters.cv") -> $.docs.letters/cv FNfn_unixtobbc("../info??") -> ^.info## FNfn_unixtobbc("A:/text/why#") -> :A.text.why? FNfn_unixtodos("\docs\letters.cv") -> \docs\letters.cv FNfn_unixtodos("..\info??") -> ..\info?? FNfn_unixtodos("A:\text\why#") -> A:\text\why#
If running on BBC/RISC OS:
FNfn_fromunix("/docs/letters.cv") -> $.docs.letters/cv FNfn_fromunix("../info??") -> ^.info## FNfn_fromunix("A:/text/why#") -> :A.text.why? FNfn_tounix("$.docs.letters/cv") -> /docs/letters.cv FNfn_tounix("^.info##") -> ../info?? FNfn_tounix(":A.text.why?") -> A:/text/why#
If running on DOS/Windows:
FNfn_fromunix("/docs/letters.cv") -> \docs\letters/cv FNfn_fromunix("../info??") -> ..\info?? FNfn_fromunix("A:/text/why#") -> A:\text\why? FNfn_tounix("\docs\letters.cv") -> /docs/letters.cv FNfn_tounix("..\info??") -> ../info?? FNfn_tounix("A:\text\why#") -> A:/text/why#
If running on UNIX:
FNfn_fromunix("/docs/letters.cv") -> /docs/letters.cv FNfn_fromunix("../info??") -> ../info?? FNfn_fromunix("A:/text/why#") -> A:/text/why# FNfn_tounix("/docs/letters.cv") -> /docs/letters.cv FNfn_tounix("../info??") -> ../info?? FNfn_tounix("A:/text/why#") -> A:/text/why#
Technical information
Different platforms use different characters to indicate different filename components such as directory and extension separators, drive specifiers, current, root and parent directories.
BBC DOS/Windows UNIX/ZIP/URL --------------------------------------------------------------- Drive :d d: Directory separator . \ / Extension separator / . . Root directory $ \ / Parent directory ^ .. .. Current Directory @ . . Library Directory % User Directory & %USERPROFILE% $HOME$ Wild Character # ? ? Wild String * * *
The simplest conversion is between UNIX and DOS pathnames; other than the
'/
' and '\
' directory separators all
other characters used are identical. Conversion is simply an issue of swapping
'/
' and '\
' characters.
The BBC uses '#
' as a single-character wildcard, DOS and UNIX
use '?
'. Conversely, on the BBC '?
' is an
ordinary character and on DOS and UNIX '#
' is an ordinary
character, so thay are swapped.
The BBC uses '.
' as a directory separator and '/
' as an
extension separator; DOS and UNIX use '.
' as an extension separator, DOS
uses '\
' as a directory separator and UNIX uses '/
'.
'.
' and '/
' are swapped when converting between
BBC and UNIX. BBC '.
', '\
', '/
' are
swapped with DOS '\
', '/
', '.
' when
converting between BBC and DOS.
The functions in this library do not provide a perfect translation mapping,
the BBC has more illegal filename characters than other platforms which
makes a bidirection mapping difficult. For example, the DOS filename
"$TEMP$.$$$"
cannot be translated to a BBC filename and
then have a perfect one-to-one mapping back to the same DOS filename.
If support for such more complex pathnames are needed a more advanced Filename
library should be used.
Code
REM > BLib.Filename 1.02 25-Jan-2011 REM Convert between BBC, DOS/Windows and UNIX/ZIP/URL filenames REM!Keep FNfn_frombbc(), FNfn_tobbc(), FNfn_unixtodos(), FNfn_dostounix() : REM Swap between BBC and Unix/Zip filenames REM --------------------------------------- DEFFNfn_zip(B$):LOCALB%:A$="#?./$<^>&+@=%; " FOR A%=1 TO LEN B$:B%=INSTR(A$,MID$(B$,A%,1))-1 IF B%>TRUE:B$=LEFT$(B$,A%-1)+MID$(A$+"_",(B%EOR1)+1,1)+MID$(B$,A%+1) NEXT:=B$ : DEFFNfn_bbctodos(A$):LOCALA%,B%,H%:H%=32:DEF:FNfn_frombbc() DEFFNfn_bbctounix(A$):LOCALA%,B%,H%:H%=8:DEF:FNfn_frombbc() DEFFNfn_frombbc(A$):LOCALA%,B%,H%:H%=os% IFA$=""OR(H%AND-24)=0:=A$ IFLEFT$(A$,1)=":":A%=INSTR(A$+".","."):A$=MID$(A$,2,A%-2)+":"+MID$(A$,A%-(MID$(A$,A%+1,1)="$")) A%=0:REPEAT:A%=A%+1:B%=ASCMID$(A$,A%,1) IFB%=35ORB%=63:A$=LEFT$(A$,A%-1)+CHR$(B%EOR28)+MID$(A$,A%+1) :REM # ? IFB%=61ORB%=64:A$=LEFT$(A$,A%-1)+CHR$(B%EOR125)+MID$(A$,A%+1):REM = @ IFB%=36ORB%=60:A$=LEFT$(A$,A%-1)+CHR$(B%EOR24)+MID$(A$,A%+1) :REM < $ IFB%=62ORB%=94:A$=LEFT$(A$,A%-1)+CHR$(B%EOR96)+MID$(A$,A%+1) :REM > ^ IFB%=ASC"$":IF(H%AND-24)=8:A$=LEFT$(A$,A%-1)+"/"+MID$(A$,A%+1-(A%<>LENA$)) IFB%=ASC"$":IF(H%AND-32):A$=LEFT$(A$,A%-1)+"\"+MID$(A$,A%+1-(A%<>LENA$)) IFB%=ASC"@":A$=LEFT$(A$,A%-1)+"."+MID$(A$,A%+1) IFB%=ASC"^":A$=LEFT$(A$,A%-1)+".."+MID$(A$,A%+1):A%=A%+1 IFB%=ASC"/":A$=LEFT$(A$,A%-1)+"."+MID$(A$,A%+1) IFB%=ASC".":IF(H%AND-24)=8:A$=LEFT$(A$,A%-1)+"/"+MID$(A$,A%+1) IFB%=ASC".":IF(H%AND-32):A$=LEFT$(A$,A%-1)+"\"+MID$(A$,A%+1) IFB%=ASC"\":IF(H%AND-32):A$=LEFT$(A$,A%-1)+"/"+MID$(A$,A%+1) REM IFB%=ASC"&":A$=LEFT$(A$,A%-1)+"%HOME%"+MID$(A$,A%+1) UNTILA%>LENA$:=A$ : DEFFNfn_fromunix(A$):IF(os%AND-24)=8:=A$ ELSE IF(os%AND-24)=0:=FNfn_unixtobbc(A$):DEF:FNfn_dostounix() DEFFNfn_fromdos(A$):IF(os%AND-32):=A$ ELSE IF(os%AND-24)=0:=FNfn_dostobbc(A$):DEF:FNfn_dostounix() DEFFNfn_tounix(A$):IF(os%AND-24)=8:=A$ ELSE IF(os%AND-24)=0:=FNfn_bbctounix(A$):DEF:FNfn_dostounix() DEFFNfn_todos(A$):IF(os%AND-32):=A$ ELSE IF(os%AND-24)=0:=FNfn_bbctodos(A$):DEF:FNfn_dostounix() DEFFNfn_unixtodos(A$):DEF:FNfn_dostounix() DEFFNfn_dostounix(A$) IFINSTR(A$,"/")+INSTR(A$,"\")=0:=A$ LOCAL A%,B%:A%=0:REPEAT:A%=A%+1:B%=ASCMID$(A$,A%,1):IFB%=ASC"/"ORB%=ASC"\":A$=LEFT$(A$,A%-1)+CHR$(B%EOR115)+MID$(A$,A%+1) UNTILA%>=LENA$:=A$ : DEFFNfn_dostobbc(A$):LOCALA%,B%,H%:H%=32:DEF:FNfn_tobbc() DEFFNfn_unixtobbc(A$):LOCALA%,B%,H%:H%=8:DEF:FNfn_tobbc() DEFFNfn_tobbc(A$):LOCALA%,B%,H%:H%=os% IFA$=""OR(H%AND-24)=0:=A$ IFA$="/":IF(H%AND-24)=8:="$" IFA$="\":IF(H%AND-32):="$" A%=0:REPEAT:A%=A%+1:B%=ASCMID$(A$,A%,1) IFB%=35ORB%=63:A$=LEFT$(A$,A%-1)+CHR$(B%EOR28)+MID$(A$,A%+1):REM # ? IFMID$(A$,A%,2)="..":A$=LEFT$(A$,A%-1)+"^"+MID$(A$,A%+2):A%=A%-1:B%=0 IFMID$(A$,A%)=".":A$=LEFT$(A$,A%-1)+"@":B%=0 IFMID$(A$,A%,2)="./":IF(H%AND-24)=8:A$=LEFT$(A$,A%-1)+"@"+MID$(A$,A%+1):B%=0 IFMID$(A$,A%,2)=".\":IF(H%AND-32):A$=LEFT$(A$,A%-1)+"@"+MID$(A$,A%+1):B%=0 REM IFMID$(A$,A%,6)="%HOME%":A$=LEFT$(A$,A%-1)+"&"+MID$(A$,A%+6):B%=0 IFB%=ASC".":A$=LEFT$(A$,A%-1)+"/"+MID$(A$,A%+1) IFB%=ASC"\":IF(H%AND-32):A$=LEFT$(A$,A%-1)+"."+MID$(A$,A%+1) IFB%=ASC"/":IF(H%AND-32):A$=LEFT$(A$,A%-1)+"\"+MID$(A$,A%+1) IFB%=ASC"/":IF(H%AND-24)=8:A$=LEFT$(A$,A%-1)+"."+MID$(A$,A%+1) IFB%=ASC":":A$=":"+LEFT$(A$,A%-1)+".$"+MID$(A$,A%+1):A%=A%+2 UNTILA%>LENA$:=A$ :
Requirements and Dependancies
The FNfn_from*()
and FNfn_to*()
functions require the
global variable os%
set to the host the program is running on, such as by calling FNOS_GetEnv
in
the ProgEnv library or with
A%=0:X%=1:os%=((USR&FFF4)AND&FF00)DIV256
All the other functions have no external requirements.
Notes
The code is rather untidy and can be tidied up.
See also
JGH, 25 April 2011 Jgharston (talk) 06:24, 3 April 2018 (CEST)