;;$Id: padr.el,v 1.57 1997/07/27 05:42:04 nwv Exp $
;;$Source: /u/nwv/emacs/RCS/padr.el,v $
;;#############################################################################
;;# _______ _______ ______ _______ #
;;# ( ____ )( ___ )( __ \ ( ____ ) #
;;# | ( )|| ( ) || ( \ )| ( )| #
;;# | (____)|| (___) || | ) || (____)| #
;;# | _____)| ___ || | | || __) #
;;# | ( | ( ) || | ) || (\ ( #
;;# | ) | ) ( || (__/ )| ) \ \__ #
;;# |/ |/ \|(______/ |/ \__/ #
;;# #
;;# PURPOSE: Converts USR Palm OS PDF text to HTML, TeXinfo, and ASCII. #
;;# #
;;# VERSION: (See `padr-version' variable.) #
;;# #
;;# AUTHOR: Neil W. Van Dyke (nwv@acm.org) #
;;# #
;;# CREATED: 22-Jul-1997 #
;;# #
;;# LEGAL GOO: Copyright (c) 1997 Neil W. Van Dyke, All rights reserved. #
;;# You are free to run this program for personal, noncommercial #
;;# purposes; all other uses require written permission from the #
;;# author (that's me). #
;;# You use this program solely at your own risk. For all you #
;;# know, it could land you in jail, reformat your hard disk, #
;;# seduce your significant other, and forget to feed your pet #
;;# hamster. #
;;# #
;;#############################################################################
;;--------------------------------------------------------- Usage Documentation
;; The Pilot API documentation is distributed in icky PDF format. This is good
;; for printing out, but not so good for viewing on-line. Especially if you
;; cannot run a PDF viewer on your system. What to do? Enter PADR (as in
;; ``Pilot API Docs Reformatter'')! With some help from you, PADR will parse
;; the text of the API docs and reformat it into passable HTML, TeXinfo, and
;; ASCII.
;; To accomplish the reformatting, set aside half an hour or more, and do this:
;; 1. Grab the file "http://www.usr.com/palm/ossdkwin.zip", and extract from it
;; "Guide1Win.pdf", "Guide2Win.pdf", and "Guide3Win.pdf".
;; 2. Open an empty file buffer in Emacs. Call it "raw.txt" or something.
;; 3. Get the text from "Guide1Win.pdf" into the Emacs file buffer:
;;
;; a. Load up "Guide1Win.pdf" in the Adobe AcroRead program.
;;
;; b. Put AcroRead in Text Selection mode by selecting the menu item
;; "Tools -> Select Text".
;;
;; c. Tediously select the text from pages 193-394 (Chapter 7) and paste
;; it into "raw.txt". You probably want to make many trips to do this,
;; or risk overwhelming your selection service. The pasted text should
;; be all one continuous line, with no newlines. Be sure to leave a
;; space character between each paste.
;;
;; (TIME-SAVING HINT: Turn on "View -> Continuous" and zoom to the
;; smallest scale AcroRead will allow. And watch
;; out for the AcroRead ``factorial copy'' bug.)
;; 4. Do the same thing for "Guide2Win.pdf" that you did for "Guide1Win.pdf",
;; only do pages 45-144 (Chapter 2). Don't worry; PADR will ignore the
;; evil page 74 when it runs.
;; 5. Do pages 47-196 and 198-271 of "Guide3Win.pdf".
;; 6. Make sure this program file you are reading right now has been evaluated
;; by Emacs. (Switch to this buffer and do "M-x eval-buffer RET" if you're
;; unsure. Power-users can byte-compile this file.)
;; 7. Go to the "raw.txt" Emacs buffer and execute "M-x padr RET". Wait at
;; least five minutes. Don't interrupt; PADR gets immersed in its work.
;; The status messages should update frequently to help pass the time.
;; 8. A bunch of files will have been created in the same directory as
;; "raw.txt":
;;
;; palmos-funcs-index.html | HTML index of function categories.
;; palmos-funcs-cat-*.html | Category HTML files.
;; palmos-funcs.html | Alternative self-contained HTML file.
;; palmos-funcs.texi | TeXinfo format (see "For TeXinfo Users").
;; palmos-funcs.txt | Plain ASCII file.
;; 9. All done. You may want to exit your Emacs at this point, just to make
;; sure you've liberated all that VM it sucked up.
;; BTW, when you view the reformatted docs, you're gonna see a few function
;; names with "-2" after them. Those are from when the PDF docs have multiple
;; definitions in them ("Crc16CalcBlock", "DmFindSortPosition",
;; "FindDrawHeader", "FindGetLineBounds", "FindSaveMatch", "FindStrInStr"). At
;; this point, you're free to leave them as-is or delete the offending text
;; from "raw.txt" and re-run PADR.
;;----------------------------------------------------------- For TeXinfo Users
;; The TeXinfo format is used to produce both Emacs Info hypertext format and
;; TeX typeset printed manuals. Why anyone would want to print out TeX manuals
;; instead of the much better original PDF ones is a mystery, but the Info
;; format is pretty useful to die-hard Emacs weenors.
;; If you want to use the Info format, do:
;; 1. Make sure you have a copy of the TeXinfo package. It can be gotten from
;; "ftp://prep.ai.mit.edu/pub/gnu/".
;; 2. Run the command "makeinfo palmos-funcs.texi". This will generate a
;; "palmos-funcs.info" and probably "palmos-funcs.info-*".
;; 3. Move the "palmos-funcs.info*" files to your Emacs local Info directory.
;; 4. Add the following line to the "dir" file in your Emacs Info directory.
;;
;; * Palm OS Functions: (palmos-funcs.info).
;; 5. Try it out in Info browser mode. Note that you can navigate to any
;; function or category with the `i' command, and you can do full-text
;; search with the `s' command.
;;--------------------------------------------------------- System Requirements
;; This package was developed under Emacs 19.34 on SPARC Solaris 2.5.1, and
;; should work with Emacs on any Unix platform.
;; XEmacs and Win* users must fend for themselves, the heathens.
;;------------------------------------------------- Frequently-Asked Questions:
;; 1. Q: Yo! Why do I have to go to all this work? Why won't you just put up
;; the reformatted versions on the Web so I can snarf them?
;;
;; A: The answer is that it's probably a technical violation of the
;; copyright of the original documentation to distribute the reformatted
;; versions. Indeed, it may even be a violation to run this program,
;; though I highly doubt the copyright holder really cares how you view
;; the docs for your personal use. (Tangential Note: If you send me rude
;; bug reports, I just might narc on you to the Copyright Police.)
;; Please don't distribute the reformatted versions; that *will* probably
;; annoy the copyright holders, and then they might send me unfriendly
;; messages that hurt my feelings.
;; 2. Q: The output is imperfect, and it may even be missing a couple
;; functions.
;;
;; A: This is true. I haven't verified the conversion beyond glancing at
;; the output and saying ``That looks about right.'' Try manually
;; adjusting "raw.txt" before running PADR, and feel free to send me a
;; precise characterization of any problems you discover.
;; 3. Q: This is a quick&dirty kludge.
;;
;; A: Pretty much, yes.
;; 4. Q: Yet I find it strangely appealing. And its author as well.
;;
;; A: *blush* Oh, do go on...
;;------------------------------------------------------------- Release History
;; [Version 1.2, 27-Jul-1997, nwv@acm.org] Added TeXinfo support. Made ASCII
;; version not put newlines between See Also items. Rewrote
;; `padr-object-is-blank' to deal with newlines. Fixed Slicing bug that threw
;; away first entry. Added handling for a chapter header we missed before.
;; [Version 1.1, 25-Jul-1997, nwv@acm.org] ASCII output wasn't doing Sockets
;; Equivalent field right.
;; [Version 1.0, 25-Jul-1997, nwv@acm.org] Made it work for Palm OS 2.0 docs,
;; which required nontrivial changes. Also made several presentation
;; improvements. Announced for the first time.
;; [Version 0.1, 24-Jul-1997, nwv@acm.org] Just ran into AcroRead text copy
;; problem and also discovered Palm OS 2.0 docs are available now. Releasing
;; this version as a snapshot cuz I'm gonna tackle 2.0 docs and forget about
;; 1.0 doc compatibility. Did not announce.
;;------------------------------------------------------------------ To-Do List
;; This section is mainly for the author's benefit. Mention of something here
;; does not constitute an agreement to someday implement it.
;; --- HIGH PRIORITY ---
;; --- LOW PRIORITY ---
;; Convert the HTML and ASCII generation to use the new `padr-organ-list'.
;; Parse function prototypes and use the information for better presentation
;; and for help in parsing the Parameters field. An EBNF for the prototypes
;; currently used in Palm OS is:
;;
;; --> "(" ")"
;; --> [ { "," }* ]
;; --> [ "const" ] { "*" }*
;; { "[" "]" }*
;; The following system-use-only functions (from 2.0-III-170) do not have
;; either "Purpose" or "Prototype" fields: SerReceiveISP,
;; SerReceiveWindowClose, SerReceiveWindowOpen, SerSetWakeupHandler, SerSleep,
;; SerWake. If we're feeling bored, we mess with the parsing code to grok
;; them, but it's a low priority.
;; "Setting Type Description" table header runs into text. We should probably
;; just kill all table headers since they are out of order anyway due to
;; AcroRead text copy drain-bamage.
;; There is a "Find" category and a "Find" function. Make HTML anchors be OK
;; with this fact.
;; Visually inspect for AcroRead text copy problems such as we had with
;; "DmOpenDatabase".
;; If we really cared about TeX output, we would fix those overfull hbox
;; problems. Especially with the function prototypes.
;; Maybe put a note at beginning of Net section about unformatted tables.
;; Would be nice if we could grok some of the big multipage tables, such as one
;; on III-266. Finding the table start and end not difficult (well, harder cuz
;; of AcroRead text copy ordering problem), but finding cell boundaries is
;; harder.
;; Build in some knowledge about misc. functions and put them in defined
;; category, instead of taking identifier prefix as category.
;; Maybe build in single-phrase summaries of each package.
;; When parsing labels, add word boundaries to the regexps. Tried this and it
;; broke. Maybe need to do "(|)" instead of "<(a|b)>".
;; When trimming headers, add word boundaries to the regexps.
;; Trimming "Serial Manager" is not so good in 1.0. Too bad the docs aren't
;; consistent and use the heading "Serial Manager Functions" instead.
;; Deal with entries continued across pages. There's that little continuation
;; heading (in 1.0 only?) that might be screwing us up.
;; Format ASCII output better. Word-wrap.
;; Maybe unify the two HTML entry formatters and the HTML file begin&end pieces
;; of code.
;; Maybe parse and format "Note:" stuff. Examples in TblSetCustomDrawProcedure
;; (proto), TblSetLoadDataProcedure (proto), TblSetSaveDataProcedure (proto),
;; GetCharCaselessValue (result), GetCharSortValue (result), DateToAscii
;; (proto), SndDoCmd (purpose). Those are 1.0, btw.
;; Put function links at top of each HTML category file.
;; Put function links in every category section of flat HTML file.
;; Add links to function references in the body of Purpose and Comments and the
;; like.
;; Add support for types and global variables, maybe. If not automatically
;; extracting their definitions, at least adding links from references to
;; manually-created HTML for them.
;; Find a PDF->ASCII convertor so that we don't need to inflict this infernal
;; copy&paste upon hapless little users. XPDF 0.7 seg-faulted on
;; "Guide1Win.pdf" when I tried it.
;;-------------------------------------------------------- Package Dependencies
(require 'cl)
;;-------------------------------------------- Package Identification Constants
(defvar padr-version "1.2")
(defvar padr-author "Neil W. Van Dyke (nwv@acm.org)")
;;------------------------------------------------------------------- Constants
(defvar padr-fname-ascii "palmos-funcs.txt")
(defvar padr-fname-html-flat "palmos-funcs.html")
(defvar padr-fname-html-index "palmos-funcs-index.html")
(defvar padr-fname-info "palmos-funcs.info")
(defvar padr-fname-texi "palmos-funcs.texi")
;;------------------------------------------------------------ Global Variables
(defvar padr-entry-list '())
(defvar padr-organ-list '())
(defvar padr-start-time-str nil)
(defvar padr-runner nil)
;;--------------------------------------------------------------- Generic Stuff
(defun padr-neighbor-mapc (func list)
"Calls `func' once for each cell in `list' in order, with three arguments:
the cars of each of the previous, current, and next cells.
`nil' is used when there is no previous or next cell in the list.
For example, (padr-neighbor-mapc 'f '(a b c)) will call the function bound to
symbol `f' three times:
(f nil 'a 'b)
(f 'a 'b 'c)
(f 'b 'c nil)
The called function should not modify `list'.
The return value is `list'."
(let ((prev-car nil)
(cur-cell list))
(while cur-cell
(funcall func
prev-car
(setq prev-car (car cur-cell))
(car (setq cur-cell (cdr cur-cell))))))
list)
(defun padr-object-is-blank (obj)
;; Note: Extend to other types as needed. This is a laziness function.
(cond
((null obj) t)
((stringp obj) (let ((blank t)
(len (length obj))
(pos 0))
(while (and (< pos len)
(or (memq (aref obj pos)
'(?\011 ?\012 ?\015 ?\040))
(setq blank nil))
(setq pos (1+ pos))))
blank))))
(defun padr-str-chr-replace (old-str old-chr new-chr)
(let ((len (length old-str))
(new-str (copy-sequence old-str))
(i 0))
(while (< i len)
(if (= (aref new-str i) old-chr)
(aset new-str i new-chr))
(setq i (1+ i)))
new-str))
(defun padr-str-is-blank (str)
(or (null str)
(save-match-data (string-match "^[ \t]*$" str))))
(defun padr-str-replace-regexp (str regexp replace)
(let ((new "")
(pos 0))
(save-match-data
(while (string-match regexp str pos)
(setq new (concat new
(substring str pos (match-beginning 0))
replace))
(setq pos (match-end 0))))
(concat new (substring str pos))))
(defun padr-str-trim-ws (str)
(save-match-data
(if (string-match "^[ \t\n\r]+" str)
(setq str (substring str (match-end 0))))
(if (string-match "[ \t\n\r]+$" str)
(setq str (substring str 0 (match-beginning 0))))
str))
;;----------------------------------------------------------------- Identifiers
(defun padr-ident-cat (ident)
(save-match-data
(setq case-fold-search nil)
(if (string-match "^\\(UI\\|[A-Z][a-z]+\\)" ident)
(match-string 1 ident))))
;;-------------------------------------------------------- Entry Objects & List
(defun padr-entry-add (name)
(let ((entry (cons name (make-vector 15 nil))))
(setq padr-entry-list (append padr-entry-list (list entry)))
entry))
(defun padr-entry-get (name)
(assoc name padr-entry-list))
(defmacro padr-entry-get-name (entry) `(car ,entry))
(defmacro padr-entry-get-textbegin (entry) `(aref (cdr ,entry) 0))
(defmacro padr-entry-get-textend (entry) `(aref (cdr ,entry) 1))
(defmacro padr-entry-get-purpose (entry) `(aref (cdr ,entry) 2))
(defmacro padr-entry-get-proto (entry) `(aref (cdr ,entry) 3))
(defmacro padr-entry-get-params (entry) `(aref (cdr ,entry) 4))
(defmacro padr-entry-get-result (entry) `(aref (cdr ,entry) 5))
(defmacro padr-entry-get-comments (entry) `(aref (cdr ,entry) 6))
(defmacro padr-entry-get-seealso (entry) `(aref (cdr ,entry) 7))
(defmacro padr-entry-get-warnings (entry) `(aref (cdr ,entry) 8))
(defmacro padr-entry-get-port (entry) `(aref (cdr ,entry) 9))
(defmacro padr-entry-get-rescodes (entry) `(aref (cdr ,entry) 10))
(defmacro padr-entry-get-errors (entry) `(aref (cdr ,entry) 11))
(defmacro padr-entry-get-caveats (entry) `(aref (cdr ,entry) 12))
(defmacro padr-entry-get-sockequiv (entry) `(aref (cdr ,entry) 13))
(defmacro padr-entry-get-sysuse (entry) `(aref (cdr ,entry) 14))
(defmacro padr-entry-set-textbegin (entry val) `(aset (cdr ,entry) 0 ,val))
(defmacro padr-entry-set-textend (entry val) `(aset (cdr ,entry) 1 ,val))
(defmacro padr-entry-set-purpose (entry val) `(aset (cdr ,entry) 2 ,val))
(defmacro padr-entry-set-proto (entry val) `(aset (cdr ,entry) 3 ,val))
(defmacro padr-entry-set-params (entry val) `(aset (cdr ,entry) 4 ,val))
(defmacro padr-entry-set-result (entry val) `(aset (cdr ,entry) 5 ,val))
(defmacro padr-entry-set-comments (entry val) `(aset (cdr ,entry) 6 ,val))
(defmacro padr-entry-set-seealso (entry val) `(aset (cdr ,entry) 7 ,val))
(defmacro padr-entry-set-warnings (entry val) `(aset (cdr ,entry) 8 ,val))
(defmacro padr-entry-set-port (entry val) `(aset (cdr ,entry) 9 ,val))
(defmacro padr-entry-set-rescodes (entry val) `(aset (cdr ,entry) 10 ,val))
(defmacro padr-entry-set-errors (entry val) `(aset (cdr ,entry) 11 ,val))
(defmacro padr-entry-set-caveats (entry val) `(aset (cdr ,entry) 12 ,val))
(defmacro padr-entry-set-sockequiv (entry val) `(aset (cdr ,entry) 13 ,val))
(defmacro padr-entry-set-sysuse (entry val) `(aset (cdr ,entry) 14 ,val))
;;------------------------------------------------------------------------ Main
(defun padr ()
(interactive)
(let ((garbage-collection-messages nil))
(setq padr-start-time-str (current-time-string))
(setq padr-runner
(concat (or (user-full-name) "???")
" ("
(or user-mail-address
(concat (or (user-login-name)
"???")
"@"
(or mail-host-address
(system-name)
"???")))
")"))
(padr-nick-it)
(padr-trim-it)
(padr-slice-it)
(padr-dice-it)
(padr-organ-it)
(padr-flathtml)
(padr-cathtml)
(padr-gentexi)
(padr-genascii)
))
;;--------------------------------------------------------------------- Nicking
(defun padr-nick-it ()
(message "Nicking...")
(let* ((table '(("- " . "")
("\245" . "*")
("\321" . " -- ")
("\322" . "``")
("\323" . "''")
("\325" . "'")
("\336" . "fi")
("\337" . "fl")))
(regexp (mapconcat 'car table "\\|")))
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(replace-match (cdr (assoc (match-string 0) table)) nil t)))
(message "Nicking...done"))
;;-------------------------------------------------------------------- Trimming
(defun padr-trim-it ()
(interactive)
(let ((regexp
(mapconcat
(function
(lambda (item)
(concat "\\(\\([0-9]+ \\)?" item "\\)")))
(list
;; Title
;; (Note: Some footers in 1.0 Part II don't say "Part II".)
;; (Note: 2.0-III p. 51 has no comma in footer. Some poor tech
;; writer is probably doing a lot of this by hand.)
(concat "Developing Palm OS \\(2.0 \\)?Applications"
"\\(,? Part \\(II*\\)\\)?"
"\\( [0-9]+\\)?")
;; Page in 2.0-II
(concat
"Palm OS 2\\.0 implements floating point arithmetic"
".*"
"use the 1\\.0 calls (FplAdd, etc) and don't link in the library.")
;; Top of 2.0-III-168.
(concat "These routines are for use by the system software only"
"[ a-z]*\\.")
;; Part I
"Alarm Manager API"
"Category Functions"
"Character Attribute Functions"
"ClipBoard Functions"
"Control Functions"
"Control, Field, and Insertion Point Functions"
"Error Manager Functions"
"Feature, Time, Float, and String Functions"
"Field UI Functions"
"Find Functions"
"Float Manager Functions"
"Font Functions"
"For System Use Only"
"Form Functions"
"Form, List, and Menu Functions"
"Functions for System Use Only"
"Graffiti Manager Functions"
"GraffitiShift Functions"
"Key Manager Functions"
"List UI Functions"
"Menu Functions"
"Miscellaneous User Interface Functions"
"Other User Interface Functions"
"Pen Manager Functions"
"Pen, Key, and Graffiti Functions"
"Sound Manager Functions"
"String Manager Functions"
"System Event Manager Functions"
"System Functions"
"System Preferences Functions"
"System, Error, Preferences, and Find Functions"
"Table Functions"
"Time Manager Functions"
"Window Functions"
;; Added for 2.0 Part I
"Insertion Point Functions"
"Palm OS User Interface Functions"
"Scrollbar Functions"
"Time Selection Functions"
;; Part II stuff not in Part I
"Communications Functions"
"Data and Resource Manager Functions"
"Functions for System Use Only"
"Memory Manager Functions"
"Miscellaneous Communications Functions"
"PAD Server Functions"
"Serial Link Manager Functions"
;;"Serial Manager" ;; Needed for 1.0, but not 2.0, I think...
;; Added for 2.0 Part II
"Event Manager Functions"
"Feature Functions"
"Miscellaneous System Functions"
"Palm OS System Functions"
"Password Functions"
;; 2.0 Part III
"Berkeley Sockets API Calls"
"Configuration"
"Functions Used Only by System Software"
"Library Open and Close"
"Library Open and Close"
"Memory Management Functions"
"Net Library Functions"
"Send and Receive Routines"
"Serial Manager Functions"
"Socket Connections"
"Socket Creation and Deletion"
"Socket Options"
"Supported Byte Ordering Functions"
"Supported Network Address Conversion Functions"
"Supported Network Utility Functions"
"Supported Socket Functions"
"Supported System Utility Functions"
"Utilities"
;; Table Headers from 2.0 III
"Setting Type Description"
;; (Note: Do more table headers here.)
)
"\\|"))
(deletions-count 0)
(deletions-length 0)
(orig-length (float (- (point-max) (point-min)))))
(goto-char (point-min))
(message "Trimming...started")
(setq case-fold-search nil)
(while (re-search-forward regexp nil t)
(delete-region (match-beginning 0) (match-end 0))
(setq deletions-count (1+ deletions-count)
deletions-length (+ deletions-length
(- (match-end 0)
(match-beginning 0))))
(message "Trimming... (%d%%, %d edits)"
(* (/ (float (+ deletions-length
(point)))
orig-length)
100.0)
deletions-count))
(message "Trimming...done (%d edits)"
deletions-count)))
;;--------------------------------------------------------------------- Slicing
(defun padr-slice-it ()
(let ((entries-count 0)
(orig-length (float (- (point-max) (point-min)))))
(goto-char (point-min))
(setq padr-entry-list '())
(message "Slicing...started")
(let ((last-entry nil))
(setq case-fold-search nil)
(while (progn
;; Note: Too bad not all entries have a "Purpose".
(or (not last-entry)
(re-search-forward "\\" nil t)
(error "Entry has no \"Prototype\" field."))
(re-search-forward
"\\([A-Za-z0-9]+\\) \\(Purpose\\>\\|Prototype\\>\\)"
nil t))
(if last-entry
(padr-entry-set-textend last-entry (match-beginning 0)))
(setq last-entry (padr-entry-add (match-string 1)))
(setq entries-count (1+ entries-count))
(if (string= (match-string 2) "Purpose")
(padr-entry-set-textbegin last-entry (match-end 0))
(goto-char (match-beginning 2))
(padr-entry-set-textbegin last-entry (point)))
(message "Slicing... (%d%%, %d entries)"
(* (/ (float (point)) orig-length) 100.0)
entries-count))
(if last-entry (padr-entry-set-textend last-entry (point-max))))
(message "Slicing...done (%d entries)" entries-count)))
;;---------------------------------------------------------------------- Dicing
(defun padr-dice-it ()
(message "Dicing...started")
(let* ((entries-count (float (length padr-entry-list)))
(entry-num 0)
(label-list '(("2.0 Note" . port)
("Caveats" . caveats)
("Caveat" . caveats)
("Comments" . comments)
("Comment" . comments)
("Parameters" . params)
("Prototype" . proto)
("Result Codes" . rescodes)
("Result" . result)
("See Also" . seealso)
("Sockets Equivalent" . sockequiv)
("comment" . comments)
("WARNING:" . warning)
("Warning:" . warning)))
(label-regexp (concat ;;"\\<\\("
(mapconcat (function (lambda (n)
(car n)))
label-list
"\\|")
;;"\\)\\>"
)))
(setq case-fold-search nil)
(mapc (function
(lambda (entry)
(let* ((entry-textbegin (padr-entry-get-textbegin entry))
(entry-textend (padr-entry-get-textend entry))
(last-begin entry-textbegin)
(last-label 'purpose))
(goto-char entry-textbegin)
(while (re-search-forward label-regexp entry-textend t)
(padr-dice-process-part entry last-label last-begin
(match-beginning 0))
(setq last-label (cdr (assoc (match-string 0) label-list)))
(setq last-begin (match-end 0)))
(padr-dice-process-part entry last-label last-begin
entry-textend))
(setq entry-num (1+ entry-num))
(message "Dicing... (%d%%)"
(* (/ (float entry-num) entries-count) 100.0))))
padr-entry-list))
(message "Dicing...done"))
(defun padr-dice-process-part (entry label begin end)
(let ((text (padr-str-chr-replace
(padr-str-trim-ws (buffer-substring-no-properties begin end))
?\260 ?*)))
(ecase label
;; The easy ones.
('caveats (padr-entry-set-caveats entry text))
('comments (padr-entry-set-comments entry text))
('errors (padr-entry-set-errors entry text))
('params (padr-entry-set-params entry text))
('port (padr-entry-set-port entry text))
('proto (padr-entry-set-proto entry text))
('purpose (padr-entry-set-purpose entry text))
('rescodes (padr-entry-set-rescodes entry text))
('result (padr-entry-set-result entry text))
('sockequiv (padr-entry-set-sockequiv entry text))
;; The trickier ones.
('seealso
;; Some of these kludges are worthy of even a certain large software
;; company that we won't name (in case we ever need a job from them).
(if (string= (padr-entry-get-name entry) "DmOpenDatabase")
(save-match-data
(setq case-fold-search nil)
(if (string-match "dmModeReadWrite.*database" text)
(let ((table (match-string 0 text))
(comments (padr-entry-get-comments entry)))
(setq text (concat (substring text 0 (match-beginning 0))
(substring text (match-end 0))))
(or (string-match "together:" comments)
(error "Can't kludge \"DmOpenDatabase\"."))
(padr-entry-set-comments
entry
(concat (substring comments 0 (match-end 0))
" "
table
" "
(substring comments (match-end 0))))))))
(padr-entry-set-seealso entry (padr-dice-seealso-list-parse text)))
('warning
;; Ones found in 2.0 docs: "For System Use Only." "System Use Only!"
;; "System Use Only." "System use only!" "This function for System use
;; only" "This function for use by system software only." Impressive,
;; no?
(setq case-fold-search t)
(save-match-data
(if (or (string= text ".")
(string-match "system use only\\|for use by system" text))
(padr-entry-set-sysuse entry t)
(let ((existing (padr-entry-get-warnings entry)))
(padr-entry-set-warnings entry
(if existing
(append existing (list text))
(list text))))))
(setq case-fold-search nil)))))
(defun padr-dice-seealso-list-parse (str)
(let ((list nil)
(start 0))
(save-match-data
(setq case-fold-search nil)
(while (string-match
"\\(``[^']*''\\)\\|\\(\"[^\"]*\"\\)\\|\\([A-Za-z0-9]+\\)"
str start)
(let ((match (match-string 0 str)))
(if (not (or (= (aref match 0) ?\")
(= (aref match 0) ?\`)
(string= match "documented")
(string= match "in")))
;; C'mon, it's only a kludgey one-shot program...
;; Actually, it won't be necessary if we use word boundaries on
;; page numbers preceding headers when trimming, like good boys.
(setq list (append list
(list (if (= (aref match (1- (length match)))
?V)
(concat match "10")
match)))))
(setq start (match-end 0)))))
list))
;;------------------------------------------------------------------ Organizing
(defun padr-organ-it ()
;; "Huhuhuh... He said `organ'..."
(message "Organizing...")
;; Sort the entry list.
(setq padr-entry-list (sort padr-entry-list
(function (lambda (a b)
(string-lessp (car a) (car b))))))
;; Uniquify the names.
(let ((last-name nil))
(mapc (function
(lambda (entry)
(if (string= last-name
(setq last-name (car entry)))
(setcar entry (concat last-name "-2")))))
padr-entry-list))
;; Build the organized list.
(setq padr-organ-list '())
(let ((last-cat nil)
(last-cell nil))
(mapc (function
(lambda (entry)
(let* ((name (padr-entry-get-name entry))
(cat (padr-ident-cat name))
(cell (cons entry nil)))
(or cat
(error "Entry name \"%s\" has no category." name))
(if (string= cat last-cat)
(setcdr last-cell cell)
(setq padr-organ-list (append padr-organ-list
(list (cons cat cell))))
(setq last-cat cat))
(setq last-cell cell))))
padr-entry-list))
(message "Organizing...done"))
;;---------------------------------------------------------- TeXinfo Generation
(defun padr-gentexi ()
(find-file padr-fname-texi)
(message "Generating TeXinfo...")
(delete-region (point-min) (point-max))
(padr-gentexi-do-begin)
(padr-gentexi-do-tofu)
(padr-gentexi-do-end)
(save-buffer)
(kill-buffer (current-buffer))
(message "Generating TeXinfo...done"))
(defun padr-gentexi-chap-node (organ-cat)
;; Note: Change index node name if we someday get a category called "Index".
(concat (car organ-cat) "*"))
(defun padr-gentexi-escape (str)
(let ((new "")
(pos 0))
(save-match-data
(while (string-match "@\\|{\\|}" str pos)
(setq new (concat new
(substring str pos (match-beginning 0))
"@"
(match-string 0 str)))
(setq pos (match-end 0))))
(concat new (substring str pos))))
(defun padr-gentexi-do-begin ()
(insert
"\\input texinfo @c -*-texinfo-*-\n"
"@c %**start of header\n"
"@setfilename "
padr-fname-info
"\n"
"@settitle Palm OS Functions\n"
"@setchapternewpage odd\n"
"@syncodeindex fn cp\n"
"@c %**end of header\n"
"\n"
"@ifinfo\n"
"Program Name: PADR "
padr-version
"\n"
"Program Author: "
(padr-gentexi-escape padr-author)
"\n"
"Run By: "
(padr-gentexi-escape padr-runner)
"\n"
"Run At: "
padr-start-time-str
"\n"
"@end ifinfo\n"
"\n"
"@titlepage\n"
"\n"
"@title Palm OS Functions\n"
"@subtitle For the U.S. Robotics PalmPilot SDK\n"
"@author Reformatted by PADR "
padr-version
"\n"
"\n"
"@page\n"
"@vskip 0pt plus 1filll\n"
"Copyright @copyright{} U.S. Robotics\n"
"\n"
"This was presumably reformatted by you for your own personal use.\n"
"Giving copies of this to others is probably a legal no-no.\n"
"\n"
"@end titlepage\n"
"\n"
"@node Top, "
(padr-gentexi-chap-node (car padr-organ-list))
", (dir), (dir)\n"
"\n"
"@ifinfo\n"
"@c @noindent\n"
"@top Palm OS Functions\n"
"\n"
"This documentation is Copyright U.S. Robotics, Inc.\n"
"It was presumably reformatted by you for your own personal use.\n"
"Giving copies of this to others is probably a legal no-no.\n"
"@end ifinfo\n"
"\n"
"@menu\n")
(mapc (function
(lambda (cat)
(insert "* " (padr-gentexi-chap-node cat) "::\n")))
padr-organ-list)
(insert
"\n* Index::\n"
"@end menu\n"))
(defun padr-gentexi-do-end ()
(insert
"\n@node Index, , "
(padr-gentexi-chap-node (car (last padr-organ-list)))
", Top\n"
"@unnumbered Index\n"
"@printindex cp\n"
"@summarycontents\n"
"@contents\n"
"@bye\n"))
(defun padr-gentexi-do-tofu ()
;; This is the meat of the TeXinfo file.
;; Chapter and section nodes.
(padr-neighbor-mapc
(function
(lambda (prev-cat cat next-cat)
(let ((cat-name (car cat))
(chap-node (padr-gentexi-chap-node cat)))
;; Begin chapter node.
(insert
"\n@node "
chap-node
", "
(if next-cat (padr-gentexi-chap-node next-cat) "Index")
", "
(if prev-cat (padr-gentexi-chap-node prev-cat) "Top")
", "
"Top\n@chapter "
cat-name
" Category\n"
"@cindex @code{"
cat-name
"} category\n")
;; Chapter menu.
(insert "\n@menu\n")
(mapc (function
(lambda (entry)
(insert "* "
(padr-entry-get-name entry)
"::\n")))
(cdr cat))
(insert "@end menu\n")
;; Chapter section nodes.
(padr-neighbor-mapc
(function
(lambda (prev-entry entry next-entry)
(let ((entry-name (padr-entry-get-name entry)))
;; Begin entry node.
(insert
"\n@node "
entry-name
", "
(if next-entry (padr-entry-get-name next-entry) " ")
", "
(if prev-entry (padr-entry-get-name prev-entry) chap-node)
", "
chap-node
"\n"
"@ifinfo\n"
"@section "
entry-name
" Function\n"
"@end ifinfo\n"
"@iftex\n"
"@section "
entry-name
"\n"
"@end iftex\n"
"@findex "
entry-name
"\n@table @sc\n")
;; Entry fields.
(padr-gentexi-field "Purpose" (padr-entry-get-purpose entry) t)
(padr-gentexi-field "Prototype"
(let ((n (padr-entry-get-proto entry)))
(if n
(concat "@ifinfo\n"
(padr-gentexi-escape n)
"\n@end ifinfo\n"
"@iftex\n"
"@code{"
(padr-gentexi-escape n)
"}\n"
"@end iftex\n")))
nil)
(padr-gentexi-field "Parameters" (padr-entry-get-params entry) t)
(padr-gentexi-field "Result" (padr-entry-get-result entry) t)
(padr-gentexi-field "Result Codes"
(padr-entry-get-rescodes entry) t)
(padr-gentexi-field "Errors" (padr-entry-get-errors entry) t)
(padr-gentexi-field "Comments" (padr-entry-get-comments entry) t)
(padr-gentexi-field "Caveats" (padr-entry-get-caveats entry) t)
(padr-gentexi-field "Sockets Equivalent"
(padr-entry-get-sockequiv entry) t)
(padr-gentexi-field "Portability" (padr-entry-get-port entry) t)
(padr-gentexi-field "Warnings" (padr-entry-get-warnings entry) t)
(padr-gentexi-field "See Also"
(let ((n (padr-entry-get-seealso entry)))
(if n
(concat "@ifinfo\n"
(mapconcat
(function
(lambda (x)
(if (padr-entry-get x)
(concat "@ref{" x "}")
x)))
n
".@*\n")
".\n"
"@end ifinfo\n"
"@iftex\n"
(mapconcat
(function
(lambda (x)
(concat "@code{" x "}")))
n
",\n")
"\n@end iftex\n")))
nil)
;; End entry node.
(insert "\n@end table\n"))))
(cdr cat)))))
padr-organ-list))
(defun padr-gentexi-field (label text escape)
(if (not (padr-object-is-blank text))
(progn
(if (listp text)
(let ((temp text))
(setq text (mapconcat 'identity temp " "))))
(if escape
(setq text (padr-gentexi-escape text)))
(insert "\n@item "
label
"\n"
text
"\n"))))
;;------------------------------------------------------------ ASCII Generation
(defun padr-genascii ()
(find-file padr-fname-ascii)
(message "Generating ASCII...")
(delete-region (point-min) (point-max))
(mapc (function
(lambda (entry)
(insert "\n"
"---- "
(padr-entry-get-name entry)
" ----\n")
(if (padr-entry-get-sysuse entry)
(insert "(System Use Only)\n"))
(padr-genascii-field "Purpose" (padr-entry-get-purpose entry))
(padr-genascii-field "Prototype" (padr-entry-get-proto entry))
(padr-genascii-field "Parameters" (padr-entry-get-params entry))
(padr-genascii-field "Result" (padr-entry-get-result entry))
(padr-genascii-field "Result Codes" (padr-entry-get-rescodes entry))
(padr-genascii-field "Errors" (padr-entry-get-errors entry))
(padr-genascii-field "Comments" (padr-entry-get-comments entry))
(padr-genascii-field "Caveats" (padr-entry-get-caveats entry))
(padr-genascii-field "Sockets Equivalent"
(padr-entry-get-sockequiv entry))
(padr-genascii-field "Portability" (padr-entry-get-port entry))
(padr-genascii-field "Warnings" (padr-entry-get-warnings entry))
(padr-genascii-field "See Also" (padr-entry-get-seealso entry))
))
padr-entry-list)
(save-buffer)
(kill-buffer (current-buffer))
(message "Generating ASCII...done"))
(defun padr-genascii-field (label text)
(if (not (padr-object-is-blank text))
(insert (upcase label)
": "
(if (listp text)
(mapconcat 'identity text " ")
text)
"\n")))
;;------------------------------------------------- Categorized HTML Generation
(defun padr-cathtml ()
(message "Generating Categorized HTML...")
(let ((cat-list '()))
;; Generate
(let ((last-cat nil))
(mapc (function
(lambda (entry)
(let* ((name (padr-entry-get-name entry))
(cat (padr-ident-cat name)))
(or cat (error "Function name \"%s\" has no category." name))
(or (string= cat last-cat)
(progn
(if last-cat
(padr-cathtml-file-end last-cat))
(setq cat-list (append cat-list (list cat)))
(padr-cathtml-file-begin cat)
(message "Generating Categorized HTML... (%s category)"
cat)
(setq last-cat cat)))
(insert ""
""
name
(if (padr-entry-get-sysuse entry)
(concat "\n"
""
""
"(System Use Only)"
""
"")
"")
"
\n"
""
"
\n")
(padr-cathtml-field "Purpose" (padr-entry-get-purpose entry))
(padr-cathtml-field "Prototype"
(let ((n (padr-entry-get-proto entry)))
(if n
(concat "" n ""))))
(padr-cathtml-field "Parameters"
(padr-entry-get-params entry))
(padr-cathtml-field "Result" (padr-entry-get-result entry))
(padr-cathtml-field "Result Codes"
(padr-entry-get-rescodes entry))
(padr-cathtml-field "Errors" (padr-entry-get-errors entry))
(padr-cathtml-field "Comments"
(padr-entry-get-comments entry))
(padr-cathtml-field "Caveats" (padr-entry-get-caveats entry))
(padr-cathtml-field "Sockets
Equivalent"
(padr-entry-get-sockequiv entry))
(padr-cathtml-field "Portability" (padr-entry-get-port entry))
(padr-cathtml-field "Warnings"
(padr-entry-get-warnings entry))
(padr-cathtml-field
"See Also"
(let ((n (padr-entry-get-seealso entry)))
(if n
(mapconcat (function
(lambda (e)
(concat ""
e
"")))
n
", "))))
(insert "
"
"
"
"\n"))))
padr-entry-list)
(if last-cat
(padr-cathtml-file-end last-cat)))
;; Generate index.
(message "Generating Categorized HTML... (index)")
(padr-cathtml-file-begin nil)
(insert ""
(mapconcat (function
(lambda (cat)
(concat ""
""
cat
""
""
"\n")))
cat-list
", ")
"
\n")
(padr-cathtml-file-end nil)
;; End
)
;; Done message.
(message "Generating Categorized HTML...done"))
(defun padr-cathtml-fname (cat)
(concat "palmos-funcs-cat-" (downcase cat) ".html"))
(defun padr-cathtml-href (cur-cat ident)
(let ((ident-cat (padr-ident-cat ident)))
(or ident-cat (error "Identifier \"%s\" has no category." ident))
(concat (if (string= ident-cat cur-cat)
""
(padr-cathtml-fname ident-cat))
"#"
ident)))
(defun padr-cathtml-file-begin (cat)
(find-file (if cat
(padr-cathtml-fname cat)
padr-fname-html-index))
(delete-region (point-min) (point-max))
(let ((title (concat "Palm OS Functions" (if cat
(concat ": " cat)
""))))
(insert
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
""
title
"\n"
"\n"
"\n"
""
title
"
\n"
(if cat
(concat
""
""
"[Return to Index]"
""
"
\n")
(concat
""
""
"This documentation is Copyright © U.S. Robotics, Inc.
\n"
"It was presumably reformatted by you for your own personal use.
\n"
"Giving copies of this to others is probably a legal no-no."
""
"
\n")))))
(defun padr-cathtml-file-end (cat)
(insert (if cat
(concat ""
""
"Copyright © U.S. Robotics, Inc."
""
"
\n")
"")
"\n"
"\n")
(goto-char (point-min))
(save-buffer)
(kill-buffer (current-buffer)))
(defun padr-cathtml-field (label text)
(if (not (padr-object-is-blank text))
(insert "\n"
"| "
""
label
""
" | \n"
""
(if (listp text)
(mapconcat 'identity
text
"\n")
text)
" | \n"
"
\n")))
;;-------------------------------------------------------- Flat HTML Generation
(defun padr-flathtml ()
(message "Generating Flat HTML...")
(find-file padr-fname-html-flat)
(delete-region (point-min) (point-max))
(let ((index-cookie "")
(cat-list '()))
(insert
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"Palm OS Functions\n"
"\n"
"\n"
"Palm OS Functions
\n"
""
""
"This documentation is Copyright © U.S. Robotics, Inc.
\n"
"It was presumably reformatted by you for your own personal use.
\n"
"Giving copies of this to others is probably a legal no-no."
""
"
\n"
index-cookie)
(let ((last-cat nil))
(mapc (function
(lambda (entry)
(let* ((name (padr-entry-get-name entry))
(cat (padr-ident-cat name)))
(if (not (string= cat last-cat))
(progn
(insert ""
"
"
"\n")
(setq last-cat cat)
(setq cat-list (append cat-list (list cat)))))
(insert ""
""
name
(if (padr-entry-get-sysuse entry)
(concat "\n"
""
""
"(System Use Only)"
""
"")
"")
"
\n"
""
"
\n")
(padr-flathtml-field "Purpose" (padr-entry-get-purpose entry))
(padr-flathtml-field
"Prototype"
(let ((n (padr-entry-get-proto entry)))
(if n (concat "" n ""))))
(padr-flathtml-field "Parameters"
(padr-entry-get-params entry))
(padr-flathtml-field "Result"
(padr-entry-get-result entry))
(padr-flathtml-field "Result Codes"
(padr-entry-get-rescodes entry))
(padr-flathtml-field "Errors"
(padr-entry-get-errors entry))
(padr-flathtml-field "Comments"
(padr-entry-get-comments entry))
(padr-flathtml-field "Caveats"
(padr-entry-get-caveats entry))
(padr-flathtml-field "Sockets
Equivalent"
(padr-entry-get-sockequiv entry))
(padr-flathtml-field "Portability"
(padr-entry-get-port entry))
(padr-flathtml-field "Warnings"
(padr-entry-get-warnings entry))
(padr-flathtml-field
"See Also"
(let ((n (padr-entry-get-seealso entry)))
(if n
(mapconcat (function
(lambda (e)
(concat ""
e
"")))
n
", "))))
(insert "
"
""
"\n"))))
padr-entry-list))
(insert "
\n"
""
""
"Copyright © U.S. Robotics, Inc."
""
"
\n"
"\n"
"\n")
;; Backpatch the category index.
(goto-char (point-min))
(setq case-fold-search nil)
(or (search-forward index-cookie nil t)
(error "Couldn't find index cookie."))
(replace-match (concat "
\n"
""
(mapconcat (function
(lambda (cat)
(concat ""
""
cat
""
"")))
cat-list
", ")
"
\n")
t t)
;;
)
;;; Save file and finish.
(save-buffer)
(kill-buffer (current-buffer))
(message "Generating Flat HTML...done"))
(defun padr-flathtml-field (label text)
(if (not (padr-object-is-blank text))
(insert "\n"
"| "
""
label
""
" | \n"
""
(if (listp text)
(mapconcat 'identity
text
"\n")
text)
" | \n"
"
\n")))
;;-----------------------------------------------------------------------------
(provide 'padr)
;;EOF