home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / Perl / Non-RPC / !Perl / riscos / RISCOS / Filespec.pm < prev    next >
Text File  |  1998-07-31  |  11KB  |  316 lines

  1. package RISCOS::Filespec;
  2.  
  3. # Turn filename conversion off, unless parent imports the dummy symbol dont
  4. # So. If you want to import all the symbols use the tag :all
  5. # Importing /.*/ will also get 'dont'. You have been warned
  6.  
  7. # convert, convert_on, convert_off riscosify etc are implemented in riscos.c
  8.  
  9. require Exporter;
  10. use Carp;
  11.  
  12. $VERSION = 0.11;
  13. @ISA = qw(Exporter);
  14. @EXPORT = qw();
  15. # chown chroot fcntl ioctl link lstat readlink symlink
  16. # Not umask as this doesn't use a filename
  17. # Not glob as this is performed by a fuction in riscos.c
  18. # Not stat or any of the file tests as these are performed via a wrapper in
  19. # riscos.c
  20.  
  21. my @constants = qw (__RISCOSIFY_MASK __RISCOSIFY_NO_PROCESS
  22.             __RISCOSIFY_DROP_VOWEL __RISCOSIFY_NO_SUFFIX
  23.             __RISCOSIFY_DONT_CHECK_DIR __RISCOSIFY_CHECK_DIR_IS_SUFFIX
  24.             __RISCOSIFY_TRUNCATE_SHIFT __RISCOSIFY_TRUNCATE_MASK
  25.             __RISCOSIFY_DONT_TRUNCATE __RISCOSIFY_LONG_TRUNCATE
  26.             __RISCOSIFY_MEDIUM_TRUNCATE __RISCOSIFY_SHORT_TRUNCATE);
  27.  
  28. my @filespec =  qw(riscosify unixify canonicalise);
  29.  
  30. my @switch =    qw(convert convert_on convert_off);
  31.  
  32. @EXPORT_OK =   (@switch, @filespec, 'convert_set', @filespec, @constants,
  33.         'dont');
  34.  
  35. %EXPORT_TAGS = (constants => \@constants, filespec => \@filespec,
  36.         switch => \@switch, control => ['convert_set', @constants],
  37.         all => [@constants, @filespec, @swtich, @convert],
  38.         dont => ['dont']);
  39.  
  40. @EXPORT_FAIL = ('dont');
  41.  
  42. my $do = 1;
  43. # Turn off
  44. sub export_fail {
  45.     shift @_;    # Remove package name
  46.     map {
  47.     if ($_ eq 'dont') {
  48.         undef $do;
  49.         ();
  50.     } else {
  51.         $_;
  52.     }
  53.     } @_
  54. }
  55.  
  56. sub import {
  57.     my $self = shift;
  58.     local $Exporter::ExportLevel = 1;    # Export into our parent, not us!
  59.     $self->SUPER::import (@_);
  60.     convert_off() if $do;    # Turn filename conversion off
  61. }
  62.  
  63. # The riscosify magic numbers are in XS
  64. # XS is fun :)
  65.  
  66. sub AUTOLOAD {
  67.     my($constname);
  68.     ($constname = $AUTOLOAD) =~ s/.*:://;
  69.     my $val = RISCOS::Filespec::constant($constname);
  70.     croak "Undefined subroutine $AUTOLOAD" unless defined $val;
  71.     eval "sub $AUTOLOAD { $val }";
  72.     goto &$AUTOLOAD;
  73. }
  74.  
  75. 1;
  76. __END__
  77.  
  78. =head1 NAME
  79.  
  80. RISCOS::Filespec -- routines to control and perform filename conversion.
  81.  
  82. =head1 SYNOPSIS
  83.  
  84.     use RISCOS::Filespec;    # Turn off Unix filename conversion.
  85.  
  86.     use RISCOS::Filespec /riscosify/;
  87.     @name = riscosify ('miniperlmain.c');
  88.  
  89.     use RISCOS::Filespec /canonicalise/;
  90.     @pwd  = canonicalise '@';
  91.     @name = canonicalise \*STDIN;
  92.  
  93. =head1 DESCRIPTION
  94.  
  95. By default this S<RISC OS> perl port assumes that all filenames are in "Unix"
  96. format, and automatically converts to "native" format for all C<open>
  97. C<rename> I<etc.> operations.
  98.  
  99. By using C<RISCOS::Filespec> a perl script turns off this conversion, and shows
  100. that it understands S<RISC OS> file naming conventions. Because UnixLib
  101. processes command line redirection before perl starts, let alone the script, the
  102. internal conversion routine is always used for filenames in command line
  103. redirection.
  104.  
  105. As well as providing routines to control the name conversion on perl builtins,
  106. C<RISCOS::Filespec> provides access to the conversion routines to and from
  107. "Unix" format, and a subroutine to convert filenames and filehandles to
  108. canonical filenames.
  109.  
  110. The internal conversion routine to "native" format works as follows:
  111.  
  112. =over 4
  113.  
  114. =item *
  115. Full S<RISC OS> pathnames of the form 'F<ADFS::Bagpuss.$.!Boot>' and 'F<RAM:$>'
  116. are recognised as such and are passed back unmodified.
  117.  
  118. =item *
  119. Pathnames starting 'F</dev/>' are converted to paths - 'F</dev/parallel>' will
  120. return 'F<parallel:>'.
  121.  
  122. =item *
  123. Filenames starting 'C</>' are checked in a special list - this allows 'F</tmp>'
  124. to be mapped to 'F<<Wimp$ScrapDirE<gt>>'.
  125.  
  126. =item *
  127. Pathnames starting with 'C</>' 'C<$>' or 'C<<>' are taken as absolute - if a
  128. filing system name is found after 'C</>' it is returned to start the name,
  129. otherwise 'C<$.>' is used.
  130.  
  131. =item *
  132. Each 'C</>' delimited section of the pathname is then processed in turn.
  133. If the section ends in a suffixes in the suffix list it is prefixed as a
  134. directory name. Other 'C<.>' are converted to 'C</>', 'C<?>' and 'C<#>' map
  135. to each other, characters illegal in RISCOS filenames are mapped to 'C<_>'.
  136.  
  137. =back
  138.  
  139. =head2 Subroutines to control the internal conversion routines
  140.  
  141. The following routines control filename conversion on "user" filenames supplied
  142. by the script. Filename conversion for internal filenames in C<use> and
  143. C<require> statements is B<always> turned on, and is unaffected by the use of
  144. these functions. [It would be hard to change internal filenames, as the perl
  145. source code assumes that '/' is a directory separator.]
  146.  
  147. =over 4
  148.  
  149. =item convert <new_status>
  150.  
  151. =item convert
  152.  
  153. Reports the status of filename conversion prior to the call, returning true if
  154. filename conversion was turned on, false if turned off. If called with no
  155. arguments, or an undefined argument, leaves the conversion setting unchanged.
  156. Otherwise it turns conversion on if the argument is true, off it is false.
  157.  
  158. =item convert_on
  159.  
  160. Turns filename conversion on. Returns true if filename conversion was on
  161. already, false if filename conversion was off.
  162.  
  163. =item convert_off
  164.  
  165. Turns filename conversion off. Returns true if filename conversion was B<off>
  166. already, otherwise returns false.
  167.  
  168. =item convert_set <flags>
  169.  
  170. Sets the flags for filename conversion as detailed in the table below.
  171. convert_set will C<croak> if reserved bits in the flags are not zero - always
  172. use the C<__RISCOSIFY_*> subroutines provided to construct flag settings.
  173. convert_set will warn if it is called in array context - use an explicit
  174. C<scalar> if necessary, as it is proposed to change the return value for an
  175. array context.
  176.  
  177. =over 4
  178.  
  179. =item __RISCOSIFY_NO_PROCESS
  180.  
  181. If this bit is set then filename conversion is B<off>, and no further action is
  182. taken. C<riscosify> and C<unixify> return the filename unmodified, perl builtins
  183. perform no filename conversion.
  184.  
  185. =item __RISCOSIFY_DONT_TRUNCATE
  186.  
  187. =item __RISCOSIFY_LONG_TRUNCATE
  188.  
  189. =item __RISCOSIFY_MEDIUM_TRUNCATE
  190.  
  191. =item __RISCOSIFY_SHORT_TRUNCATE
  192.  
  193. Set the length to truncate each filename segment. C<__RISCOSIFY_DONT_TRUNCATE>
  194. turns truncation off, the default setting. Filing systems such as C<ADFS>
  195. currently will still truncate filenames to 10 characters, but not truncating
  196. filenames internally allows perl to work well with filing systems that support
  197. longer names.
  198.  
  199. C<__RISCOSIFY_SHORT_TRUNCATE> truncates to B<10> characters - current
  200. C<FileCore> filing systems such as C<ADFS> and C<SCSIFS> have a 10 character
  201. limit.
  202.  
  203. C<__RISCOSIFY_MEDIUM_TRUNCATE> truncates to B<19> characters - SparkFS 1.28 and
  204. earlier have a bug relating to filename truncation.
  205.  
  206. C<__RISCOSIFY_LONG_TRUNCATE> truncates to B<55> characters - the maximum length
  207. name allowed by the C<longfiles> module.
  208.  
  209. =item __RISCOSIFY_DROP_VOWEL
  210.  
  211. If the path element is too long, drop vowels before truncating.
  212. (C<a> C<e> C<i> C<o> C<u> independent of locale setting.)
  213.  
  214. =item __RISCOSIFY_NO_SUFFIX
  215.  
  216. Disable 'suffix' checking - UnixLib keeps a list of suffixes that it recognises.
  217. If a filename ends in a known suffix, it is used as a directory name.
  218. Hence 'F<foo.bar>' is mapped to 'F<foo/bar>' ('F<bar>' not a recognised suffix)
  219. whereas 'F<perl.c>' is mapped to 'F<c.perl>'  ('F<c>' is by default in the
  220. recognised list).
  221.  
  222. Currently the default list is specified by C<Unixfs$sfix> set by the F<!Boot>
  223. file - removing 'C<pl>' and 'C<pm>' from this list will cause C<use> and
  224. C<require> to fail unless you rename all files in the library from F<pm.*> to
  225. F<*.pm>
  226. [This is feasible, and if a future filecore supports long filenames will become
  227. the default distribution arrangement.]
  228.  
  229. By default suffix checking is on, so this bit is unset.
  230.  
  231. =item __RISCOSIFY_DONT_CHECK_DIR
  232.  
  233. By default this flag is off. If enabled, and the conversion routine is presented
  234. with 'F<!Perl/lib/File.pm>' it will check whether a directory
  235. 'F<!Perl.lib.File>' exists. If it does, it will return 'F<!Perl.lib.File.pm>',
  236. if it does not it will return 'F<!Perl.lib.File/pm>'.
  237.  
  238. =item __RISCOSIFY_CHECK_DIR_IS_SUFFIX
  239.  
  240. By default this flag is off. If enabled it will restrict the match of the above
  241. test to only match directories that are found in the suffix list. This allows
  242. a degree of "intuition" when presented with a filename that could be in "Unix"
  243. or "native" format:
  244. 'F<c.riscos>' will map to 'F<c.riscos>' assuming the directory 'F<c>' exists.
  245. 'F<riscos.c>' will map to 'F<c.riscos>'
  246.  
  247. =item __RISCOSIFY_MASK
  248.  
  249. Returns the mask of acceptable flag bits.
  250.  
  251. =back
  252.  
  253. =item riscosify <filename> [<flags>]
  254.  
  255. =item riscosify <filehandle> [<flags>]
  256.  
  257. Converts a filename to "native" format using the same routine as the builtin
  258. name conversion. If one argument is supplied uses the same flags as the builtin
  259. conversion routine - hence if C<convert_off> has been called C<riscosify> will
  260. return the filename unchanged. If two arguments are supplied the second is used
  261. as the flags to the conversion routine.
  262. Note that C<riscosify> performs a many to one mapping, I<e.g.>
  263. 'F<c/pp_hot>' and 'F<pp_hot.c>' both map to 'F<c.pp_hot>'
  264.  
  265. If passed a filehandle (I<i.e> reference to a typeglob, or an IO object) will
  266. convert that file handle to the name of the file it refers to, or undefined if
  267. the handle is not open on disc file. For a filehandle the value of flags doesn't
  268. affect the conversion, but will be faulted if it contains reserved bits set.
  269.  
  270. =item unixify <filename> [<flags>]
  271. =item unixify <filehandle> [<flags>]
  272.  
  273.  
  274. Converts a filename or filehanedle to "Unix" format (currently this routine is
  275. roughly C<tr :/.#?:./?#/ if convert_on();> but with knowledge about C</../> and
  276. filing system special fields. Swapping back of suffixes may be available in
  277. future. Note that as C<riscosify> performs a many to one mapping, correct
  278. recovery of the name by C<unixify> is impossible 100% of the time.
  279.  
  280. =item canonicalise
  281.  
  282. canonicalises a filename (I<i.e.> converts it to a full pathame, and removes any
  283. wildcards. If passed a filehandle (I<i.e> reference to a typeglob, or an IO
  284. object) will convert that file handle to the name of the file it refers to, or
  285. undefined if the handle is not open on disc file.
  286.  
  287. With one filename argument C<canonicalise> is effectively
  288.  
  289.     riscosify
  290.     OS_FSControl 37
  291.     unixify
  292.  
  293. and with one filehandle argument
  294.  
  295.     OS_Args 7
  296.     unixify
  297.  
  298. If a second argument is given it is used as flags for C<riscosify> and
  299. C<unixify>. If three arguments are given, the second is the flag for
  300. C<riscosify>, the third the flag for C<unixify>.
  301.  
  302. =item RISCOS::Filespec::convert_internal
  303.  
  304. returns the riscosify flags used by internal opens (I<e.g.> use). This value is
  305. needed for the throwback module.
  306.  
  307. =back
  308.  
  309. =head1 BUGS
  310.  
  311. Aside from the deficiencies noted above, none known.
  312.  
  313. =head1 AUTHOR
  314.  
  315. Nicholas Clark <F<nick@unfortu.net>>
  316.