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

  1. package RISCOS::File;
  2.  
  3. require Exporter;
  4. use Carp;
  5. # use RISCOS::Filespec qw (canonicalise);
  6. # it's a builtin, and don't want to turn off conversion in makeddf
  7. use RISCOS::SWI;
  8. use strict;
  9. use vars qw ($os_file $VERSION @ISA @EXPORT_OK $AUTOLOAD);
  10.  
  11. $VERSION = 0.08;
  12. @ISA = qw(Exporter);
  13.  
  14. @EXPORT_OK = qw(settype gettype globlist load os_file filetype getdatestamp
  15.         copy glob_control fileglob_PrintExpandedPaths
  16.         fileglob_PrintOriginalPath fileglob_PrintPathMask
  17.         fileglob_IncludeDotFiles fileglob_SkipDotFiles
  18.         fileglob_DotFilesMask fileglob_DontSplitOnWhitespace
  19.         fileglob_WhitespaceMask fileglob_SplitOnWhitespace
  20.         fileglob_ImagesAreFiles fileglob_ImagesAreDirectories
  21.         fileglob_ImagesMask );
  22.  
  23. # The fileglob magic numbers are in riscos.c
  24.  
  25. sub globlist
  26. {
  27.     my (@globbed);
  28.     map {
  29.     @globbed = glob ($_);
  30.     # Push the glob pattern if it doesn't match
  31.     # (ie emulate unix shell behaviour)
  32.     @globbed ? @globbed : $_;
  33.     } @_
  34. }
  35.  
  36. sub load ($) {
  37.     return undef unless my $file = shift;
  38.     # If passed ref to scalar assume that we have been given the file's contents
  39.     return $$file if ref($file) eq 'SCALAR' or ref($file) eq 'LVALUE';
  40.  
  41.     local *FILE;
  42.  
  43.     if (ref($file) ? (ref($file) eq 'GLOB'
  44.               || UNIVERSAL::isa($file, 'GLOB')
  45.               || UNIVERSAL::isa($file, 'IO::Handle'))
  46.            : (ref(\$file) eq 'GLOB'))
  47.     {
  48.     *FILE = $file;
  49.     }
  50.     else
  51.     {
  52.     open FILE, "<$file" or croak "Unable to open '$file': $!";
  53.     }
  54.     local $/; undef $/;
  55.  
  56.     return scalar <FILE> unless wantarray;    # Schluuuuuuuurp!
  57.  
  58.     my @result = os_file (5, \*FILE);
  59.     return scalar <FILE> unless @result;
  60.     (scalar (<FILE>), @result[0..5]);
  61. }
  62.  
  63. sub AUTOLOAD {
  64.     my($constname);
  65.     ($constname = $AUTOLOAD) =~ s/.*:://;
  66.     my $val = RISCOS::File::constant($constname);
  67.     croak "Undefined subroutine $AUTOLOAD" unless defined $val;
  68.     eval "sub $AUTOLOAD { $val }";
  69.     goto &$AUTOLOAD;
  70. }
  71.  
  72. sub os_file ($$;) {
  73.     return wantarray ? () : undef unless defined $_[0] and defined $_[1];
  74.     # Make sure that we don't clobber the original value
  75.     splice @_,1,1, RISCOS::Filespec::riscosify $_[1];
  76.     unshift @_, $os_file;
  77.     my $result = &kernelswi;    # Pass on modified arguments;
  78.     return (wantarray ? () : undef) unless defined $result;
  79.     return unpack 'I10', $result if wantarray;
  80.     unpack 'I', $result;
  81. }
  82.  
  83. sub filetype {
  84.     return (defined $_[0] and ($_[0] & 0xFFF00000) == 0xFFF00000)
  85.           ? ($_[0] >> 8) & 0xFFF : undef
  86.       unless wantarray;
  87.     map  { (defined $_ and ($_ & 0xFFF00000) == 0xFFF00000)
  88.           ? ($_ >> 8) & 0xFFF : undef } @_;
  89. }
  90.  
  91. sub gettype {
  92.     # "Comments are for wimps" :-)
  93.     filetype map {
  94.         # Can I combine these two lines in some way without triggering warnings
  95.         # with -w and undefined filenames?
  96.     my $result = kernelswi ($os_file, 5, RISCOS::Filespec::riscosify $_);
  97.     # Check there was no error and it was found
  98.     defined ($result) and unpack ('I', $result)
  99.      ? unpack ('x8I', $result) : undef;
  100.     } @_;
  101. }
  102.  
  103. sub _getdatestamp {
  104.     my $result = kernelswi ($os_file, 5, RISCOS::Filespec::riscosify $_[0]);
  105.     (defined ($result) and (unpack 'I', $result) 
  106.     and (unpack ('x8I', $result) & 0xFFF00000) == 0xFFF00000)
  107.       ? substr ($result, 12, 4) .  substr ($result, 8, 1) : undef;
  108.     # Look at the StrongHelp load and exec address page - if you store
  109.     # R3 and R2 in memory in that order you get dddddddd cctttff
  110. }
  111.  
  112. sub getdatestamp {
  113.     goto &_datestamp unless wantarray;
  114.     map {_datestamp $_} @_
  115. }
  116.  
  117. $os_file = SWINumberFromString('OS_File');
  118. __END__
  119.  
  120. =head1 NAME
  121.  
  122. RISCOS::File -- native file operations
  123.  
  124. =head1 SYNOPSIS
  125.  
  126.     use RISCOS::File 'globlist';
  127.     @ARGV = globlist (@ARGV);
  128.     # Simulate Unix-like filename globbing of command line arguments
  129.  
  130.     use RISCOS::File 'os_file';
  131.     @info = os_file 'perl';
  132.  
  133. =head1 DESCRIPTION
  134.  
  135. C<RISCOS::File> provides S<RISC OS> specific functions to access files, and a
  136. function C<globcontrol> to control the globbing performed by the perl builtins
  137. C<< E<gt>> and C<glob>.
  138.  
  139. =over 4
  140.  
  141. =item settype <type>, <filename>...
  142.  
  143. Sets the filetype of a list of files. I<filename> can actually be a reference to
  144. a filehandle, and I<type> can be specified as a number or a string - strings are
  145. passed to C<OS_FSControl 31> which will also convert hexadecimal strings such as
  146. C<FFF> and C<&102> to numbers.
  147.  
  148. Returns 0 for complete success, 1 if any errors occurred.
  149.  
  150. =item gettype <filename>...
  151.  
  152. Returns the numeric filetype of a list of files, or in scalar context the
  153. filetype of the first file. As you might expect I<filename> can also be a
  154. filehandle (I<i.e> reference to a typeglob, or an IO object). Returns C<undef>
  155. for filenames/handles that do not correspond to disc files, or to files that are
  156. untyped.
  157.  
  158. =item getdatestamp <filename>...
  159.  
  160. In scalar context the returns the datestamp of the first file as a 5 byte
  161. scalar, or C<undef> for filenames/handles that do not correspond to disc files,
  162. or to files that are untyped. In array context returns the list of datestamps
  163. corresponding to the list of files.
  164.  
  165. =item globlist
  166.  
  167. Passes a list of patterns to glob, and returns an list of the results. If any
  168. pattern matches zero files, it is returned verbatim (the same approach used by
  169. Unix shells). Note that this differs from C<< E<gt>> and C<glob>, which return
  170. an empty list if the pattern does not match.
  171.  
  172. =item load <file>
  173.  
  174. Loads the file specified. If I<file> is actually a reference to a scalar, it is
  175. taken as referring to the contents of the notional file, and this is returned.
  176. If I<file> is a reference to a handle, this is used, otherwise I<file> is taken
  177. to be a filename.
  178.  
  179. In scalar context returns the file contents, or undefined for failure. In array
  180. context returns an array  S<(I<file contents>, C<os_file (5, I<file>)>)>, or an
  181. array (I<file contents>) if C<os_file 5> fails (I<e.g.> the handle could not be
  182. converted to a filename).
  183.  
  184. =item os_file <reason>, <filename>
  185.  
  186. Performs the specified C<OS_File>. Returns C<R0> in scalar context, an array of
  187. C<R0>-C<R9> in array context. Oddly enough I<filename> can actually be a
  188. filehandle, which is converted to a filename to call C<OS_File>.
  189.  
  190. =item filetype <load addr>...
  191.  
  192. C<filetype> returns the numberic filetype from the load address given, or
  193. C<undef> if the load address is not for a stamped file. In scalar context it
  194. returns the filetype from the first argument, in array context C<filetype>
  195. returns a list of filetypes corresponding to the argument list.
  196.  
  197. =item copy <from>, <to> [, <flags>]
  198.  
  199. C<copy> calls the S<RISC OS> C<*copy> command copy to copy a file
  200. (C<OS_FSControl 26> to be precise). I<flags> default to 0 [*], and are as
  201. for C<OS_FSControl 26> I<except> that bit 13 is toggled. This means that 
  202. by default an appropriately sized user buffer is provided internally, avoiding
  203. problems copying to/from archives. [Appropriately sized is currently
  204. implemented as C<min( I<filesize>, 128K )> ]. If I<to> or I<from> are
  205. filehandles then they are converted to filenames (if possible) before calling
  206. C<OS_FSControl 26>.
  207.  
  208. * If flags are not supplied then force is turned on unless the target is
  209. locked. This means that you can copy over a destination file automatically.
  210.  
  211. =back
  212.  
  213. =head2 glob_control
  214.  
  215. C<glob_control> allows the script to control various options that control how
  216. the C<< E<gt>> operator and underlying C<glob> function work. C<glob_control>
  217. returns the current/old setting of the control flags. If passed a defined value
  218. it uses this as the new flag settings, otherwise the control flags are left
  219. unchanged. C<glob_control> will C<croak> if reserved bits in the flags are not
  220. zero - always use the C<fileglob_*> subroutines provided to construct flag
  221. settings.
  222.  
  223. =over 4
  224.  
  225. =item fileglob_PrintExpandedPaths
  226.  
  227. the default setting - causes globbing to (recursively) expand Path variables
  228. passed in. With this
  229.  
  230.     glob ('System:Modules.a*')
  231.  
  232. returns
  233.  
  234.     ADFS::Bagpuss.$.!BOOT.Resources.!System.310.Modules.ABCLib
  235.     ADFS::Bagpuss.$.!BOOT.Resources.!System.310.Modules.ABIMod
  236.     ADFS::Bagpuss.$.!BOOT.Resources.!System.Modules.ABIMod
  237.  
  238.  
  239. System:Modules.ABCLib
  240. System:Modules.ABIMod
  241. System:Modules.ABIMod
  242.  
  243. =item fileglob_PrintOriginalPath
  244.  
  245. causes globbing output to retain Path variables passed in, although recursive
  246. expansion is used internally. Setting this turns off
  247. I<fileglob_PrintExpandedPaths>, likewise setting I<fileglob_PrintExpandedPaths>
  248. turns off I<fileglob_PrintOriginalPath>. If both are set the result is
  249. undefined.
  250.  
  251. With this
  252.  
  253.     glob ('System:Modules.a*')
  254.  
  255. returns
  256.  
  257.     System:Modules.ABCLib
  258.     System:Modules.ABIMod
  259.     System:Modules.ABIMod
  260.  
  261. =item fileglob_PrintPathMask
  262.  
  263. bitmask of the acceptable values for the above printing options.
  264.  
  265. =item fileglob_IncludeDotFiles
  266.  
  267. When filename conversion is on, globbing a pattern not starting 'C<*>' includes
  268. files starting 'C</>' - I<i.e.> Unix "dot" files mapped to S<RISC OS>.
  269.  
  270. When filename conversion is off this flag has no effect.
  271.  
  272. =item fileglob_SkipDotFiles
  273.  
  274. When filename conversion is on, globbing a pattern not starting 'C<*>' does not
  275. include files starting 'C</>' - use a pattern explicitly starting 'C</>',
  276. I<e.g.> 'C</*>' to match these files. This is the default setting, as it is
  277. consistent with Unix.
  278.  
  279. When filename conversion is off this flag has no effect.
  280.  
  281. =item fileglob_DotFilesMask
  282.  
  283. bitmask of the acceptable values for the above dot files options.
  284.  
  285. =item fileglob_SplitOnWhitespace
  286.  
  287. This is the default setting.With this flag C<glob> will split patterns on whitespace, and glob on each
  288. section. So
  289.  
  290.     <aa* *q*z>
  291.  
  292. will glob as
  293.  
  294.     <aa*>
  295.     <*q*z>
  296.  
  297. This is consistent with Unix, and consistent with Fileswitch taking 'C< >' and
  298. other whitespace as the end of a filename. This is the default setting.
  299.  
  300. =item fileglob_DontSplitOnWhitespace
  301.  
  302. With this flag C<glob> takes no special notice of whitespace.
  303.  
  304. =item fileglob_WhitespaceMask
  305.  
  306. bitmask of the acceptable values for the above whitespace options.
  307.  
  308. =item fileglob_ImagesAreDirectories
  309.  
  310. This is the default setting - with this flag C<glob> will treat any images it
  311. finds in the path being globbed just like directories, and match against their
  312. contents. This is consistent with the behaviour of the desktop filer.
  313.  
  314. =item fileglob_ImagesAreFiles
  315.  
  316. With this flag C<glob> will treat non-leaf images as files, not directories.
  317. This means that C<glob> will not return the contents of any images.
  318.  
  319. So if F<$.FestiveRd> is an image containing 2 files F<52> and F<Shop>,
  320.  
  321.     glob "\$.FestiveRd.*"
  322.  
  323. or
  324.  
  325.     glob "\$.Festi##Rd.*"
  326.  
  327. will return
  328.  
  329.     $.FestiveRd.52
  330.     $.FestiveRd.Shop
  331.  
  332. with the normal behaviour, but
  333.  
  334.      
  335.  
  336. (I<i.e.> nothing) with this flag enabled, as images are to be treated as normal
  337. files now, and hence listing the contents in any way is forbidden.
  338.  
  339. This flag has B<no> effect on image files found as B<leaf>names in globbing
  340. patterns, as C<glob> makes no distinction between files, images, directories,
  341. (or any future object type) found as a leafname.
  342.  
  343. Note that any non-ADFS floppy disks are actually image files - with this flag
  344. set C<glob "ADFS::0.\$.*"> will B<not> give a listing of the root directory of
  345. an C<MS-DOS> floppy, because a check will be made on C<$>, which is actually
  346. an image, not a directory. This is a documented consequence of the S<RISC OS>
  347. implementation of foreign format discs.
  348.  
  349. Note also that this flag only affects C<glob>, and no other part of perl. In
  350. particular C<-d> will still return true and C<-f> false for an image.
  351.  
  352. =item fileglob_WhitespaceMask
  353.  
  354. bitmask of the acceptable values for the above image options.
  355.  
  356. =back
  357.  
  358. =head1 BUGS
  359.  
  360. Not so much bugs in this module but points to note with the port's core
  361. globbing:
  362.  
  363. C<glob> relies on C<OS_GBPB> to perform globbing, so in theory will work with
  364. case sensitive filesystems (which the PRM states are allowed). This means that
  365.  
  366. =over 4
  367.  
  368. =item *
  369.  
  370. Unix globs with ranges enclosed in C<[]> do not work.
  371.  
  372. =item *
  373.  
  374. glob results are not sorted - they are returned in the same order as the
  375. filesystem returns via C<OS_GBPB>. This means that:
  376.  
  377. =over 4
  378.  
  379. =item *
  380.  
  381. For S<RISC OS> filesystems that return filenames in sorted order, this order is
  382. case B<insensitive>, whereas Unix glob returns filenames in case sensitive
  383. order.
  384.  
  385. =item *
  386.  
  387. Not all S<RISC OS> filesystems sort their directory output in any way.
  388.  
  389. =back
  390.  
  391. =back
  392.  
  393. The upshot is if you really need the output from globbing to be sorted, C<sort>
  394. it yourself.
  395.  
  396. =head1 AUTHOR
  397.  
  398. Nicholas Clark <F<nick@unfortu.net>>
  399.