This is Info file pm.info, produced by Makeinfo version 1.68 from the input file bigpm.texi.  File: pm.info, Node: Solaris/Package, Next: Solaris/Patchdiag, Prev: Solaris/InstallDB, Up: Module List Perl module to obtain basic Solaris Package Info ************************************************ NAME ==== Solaris::Package - Perl module to obtain basic Solaris Package Info SYNOPSIS ======== use Solaris::Package; $x=Solaris::Package::new(-directory => "/tmp/install", -file => "SUNWm64.u"); DESCRIPTION =========== Solaris::Package is a class module that reads in the information from a pkginfo file for a Solaris package. It can be spawned from a Solaris::InstallDB object, or it can be used as a standalone object. CONSTRUCTOR METHOD ================== $pkg=Solaris::Package::new(-directory => $dir, -file => $pkgDir); The -directory arguement specifies what package directory to search in, the -file directory points to the directory name the package is in. Optionally, you can specify a pointer to a Solaris::InstallDB object by using the -installDB arguement. Two points to clarify: This object only works on Solaris packages in the directory format, not the data stream format, so the -file arguement is really specifying a filesystem directory. The name of a package is not necessarily the same as the name of the file of the package. The SUNWm64 example at the beginning of this documentation is an example of a package with a different directory name. OBJECT METHODS ============== pkg() name() desc() pkVersion() arch() email() hotline() vendor() basedir() pstamp() instdate() patchList() Each of these methods returns their corresponding pkginfo parameter. Note that patchList() returns an array type, with each element listing a single patch. The pkVersion() method returns the package version, and should not be confused with the version() method. pkgInfo() Returns a simplified output similar to the "pkginfo" command, but does not report filesystem contents. That can be achieved by using the Solaris::Contents object. paramDump() Returns a hash table with every parameter in the pkginfo file and every corresponding value AUTHOR ====== Chris Josephes, chrisj@onvoy.com SEE ALSO ======== The pkginfo(4) manpage.  File: pm.info, Node: Solaris/Patchdiag, Next: Sort/ArbBiLex, Prev: Solaris/Package, Up: Module List Patchdiag class file ******************** NAME ==== Solaris::Patchdiag - Patchdiag class file SYNOPSIS ======== use Solaris::Patchdiag; $pd=Solaris::Patchdiag::new(-file => $filename); DESCRIPTION =========== Solaris::Patchdiag is a class for accessing the content of the patchdiag.xref file, which is a file Sun puts out to list patches available for the Solaris operating system. An instance method of the class reads in the file, and accessor methods allow programs to obtain information about the patches, such as what OS version the patch is for, and what packages the patch is applied to. CONSTRUCTOR METHOD ================== $pd=Solaris::Patchdiag::new(-file => $filename); The new method can accept a file paramter to specify what patchdiag.xref file it should read. If no file is specified, the object will look for a patchdiag.xref file in the current directory. OBJECT METHODS ============== rev($id) releaseDate($id) recommendedFlag($id) securityFlag($id) obsoleteFlag($id) y2kFlag($id) osRelease($id) arch($id) pkgs($id) synopsis($id) Each of the above methods access fields within the file for a specified patch. To find out what operating system release patch ID 108832 is for, you would use $os=$pd->osRelease(108832); file() Returns the name of the patchdiag.xref file being referenced list() Returns a list of all patches in the patchdiag.xref file entry($id) Returns a hash table with all of the data for a particular patch recommendedList() securityList() obsoleteList() y2kList() Each of the above methods returns an array list of patches with the appropriate flag set. For example, to get a list of all of the security classified patches, use (@secpatches)=$pd->securityList(); patchesFor($pkg,$osRelease) Returns an array of all the patches that modify a package in a specific OS Release NOTES ===== The patchdiag.xref file is a REALLY awkward file format, and the fact that it isn't really documented doesn't help much. I'm only interpreting it based on the source code of the patchdiag.pl program and from observation. The "arch" field apparantly lists architectures supported by the patch, AND prerequisite patches that need to be installed beforehand. The "flag" fields contain a space when empty, which technically wastes space. The "y2k" field can contain either a "Y" or a "B", and the original patchdiag.pl program checks for the possibility of a "YB" value as well. I have no idea what the differences are, so I just report the flag as set if either character is present. The "osRelease" field specifies the Solaris OS release name, which involves some munging, and it makes no sense at times. Why report "7_x86" in one field, when you already report the platform architecture in another? Maybe it's really a Solaris naming convention issue. AUTHOR ====== Chris Josephes, chrisj@onvoy.com SEE ALSO ======== The patchdiag(1m) manpage.  File: pm.info, Node: Sort/ArbBiLex, Next: Sort/Fields, Prev: Solaris/Patchdiag, Up: Module List make sort functions for arbitrary sort orders ********************************************* NAME ==== Sort::ArbBiLex - make sort functions for arbitrary sort orders SYNOPSIS ======== use Sort::ArbBiLex ( 'fulani_sort', # ask for a &fulani_sort to be defined "a A c C ch Ch CH ch' Ch' CH' e E l L lh Lh LH n N r R s S u U z Z " ); @words = <>; @stuff = fulani_sort(@words); foreach (@stuff) { print "<$_>\n" } CONCEPTS ======== Writing systems for different languages usually have specific sort orders for the glyphs (characters, or clusters of characters) that each writing system uses. For well-known national languages, these different sort orders (or someone's idea of them) are formalized in the locale for each such language, on operating system flavors that support locales. However, there are problems with locales; cf. *Note Perllocale: (perl.info)perllocale,. Chief among the problems relevant here are: * The basic concept of "locale" conflates language/dialect, writing system, and character set - and country/region, to a certain extent. This may be inappropriate for the text you want to sort. Notably, this assumes standardization where none may exist (what's THE sort order for a language that has five different Roman-letter-based writing systems in use?). * On many OS flavors, there is no locale support. * Even on many OS flavors that do suport locales, the user cannot create his own locales as needed. * The "scope" of a locale may not be what the user wants - if you want, in a single program, to sort the array @foo by one locale, and an array @bar by another locale, this may prove difficult or impossible. In other words, locales (even if available) may not sort the way you want, and are not portable in any case. This module is meant to provide an alternative to locale-based sorting. This module makes functions for you that implement bi-level lexicographic sorting according to a sort order you specify. "Lexicographic sorting" means comparing the letters (or properly, "glyphs", as I'll call them here, when a single glyph can encompass several letters, as with digraphs) in strings, starting from the start of the string (so that "apple" comes after "apoplexy", say) - as opposed to, say, sorting by numeric value. "Lexicographic sorting" is sometimes used to mean just "ASCIIbetical sorting", but I use it to mean the sort order used by *lexicograph*ers, in dictionaries (at least for alphabetic languages). Consider the words "resume" and "rEsumE" (the latter should display on your POD viewer with acute accents on the e's). If you declare a sort order such that e-acute ("E") is a letter after e (no accent), then "rEsumE" (with accents) would sort after every word starting with "re" (no accent) - so "rEsumE" (with accents) would come after "reward". If, however, you treated e (no accent) and e-acute as the same letter, the ordering of "resume" and "rEsumE" (with accents) would be unpredictable, since they would count as the same thing - whereas "resume" should always come before "rEsumE" (with accents) in English dictionaries. What bi-level lexicographic sorting means is that you can stipulate that two letters like e (no accent) and e-acute ("E") generally count as the same letter (so that they both sort before "reward"), but that when there's a tie based on comparison that way (like the tie between "resume" and "rEsumE" (with accents)), the tie is broken by a stipulation that at a second level, e (no accent) does come before e-acute ("E"). (Some systems of sort order description allow for any number of levels in sort orders - but I can't imagine a case where this gets you anything over a two-level sort.) Moreover, the units of sorting for a writing system may not be characters exactly. In some forms of Spanish, ch, while two characters, counts as one glyph - a "letter" after c (at the first level, not just the second, like the e in the paragraph above). So "cuerno" comes before "chile". A character-based sort would not be able to see that "ch" should count as anything but "c" and "h". So this library doesn't assume that the units of comparison are necessarily individual characters. Limitations ----------- * The most notable limitation of this module is that its identification of glyphs must be context-insensitive. So you can't stipulate that, for example, ":" normally counts as a letter after "h", but that it doesn't count (or that it counts as a letter after "z", or whatever) in the special case of appearing at the start of words. * You can't declare whitespace characters of any kind as sortable glyphs using the single-string ("short form") declaration. This is, obviously, because in that declaration format, whitespace is reserved as the delimiter for glyphs and families. So if you want to have space, tab, CR, and/or LF be sortable glyphs, you just have to declare that with the long form (LoL-reference) format. See the sections on these formats, below. * When you have Sort::ArbBiLex generate a new bi-level sort function based on a sort-order declaration, both levels of comparison obviously have the same sort-order declaration - so you can't have Sort::ArbBiLex make a function where at one level "ch" counts as one glyph, and at the other, it counts as two; nor where it counts as a glyph in one position in one level, and at another position in the other level. * When you declare a glyph as consisting of several characters, you're saying that several letters should be considered as one unit. However, you can't go the other way: you can't say that a single letter should be considered as a combination of glyphs. But I've seen some descriptions of German sort order that say that a-umlaut (etc) should be treated as if it were a literal "ae" - i.e. an "a" glyph followed by an "e" glyph. This can't be done simply with Sort::ArbBiLex. * Note that ArbBiLex-generated sort routines always start sorting (at both levels) with glyphs at the start of the string, and continue to the end. But some descriptions (like p138 of the *Unicode Standard Version 3.0*) of French sort order say that the the first level of sorting goes as you'd expect, start to finish, but a later level, ties between different accents are broken *starting from the end*, and working backwards. This can't be done simply with Sort::ArbBiLex. (But it's my experience that the difference is not significant, in the case of French data.) * Currently, you cannot declare more than 255 glyph-groups (i.e., glyphs that sort the same at the first level), and no glyph-group can contain more that 255 glyphs each. (This may change in the future.) However, it's fine if the total number of glyphs in all glyph-groups sums to greater than 255 (as in the case of a declaration for 30 glyph-groups with 10 glyphs each). * I'm writing this module before all details of Perl's future handling of text in Unicode are clear. This may change how this module works, although I'm hoping it will not introduce any incompatibilities. * This library makes no provision for overriding the builtin sort function. It's probably a bad idea to try to do so, anyway. * If all of the glyphs in a given sort order are one character long, the resulting sorter function will be rather fast. If any of them are longer than that, it is rather slower. (This is because one-character mode does its work with lots of tr///'s, whereas "multi"-character mode (i.e., if any glyphs are more than one character long) uses lots of s///'s and hashes. It's as fast as I can make it, but it's still necessarily much slower than single-character mode. So if you're sorting 10,000 dictionary headwords, and you change your sort order from one that uses all one-character glyphs, to one where there's even just one two-character glyph, and you notice that it now takes 15 seconds instead of 3 before, now you know why. * *Remember*, if this module produces a function that *almost* does what you want, but doesn't exactly, because of the above limitations, then you can be have it output the source (via `source_maker') of the function, and try modifying that function on your own. DESCRIPTION =========== This module provides two functions, `Sort::ArbBiLex::maker' and `Sort::ArbBiLex::source_maker', and it also presents an interface that accepts parameters in the `use Sort::ArbBiLex ( ... )' statement. `use Sort::ArbBiLex;' --------------------- This merely loads the module at compile-time, just like any normal "use *[modulename]*". But with parameters, it's special: `use Sort::ArbBiLex ( 'name', DECLARATION, ... );' --------------------------------------------------- This compile-time directive, besides loading the module if it's not already in memory, will interpret the parameters as a list of pairs, where each pair is first the name of a sub to create and then the DECLARATION of its sort order. This calls `Sort::ArbBiLex::maker(DECLARATION)' to make a such-named function, that sorts according to the sort order you specify. This is probably the only way most users will need to interact with this module; they probably won't need to call `Sort::ArbBiLex::maker(DECLARATION)' (much less `Sort::ArbBiLex::source_maker(DECLARATION)'!) directly. Unless your sort-order declarations are variables, you can simply use this `use Sort::ArbBiLex (...)' syntax. Feel free to skip ahead to the "Values for DECLARATION" section. The function Sort::ArbBiLex::maker(DECLARATION) ----------------------------------------------- `maker' is called thus: Sort::ArbBiLex::maker(DECLARATION) This will make a sort function, based on the contents of DECLARATION. The return value is an anonymous subroutine reference. While you can store this just like any another anonymous subroutine reference, you probably want to associate it with name, like most functions. To associate it with the symbol `fulani_sort' in the current package, do this: *fulani_sort = Sort::ArbBiLex::maker($my_decl); Then you can call `fulani_sort(@whatever)' just like any other kind of function, just as if you'd defined `fulani_sort' via: sub fulani_sort { ...blah blah blah... } As you might expect, you can specify a package, like so: *MySorts::fulani_sort = Sort::ArbBiLex::maker($my_decl); If you don't know what `*thing = EXPR' means or how it works, don't worry, just use it - or duck the whole issue by using the "`use Sort::ArbBiLex ('fulani_sort', DECL);'". Actually, there's a minor difference between the various ways of declaring the subroutine `fulani_sort': if you declare it via a call to this: *fulani_sort = Sort::ArbBiLex::maker($my_decl); then that happens at runtime, not compile time. However, compile-time is when Perl wants to know what subs will exist if you want to be able to call them without parens. I.e., this: @stuff = fulani_sort @whatever; # no parens! will cause all sorts of angry error messages, which you can happily avoid by simply adding a "forward declaration" at some early point in the program, to express that you're goung to want to use "fulani_sort" as a sub name: sub fulani_sort; # yup, just that! ...later... *fulani_sort = Sort::ArbBiLex::maker($my_decl); ...later... @stuff = fulani_sort @whatever; # no parens! And then all should be well. The short story is to use the "`use Sort::ArbBiLex ('fulani_sort', ...)'" syntax whenever possible (at which point you're free to omit parens, since the "use" makes it happen at compile-time, not runtime). But when you can't use the "`use Sort::ArbBiLex ('fulani_sort', ...)'" syntax, and you need to use a "`*foo = ...'" syntax instead (which *is* usually necessary if your declaration is a variable, instead of a literal), then either add a "`sub fulani_sort;'" line to your program; or just be sure to use parens on every call to the `fulani_sort' function. See also: *Note Perlsub: (perl.info)perlsub,, for the whys and wherefors of function protoptying, if you want all the scary details. The function Sort::ArbBiLex::source_maker(DECLARATION) ------------------------------------------------------ `Sort::ArbBiLex::source_maker' is just like `Sort::ArbBiLex::maker', except that it returns a string containing the source of the function. It's here if you want to, well, look at the source of the function, or write it to a file and modify it. Values for DECLARATION ====================== DECLARATION is a specification of the sort order you want the new function to sort according to. It can occur in two formats: short form (a single string), and long form (a reference to a list of lists of glyphs). Short-form DECLARATION values ----------------------------- A short-form specification consists of a string that consists of lines containing glyphs. The example in the SYNOPSIS section shows this format. Formally, lines in the short-form declaration string are separated by carriage returns and/or linefeeds. Each line consists of glyphs separated by whitespace (other than CRs or LFs). Lines that are empty (i.e., which contain no glyphs) are ignored. A declaration that contains no glyphs at all is illegal, and causes a fatal error. A "glyph" is any sequence of non-whitespace characters. No glyph can appear more that once in the declaration, or it's a fatal error. A degenerate case of there being only one glyph-family with many glyphs in it (i.e., a one-level sort instead of a bi-level), like this: Sort::ArbBiLex::maker('fulani_sort', "a A c C c' C' e E h H x X i I : l L n N r R s S u U z Z zh Zh ZH" ); is actually treated as if it were that many glyph-families with only one glyph in each. This in an internal optimization. PLEASE NOTE that any characters that *are* in the data being sorted but which *do not* appear in the sort order declaration (neither as themselves, or as part of glyphs) are treated *as if they are not there*. In other words, given the sort order in the above example, if you had "David" as an item to sort, it would sort just as if it were "ai" - since "D", "v", and "d" aren't in that declaration. So think twice before deciding that certain letters "are not part of the alphabet" of the language in question. Note also that if, say, "ch" is in the sort order, but "h" isn't, then an "h" not after a "c" (like in "helicopter" or "pushed") will not be counted for sake of sorting. Long-form DECLARATION values ---------------------------- A long-form specification consists of a reference to a list of lists of glyphs. For example, the example from the SYNOPSIS section could just as well be denoted with a long-form declaration like this: use Sort::ArbBiLex ( 'fulani_sort', [ [ "a", "A" ], [ "c", "C" ], [ "ch", "Ch", "CH" ], [ "ch'", "Ch'", "CH'" ], [ "e", "E" ], [ "l", "L" ], [ "lh", "Lh", "LH" ], [ "n", "N" ], [ "r", "R" ], [ "s", "S" ], [ "u", "U" ], [ "z", "Z" ], ] ); The main practical reason I provide this declaration is that, as discussed in the Limitations section, the short form doesn't allow you to declare whitespace characters of any kind as sortable glyphs using the single-string ("short form") declaration, because in that declaration format, whitespace is reserved as the delimiter for glyphs and families. But you can do it in the long form. In the above example, you'd just add a line before the one for a/A, like this: use Sort::ArbBiLex ( 'fulani_sort', [ [ " ", "\t", "\cm", "\cj" ], # whitespace characters. [ "a", "A" ], ...etc... That'd make whitespace the first glyph family. The effect of this would be to make sorting sensitive to whitespace, such that "for", "for sure", and "forest" would sort in that order. It's my impression that most modern English dictionaries sort without respect to whitespace (so that that list, sorted, would be "for", "forest", "for sure"), but I also realize that that's not the only way to do it. In fact, sensitivity to whitespace seems an inevitable part of conventional sort orders for some languages. A thought: Presumably the only place you'd want to put the whitespace family is at the start of the declaration. It'd be really strange in the middle or the end, I think. A word of caution: Note that, if you have whitespace as a glyph family, "for sure" (with just the one space) and "for sure" (with two spaces inbetween) do not sort the same. You may expect that the sorter would magically collapse whitespace, seeing all sequences of whitespace as equal. Au contraire! They're glyphs, just like any others, so sorting "for sure" and "for sure" (two spaces) is totally analogous to sorting "ika" and "ikka". GUTS ==== * ArbBiLex stands for "arbitrary bi-level lexicographic". * The source to this module may tie your brain in knots. That's what it does to me, *and I wrote it*. Code that writes code can be icky that way. If you want to figure out this module's workings, try using: print Sort::ArbBiLex::source_maker($decl); where you start out with $decl as something short. Understand the code that this module makes before you try to understand how it makes it. * The sorter functions this module makes are built around the Schwartzian transform - i.e., the construct "map BLOCK sort BLOCK map BLOCK List". For a brief discussion of that, see *Note Perlfaq4: (perl.info)perlfaq4,, under the question "How do I sort an array by (anything)?". Or maybe I'll write a *Perl Journal* (www.tpj.com) article about it some time. * If you look at, say, use Sort::ArbBiLex (fu => "a b c ch d i h s sh x"); @x = fu( qw(chachi baba) ); and if you wonder how the "ch" in "chachi" ends up as one glyph "ch" (which is what happens), instead of as a glyph "c" and a glyph "h" (which is not what happens), then consider that this print "<$1>" while 'chache' =~ /(ch|c|h|a|e)/g prints "", not "". * While you're at it, consider that this: print "<$1>" while "itlha" =~ /(tl|lh|l|h|i|a)/g prints "", never "". Presumably this is always The Right Thing. * Most modules that define an import method (either directly, or by inheritating from the Exporter module), use it to just export pre-existing subs from their own package into the calling package. But Sort::ArbBiLex's import is different - there's no pre-existing subs to export, so it just makes new anonymous subs on demand, and sticks them into the package that's current for the given "`use Sort::ArbBiLex'" line (unless the given subname already has a package name on it, like "MySorts::nornish"). COPYRIGHT ========= Copyright 1999, 2000, Sean M. Burke `sburke@cpan.org', all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. AUTHOR ====== Sean M. Burke `sburke@cpan.org'  File: pm.info, Node: Sort/Fields, Next: Sort/PolySort, Prev: Sort/ArbBiLex, Up: Module List Sort lines containing delimited fields ************************************** NAME ==== Sort::Fields - Sort lines containing delimited fields SYNOPSIS ======== use Sort::Fields; @sorted = fieldsort [3, '2n'], @lines; @sorted = fieldsort '\+', [-1, -3, 0], @lines; $sort_3_2n = make_fieldsort [3, '2n'], @lines; @sorted = $sort_3_2n->(@lines); DESCRIPTION =========== Sort::Fields provides a general purpose technique for efficiently sorting lists of lines that contain data separated into fields. Sort::Fields automatically imports two subroutines, `fieldsort' and `make_fieldsort', and two variants, `stable_fieldsort' and `make_stable_fieldsort'. `make_fieldsort' generates a sorting subroutine and returns a reference to it. `fieldsort' is a wrapper for the `make_fieldsort' subroutine. The first argument to make_fieldsort is a delimiter string, which is used as a regular expression argument for a split operator. The delimiter string is optional. If it is not supplied, make_fieldsort splits each line using `/\s+/'. The second argument is an array reference containing one or more field specifiers. The specifiers indicate what fields in the strings will be used to sort the data. The specifier "1" indicates the first field, "2" indicates the second, and so on. A negative specifier like "-2" means to sort on the second field in reverse (descending) order. To indicate a numeric rather than alphabetic comparison, append "n" to the specifier. A specifier of "0" means the entire string ("-0" means the entire string, in reverse order). The order in which the specifiers appear is the order in which they will be used to sort the data. The primary key is first, the secondary key is second, and so on. `fieldsort [1, 2], @data' is roughly equivalent to `make_fieldsort([1, 2])->(@data)'. Avoid calling fieldsort repeatedly with the same sort specifiers. If you need to use a particular sort more than once, it is more efficient to call `make_fieldsort' once and reuse the subroutine it returns. `stable_fieldsort' and `make_stable_fieldsort' are like their "unstable" counterparts, except that the items that compare the same are maintained in their original order. EXAMPLES ======== Some sample data (in array `@data'): 123 asd 1.22 asdd 32 ewq 2.32 asdd 43 rewq 2.12 ewet 51 erwt 34.2 ewet 23 erww 4.21 ewet 91 fdgs 3.43 ewet 123 refs 3.22 asdd 123 refs 4.32 asdd # alpha sort on column 1 print fieldsort [1], @data; 123 asd 1.22 asdd 123 refs 3.22 asdd 123 refs 4.32 asdd 23 erww 4.21 ewet 32 ewq 2.32 asdd 43 rewq 2.12 ewet 51 erwt 34.2 ewet 91 fdgs 3.43 ewet # numeric sort on column 1 print fieldsort ['1n'], @data; 23 erww 4.21 ewet 32 ewq 2.32 asdd 43 rewq 2.12 ewet 51 erwt 34.2 ewet 91 fdgs 3.43 ewet 123 asd 1.22 asdd 123 refs 3.22 asdd 123 refs 4.32 asdd # reverse numeric sort on column 1 print fieldsort ['-1n'], @data; 123 asd 1.22 asdd 123 refs 3.22 asdd 123 refs 4.32 asdd 91 fdgs 3.43 ewet 51 erwt 34.2 ewet 43 rewq 2.12 ewet 32 ewq 2.32 asdd 23 erww 4.21 ewet # alpha sort on column 2, then alpha on entire line print fieldsort [2, 0], @data; 123 asd 1.22 asdd 51 erwt 34.2 ewet 23 erww 4.21 ewet 32 ewq 2.32 asdd 91 fdgs 3.43 ewet 123 refs 3.22 asdd 123 refs 4.32 asdd 43 rewq 2.12 ewet # alpha sort on column 4, then numeric on column 1, then reverse # numeric on column 3 print fieldsort [4, '1n', '-3n'], @data; 32 ewq 2.32 asdd 123 refs 4.32 asdd 123 refs 3.22 asdd 123 asd 1.22 asdd 23 erww 4.21 ewet 43 rewq 2.12 ewet 51 erwt 34.2 ewet 91 fdgs 3.43 ewet # now, splitting on either literal period or whitespace # sort numeric on column 4 (fractional part of decimals) then # numeric on column 3 (whole part of decimals) print fieldsort '(?:\.|\s+)', ['4n', '3n'], @data; 51 erwt 34.2 ewet 43 rewq 2.12 ewet 23 erww 4.21 ewet 123 asd 1.22 asdd 123 refs 3.22 asdd 32 ewq 2.32 asdd 123 refs 4.32 asdd 91 fdgs 3.43 ewet # alpha sort on column 4, then numeric on the entire line # NOTE: produces warnings under -w print fieldsort [4, '0n'], @data; 32 ewq 2.32 asdd 123 asd 1.22 asdd 123 refs 3.22 asdd 123 refs 4.32 asdd 23 erww 4.21 ewet 43 rewq 2.12 ewet 51 erwt 34.2 ewet 91 fdgs 3.43 ewet # stable alpha sort on column 4 (maintains original relative order # among items that compare the same) print stable_fieldsort [4], @data; 123 asd 1.22 asdd 32 ewq 2.32 asdd 123 refs 3.22 asdd 123 refs 4.32 asdd 43 rewq 2.12 ewet 51 erwt 34.2 ewet 23 erww 4.21 ewet 91 fdgs 3.43 ewet BUGS ==== Some rudimentary tests now. Perhaps something should be done to catch things like: fieldsort '.', [1, 2], @lines; `'.'' translates to `split /./' - probably not what you want. Passing blank lines and/or lines containing the wrong kind of data (alphas instead of numbers) can result in copious warning messages under -w. If the regexp contains memory parentheses (`(...)' rather than `(?:...)'), split will function in "delimiter retention" mode, capturing the contents of the parentheses as well as the stuff between the delimiters. I could imagine how this could be useful, but on the other hand I could also imagine how it could be confusing if encountered unexpectedly. Caveat sortor. Not really a bug, but if you are planning to sort a large text file, consider using sort(1). Unless, of course, your operating system doesn't have sort(1). AUTHOR ====== Joseph N. Hall, joseph@5sigma.com SEE ALSO ======== perl(1).  File: pm.info, Node: Sort/PolySort, Next: Sort/Versions, Prev: Sort/Fields, Up: Module List general rules-based sorting of lists ************************************ NAME ==== Sort::PolySort -- general rules-based sorting of lists SYNOPSIS ======== use Sort::PolySort; $s=new Sort::PolySort; # defaults to 'name' @people=('John Doe','Jane Doll','John Quasimodo Doe'); print join(", ",$s->sort(@people),"\n"; use Sort::PolySort; $s=new Sort::PolySort('dateus'); # sets internal @dates=$s->sort(@dates); # uses internal $s->by('email'); # sets internal @names=$s->sortby('name',@names); # overrides internal @emails=$s->sort(@emails); # internal is still 'email' DESCRIPTION =========== This module provides methods to sort a list of strings based on parsing the strings according to a configurable set of specifications. METHODS ------- The following methods are available: new Creates a new polysort object. Takes optional arguement of initial named spec set (defaults to name). by Configures for the named set of sorting specs. Arguement is name of spec set. sort Sorts by the previously-set (by new or by) specs. Arguement is a list of items to sort. Returns the sorted list, leaving the original unchanged. sortby Sorts by the given (named) set of specs. The specs are only changed for this particular sort, so future calls to sort will use whatever specs were in effect before the sortby call. First arguement is name of spec set, second arguement is a list of items to sort. Returns the sorted list, leaving the original unchanged. get Returns an associative array of the current sort specs. See `' in this node. set Sets the current sort specs to the given associative array. Specs not appearing in the passed array retain their previous values, so this method can be used along with get to keep state during a subroutine call or to alter particular specs to get new sorting results. Arguement is an associative array. See `' in this node. Specs ----- The following specifications are local to each Sort::PolySort object: `GLOBTOP' Lump last two levels together? `LEVELS' Number of levels to consider (0=all) `R2L' Count fields right to left? `NUMERIC' Do numerical sort? CASE Do case-sensitive sort? `DELIM1' Primary element delimiter (must not be null). `DELIM2' Secondary element delimiter (can be null). Parsing Scheme -------------- The following order is followed to determine the keys used to sort the given array: 1. *DELIM2* (if given) Remove up to leftmost (rightmost if *R2L* is true) occurance of *DELIM2* (will be brought back later). 2. *DELIM1* Split remainder at all occurances of *DELIM1*. 3. *GLOBTOP* (if true) Rejoin left (right if *R2L* is true) 2 elements (always joined left-to-right, regardless of *R2L*). 4. *R2L* (if true) Reverse list of elements. 5. *LEVELS* Store first *LEVELS* (all if =0) elements (last 2 considered as a single element if *GLOBTOP* is true). 6. *DELIM2* (if true) Store string from left of *DELIM2* as next element. 7. *LEVELS* (unless 0) Rejoin remaining elements (in original order, regardless of *R2L*) and store as next element. Named Specs ----------- The following (case-sensitive) names are used by new, by and sortby to represent pre-defined sets of specs: datebr by European (dd/mm/yy) date dateus by US-style (mm/dd/yy) date email by user for each machine (all parts of FQDN) email2 by user for each top-level domain (last 2 atoms) emaild by user for each domain-name (next-to-last atom) ip by numerical (aaa.bbb.ccc.ddd) ip address name by last name/first name/middle name or initials ERRORS ====== The following errors may occur: *No specname given* by or sortby wasn't passed a specname. *Never heard of specname "foo"* new, by, or sortby was passed a name that was not in the list of known specnames. NOTES ===== The whole parsing method is pretty perverse, but honestly was the first thing that came to mind. It works, but is not very fast or extensible. Enough interested folks mailed me that I wanted to get this out now, but it's dyin' for a rewrite. So this is just a beta. The main interface will remain the same, but the parser will be rewritten and the spec variables changed. Accessor methods will change as a result (using `%s=$s-'get; ... ;$s->set(%s) will probably still work to save state, though). And accessor methods wll be added so that new names spec sets can be added at runtime or known ones modified. And new named spec sets will be added. And on and on and on... AUTHOR ====== Daniel Macks COPYRIGHT ========= Copyright (c) 1996 by Daniel Macks. All rights reserved. This module is free software; you may redistribute it and/or modify it under the same terms as Perl itself.  File: pm.info, Node: Sort/Versions, Next: Spectrum/CLI, Prev: Sort/PolySort, Up: Module List a perl 5 module for sorting of revision-like numbers **************************************************** NAME ==== Sort::Versions - a perl 5 module for sorting of revision-like numbers SYNOPSIS ======== use Sort::Versions; @l = sort versions qw( 1.2 1.2.0 1.2a.0 1.2.a 1.a 02.a ); ... use Sort::Versions; print "lower" if versioncmp("1.2","1.2a")==-1; ... use Sort::Versions; %h = (1 => "d", 2 => "c", 3 => "b", 4 => "a"); @h = sort {versioncmp $h{$a}, $h{$b}} keys %h; DESCRIPTION =========== Sort::Versions allows easy sorting of mixed non-numeric and numeric strings, like the "version numbers" that many shared library systems and revision control packages use. This is quite useful if you are trying to deal with shared libraries. It can also be applied to applications that intersperse variable-width numeric fields within text. Other applications can undoubtedly be found. For an explanation of the algorithm, it's simplest to look at these examples: 1.1 < 1.2 1.1a < 1.2 1.1 < 1.1.1 1.1 < 1.1a 1.1.a < 1.1a 1 < a a < b 1 < 2 1 < 0002 1.5 < 1.06 More precisely (but less comprehensibly), the two strings are treated as subunits delimited by periods. Each subunit can contain any number of groups of digits or non-digits. If digit groups are being compared on both sides, a numeric comparison is used, otherwise a ASCII ordering is used. A group or subgroup with more units will win if all comparisons are equal. One important thing to note is that if a numeric comparison is made, then leading zeros are ignored. Thus 1.5 sorts before `1.06', since two separate comparisons are being made: `1 == 1', and `5 < 6'. This is not the same as `if(1.5 < 1.06) {...}'. USAGE ===== Sort::Versions exports `versions' and `versioncmp'. The former is a function suitable for handing directly to sort. The second function, `versioncmp', takes two arguments and returns a cmp style comparison value. This is handy in indirect comparisons, as shown above. AUTHOR ====== Kenneth J. Albanowski kjahds@kjahds.com Copyright (c) 1996, Kenneth J. Albanowski. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.  File: pm.info, Node: Spectrum/CLI, Next: Speech/Audio/FileWave, Prev: Sort/Versions, Up: Module List wrapper class for the Spectrum Command Line Interface ***************************************************** NAME ==== Spectrum::CLI - wrapper class for the Spectrum Command Line Interface SYNOPSIS ======== use Spectrum::CLI; see METHODS section below DESCRIPTION =========== `Spectrum::CLI' is class which intends to provide a convenient way to invoke the various CLI commands of Spectrum Enterprise Manager from within perl scripts. In the author's estimation, the two primary benefits of `Spectrum::CLI' are: * the parsing of "show" command results `Spectrum::CLI' intelligently parses of the output of CLI "show" commands. That is, it will split apart the columnar values for you, and return them as an array of hashes, each element representing one line of output. * the elimination of "SpecHex" numbers in scripts Because of the aforementioned results parsing, it is now easy to mention spectrum data objects by name rather than by their hexadecimal Handle or Id. For instance, the following one=liner will create a hash of models by model name: map { $Model{$_->{MName}} = $_ } Spectrum::CLI->new->show_models; This would subsequently enable one to refer to a model's handle like this: my $handle = $Model{Universe}{MHandle}; In this way, scripts can be written which discover all SpecHex magic numbers, and are, therefore, more readable and potentially more portable/reusable amongst Spectrum installations. METHODS ======= new - create a new Spectrum::CLI object $obj = Spectrum::CLI->new([VNM_Name,] [SPECROOT,] [ { [verbose => 1,] [Verbose => 1,] [CLISESSID => $sessid,] [CLIMNAMEWIDTH => $width,] [VNMSHRCPATH => $path,] [localhostname => $localname,] [timeout => $seconds,] } ]); my $cli = new Spectrum::CLI; This is the class' constructor - it returns a `Spectrum::CLI' object upon success or undef on failure. Its arguments are optional, and may occur in any order. In general, it can be called with no arguments unless the SPECROOT environment variable is not set, or one wishes to connect to a SpectroSERVER on another host (i.e. the script is not running on the VNM host). The optional constructor arguments are: *VNM name* You may pass a string specifying the name of the VNM machine where the SpectroSERVER to which you'd like to connect resides. (This is passed to the as the first argument to the "connect" command.) *SPECROOT value* You may pass a string specifying the absolute path to the "vnmsh" directory. It should point to a directory which contains the "vnmsh" sub-directory. (It is not necessary to pass this argument if either the SPECROOT or SPEC_ROOT environment variables are set.) *options hashref* A hash reference may also be passed as an argument. The hash can be used to specify a number of options. These include: verbose Passing { verbose => 1 } will cause the package to report errors from the CLI commands to STDERR. This feature can also be enabled by calling the "verbose" object method with a non-zero argument after the constructor returns successfully with that object. Verbose Primarily for use while debugging, passing { Verbose => 1 } will cause the package to report what it is doing, such as which CLI command it is about to execute. This feature can also be enabled by calling the "Verbose" object method with a non-zero argument after the constructor returns successfully with that object. CLISESSID Passing { CLISESSID => value } will cause `Spectrum::CLI' to use that value as the session id. Normally, in the absence of this option, the perl script's process id is used. Use of this option is discouraged unless the default value is somehow problematic. CLIMNAMEWIDTH Passing { CLIMNAMEWIDTH => value } will cause `Spectrum::CLI' to use that value as the model name width for CLI "show" commands. Normally, in the absence of this option, the value 1024 is used. Use of this option is discouraged unless the default value is somehow problematic. VNMSHRCPATH Passing { VNMSHRCPATH => value } will cause `Spectrum::CLI' to use that value as the full path to the configuration file for the CLI. Normally, in the absence of this option, the value "$SPECROOT/vnmsh/.vnmshrc" is used. Use of this option is discouraged unless the default value is somehow problematic. localhostname Passing { localhostname => value } will cause `Spectrum::CLI' to use that value as the IP address or resolvable hostname to determine whether or not the local VnmShd is running. (If VnmShd is not running, the constructor will attempt to launch it.) Normally, in the absence of this option, the return value from Sys::Hostname::hostname is used. Use of this option is discouraged unless the default value is somehow problematic. (That should probably never happen as currently VnmShd seems to bind(2) and listen(2) at the address associated with the system's hostname.) timeout Passing { timeout => value } will cause `Spectrum::CLI' to use that value as the number of seconds to sleep before attempting to connect to the VnmShd that it just launched. If the VnmShd is already running (when the constructor is called) this timeout is not used. Perhaps in the future this timeout will be use for other things as well. Normally, in the absence of this option, the value of 5 seconds will be used. Use of this option is discouraged unless the default value is somehow problematic. # show_types: map { $Type{$_->{Name}} = $_ } $cli->show_types; # show_attributes: map { $UserAttr{$_->{Name}} = $_ } $cli->show_attributes("mth=$Type{User}{Handle}"); # ... These methods invoke the CLI "show" command. They return an array of hashes where the hash keys are the column headings from the first line of output of the corresponding CLI command, and the values are the corresponding value in that column for the given row. seek @results = $obj->seek("attr=attribute_id,val=value", [lh=landscape_handle]); This method invokes the CLI "seek" command. It returns values in a like the "show" methods. *destroy_**, etc. # create_model: $cli->create_model("mth=$Type{User}{Handle}", "attr=$UserAttr{Model_Name}{Id},val=joe", "attr=$UserAttr{User_Full_Name}{Id},val='Joe User'"); ALL of the other CLI commands are available as methods. The return value(s) of these methods differs markedly from that of the aforementioned show_* or seek methods. This is because these methods do not normally produce columnar output, but instead produce messages which sometimes include some useful piece of information. For instance, "create model" produces a message upon success, which indicates the model handle of the create model. The caller will nearly always want to obtain that handle, which can be done by parsing the returned values. (See the results method for a hint at how to do this.) In an array context these methods return an array in which the first element is the exit status (i.e. zero indication success) of the underlying CLI command. The subsequent elements of the returned array are the standard output and standard error (if any) lines produced by the underlying CLI command. In a scalar context these methods return non-zero if the command succeeds, zero otherwise. Regardless of the context in which they are invoked, these methods cause the objects internal status and results to be set. If it is more convenient, these values can be retrieved using the status and results methods rather than having to collect them as return values. dir print $obj->dir; this method returns the absolute path to the directory containing the vnmsh commands. verbose $obj->verbose(1); print $obj->verbose; This method returns a boolean value indicating whether or not verbose behavior is currently turned on. If a zero or non-zero argument is passed it will either clear or set this feature, respectively. Verbose $obj->Verbose(1); print $obj->Verbose; This method returns a boolean value indicating whether or not "very verbose" behavior is currently turned on. If a zero or non-zero argument is passed it will either clear or set this feature, respectively. results @results = $obj->results; This method returns an array containing the results (standard output and standard error) of the last vnmsh command that was executed. The results method is *extremely* useful to determine things such as the model handle of the model that was created by a call to *create_model*. For instance: if ($obj->create_model("mth=$T{User}{Handle}", "attr=$A{Model_Name}{Id},val=joe", "attr=$A{User_Full_Name}{Id},val='Joe User'")) { printf "created model: %s\n", model_handle($obj->results) } sub model_handle { my $mh; grep { m/(0x[0-9A-Fa-f]+)$/ && ($mh = $&)} @_; return $mh } status if (0 != ($status = $obj->status)) { printf("the previous vnmsh command failed: %d\n", $status) } This method returns the exit status of the last vnmsh command that was executed. IMPLEMENTATION ============== Spectrum::CLI is a perl AutoLoader. As such, there is no explicit definition of each method that corresponds to a CLI command. Instead, this module "discovers" which commands are available in the vnmsh directory, and invokes them based on the called method name as determined at run time. Theoretically, this has at least two advantages: * If new CLI commands or options are ever introduced, they will magically appear as part of this API and perhaps even behave as expected. This is especially likely if the output and return values are like those of the current commands. * This module is relatively terse. It would have been much more work to create and maintain if a seperate method needed to be written for each and command and argument combination. AUTHOR ====== Dave Plonka Copyright (C) 1999-2000 Dave Plonka. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SEE ALSO ======== perl(1).