home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / progs / latexidx.icn < prev    next >
Text File  |  2000-07-29  |  5KB  |  142 lines

  1. ############################################################################
  2. #
  3. #    File:     latexidx.icn
  4. #
  5. #    Subject:  Program to process LaTeX idx file
  6. #
  7. #    Author:   David S. Cargo
  8. #
  9. #    Date:     April 19, 1989
  10. #
  11. ############################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #
  17. #  Input:
  18. #
  19. #     A latex .idx file containing the \indexentry lines.
  20. #
  21. #  Output:
  22. #
  23. #     \item lines sorted in order by entry value,
  24. #  with page references put into sorted order.
  25. #
  26. # Processing:
  27. #
  28. #     While lines are available from standard input
  29. #         Read a line containing an \indexentry
  30. #         Form a sort key for the indexentry
  31. #         If there is no table entry for it
  32. #         Then create a subtable for it and assign it an initial value
  33. #         If there is a table entry for it,
  34. #         But not an subtable entry for the actual indexentry
  35. #         Then create an initial page number set for it
  36. #         Otherwise add the page number to the corresponding page number set
  37. #    Sort the table of subtables by sort key value
  38. #    For all subtables in the sorted list
  39. #         Sort the subtables by indexentry values
  40. #         For all the indexentries in the resulting list
  41. #             Sort the set of page references
  42. #             Write an \item entry for each indexentry and the page references
  43. #
  44. #  Limitations:
  45. #
  46. #     Length of index handled depends on implementation limits of memory alloc.
  47. #  Page numbers must be integers (no roman numerals).  Sort key formed by
  48. #  mapping to lower case and removing leading articles (a separate function
  49. #  is used to produce the sort key, simplifying customization) -- otherwise
  50. #  sorting is done in ASCII order.
  51. #
  52. ############################################################################
  53.  
  54. procedure main()                       # no parameters, reading from stdin
  55.     local key_table, s, page_num, itemval, key, item_list, one_item
  56.     local page_list, refs
  57.  
  58.     key_table := table()               # for items and tables of page sets
  59.     while s := read() do               # read strings from standard input
  60.         {
  61.         # start with s = "\indexentry{item}{page}"
  62.         # save what's between the opening brace and the closing brace,
  63.         # and reverse it
  64.         s := reverse(s[upto('{',s)+1:-1])
  65.         # giving s = "egap{}meti"
  66.  
  67.         # reversing allows extracting the page number first, thereby allowing
  68.         # ANYTHING to be in the item field
  69.  
  70.         # grab the "egap", reverse it, convert to integer, convert to set
  71.         # in case of conversion failure, use 0 as the default page number
  72.         page_num := set([integer(reverse(s[1:upto('{',s)])) | 0])
  73.  
  74.         # the reversed item starts after the first closing brace
  75.         # grab the "meti", reverse it
  76.         itemval := reverse(s[upto('}', s)+1:0])
  77.  
  78.         # allow the sort key to be different from the item
  79.         # reform may be customized to produce different equivalence classes
  80.         key := reform(itemval)
  81.  
  82.         # if the assigned value for the key is null
  83.         if /key_table[key]
  84.         then
  85.             {
  86.             # create a subtable for the key and give it its initial value
  87.             key_table[key] := table()
  88.             key_table[key][itemval] := page_num
  89.             }
  90.  
  91.         # else if the assigned value for the itemval is null
  92.         # (e. g., when the second itemval associated with a key is found)
  93.         else if /key_table[key][itemval]
  94.  
  95.         # give it its initial value
  96.         then key_table[key][itemval] := page_num
  97.  
  98.         # otherwise just add it to the existing page number set
  99.         else key_table[key][itemval] ++:= page_num
  100.         }
  101.  
  102.     # now that all the input has been read....
  103.     # sort keys and subtables by key value
  104.     key_table := sort(key_table, 3)
  105.  
  106.     # loop, discarding the sort keys
  107.     while get(key_table) do
  108.         {
  109.         # dequeue and sort one subtable into a list
  110.         # sort is strictly by ASCII order within the equivalence class
  111.         item_list := sort(get(key_table), 3)
  112.  
  113.         # loop, consuming the item and the page number sets as we go
  114.         while one_item := get(item_list) do
  115.             {
  116.             # convert the page number set into a sorted list
  117.             page_list := sort(get(item_list))
  118.  
  119.             # dequeue first integer and convert to string
  120.             refs := string(get(page_list))
  121.  
  122.             # dequeue rest of page nums and append
  123.             while (refs ||:= ", " || string(get(page_list)))
  124.  
  125.             write("\\item ", one_item, " ", refs)
  126.             }
  127.         }
  128.     return
  129. end
  130.  
  131. # reform - modify the item to enforce sort order appropriately
  132. # This could do much more. For example it could strip leading braces,
  133. # control sequences, quotation marks, etc.  It doesn't.  Maybe later.
  134. procedure reform(item)
  135.    item := map(item)        # map to lowercase
  136. # drop leading article if present
  137.    if match("a ",   item) then return item[3:0]
  138.    if match("an ",  item) then return item[4:0]
  139.    if match("the ", item) then return item[5:0]
  140.    return item
  141. end
  142.