home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / ALF20WB.ZIP / ALF.ZIP / QSORT.ZIP / QSORT.DOC next >
Encoding:
Text File  |  1986-10-25  |  22.5 KB  |  424 lines

  1.                          QSORT - Version 2.1
  2.       Copyright (c) 1985, 1986 - Ben Baker - All rights reserved
  3.  
  4.  
  5. QSORT   may  be  freely  copied  and  distributed  for  non-commercial
  6. purposes, provided that 1) it is distributed under the  name  "QSORT,"
  7. and 2) this documentation file always accompanies it.  Vendors wishing
  8. to distribute QSORT commercially,  or  with  commercial  products  may
  9. contact the author at the address below for terms.
  10.  
  11. QSORT  is  made available under the "share-ware" concept.  If you find
  12. this program useful, you are asked  to  send  its  author  a  donation
  13. commensurate  with  its  value  to you ($20 would be nice).  This will
  14. encourage the development of other  useful,  affordable  tools.   Send
  15. checks to:
  16.  
  17.                          Ben Baker
  18.                          RR #1, Box 637
  19.                          E. Alton, Il 62024
  20.  
  21. Bug reports or suggestions may be sent to the  above  address  or  via
  22. FidoNet  mail  to Fido node # 100/76, Baker's Acre, or by logging into
  23. Baker's Acre at 618-251-2169.
  24.  
  25.  
  26. Purpose:   This filter command reads text data from the standard input
  27.            device,  sorts  it  and  writes  it  to the standard output
  28.            device.  Optionally, it may be used  to  sort  a  file  "in
  29.            place."
  30.  
  31. Format:    QSORT[L] [filespec] [/R] [[/Flen] | [/Mlen]] [/T[tag]]      |
  32.                             [/[L][+|-][col][:width]. . .
  33.  
  34. Type:      Internal     External
  35.                           ****
  36.  
  37. Remarks:   Sorts  are  done  using  the  ASCII  collating sequence, or
  38.            optionally using lexical sequence.  Tab characters are  not
  39.            expanded with blanks.
  40.  
  41.            Files  containing  fixed-length  records may be sorted, but |
  42.            key fields must be ASCII  strings.   Fixed  length  records |
  43.            need  not  be terminated by a CR/LF character pair, but the |
  44.            lines in all other files must end with CR/LF.               |
  45.  
  46.            Up  to  30 key field parameters, /[L][+|-][col][:width] may
  47.            be used to specify key fields  and  are  ordered  major  to
  48.            minor from left  to  right.  The 'L', if present, specifies
  49.            "lexical" sequence for  this  field.   (See  discussion  of
  50.            lexical  sequence  below.)  The  minus  (-)  sign specifies
  51.            reverse order for this field.  The plus  (+)  sign  (or  no
  52.            sign)  specifies  normal  sort  order.   If  present, [col]
  53.            defines the beginning column of  the  field.   If  omitted,
  54.            column  1  is  assumed.   If  present, [:width] defines the
  55.            field width in columns.  If width is omitted, the  rest  of
  56.            the  record  is  assumed.   If  no key field parameters are
  57.            given, the entire record is the key field.  Any  key  field
  58.            which  falls  beyond  the  end  of  a  particular record is
  59.            treated as a null (zero length) field for that record,  and
  60.            collates low.
  61.  
  62.            The   /Mlen  parameter  allows  optionally  specifying  the
  63.            maximum record length.  It may lie in the range of /M132 to
  64.            /M65535.   If  this  parameter  is  present, it must appear
  65.            before any field parameters.  If it is omitted, 132 is  the
  66.            default.   NOTE:   Maximum record length may be larger than
  67.            any record in the file to be sorted, but excessive  maximum
  68.            record  length will unecessarily degrade the performance of
  69.            QSORT.
  70.  
  71.            The /Flen parameter defines the record length for a file of |
  72.            fixed-length records.  All records in the input  file  MUST |
  73.            be  exactly  <len>  bytes  long.  The records need not (but |
  74.            may) be terminated with a CR/LF sequence.  They may contain |
  75.            any  data,  even  binary  date,  but the key fields must be |
  76.            ASCII strings.  Strings  may  be  terminated  with  a  null |
  77.            (binary  zero)  character,  or  may be padded with trailing |
  78.            spaces to the full length of the field.   Note  that  QSORT |
  79.            does  not  attempt  to support Pascal style strings.  These |
  80.            are strings which begin with a character whose binary value |
  81.            is   a  character  count.   This  is  followed  by  <count> |
  82.            characters of ASCII data, which  in  turn  is  followed  by |
  83.            random data out to the maximum length of the string.  These |
  84.            strings may be used as key fields, but the programmer  must |
  85.            insure  that  either  the  last  real  character  is a null |
  86.            character, or the field is padded to its full  length  with |
  87.            spaces.   QSORT  must  be  told  that the key begins in the |
  88.            second character position  (the  first  character  of  real |
  89.            data).                                                      |
  90.                                                                        |
  91.            The  /Mlen and /Flen parameters are mutually exclusive.  If |
  92.            either is specified, it must appear before  the  first  key |
  93.            field parameter.  It is an error to specify both.           |
  94.  
  95.            The  /R  parameter  is  included for compatibility with DOS
  96.            SORT and is redundant.   It  reverses  the  sense  of  sort
  97.            direction for all key fields.
  98.  
  99.            If  filespec  is  included  in the command, any redirection
  100.            specified will be ignored.  Disk and path specifiers may be
  101.            included  in  filespec  and will be used for both input and
  102.            output.  QSORT will sort the input file defined by filespec
  103.            to a file with an extent of .$$$.  On successful completion
  104.            of the sort, the input file is deleted and the output  file
  105.            is  renamed  to  filespec,  accomplishing,  in  effect,  an
  106.            "in-place" sort.
  107.  
  108.            The  /T[tag]  parameter,  if  present,  indicates  that the
  109.            "records" to be sorted may be more than a single line long.
  110.            If "tag" is also present, it defines a character to be used
  111.            to tag the "end-of-record." If "tag" is  not  present,  the
  112.            first  empty line terminates the record.  For this purpose,
  113.            "empty" means "no characters."  A  line  containing  but  a
  114.            single space is NOT empty!
  115.  
  116.            A  line  may  be  "tagged"  by  placing  the  tag character
  117.            anywhere on the last line of a logical record.  The  entire
  118.            line,  including  the tag character will appear as the last
  119.            line of the record.
  120.  
  121.            The  /Mlen or /Flen parameter and key field parameters must |
  122.            observe the relative ordering defined above, but the  other
  123.            parameters  may  appear  anywhere  and  in any order on the
  124.            command line.
  125.  
  126. Examples:  Produce  a  directory  listing  sorted by creation date and
  127.            time, and display it on the console a screen's worth  at  a
  128.            time:
  129.  
  130.                A>DIR | QSORT /30:2 /24:5 /39 /34:5 | MORE
  131.  
  132.            The  output  of the DIR command is piped to QSORT.  The key
  133.            fields defined are, from left to right  (major  to  minor),
  134.            year  (2  digits), month and day, AM/PM flag and time.  The
  135.            output of QSORT is then piped to MORE for display.
  136.  
  137.            Next, replace the unsorted  FILE.TXT  with  the  same  data
  138.            sorted  in reverse order.  Use columns 10 to 16 as the sort
  139.            key:
  140.  
  141.                A>QSORT FILE.TXT /-10:7
  142.            or
  143.                A>QSORT FILE.TXT /10:7 /R
  144.            or (SORT compatible)
  145.                A>QSORT FILE.TXT /R /+10
  146.  
  147.            Next, perform a simple sort on a file with 240 byte records
  148.  
  149.                A>QSORT LARGE.REC /M240
  150.  
  151.            GLOSS.TXT is an unsorted glossary of terms.  The term being
  152.            defined  by  each  entry appears first, followed by several
  153.            lines of definition, not exceeding  1000  characters.   The
  154.            entries are separated by empty lines.  Produce GLOSS.SRT, a
  155.            sorted version of the glossary:
  156.  
  157.                A>QSORT /T /M1000 <GLOSS.TXT >GLOSS.SRT
  158.  
  159.            A lawyer keeps a running log of his billable activities  in
  160.            TIME.LOG.   The first line of each entry is "mm/dd/yy hh:mm
  161.            account#." He always places a tilde (~) in the last line of
  162.            each  entry,  which  may be as many as 2500 characters.  He
  163.            wishes to sort the log by account number, and by  ascending
  164.            date and time within each account:
  165.  
  166.                QSORT /M2500 /16:7 /7:2 /1:5 /10:5 /T~  TIME.LOG        |
  167.                                                                        |
  168.            The directory of users for a bulletin board system is  kept |
  169.            in  a  file  binary  file of fixed-length records 180 bytes |
  170.            long.  The user name is a 26-character field  beginning  in |
  171.            the   first   position   and  the  city/state  field  is  a |
  172.            16-character field  beginning  in  the  fortieth  position. |
  173.            Sort the file by city/state and name.                       |
  174.                                                                        |
  175.                QSORT /F180 /40:16 /1:26 USER.BBS                       |
  176.  
  177.                      --- Implementation Notes ---
  178.  
  179. QSORT  is  intended  as  an  enhanced replacement for DOS SORT.  It is
  180. nearly fully upward compatible, but provides  much  more  flexibility.
  181. Multiple  sort  keys  may  be specified, a pseudo in-place sort may be
  182. performed and files and/or records of any size may be sorted  provided
  183. only that there is sufficient disk space for work files and the output
  184. file.  QSORT uses the "quick sort" algorithm, which  cannot  guarantee
  185. the  order  of  records  whose  keys  are  all equal.  This is the one
  186. "incompatibility" with DOS SORT, which retains the original  order  of
  187. records  when  its only key compares equal.  This is important to SORT
  188. because it must be invoked multiple times to  effect  a  multiple  key
  189. sort.   With  QSORT,  you  only sort once and there are usually enough
  190. keys available to insure you get the order you want the first time.
  191.  
  192. QSORT uses a sort buffer of about 60K bytes  and will fill the  buffer
  193. as full as possible, and then sorts the contents of the buffer.  If it
  194. has reached the end of the input file and has not  yet  generated  any
  195. work files, the contents of the buffer are written to the output file,
  196. completing the sort operation.
  197.  
  198. If the input file is too large to fit into the sort buffer, as much of
  199. the  input  file  as  possible  is  read into the buffer, sorted, then
  200. written to a temporary work file.  This process is  repeated  as  many
  201. times  as  necessary  to  process  the  entire  input  file, each time
  202. creating a new work file for the sorted output.
  203.  
  204. Upon completion of the "sort phase," QSORT  begins  a  "merge  phase."
  205. Each  work  file  is  a  sorted sub-set of the input file.  Thus, work
  206. files may be read  sequentially  and  combined  to  produce  a  sorted
  207. output.   QSORT  will  open as many work files as DOS permits (more on
  208. this later).  If all the remaining  work  files  can  be  opened,  the
  209. sorted  result  is  written to the output file.  Otherwise, a new work
  210. file is created and another merge pass  will  be  required.   On  each
  211. merge  pass,  the  number  of work files is reduced and eventually all
  212. remaining work files will be opened and the sorted output file will be
  213. written completing the sort operation.
  214.  
  215. QSORT  is  smart  enough  to  never have just one work file remaining,
  216. which would require an unnecessary copy operation.
  217.  
  218. QSORT, to work properly, needs enough space on the output disk to hold
  219. the  output file.  Even if the input file is to be deleted and resides
  220. in the same directory, that is not done until after  the  output  file
  221. has  been  successfully  written.   If one merge pass is required, the
  222. default directory should have about 10% more space than  the  size  of
  223. the  input  file  for work files.  If more than one merge pass will be
  224. required, allow about twice the size of the input file  as  work  file
  225. space  on  the default disk.  If QSORT has an error, it will terminate
  226. with the input  file  still  intact,  and  will  return  to  DOS  with
  227. ERRORLEVEL = 1.
  228.  
  229. Each time QSORT must create a new work file, the data put into it must
  230. be processed again.  Obviously, the more files QSORT can  open  during
  231. the  merge  phase,  the  faster  it  can  sort large files.  If DOS is
  232. properly pre-conditioned, QSORT can have up to 15 work files  open  at
  233. once,  and  very large files can be sorted with just one sort pass and
  234. one merge pass.  Unfortunately, that capability is not automatic.
  235.  
  236. DOS has a fixed number of file "handles" that it associates with  open
  237. files.   The  default  number is eight, but DOS opens five of them for
  238. standard input, standard output, standard error, standard printer  and
  239. standard  auxiliary  device.   That  leaves three for merging.  A 250K
  240. input file would produce five work files and  that  would  take  three
  241. merge  passes;   merge two into one, leaving four;  merge two into one
  242. leaving three;  and finally merge three into the output file.
  243.  
  244. Worse yet, since you need at least three handles for merging,  if  you
  245. have resident programs that have open files you can't merge at all!
  246.  
  247. DOS can be told to set aside more space for file handles.  Each handle
  248. is only 39 bytes and it's memory very well  spent.   One  process  can
  249. have  a  maximum  of  20  handles open at one time, but since resident
  250. processes may be using handles, I recommend 25 to 35.  To do this, the
  251. root  directory of the DISK OR DISKS YOU BOOT FROM must contain a file
  252. named CONFIG.SYS.  If your boot disk(s) already contains a CONFIG.SYS,
  253. edit it, or if not, create it to contain the following line:
  254.  
  255.      FILES=25 (or more)
  256.  
  257. While  we're  at it, let's add one more thing to CONFIG.SYS which will
  258. improve the performance of QSORT and many other programs as well.  DOS
  259. provides, by default, two disk buffers.  These are the buffers it uses
  260. to do its disk reads and writes.  During the  merge  phase  QSORT  may
  261. have many files open at once, reading from them in more or less random
  262. order.  DOS may have to read the same physical sector several times to
  263. get  all  its  data.   But  DOS can remember what's in each buffer and
  264. where it came from, and will not re-read a sector it already has in  a
  265. buffer.   DOS needs 528 bytes for each buffer.  I recommend 20 buffers
  266. to make QSORT perform well under the most  adverse  conditions.   This
  267. will  require an additional 9504 bytes or slightly more than 9K, again
  268. memory well spent, so we add to CONFIG.SYS the following line:
  269.  
  270.      BUFFERS=20
  271.  
  272. I hope you find this program useful.  Your  comments  and  suggestions
  273. are  welcome.   My  address  is  at  the  top of this file.
  274.  
  275.                         Notes on Version 1.1:
  276.                         ----- -- ------- ----
  277.  
  278. QSORT 1.0 set an arbritrary maximum record length of 132.  This should
  279. certainly be enough, right?  Wrong!  The program had not been released
  280. a  month  before  I  heard  from  a  user  who needed to sort 240-byte
  281. records.  It occurred to me that, for any reasonable  maximum  length,
  282. someone  would  need  to  sort  bigger  records.   The  sort and merge
  283. subroutines need to know the maximum size record  to  be  expected  in
  284. order  to manage their buffers, and an unnecessarily large limit would
  285. make them wasteful of space and degrade performance.
  286.  
  287. The solution, of course, was to add the  '/M'  parameter,  allowing  a
  288. user to specify his own limit if 132 is not enough.
  289.  
  290. One  other  minor  change  was  made  to  the  program.   Version  1.0
  291. documentation implied (in fact stated!) that column  number  could  be
  292. omitted from a field parameter and would default to 1.  In other words
  293. '/1:4' and '/:4' were equivalent.  The  program,  however,  would  not
  294. accept  the latter.  Since this is a useful shorthand, the program has
  295. been changed to match the documentation.
  296.  
  297.                         Notes on Version 1.2:
  298.                         ----- -- ------- ----
  299.  
  300. This version was borne out of my own need to  sort  files  with  mixed
  301. capitalization.   ASCII  sequence  produced  some bizarre results when
  302. words beginning with 'Z'  sorted  before  those  beginning  with  'a.'
  303. Case-insensitive  sorting  isn't  much  better because upper and lower
  304. case get mixed randomly.
  305.  
  306. The following table will illustrate what I mean:
  307.  
  308.      INPUT         ASCII          CASE           LEXICAL
  309.                                INSENSITIVE
  310.      
  311.      DeLaPort      Baker          Baker          Baker
  312.      Smith         Brown          brown          Brown
  313.      brown         DeAngelo       bRown          bRown
  314.      deLaPorte     DeLaPort       Brown          brown
  315.      Deangelo      Deangelo       Deangelo       DeAngelo
  316.      deAngelo      Deangelo       deangelo       Deangelo
  317.      Brown         DelaPort       Deangelo       Deangelo
  318.      smith         DelaPorte      deAngelo       deAngelo
  319.      delaPorte     Harry          DeAngelo       deangelo
  320.      DelaPort      Smith          delaPort       DeLaPort
  321.      DeAngelo      bRown          DelaPort       DelaPort
  322.      DelaPorte     brown          delaPort       delaPort
  323.      deangelo      deAngelo       DeLaPort       delaPort
  324.      Harry         deLaPorte      DelaPorte      DelaPorte
  325.      delaPort      deLaPorte      deLaPorte      deLaPorte
  326.      Baker         deangelo       delaPorte      deLaPorte
  327.      deLaPorte     delaPort       deLaPorte      delaPorte
  328.      Deangelo      delaPort       Harry          Harry
  329.      bRown         delaPorte      smith          Smith
  330.      delaPort      smith          Smith          smith
  331.  
  332. The first column is a list of names in arbitrary order.  The second is
  333. an   ASCII   sort   of   that   list.   Third  we  have  one  possible
  334. case-insensitive sort of the list.  The fourth column is what I really
  335. wanted.   It  is  sorted  the  way  these  words  would be sorted in a
  336. dictionary (or lexicon).  The third and fourth  columns  both  collect
  337. words  of identical spellings together, but in the third column, upper
  338. and lower case spellings are in  arbitrary  order,  while  the  fourth
  339. column places upper case spellings ahead of lower case spellings.
  340.  
  341. For  example,  the  two  occurrences  of Smith are widely separated in
  342. column 2 because one is capitalized and the other is  not.   Column  3
  343. brings the two together, but in the wrong order.  They might have been
  344. in the right order, but the order is strictly arbitrary.  In column 4,
  345. Smith  comes before smith, and lexical sorting will always put them in
  346. this order.
  347.  
  348. The lexical sort implemented in this version  is  achieved  by  making
  349. case-insensitive   comparisions   of   entire  fields.   Only  when  a
  350. comparison of the entire field is equal is an ASCII comparison  called
  351. upon to arbitrate ties.
  352.  
  353. Lexical  sorting  can  be  very  useful when needed, but be aware that
  354. unnecessarily specifying lexical ordering may degrade  performance  of
  355. QSORT.
  356.  
  357. Speaking  of  performance, QSORT does pretty well.  Matt Kanter of New
  358. York reports sorting a 650K file in 40  minutes  and  that  ain't  too
  359. shabby!   Nevertheless,  QSORT  has  been made more intelligent in the
  360. way it schedules merging of very  very  large  files,  thus  improving
  361. performance  when  multiple  merge passes are required, a feature that
  362. will go unnoticed by most users (sigh).
  363.  
  364.                          Notes on version 2.0
  365.                          ----- -- ------- ---
  366.  
  367. First,   you  will  notice  there  are  two  programs,  QSORT.EXE  and
  368. QSORTL.EXE in the distribution archive.  The source for these programs
  369. is  identical  and all the above instructions apply to both.  The only
  370. difference is that QSORTL is compiled for the "large data model." This
  371. allows  it  to  use  all  of  available  memory  as a sort buffer, but
  372. requires it to use a slower 32-bit addressing scheme to  access  data.
  373. For  most  normal  sorting chores, QSORT will run significantly faster
  374. than QSORTL, but for very large files, or when a  very  large  maximum
  375. record length is specified, QSORTL will outperform QSORT.
  376.  
  377. Version  2.0  also  adds  a  significant  new capability to QSORT, the
  378. ability to sort logical records which span many lines  of  text.   Two
  379. such  files are illustrated in the examples above, glossaries and time
  380. accounting logs.  Many other kinds of files fit this  catagory.   This
  381. feature,  triggered  by  the  /T  parameter,  usually  requires the /M
  382. parameter to tell QSORT(L) the largest logical record it can expect.
  383.  
  384. Finally, QSORT has been converted  from  Lattice  C  version  2.14  to
  385. version  3.0  of that compiler, resulting in a leaner, faster program.
  386. As  a  test,  I performed identical simple sorts of various file sizes
  387. on  my  640K XT (with a badly fragmented 10-meg disk) using QSORT-2.0,
  388. QSORTL-2.0 and QSORT-1.2.  Here are actual test results:
  389.  
  390.      File Size        QSORT-2.0   QSORTL-2.0    QSORT-1.2
  391.  
  392.         52k            0:51.35      1:10.19      1:36.56
  393.        148k            3:41.90      3:23.39      4:49.62
  394.        296k            7:17.04      7:30.44      9:47.65
  395.  
  396. I  did  not  have sufficient disk space to test the programs on larger
  397. files, but suspect  QSORTL  will  have  a  step-function  increase  in
  398. running time when file size exceeds available buffer space (about 450K
  399. in my case) making it slower that  QSORT  from  that  point  to  about
  400. 1500K.   Above  that point QSORT will have to make more than one merge
  401. pass and should slow down rapidly.  I would  appreciate  hearing  your
  402. test results with very large files.
  403.  
  404.                          Notes on Version 2.1
  405.  
  406. With this version, QSORT.COM is replaced by QSORT.EXE.  If you have an
  407. earlier QSORT.COM, delete it.  DOS looks first for a ".COM'" file  and
  408. then a ".EXE".
  409.  
  410. The  most noticable change is the addition of support for fixed-length
  411. records.  However, some changes were made to improve performance.  For
  412. instance, instead of a single, general purpose compare function, QSORT
  413. now has several special purpose compare routines, and it  selects  the
  414. most  efficient  based on the combination of parameters you use on the
  415. command line.
  416.  
  417. Because of this change, QSORTL is  quite  competetive  with  QSORT  on
  418. small  files,  and  is decidedly better on large files.  I suggest you
  419. compare the two on your most typical sort jobs and use the  one  which
  420. performs best in that environment for all sorting.
  421.  
  422. I am still not wholly satisfied with performance, and the next version
  423. will probably have compare routines written in assembly language.
  424.