wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit ae3c20b7ae11c1becd86198475162f5ad9dbb222
parent c04f3ec6a0a6ceac3c1d968222e1b15969a01753
Author: Kris Maglione <kris@suckless.org>
Date:   Sat, 22 May 2010 20:55:16 -0400

Cleanup the top directory a bit. sed -i 's/\$\{([^{]+)\}/$(\1)/g' **/Makefile **/*.mk

Diffstat:
Makefile | 19+++++--------------
NEWS | 3+++
cmd/click/Makefile | 8++++----
cmd/strut/Makefile | 8++++----
include/Makefile | 4++--
lib/Makefile | 18++++++++++++++++++
lib/libbio/Makefile | 27+++++++++++++++++++++++++++
lib/libbio/NOTICE | 34++++++++++++++++++++++++++++++++++
lib/libbio/README | 5+++++
lib/libbio/bbuffered.c | 20++++++++++++++++++++
lib/libbio/bcat.c | 46++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/bfildes.c | 9+++++++++
lib/libbio/bflush.c | 33+++++++++++++++++++++++++++++++++
lib/libbio/bgetc.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/bgetd.c | 36++++++++++++++++++++++++++++++++++++
lib/libbio/bgetrune.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/binit.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/bio.3 | 371+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/boffset.c | 25+++++++++++++++++++++++++
lib/libbio/bprint.c | 14++++++++++++++
lib/libbio/bputc.c | 20++++++++++++++++++++
lib/libbio/bputrune.c | 23+++++++++++++++++++++++
lib/libbio/brdline.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/brdstr.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/bread.c | 45+++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/bseek.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libbio/bvprint.c | 36++++++++++++++++++++++++++++++++++++
lib/libbio/bwrite.c | 38++++++++++++++++++++++++++++++++++++++
lib/libfmt/Makefile | 48++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/NOTICE | 25+++++++++++++++++++++++++
lib/libfmt/README | 5+++++
lib/libfmt/charstod.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/dofmt.c | 537+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/dorfmt.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/errfmt.c | 28++++++++++++++++++++++++++++
lib/libfmt/fltfmt.c | 392+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmt.c | 218+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtdef.h | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtfd.c | 46++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtfdflush.c | 34++++++++++++++++++++++++++++++++++
lib/libfmt/fmtinstall.3 | 379+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtlock.c | 27+++++++++++++++++++++++++++
lib/libfmt/fmtprint.c | 48++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtquote.c | 264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtrune.c | 40++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fmtstr.c | 27+++++++++++++++++++++++++++
lib/libfmt/fmtvprint.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/fprint.c | 29+++++++++++++++++++++++++++++
lib/libfmt/libfmt.a | 0
lib/libfmt/nan64.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/pow10.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/print.3 | 482+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/print.c | 29+++++++++++++++++++++++++++++
lib/libfmt/runefmtstr.c | 27+++++++++++++++++++++++++++
lib/libfmt/runeseprint.c | 30++++++++++++++++++++++++++++++
lib/libfmt/runesmprint.c | 30++++++++++++++++++++++++++++++
lib/libfmt/runesnprint.c | 31+++++++++++++++++++++++++++++++
lib/libfmt/runesprint.c | 30++++++++++++++++++++++++++++++
lib/libfmt/runevseprint.c | 40++++++++++++++++++++++++++++++++++++++++
lib/libfmt/runevsmprint.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/runevsnprint.c | 39+++++++++++++++++++++++++++++++++++++++
lib/libfmt/seprint.c | 29+++++++++++++++++++++++++++++
lib/libfmt/smprint.c | 29+++++++++++++++++++++++++++++
lib/libfmt/snprint.c | 30++++++++++++++++++++++++++++++
lib/libfmt/sprint.c | 37+++++++++++++++++++++++++++++++++++++
lib/libfmt/strtod.c | 532+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/test.c | 44++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/test2.c | 9+++++++++
lib/libfmt/test3.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/vfprint.c | 33+++++++++++++++++++++++++++++++++
lib/libfmt/vseprint.c | 39+++++++++++++++++++++++++++++++++++++++
lib/libfmt/vsmprint.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libfmt/vsnprint.c | 39+++++++++++++++++++++++++++++++++++++++
lib/libregexp/Makefile | 17+++++++++++++++++
lib/libregexp/NOTICE | 25+++++++++++++++++++++++++
lib/libregexp/README | 5+++++
lib/libregexp/regaux.c | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/regcomp.c | 559+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/regerror.c | 15+++++++++++++++
lib/libregexp/regexec.c | 232+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/regexp9.3 | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/regexp9.7 | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/regsub.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/rregexec.c | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/rregsub.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/test.c | 46++++++++++++++++++++++++++++++++++++++++++++++
lib/libregexp/test2.c | 20++++++++++++++++++++
lib/libstuff/Makefile | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/buffer.c | 8++++++++
lib/libstuff/clientutil.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/event/buttonpress.c | 14++++++++++++++
lib/libstuff/event/buttonrelease.c | 12++++++++++++
lib/libstuff/event/clientmessage.c | 10++++++++++
lib/libstuff/event/configurenotify.c | 12++++++++++++
lib/libstuff/event/configurerequest.c | 24++++++++++++++++++++++++
lib/libstuff/event/destroynotify.c | 12++++++++++++
lib/libstuff/event/enternotify.c | 16++++++++++++++++
lib/libstuff/event/event.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/event/event.h | 9+++++++++
lib/libstuff/event/expose.c | 12++++++++++++
lib/libstuff/event/focusin.c | 27+++++++++++++++++++++++++++
lib/libstuff/event/focusout.c | 19+++++++++++++++++++
lib/libstuff/event/keypress.c | 13+++++++++++++
lib/libstuff/event/leavenotify.c | 13+++++++++++++
lib/libstuff/event/mapnotify.c | 12++++++++++++
lib/libstuff/event/mappingnotify.c | 11+++++++++++
lib/libstuff/event/maprequest.c | 12++++++++++++
lib/libstuff/event/motionnotify.c | 13+++++++++++++
lib/libstuff/event/propertynotify.c | 13+++++++++++++
lib/libstuff/event/unmapnotify.c | 15+++++++++++++++
lib/libstuff/event/xtime.c | 33+++++++++++++++++++++++++++++++++
lib/libstuff/geom/get_sticky.c | 24++++++++++++++++++++++++
lib/libstuff/geom/quadrant.c | 23+++++++++++++++++++++++
lib/libstuff/geom/rect_contains_p.c | 12++++++++++++
lib/libstuff/geom/rect_haspoint_p.c | 10++++++++++
lib/libstuff/geom/rect_intersect_p.c | 12++++++++++++
lib/libstuff/geom/rect_intersection.c | 17+++++++++++++++++
lib/libstuff/init_screens.c | 9+++++++++
lib/libstuff/map.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/printevent.c | 994+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/printevent.h | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/_die.c | 26++++++++++++++++++++++++++
lib/libstuff/util/backtrace.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/closeexec.c | 12++++++++++++
lib/libstuff/util/comm.c | 42++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/doublefork.c | 30++++++++++++++++++++++++++++++
lib/libstuff/util/emalloc.c | 11+++++++++++
lib/libstuff/util/emallocz.c | 11+++++++++++
lib/libstuff/util/erealloc.c | 11+++++++++++
lib/libstuff/util/estrdup.c | 12++++++++++++
lib/libstuff/util/estrndup.c | 15+++++++++++++++
lib/libstuff/util/fatal.c | 39+++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/freelater.c | 15+++++++++++++++
lib/libstuff/util/getbase.c | 43+++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/getint.c | 14++++++++++++++
lib/libstuff/util/getlong.c | 23+++++++++++++++++++++++
lib/libstuff/util/getulong.c | 23+++++++++++++++++++++++
lib/libstuff/util/grep.c | 22++++++++++++++++++++++
lib/libstuff/util/join.c | 22++++++++++++++++++++++
lib/libstuff/util/max.c | 10++++++++++
lib/libstuff/util/mfatal.c | 33+++++++++++++++++++++++++++++++++
lib/libstuff/util/min.c | 10++++++++++
lib/libstuff/util/pathsearch.c | 32++++++++++++++++++++++++++++++++
lib/libstuff/util/refree.c | 13+++++++++++++
lib/libstuff/util/reinit.c | 16++++++++++++++++
lib/libstuff/util/spawn3.c | 43+++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/spawn3l.c | 28++++++++++++++++++++++++++++
lib/libstuff/util/stokenize.c | 22++++++++++++++++++++++
lib/libstuff/util/strcasestr.c | 25+++++++++++++++++++++++++
lib/libstuff/util/strend.c | 13+++++++++++++
lib/libstuff/util/strlcat.c | 26++++++++++++++++++++++++++
lib/libstuff/util/strlcatprint.c | 19+++++++++++++++++++
lib/libstuff/util/sxprint.c | 14++++++++++++++
lib/libstuff/util/tokenize.c | 21+++++++++++++++++++++
lib/libstuff/util/uniq.c | 18++++++++++++++++++
lib/libstuff/util/unquote.c | 38++++++++++++++++++++++++++++++++++++++
lib/libstuff/util/utflcpy.c | 11+++++++++++
lib/libstuff/util/util.h | 5+++++
lib/libstuff/util/vector.c | 33+++++++++++++++++++++++++++++++++
lib/libstuff/util/vsxprint.c | 13+++++++++++++
lib/libstuff/x11/colors/loadcolor.c | 18++++++++++++++++++
lib/libstuff/x11/colors/namedcolor.c | 22++++++++++++++++++++++
lib/libstuff/x11/colors/xftcolor.c | 19+++++++++++++++++++
lib/libstuff/x11/convpts.c | 17+++++++++++++++++
lib/libstuff/x11/drawing/border.c | 19+++++++++++++++++++
lib/libstuff/x11/drawing/drawline.c | 11+++++++++++
lib/libstuff/x11/drawing/drawpoly.c | 15+++++++++++++++
lib/libstuff/x11/drawing/drawstring.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/drawing/fill.c | 11+++++++++++
lib/libstuff/x11/drawing/fillpoly.c | 14++++++++++++++
lib/libstuff/x11/errors.c | 40++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/focus/getfocus.c | 13+++++++++++++
lib/libstuff/x11/focus/setfocus.c | 9+++++++++
lib/libstuff/x11/freestringlist.c | 9+++++++++
lib/libstuff/x11/geometry/XRect.c | 15+++++++++++++++
lib/libstuff/x11/geometry/addpt.c | 11+++++++++++
lib/libstuff/x11/geometry/divpt.c | 11+++++++++++
lib/libstuff/x11/geometry/eqpt.c | 9+++++++++
lib/libstuff/x11/geometry/eqrect.c | 10++++++++++
lib/libstuff/x11/geometry/insetrect.c | 13+++++++++++++
lib/libstuff/x11/geometry/mulpt.c | 11+++++++++++
lib/libstuff/x11/geometry/rectaddpt.c | 13+++++++++++++
lib/libstuff/x11/geometry/rectsetorigin.c | 15+++++++++++++++
lib/libstuff/x11/geometry/rectsubpt.c | 13+++++++++++++
lib/libstuff/x11/geometry/subpt.c | 11+++++++++++
lib/libstuff/x11/ignored_xerrors.c | 9+++++++++
lib/libstuff/x11/images/allocimage.c | 21+++++++++++++++++++++
lib/libstuff/x11/images/copyimage.c | 13+++++++++++++
lib/libstuff/x11/images/freeimage.c | 18++++++++++++++++++
lib/libstuff/x11/images/xftdrawable.c | 11+++++++++++
lib/libstuff/x11/initdisplay.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/insanity/gravitate.c | 19+++++++++++++++++++
lib/libstuff/x11/insanity/sethints.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/insanity/sizehint.c | 42++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/keyboard/grabkeyboard.c | 12++++++++++++
lib/libstuff/x11/keyboard/ungrabkeyboard.c | 9+++++++++
lib/libstuff/x11/keys/keycode.c | 9+++++++++
lib/libstuff/x11/keys/parsekey.c | 46++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/mouse/grabpointer.c | 16++++++++++++++++
lib/libstuff/x11/mouse/pointerscreen.c | 15+++++++++++++++
lib/libstuff/x11/mouse/querypointer.c | 15+++++++++++++++
lib/libstuff/x11/mouse/translate.c | 14++++++++++++++
lib/libstuff/x11/mouse/ungrabpointer.c | 9+++++++++
lib/libstuff/x11/mouse/warppointer.c | 23+++++++++++++++++++++++
lib/libstuff/x11/properties/changeprop_char.c | 9+++++++++
lib/libstuff/x11/properties/changeprop_long.c | 9+++++++++
lib/libstuff/x11/properties/changeprop_short.c | 9+++++++++
lib/libstuff/x11/properties/changeprop_string.c | 10++++++++++
lib/libstuff/x11/properties/changeprop_textlist.c | 24++++++++++++++++++++++++
lib/libstuff/x11/properties/changeprop_ulong.c | 9+++++++++
lib/libstuff/x11/properties/changeproperty.c | 11+++++++++++
lib/libstuff/x11/properties/delproperty.c | 9+++++++++
lib/libstuff/x11/properties/getprop.c | 28++++++++++++++++++++++++++++
lib/libstuff/x11/properties/getprop_long.c | 19+++++++++++++++++++
lib/libstuff/x11/properties/getprop_string.c | 19+++++++++++++++++++
lib/libstuff/x11/properties/getprop_textlist.c | 22++++++++++++++++++++++
lib/libstuff/x11/properties/getprop_ulong.c | 10++++++++++
lib/libstuff/x11/properties/getproperty.c | 12++++++++++++
lib/libstuff/x11/properties/strlistdup.c | 29+++++++++++++++++++++++++++++
lib/libstuff/x11/sendevent.c | 9+++++++++
lib/libstuff/x11/sendmessage.c | 20++++++++++++++++++++
lib/libstuff/x11/setgccol.c | 9+++++++++
lib/libstuff/x11/shape/setshapemask.c | 11+++++++++++
lib/libstuff/x11/sync.c | 9+++++++++
lib/libstuff/x11/text/freefont.c | 23+++++++++++++++++++++++
lib/libstuff/x11/text/labelh.c | 9+++++++++
lib/libstuff/x11/text/loadfont.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libstuff/x11/text/textextents_l.c | 34++++++++++++++++++++++++++++++++++
lib/libstuff/x11/text/textwidth.c | 10++++++++++
lib/libstuff/x11/text/textwidth_l.c | 12++++++++++++
lib/libstuff/x11/windows/configwin.c | 22++++++++++++++++++++++
lib/libstuff/x11/windows/createwindow.c | 9+++++++++
lib/libstuff/x11/windows/createwindow_visual.c | 33+++++++++++++++++++++++++++++++++
lib/libstuff/x11/windows/destroywindow.c | 16++++++++++++++++
lib/libstuff/x11/windows/findwin.c | 14++++++++++++++
lib/libstuff/x11/windows/getwinrect.c | 15+++++++++++++++
lib/libstuff/x11/windows/lowerwin.c | 10++++++++++
lib/libstuff/x11/windows/mapwin.c | 15+++++++++++++++
lib/libstuff/x11/windows/movewin.c | 13+++++++++++++
lib/libstuff/x11/windows/raisewin.c | 10++++++++++
lib/libstuff/x11/windows/reparentwindow.c | 13+++++++++++++
lib/libstuff/x11/windows/reshapewin.c | 12++++++++++++
lib/libstuff/x11/windows/selectinput.c | 9+++++++++
lib/libstuff/x11/windows/setborder.c | 14++++++++++++++
lib/libstuff/x11/windows/sethandler.c | 23+++++++++++++++++++++++
lib/libstuff/x11/windows/setwinattr.c | 10++++++++++
lib/libstuff/x11/windows/unmapwin.c | 16++++++++++++++++
lib/libstuff/x11/windows/window.c | 14++++++++++++++
lib/libstuff/x11/x11.c | 12++++++++++++
lib/libstuff/x11/x11.h | 31+++++++++++++++++++++++++++++++
lib/libstuff/x11/xatom.c | 14++++++++++++++
lib/libstuff/x11/xft.c | 39+++++++++++++++++++++++++++++++++++++++
lib/libstuff/xext.c | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/Makefile | 30++++++++++++++++++++++++++++++
lib/libutf/NOTICE | 25+++++++++++++++++++++++++
lib/libutf/README | 5+++++
lib/libutf/isalpharune.3 | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/libutf.a | 0
lib/libutf/rune.3 | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/rune.c | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/runestrcat.3 | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/runestrcat.c | 24++++++++++++++++++++++++
lib/libutf/runestrchr.c | 35+++++++++++++++++++++++++++++++++++
lib/libutf/runestrcmp.c | 35+++++++++++++++++++++++++++++++++++
lib/libutf/runestrcpy.c | 28++++++++++++++++++++++++++++
lib/libutf/runestrdup.c | 27+++++++++++++++++++++++++++
lib/libutf/runestrecpy.c | 32++++++++++++++++++++++++++++++++
lib/libutf/runestrlen.c | 21+++++++++++++++++++++
lib/libutf/runestrncat.c | 32++++++++++++++++++++++++++++++++
lib/libutf/runestrncmp.c | 37+++++++++++++++++++++++++++++++++++++
lib/libutf/runestrncpy.c | 33+++++++++++++++++++++++++++++++++
lib/libutf/runestrrchr.c | 30++++++++++++++++++++++++++++++
lib/libutf/runestrstr.c | 45+++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/runetype.c | 1151+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/utf.7 | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/utfecpy.c | 36++++++++++++++++++++++++++++++++++++
lib/libutf/utflen.c | 37+++++++++++++++++++++++++++++++++++++
lib/libutf/utfnlen.c | 41+++++++++++++++++++++++++++++++++++++++++
lib/libutf/utfrrune.c | 45+++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/utfrune.c | 44++++++++++++++++++++++++++++++++++++++++++++
lib/libutf/utfutf.c | 41+++++++++++++++++++++++++++++++++++++++++
lib/libwmii_hack/Makefile | 17+++++++++++++++++
lib/libwmii_hack/hack.c | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libwmii_hack/hack.h | 28++++++++++++++++++++++++++++
lib/libwmii_hack/util.c | 43+++++++++++++++++++++++++++++++++++++++++++
lib/libwmii_hack/x11.c | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libwmii_hack/x11.h | 18++++++++++++++++++
libbio/Makefile | 27---------------------------
libbio/NOTICE | 34----------------------------------
libbio/README | 5-----
libbio/bbuffered.c | 20--------------------
libbio/bcat.c | 46----------------------------------------------
libbio/bfildes.c | 9---------
libbio/bflush.c | 33---------------------------------
libbio/bgetc.c | 53-----------------------------------------------------
libbio/bgetd.c | 36------------------------------------
libbio/bgetrune.c | 47-----------------------------------------------
libbio/binit.c | 154-------------------------------------------------------------------------------
libbio/bio.3 | 371-------------------------------------------------------------------------------
libbio/boffset.c | 25-------------------------
libbio/bprint.c | 14--------------
libbio/bputc.c | 20--------------------
libbio/bputrune.c | 23-----------------------
libbio/brdline.c | 94-------------------------------------------------------------------------------
libbio/brdstr.c | 112-------------------------------------------------------------------------------
libbio/bread.c | 45---------------------------------------------
libbio/bseek.c | 60------------------------------------------------------------
libbio/bvprint.c | 36------------------------------------
libbio/bwrite.c | 38--------------------------------------
libfmt/Makefile | 48------------------------------------------------
libfmt/NOTICE | 25-------------------------
libfmt/README | 5-----
libfmt/charstod.c | 85-------------------------------------------------------------------------------
libfmt/dofmt.c | 537-------------------------------------------------------------------------------
libfmt/dorfmt.c | 60------------------------------------------------------------
libfmt/errfmt.c | 28----------------------------
libfmt/fltfmt.c | 392-------------------------------------------------------------------------------
libfmt/fmt.c | 218-------------------------------------------------------------------------------
libfmt/fmtdef.h | 112-------------------------------------------------------------------------------
libfmt/fmtfd.c | 46----------------------------------------------
libfmt/fmtfdflush.c | 34----------------------------------
libfmt/fmtinstall.3 | 379-------------------------------------------------------------------------------
libfmt/fmtlock.c | 27---------------------------
libfmt/fmtprint.c | 48------------------------------------------------
libfmt/fmtquote.c | 264-------------------------------------------------------------------------------
libfmt/fmtrune.c | 40----------------------------------------
libfmt/fmtstr.c | 27---------------------------
libfmt/fmtvprint.c | 49-------------------------------------------------
libfmt/fprint.c | 29-----------------------------
libfmt/libfmt.a | 0
libfmt/nan64.c | 67-------------------------------------------------------------------
libfmt/pow10.c | 57---------------------------------------------------------
libfmt/print.3 | 482-------------------------------------------------------------------------------
libfmt/print.c | 29-----------------------------
libfmt/runefmtstr.c | 27---------------------------
libfmt/runeseprint.c | 30------------------------------
libfmt/runesmprint.c | 30------------------------------
libfmt/runesnprint.c | 31-------------------------------
libfmt/runesprint.c | 30------------------------------
libfmt/runevseprint.c | 40----------------------------------------
libfmt/runevsmprint.c | 91-------------------------------------------------------------------------------
libfmt/runevsnprint.c | 39---------------------------------------
libfmt/seprint.c | 29-----------------------------
libfmt/smprint.c | 29-----------------------------
libfmt/snprint.c | 30------------------------------
libfmt/sprint.c | 37-------------------------------------
libfmt/strtod.c | 532-------------------------------------------------------------------------------
libfmt/test.c | 44--------------------------------------------
libfmt/test2.c | 9---------
libfmt/test3.c | 52----------------------------------------------------
libfmt/vfprint.c | 33---------------------------------
libfmt/vseprint.c | 39---------------------------------------
libfmt/vsmprint.c | 88-------------------------------------------------------------------------------
libfmt/vsnprint.c | 39---------------------------------------
libregexp/Makefile | 17-----------------
libregexp/NOTICE | 25-------------------------
libregexp/README | 5-----
libregexp/regaux.c | 112-------------------------------------------------------------------------------
libregexp/regcomp.c | 559-------------------------------------------------------------------------------
libregexp/regerror.c | 15---------------
libregexp/regexec.c | 232-------------------------------------------------------------------------------
libregexp/regexp9.3 | 220-------------------------------------------------------------------------------
libregexp/regexp9.7 | 141-------------------------------------------------------------------------------
libregexp/regsub.c | 63---------------------------------------------------------------
libregexp/rregexec.c | 213-------------------------------------------------------------------------------
libregexp/rregsub.c | 63---------------------------------------------------------------
libregexp/test.c | 46----------------------------------------------
libregexp/test2.c | 20--------------------
libstuff/Makefile | 172-------------------------------------------------------------------------------
libstuff/buffer.c | 8--------
libstuff/clientutil.c | 50--------------------------------------------------
libstuff/event/buttonpress.c | 14--------------
libstuff/event/buttonrelease.c | 12------------
libstuff/event/clientmessage.c | 10----------
libstuff/event/configurenotify.c | 12------------
libstuff/event/configurerequest.c | 24------------------------
libstuff/event/destroynotify.c | 12------------
libstuff/event/enternotify.c | 16----------------
libstuff/event/event.c | 107-------------------------------------------------------------------------------
libstuff/event/event.h | 9---------
libstuff/event/expose.c | 12------------
libstuff/event/focusin.c | 27---------------------------
libstuff/event/focusout.c | 19-------------------
libstuff/event/keypress.c | 13-------------
libstuff/event/leavenotify.c | 13-------------
libstuff/event/mapnotify.c | 12------------
libstuff/event/mappingnotify.c | 11-----------
libstuff/event/maprequest.c | 12------------
libstuff/event/motionnotify.c | 13-------------
libstuff/event/propertynotify.c | 13-------------
libstuff/event/unmapnotify.c | 15---------------
libstuff/event/xtime.c | 33---------------------------------
libstuff/geom/get_sticky.c | 24------------------------
libstuff/geom/quadrant.c | 23-----------------------
libstuff/geom/rect_contains_p.c | 12------------
libstuff/geom/rect_haspoint_p.c | 10----------
libstuff/geom/rect_intersect_p.c | 12------------
libstuff/geom/rect_intersection.c | 17-----------------
libstuff/init_screens.c | 9---------
libstuff/map.c | 126-------------------------------------------------------------------------------
libstuff/printevent.c | 994-------------------------------------------------------------------------------
libstuff/printevent.h | 248-------------------------------------------------------------------------------
libstuff/util/_die.c | 26--------------------------
libstuff/util/backtrace.c | 87-------------------------------------------------------------------------------
libstuff/util/closeexec.c | 12------------
libstuff/util/comm.c | 42------------------------------------------
libstuff/util/doublefork.c | 30------------------------------
libstuff/util/emalloc.c | 11-----------
libstuff/util/emallocz.c | 11-----------
libstuff/util/erealloc.c | 11-----------
libstuff/util/estrdup.c | 12------------
libstuff/util/estrndup.c | 15---------------
libstuff/util/fatal.c | 39---------------------------------------
libstuff/util/freelater.c | 15---------------
libstuff/util/getbase.c | 43-------------------------------------------
libstuff/util/getint.c | 14--------------
libstuff/util/getlong.c | 23-----------------------
libstuff/util/getulong.c | 23-----------------------
libstuff/util/grep.c | 22----------------------
libstuff/util/join.c | 22----------------------
libstuff/util/max.c | 10----------
libstuff/util/mfatal.c | 33---------------------------------
libstuff/util/min.c | 10----------
libstuff/util/pathsearch.c | 32--------------------------------
libstuff/util/refree.c | 13-------------
libstuff/util/reinit.c | 16----------------
libstuff/util/spawn3.c | 43-------------------------------------------
libstuff/util/spawn3l.c | 28----------------------------
libstuff/util/stokenize.c | 22----------------------
libstuff/util/strcasestr.c | 25-------------------------
libstuff/util/strend.c | 13-------------
libstuff/util/strlcat.c | 26--------------------------
libstuff/util/strlcatprint.c | 19-------------------
libstuff/util/sxprint.c | 14--------------
libstuff/util/tokenize.c | 21---------------------
libstuff/util/uniq.c | 18------------------
libstuff/util/unquote.c | 38--------------------------------------
libstuff/util/utflcpy.c | 11-----------
libstuff/util/util.h | 5-----
libstuff/util/vector.c | 33---------------------------------
libstuff/util/vsxprint.c | 13-------------
libstuff/x11/colors/loadcolor.c | 18------------------
libstuff/x11/colors/namedcolor.c | 22----------------------
libstuff/x11/colors/xftcolor.c | 19-------------------
libstuff/x11/convpts.c | 17-----------------
libstuff/x11/drawing/border.c | 19-------------------
libstuff/x11/drawing/drawline.c | 11-----------
libstuff/x11/drawing/drawpoly.c | 15---------------
libstuff/x11/drawing/drawstring.c | 89-------------------------------------------------------------------------------
libstuff/x11/drawing/fill.c | 11-----------
libstuff/x11/drawing/fillpoly.c | 14--------------
libstuff/x11/errors.c | 40----------------------------------------
libstuff/x11/focus/getfocus.c | 13-------------
libstuff/x11/focus/setfocus.c | 9---------
libstuff/x11/freestringlist.c | 9---------
libstuff/x11/geometry/XRect.c | 15---------------
libstuff/x11/geometry/addpt.c | 11-----------
libstuff/x11/geometry/divpt.c | 11-----------
libstuff/x11/geometry/eqpt.c | 9---------
libstuff/x11/geometry/eqrect.c | 10----------
libstuff/x11/geometry/insetrect.c | 13-------------
libstuff/x11/geometry/mulpt.c | 11-----------
libstuff/x11/geometry/rectaddpt.c | 13-------------
libstuff/x11/geometry/rectsetorigin.c | 15---------------
libstuff/x11/geometry/rectsubpt.c | 13-------------
libstuff/x11/geometry/subpt.c | 11-----------
libstuff/x11/ignored_xerrors.c | 9---------
libstuff/x11/images/allocimage.c | 21---------------------
libstuff/x11/images/copyimage.c | 13-------------
libstuff/x11/images/freeimage.c | 18------------------
libstuff/x11/images/xftdrawable.c | 11-----------
libstuff/x11/initdisplay.c | 84-------------------------------------------------------------------------------
libstuff/x11/insanity/gravitate.c | 19-------------------
libstuff/x11/insanity/sethints.c | 100-------------------------------------------------------------------------------
libstuff/x11/insanity/sizehint.c | 42------------------------------------------
libstuff/x11/keyboard/grabkeyboard.c | 12------------
libstuff/x11/keyboard/ungrabkeyboard.c | 9---------
libstuff/x11/keys/keycode.c | 9---------
libstuff/x11/keys/parsekey.c | 46----------------------------------------------
libstuff/x11/mouse/grabpointer.c | 16----------------
libstuff/x11/mouse/pointerscreen.c | 15---------------
libstuff/x11/mouse/querypointer.c | 15---------------
libstuff/x11/mouse/translate.c | 14--------------
libstuff/x11/mouse/ungrabpointer.c | 9---------
libstuff/x11/mouse/warppointer.c | 23-----------------------
libstuff/x11/properties/changeprop_char.c | 9---------
libstuff/x11/properties/changeprop_long.c | 9---------
libstuff/x11/properties/changeprop_short.c | 9---------
libstuff/x11/properties/changeprop_string.c | 10----------
libstuff/x11/properties/changeprop_textlist.c | 24------------------------
libstuff/x11/properties/changeprop_ulong.c | 9---------
libstuff/x11/properties/changeproperty.c | 11-----------
libstuff/x11/properties/delproperty.c | 9---------
libstuff/x11/properties/getprop.c | 28----------------------------
libstuff/x11/properties/getprop_long.c | 19-------------------
libstuff/x11/properties/getprop_string.c | 19-------------------
libstuff/x11/properties/getprop_textlist.c | 22----------------------
libstuff/x11/properties/getprop_ulong.c | 10----------
libstuff/x11/properties/getproperty.c | 12------------
libstuff/x11/properties/strlistdup.c | 29-----------------------------
libstuff/x11/sendevent.c | 9---------
libstuff/x11/sendmessage.c | 20--------------------
libstuff/x11/setgccol.c | 9---------
libstuff/x11/shape/setshapemask.c | 11-----------
libstuff/x11/sync.c | 9---------
libstuff/x11/text/freefont.c | 23-----------------------
libstuff/x11/text/labelh.c | 9---------
libstuff/x11/text/loadfont.c | 70----------------------------------------------------------------------
libstuff/x11/text/textextents_l.c | 34----------------------------------
libstuff/x11/text/textwidth.c | 10----------
libstuff/x11/text/textwidth_l.c | 12------------
libstuff/x11/windows/configwin.c | 22----------------------
libstuff/x11/windows/createwindow.c | 9---------
libstuff/x11/windows/createwindow_visual.c | 33---------------------------------
libstuff/x11/windows/destroywindow.c | 16----------------
libstuff/x11/windows/findwin.c | 14--------------
libstuff/x11/windows/getwinrect.c | 15---------------
libstuff/x11/windows/lowerwin.c | 10----------
libstuff/x11/windows/mapwin.c | 15---------------
libstuff/x11/windows/movewin.c | 13-------------
libstuff/x11/windows/raisewin.c | 10----------
libstuff/x11/windows/reparentwindow.c | 13-------------
libstuff/x11/windows/reshapewin.c | 12------------
libstuff/x11/windows/selectinput.c | 9---------
libstuff/x11/windows/setborder.c | 14--------------
libstuff/x11/windows/sethandler.c | 23-----------------------
libstuff/x11/windows/setwinattr.c | 10----------
libstuff/x11/windows/unmapwin.c | 16----------------
libstuff/x11/windows/window.c | 14--------------
libstuff/x11/x11.c | 12------------
libstuff/x11/x11.h | 31-------------------------------
libstuff/x11/xatom.c | 14--------------
libstuff/x11/xft.c | 39---------------------------------------
libstuff/xext.c | 161-------------------------------------------------------------------------------
libutf/Makefile | 30------------------------------
libutf/NOTICE | 25-------------------------
libutf/README | 5-----
libutf/isalpharune.3 | 57---------------------------------------------------------
libutf/libutf.a | 0
libutf/rune.3 | 194-------------------------------------------------------------------------------
libutf/rune.c | 175-------------------------------------------------------------------------------
libutf/runestrcat.3 | 74--------------------------------------------------------------------------
libutf/runestrcat.c | 24------------------------
libutf/runestrchr.c | 35-----------------------------------
libutf/runestrcmp.c | 35-----------------------------------
libutf/runestrcpy.c | 28----------------------------
libutf/runestrdup.c | 27---------------------------
libutf/runestrecpy.c | 32--------------------------------
libutf/runestrlen.c | 21---------------------
libutf/runestrncat.c | 32--------------------------------
libutf/runestrncmp.c | 37-------------------------------------
libutf/runestrncpy.c | 33---------------------------------
libutf/runestrrchr.c | 30------------------------------
libutf/runestrstr.c | 45---------------------------------------------
libutf/runetype.c | 1151-------------------------------------------------------------------------------
libutf/utf.7 | 99-------------------------------------------------------------------------------
libutf/utfecpy.c | 36------------------------------------
libutf/utflen.c | 37-------------------------------------
libutf/utfnlen.c | 41-----------------------------------------
libutf/utfrrune.c | 45---------------------------------------------
libutf/utfrune.c | 44--------------------------------------------
libutf/utfutf.c | 41-----------------------------------------
libwmii_hack/Makefile | 17-----------------
libwmii_hack/hack.c | 133-------------------------------------------------------------------------------
libwmii_hack/hack.h | 28----------------------------
libwmii_hack/util.c | 43-------------------------------------------
libwmii_hack/x11.c | 213-------------------------------------------------------------------------------
libwmii_hack/x11.h | 18------------------
man/Makefile | 6+++---
mk/hdr.mk | 24++++++++++++------------
mk/lib.mk | 6+++---
mk/man.mk | 4++--
mk/many.mk | 10+++++-----
mk/one.mk | 4++--
mk/so.mk | 4++--
575 files changed, 15258 insertions(+), 15246 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,23 +1,15 @@ ROOT=. -include ${ROOT}/mk/hdr.mk -include ${ROOT}/mk/wmii.mk +include $(ROOT)/mk/hdr.mk +include $(ROOT)/mk/wmii.mk -PDIRS = \ +DIRS = \ doc \ man \ + lib \ cmd \ - libwmii_hack \ rc \ alternative_wmiircs -DIRS = \ - libstuff \ - libbio \ - libfmt \ - libregexp \ - libutf \ - $(PDIRS) - DOCS = README \ LICENSE @@ -34,6 +26,5 @@ deb: dpkg-buildpackage -rfakeroot -b -nc [ -d .hg ] && hg revert debian/changelog -include ${ROOT}/mk/dir.mk -INSTDIRS = $(PDIRS) +include $(ROOT)/mk/dir.mk diff --git a/NEWS b/NEWS @@ -1,3 +1,6 @@ +3.1b1: + * Xft is now loaded on demand + * colrules widths may now be specified in pixels 3.9b1: * wmii9menu is now Xinerama aware. diff --git a/cmd/click/Makefile b/cmd/click/Makefile @@ -1,8 +1,8 @@ ROOT= ../.. -include ${ROOT}/mk/hdr.mk -include ${ROOT}/mk/wmii.mk +include $(ROOT)/mk/hdr.mk +include $(ROOT)/mk/wmii.mk -main.c: ${ROOT}/mk/wmii.mk +main.c: $(ROOT)/mk/wmii.mk TARG = click HFILES= dat.h fns.h @@ -14,5 +14,5 @@ LIBS += -lm -lXtst $(LIBS9) CFLAGS += -DIXP_NEEDAPI=86 OBJ = main -include ${ROOT}/mk/one.mk +include $(ROOT)/mk/one.mk diff --git a/cmd/strut/Makefile b/cmd/strut/Makefile @@ -1,8 +1,8 @@ ROOT= ../.. -include ${ROOT}/mk/hdr.mk -include ${ROOT}/mk/wmii.mk +include $(ROOT)/mk/hdr.mk +include $(ROOT)/mk/wmii.mk -main.c: ${ROOT}/mk/wmii.mk +main.c: $(ROOT)/mk/wmii.mk TARG = wistrut HFILES= dat.h fns.h @@ -16,5 +16,5 @@ OBJ = main \ ewmh \ win -include ${ROOT}/mk/one.mk +include $(ROOT)/mk/one.mk diff --git a/include/Makefile b/include/Makefile @@ -1,6 +1,6 @@ ROOT= .. -include ${ROOT}/mk/hdr.mk +include $(ROOT)/mk/hdr.mk HFILES = ixp.h ixp_fcall.h -include ${ROOT}/mk/common.mk +include $(ROOT)/mk/common.mk diff --git a/lib/Makefile b/lib/Makefile @@ -0,0 +1,18 @@ +ROOT=.. +include $(ROOT)/mk/hdr.mk +include $(ROOT)/mk/wmii.mk + +PDIRS = \ + libwmii_hack + +DIRS = \ + libstuff \ + libbio \ + libfmt \ + libregexp \ + libutf \ + $(PDIRS) + +include $(ROOT)/mk/dir.mk +INSTDIRS = $(PDIRS) + diff --git a/lib/libbio/Makefile b/lib/libbio/Makefile @@ -0,0 +1,27 @@ +ROOT= ../.. +include $(ROOT)/mk/hdr.mk + +VERSION=2.0 +TARG=libbio + +OBJ=\ + bbuffered\ + bfildes\ + bflush\ + bgetc\ + bgetd\ + bgetrune\ + binit\ + boffset\ + bprint\ + bvprint\ + bputc\ + bputrune\ + brdline\ + brdstr\ + bread\ + bseek\ + bwrite + +include $(ROOT)/mk/lib.mk + diff --git a/lib/libbio/NOTICE b/lib/libbio/NOTICE @@ -0,0 +1,34 @@ +This copyright NOTICE applies to all files in this directory and +subdirectories, unless another copyright notice appears in a given +file or subdirectory. If you take substantial code from this software to use in +other programs, you must somehow include with it an appropriate +copyright notice that includes the copyright notice and the other +notices below. It is fine (and often tidier) to do that in a separate +file such as NOTICE, LICENCE or COPYING. + + Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. + Revisions Copyright © 2000-2005 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +---- + +This software is also made available under the Lucent Public License +version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html + diff --git a/lib/libbio/README b/lib/libbio/README @@ -0,0 +1,5 @@ +This software was packaged for Unix by Russ Cox. +Please send comments to rsc@swtch.com. + +http://swtch.com/plan9port/unix + diff --git a/lib/libbio/bbuffered.c b/lib/libbio/bbuffered.c @@ -0,0 +1,20 @@ +#include "plan9.h" +#include <bio.h> + +int +Bbuffered(Biobuf *bp) +{ + switch(bp->state) { + case Bracteof: + case Bractive: + return -bp->icount; + + case Bwactive: + return bp->bsize + bp->ocount; + + case Binactive: + return 0; + } + fprint(2, "Bbuffered: unknown state %d\n", bp->state); + return 0; +} diff --git a/lib/libbio/bcat.c b/lib/libbio/bcat.c @@ -0,0 +1,46 @@ +#include <fmt.h> +#include "bio.h" + +Biobuf bout; + +void +bcat(Biobuf *b, char *name) +{ + char buf[1000]; + int n; + + while((n = Bread(b, buf, sizeof buf)) > 0){ + if(Bwrite(&bout, buf, n) < 0) + fprint(2, "writing during %s: %r\n", name); + } + if(n < 0) + fprint(2, "reading %s: %r\n", name); +} + +int +main(int argc, char **argv) +{ + int i; + Biobuf b, *bp; + Fmt fmt; + + Binit(&bout, 1, O_WRONLY); + Bfmtinit(&fmt, &bout); + fmtprint(&fmt, "hello, world\n"); + Bfmtflush(&fmt); + + if(argc == 1){ + Binit(&b, 0, O_RDONLY); + bcat(&b, "<stdin>"); + }else{ + for(i=1; i<argc; i++){ + if((bp = Bopen(argv[i], O_RDONLY)) == 0){ + fprint(2, "Bopen %s: %r\n", argv[i]); + continue; + } + bcat(bp, argv[i]); + Bterm(bp); + } + } + exit(0); +} diff --git a/lib/libbio/bfildes.c b/lib/libbio/bfildes.c @@ -0,0 +1,9 @@ +#include "plan9.h" +#include <bio.h> + +int +Bfildes(Biobuf *bp) +{ + + return bp->fid; +} diff --git a/lib/libbio/bflush.c b/lib/libbio/bflush.c @@ -0,0 +1,33 @@ +#include "plan9.h" +#include <bio.h> + +int +Bflush(Biobuf *bp) +{ + int n, c; + + switch(bp->state) { + case Bwactive: + n = bp->bsize+bp->ocount; + if(n == 0) + return 0; + c = write(bp->fid, bp->bbuf, n); + if(n == c) { + bp->offset += n; + bp->ocount = -bp->bsize; + return 0; + } + bp->state = Binactive; + bp->ocount = 0; + break; + + case Bracteof: + bp->state = Bractive; + + case Bractive: + bp->icount = 0; + bp->gbuf = bp->ebuf; + return 0; + } + return Beof; +} diff --git a/lib/libbio/bgetc.c b/lib/libbio/bgetc.c @@ -0,0 +1,53 @@ +#include "plan9.h" +#include <bio.h> + +int +Bgetc(Biobuf *bp) +{ + int i; + +loop: + i = bp->icount; + if(i != 0) { + bp->icount = i+1; + return bp->ebuf[i]; + } + if(bp->state != Bractive) { + if(bp->state == Bracteof) + bp->state = Bractive; + return Beof; + } + /* + * get next buffer, try to keep Bungetsize + * characters pre-catenated from the previous + * buffer to allow that many ungets. + */ + memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize); + i = read(bp->fid, bp->bbuf, bp->bsize); + bp->gbuf = bp->bbuf; + if(i <= 0) { + bp->state = Bracteof; + if(i < 0) + bp->state = Binactive; + return Beof; + } + if(i < bp->bsize) { + memmove(bp->ebuf-i-Bungetsize, bp->bbuf-Bungetsize, i+Bungetsize); + bp->gbuf = bp->ebuf-i; + } + bp->icount = -i; + bp->offset += i; + goto loop; +} + +int +Bungetc(Biobuf *bp) +{ + + if(bp->state == Bracteof) + bp->state = Bractive; + if(bp->state != Bractive) + return Beof; + bp->icount--; + return 1; +} diff --git a/lib/libbio/bgetd.c b/lib/libbio/bgetd.c @@ -0,0 +1,36 @@ +#include "plan9.h" +#include <bio.h> + +struct bgetd +{ + Biobuf* b; + int eof; +}; + +static int +Bgetdf(void *vp) +{ + int c; + struct bgetd *bg = vp; + + c = Bgetc(bg->b); + if(c == Beof) + bg->eof = 1; + return c; +} + +int +Bgetd(Biobuf *bp, double *dp) +{ + double d; + struct bgetd b; + + b.b = bp; + b.eof = 0; + d = fmtcharstod(Bgetdf, &b); + if(b.eof) + return -1; + Bungetc(bp); + *dp = d; + return 1; +} diff --git a/lib/libbio/bgetrune.c b/lib/libbio/bgetrune.c @@ -0,0 +1,47 @@ +#include "plan9.h" +#include <bio.h> +#include <utf.h> + +long +Bgetrune(Biobuf *bp) +{ + int c, i; + Rune rune; + char str[4]; + + c = Bgetc(bp); + if(c < Runeself) { /* one char */ + bp->runesize = 1; + return c; + } + str[0] = c; + + for(i=1;;) { + c = Bgetc(bp); + if(c < 0) + return c; + str[i++] = c; + + if(fullrune(str, i)) { + bp->runesize = chartorune(&rune, str); + while(i > bp->runesize) { + Bungetc(bp); + i--; + } + return rune; + } + } +} + +int +Bungetrune(Biobuf *bp) +{ + + if(bp->state == Bracteof) + bp->state = Bractive; + if(bp->state != Bractive) + return Beof; + bp->icount -= bp->runesize; + bp->runesize = 0; + return 1; +} diff --git a/lib/libbio/binit.c b/lib/libbio/binit.c @@ -0,0 +1,154 @@ +#include <stdlib.h> +#include <plan9.h> +#include <bio.h> + +enum +{ + MAXBUFS = 20 +}; + +static Biobuf* wbufs[MAXBUFS]; +static int atexitflag; + +static +void +batexit(void) +{ + Biobuf *bp; + int i; + + for(i=0; i<MAXBUFS; i++) { + bp = wbufs[i]; + if(bp != 0) { + wbufs[i] = 0; + Bflush(bp); + } + } +} + +static +void +deinstall(Biobuf *bp) +{ + int i; + + for(i=0; i<MAXBUFS; i++) + if(wbufs[i] == bp) + wbufs[i] = 0; +} + +static +void +install(Biobuf *bp) +{ + int i; + + deinstall(bp); + for(i=0; i<MAXBUFS; i++) + if(wbufs[i] == 0) { + wbufs[i] = bp; + break; + } + if(atexitflag == 0) { + atexitflag = 1; + atexit(batexit); + } +} + +int +Binits(Biobuf *bp, int f, int mode, unsigned char *p, int size) +{ + + p += Bungetsize; /* make room for Bungets */ + size -= Bungetsize; + + switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) { + default: + fprint(2, "Bopen: unknown mode %d\n", mode); + return Beof; + + case OREAD: + bp->state = Bractive; + bp->ocount = 0; + break; + + case OWRITE: + install(bp); + bp->state = Bwactive; + bp->ocount = -size; + break; + } + bp->bbuf = p; + bp->ebuf = p+size; + bp->bsize = size; + bp->icount = 0; + bp->gbuf = bp->ebuf; + bp->fid = f; + bp->flag = 0; + bp->rdline = 0; + bp->offset = 0; + bp->runesize = 0; + return 0; +} + + +int +Binit(Biobuf *bp, int f, int mode) +{ + return Binits(bp, f, mode, bp->b, sizeof(bp->b)); +} + +Biobuf* +Bfdopen(int f, int mode) +{ + Biobuf *bp; + + bp = malloc(sizeof(Biobuf)); + if(bp == 0) + return 0; + Binits(bp, f, mode, bp->b, sizeof(bp->b)); + bp->flag = Bmagic; + return bp; +} + +Biobuf* +Bopen(const char *name, int mode) +{ + Biobuf *bp; + int f; + + switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) { + default: + fprint(2, "Bopen: unknown mode %d\n", mode); + return 0; + + case OREAD: + f = open(name, OREAD); + if(f < 0) + return 0; + break; + + case OWRITE: + f = creat(name, 0666); + if(f < 0) + return 0; + } + bp = Bfdopen(f, mode); + if(bp == 0) + close(f); + return bp; +} + +int +Bterm(Biobuf *bp) +{ + + deinstall(bp); + Bflush(bp); + if(bp->flag == Bmagic) { + bp->flag = 0; + close(bp->fid); + free(bp); + } + return 0; +} diff --git a/lib/libbio/bio.3 b/lib/libbio/bio.3 @@ -0,0 +1,371 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH BIO 3 +.SH NAME +Bopen, Bfdopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetrune, Bgetd, Bungetc, Bungetrune, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bputrune, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output +.SH SYNOPSIS +.ta \w'\fLBiobuf* 'u +.B #include <utf.h> +.br +.B #include <fmt.h> +.br +.B #include <bio.h> +.PP +.B +Biobuf* Bopen(char *file, int mode) +.PP +.B +Biobuf* Bfdopen(int fd, int mode) +.PP +.B +int Binit(Biobuf *bp, int fd, int mode) +.PP +.B +int Binits(Biobufhdr *bp, int fd, int mode, uchar *buf, int size) +.PP +.B +int Bterm(Biobufhdr *bp) +.PP +.B +int Bprint(Biobufhdr *bp, char *format, ...) +.PP +.B +int Bvprint(Biobufhdr *bp, char *format, va_list arglist); +.PP +.B +void* Brdline(Biobufhdr *bp, int delim) +.PP +.B +char* Brdstr(Biobufhdr *bp, int delim, int nulldelim) +.PP +.B +int Blinelen(Biobufhdr *bp) +.PP +.B +vlong Boffset(Biobufhdr *bp) +.PP +.B +int Bfildes(Biobufhdr *bp) +.PP +.B +int Bgetc(Biobufhdr *bp) +.PP +.B +long Bgetrune(Biobufhdr *bp) +.PP +.B +int Bgetd(Biobufhdr *bp, double *d) +.PP +.B +int Bungetc(Biobufhdr *bp) +.PP +.B +int Bungetrune(Biobufhdr *bp) +.PP +.B +vlong Bseek(Biobufhdr *bp, vlong n, int type) +.PP +.B +int Bputc(Biobufhdr *bp, int c) +.PP +.B +int Bputrune(Biobufhdr *bp, long c) +.PP +.B +long Bread(Biobufhdr *bp, void *addr, long nbytes) +.PP +.B +long Bwrite(Biobufhdr *bp, void *addr, long nbytes) +.PP +.B +int Bflush(Biobufhdr *bp) +.PP +.B +int Bbuffered(Biobufhdr *bp) +.PP +.SH DESCRIPTION +These routines implement fast buffered I/O. +I/O on different file descriptors is independent. +.PP +.I Bopen +opens +.I file +for mode +.B O_RDONLY +or creates for mode +.BR O_WRONLY . +It calls +.IR malloc (3) +to allocate a buffer. +.PP +.I Bfdopen +allocates a buffer for the already-open file descriptor +.I fd +for mode +.B O_RDONLY +or +.BR O_WRONLY . +It calls +.IR malloc (3) +to allocate a buffer. +.PP +.I Binit +initializes a standard size buffer, type +.IR Biobuf , +with the open file descriptor passed in +by the user. +.I Binits +initializes a non-standard size buffer, type +.IR Biobufhdr , +with the open file descriptor, +buffer area, and buffer size passed in +by the user. +.I Biobuf +and +.I Biobufhdr +are related by the declaration: +.IP +.EX +typedef struct Biobuf Biobuf; +struct Biobuf +{ + Biobufhdr; + uchar b[Bungetsize+Bsize]; +}; +.EE +.PP +Arguments +of types pointer to Biobuf and pointer to Biobufhdr +can be used interchangeably in the following routines. +.PP +.IR Bopen , +.IR Binit , +or +.I Binits +should be called before any of the +other routines on that buffer. +.I Bfildes +returns the integer file descriptor of the associated open file. +.PP +.I Bterm +flushes the buffer for +.IR bp . +If the buffer was allocated by +.IR Bopen , +the buffer is +.I freed +and the file is closed. +.PP +.I Brdline +reads a string from the file associated with +.I bp +up to and including the first +.I delim +character. +The delimiter character at the end of the line is +not altered. +.I Brdline +returns a pointer to the start of the line or +.L 0 +on end-of-file or read error. +.I Blinelen +returns the length (including the delimiter) +of the most recent string returned by +.IR Brdline . +.PP +.I Brdstr +returns a +.IR malloc (3)-allocated +buffer containing the next line of input delimited by +.IR delim , +terminated by a NUL (0) byte. +Unlike +.IR Brdline , +which returns when its buffer is full even if no delimiter has been found, +.I Brdstr +will return an arbitrarily long line in a single call. +If +.I nulldelim +is set, the terminal delimiter will be overwritten with a NUL. +After a successful call to +.IR Brdstr , +the return value of +.I Blinelen +will be the length of the returned buffer, excluding the NUL. +.PP +.I Bgetc +returns the next character from +.IR bp , +or a negative value +at end of file. +.I Bungetc +may be called immediately after +.I Bgetc +to allow the same character to be reread. +.PP +.I Bgetrune +calls +.I Bgetc +to read the bytes of the next +.SM UTF +sequence in the input stream and returns the value of the rune +represented by the sequence. +It returns a negative value +at end of file. +.I Bungetrune +may be called immediately after +.I Bgetrune +to allow the same +.SM UTF +sequence to be reread as either bytes or a rune. +.I Bungetc +and +.I Bungetrune +may back up a maximum of five bytes. +.PP +.I Bgetd +uses +.I fmtcharstod +(see +.IR fmtstrtod (3)) +and +.I Bgetc +to read the formatted +floating-point number in the input stream, +skipping initial blanks and tabs. +The value is stored in +.BR *d. +.PP +.I Bread +reads +.I nbytes +of data from +.I bp +into memory starting at +.IR addr . +The number of bytes read is returned on success +and a negative value is returned if a read error occurred. +.PP +.I Bseek +applies +.IR lseek (2) +to +.IR bp . +It returns the new file offset. +.I Boffset +returns the file offset of the next character to be processed. +.PP +.I Bputc +outputs the low order 8 bits of +.I c +on +.IR bp . +If this causes a +.IR write +to occur and there is an error, +a negative value is returned. +Otherwise, a zero is returned. +.PP +.I Bputrune +calls +.I Bputc +to output the low order +16 bits of +.I c +as a rune +in +.SM UTF +format +on the output stream. +.PP +.I Bprint +is a buffered interface to +.IR print (3). +If this causes a +.IR write +to occur and there is an error, +a negative value +.RB ( Beof ) +is returned. +Otherwise, the number of bytes output is returned. +.I Bvprint +does the same except it takes as argument a +.B va_list +parameter, so it can be called within a variadic function. +.PP +.I Bwrite +outputs +.I nbytes +of data starting at +.I addr +to +.IR bp . +If this causes a +.IR write +to occur and there is an error, +a negative value is returned. +Otherwise, the number of bytes written is returned. +.PP +.I Bflush +causes any buffered output associated with +.I bp +to be written. +The return is as for +.IR Bputc . +.I Bflush +is called on +exit for every buffer still open +for writing. +.PP +.I Bbuffered +returns the number of bytes in the buffer. +When reading, this is the number of bytes still available from the last +read on the file; when writing, it is the number of bytes ready to be +written. +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH SEE ALSO +.IR open (2), +.IR print (3), +.IR atexit (3), +.IR utf (7), +.SH DIAGNOSTICS +.I Bio +routines that return integers yield +.B Beof +if +.I bp +is not the descriptor of an open file. +.I Bopen +returns zero if the file cannot be opened in the given mode. +All routines set +.I errstr +on error. +.SH BUGS +.I Brdline +returns an error on strings longer than the buffer associated +with the file +and also if the end-of-file is encountered +before a delimiter. +.I Blinelen +will tell how many characters are available +in these cases. +In the case of a true end-of-file, +.I Blinelen +will return zero. +At the cost of allocating a buffer, +.I Brdstr +sidesteps these issues. +.PP +The data returned by +.I Brdline +may be overwritten by calls to any other +.I bio +routine on the same +.IR bp. diff --git a/lib/libbio/boffset.c b/lib/libbio/boffset.c @@ -0,0 +1,25 @@ +#include "plan9.h" +#include <bio.h> + +off_t +Boffset(Biobuf *bp) +{ + off_t n; + + switch(bp->state) { + default: + fprint(2, "Boffset: unknown state %d\n", bp->state); + n = Beof; + break; + + case Bracteof: + case Bractive: + n = bp->offset + bp->icount; + break; + + case Bwactive: + n = bp->offset + (bp->bsize + bp->ocount); + break; + } + return n; +} diff --git a/lib/libbio/bprint.c b/lib/libbio/bprint.c @@ -0,0 +1,14 @@ +#include "plan9.h" +#include <bio.h> + +int +Bprint(Biobuf *bp, const char *fmt, ...) +{ + int n; + va_list arg; + + va_start(arg, fmt); + n = Bvprint(bp, fmt, arg); + va_end(arg); + return n; +} diff --git a/lib/libbio/bputc.c b/lib/libbio/bputc.c @@ -0,0 +1,20 @@ +#include "plan9.h" +#include <bio.h> + +int +Bputc(Biobuf *bp, int c) +{ + int i; + + for(;;) { + i = bp->ocount; + if(i) { + bp->ebuf[i++] = c; + bp->ocount = i; + return 0; + } + if(Bflush(bp) == Beof) + break; + } + return Beof; +} diff --git a/lib/libbio/bputrune.c b/lib/libbio/bputrune.c @@ -0,0 +1,23 @@ +#include "plan9.h" +#include <bio.h> +#include <utf.h> + +int +Bputrune(Biobuf *bp, long c) +{ + Rune rune; + char str[4]; + int n; + + rune = c; + if(rune < Runeself) { + Bputc(bp, rune); + return 1; + } + n = runetochar(str, &rune); + if(n == 0) + return Bbad; + if(Bwrite(bp, str, n) != n) + return Beof; + return n; +} diff --git a/lib/libbio/brdline.c b/lib/libbio/brdline.c @@ -0,0 +1,94 @@ +#include "plan9.h" +#include <bio.h> + +void* +Brdline(Biobuf *bp, int delim) +{ + char *ip, *ep; + int i, j; + + i = -bp->icount; + if(i == 0) { + /* + * eof or other error + */ + if(bp->state != Bractive) { + if(bp->state == Bracteof) + bp->state = Bractive; + bp->rdline = 0; + bp->gbuf = bp->ebuf; + return 0; + } + } + + /* + * first try in remainder of buffer (gbuf doesn't change) + */ + ip = (char*)bp->ebuf - i; + ep = memchr(ip, delim, i); + if(ep) { + j = (ep - ip) + 1; + bp->rdline = j; + bp->icount += j; + return ip; + } + + /* + * copy data to beginning of buffer + */ + if(i < bp->bsize) + memmove(bp->bbuf, ip, i); + bp->gbuf = bp->bbuf; + + /* + * append to buffer looking for the delim + */ + ip = (char*)bp->bbuf + i; + while(i < bp->bsize) { + j = read(bp->fid, ip, bp->bsize-i); + if(j <= 0) { + /* + * end of file with no delim + */ + memmove(bp->ebuf-i, bp->bbuf, i); + bp->rdline = i; + bp->icount = -i; + bp->gbuf = bp->ebuf-i; + return 0; + } + bp->offset += j; + i += j; + ep = memchr(ip, delim, j); + if(ep) { + /* + * found in new piece + * copy back up and reset everything + */ + ip = (char*)bp->ebuf - i; + if(i < bp->bsize){ + memmove(ip, bp->bbuf, i); + bp->gbuf = (unsigned char*)ip; + } + j = (ep - (char*)bp->bbuf) + 1; + bp->rdline = j; + bp->icount = j - i; + return ip; + } + ip += j; + } + + /* + * full buffer without finding + */ + bp->rdline = bp->bsize; + bp->icount = -bp->bsize; + bp->gbuf = bp->bbuf; + return 0; +} + +int +Blinelen(Biobuf *bp) +{ + + return bp->rdline; +} diff --git a/lib/libbio/brdstr.c b/lib/libbio/brdstr.c @@ -0,0 +1,112 @@ +#include <stdlib.h> +#include <plan9.h> +#include <bio.h> + +static char* +badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim) +{ + int n; + + n = *np; + p = realloc(p, n+ndata+1); + if(p){ + memmove(p+n, data, ndata); + n += ndata; + if(n>0 && nulldelim && p[n-1]==delim) + p[--n] = '\0'; + else + p[n] = '\0'; + *np = n; + } + return p; +} + +char* +Brdstr(Biobuf *bp, int delim, int nulldelim) +{ + char *ip, *ep, *p; + int i, j; + + i = -bp->icount; + bp->rdline = 0; + if(i == 0) { + /* + * eof or other error + */ + if(bp->state != Bractive) { + if(bp->state == Bracteof) + bp->state = Bractive; + bp->gbuf = bp->ebuf; + return nil; + } + } + + /* + * first try in remainder of buffer (gbuf doesn't change) + */ + ip = (char*)bp->ebuf - i; + ep = memchr(ip, delim, i); + if(ep) { + j = (ep - ip) + 1; + bp->icount += j; + return badd(nil, &bp->rdline, ip, j, delim, nulldelim); + } + + /* + * copy data to beginning of buffer + */ + if(i < bp->bsize) + memmove(bp->bbuf, ip, i); + bp->gbuf = bp->bbuf; + + /* + * append to buffer looking for the delim + */ + p = nil; + for(;;){ + ip = (char*)bp->bbuf + i; + while(i < bp->bsize) { + j = read(bp->fid, ip, bp->bsize-i); + if(j <= 0 && i == 0) + return p; + if(j <= 0 && i > 0){ + /* + * end of file but no delim. pretend we got a delim + * by making the delim \0 and smashing it with nulldelim. + */ + j = 1; + ep = ip; + delim = '\0'; + nulldelim = 1; + *ep = delim; /* there will be room for this */ + }else{ + bp->offset += j; + ep = memchr(ip, delim, j); + } + i += j; + if(ep) { + /* + * found in new piece + * copy back up and reset everything + */ + ip = (char*)bp->ebuf - i; + if(i < bp->bsize){ + memmove(ip, bp->bbuf, i); + bp->gbuf = (unsigned char*)ip; + } + j = (ep - (char*)bp->bbuf) + 1; + bp->icount = j - i; + return badd(p, &bp->rdline, ip, j, delim, nulldelim); + } + ip += j; + } + + /* + * full buffer without finding; add to user string and continue + */ + p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0); + i = 0; + bp->icount = 0; + bp->gbuf = bp->ebuf; + } +} diff --git a/lib/libbio/bread.c b/lib/libbio/bread.c @@ -0,0 +1,45 @@ +#include "plan9.h" +#include <bio.h> + +long +Bread(Biobuf *bp, void *ap, long count) +{ + long c; + unsigned char *p; + int i, n, ic; + + p = ap; + c = count; + ic = bp->icount; + + while(c > 0) { + n = -ic; + if(n > c) + n = c; + if(n == 0) { + if(bp->state != Bractive) + break; + i = read(bp->fid, bp->bbuf, bp->bsize); + if(i <= 0) { + bp->state = Bracteof; + if(i < 0) + bp->state = Binactive; + break; + } + bp->gbuf = bp->bbuf; + bp->offset += i; + if(i < bp->bsize) { + memmove(bp->ebuf-i, bp->bbuf, i); + bp->gbuf = bp->ebuf-i; + } + ic = -i; + continue; + } + memmove(p, bp->ebuf+ic, n); + c -= n; + ic += n; + p += n; + } + bp->icount = ic; + return count-c; +} diff --git a/lib/libbio/bseek.c b/lib/libbio/bseek.c @@ -0,0 +1,60 @@ +#include "plan9.h" +#include <bio.h> + +off_t +Bseek(Biobuf *bp, off_t offset, int base) +{ + vlong n, d; + int bufsz; + + switch(bp->state) { + default: + fprint(2, "Bseek: unknown state %d\n", bp->state); + return Beof; + + case Bracteof: + bp->state = Bractive; + bp->icount = 0; + bp->gbuf = bp->ebuf; + + case Bractive: + n = offset; + if(base == 1) { + n += Boffset(bp); + base = 0; + } + + /* + * try to seek within buffer + */ + if(base == 0) { + d = n - Boffset(bp); + bufsz = bp->ebuf - bp->gbuf; + if(-bufsz <= d && d <= bufsz){ + bp->icount += d; + if(d >= 0) { + if(bp->icount <= 0) + return n; + } else { + if(bp->ebuf - bp->gbuf >= -bp->icount) + return n; + } + } + } + + /* + * reset the buffer + */ + n = lseek(bp->fid, n, base); + bp->icount = 0; + bp->gbuf = bp->ebuf; + break; + + case Bwactive: + Bflush(bp); + n = lseek(bp->fid, offset, base); + break; + } + bp->offset = n; + return n; +} diff --git a/lib/libbio/bvprint.c b/lib/libbio/bvprint.c @@ -0,0 +1,36 @@ +#include "plan9.h" +#include <bio.h> + +static int +fmtBflush(Fmt *f) +{ + Biobuf *bp; + + bp = f->farg; + bp->ocount = (char*)f->to - (char*)f->stop; + if(Bflush(bp) < 0) + return 0; + f->stop = bp->ebuf; + f->to = (char*)f->stop + bp->ocount; + f->start = f->to; + return 1; +} + +int +Bvprint(Biobuf *bp, const char *fmt, va_list arg) +{ + int n; + Fmt f; + + f.runes = 0; + f.stop = bp->ebuf; + f.start = (char*)f.stop + bp->ocount; + f.to = f.start; + f.flush = fmtBflush; + f.farg = bp; + f.nfmt = 0; + n = fmtvprint(&f, fmt, arg); + bp->ocount = (char*)f.to - (char*)f.stop; + return n; +} + diff --git a/lib/libbio/bwrite.c b/lib/libbio/bwrite.c @@ -0,0 +1,38 @@ +#include "plan9.h" +#include <bio.h> + +long +Bwrite(Biobuf *bp, void *ap, long count) +{ + long c; + unsigned char *p; + int i, n, oc; + + p = ap; + c = count; + oc = bp->ocount; + + while(c > 0) { + n = -oc; + if(n > c) + n = c; + if(n == 0) { + if(bp->state != Bwactive) + return Beof; + i = write(bp->fid, bp->bbuf, bp->bsize); + if(i != bp->bsize) { + bp->state = Binactive; + return Beof; + } + bp->offset += i; + oc = -bp->bsize; + continue; + } + memmove(bp->ebuf+oc, p, n); + oc += n; + c -= n; + p += n; + } + bp->ocount = oc; + return count-c; +} diff --git a/lib/libfmt/Makefile b/lib/libfmt/Makefile @@ -0,0 +1,48 @@ +ROOT= ../.. +include $(ROOT)/mk/hdr.mk + +VERSION=2.0 +TARG=libfmt + +NUM=\ + charstod\ + pow10\ + nan64 + +OBJ=\ + dofmt\ + dorfmt\ + errfmt\ + fltfmt\ + fmt\ + fmtfd\ + fmtfdflush\ + fmtlock\ + fmtprint\ + fmtquote\ + fmtrune\ + fmtstr\ + fmtvprint\ + fprint\ + print\ + runefmtstr\ + runeseprint\ + runesmprint\ + runesnprint\ + runesprint\ + runevseprint\ + runevsmprint\ + runevsnprint\ + seprint\ + smprint\ + snprint\ + sprint\ + strtod\ + vfprint\ + vseprint\ + vsmprint\ + vsnprint\ + $(NUM) + +include $(ROOT)/mk/lib.mk + diff --git a/lib/libfmt/NOTICE b/lib/libfmt/NOTICE @@ -0,0 +1,25 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. +*/ + +This is a Unix port of the Plan 9 formatted I/O package. + +Please send comments about the packaging +to Russ Cox <rsc@swtch.com>. + + +---- + +This software is also made available under the Lucent Public License +version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html + diff --git a/lib/libfmt/README b/lib/libfmt/README @@ -0,0 +1,5 @@ +This software was packaged for Unix by Russ Cox. +Please send comments to rsc@swtch.com. + +http://swtch.com/plan9port/unix + diff --git a/lib/libfmt/charstod.c b/lib/libfmt/charstod.c @@ -0,0 +1,85 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* + * Reads a floating-point number by interpreting successive characters + * returned by (*f)(vp). The last call it makes to f terminates the + * scan, so is not a character in the number. It may therefore be + * necessary to back up the input stream up one byte after calling charstod. + */ + +double +fmtcharstod(int(*f)(void*), void *vp) +{ + double num, dem; + int neg, eneg, dig, exp, c; + + num = 0; + neg = 0; + dig = 0; + exp = 0; + eneg = 0; + + c = (*f)(vp); + while(c == ' ' || c == '\t') + c = (*f)(vp); + if(c == '-' || c == '+'){ + if(c == '-') + neg = 1; + c = (*f)(vp); + } + while(c >= '0' && c <= '9'){ + num = num*10 + c-'0'; + c = (*f)(vp); + } + if(c == '.') + c = (*f)(vp); + while(c >= '0' && c <= '9'){ + num = num*10 + c-'0'; + dig++; + c = (*f)(vp); + } + if(c == 'e' || c == 'E'){ + c = (*f)(vp); + if(c == '-' || c == '+'){ + if(c == '-'){ + dig = -dig; + eneg = 1; + } + c = (*f)(vp); + } + while(c >= '0' && c <= '9'){ + exp = exp*10 + c-'0'; + c = (*f)(vp); + } + } + exp -= dig; + if(exp < 0){ + exp = -exp; + eneg = !eneg; + } + dem = __fmtpow10(exp); + if(eneg) + num /= dem; + else + num *= dem; + if(neg) + return -num; + return num; +} diff --git a/lib/libfmt/dofmt.c b/lib/libfmt/dofmt.c @@ -0,0 +1,537 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* format the output into f->to and return the number of characters fmted */ +int +dofmt(Fmt *f, const char *fmt) +{ + Rune rune, *rt, *rs; + int r; + char *t, *s; + int n, nfmt; + + nfmt = f->nfmt; + for(;;){ + if(f->runes){ + rt = (Rune*)f->to; + rs = (Rune*)f->stop; + while((r = *(uchar*)fmt) && r != '%'){ + if(r < Runeself) + fmt++; + else{ + fmt += chartorune(&rune, fmt); + r = rune; + } + FMTRCHAR(f, rt, rs, r); + } + fmt++; + f->nfmt += rt - (Rune *)f->to; + f->to = rt; + if(!r) + return f->nfmt - nfmt; + f->stop = rs; + }else{ + t = (char*)f->to; + s = (char*)f->stop; + while((r = *(uchar*)fmt) && r != '%'){ + if(r < Runeself){ + FMTCHAR(f, t, s, r); + fmt++; + }else{ + n = chartorune(&rune, fmt); + if(t + n > s){ + t = (char*)__fmtflush(f, t, n); + if(t != nil) + s = (char*)f->stop; + else + return -1; + } + while(n--) + *t++ = *fmt++; + } + } + fmt++; + f->nfmt += t - (char *)f->to; + f->to = t; + if(!r) + return f->nfmt - nfmt; + f->stop = s; + } + + fmt = (char*)__fmtdispatch(f, fmt, 0); + if(fmt == nil) + return -1; + } +} + +void * +__fmtflush(Fmt *f, void *t, int len) +{ + if(f->runes) + f->nfmt += (Rune*)t - (Rune*)f->to; + else + f->nfmt += (char*)t - (char *)f->to; + f->to = t; + if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){ + f->stop = f->to; + return nil; + } + return f->to; +} + +/* + * put a formatted block of memory sz bytes long of n runes into the output buffer, + * left/right justified in a field of at least f->width charactes + */ +int +__fmtpad(Fmt *f, int n) +{ + char *t, *s; + int i; + + t = (char*)f->to; + s = (char*)f->stop; + for(i = 0; i < n; i++) + FMTCHAR(f, t, s, ' '); + f->nfmt += t - (char *)f->to; + f->to = t; + return 0; +} + +int +__rfmtpad(Fmt *f, int n) +{ + Rune *t, *s; + int i; + + t = (Rune*)f->to; + s = (Rune*)f->stop; + for(i = 0; i < n; i++) + FMTRCHAR(f, t, s, ' '); + f->nfmt += t - (Rune *)f->to; + f->to = t; + return 0; +} + +int +__fmtcpy(Fmt *f, const void *vm, int n, int sz) +{ + Rune *rt, *rs, r; + char *t, *s, *m, *me; + ulong fl; + int nc, w; + + m = (char*)vm; + me = m + sz; + w = f->width; + fl = f->flags; + if((fl & FmtPrec) && n > f->prec) + n = f->prec; + if(f->runes){ + if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) + return -1; + rt = (Rune*)f->to; + rs = (Rune*)f->stop; + for(nc = n; nc > 0; nc--){ + r = *(uchar*)m; + if(r < Runeself) + m++; + else if((me - m) >= UTFmax || fullrune(m, me-m)) + m += chartorune(&r, m); + else + break; + FMTRCHAR(f, rt, rs, r); + } + f->nfmt += rt - (Rune *)f->to; + f->to = rt; + if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) + return -1; + }else{ + if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) + return -1; + t = (char*)f->to; + s = (char*)f->stop; + for(nc = n; nc > 0; nc--){ + r = *(uchar*)m; + if(r < Runeself) + m++; + else if((me - m) >= UTFmax || fullrune(m, me-m)) + m += chartorune(&r, m); + else + break; + FMTRUNE(f, t, s, r); + } + f->nfmt += t - (char *)f->to; + f->to = t; + if(fl & FmtLeft && __fmtpad(f, w - n) < 0) + return -1; + } + return 0; +} + +int +__fmtrcpy(Fmt *f, const void *vm, int n) +{ + Rune r, *m, *me, *rt, *rs; + char *t, *s; + ulong fl; + int w; + + m = (Rune*)vm; + w = f->width; + fl = f->flags; + if((fl & FmtPrec) && n > f->prec) + n = f->prec; + if(f->runes){ + if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) + return -1; + rt = (Rune*)f->to; + rs = (Rune*)f->stop; + for(me = m + n; m < me; m++) + FMTRCHAR(f, rt, rs, *m); + f->nfmt += rt - (Rune *)f->to; + f->to = rt; + if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) + return -1; + }else{ + if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) + return -1; + t = (char*)f->to; + s = (char*)f->stop; + for(me = m + n; m < me; m++){ + r = *m; + FMTRUNE(f, t, s, r); + } + f->nfmt += t - (char *)f->to; + f->to = t; + if(fl & FmtLeft && __fmtpad(f, w - n) < 0) + return -1; + } + return 0; +} + +/* fmt out one character */ +int +__charfmt(Fmt *f) +{ + char x[1]; + + x[0] = va_arg(f->args, int); + f->prec = 1; + return __fmtcpy(f, (const char*)x, 1, 1); +} + +/* fmt out one rune */ +int +__runefmt(Fmt *f) +{ + Rune x[1]; + + x[0] = va_arg(f->args, int); + return __fmtrcpy(f, (const void*)x, 1); +} + +/* public helper routine: fmt out a null terminated string already in hand */ +int +fmtstrcpy(Fmt *f, const char *s) +{ + int i, j; + Rune r; + + if(!s) + return __fmtcpy(f, "<nil>", 5, 5); + /* if precision is specified, make sure we don't wander off the end */ + if(f->flags & FmtPrec){ + i = 0; + for(j=0; j<f->prec && s[i]; j++) + i += chartorune(&r, s+i); + return __fmtcpy(f, s, j, i); + } + return __fmtcpy(f, s, utflen(s), strlen(s)); +} + +/* fmt out a null terminated utf string */ +int +__strfmt(Fmt *f) +{ + char *s; + + s = va_arg(f->args, char *); + return fmtstrcpy(f, s); +} + +/* public helper routine: fmt out a null terminated rune string already in hand */ +int +fmtrunestrcpy(Fmt *f, Rune *s) +{ + Rune *e; + int n, p; + + if(!s) + return __fmtcpy(f, "<nil>", 5, 5); + /* if precision is specified, make sure we don't wander off the end */ + if(f->flags & FmtPrec){ + p = f->prec; + for(n = 0; n < p; n++) + if(s[n] == 0) + break; + }else{ + for(e = s; *e; e++) + ; + n = e - s; + } + return __fmtrcpy(f, s, n); +} + +/* fmt out a null terminated rune string */ +int +__runesfmt(Fmt *f) +{ + Rune *s; + + s = va_arg(f->args, Rune *); + return fmtrunestrcpy(f, s); +} + +/* fmt a % */ +int +__percentfmt(Fmt *f) +{ + Rune x[1]; + + x[0] = f->r; + f->prec = 1; + return __fmtrcpy(f, (const void*)x, 1); +} + +/* fmt an integer */ +int +__ifmt(Fmt *f) +{ + char buf[70], *p, *conv; + uvlong vu; + ulong u; + int neg, base, i, n, fl, w, isv; + + neg = 0; + fl = f->flags; + isv = 0; + vu = 0; + u = 0; + if(f->r == 'p'){ + u = (ulong)va_arg(f->args, void*); + f->r = 'x'; + fl |= FmtUnsigned; + }else if(fl & FmtVLong){ + isv = 1; + if(fl & FmtUnsigned) + vu = va_arg(f->args, uvlong); + else + vu = va_arg(f->args, vlong); + }else if(fl & FmtLong){ + if(fl & FmtUnsigned) + u = va_arg(f->args, ulong); + else + u = va_arg(f->args, long); + }else if(fl & FmtByte){ + if(fl & FmtUnsigned) + u = (uchar)va_arg(f->args, int); + else + u = (char)va_arg(f->args, int); + }else if(fl & FmtShort){ + if(fl & FmtUnsigned) + u = (ushort)va_arg(f->args, int); + else + u = (short)va_arg(f->args, int); + }else{ + if(fl & FmtUnsigned) + u = va_arg(f->args, uint); + else + u = va_arg(f->args, int); + } + conv = "0123456789abcdef"; + switch(f->r){ + case 'd': + case 'i': + case 'u': + base = 10; + break; + case 'x': + base = 16; + break; + case 'X': + base = 16; + conv = "0123456789ABCDEF"; + break; + case 'b': + base = 2; + break; + case 'o': + base = 8; + break; + default: + return -1; + } + if(!(fl & FmtUnsigned)){ + if(isv && (vlong)vu < 0){ + vu = -(vlong)vu; + neg = 1; + }else if(!isv && (long)u < 0){ + u = -(long)u; + neg = 1; + } + } + p = buf + sizeof buf - 1; + n = 0; + if(isv){ + while(vu){ + i = vu % base; + vu /= base; + if((fl & FmtComma) && n % 4 == 3){ + *p-- = ','; + n++; + } + *p-- = conv[i]; + n++; + } + }else{ + while(u){ + i = u % base; + u /= base; + if((fl & FmtComma) && n % 4 == 3){ + *p-- = ','; + n++; + } + *p-- = conv[i]; + n++; + } + } + if(n == 0){ + *p-- = '0'; + n = 1; + } + for(w = f->prec; n < w && p > buf+3; n++) + *p-- = '0'; + if(neg || (fl & (FmtSign|FmtSpace))) + n++; + if(fl & FmtSharp){ + if(base == 16) + n += 2; + else if(base == 8){ + if(p[1] == '0') + fl &= ~FmtSharp; + else + n++; + } + } + if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){ + for(w = f->width; n < w && p > buf+3; n++) + *p-- = '0'; + f->width = 0; + } + if(fl & FmtSharp){ + if(base == 16) + *p-- = f->r; + if(base == 16 || base == 8) + *p-- = '0'; + } + if(neg) + *p-- = '-'; + else if(fl & FmtSign) + *p-- = '+'; + else if(fl & FmtSpace) + *p-- = ' '; + f->flags &= ~FmtPrec; + return __fmtcpy(f, p + 1, n, n); +} + +int +__countfmt(Fmt *f) +{ + void *p; + ulong fl; + + fl = f->flags; + p = va_arg(f->args, void*); + if(fl & FmtVLong){ + *(vlong*)p = f->nfmt; + }else if(fl & FmtLong){ + *(long*)p = f->nfmt; + }else if(fl & FmtByte){ + *(char*)p = f->nfmt; + }else if(fl & FmtShort){ + *(short*)p = f->nfmt; + }else{ + *(int*)p = f->nfmt; + } + return 0; +} + +int +__flagfmt(Fmt *f) +{ + switch(f->r){ + case ',': + f->flags |= FmtComma; + break; + case '-': + f->flags |= FmtLeft; + break; + case '+': + f->flags |= FmtSign; + break; + case '#': + f->flags |= FmtSharp; + break; + case ' ': + f->flags |= FmtSpace; + break; + case 'u': + f->flags |= FmtUnsigned; + break; + case 'h': + if(f->flags & FmtShort) + f->flags |= FmtByte; + f->flags |= FmtShort; + break; + case 'L': + f->flags |= FmtLDouble; + break; + case 'l': + if(f->flags & FmtLong) + f->flags |= FmtVLong; + f->flags |= FmtLong; + break; + } + return 1; +} + +/* default error format */ +int +__badfmt(Fmt *f) +{ + char x[3]; + + x[0] = '%'; + x[1] = f->r; + x[2] = '%'; + f->prec = 3; + __fmtcpy(f, (const void*)x, 3, 3); + return 0; +} diff --git a/lib/libfmt/dorfmt.c b/lib/libfmt/dorfmt.c @@ -0,0 +1,60 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* format the output into f->to and return the number of characters fmted */ + +int +dorfmt(Fmt *f, const Rune *fmt) +{ + Rune *rt, *rs; + int r; + char *t, *s; + int nfmt; + + nfmt = f->nfmt; + for(;;){ + if(f->runes){ + rt = f->to; + rs = f->stop; + while((r = *fmt++) && r != '%'){ + FMTRCHAR(f, rt, rs, r); + } + f->nfmt += rt - (Rune *)f->to; + f->to = rt; + if(!r) + return f->nfmt - nfmt; + f->stop = rs; + }else{ + t = f->to; + s = f->stop; + while((r = *fmt++) && r != '%'){ + FMTRUNE(f, t, f->stop, r); + } + f->nfmt += t - (char *)f->to; + f->to = t; + if(!r) + return f->nfmt - nfmt; + f->stop = s; + } + + fmt = __fmtdispatch(f, (Rune*)fmt, 1); + if(fmt == nil) + return -1; + } +} diff --git a/lib/libfmt/errfmt.c b/lib/libfmt/errfmt.c @@ -0,0 +1,28 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +__errfmt(Fmt *f) +{ + char *s; + + s = strerror(errno); + return fmtstrcpy(f, s); +} diff --git a/lib/libfmt/fltfmt.c b/lib/libfmt/fltfmt.c @@ -0,0 +1,392 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdio.h> +#include <math.h> +#include <float.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <stdarg.h> +#include <ctype.h> +#include "plan9.h" +#include "fmtdef.h" + +enum +{ + FDIGIT = 30, + FDEFLT = 6, + NSIGNIF = 17 +}; + +/* + * first few powers of 10, enough for about 1/2 of the + * total space for doubles. + */ +static double pows10[] = +{ + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, + 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, + 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, + 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, + 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, + 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, + 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, + 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, +}; + +#define pow10(x) fmtpow10(x) + +static double +pow10(int n) +{ + double d; + int neg; + + neg = 0; + if(n < 0){ + if(n < DBL_MIN_10_EXP){ + return 0.; + } + neg = 1; + n = -n; + }else if(n > DBL_MAX_10_EXP){ + return HUGE_VAL; + } + if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))) + d = pows10[n]; + else{ + d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1]; + for(;;){ + n -= sizeof(pows10)/sizeof(pows10[0]) - 1; + if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){ + d *= pows10[n]; + break; + } + d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1]; + } + } + if(neg){ + return 1./d; + } + return d; +} + +static int +xadd(char *a, int n, int v) +{ + char *b; + int c; + + if(n < 0 || n >= NSIGNIF) + return 0; + for(b = a+n; b >= a; b--) { + c = *b + v; + if(c <= '9') { + *b = c; + return 0; + } + *b = '0'; + v = 1; + } + *a = '1'; /* overflow adding */ + return 1; +} + +static int +xsub(char *a, int n, int v) +{ + char *b; + int c; + + for(b = a+n; b >= a; b--) { + c = *b - v; + if(c >= '0') { + *b = c; + return 0; + } + *b = '9'; + v = 1; + } + *a = '9'; /* underflow subtracting */ + return 1; +} + +static void +xdtoa(Fmt *fmt, char *s2, double f) +{ + char s1[NSIGNIF+10]; + double g, h; + int e, d, i, n; + int c1, c2, c3, c4, ucase, sign, chr, prec; + + prec = FDEFLT; + if(fmt->flags & FmtPrec) + prec = fmt->prec; + if(prec > FDIGIT) + prec = FDIGIT; + if(__isNaN(f)) { + strcpy(s2, "NaN"); + return; + } + if(__isInf(f, 1)) { + strcpy(s2, "+Inf"); + return; + } + if(__isInf(f, -1)) { + strcpy(s2, "-Inf"); + return; + } + sign = 0; + if(f < 0) { + f = -f; + sign++; + } + ucase = 0; + chr = fmt->r; + if(isupper(chr)) { + ucase = 1; + chr = tolower(chr); + } + + e = 0; + g = f; + if(g != 0) { + frexp(f, &e); + e = e * .301029995664; + if(e >= -150 && e <= +150) { + d = 0; + h = f; + } else { + d = e/2; + h = f * pow10(-d); + } + g = h * pow10(d-e); + while(g < 1) { + e--; + g = h * pow10(d-e); + } + while(g >= 10) { + e++; + g = h * pow10(d-e); + } + } + + /* + * convert NSIGNIF digits and convert + * back to get accuracy. + */ + for(i=0; i<NSIGNIF; i++) { + d = g; + s1[i] = d + '0'; + g = (g - d) * 10; + } + s1[i] = 0; + + /* + * try decimal rounding to eliminate 9s + */ + c2 = prec + 1; + if(chr == 'f') + c2 += e; + if(c2 >= NSIGNIF-2) { + strcpy(s2, s1); + d = e; + s1[NSIGNIF-2] = '0'; + s1[NSIGNIF-1] = '0'; + sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); + g = strtod(s1, nil); + if(g == f) + goto found; + if(xadd(s1, NSIGNIF-3, 1)) { + e++; + sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); + } + g = strtod(s1, nil); + if(g == f) + goto found; + strcpy(s1, s2); + e = d; + } + + /* + * convert back so s1 gets exact answer + */ + for(;;) { + sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); + g = strtod(s1, nil); + if(f > g) { + if(xadd(s1, NSIGNIF-1, 1)) + e--; + continue; + } + if(f < g) { + if(xsub(s1, NSIGNIF-1, 1)) + e++; + continue; + } + break; + } + +found: + /* + * sign + */ + d = 0; + i = 0; + if(sign) + s2[d++] = '-'; + else if(fmt->flags & FmtSign) + s2[d++] = '+'; + else if(fmt->flags & FmtSpace) + s2[d++] = ' '; + + /* + * copy into final place + * c1 digits of leading '0' + * c2 digits from conversion + * c3 digits of trailing '0' + * c4 digits after '.' + */ + c1 = 0; + c2 = prec + 1; + c3 = 0; + c4 = prec; + switch(chr) { + default: + if(xadd(s1, c2, 5)) + e++; + break; + case 'g': + /* + * decide on 'e' of 'f' style convers + */ + if(xadd(s1, c2, 5)) + e++; + if(e >= -5 && e <= prec) { + c1 = -e - 1; + c4 = prec - e; + chr = 'h'; // flag for 'f' style + } + break; + case 'f': + if(xadd(s1, c2+e, 5)) + e++; + c1 = -e; + if(c1 > prec) + c1 = c2; + c2 += e; + break; + } + + /* + * clean up c1 c2 and c3 + */ + if(c1 < 0) + c1 = 0; + if(c2 < 0) + c2 = 0; + if(c2 > NSIGNIF) { + c3 = c2-NSIGNIF; + c2 = NSIGNIF; + } + + /* + * copy digits + */ + while(c1 > 0) { + if(c1+c2+c3 == c4) + s2[d++] = '.'; + s2[d++] = '0'; + c1--; + } + while(c2 > 0) { + if(c2+c3 == c4) + s2[d++] = '.'; + s2[d++] = s1[i++]; + c2--; + } + while(c3 > 0) { + if(c3 == c4) + s2[d++] = '.'; + s2[d++] = '0'; + c3--; + } + + /* + * strip trailing '0' on g conv + */ + if(fmt->flags & FmtSharp) { + if(0 == c4) + s2[d++] = '.'; + } else + if(chr == 'g' || chr == 'h') { + for(n=d-1; n>=0; n--) + if(s2[n] != '0') + break; + for(i=n; i>=0; i--) + if(s2[i] == '.') { + d = n; + if(i != n) + d++; + break; + } + } + if(chr == 'e' || chr == 'g') { + if(ucase) + s2[d++] = 'E'; + else + s2[d++] = 'e'; + c1 = e; + if(c1 < 0) { + s2[d++] = '-'; + c1 = -c1; + } else + s2[d++] = '+'; + if(c1 >= 100) { + s2[d++] = c1/100 + '0'; + c1 = c1%100; + } + s2[d++] = c1/10 + '0'; + s2[d++] = c1%10 + '0'; + } + s2[d] = 0; +} + +static int +floatfmt(Fmt *fmt, double f) +{ + char s[FDIGIT+10]; + + xdtoa(fmt, s, f); + fmt->flags &= FmtWidth|FmtLeft; + __fmtcpy(fmt, s, strlen(s), strlen(s)); + return 0; +} + +int +__efgfmt(Fmt *f) +{ + double d; + + d = va_arg(f->args, double); + return floatfmt(f, d); +} diff --git a/lib/libfmt/fmt.c b/lib/libfmt/fmt.c @@ -0,0 +1,218 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +enum +{ + Maxfmt = 64 +}; + +typedef struct Convfmt Convfmt; +struct Convfmt +{ + int c; + volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */ +}; + +struct +{ + /* lock by calling __fmtlock, __fmtunlock */ + int nfmt; + Convfmt fmt[Maxfmt]; +} fmtalloc; + +static Convfmt knownfmt[] = { + ' ', __flagfmt, + '#', __flagfmt, + '%', __percentfmt, + '+', __flagfmt, + ',', __flagfmt, + '-', __flagfmt, + 'C', __runefmt, /* Plan 9 addition */ + 'E', __efgfmt, + 'G', __efgfmt, + 'S', __runesfmt, /* Plan 9 addition */ + 'X', __ifmt, + 'b', __ifmt, /* Plan 9 addition */ + 'c', __charfmt, + 'd', __ifmt, + 'e', __efgfmt, + 'f', __efgfmt, + 'g', __efgfmt, + 'h', __flagfmt, + 'l', __flagfmt, + 'n', __countfmt, + 'o', __ifmt, + 'p', __ifmt, + 'r', __errfmt, + 's', __strfmt, + 'u', __flagfmt, + 'x', __ifmt, + 0, nil, +}; + + +int (*fmtdoquote)(int); + +/* + * __fmtlock() must be set + */ +static int +__fmtinstall(int c, Fmts f) +{ + Convfmt *p, *ep; + + if(c<=0 || c>=65536) + return -1; + if(!f) + f = __badfmt; + + ep = &fmtalloc.fmt[fmtalloc.nfmt]; + for(p=fmtalloc.fmt; p<ep; p++) + if(p->c == c) + break; + + if(p == &fmtalloc.fmt[Maxfmt]) + return -1; + + p->fmt = f; + if(p == ep){ /* installing a new format character */ + fmtalloc.nfmt++; + p->c = c; + } + + return 0; +} + +int +fmtinstall(int c, int (*f)(Fmt*)) +{ + int ret; + + __fmtlock(); + ret = __fmtinstall(c, f); + __fmtunlock(); + return ret; +} + +static Fmts +fmtfmt(int c) +{ + Convfmt *p, *ep; + + ep = &fmtalloc.fmt[fmtalloc.nfmt]; + for(p=fmtalloc.fmt; p<ep; p++) + if(p->c == c){ + while(p->fmt == nil) /* loop until value is updated */ + ; + return p->fmt; + } + + /* is this a predefined format char? */ + __fmtlock(); + for(p=knownfmt; p->c; p++) + if(p->c == c){ + __fmtinstall(p->c, p->fmt); + __fmtunlock(); + return p->fmt; + } + __fmtunlock(); + + return __badfmt; +} + +void* +__fmtdispatch(Fmt *f, const void *fmt, int isrunes) +{ + Rune rune, r; + int i, n; + + f->flags = 0; + f->width = f->prec = 0; + + for(;;){ + if(isrunes){ + r = *(Rune*)fmt; + fmt = (Rune*)fmt + 1; + }else{ + fmt = (char*)fmt + chartorune(&rune, (char*)fmt); + r = rune; + } + f->r = r; + switch(r){ + case '\0': + return nil; + case '.': + f->flags |= FmtWidth|FmtPrec; + continue; + case '0': + if(!(f->flags & FmtWidth)){ + f->flags |= FmtZero; + continue; + } + /* fall through */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + i = 0; + while(r >= '0' && r <= '9'){ + i = i * 10 + r - '0'; + if(isrunes){ + r = *(Rune*)fmt; + fmt = (Rune*)fmt + 1; + }else{ + r = *(char*)fmt; + fmt = (char*)fmt + 1; + } + } + if(isrunes) + fmt = (Rune*)fmt - 1; + else + fmt = (char*)fmt - 1; + numflag: + if(f->flags & FmtWidth){ + f->flags |= FmtPrec; + f->prec = i; + }else{ + f->flags |= FmtWidth; + f->width = i; + } + continue; + case '*': + i = va_arg(f->args, int); + if(i < 0){ + /* + * negative precision => + * ignore the precision. + */ + if(f->flags & FmtPrec){ + f->flags &= ~FmtPrec; + f->prec = 0; + continue; + } + i = -i; + f->flags |= FmtLeft; + } + goto numflag; + } + n = (*fmtfmt(r))(f); + if(n < 0) + return nil; + if(n == 0) + return (void*)fmt; + } +} diff --git a/lib/libfmt/fmtdef.h b/lib/libfmt/fmtdef.h @@ -0,0 +1,112 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ + +/* + * dofmt -- format to a buffer + * the number of characters formatted is returned, + * or -1 if there was an error. + * if the buffer is ever filled, flush is called. + * it should reset the buffer and return whether formatting should continue. + */ + +typedef int (*Fmts)(Fmt*); + +typedef struct Quoteinfo Quoteinfo; +struct Quoteinfo +{ + int quoted; /* if set, string must be quoted */ + int nrunesin; /* number of input runes that can be accepted */ + int nbytesin; /* number of input bytes that can be accepted */ + int nrunesout; /* number of runes that will be generated */ + int nbytesout; /* number of bytes that will be generated */ +}; + +/* Edit .+1,/^$/ |cfn |grep -v static | grep __ */ +double __Inf(int sign); +double __NaN(void); +int __badfmt(Fmt *f); +int __charfmt(Fmt *f); +int __countfmt(Fmt *f); +int __efgfmt(Fmt *fmt); +int __errfmt(Fmt *f); +int __flagfmt(Fmt *f); +int __fmtFdFlush(Fmt *f); +int __fmtcpy(Fmt *f, const void *vm, int n, int sz); +void* __fmtdispatch(Fmt *f, const void *fmt, int isrunes); +void * __fmtflush(Fmt *f, void *t, int len); +void __fmtlock(void); +int __fmtpad(Fmt *f, int n); +double __fmtpow10(int n); +int __fmtrcpy(Fmt *f, const void *vm, int n); +void __fmtunlock(void); +int __ifmt(Fmt *f); +int __isInf(double d, int sign); +int __isNaN(double d); +int __needsquotes(char *s, int *quotelenp); +int __percentfmt(Fmt *f); +void __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout); +int __quotestrfmt(int runesin, Fmt *f); +int __rfmtpad(Fmt *f, int n); +int __runefmt(Fmt *f); +int __runeneedsquotes(Rune *r, int *quotelenp); +int __runesfmt(Fmt *f); +int __strfmt(Fmt *f); + +#define FMTCHAR(f, t, s, c)\ + do{\ + if(t + 1 > (char*)s){\ + t = __fmtflush(f, t, 1);\ + if(t != nil)\ + s = f->stop;\ + else\ + return -1;\ + }\ + *t++ = c;\ + }while(0) + +#define FMTRCHAR(f, t, s, c)\ + do{\ + if(t + 1 > (Rune*)s){\ + t = __fmtflush(f, t, sizeof(Rune));\ + if(t != nil)\ + s = f->stop;\ + else\ + return -1;\ + }\ + *t++ = c;\ + }while(0) + +#define FMTRUNE(f, t, s, r)\ + do{\ + Rune _rune;\ + int _runelen;\ + if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\ + t = __fmtflush(f, t, _runelen);\ + if(t != nil)\ + s = f->stop;\ + else\ + return -1;\ + }\ + if(r < Runeself)\ + *t++ = r;\ + else{\ + _rune = r;\ + t += runetochar(t, &_rune);\ + }\ + }while(0) + +#ifndef va_copy +# define va_copy(a,b) (a) = (b) +#endif + diff --git a/lib/libfmt/fmtfd.c b/lib/libfmt/fmtfd.c @@ -0,0 +1,46 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* + * public routine for final flush of a formatting buffer + * to a file descriptor; returns total char count. + */ +int +fmtfdflush(Fmt *f) +{ + if(__fmtFdFlush(f) <= 0) + return -1; + return f->nfmt; +} + +/* + * initialize an output buffer for buffered printing + */ +int +fmtfdinit(Fmt *f, int fd, char *buf, int size) +{ + f->runes = 0; + f->start = buf; + f->to = buf; + f->stop = buf + size; + f->flush = __fmtFdFlush; + f->farg = (void*)(uintptr_t)fd; + f->nfmt = 0; + return 0; +} diff --git a/lib/libfmt/fmtfdflush.c b/lib/libfmt/fmtfdflush.c @@ -0,0 +1,34 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <unistd.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* + * generic routine for flushing a formatting buffer + * to a file descriptor + */ +int +__fmtFdFlush(Fmt *f) +{ + int n; + + n = (char*)f->to - (char*)f->start; + if(n && write((uintptr_t)f->farg, f->start, n) != n) + return 0; + f->to = f->start; + return 1; +} diff --git a/lib/libfmt/fmtinstall.3 b/lib/libfmt/fmtinstall.3 @@ -0,0 +1,379 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH FMTINSTALL 3 +.SH NAME +fmtinstall, dofmt, dorfmt, fmtprint, fmtvprint, fmtrune, fmtstrcpy, fmtrunestrcpy, fmtfdinit, fmtfdflush, fmtstrinit, fmtstrflush, runefmtstrinit, runefmtstrflush, errfmt \- support for user-defined print formats and output routines +.SH SYNOPSIS +.B #include <utf.h> +.br +.B #include <fmt.h> +.PP +.ft L +.nf +.ta \w' 'u +\w' 'u +\w' 'u +\w' 'u +\w' 'u +typedef struct Fmt Fmt; +struct Fmt{ + uchar runes; /* output buffer is runes or chars? */ + void *start; /* of buffer */ + void *to; /* current place in the buffer */ + void *stop; /* end of the buffer; overwritten if flush fails */ + int (*flush)(Fmt*); /* called when to == stop */ + void *farg; /* to make flush a closure */ + int nfmt; /* num chars formatted so far */ + va_list args; /* args passed to dofmt */ + int r; /* % format Rune */ + int width; + int prec; + ulong flags; +}; + +enum{ + FmtWidth = 1, + FmtLeft = FmtWidth << 1, + FmtPrec = FmtLeft << 1, + FmtSharp = FmtPrec << 1, + FmtSpace = FmtSharp << 1, + FmtSign = FmtSpace << 1, + FmtZero = FmtSign << 1, + FmtUnsigned = FmtZero << 1, + FmtShort = FmtUnsigned << 1, + FmtLong = FmtShort << 1, + FmtVLong = FmtLong << 1, + FmtComma = FmtVLong << 1, + + FmtFlag = FmtComma << 1 +}; +.fi +.PP +.B +.ta \w'\fLchar* 'u + +.PP +.B +int fmtfdinit(Fmt *f, int fd, char *buf, int nbuf); +.PP +.B +int fmtfdflush(Fmt *f); +.PP +.B +int fmtstrinit(Fmt *f); +.PP +.B +char* fmtstrflush(Fmt *f); +.PP +.B +int runefmtstrinit(Fmt *f); +.PP +.B +Rune* runefmtstrflush(Fmt *f); + +.PP +.B +int fmtinstall(int c, int (*fn)(Fmt*)); +.PP +.B +int dofmt(Fmt *f, char *fmt); +.PP +.B +int dorfmt(Fmt*, Rune *fmt); +.PP +.B +int fmtprint(Fmt *f, char *fmt, ...); +.PP +.B +int fmtvprint(Fmt *f, char *fmt, va_list v); +.PP +.B +int fmtrune(Fmt *f, int r); +.PP +.B +int fmtstrcpy(Fmt *f, char *s); +.PP +.B +int fmtrunestrcpy(Fmt *f, Rune *s); +.PP +.B +int errfmt(Fmt *f); +.SH DESCRIPTION +The interface described here allows the construction of custom +.IR print (3) +verbs and output routines. +In essence, they provide access to the workings of the formatted print code. +.PP +The +.IR print (3) +suite maintains its state with a data structure called +.BR Fmt . +A typical call to +.IR print (3) +or its relatives initializes a +.B Fmt +structure, passes it to subsidiary routines to process the output, +and finishes by emitting any saved state recorded in the +.BR Fmt . +The details of the +.B Fmt +are unimportant to outside users, except insofar as the general +design influences the interface. +The +.B Fmt +records whether the output is in runes or bytes, +the verb being processed, its precision and width, +and buffering parameters. +Most important, it also records a +.I flush +routine that the library will call if a buffer overflows. +When printing to a file descriptor, the flush routine will +emit saved characters and reset the buffer; when printing +to an allocated string, it will resize the string to receive more output. +The flush routine is nil when printing to fixed-size buffers. +User code need never provide a flush routine; this is done internally +by the library. +.SS Custom output routines +To write a custom output routine, such as an error handler that +formats and prints custom error messages, the output sequence can be run +from outside the library using the routines described here. +There are two main cases: output to an open file descriptor +and output to a string. +.PP +To write to a file descriptor, call +.I fmtfdinit +to initialize the local +.B Fmt +structure +.IR f , +giving the file descriptor +.IR fd , +the buffer +.IR buf , +and its size +.IR nbuf . +Then call +.IR fmtprint +or +.IR fmtvprint +to generate the output. +These behave like +.B fprint +(see +.IR print (3)) +or +.B vfprint +except that the characters are buffered until +.I fmtfdflush +is called and the return value is either 0 or \-1. +A typical example of this sequence appears in the Examples section. +.PP +The same basic sequence applies when outputting to an allocated string: +call +.I fmtstrinit +to initialize the +.BR Fmt , +then call +.I fmtprint +and +.I fmtvprint +to generate the output. +Finally, +.I fmtstrflush +will return the allocated string, which should be freed after use. +To output to a rune string, use +.I runefmtstrinit +and +.IR runefmtstrflush . +Regardless of the output style or type, +.I fmtprint +or +.I fmtvprint +generates the characters. +.SS Custom format verbs +.I Fmtinstall +is used to install custom verbs and flags labeled by character +.IR c , +which may be any non-zero Unicode character. +.I Fn +should be declared as +.IP +.EX +int fn(Fmt*) +.EE +.PP +.IB Fp ->r +is the flag or verb character to cause +.I fn +to be called. +In +.IR fn , +.IB fp ->width , +.IB fp ->prec +are the width and precision, and +.IB fp ->flags +the decoded flags for the verb (see +.IR print (3) +for a description of these items). +The standard flag values are: +.B FmtSign +.RB ( + ), +.B FmtLeft +.RB ( - ), +.B FmtSpace +.RB ( '\ ' ), +.B FmtSharp +.RB ( # ), +.B FmtComma +.RB ( , ), +.B FmtLong +.RB ( l ), +.B FmtShort +.RB ( h ), +.B FmtUnsigned +.RB ( u ), +and +.B FmtVLong +.RB ( ll ). +The flag bits +.B FmtWidth +and +.B FmtPrec +identify whether a width and precision were specified. +.PP +.I Fn +is passed a pointer to the +.B Fmt +structure recording the state of the output. +If +.IB fp ->r +is a verb (rather than a flag), +.I fn +should use +.B Fmt->args +to fetch its argument from the list, +then format it, and return zero. +If +.IB fp ->r +is a flag, +.I fn +should return one. +All interpretation of +.IB fp ->width\f1, +.IB fp ->prec\f1, +and +.IB fp-> flags +is left up to the conversion routine. +.I Fmtinstall +returns 0 if the installation succeeds, \-1 if it fails. +.PP +.IR Fmtprint +and +.IR fmtvprint +may be called to +help prepare output in custom conversion routines. +However, these functions clear the width, precision, and flags. +Both functions return 0 for success and \-1 for failure. +.PP +The functions +.I dofmt +and +.I dorfmt +are the underlying formatters; they +use the existing contents of +.B Fmt +and should be called only by sophisticated conversion routines. +These routines return the number of characters (bytes of UTF or runes) +produced. +.PP +Some internal functions may be useful to format primitive types. +They honor the width, precision and flags as described in +.IR print (3). +.I Fmtrune +formats a single character +.BR r . +.I Fmtstrcpy +formats a string +.BR s ; +.I fmtrunestrcpy +formats a rune string +.BR s . +.I Errfmt +formats the system error string. +All these routines return zero for successful execution. +Conversion routines that call these functions will work properly +regardless of whether the output is bytes or runes. +.\" .PP +.\" .IR 2c (1) +.\" describes the C directive +.\" .B #pragma +.\" .B varargck +.\" that can be used to provide type-checking for custom print verbs and output routines. +.SH EXAMPLES +This function prints an error message with a variable +number of arguments and then quits. +Compared to the corresponding example in +.IR print (3), +this version uses a smaller buffer, will never truncate +the output message, but might generate multiple +.B write +system calls to produce its output. +.IP +.EX +.ta 6n +6n +6n +6n +6n +6n +6n +6n +6n +#pragma varargck argpos error 1 + +void fatal(char *fmt, ...) +{ + Fmt f; + char buf[64]; + va_list arg; + + fmtfdinit(&f, 1, buf, sizeof buf); + fmtprint(&f, "fatal: "); + va_start(arg, fmt); + fmtvprint(&f, fmt, arg); + va_end(arg); + fmtprint(&f, "\en"); + fmtfdflush(&f); + exits("fatal error"); +} +.EE +.PP +This example adds a verb to print complex numbers. +.IP +.EX +typedef +struct { + double r, i; +} Complex; + +#pragma varargck type "X" Complex + +int +Xfmt(Fmt *f) +{ + Complex c; + + c = va_arg(f->args, Complex); + return fmtprint(f, "(%g,%g)", c.r, c.i); +} + +main(...) +{ + Complex x = (Complex){ 1.5, -2.3 }; + + fmtinstall('X', Xfmt); + print("x = %X\en", x); +} +.EE +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH SEE ALSO +.IR print (3), +.IR utf (7) +.SH DIAGNOSTICS +These routines return negative numbers or nil for errors and set +.IR errstr . diff --git a/lib/libfmt/fmtlock.c b/lib/libfmt/fmtlock.c @@ -0,0 +1,27 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +void +__fmtlock(void) +{ +} + +void +__fmtunlock(void) +{ +} diff --git a/lib/libfmt/fmtprint.c b/lib/libfmt/fmtprint.c @@ -0,0 +1,48 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* + * format a string into the output buffer + * designed for formats which themselves call fmt, + * but ignore any width flags + */ +int +fmtprint(Fmt *f, const char *fmt, ...) +{ + va_list va; + int n; + + f->flags = 0; + f->width = 0; + f->prec = 0; + va_copy(va, f->args); + va_end(f->args); + va_start(f->args, fmt); + n = dofmt(f, fmt); + va_end(f->args); + f->flags = 0; + f->width = 0; + f->prec = 0; + va_copy(f->args,va); + va_end(va); + if(n >= 0) + return 0; + return n; +} + diff --git a/lib/libfmt/fmtquote.c b/lib/libfmt/fmtquote.c @@ -0,0 +1,264 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* + * How many bytes of output UTF will be produced by quoting (if necessary) this string? + * How many runes? How much of the input will be consumed? + * The parameter q is filled in by __quotesetup. + * The string may be UTF or Runes (s or r). + * Return count does not include NUL. + * Terminate the scan at the first of: + * NUL in input + * count exceeded in input + * count exceeded on output + * *ninp is set to number of input bytes accepted. + * nin may be <0 initially, to avoid checking input by count. + */ +void +__quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout) +{ + int w; + Rune c; + + q->quoted = 0; + q->nbytesout = 0; + q->nrunesout = 0; + q->nbytesin = 0; + q->nrunesin = 0; + if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){ + if(nout < 2) + return; + q->quoted = 1; + q->nbytesout = 2; + q->nrunesout = 2; + } + for(; nin!=0; nin--){ + if(s) + w = chartorune(&c, s); + else{ + c = *r; + w = runelen(c); + } + + if(c == '\0') + break; + if(runesout){ + if(q->nrunesout+1 > nout) + break; + }else{ + if(q->nbytesout+w > nout) + break; + } + + if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){ + if(!q->quoted){ + if(runesout){ + if(1+q->nrunesout+1+1 > nout) /* no room for quotes */ + break; + }else{ + if(1+q->nbytesout+w+1 > nout) /* no room for quotes */ + break; + } + q->nrunesout += 2; /* include quotes */ + q->nbytesout += 2; /* include quotes */ + q->quoted = 1; + } + if(c == '\'') { + if(runesout){ + if(1+q->nrunesout+1 > nout) /* no room for quotes */ + break; + }else{ + if(1+q->nbytesout+w > nout) /* no room for quotes */ + break; + } + q->nbytesout++; + q->nrunesout++; /* quotes reproduce as two characters */ + } + } + + /* advance input */ + if(s) + s += w; + else + r++; + q->nbytesin += w; + q->nrunesin++; + + /* advance output */ + q->nbytesout += w; + q->nrunesout++; + } +} + +static int +qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f) +{ + Rune r, *rm, *rme; + char *t, *s, *m, *me; + Rune *rt, *rs; + ulong fl; + int nc, w; + + m = sin; + me = m + q->nbytesin; + rm = rin; + rme = rm + q->nrunesin; + + w = f->width; + fl = f->flags; + if(f->runes){ + if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0) + return -1; + }else{ + if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) + return -1; + } + t = (char*)f->to; + s = (char*)f->stop; + rt = (Rune*)f->to; + rs = (Rune*)f->stop; + if(f->runes) + FMTRCHAR(f, rt, rs, '\''); + else + FMTRUNE(f, t, s, '\''); + for(nc = q->nrunesin; nc > 0; nc--){ + if(sin){ + r = *(uchar*)m; + if(r < Runeself) + m++; + else if((me - m) >= UTFmax || fullrune(m, me-m)) + m += chartorune(&r, m); + else + break; + }else{ + if(rm >= rme) + break; + r = *(uchar*)rm++; + } + if(f->runes){ + FMTRCHAR(f, rt, rs, r); + if(r == '\'') + FMTRCHAR(f, rt, rs, r); + }else{ + FMTRUNE(f, t, s, r); + if(r == '\'') + FMTRUNE(f, t, s, r); + } + } + + if(f->runes){ + FMTRCHAR(f, rt, rs, '\''); + USED(rs); + f->nfmt += rt - (Rune *)f->to; + f->to = rt; + if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0) + return -1; + }else{ + FMTRUNE(f, t, s, '\''); + USED(s); + f->nfmt += t - (char *)f->to; + f->to = t; + if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0) + return -1; + } + return 0; +} + +int +__quotestrfmt(int runesin, Fmt *f) +{ + int nin, outlen; + Rune *r; + char *s; + Quoteinfo q; + + nin = -1; + if(f->flags&FmtPrec) + nin = f->prec; + if(runesin){ + r = va_arg(f->args, Rune *); + s = nil; + }else{ + s = va_arg(f->args, char *); + r = nil; + } + if(!s && !r) + return __fmtcpy(f, (void*)"<nil>", 5, 5); + + if(f->flush) + outlen = 0x7FFFFFFF; /* if we can flush, no output limit */ + else if(f->runes) + outlen = (Rune*)f->stop - (Rune*)f->to; + else + outlen = (char*)f->stop - (char*)f->to; + + __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes); +//print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); + + if(runesin){ + if(!q.quoted) + return __fmtrcpy(f, r, q.nrunesin); + return qstrfmt(nil, r, &q, f); + } + + if(!q.quoted) + return __fmtcpy(f, s, q.nrunesin, q.nbytesin); + return qstrfmt(s, nil, &q, f); +} + +int +quotestrfmt(Fmt *f) +{ + return __quotestrfmt(0, f); +} + +int +quoterunestrfmt(Fmt *f) +{ + return __quotestrfmt(1, f); +} + +void +quotefmtinstall(void) +{ + fmtinstall('q', quotestrfmt); + fmtinstall('Q', quoterunestrfmt); +} + +int +__needsquotes(char *s, int *quotelenp) +{ + Quoteinfo q; + + __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0); + *quotelenp = q.nbytesout; + + return q.quoted; +} + +int +__runeneedsquotes(Rune *r, int *quotelenp) +{ + Quoteinfo q; + + __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0); + *quotelenp = q.nrunesout; + + return q.quoted; +} diff --git a/lib/libfmt/fmtrune.c b/lib/libfmt/fmtrune.c @@ -0,0 +1,40 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +fmtrune(Fmt *f, int r) +{ + Rune *rt; + char *t; + int n; + + if(f->runes){ + rt = (Rune*)f->to; + FMTRCHAR(f, rt, f->stop, r); + f->to = rt; + n = 1; + }else{ + t = (char*)f->to; + FMTRUNE(f, t, f->stop, r); + n = t - (char*)f->to; + f->to = t; + } + f->nfmt += n; + return 0; +} diff --git a/lib/libfmt/fmtstr.c b/lib/libfmt/fmtstr.c @@ -0,0 +1,27 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdlib.h> +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +char* +fmtstrflush(Fmt *f) +{ + if(f->start == nil) + return nil; + *(char*)f->to = '\0'; + return (char*)f->start; +} diff --git a/lib/libfmt/fmtvprint.c b/lib/libfmt/fmtvprint.c @@ -0,0 +1,49 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + + +/* + * format a string into the output buffer + * designed for formats which themselves call fmt, + * but ignore any width flags + */ +int +fmtvprint(Fmt *f, const char *fmt, va_list args) +{ + va_list va; + int n; + + f->flags = 0; + f->width = 0; + f->prec = 0; + va_copy(va,f->args); + va_end(f->args); + va_copy(f->args,args); + n = dofmt(f, fmt); + f->flags = 0; + f->width = 0; + f->prec = 0; + va_end(f->args); + va_copy(f->args,va); + va_end(va); + if(n >= 0) + return 0; + return n; +} + diff --git a/lib/libfmt/fprint.c b/lib/libfmt/fprint.c @@ -0,0 +1,29 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +fprint(int fd, const char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = vfprint(fd, fmt, args); + va_end(args); + return n; +} diff --git a/lib/libfmt/libfmt.a b/lib/libfmt/libfmt.a Binary files differ. diff --git a/lib/libfmt/nan64.c b/lib/libfmt/nan64.c @@ -0,0 +1,67 @@ +/* + * 64-bit IEEE not-a-number routines. + * This is big/little-endian portable assuming that + * the 64-bit doubles and 64-bit integers have the + * same byte ordering. + */ + +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +#if defined (__APPLE__) || (__powerpc__) +#define _NEEDLL +#endif + +static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001; +static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000; +static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000; + +double +__NaN(void) +{ + uvlong *p; + + /* gcc complains about "return *(double*)&uvnan;" */ + p = &uvnan; + return *(double*)p; +} + +int +__isNaN(double d) +{ + uvlong x; + double *p; + + p = &d; + x = *(uvlong*)p; + return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0); +} + +double +__Inf(int sign) +{ + uvlong *p; + + if(sign < 0) + p = &uvinf; + else + p = &uvneginf; + return *(double*)p; +} + +int +__isInf(double d, int sign) +{ + uvlong x; + double *p; + + p = &d; + x = *(uvlong*)p; + if(sign == 0) + return x==uvinf || x==uvneginf; + else if(sign > 0) + return x==uvinf; + else + return x==uvneginf; +} diff --git a/lib/libfmt/pow10.c b/lib/libfmt/pow10.c @@ -0,0 +1,57 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +/* + * this table might overflow 127-bit exponent representations. + * in that case, truncate it after 1.0e38. + * it is important to get all one can from this + * routine since it is used in atof to scale numbers. + * the presumption is that C converts fp numbers better + * than multipication of lower powers of 10. + */ + +static +double tab[] = +{ + 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, + 1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19, + 1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29, + 1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39, + 1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49, + 1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59, + 1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69, +}; + +double +__fmtpow10(int n) +{ + int m; + + if(n < 0) { + n = -n; + if(n < (int)(sizeof(tab)/sizeof(tab[0]))) + return 1/tab[n]; + m = n/2; + return __fmtpow10(-m) * __fmtpow10(m-n); + } + if(n < (int)(sizeof(tab)/sizeof(tab[0]))) + return tab[n]; + m = n/2; + return __fmtpow10(m) * __fmtpow10(n-m); +} diff --git a/lib/libfmt/print.3 b/lib/libfmt/print.3 @@ -0,0 +1,482 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.\" diffs from /usr/local/plan9/man/man3/print.3: +.\" +.\" - include different headers +.\" - drop reference to bio(3) +.\" - change exits to exit +.\" - text about unsigned verbs +.\" - source pointer +.\" +.TH PRINT 3 +.SH NAME +print, fprint, sprint, snprint, seprint, smprint, runesprint, runesnprint, runeseprint, runesmprint, vfprint, vsnprint, vseprint, vsmprint, runevsnprint, runevseprint, runevsmprint \- print formatted output +.SH SYNOPSIS +.B #include <utf.h> +.PP +.B #include <fmt.h> +.PP +.ta \w'\fLchar* 'u +.B +int print(char *format, ...) +.PP +.B +int fprint(int fd, char *format, ...) +.PP +.B +int sprint(char *s, char *format, ...) +.PP +.B +int snprint(char *s, int len, char *format, ...) +.PP +.B +char* seprint(char *s, char *e, char *format, ...) +.PP +.B +char* smprint(char *format, ...) +.PP +.B +int runesprint(Rune *s, char *format, ...) +.PP +.B +int runesnprint(Rune *s, int len, char *format, ...) +.PP +.B +Rune* runeseprint(Rune *s, Rune *e, char *format, ...) +.PP +.B +Rune* runesmprint(char *format, ...) +.PP +.B +int vfprint(int fd, char *format, va_list v) +.PP +.B +int vsnprint(char *s, int len, char *format, va_list v) +.PP +.B +char* vseprint(char *s, char *e, char *format, va_list v) +.PP +.B +char* vsmprint(char *format, va_list v) +.PP +.B +int runevsnprint(Rune *s, int len, char *format, va_list v) +.PP +.B +Rune* runevseprint(Rune *s, Rune *e, char *format, va_list v) +.PP +.B +Rune* runevsmprint(Rune *format, va_list v) +.PP +.B +.SH DESCRIPTION +.I Print +writes text to the standard output. +.I Fprint +writes to the named output +file descriptor: +a buffered form +is described in +.IR bio (3). +.I Sprint +places text +followed by the NUL character +.RB ( \e0 ) +in consecutive bytes starting at +.IR s ; +it is the user's responsibility to ensure that +enough storage is available. +Each function returns the number of bytes +transmitted (not including the NUL +in the case of +.IR sprint ), +or +a negative value if an output error was encountered. +.PP +.I Snprint +is like +.IR sprint , +but will not place more than +.I len +bytes in +.IR s . +Its result is always NUL-terminated and holds the maximal +number of complete UTF-8 characters that can fit. +.I Seprint +is like +.IR snprint , +except that the end is indicated by a pointer +.I e +rather than a count and the return value points to the terminating NUL of the +resulting string. +.I Smprint +is like +.IR sprint , +except that it prints into and returns a string of the required length, which is +allocated by +.IR malloc (3). +.PP +The routines +.IR runesprint , +.IR runesnprint , +.IR runeseprint , +and +.I runesmprint +are the same as +.IR sprint , +.IR snprint , +.IR seprint +and +.I smprint +except that their output is rune strings instead of byte strings. +.PP +Finally, the routines +.IR vfprint , +.IR vsnprint , +.IR vseprint , +.IR vsmprint , +.IR runevsnprint , +.IR runevseprint , +and +.I runevsmprint +are like their +.BR v-less +relatives except they take as arguments a +.B va_list +parameter, so they can be called within a variadic function. +The Example section shows a representative usage. +.PP +Each of these functions +converts, formats, and prints its +trailing arguments +under control of a +.IR format +string. +The +format +contains two types of objects: +plain characters, which are simply copied to the +output stream, +and conversion specifications, +each of which results in fetching of +zero or more +arguments. +The results are undefined if there are arguments of the +wrong type or too few +arguments for the format. +If the format is exhausted while +arguments remain, the excess +is ignored. +.PP +Each conversion specification has the following format: +.IP +.B "% [flags] verb +.PP +The verb is a single character and each flag is a single character or a +(decimal) numeric string. +Up to two numeric strings may be used; +the first is called +.IR width , +the second +.IR precision . +A period can be used to separate them, and if the period is +present then +.I width +and +.I precision +are taken to be zero if missing, otherwise they are `omitted'. +Either or both of the numbers may be replaced with the character +.BR * , +meaning that the actual number will be obtained from the argument list +as an integer. +The flags and numbers are arguments to +the +.I verb +described below. +.PP +The numeric verbs +.BR d , +.BR i , +.BR u , +.BR o , +.BR b , +.BR x , +and +.B X +format their arguments in decimal, decimal, +unsigned decimal, octal, binary, hexadecimal, and upper case hexadecimal. +Each interprets the flags +.BR 0 , +.BR h , +.BR hh , +.BR l , +.BR + , +.BR - , +.BR , , +and +.B # +to mean pad with zeros, +short, byte, long, always print a sign, left justified, commas every three digits, +and alternate format. +Also, a space character in the flag +position is like +.BR + , +but prints a space instead of a plus sign for non-negative values. +If neither +short nor long is specified, +then the argument is an +.BR int . +If an unsigned verb is specified, +then the argument is interpreted as a +positive number and no sign is output; +space and +.B + +flags are ignored for unsigned verbs. +If two +.B l +flags are given, +then the argument is interpreted as a +.B vlong +(usually an 8-byte, sometimes a 4-byte integer). +If +.I precision +is not omitted, the number is padded on the left with zeros +until at least +.I precision +digits appear. +If +.I precision +is explicitly 0, and the number is 0, +no digits are generated, and alternate formatting +does not apply. +Then, if alternate format is specified, +for +.B o +conversion, the number is preceded by a +.B 0 +if it doesn't already begin with one. +For non-zero numbers and +.B x +conversion, the number is preceded by +.BR 0x ; +for +.B X +conversion, the number is preceded by +.BR 0X . +Finally, if +.I width +is not omitted, the number is padded on the left (or right, if +left justification is specified) with enough blanks to +make the field at least +.I width +characters long. +.PP +The floating point verbs +.BR f , +.BR e , +.BR E , +.BR g , +and +.B G +take a +.B double +argument. +Each interprets the flags +.BR 0 , +.BR L +.BR + , +.BR - , +and +.B # +to mean pad with zeros, +long double argument, +always print a sign, +left justified, +and +alternate format. +.I Width +is the minimum field width and, +if the converted value takes up less than +.I width +characters, it is padded on the left (or right, if `left justified') +with spaces. +.I Precision +is the number of digits that are converted after the decimal place for +.BR e , +.BR E , +and +.B f +conversions, +and +.I precision +is the maximum number of significant digits for +.B g +and +.B G +conversions. +The +.B f +verb produces output of the form +.RB [ - ] digits [ .digits\fR]. +.B E +conversion appends an exponent +.BR E [ - ] digits , +and +.B e +conversion appends an exponent +.BR e [ - ] digits . +The +.B g +verb will output the argument in either +.B e +or +.B f +with the goal of producing the smallest output. +Also, trailing zeros are omitted from the fraction part of +the output, and a trailing decimal point appears only if it is followed +by a digit. +The +.B G +verb is similar, but uses +.B E +format instead of +.BR e . +When alternate format is specified, the result will always contain a decimal point, +and for +.B g +and +.B G +conversions, trailing zeros are not removed. +.PP +The +.B s +verb copies a string +(pointer to +.BR char ) +to the output. +The number of characters copied +.RI ( n ) +is the minimum +of the size of the string and +.IR precision . +These +.I n +characters are justified within a field of +.I width +characters as described above. +If a +.I precision +is given, it is safe for the string not to be nul-terminated +as long as it is at least +.I precision +characters (not bytes!) long. +The +.B S +verb is similar, but it interprets its pointer as an array +of runes (see +.IR utf (7)); +the runes are converted to +.SM UTF +before output. +.PP +The +.B c +verb copies a single +.B char +(promoted to +.BR int ) +justified within a field of +.I width +characters as described above. +The +.B C +verb is similar, but works on runes. +.PP +The +.B p +verb formats a pointer value. +At the moment, it is a synonym for +.BR x , +but that will change if pointers and integers are different sizes. +.PP +The +.B r +verb takes no arguments; it copies the error string returned by a call to +.IR strerror (3) +with an argument of +.IR errno. +.PP +Custom verbs may be installed using +.IR fmtinstall (3). +.SH EXAMPLE +This function prints an error message with a variable +number of arguments and then quits. +.IP +.EX +.ta 6n +6n +6n +void fatal(char *msg, ...) +{ + char buf[1024], *out; + va_list arg; + + out = seprint(buf, buf+sizeof buf, "Fatal error: "); + va_start(arg, msg); + out = vseprint(out, buf+sizeof buf, msg, arg); + va_end(arg); + write(2, buf, out-buf); + exit(1); +} +.EE +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH SEE ALSO +.IR fmtinstall (3), +.IR fprintf (3), +.IR utf (7) +.SH DIAGNOSTICS +Routines that write to a file descriptor or call +.IR malloc +set +.IR errstr . +.SH BUGS +The formatting is close to that specified for ANSI +.IR fprintf (3); +the main difference is that +.B b +and +.B r +are not in ANSI and some +.B C9X +verbs and syntax are missing. +Also, and distinctly not a bug, +.I print +and friends generate +.SM UTF +rather than +.SM ASCII. +.PP +There is no +.IR runeprint , +.IR runefprint , +etc. because runes are byte-order dependent and should not be written directly to a file; use the +UTF output of +.I print +or +.I fprint +instead. +Also, +.I sprint +is deprecated for safety reasons; use +.IR snprint , +.IR seprint , +or +.I smprint +instead. +Safety also precludes the existence of +.IR runesprint . diff --git a/lib/libfmt/print.c b/lib/libfmt/print.c @@ -0,0 +1,29 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +print(const char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = vfprint(1, fmt, args); + va_end(args); + return n; +} diff --git a/lib/libfmt/runefmtstr.c b/lib/libfmt/runefmtstr.c @@ -0,0 +1,27 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <stdlib.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +Rune* +runefmtstrflush(Fmt *f) +{ + if(f->start == nil) + return nil; + *(Rune*)f->to = '\0'; + return f->start; +} diff --git a/lib/libfmt/runeseprint.c b/lib/libfmt/runeseprint.c @@ -0,0 +1,30 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +Rune* +runeseprint(Rune *buf, Rune *e, const char *fmt, ...) +{ + Rune *p; + va_list args; + + va_start(args, fmt); + p = runevseprint(buf, e, fmt, args); + va_end(args); + return p; +} diff --git a/lib/libfmt/runesmprint.c b/lib/libfmt/runesmprint.c @@ -0,0 +1,30 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +Rune* +runesmprint(const char *fmt, ...) +{ + va_list args; + Rune *p; + + va_start(args, fmt); + p = runevsmprint(fmt, args); + va_end(args); + return p; +} diff --git a/lib/libfmt/runesnprint.c b/lib/libfmt/runesnprint.c @@ -0,0 +1,31 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +runesnprint(Rune *buf, int len, const char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = runevsnprint(buf, len, fmt, args); + va_end(args); + return n; +} + diff --git a/lib/libfmt/runesprint.c b/lib/libfmt/runesprint.c @@ -0,0 +1,30 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +runesprint(Rune *buf, const char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = runevsnprint(buf, 256, fmt, args); + va_end(args); + return n; +} diff --git a/lib/libfmt/runevseprint.c b/lib/libfmt/runevseprint.c @@ -0,0 +1,40 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +Rune* +runevseprint(Rune *buf, Rune *e, const char *fmt, va_list args) +{ + Fmt f; + + if(e <= buf) + return nil; + f.runes = 1; + f.start = buf; + f.to = buf; + f.stop = e - 1; + f.flush = nil; + f.farg = nil; + f.nfmt = 0; + va_copy(f.args,args); + dofmt(&f, fmt); + va_end(f.args); + *(Rune*)f.to = '\0'; + return (Rune*)f.to; +} + diff --git a/lib/libfmt/runevsmprint.c b/lib/libfmt/runevsmprint.c @@ -0,0 +1,91 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +/* + * Plan 9 port version must include libc.h in order to + * get Plan 9 debugging malloc, which sometimes returns + * different pointers than the standard malloc. + */ +#include <stdlib.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +static int +runeFmtStrFlush(Fmt *f) +{ + Rune *s; + int n; + + if(f->start == nil) + return 0; + n = (uintptr_t)f->farg; + n *= 2; + s = (Rune*)f->start; + f->start = realloc(s, sizeof(Rune)*n); + if(f->start == nil){ + f->farg = nil; + f->to = nil; + f->stop = nil; + free(s); + return 0; + } + f->farg = (void*)(uintptr_t)n; + f->to = (Rune*)f->start + ((Rune*)f->to - s); + f->stop = (Rune*)f->start + n - 1; + return 1; +} + +int +runefmtstrinit(Fmt *f) +{ + int n; + + memset(f, 0, sizeof *f); + f->runes = 1; + n = 32; + f->start = malloc(sizeof(Rune)*n); + if(f->start == nil) + return -1; + f->to = f->start; + f->stop = (Rune*)f->start + n - 1; + f->flush = runeFmtStrFlush; + f->farg = (void*)(uintptr_t)n; + f->nfmt = 0; + return 0; +} + +/* + * print into an allocated string buffer + */ +Rune* +runevsmprint(const char *fmt, va_list args) +{ + Fmt f; + int n; + + if(runefmtstrinit(&f) < 0) + return nil; + va_copy(f.args,args); + n = dofmt(&f, fmt); + va_end(f.args); + if(f.start == nil) + return nil; + if(n < 0){ + free(f.start); + return nil; + } + *(Rune*)f.to = '\0'; + return (Rune*)f.start; +} diff --git a/lib/libfmt/runevsnprint.c b/lib/libfmt/runevsnprint.c @@ -0,0 +1,39 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +runevsnprint(Rune *buf, int len, const char *fmt, va_list args) +{ + Fmt f; + + if(len <= 0) + return -1; + f.runes = 1; + f.start = buf; + f.to = buf; + f.stop = buf + len - 1; + f.flush = nil; + f.farg = nil; + f.nfmt = 0; + va_copy(f.args,args); + dofmt(&f, fmt); + va_end(f.args); + *(Rune*)f.to = '\0'; + return (Rune*)f.to - buf; +} diff --git a/lib/libfmt/seprint.c b/lib/libfmt/seprint.c @@ -0,0 +1,29 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +char* +seprint(char *buf, char *e, const char *fmt, ...) +{ + char *p; + va_list args; + + va_start(args, fmt); + p = vseprint(buf, e, fmt, args); + va_end(args); + return p; +} diff --git a/lib/libfmt/smprint.c b/lib/libfmt/smprint.c @@ -0,0 +1,29 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +char* +smprint(const char *fmt, ...) +{ + va_list args; + char *p; + + va_start(args, fmt); + p = vsmprint(fmt, args); + va_end(args); + return p; +} diff --git a/lib/libfmt/snprint.c b/lib/libfmt/snprint.c @@ -0,0 +1,30 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +snprint(char *buf, int len, const char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = vsnprint(buf, len, fmt, args); + va_end(args); + return n; +} + diff --git a/lib/libfmt/sprint.c b/lib/libfmt/sprint.c @@ -0,0 +1,37 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmtdef.h" + +int +sprint(char *buf, const char *fmt, ...) +{ + int n; + uint len; + va_list args; + + len = 1<<30; /* big number, but sprint is deprecated anyway */ + /* + * on PowerPC, the stack is near the top of memory, so + * we must be sure not to overflow a 32-bit pointer. + */ + if(buf+len < buf) + len = -(uintptr_t)buf-1; + + va_start(args, fmt); + n = vsnprint(buf, len, fmt, args); + va_end(args); + return n; +} diff --git a/lib/libfmt/strtod.c b/lib/libfmt/strtod.c @@ -0,0 +1,532 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdlib.h> +#include <math.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +static ulong +umuldiv(ulong a, ulong b, ulong c) +{ + double d; + + d = ((double)a * (double)b) / (double)c; + if(d >= 4294967295.) + d = 4294967295.; + return (ulong)d; +} + +/* + * This routine will convert to arbitrary precision + * floating point entirely in multi-precision fixed. + * The answer is the closest floating point number to + * the given decimal number. Exactly half way are + * rounded ala ieee rules. + * Method is to scale input decimal between .500 and .999... + * with external power of 2, then binary search for the + * closest mantissa to this decimal number. + * Nmant is is the required precision. (53 for ieee dp) + * Nbits is the max number of bits/word. (must be <= 28) + * Prec is calculated - the number of words of fixed mantissa. + */ +enum +{ + Nbits = 28, /* bits safely represented in a ulong */ + Nmant = 53, /* bits of precision required */ + Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */ + Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */ + Ndig = 1500, + One = (ulong)(1<<Nbits), + Half = (ulong)(One>>1), + Maxe = 310, + + Fsign = 1<<0, /* found - */ + Fesign = 1<<1, /* found e- */ + Fdpoint = 1<<2, /* found . */ + + S0 = 0, /* _ _S0 +S1 #S2 .S3 */ + S1, /* _+ #S2 .S3 */ + S2, /* _+# #S2 .S4 eS5 */ + S3, /* _+. #S4 */ + S4, /* _+#.# #S4 eS5 */ + S5, /* _+#.#e +S6 #S7 */ + S6, /* _+#.#e+ #S7 */ + S7, /* _+#.#e+# #S7 */ +}; + +static int xcmp(char*, char*); +static int fpcmp(char*, ulong*); +static void frnorm(ulong*); +static void divascii(char*, int*, int*, int*); +static void mulascii(char*, int*, int*, int*); + +typedef struct Tab Tab; +struct Tab +{ + int bp; + int siz; + char* cmp; +}; + +double +fmtstrtod(const char *as, char **aas) +{ + int na, ex, dp, bp, c, i, flag, state; + ulong low[Prec], hig[Prec], mid[Prec]; + double d; + char *s, a[Ndig]; + + flag = 0; /* Fsign, Fesign, Fdpoint */ + na = 0; /* number of digits of a[] */ + dp = 0; /* na of decimal point */ + ex = 0; /* exonent */ + + state = S0; + for(s=(char*)as;; s++) { + c = *s; + if(c >= '0' && c <= '9') { + switch(state) { + case S0: + case S1: + case S2: + state = S2; + break; + case S3: + case S4: + state = S4; + break; + + case S5: + case S6: + case S7: + state = S7; + ex = ex*10 + (c-'0'); + continue; + } + if(na == 0 && c == '0') { + dp--; + continue; + } + if(na < Ndig-50) + a[na++] = c; + continue; + } + switch(c) { + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + if(state == S0) + continue; + break; + case '-': + if(state == S0) + flag |= Fsign; + else + flag |= Fesign; + case '+': + if(state == S0) + state = S1; + else + if(state == S5) + state = S6; + else + break; /* syntax */ + continue; + case '.': + flag |= Fdpoint; + dp = na; + if(state == S0 || state == S1) { + state = S3; + continue; + } + if(state == S2) { + state = S4; + continue; + } + break; + case 'e': + case 'E': + if(state == S2 || state == S4) { + state = S5; + continue; + } + break; + } + break; + } + + /* + * clean up return char-pointer + */ + switch(state) { + case S0: + if(xcmp(s, "nan") == 0) { + if(aas != nil) + *aas = s+3; + goto retnan; + } + case S1: + if(xcmp(s, "infinity") == 0) { + if(aas != nil) + *aas = s+8; + goto retinf; + } + if(xcmp(s, "inf") == 0) { + if(aas != nil) + *aas = s+3; + goto retinf; + } + case S3: + if(aas != nil) + *aas = (char*)as; + goto ret0; /* no digits found */ + case S6: + s--; /* back over +- */ + case S5: + s--; /* back over e */ + break; + } + if(aas != nil) + *aas = s; + + if(flag & Fdpoint) + while(na > 0 && a[na-1] == '0') + na--; + if(na == 0) + goto ret0; /* zero */ + a[na] = 0; + if(!(flag & Fdpoint)) + dp = na; + if(flag & Fesign) + ex = -ex; + dp += ex; + if(dp < -Maxe){ + errno = ERANGE; + goto ret0; /* underflow by exp */ + } else + if(dp > +Maxe) + goto retinf; /* overflow by exp */ + + /* + * normalize the decimal ascii number + * to range .[5-9][0-9]* e0 + */ + bp = 0; /* binary exponent */ + while(dp > 0) + divascii(a, &na, &dp, &bp); + while(dp < 0 || a[0] < '5') + mulascii(a, &na, &dp, &bp); + + /* close approx by naive conversion */ + mid[0] = 0; + mid[1] = 1; + for(i=0; c=a[i]; i++) { + mid[0] = mid[0]*10 + (c-'0'); + mid[1] = mid[1]*10; + if(i >= 8) + break; + } + low[0] = umuldiv(mid[0], One, mid[1]); + hig[0] = umuldiv(mid[0]+1, One, mid[1]); + for(i=1; i<Prec; i++) { + low[i] = 0; + hig[i] = One-1; + } + + /* binary search for closest mantissa */ + for(;;) { + /* mid = (hig + low) / 2 */ + c = 0; + for(i=0; i<Prec; i++) { + mid[i] = hig[i] + low[i]; + if(c) + mid[i] += One; + c = mid[i] & 1; + mid[i] >>= 1; + } + frnorm(mid); + + /* compare */ + c = fpcmp(a, mid); + if(c > 0) { + c = 1; + for(i=0; i<Prec; i++) + if(low[i] != mid[i]) { + c = 0; + low[i] = mid[i]; + } + if(c) + break; /* between mid and hig */ + continue; + } + if(c < 0) { + for(i=0; i<Prec; i++) + hig[i] = mid[i]; + continue; + } + + /* only hard part is if even/odd roundings wants to go up */ + c = mid[Prec-1] & (Sigbit-1); + if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0) + mid[Prec-1] -= c; + break; /* exactly mid */ + } + + /* normal rounding applies */ + c = mid[Prec-1] & (Sigbit-1); + mid[Prec-1] -= c; + if(c >= Sigbit/2) { + mid[Prec-1] += Sigbit; + frnorm(mid); + } + goto out; + +ret0: + return 0; + +retnan: + return __NaN(); + +retinf: + /* + * Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */ + errno = ERANGE; + if(flag & Fsign) + return -HUGE_VAL; + return HUGE_VAL; + +out: + d = 0; + for(i=0; i<Prec; i++) + d = d*One + mid[i]; + if(flag & Fsign) + d = -d; + d = ldexp(d, bp - Prec*Nbits); + if(d == 0){ /* underflow */ + errno = ERANGE; + } + return d; +} + +static void +frnorm(ulong *f) +{ + int i, c; + + c = 0; + for(i=Prec-1; i>0; i--) { + f[i] += c; + c = f[i] >> Nbits; + f[i] &= One-1; + } + f[0] += c; +} + +static int +fpcmp(char *a, ulong* f) +{ + ulong tf[Prec]; + int i, d, c; + + for(i=0; i<Prec; i++) + tf[i] = f[i]; + + for(;;) { + /* tf *= 10 */ + for(i=0; i<Prec; i++) + tf[i] = tf[i]*10; + frnorm(tf); + d = (tf[0] >> Nbits) + '0'; + tf[0] &= One-1; + + /* compare next digit */ + c = *a; + if(c == 0) { + if('0' < d) + return -1; + if(tf[0] != 0) + goto cont; + for(i=1; i<Prec; i++) + if(tf[i] != 0) + goto cont; + return 0; + } + if(c > d) + return +1; + if(c < d) + return -1; + a++; + cont:; + } +} + +static void +divby(char *a, int *na, int b) +{ + int n, c; + char *p; + + p = a; + n = 0; + while(n>>b == 0) { + c = *a++; + if(c == 0) { + while(n) { + c = n*10; + if(c>>b) + break; + n = c; + } + goto xx; + } + n = n*10 + c-'0'; + (*na)--; + } + for(;;) { + c = n>>b; + n -= c<<b; + *p++ = c + '0'; + c = *a++; + if(c == 0) + break; + n = n*10 + c-'0'; + } + (*na)++; +xx: + while(n) { + n = n*10; + c = n>>b; + n -= c<<b; + *p++ = c + '0'; + (*na)++; + } + *p = 0; +} + +static Tab tab1[] = +{ + 1, 0, "", + 3, 1, "7", + 6, 2, "63", + 9, 3, "511", + 13, 4, "8191", + 16, 5, "65535", + 19, 6, "524287", + 23, 7, "8388607", + 26, 8, "67108863", + 27, 9, "134217727", +}; + +static void +divascii(char *a, int *na, int *dp, int *bp) +{ + int b, d; + Tab *t; + + d = *dp; + if(d >= (int)(nelem(tab1))) + d = (int)(nelem(tab1))-1; + t = tab1 + d; + b = t->bp; + if(memcmp(a, t->cmp, t->siz) > 0) + d--; + *dp -= d; + *bp += b; + divby(a, na, b); +} + +static void +mulby(char *a, char *p, char *q, int b) +{ + int n, c; + + n = 0; + *p = 0; + for(;;) { + q--; + if(q < a) + break; + c = *q - '0'; + c = (c<<b) + n; + n = c/10; + c -= n*10; + p--; + *p = c + '0'; + } + while(n) { + c = n; + n = c/10; + c -= n*10; + p--; + *p = c + '0'; + } +} + +static Tab tab2[] = +{ + 1, 1, "", /* dp = 0-0 */ + 3, 3, "125", + 6, 5, "15625", + 9, 7, "1953125", + 13, 10, "1220703125", + 16, 12, "152587890625", + 19, 14, "19073486328125", + 23, 17, "11920928955078125", + 26, 19, "1490116119384765625", + 27, 19, "7450580596923828125", /* dp 8-9 */ +}; + +static void +mulascii(char *a, int *na, int *dp, int *bp) +{ + char *p; + int d, b; + Tab *t; + + d = -*dp; + if(d >= (int)(nelem(tab2))) + d = (int)(nelem(tab2))-1; + t = tab2 + d; + b = t->bp; + if(memcmp(a, t->cmp, t->siz) < 0) + d--; + p = a + *na; + *bp -= b; + *dp += d; + *na += d; + mulby(a, p+d, p, b); +} + +static int +xcmp(char *a, char *b) +{ + int c1, c2; + + while(c1 = *b++) { + c2 = *a++; + if(isupper(c2)) + c2 = tolower(c2); + if(c1 != c2) + return 1; + } + return 0; +} diff --git a/lib/libfmt/test.c b/lib/libfmt/test.c @@ -0,0 +1,44 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdio.h> +#include <stdarg.h> +#include <utf.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +main(int argc, char *argv[]) +{ + quotefmtinstall(); + print("hello world\n"); + print("x: %x\n", 0x87654321); + print("u: %u\n", 0x87654321); + print("d: %d\n", 0x87654321); + print("s: %s\n", "hi there"); + print("q: %q\n", "hi i'm here"); + print("c: %c\n", '!'); + print("g: %g %g %g\n", 3.14159, 3.14159e10, 3.14159e-10); + print("e: %e %e %e\n", 3.14159, 3.14159e10, 3.14159e-10); + print("f: %f %f %f\n", 3.14159, 3.14159e10, 3.14159e-10); + print("smiley: %C\n", (Rune)0x263a); + print("%g %.18g\n", 2e25, 2e25); + print("%2.18g\n", 1.0); + print("%2.18f\n", 1.0); + print("%f\n", 3.1415927/4); + print("%d\n", 23); + print("%i\n", 23); + print("%0.10d\n", 12345); + return 0; +} diff --git a/lib/libfmt/test2.c b/lib/libfmt/test2.c @@ -0,0 +1,9 @@ +#include <stdarg.h> +#include <utf.h> +#include <fmt.h> + +int +main(int argc, char **argv) +{ + print("%020.10d\n", 100); +} diff --git a/lib/libfmt/test3.c b/lib/libfmt/test3.c @@ -0,0 +1,52 @@ +#include <u.h> +#include <libc.h> +#include <stdio.h> + +void +test(char *fmt, ...) +{ + va_list arg; + char fmtbuf[100], stdbuf[100]; + + va_start(arg, fmt); + vsnprint(fmtbuf, sizeof fmtbuf, fmt, arg); + va_end(arg); + + va_start(arg, fmt); + vsnprint(stdbuf, sizeof stdbuf, fmt, arg); + va_end(arg); + + if(strcmp(fmtbuf, stdbuf) != 0) + print("fmt %s: fmt=\"%s\" std=\"%s\"\n", fmt, fmtbuf, stdbuf); + + print("fmt %s: %s\n", fmt, fmtbuf); +} + + +int +main(int argc, char *argv[]) +{ + test("%f", 3.14159); + test("%f", 3.14159e10); + test("%f", 3.14159e-10); + + test("%e", 3.14159); + test("%e", 3.14159e10); + test("%e", 3.14159e-10); + + test("%g", 3.14159); + test("%g", 3.14159e10); + test("%g", 3.14159e-10); + + test("%g", 2e25); + test("%.18g", 2e25); + + test("%2.18g", 1.0); + test("%2.18f", 1.0); + test("%f", 3.1415927/4); + + test("%20.10d", 12345); + test("%0.10d", 12345); + + return 0; +} diff --git a/lib/libfmt/vfprint.c b/lib/libfmt/vfprint.c @@ -0,0 +1,33 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +vfprint(int fd, const char *fmt, va_list args) +{ + Fmt f; + char buf[256]; + int n; + + fmtfdinit(&f, fd, buf, sizeof(buf)); + va_copy(f.args,args); + n = dofmt(&f, fmt); + va_end(f.args); + if(n > 0 && __fmtFdFlush(&f) == 0) + return -1; + return n; +} diff --git a/lib/libfmt/vseprint.c b/lib/libfmt/vseprint.c @@ -0,0 +1,39 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +char* +vseprint(char *buf, char *e, const char *fmt, va_list args) +{ + Fmt f; + + if(e <= buf) + return nil; + f.runes = 0; + f.start = buf; + f.to = buf; + f.stop = e - 1; + f.flush = 0; + f.farg = nil; + f.nfmt = 0; + va_copy(f.args,args); + dofmt(&f, fmt); + va_end(f.args); + *(char*)f.to = '\0'; + return (char*)f.to; +} + diff --git a/lib/libfmt/vsmprint.c b/lib/libfmt/vsmprint.c @@ -0,0 +1,88 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +/* + * Plan 9 port version must include libc.h in order to + * get Plan 9 debugging malloc, which sometimes returns + * different pointers than the standard malloc. + */ +#include <stdlib.h> +#include <string.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +static int +fmtStrFlush(Fmt *f) +{ + char *s; + int n; + + if(f->start == nil) + return 0; + n = (uintptr_t)f->farg; + n *= 2; + s = (char*)f->start; + f->start = realloc(s, n); + if(f->start == nil){ + f->farg = nil; + f->to = nil; + f->stop = nil; + free(s); + return 0; + } + f->farg = (void*)(uintptr_t)n; + f->to = (char*)f->start + ((char*)f->to - s); + f->stop = (char*)f->start + n - 1; + return 1; +} + +int +fmtstrinit(Fmt *f) +{ + int n; + + memset(f, 0, sizeof *f); + f->runes = 0; + n = 32; + f->start = malloc(n); + if(f->start == nil) + return -1; + f->to = f->start; + f->stop = (char*)f->start + n - 1; + f->flush = fmtStrFlush; + f->farg = (void*)(uintptr_t)n; + f->nfmt = 0; + return 0; +} + +/* + * print into an allocated string buffer + */ +char* +vsmprint(const char *fmt, va_list args) +{ + Fmt f; + int n; + + if(fmtstrinit(&f) < 0) + return nil; + va_copy(f.args,args); + n = dofmt(&f, fmt); + va_end(f.args); + if(n < 0){ + free(f.start); + return nil; + } + return fmtstrflush(&f); +} diff --git a/lib/libfmt/vsnprint.c b/lib/libfmt/vsnprint.c @@ -0,0 +1,39 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdlib.h> +#include <stdarg.h> +#include "plan9.h" +#include "fmt.h" +#include "fmtdef.h" + +int +vsnprint(char *buf, int len, const char *fmt, va_list args) +{ + Fmt f; + + if(len <= 0) + return -1; + f.runes = 0; + f.start = buf; + f.to = buf; + f.stop = buf + len - 1; + f.flush = 0; + f.farg = nil; + f.nfmt = 0; + va_copy(f.args,args); + dofmt(&f, fmt); + va_end(f.args); + *(char*)f.to = '\0'; + return (char*)f.to - buf; +} diff --git a/lib/libregexp/Makefile b/lib/libregexp/Makefile @@ -0,0 +1,17 @@ +ROOT= ../.. +include $(ROOT)/mk/hdr.mk + +VERSION=2.0 +TARG=libregexp9 + +OBJ=\ + regcomp\ + regerror\ + regexec\ + regsub\ + regaux\ + rregexec\ + rregsub + +include $(ROOT)/mk/lib.mk + diff --git a/lib/libregexp/NOTICE b/lib/libregexp/NOTICE @@ -0,0 +1,25 @@ +/* + * The authors of this software is Rob Pike. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. +*/ + +This is a Unix port of the Plan 9 regular expression library. + +Please send comments about the packaging +to Russ Cox <rsc@swtch.com>. + + +---- + +This software is also made available under the Lucent Public License +version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html + diff --git a/lib/libregexp/README b/lib/libregexp/README @@ -0,0 +1,5 @@ +This software was packaged for Unix by Russ Cox. +Please send comments to rsc@swtch.com. + +http://swtch.com/plan9port/unix + diff --git a/lib/libregexp/regaux.c b/lib/libregexp/regaux.c @@ -0,0 +1,112 @@ +#include "plan9.h" +#include "regexp9.h" +#include "regcomp.h" + + +/* + * save a new match in mp + */ +extern void +_renewmatch(Resub *mp, int ms, Resublist *sp) +{ + int i; + + if(mp==0 || ms<=0) + return; + if(mp[0].s.sp==0 || sp->m[0].s.sp<mp[0].s.sp || + (sp->m[0].s.sp==mp[0].s.sp && sp->m[0].e.ep>mp[0].e.ep)){ + for(i=0; i<ms && i<NSUBEXP; i++) + mp[i] = sp->m[i]; + for(; i<ms; i++) + mp[i].s.sp = mp[i].e.ep = 0; + } +} + +/* + * Note optimization in _renewthread: + * *lp must be pending when _renewthread called; if *l has been looked + * at already, the optimization is a bug. + */ +extern Relist* +_renewthread(Relist *lp, /* _relist to add to */ + Reinst *ip, /* instruction to add */ + int ms, + Resublist *sep) /* pointers to subexpressions */ +{ + Relist *p; + + for(p=lp; p->inst; p++){ + if(p->inst == ip){ + if(sep->m[0].s.sp < p->se.m[0].s.sp){ + if(ms > 1) + p->se = *sep; + else + p->se.m[0] = sep->m[0]; + } + return 0; + } + } + p->inst = ip; + if(ms > 1) + p->se = *sep; + else + p->se.m[0] = sep->m[0]; + (++p)->inst = 0; + return p; +} + +/* + * same as renewthread, but called with + * initial empty start pointer. + */ +extern Relist* +_renewemptythread(Relist *lp, /* _relist to add to */ + Reinst *ip, /* instruction to add */ + int ms, + char *sp) /* pointers to subexpressions */ +{ + Relist *p; + + for(p=lp; p->inst; p++){ + if(p->inst == ip){ + if(sp < p->se.m[0].s.sp) { + if(ms > 1) + memset(&p->se, 0, sizeof(p->se)); + p->se.m[0].s.sp = sp; + } + return 0; + } + } + p->inst = ip; + if(ms > 1) + memset(&p->se, 0, sizeof(p->se)); + p->se.m[0].s.sp = sp; + (++p)->inst = 0; + return p; +} + +extern Relist* +_rrenewemptythread(Relist *lp, /* _relist to add to */ + Reinst *ip, /* instruction to add */ + int ms, + Rune *rsp) /* pointers to subexpressions */ +{ + Relist *p; + + for(p=lp; p->inst; p++){ + if(p->inst == ip){ + if(rsp < p->se.m[0].s.rsp) { + if(ms > 1) + memset(&p->se, 0, sizeof(p->se)); + p->se.m[0].s.rsp = rsp; + } + return 0; + } + } + p->inst = ip; + if(ms > 1) + memset(&p->se, 0, sizeof(p->se)); + p->se.m[0].s.rsp = rsp; + (++p)->inst = 0; + return p; +} diff --git a/lib/libregexp/regcomp.c b/lib/libregexp/regcomp.c @@ -0,0 +1,559 @@ +#include <setjmp.h> +#include <stdlib.h> +#include "plan9.h" +#include "regexp9.h" +#include "regcomp.h" + +enum { + FALSE, + TRUE, +}; + +/* + * Parser Information + */ +typedef struct Node Node; +struct Node +{ + Reinst* first; + Reinst* last; +}; + +#define NSTACK 20 +static Node andstack[NSTACK]; +static Node *andp; +static int atorstack[NSTACK]; +static int* atorp; +static int cursubid; /* id of current subexpression */ +static int subidstack[NSTACK]; /* parallel to atorstack */ +static int* subidp; +static int lastwasand; /* Last token was operand */ +static int nbra; +static char* exprp; /* pointer to next character in source expression */ +static int lexdone; +static int nclass; +static Reclass*classp; +static Reinst* freep; +static int errors; +static Rune yyrune; /* last lex'd rune */ +static Reclass*yyclassp; /* last lex'd class */ + +/* predeclared crap */ +static void operator(int); +static void pushand(Reinst*, Reinst*); +static void pushator(int); +static void evaluntil(int); +static int bldcclass(void); + +static jmp_buf regkaboom; + +static void +rcerror(char *s) +{ + errors++; + regerror(s); + longjmp(regkaboom, 1); +} + +static Reinst* +newinst(int t) +{ + freep->type = t; + freep->u2.left = 0; + freep->u1.right = 0; + return freep++; +} + +static void +operand(int t) +{ + Reinst *i; + + if(lastwasand) + operator(CAT); /* catenate is implicit */ + i = newinst(t); + + if(t == CCLASS || t == NCCLASS) + i->u1.cp = yyclassp; + if(t == RUNE) + i->u1.r = yyrune; + + pushand(i, i); + lastwasand = TRUE; +} + +static void +operator(int t) +{ + if(t==RBRA && --nbra<0) + rcerror("unmatched right paren"); + if(t==LBRA){ + if(++cursubid >= NSUBEXP) + rcerror ("too many subexpressions"); + nbra++; + if(lastwasand) + operator(CAT); + } else + evaluntil(t); + if(t != RBRA) + pushator(t); + lastwasand = FALSE; + if(t==STAR || t==QUEST || t==PLUS || t==RBRA) + lastwasand = TRUE; /* these look like operands */ +} + +static void +regerr2(char *s, int c) +{ + char buf[100]; + char *cp = buf; + while(*s) + *cp++ = *s++; + *cp++ = c; + *cp = '\0'; + rcerror(buf); +} + +static void +cant(char *s) +{ + char buf[100]; + strcpy(buf, "can't happen: "); + strcat(buf, s); + rcerror(buf); +} + +static void +pushand(Reinst *f, Reinst *l) +{ + if(andp >= &andstack[NSTACK]) + cant("operand stack overflow"); + andp->first = f; + andp->last = l; + andp++; +} + +static void +pushator(int t) +{ + if(atorp >= &atorstack[NSTACK]) + cant("operator stack overflow"); + *atorp++ = t; + *subidp++ = cursubid; +} + +static Node* +popand(int op) +{ + Reinst *inst; + + if(andp <= &andstack[0]){ + regerr2("missing operand for ", op); + inst = newinst(NOP); + pushand(inst,inst); + } + return --andp; +} + +static int +popator(void) +{ + if(atorp <= &atorstack[0]) + cant("operator stack underflow"); + --subidp; + return *--atorp; +} + +static void +evaluntil(int pri) +{ + Node *op1, *op2; + Reinst *inst1, *inst2; + + while(pri==RBRA || atorp[-1]>=pri){ + switch(popator()){ + default: + rcerror("unknown operator in evaluntil"); + break; + case LBRA: /* must have been RBRA */ + op1 = popand('('); + inst2 = newinst(RBRA); + inst2->u1.subid = *subidp; + op1->last->u2.next = inst2; + inst1 = newinst(LBRA); + inst1->u1.subid = *subidp; + inst1->u2.next = op1->first; + pushand(inst1, inst2); + return; + case OR: + op2 = popand('|'); + op1 = popand('|'); + inst2 = newinst(NOP); + op2->last->u2.next = inst2; + op1->last->u2.next = inst2; + inst1 = newinst(OR); + inst1->u1.right = op1->first; + inst1->u2.left = op2->first; + pushand(inst1, inst2); + break; + case CAT: + op2 = popand(0); + op1 = popand(0); + op1->last->u2.next = op2->first; + pushand(op1->first, op2->last); + break; + case STAR: + op2 = popand('*'); + inst1 = newinst(OR); + op2->last->u2.next = inst1; + inst1->u1.right = op2->first; + pushand(inst1, inst1); + break; + case PLUS: + op2 = popand('+'); + inst1 = newinst(OR); + op2->last->u2.next = inst1; + inst1->u1.right = op2->first; + pushand(op2->first, inst1); + break; + case QUEST: + op2 = popand('?'); + inst1 = newinst(OR); + inst2 = newinst(NOP); + inst1->u2.left = inst2; + inst1->u1.right = op2->first; + op2->last->u2.next = inst2; + pushand(inst1, inst2); + break; + } + } +} + +static Reprog* +optimize(Reprog *pp) +{ + Reinst *inst, *target; + int size; + Reprog *npp; + Reclass *cl; + int diff; + + /* + * get rid of NOOP chains + */ + for(inst=pp->firstinst; inst->type!=END; inst++){ + target = inst->u2.next; + while(target->type == NOP) + target = target->u2.next; + inst->u2.next = target; + } + + /* + * The original allocation is for an area larger than + * necessary. Reallocate to the actual space used + * and then relocate the code. + */ + size = sizeof(Reprog) + (freep - pp->firstinst)*sizeof(Reinst); + npp = realloc(pp, size); + if(npp==0 || npp==pp) + return pp; + diff = (char *)npp - (char *)pp; + freep = (Reinst *)((char *)freep + diff); + for(inst=npp->firstinst; inst<freep; inst++){ + switch(inst->type){ + case OR: + case STAR: + case PLUS: + case QUEST: + *(char **)&inst->u1.right += diff; + break; + case CCLASS: + case NCCLASS: + *(char **)&inst->u1.right += diff; + cl = inst->u1.cp; + *(char **)&cl->end += diff; + break; + } + *(char **)&inst->u2.left += diff; + } + *(char **)&npp->startinst += diff; + return npp; +} + +#ifdef DEBUG +static void +dumpstack(void){ + Node *stk; + int *ip; + + print("operators\n"); + for(ip=atorstack; ip<atorp; ip++) + print("0%o\n", *ip); + print("operands\n"); + for(stk=andstack; stk<andp; stk++) + print("0%o\t0%o\n", stk->first->type, stk->last->type); +} + +static void +dump(Reprog *pp) +{ + Reinst *l; + Rune *p; + + l = pp->firstinst; + do{ + print("%d:\t0%o\t%d\t%d", l-pp->firstinst, l->type, + l->u2.left-pp->firstinst, l->u1.right-pp->firstinst); + if(l->type == RUNE) + print("\t%C\n", l->u1.r); + else if(l->type == CCLASS || l->type == NCCLASS){ + print("\t["); + if(l->type == NCCLASS) + print("^"); + for(p = l->u1.cp->spans; p < l->u1.cp->end; p += 2) + if(p[0] == p[1]) + print("%C", p[0]); + else + print("%C-%C", p[0], p[1]); + print("]\n"); + } else + print("\n"); + }while(l++->type); +} +#endif + +static Reclass* +newclass(void) +{ + if(nclass >= NCLASS) + regerr2("too many character classes; limit", NCLASS+'0'); + return &(classp[nclass++]); +} + +static int +nextc(Rune *rp) +{ + if(lexdone){ + *rp = 0; + return 1; + } + exprp += chartorune(rp, exprp); + if(*rp == '\\'){ + exprp += chartorune(rp, exprp); + return 1; + } + if(*rp == 0) + lexdone = 1; + return 0; +} + +static int +lex(int literal, int dot_type) +{ + int quoted; + + quoted = nextc(&yyrune); + if(literal || quoted){ + if(yyrune == 0) + return END; + return RUNE; + } + + switch(yyrune){ + case 0: + return END; + case '*': + return STAR; + case '?': + return QUEST; + case '+': + return PLUS; + case '|': + return OR; + case '.': + return dot_type; + case '(': + return LBRA; + case ')': + return RBRA; + case '^': + return BOL; + case '$': + return EOL; + case '[': + return bldcclass(); + } + return RUNE; +} + +static int +bldcclass(void) +{ + int type; + Rune r[NCCRUNE]; + Rune *p, *ep, *np; + Rune rune; + int quoted; + + /* we have already seen the '[' */ + type = CCLASS; + yyclassp = newclass(); + + /* look ahead for negation */ + /* SPECIAL CASE!!! negated classes don't match \n */ + ep = r; + quoted = nextc(&rune); + if(!quoted && rune == '^'){ + type = NCCLASS; + quoted = nextc(&rune); + *ep++ = '\n'; + *ep++ = '\n'; + } + + /* parse class into a set of spans */ + for(; ep<&r[NCCRUNE];){ + if(rune == 0){ + rcerror("malformed '[]'"); + return 0; + } + if(!quoted && rune == ']') + break; + if(!quoted && rune == '-'){ + if(ep == r){ + rcerror("malformed '[]'"); + return 0; + } + quoted = nextc(&rune); + if((!quoted && rune == ']') || rune == 0){ + rcerror("malformed '[]'"); + return 0; + } + *(ep-1) = rune; + } else { + *ep++ = rune; + *ep++ = rune; + } + quoted = nextc(&rune); + } + + /* sort on span start */ + for(p = r; p < ep; p += 2){ + for(np = p; np < ep; np += 2) + if(*np < *p){ + rune = np[0]; + np[0] = p[0]; + p[0] = rune; + rune = np[1]; + np[1] = p[1]; + p[1] = rune; + } + } + + /* merge spans */ + np = yyclassp->spans; + p = r; + if(r == ep) + yyclassp->end = np; + else { + np[0] = *p++; + np[1] = *p++; + for(; p < ep; p += 2) + if(p[0] <= np[1]){ + if(p[1] > np[1]) + np[1] = p[1]; + } else { + np += 2; + np[0] = p[0]; + np[1] = p[1]; + } + yyclassp->end = np+2; + } + + return type; +} + +static Reprog* +regcomp1(char *s, int literal, int dot_type) +{ + int token; + Reprog *volatile pp; + + /* get memory for the program */ + pp = malloc(sizeof(Reprog) + 6*sizeof(Reinst)*strlen(s)); + if(pp == 0){ + regerror("out of memory"); + return 0; + } + freep = pp->firstinst; + classp = pp->class; + errors = 0; + + if(setjmp(regkaboom)) + goto out; + + /* go compile the sucker */ + lexdone = 0; + exprp = s; + nclass = 0; + nbra = 0; + atorp = atorstack; + andp = andstack; + subidp = subidstack; + lastwasand = FALSE; + cursubid = 0; + + /* Start with a low priority operator to prime parser */ + pushator(START-1); + while((token = lex(literal, dot_type)) != END){ + if((token&0300) == OPERATOR) + operator(token); + else + operand(token); + } + + /* Close with a low priority operator */ + evaluntil(START); + + /* Force END */ + operand(END); + evaluntil(START); +#ifdef DEBUG + dumpstack(); +#endif + if(nbra) + rcerror("unmatched left paren"); + --andp; /* points to first and only operand */ + pp->startinst = andp->first; +#ifdef DEBUG + dump(pp); +#endif + pp = optimize(pp); +#ifdef DEBUG + print("start: %d\n", andp->first-pp->firstinst); + dump(pp); +#endif +out: + if(errors){ + free(pp); + pp = 0; + } + return pp; +} + +extern Reprog* +regcomp(char *s) +{ + return regcomp1(s, 0, ANY); +} + +extern Reprog* +regcomplit(char *s) +{ + return regcomp1(s, 1, ANY); +} + +extern Reprog* +regcompnl(char *s) +{ + return regcomp1(s, 0, ANYNL); +} diff --git a/lib/libregexp/regerror.c b/lib/libregexp/regerror.c @@ -0,0 +1,15 @@ +#include <stdlib.h> +#include <plan9.h> +#include <regexp9.h> + +void +regerror(char *s) +{ + char buf[132]; + + strcpy(buf, "regerror: "); + strcat(buf, s); + strcat(buf, "\n"); + write(2, buf, strlen(buf)); + exits("regerr"); +} diff --git a/lib/libregexp/regexec.c b/lib/libregexp/regexec.c @@ -0,0 +1,232 @@ +#include <stdlib.h> +#include "plan9.h" +#include "regexp9.h" +#include "regcomp.h" + + +/* + * return 0 if no match + * >0 if a match + * <0 if we ran out of _relist space + */ +static int +regexec1(Reprog *progp, /* program to run */ + char *bol, /* string to run machine on */ + Resub *mp, /* subexpression elements */ + int ms, /* number of elements at mp */ + Reljunk *j +) +{ + int flag=0; + Reinst *inst; + Relist *tlp; + char *s; + int i, checkstart; + Rune r, *rp, *ep; + int n; + Relist* tl; /* This list, next list */ + Relist* nl; + Relist* tle; /* ends of this and next list */ + Relist* nle; + int match; + char *p; + + match = 0; + checkstart = j->starttype; + if(mp) + for(i=0; i<ms; i++) { + mp[i].s.sp = 0; + mp[i].e.ep = 0; + } + j->relist[0][0].inst = 0; + j->relist[1][0].inst = 0; + + /* Execute machine once for each character, including terminal NUL */ + s = j->starts; + do{ + /* fast check for first char */ + if(checkstart) { + switch(j->starttype) { + case RUNE: + p = utfrune(s, j->startchar); + if(p == 0 || s == j->eol) + return match; + s = p; + break; + case BOL: + if(s == bol) + break; + p = utfrune(s, '\n'); + if(p == 0 || s == j->eol) + return match; + s = p; + break; + } + } + r = *(uchar*)s; + if(r < Runeself) + n = 1; + else + n = chartorune(&r, s); + + /* switch run lists */ + tl = j->relist[flag]; + tle = j->reliste[flag]; + nl = j->relist[flag^=1]; + nle = j->reliste[flag]; + nl->inst = 0; + + /* Add first instruction to current list */ + if(match == 0) + _renewemptythread(tl, progp->startinst, ms, s); + + /* Execute machine until current list is empty */ + for(tlp=tl; tlp->inst; tlp++){ /* assignment = */ + for(inst = tlp->inst; ; inst = inst->u2.next){ + switch(inst->type){ + case RUNE: /* regular character */ + if(inst->u1.r == r){ + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + } + break; + case LBRA: + tlp->se.m[inst->u1.subid].s.sp = s; + continue; + case RBRA: + tlp->se.m[inst->u1.subid].e.ep = s; + continue; + case ANY: + if(r != '\n') + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case ANYNL: + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case BOL: + if(s == bol || *(s-1) == '\n') + continue; + break; + case EOL: + if(s == j->eol || r == 0 || r == '\n') + continue; + break; + case CCLASS: + ep = inst->u1.cp->end; + for(rp = inst->u1.cp->spans; rp < ep; rp += 2) + if(r >= rp[0] && r <= rp[1]){ + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + } + break; + case NCCLASS: + ep = inst->u1.cp->end; + for(rp = inst->u1.cp->spans; rp < ep; rp += 2) + if(r >= rp[0] && r <= rp[1]) + break; + if(rp == ep) + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case OR: + /* evaluate right choice later */ + if(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle) + return -1; + /* efficiency: advance and re-evaluate */ + continue; + case END: /* Match! */ + match = 1; + tlp->se.m[0].e.ep = s; + if(mp != 0) + _renewmatch(mp, ms, &tlp->se); + break; + } + break; + } + } + if(s == j->eol) + break; + checkstart = j->starttype && nl->inst==0; + s += n; + }while(r); + return match; +} + +static int +regexec2(Reprog *progp, /* program to run */ + char *bol, /* string to run machine on */ + Resub *mp, /* subexpression elements */ + int ms, /* number of elements at mp */ + Reljunk *j +) +{ + int rv; + Relist *relist0, *relist1; + + /* mark space */ + relist0 = malloc(BIGLISTSIZE*sizeof(Relist)); + if(relist0 == nil) + return -1; + relist1 = malloc(BIGLISTSIZE*sizeof(Relist)); + if(relist1 == nil){ + free(relist1); + return -1; + } + j->relist[0] = relist0; + j->relist[1] = relist1; + j->reliste[0] = relist0 + BIGLISTSIZE - 2; + j->reliste[1] = relist1 + BIGLISTSIZE - 2; + + rv = regexec1(progp, bol, mp, ms, j); + free(relist0); + free(relist1); + return rv; +} + +extern int +regexec(Reprog *progp, /* program to run */ + char *bol, /* string to run machine on */ + Resub *mp, /* subexpression elements */ + int ms) /* number of elements at mp */ +{ + Reljunk j; + Relist relist0[LISTSIZE], relist1[LISTSIZE]; + int rv; + + /* + * use user-specified starting/ending location if specified + */ + j.starts = bol; + j.eol = 0; + if(mp && ms>0){ + if(mp->s.sp) + j.starts = mp->s.sp; + if(mp->e.ep) + j.eol = mp->e.ep; + } + j.starttype = 0; + j.startchar = 0; + if(progp->startinst->type == RUNE && progp->startinst->u1.r < Runeself) { + j.starttype = RUNE; + j.startchar = progp->startinst->u1.r; + } + if(progp->startinst->type == BOL) + j.starttype = BOL; + + /* mark space */ + j.relist[0] = relist0; + j.relist[1] = relist1; + j.reliste[0] = relist0 + nelem(relist0) - 2; + j.reliste[1] = relist1 + nelem(relist1) - 2; + + rv = regexec1(progp, bol, mp, ms, &j); + if(rv >= 0) + return rv; + rv = regexec2(progp, bol, mp, ms, &j); + if(rv >= 0) + return rv; + return -1; +} diff --git a/lib/libregexp/regexp9.3 b/lib/libregexp/regexp9.3 @@ -0,0 +1,220 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH REGEXP9 3 +.SH NAME +regcomp, regcomplit, regcompnl, regexec, regsub, rregexec, rregsub, regerror \- regular expression +.SH SYNOPSIS +.B #include <utf.h> +.br +.B #include <fmt.h> +.br +.B #include <regexp9.h> +.PP +.ta \w'\fLRegprog 'u +.B +Reprog *regcomp(char *exp) +.PP +.B +Reprog *regcomplit(char *exp) +.PP +.B +Reprog *regcompnl(char *exp) +.PP +.nf +.B +int regexec(Reprog *prog, char *string, Resub *match, int msize) +.PP +.nf +.B +void regsub(char *source, char *dest, int dlen, Resub *match, int msize) +.PP +.nf +.B +int rregexec(Reprog *prog, Rune *string, Resub *match, int msize) +.PP +.nf +.B +void rregsub(Rune *source, Rune *dest, int dlen, Resub *match, int msize) +.PP +.B +void regerror(char *msg) +.SH DESCRIPTION +.I Regcomp +compiles a +regular expression and returns +a pointer to the generated description. +The space is allocated by +.IR malloc (3) +and may be released by +.IR free . +Regular expressions are exactly as in +.IR regexp9 (7). +.PP +.I Regcomplit +is like +.I regcomp +except that all characters are treated literally. +.I Regcompnl +is like +.I regcomp +except that the +.B . +metacharacter matches all characters, including newlines. +.PP +.I Regexec +matches a null-terminated +.I string +against the compiled regular expression in +.IR prog . +If it matches, +.I regexec +returns +.B 1 +and fills in the array +.I match +with character pointers to the substrings of +.I string +that correspond to the +parenthesized subexpressions of +.IR exp : +.BI match[ i ].sp +points to the beginning and +.BI match[ i ].ep +points just beyond +the end of the +.IR i th +substring. +(Subexpression +.I i +begins at the +.IR i th +left parenthesis, counting from 1.) +Pointers in +.B match[0] +pick out the substring that corresponds to +the whole regular expression. +Unused elements of +.I match +are filled with zeros. +Matches involving +.LR * , +.LR + , +and +.L ? +are extended as far as possible. +The number of array elements in +.I match +is given by +.IR msize . +The structure of elements of +.I match +is: +.IP +.EX +typedef struct { + union { + char *sp; + Rune *rsp; + }; + union { + char *ep; + Rune *rep; + }; +} Resub; +.EE +.LP +If +.B match[0].sp +is nonzero on entry, +.I regexec +starts matching at that point within +.IR string . +If +.B match[0].ep +is nonzero on entry, +the last character matched is the one +preceding that point. +.PP +.I Regsub +places in +.I dest +a substitution instance of +.I source +in the context of the last +.I regexec +performed using +.IR match . +Each instance of +.BI \e n\f1, +where +.I n +is a digit, is replaced by the +string delimited by +.BI match[ n ].sp +and +.BI match[ n ].ep\f1. +Each instance of +.L & +is replaced by the string delimited by +.B match[0].sp +and +.BR match[0].ep . +The substitution will always be null terminated and +trimmed to fit into dlen bytes. +.PP +.IR Regerror , +called whenever an error is detected in +.IR regcomp , +writes the string +.I msg +on the standard error file and exits. +.I Regerror +can be replaced to perform +special error processing. +If the user supplied +.I regerror +returns rather than exits, +.I regcomp +will return 0. +.PP +.I Rregexec +and +.I rregsub +are variants of +.I regexec +and +.I regsub +that use strings of +.B Runes +instead of strings of +.BR chars . +With these routines, the +.I rsp +and +.I rep +fields of the +.I match +array elements should be used. +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH "SEE ALSO" +.IR grep (1) +.SH DIAGNOSTICS +.I Regcomp +returns +.B 0 +for an illegal expression +or other failure. +.I Regexec +returns 0 +if +.I string +is not matched. +.SH BUGS +There is no way to specify or match a NUL character; NULs terminate patterns and strings. diff --git a/lib/libregexp/regexp9.7 b/lib/libregexp/regexp9.7 @@ -0,0 +1,141 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH REGEXP9 7 +.SH NAME +regexp \- Plan 9 regular expression notation +.SH DESCRIPTION +This manual page describes the regular expression +syntax used by the Plan 9 regular expression library +.IR regexp9 (3). +It is the form used by +.IR egrep (1) +before +.I egrep +got complicated. +.PP +A +.I "regular expression" +specifies +a set of strings of characters. +A member of this set of strings is said to be +.I matched +by the regular expression. In many applications +a delimiter character, commonly +.LR / , +bounds a regular expression. +In the following specification for regular expressions +the word `character' means any character (rune) but newline. +.PP +The syntax for a regular expression +.B e0 +is +.IP +.EX +e3: literal | charclass | '.' | '^' | '$' | '(' e0 ')' + +e2: e3 + | e2 REP + +REP: '*' | '+' | '?' + +e1: e2 + | e1 e2 + +e0: e1 + | e0 '|' e1 +.EE +.PP +A +.B literal +is any non-metacharacter, or a metacharacter +(one of +.BR .*+?[]()|\e^$ ), +or the delimiter +preceded by +.LR \e . +.PP +A +.B charclass +is a nonempty string +.I s +bracketed +.BI [ \|s\| ] +(or +.BI [^ s\| ]\fR); +it matches any character in (or not in) +.IR s . +A negated character class never +matches newline. +A substring +.IB a - b\f1, +with +.I a +and +.I b +in ascending +order, stands for the inclusive +range of +characters between +.I a +and +.IR b . +In +.IR s , +the metacharacters +.LR - , +.LR ] , +an initial +.LR ^ , +and the regular expression delimiter +must be preceded by a +.LR \e ; +other metacharacters +have no special meaning and +may appear unescaped. +.PP +A +.L . +matches any character. +.PP +A +.L ^ +matches the beginning of a line; +.L $ +matches the end of the line. +.PP +The +.B REP +operators match zero or more +.RB ( * ), +one or more +.RB ( + ), +zero or one +.RB ( ? ), +instances respectively of the preceding regular expression +.BR e2 . +.PP +A concatenated regular expression, +.BR "e1\|e2" , +matches a match to +.B e1 +followed by a match to +.BR e2 . +.PP +An alternative regular expression, +.BR "e0\||\|e1" , +matches either a match to +.B e0 +or a match to +.BR e1 . +.PP +A match to any part of a regular expression +extends as far as possible without preventing +a match to the remainder of the regular expression. +.SH "SEE ALSO +.IR regexp9 (3) diff --git a/lib/libregexp/regsub.c b/lib/libregexp/regsub.c @@ -0,0 +1,63 @@ +#include "plan9.h" +#include "regexp9.h" + +/* substitute into one string using the matches from the last regexec() */ +extern void +regsub(char *sp, /* source string */ + char *dp, /* destination string */ + int dlen, + Resub *mp, /* subexpression elements */ + int ms) /* number of elements pointed to by mp */ +{ + char *ssp, *ep; + int i; + + ep = dp+dlen-1; + while(*sp != '\0'){ + if(*sp == '\\'){ + switch(*++sp){ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + i = *sp-'0'; + if(mp[i].s.sp != 0 && mp!=0 && ms>i) + for(ssp = mp[i].s.sp; + ssp < mp[i].e.ep; + ssp++) + if(dp < ep) + *dp++ = *ssp; + break; + case '\\': + if(dp < ep) + *dp++ = '\\'; + break; + case '\0': + sp--; + break; + default: + if(dp < ep) + *dp++ = *sp; + break; + } + }else if(*sp == '&'){ + if(mp[0].s.sp != 0 && mp!=0 && ms>0) + if(mp[0].s.sp != 0) + for(ssp = mp[0].s.sp; + ssp < mp[0].e.ep; ssp++) + if(dp < ep) + *dp++ = *ssp; + }else{ + if(dp < ep) + *dp++ = *sp; + } + sp++; + } + *dp = '\0'; +} diff --git a/lib/libregexp/rregexec.c b/lib/libregexp/rregexec.c @@ -0,0 +1,213 @@ +#include "plan9.h" +#include "regexp9.h" +#include "regcomp.h" + +/* + * return 0 if no match + * >0 if a match + * <0 if we ran out of _relist space + */ +static int +rregexec1(Reprog *progp, /* program to run */ + Rune *bol, /* string to run machine on */ + Resub *mp, /* subexpression elements */ + int ms, /* number of elements at mp */ + Reljunk *j) +{ + int flag=0; + Reinst *inst; + Relist *tlp; + Rune *s; + int i, checkstart; + Rune r, *rp, *ep; + Relist* tl; /* This list, next list */ + Relist* nl; + Relist* tle; /* ends of this and next list */ + Relist* nle; + int match; + + match = 0; + checkstart = j->startchar; + if(mp) + for(i=0; i<ms; i++) { + mp[i].s.rsp = 0; + mp[i].e.rep = 0; + } + j->relist[0][0].inst = 0; + j->relist[1][0].inst = 0; + + /* Execute machine once for each character, including terminal NUL */ + s = j->rstarts; + do{ + + /* fast check for first char */ + if(checkstart) { + switch(j->starttype) { + case RUNE: + while(*s != j->startchar) { + if(*s == 0 || s == j->reol) + return match; + s++; + } + break; + case BOL: + if(s == bol) + break; + while(*s != '\n') { + if(*s == 0 || s == j->reol) + return match; + s++; + } + break; + } + } + + r = *s; + + /* switch run lists */ + tl = j->relist[flag]; + tle = j->reliste[flag]; + nl = j->relist[flag^=1]; + nle = j->reliste[flag]; + nl->inst = 0; + + /* Add first instruction to current list */ + _rrenewemptythread(tl, progp->startinst, ms, s); + + /* Execute machine until current list is empty */ + for(tlp=tl; tlp->inst; tlp++){ + for(inst=tlp->inst; ; inst = inst->u2.next){ + switch(inst->type){ + case RUNE: /* regular character */ + if(inst->u1.r == r) + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case LBRA: + tlp->se.m[inst->u1.subid].s.rsp = s; + continue; + case RBRA: + tlp->se.m[inst->u1.subid].e.rep = s; + continue; + case ANY: + if(r != '\n') + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case ANYNL: + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case BOL: + if(s == bol || *(s-1) == '\n') + continue; + break; + case EOL: + if(s == j->reol || r == 0 || r == '\n') + continue; + break; + case CCLASS: + ep = inst->u1.cp->end; + for(rp = inst->u1.cp->spans; rp < ep; rp += 2) + if(r >= rp[0] && r <= rp[1]){ + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + } + break; + case NCCLASS: + ep = inst->u1.cp->end; + for(rp = inst->u1.cp->spans; rp < ep; rp += 2) + if(r >= rp[0] && r <= rp[1]) + break; + if(rp == ep) + if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) + return -1; + break; + case OR: + /* evaluate right choice later */ + if(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle) + return -1; + /* efficiency: advance and re-evaluate */ + continue; + case END: /* Match! */ + match = 1; + tlp->se.m[0].e.rep = s; + if(mp != 0) + _renewmatch(mp, ms, &tlp->se); + break; + } + break; + } + } + if(s == j->reol) + break; + checkstart = j->startchar && nl->inst==0; + s++; + }while(r); + return match; +} + +static int +rregexec2(Reprog *progp, /* program to run */ + Rune *bol, /* string to run machine on */ + Resub *mp, /* subexpression elements */ + int ms, /* number of elements at mp */ + Reljunk *j +) +{ + Relist relist0[5*LISTSIZE], relist1[5*LISTSIZE]; + + /* mark space */ + j->relist[0] = relist0; + j->relist[1] = relist1; + j->reliste[0] = relist0 + nelem(relist0) - 2; + j->reliste[1] = relist1 + nelem(relist1) - 2; + + return rregexec1(progp, bol, mp, ms, j); +} + +extern int +rregexec(Reprog *progp, /* program to run */ + Rune *bol, /* string to run machine on */ + Resub *mp, /* subexpression elements */ + int ms) /* number of elements at mp */ +{ + Reljunk j; + Relist relist0[LISTSIZE], relist1[LISTSIZE]; + int rv; + + /* + * use user-specified starting/ending location if specified + */ + j.rstarts = bol; + j.reol = 0; + if(mp && ms>0){ + if(mp->s.sp) + j.rstarts = mp->s.rsp; + if(mp->e.ep) + j.reol = mp->e.rep; + } + j.starttype = 0; + j.startchar = 0; + if(progp->startinst->type == RUNE && progp->startinst->u1.r < Runeself) { + j.starttype = RUNE; + j.startchar = progp->startinst->u1.r; + } + if(progp->startinst->type == BOL) + j.starttype = BOL; + + /* mark space */ + j.relist[0] = relist0; + j.relist[1] = relist1; + j.reliste[0] = relist0 + nelem(relist0) - 2; + j.reliste[1] = relist1 + nelem(relist1) - 2; + + rv = rregexec1(progp, bol, mp, ms, &j); + if(rv >= 0) + return rv; + rv = rregexec2(progp, bol, mp, ms, &j); + if(rv >= 0) + return rv; + return -1; +} diff --git a/lib/libregexp/rregsub.c b/lib/libregexp/rregsub.c @@ -0,0 +1,63 @@ +#include "plan9.h" +#include "regexp9.h" + +/* substitute into one string using the matches from the last regexec() */ +extern void +rregsub(Rune *sp, /* source string */ + Rune *dp, /* destination string */ + int dlen, + Resub *mp, /* subexpression elements */ + int ms) /* number of elements pointed to by mp */ +{ + Rune *ssp, *ep; + int i; + + ep = dp+(dlen/sizeof(Rune))-1; + while(*sp != '\0'){ + if(*sp == '\\'){ + switch(*++sp){ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + i = *sp-'0'; + if(mp[i].s.rsp != 0 && mp!=0 && ms>i) + for(ssp = mp[i].s.rsp; + ssp < mp[i].e.rep; + ssp++) + if(dp < ep) + *dp++ = *ssp; + break; + case '\\': + if(dp < ep) + *dp++ = '\\'; + break; + case '\0': + sp--; + break; + default: + if(dp < ep) + *dp++ = *sp; + break; + } + }else if(*sp == '&'){ + if(mp[0].s.rsp != 0 && mp!=0 && ms>0) + if(mp[0].s.rsp != 0) + for(ssp = mp[0].s.rsp; + ssp < mp[0].e.rep; ssp++) + if(dp < ep) + *dp++ = *ssp; + }else{ + if(dp < ep) + *dp++ = *sp; + } + sp++; + } + *dp = '\0'; +} diff --git a/lib/libregexp/test.c b/lib/libregexp/test.c @@ -0,0 +1,46 @@ +#include "plan9.h" +#include <regexp9.h> + +struct x +{ + char *re; + char *s; + Reprog *p; +}; + +struct x t[] = { + { "^[^!@]+$", "/bin/upas/aliasmail '&'", 0 }, + { "^local!(.*)$", "/mail/box/\\1/mbox", 0 }, + { "^plan9!(.*)$", "\\1", 0 }, + { "^helix!(.*)$", "\\1", 0 }, + { "^([^!]+)@([^!@]+)$", "\\2!\\1", 0 }, + { "^(uk\\.[^!]*)(!.*)$", "/bin/upas/uk2uk '\\1' '\\2'", 0 }, + { "^[^!]*\\.[^!]*!.*$", "inet!&", 0 }, + { "^\xE2\x98\xBA$", "smiley", 0 }, + { "^(coma|research|pipe|pyxis|inet|hunny|gauss)!(.*)$", "/mail/lib/qmail '\\s' 'net!\\1' '\\2'", 0 }, + { "^.*$", "/mail/lib/qmail '\\s' 'net!research' '&'", 0 }, + { 0, 0, 0 }, +}; + +main(int ac, char **av) +{ + Resub rs[10]; + char dst[128]; + int n; + struct x *tp; + + for(tp = t; tp->re; tp++) + tp->p = regcomp(tp->re); + + + for(tp = t; tp->re; tp++){ + print("%s VIA %s", av[1], tp->re); + memset(rs, 0, sizeof rs); + if(regexec(tp->p, av[1], rs, 10)){ + regsub(tp->s, dst, sizeof dst, rs, 10); + print(" sub %s -> %s", tp->s, dst); + } + print("\n"); + } + exit(0); +} diff --git a/lib/libregexp/test2.c b/lib/libregexp/test2.c @@ -0,0 +1,20 @@ +#include "plan9.h" +#include <regexp9.h> + + +main(int ac, char **av) +{ + Resub rs[10]; + Reprog *p; + char *s; + int i; + + p = regcomp("[^a-z]"); + s = "\n"; + if(regexec(p, s, rs, 10)) + print("%s %lux %lux %lux\n", s, s, rs[0].sp, rs[0].ep); + s = "0"; + if(regexec(p, s, rs, 10)) + print("%s %lux %lux %lux\n", s, s, rs[0].sp, rs[0].ep); + exit(0); +} diff --git a/lib/libstuff/Makefile b/lib/libstuff/Makefile @@ -0,0 +1,172 @@ +ROOT= ../.. +include $(ROOT)/mk/hdr.mk + +TARG=libstuff + +PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama + +OBJ=\ + buffer \ + clientutil \ + event/buttonpress \ + event/buttonrelease \ + event/clientmessage \ + event/configurenotify \ + event/configurerequest \ + event/destroynotify \ + event/enternotify \ + event/event \ + event/expose \ + event/focusin \ + event/focusout \ + event/keypress \ + event/leavenotify \ + event/mapnotify \ + event/maprequest \ + event/mappingnotify \ + event/motionnotify \ + event/propertynotify \ + event/unmapnotify \ + event/xtime \ + geom/get_sticky \ + geom/quadrant \ + geom/rect_contains_p \ + geom/rect_haspoint_p \ + geom/rect_intersect_p \ + geom/rect_intersection \ + init_screens \ + map \ + printevent \ + util/_die \ + util/backtrace \ + util/closeexec \ + util/comm \ + util/doublefork \ + util/emalloc \ + util/emallocz \ + util/erealloc \ + util/estrdup \ + util/estrndup \ + util/fatal \ + util/freelater \ + util/getbase \ + util/getint \ + util/getlong \ + util/getulong \ + util/grep \ + util/join \ + util/max \ + util/mfatal \ + util/min \ + util/pathsearch \ + util/refree \ + util/reinit \ + util/spawn3 \ + util/spawn3l \ + util/stokenize \ + util/strcasestr \ + util/strend \ + util/strlcat \ + util/strlcatprint \ + util/sxprint \ + util/tokenize \ + util/uniq \ + util/unquote \ + util/utflcpy \ + util/vector \ + util/vsxprint \ + x11/convpts \ + x11/errors \ + x11/ignored_xerrors \ + x11/freestringlist \ + x11/initdisplay \ + x11/sendevent \ + x11/sendmessage \ + x11/setgccol \ + x11/sync \ + x11/x11 \ + x11/xatom \ + x11/xft \ + x11/colors/loadcolor \ + x11/colors/namedcolor \ + x11/colors/xftcolor \ + x11/drawing/border \ + x11/drawing/drawline \ + x11/drawing/drawpoly \ + x11/drawing/drawstring \ + x11/drawing/fill \ + x11/drawing/fillpoly \ + x11/focus/getfocus \ + x11/focus/setfocus \ + x11/geometry/XRect \ + x11/geometry/addpt \ + x11/geometry/divpt \ + x11/geometry/eqpt \ + x11/geometry/eqrect \ + x11/geometry/insetrect \ + x11/geometry/mulpt \ + x11/geometry/rectaddpt \ + x11/geometry/rectsetorigin \ + x11/geometry/rectsubpt \ + x11/geometry/subpt \ + x11/images/allocimage \ + x11/images/copyimage \ + x11/images/freeimage \ + x11/images/xftdrawable \ + x11/insanity/gravitate \ + x11/insanity/sethints \ + x11/insanity/sizehint \ + x11/keyboard/grabkeyboard \ + x11/keyboard/ungrabkeyboard \ + x11/keys/keycode \ + x11/keys/parsekey \ + x11/mouse/grabpointer \ + x11/mouse/pointerscreen \ + x11/mouse/querypointer \ + x11/mouse/translate \ + x11/mouse/ungrabpointer \ + x11/mouse/warppointer \ + x11/properties/changeprop_char \ + x11/properties/changeprop_long \ + x11/properties/changeprop_short \ + x11/properties/changeprop_string \ + x11/properties/changeprop_textlist \ + x11/properties/changeprop_ulong \ + x11/properties/changeproperty \ + x11/properties/delproperty \ + x11/properties/getprop \ + x11/properties/getprop_long \ + x11/properties/getprop_string \ + x11/properties/getprop_textlist \ + x11/properties/getprop_ulong \ + x11/properties/getproperty \ + x11/properties/strlistdup \ + x11/shape/setshapemask \ + x11/text/freefont \ + x11/text/labelh \ + x11/text/loadfont \ + x11/text/textextents_l \ + x11/text/textwidth \ + x11/text/textwidth_l \ + x11/windows/configwin \ + x11/windows/createwindow \ + x11/windows/createwindow_visual \ + x11/windows/destroywindow \ + x11/windows/findwin \ + x11/windows/getwinrect \ + x11/windows/lowerwin \ + x11/windows/mapwin \ + x11/windows/movewin \ + x11/windows/raisewin \ + x11/windows/reparentwindow \ + x11/windows/reshapewin \ + x11/windows/selectinput \ + x11/windows/setborder \ + x11/windows/sethandler \ + x11/windows/setwinattr \ + x11/windows/unmapwin \ + x11/windows/window \ + xext + +include $(ROOT)/mk/lib.mk + diff --git a/lib/libstuff/buffer.c b/lib/libstuff/buffer.c @@ -0,0 +1,8 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ + +char buffer[8092]; +char* _buffer; +char* const _buf_end = buffer + sizeof buffer; + diff --git a/lib/libstuff/clientutil.c b/lib/libstuff/clientutil.c @@ -0,0 +1,50 @@ +#define IXP_NO_P9_ +#define IXP_P9_STRUCTS +#define CLIENTEXTERN +#include <string.h> +#include <ixp.h> +#include <stuff/clientutil.h> +#include <stuff/util.h> + +static IxpCFid* ctlfid; +static char ctl[1024]; +static char* ectl; + +char* +readctl(char *key) { + char *s, *p; + int nkey, n; + + if(ctlfid == nil) { + ctlfid = ixp_open(client, "ctl", OREAD); + n = ixp_read(ctlfid, ctl, 1023); + ectl = ctl + n; + ixp_close(ctlfid); + } + + nkey = strlen(key); + p = ctl - 1; + do { + p++; + if(!strncmp(p, key, nkey)) { + p += nkey; + s = strchr(p, '\n'); + n = (s ? s : ectl) - p; + s = freelater(emalloc(n + 1)); + s[n] = '\0'; + return strncpy(s, p, n); + } + } while((p = strchr(p, '\n'))); + return ""; +} + +void +client_init(char* address) { + if(address && *address) + client = ixp_mount(address); + else + client = ixp_nsmount("wmii"); + if(client == nil) + fatal("can't mount: %r\n"); +} + diff --git a/lib/libstuff/event/buttonpress.c b/lib/libstuff/event/buttonpress.c @@ -0,0 +1,14 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_buttonpress(XButtonPressedEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, bdown, ev); + else + XAllowEvents(display, ReplayPointer, ev->time); +} diff --git a/lib/libstuff/event/buttonrelease.c b/lib/libstuff/event/buttonrelease.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_buttonrelease(XButtonPressedEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, bup, ev); +} diff --git a/lib/libstuff/event/clientmessage.c b/lib/libstuff/event/clientmessage.c @@ -0,0 +1,10 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_clientmessage(XClientMessageEvent *ev) { + + USED(ev); +} diff --git a/lib/libstuff/event/configurenotify.c b/lib/libstuff/event/configurenotify.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_configurenotify(XConfigureEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, config, ev); +} diff --git a/lib/libstuff/event/configurerequest.c b/lib/libstuff/event/configurerequest.c @@ -0,0 +1,24 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_configurerequest(XConfigureRequestEvent *ev) { + XWindowChanges wc; + Window *w; + + if((w = findwin(ev->window))) + handle(w, configreq, ev); + else{ + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(display, ev->window, ev->value_mask, &wc); + } +} + diff --git a/lib/libstuff/event/destroynotify.c b/lib/libstuff/event/destroynotify.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_destroynotify(XDestroyWindowEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, destroy, ev); +} diff --git a/lib/libstuff/event/enternotify.c b/lib/libstuff/event/enternotify.c @@ -0,0 +1,16 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_enternotify(XCrossingEvent *ev) { + Window *w; + + event_xtime = ev->time; + if(ev->mode != NotifyNormal) + return; + + if((w = findwin(ev->window))) + handle(w, enter, ev); +} diff --git a/lib/libstuff/event/event.c b/lib/libstuff/event/event.c @@ -0,0 +1,107 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void (*event_debug)(XEvent*); +long event_xtime; +bool event_looprunning; + +EventHandler event_handler[LASTEvent] = { + [ButtonPress] = (EventHandler)event_buttonpress, + [ButtonRelease] = (EventHandler)event_buttonrelease, + [ClientMessage] = (EventHandler)event_clientmessage, + [ConfigureNotify] = (EventHandler)event_configurenotify, + [ConfigureRequest] = (EventHandler)event_configurerequest, + [DestroyNotify] = (EventHandler)event_destroynotify, + [EnterNotify] = (EventHandler)event_enternotify, + [Expose] = (EventHandler)event_expose, + [FocusIn] = (EventHandler)event_focusin, + [FocusOut] = (EventHandler)event_focusout, + [KeyPress] = (EventHandler)event_keypress, + [LeaveNotify] = (EventHandler)event_leavenotify, + [MapNotify] = (EventHandler)event_mapnotify, + [MapRequest] = (EventHandler)event_maprequest, + [MappingNotify] = (EventHandler)event_mappingnotify, + [MotionNotify] = (EventHandler)event_motionnotify, + [PropertyNotify] = (EventHandler)event_propertynotify, + [UnmapNotify] = (EventHandler)event_unmapnotify, +}; + +void +event_dispatch(XEvent *e) { + if(event_debug) + event_debug(e); + + if(e->type < nelem(event_handler)) { + if(event_handler[e->type]) + event_handler[e->type](e); + }else + xext_event(e); +} + +void +event_check(void) { + XEvent ev; + + while(XPending(display)) { + XNextEvent(display, &ev); + event_dispatch(&ev); + } +} + +void +event_loop(void) { + XEvent ev; + + while(event_looprunning) { + XNextEvent(display, &ev); + event_dispatch(&ev); + } +} + +uint +event_flush(long event_mask, bool dispatch) { + XEvent ev; + uint n = 0; + + while(XCheckMaskEvent(display, event_mask, &ev)) { + if(dispatch) + event_dispatch(&ev); + n++; + } + return n; +} + +static int +findenter(Display *d, XEvent *e, XPointer v) { + long *l; + + USED(d); + l = (long*)v; + if(*l) + return false; + if(e->type == EnterNotify) + return true; + if(e->type == MotionNotify) + (*l)++; + return false; +} + +/* This isn't perfect. If there were motion events in the queue + * before this was called, then it flushes nothing. If we don't + * check for them, we might lose a legitamate enter event. + */ +uint +event_flushenter(void) { + XEvent e; + long l; + int n; + + l = 0; + n = 0; + while(XCheckIfEvent(display, &e, findenter, (void*)&l)) + n++; + return n; +} + diff --git a/lib/libstuff/event/event.h b/lib/libstuff/event/event.h @@ -0,0 +1,9 @@ +#include <stuff/x.h> + +typedef void (*EventHandler)(XEvent*); + +#define handle(w, fn, ev) \ + BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev)) + +extern EventHandler event_handler[LASTEvent]; + diff --git a/lib/libstuff/event/expose.c b/lib/libstuff/event/expose.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_expose(XExposeEvent *ev) { + Window *w; + + if(ev->count == 0 && (w = findwin(ev->window))) + handle(w, expose, ev); +} diff --git a/lib/libstuff/event/focusin.c b/lib/libstuff/event/focusin.c @@ -0,0 +1,27 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_focusin(XFocusChangeEvent *ev) { + Window *w; + + /* Yes, we're focusing in on nothing, here. */ + if(ev->detail == NotifyDetailNone) { + /* FIXME: Do something. */ + return; + } + + if(!((ev->detail == NotifyNonlinear) + ||(ev->detail == NotifyNonlinearVirtual) + ||(ev->detail == NotifyVirtual) + ||(ev->detail == NotifyInferior) + ||(ev->detail == NotifyAncestor))) + return; + if((ev->mode == NotifyWhileGrabbed)) + return; + + if((w = findwin(ev->window))) + handle(w, focusin, ev); +} diff --git a/lib/libstuff/event/focusout.c b/lib/libstuff/event/focusout.c @@ -0,0 +1,19 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_focusout(XFocusChangeEvent *ev) { + Window *w; + + if(!((ev->detail == NotifyNonlinear) + ||(ev->detail == NotifyNonlinearVirtual) + ||(ev->detail == NotifyVirtual) + ||(ev->detail == NotifyInferior) + ||(ev->detail == NotifyAncestor))) + return; + + if((w = findwin(ev->window))) + handle(w, focusout, ev); +} diff --git a/lib/libstuff/event/keypress.c b/lib/libstuff/event/keypress.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_keypress(XKeyEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, kdown, ev); +} diff --git a/lib/libstuff/event/leavenotify.c b/lib/libstuff/event/leavenotify.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_leavenotify(XCrossingEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, leave, ev); +} diff --git a/lib/libstuff/event/mapnotify.c b/lib/libstuff/event/mapnotify.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_mapnotify(XMapEvent *ev) { + Window *w; + + if((w = findwin(ev->window))) + handle(w, map, ev); +} diff --git a/lib/libstuff/event/mappingnotify.c b/lib/libstuff/event/mappingnotify.c @@ -0,0 +1,11 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_mappingnotify(XMappingEvent *ev) { + + /* Why do you need me to tell you this? */ + XRefreshKeyboardMapping(ev); +} diff --git a/lib/libstuff/event/maprequest.c b/lib/libstuff/event/maprequest.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_maprequest(XMapRequestEvent *ev) { + Window *w; + + if((w = findwin(ev->parent))) + handle(w, mapreq, ev); +} diff --git a/lib/libstuff/event/motionnotify.c b/lib/libstuff/event/motionnotify.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_motionnotify(XMotionEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, motion, ev); +} diff --git a/lib/libstuff/event/propertynotify.c b/lib/libstuff/event/propertynotify.c @@ -0,0 +1,13 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_propertynotify(XPropertyEvent *ev) { + Window *w; + + event_xtime = ev->time; + if((w = findwin(ev->window))) + handle(w, property, ev); +} diff --git a/lib/libstuff/event/unmapnotify.c b/lib/libstuff/event/unmapnotify.c @@ -0,0 +1,15 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "event.h" + +void +event_unmapnotify(XUnmapEvent *ev) { + Window *w; + + if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) { + w->mapped = false; + if(w->parent && (ev->send_event || w->unmapped-- == 0)) + handle(w, unmap, ev); + } +} diff --git a/lib/libstuff/event/xtime.c b/lib/libstuff/event/xtime.c @@ -0,0 +1,33 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/x.h> + +static int +findtime(Display *d, XEvent *e, XPointer v) { + Window *w; + + w = (Window*)v; + if(e->type == PropertyNotify && e->xproperty.window == w->xid) { + event_xtime = e->xproperty.time; + return true; + } + return false; +} + +void +event_updatextime(void) { + Window *w; + WinAttr wa; + XEvent e; + long l; + + w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0); + + XSelectInput(display, w->xid, PropertyChangeMask); + changeprop_long(w, "ATOM", "ATOM", &l, 0); + XIfEvent(display, &e, findtime, (void*)w); + + destroywindow(w); +} + diff --git a/lib/libstuff/geom/get_sticky.c b/lib/libstuff/geom/get_sticky.c @@ -0,0 +1,24 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +Align +get_sticky(Rectangle src, Rectangle dst) { + Align corner; + + corner = 0; + if(src.min.x != dst.min.x + && src.max.x == dst.max.x) + corner |= East; + else + corner |= West; + + if(src.min.y != dst.min.y + && src.max.y == dst.max.y) + corner |= South; + else + corner |= North; + + return corner; +} diff --git a/lib/libstuff/geom/quadrant.c b/lib/libstuff/geom/quadrant.c @@ -0,0 +1,23 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +Align +quadrant(Rectangle r, Point pt) { + Align ret; + + pt = subpt(pt, r.min); + ret = 0; + + if(pt.x >= Dx(r) * .5) + ret |= East; + if(pt.x <= Dx(r) * .5) + ret |= West; + if(pt.y <= Dy(r) * .5) + ret |= North; + if(pt.y >= Dy(r) * .5) + ret |= South; + + return ret; +} diff --git a/lib/libstuff/geom/rect_contains_p.c b/lib/libstuff/geom/rect_contains_p.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +bool +rect_contains_p(Rectangle r, Rectangle r2) { + return r2.min.x >= r.min.x + && r2.max.x <= r.max.x + && r2.min.y >= r.min.y + && r2.max.y <= r.max.y; +} diff --git a/lib/libstuff/geom/rect_haspoint_p.c b/lib/libstuff/geom/rect_haspoint_p.c @@ -0,0 +1,10 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +bool +rect_haspoint_p(Point pt, Rectangle r) { + return (pt.x >= r.min.x) && (pt.x < r.max.x) + && (pt.y >= r.min.y) && (pt.y < r.max.y); +} diff --git a/lib/libstuff/geom/rect_intersect_p.c b/lib/libstuff/geom/rect_intersect_p.c @@ -0,0 +1,12 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> + +bool +rect_intersect_p(Rectangle r, Rectangle r2) { + return r.min.x <= r2.max.x + && r.max.x >= r2.min.x + && r.min.y <= r2.max.y + && r.max.y >= r2.min.y; +} diff --git a/lib/libstuff/geom/rect_intersection.c b/lib/libstuff/geom/rect_intersection.c @@ -0,0 +1,17 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/geom.h> +#include <stuff/util.h> + +Rectangle +rect_intersection(Rectangle r, Rectangle r2) { + Rectangle ret; + + /* ret != canonrect(ret) ≡ no intersection. */ + ret.min.x = max(r.min.x, r2.min.x); + ret.max.x = min(r.max.x, r2.max.x); + ret.min.y = max(r.min.y, r2.min.y); + ret.max.y = min(r.max.y, r2.max.y); + return ret; +} diff --git a/lib/libstuff/init_screens.c b/lib/libstuff/init_screens.c @@ -0,0 +1,9 @@ +/* Copyright ©2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ + +void init_screens(void); +void +init_screens(void) { +} + diff --git a/lib/libstuff/map.c b/lib/libstuff/map.c @@ -0,0 +1,126 @@ +/* Written by Kris Maglione */ +/* Public domain */ +#include <string.h> +#include <stuff/util.h> + +/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */ + +struct MapEnt { + ulong hash; + const char* key; + void* val; + MapEnt* next; +}; + +MapEnt *NM; + +/* By Dan Bernstein. Public domain. */ +static ulong +hash(const char *str) { + ulong h; + + h = 5381; + while (*str != '\0') { + h += h << 5; /* h *= 33 */ + h ^= *str++; + } + return h; +} + +static void +insert(MapEnt **e, ulong val, const char *key) { + MapEnt *te; + + te = emallocz(sizeof *te); + te->hash = val; + te->key = key; + te->next = *e; + *e = te; +} + +static MapEnt** +map_getp(Map *map, ulong val, int create) { + MapEnt **e; + + e = &map->bucket[val%map->nhash]; + for(; *e; e = &(*e)->next) + if((*e)->hash >= val) break; + if(*e == nil || (*e)->hash != val) { + if(create) + insert(e, val, nil); + else + e = &NM; + } + return e; +} + +static MapEnt** +hash_getp(Map *map, const char *str, int create) { + MapEnt **e; + ulong h; + int cmp; + + h = hash(str); + e = map_getp(map, h, create); + if(*e && (*e)->key == nil) + (*e)->key = str; + else { + SET(cmp); + for(; *e; e = &(*e)->next) + if((*e)->hash > h || (cmp = strcmp((*e)->key, str)) >= 0) + break; + if(*e == nil || (*e)->hash > h || cmp > 0) + if(create) + insert(e, h, str); + } + return e; +} + +void** +map_get(Map *map, ulong val, bool create) { + MapEnt *e; + + e = *map_getp(map, val, create); + return e ? &e->val : nil; +} + +void** +hash_get(Map *map, const char *str, bool create) { + MapEnt *e; + + e = *hash_getp(map, str, create); + return e ? &e->val : nil; +} + +void* +map_rm(Map *map, ulong val) { + MapEnt **e, *te; + void *ret; + + ret = nil; + e = map_getp(map, val, 0); + if(*e) { + te = *e; + ret = te->val; + *e = te->next; + free(te); + } + return ret; +} + +void* +hash_rm(Map *map, const char *str) { + MapEnt **e, *te; + void *ret; + + ret = nil; + e = hash_getp(map, str, 0); + if(*e) { + te = *e; + ret = te->val; + *e = te->next; + free(te); + } + return ret; +} + diff --git a/lib/libstuff/printevent.c b/lib/libstuff/printevent.c @@ -0,0 +1,994 @@ +/* + * Original code posted to comp.sources.x + * Modifications by Russ Cox <rsc@swtch.com>. + * Further modifications by Kris Maglione <maglione.k at Gmail> + */ + +/* + * Path: uunet!wyse!mikew From: mikew@wyse.wyse.com (Mike Wexler) Newsgroups: + * comp.sources.x Subject: v02i056: subroutine to print events in human + * readable form, Part01/01 Message-ID: <1935@wyse.wyse.com> Date: 22 Dec 88 + * 19:28:25 GMT Organization: Wyse Technology, San Jose Lines: 1093 Approved: + * mikew@wyse.com + * + * Submitted-by: richsun!darkstar!ken Posting-number: Volume 2, Issue 56 + * Archive-name: showevent/part01 + * + * + * There are times during debugging when it would be real useful to be able to + * print the fields of an event in a human readable form. Too many times I + * found myself scrounging around in section 8 of the Xlib manual looking for + * the valid fields for the events I wanted to see, then adding printf's to + * display the numeric values of the fields, and then scanning through X.h + * trying to decode the cryptic detail and state fields. After playing with + * xev, I decided to write a couple of standard functions that I could keep + * in a library and call on whenever I needed a little debugging verbosity. + * The first function, GetType(), is useful for returning the string + * representation of the type of an event. The second function, ShowEvent(), + * is used to display all the fields of an event in a readable format. The + * functions are not complicated, in fact, they are mind-numbingly boring - + * but that's just the point nobody wants to spend the time writing functions + * like this, they just want to have them when they need them. + * + * A simple, sample program is included which does little else but to + * demonstrate the use of these two functions. These functions have saved me + * many an hour during debugging and I hope you find some benefit to these. + * If you have any comments, suggestions, improvements, or if you find any + * blithering errors you can get it touch with me at the following location: + * + * ken@richsun.UUCP + */ + +#include <stdarg.h> +#include <bio.h> +#include <stuff/x.h> +#include <stuff/util.h> +#include "printevent.h" +#define Window XWindow + +#define nil ((void*)0) + +typedef struct Pair Pair; + +struct Pair { + int key; + char *val; +}; + +static char* sep = " "; + +static char * +search(Pair *lst, int key, char *(*def)(int)) { + for(; lst->val; lst++) + if(lst->key == key) + return lst->val; + return def(key); +} + +static char* +unmask(Pair *list, uint val) +{ + Pair *p; + char *s, *end; + int n; + + buffer[0] = '\0'; + end = buffer + sizeof buffer; + s = buffer; + + n = 0; + s = utfecpy(s, end, "("); + for (p = list; p->val; p++) + if (val & p->key) { + if(n++) + s = utfecpy(s, end, "|"); + s = utfecpy(s, end, p->val); + } + utfecpy(s, end, ")"); + + return buffer; +} + +static char * +strhex(int key) { + sprint(buffer, "0x%x", key); + return buffer; +} + +static char * +strdec(int key) { + sprint(buffer, "%d", key); + return buffer; +} + +static char * +strign(int key) { + USED(key); + + return "?"; +} + +/******************************************************************************/ +/**** Miscellaneous routines to convert values to their string equivalents ****/ +/******************************************************************************/ + +static void +TInt(Fmt *b, va_list *ap) { + fmtprint(b, "%d", va_arg(*ap, int)); +} + +static void +TWindow(Fmt *b, va_list *ap) { + Window w; + + w = va_arg(*ap, Window); + fmtprint(b, "0x%ux", (uint)w); +} + +static void +TData(Fmt *b, va_list *ap) { + long *l; + int i; + + l = va_arg(*ap, long*); + fmtprint(b, "{"); + for (i = 0; i < 5; i++) { + if(i > 0) + fmtprint(b, ", "); + fmtprint(b, "0x%08lx", l[i]); + } + fmtprint(b, "}"); +} + +/* Returns the string equivalent of a timestamp */ +static void +TTime(Fmt *b, va_list *ap) { + ldiv_t d; + ulong msec; + ulong sec; + ulong min; + ulong hr; + ulong day; + Time time; + + time = va_arg(*ap, Time); + + msec = time/1000; + d = ldiv(msec, 60); + msec = time-msec*1000; + + sec = d.rem; + d = ldiv(d.quot, 60); + min = d.rem; + d = ldiv(d.quot, 24); + hr = d.rem; + day = d.quot; + +#ifdef notdef + sprintf(buffer, "%lu day%s %02lu:%02lu:%02lu.%03lu", + day, day == 1 ? "" : "(s)", hr, min, sec, msec); +#endif + + fmtprint(b, "%ludd_%ludh_%ludm_%lud.%03luds", day, hr, min, sec, msec); +} + +/* Returns the string equivalent of a boolean parameter */ +static void +TBool(Fmt *b, va_list *ap) { + static Pair list[] = { + {True, "True"}, + {False, "False"}, + {0, nil}, + }; + Bool key; + + key = va_arg(*ap, Bool); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a property notify state */ +static void +TPropState(Fmt *b, va_list *ap) { + static Pair list[] = { + {PropertyNewValue, "PropertyNewValue"}, + {PropertyDelete, "PropertyDelete"}, + {0, nil}, + }; + uint key; + + key = va_arg(*ap, uint); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a visibility notify state */ +static void +TVis(Fmt *b, va_list *ap) { + static Pair list[] = { + {VisibilityUnobscured, "VisibilityUnobscured"}, + {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"}, + {VisibilityFullyObscured, "VisibilityFullyObscured"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a mask of buttons and/or modifier keys */ +static void +TModState(Fmt *b, va_list *ap) { + static Pair list[] = { + {Button1Mask, "Button1Mask"}, + {Button2Mask, "Button2Mask"}, + {Button3Mask, "Button3Mask"}, + {Button4Mask, "Button4Mask"}, + {Button5Mask, "Button5Mask"}, + {ShiftMask, "ShiftMask"}, + {LockMask, "LockMask"}, + {ControlMask, "ControlMask"}, + {Mod1Mask, "Mod1Mask"}, + {Mod2Mask, "Mod2Mask"}, + {Mod3Mask, "Mod3Mask"}, + {Mod4Mask, "Mod4Mask"}, + {Mod5Mask, "Mod5Mask"}, + {0, nil}, + }; + uint state; + + state = va_arg(*ap, uint); + fmtprint(b, "%s", unmask(list, state)); +} + +/* Returns the string equivalent of a mask of configure window values */ +static void +TConfMask(Fmt *b, va_list *ap) { + static Pair list[] = { + {CWX, "CWX"}, + {CWY, "CWY"}, + {CWWidth, "CWWidth"}, + {CWHeight, "CWHeight"}, + {CWBorderWidth, "CWBorderWidth"}, + {CWSibling, "CWSibling"}, + {CWStackMode, "CWStackMode"}, + {0, nil}, + }; + uint valuemask; + + valuemask = va_arg(*ap, uint); + fmtprint(b, "%s", unmask(list, valuemask)); +} + +/* Returns the string equivalent of a motion hint */ +#if 0 +static void +IsHint(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyNormal, "NotifyNormal"}, + {NotifyHint, "NotifyHint"}, + {0, nil}, + }; + char key; + + key = va_arg(*ap, char); + fmtprint(b, "%s", search(list, key, strign)); +} +#endif + +/* Returns the string equivalent of an id or the value "None" */ +static void +TIntNone(Fmt *b, va_list *ap) { + static Pair list[] = { + {None, "None"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strhex)); +} + +/* Returns the string equivalent of a colormap state */ +static void +TColMap(Fmt *b, va_list *ap) { + static Pair list[] = { + {ColormapInstalled, "ColormapInstalled"}, + {ColormapUninstalled, "ColormapUninstalled"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a crossing detail */ +static void +TXing(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyAncestor, "NotifyAncestor"}, + {NotifyInferior, "NotifyInferior"}, + {NotifyVirtual, "NotifyVirtual"}, + {NotifyNonlinear, "NotifyNonlinear"}, + {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a focus change detail */ +static void +TFocus(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyAncestor, "NotifyAncestor"}, + {NotifyInferior, "NotifyInferior"}, + {NotifyVirtual, "NotifyVirtual"}, + {NotifyNonlinear, "NotifyNonlinear"}, + {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, + {NotifyPointer, "NotifyPointer"}, + {NotifyPointerRoot, "NotifyPointerRoot"}, + {NotifyDetailNone, "NotifyDetailNone"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a configure detail */ +static void +TConfDetail(Fmt *b, va_list *ap) { + static Pair list[] = { + {Above, "Above"}, + {Below, "Below"}, + {TopIf, "TopIf"}, + {BottomIf, "BottomIf"}, + {Opposite, "Opposite"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a grab mode */ +static void +TGrabMode(Fmt *b, va_list *ap) { + static Pair list[] = { + {NotifyNormal, "NotifyNormal"}, + {NotifyGrab, "NotifyGrab"}, + {NotifyUngrab, "NotifyUngrab"}, + {NotifyWhileGrabbed, "NotifyWhileGrabbed"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a mapping request */ +static void +TMapping(Fmt *b, va_list *ap) { + static Pair list[] = { + {MappingModifier, "MappingModifier"}, + {MappingKeyboard, "MappingKeyboard"}, + {MappingPointer, "MappingPointer"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a stacking order place */ +static void +TPlace(Fmt *b, va_list *ap) { + static Pair list[] = { + {PlaceOnTop, "PlaceOnTop"}, + {PlaceOnBottom, "PlaceOnBottom"}, + {0, nil}, + }; + int key; + + key = va_arg(*ap, int); + fmtprint(b, "%s", search(list, key, strign)); +} + +/* Returns the string equivalent of a major code */ +static void +TMajor(Fmt *b, va_list *ap) { + static char *list[] = { XMajors }; + char *s; + uint key; + + key = va_arg(*ap, uint); + s = "<nil>"; + if(key < nelem(list)) + s = list[key]; + fmtprint(b, "%s", s); +} + +static char* +eventtype(int key) { + static Pair list[] = { + {ButtonPress, "ButtonPress"}, + {ButtonRelease, "ButtonRelease"}, + {CirculateNotify, "CirculateNotify"}, + {CirculateRequest, "CirculateRequest"}, + {ClientMessage, "ClientMessage"}, + {ColormapNotify, "ColormapNotify"}, + {ConfigureNotify, "ConfigureNotify"}, + {ConfigureRequest, "ConfigureRequest"}, + {CreateNotify, "CreateNotify"}, + {DestroyNotify, "DestroyNotify"}, + {EnterNotify, "EnterNotify"}, + {Expose, "Expose"}, + {FocusIn, "FocusIn"}, + {FocusOut, "FocusOut"}, + {GraphicsExpose, "GraphicsExpose"}, + {GravityNotify, "GravityNotify"}, + {KeyPress, "KeyPress"}, + {KeyRelease, "KeyRelease"}, + {KeymapNotify, "KeymapNotify"}, + {LeaveNotify, "LeaveNotify"}, + {MapNotify, "MapNotify"}, + {MapRequest, "MapRequest"}, + {MappingNotify, "MappingNotify"}, + {MotionNotify, "MotionNotify"}, + {NoExpose, "NoExpose"}, + {PropertyNotify, "PropertyNotify"}, + {ReparentNotify, "ReparentNotify"}, + {ResizeRequest, "ResizeRequest"}, + {SelectionClear, "SelectionClear"}, + {SelectionNotify, "SelectionNotify"}, + {SelectionRequest, "SelectionRequest"}, + {UnmapNotify, "UnmapNotify"}, + {VisibilityNotify, "VisibilityNotify"}, + {0, nil}, + }; + return search(list, key, strdec); +} +/* Returns the string equivalent the keycode contained in the key event */ +static void +TKeycode(Fmt *b, va_list *ap) { + KeySym keysym_str; + XKeyEvent *ev; + char *keysym_name; + + ev = va_arg(*ap, XKeyEvent*); + + XLookupString(ev, buffer, sizeof buffer, &keysym_str, nil); + + if (keysym_str == NoSymbol) + keysym_name = "NoSymbol"; + else + keysym_name = XKeysymToString(keysym_str); + if(keysym_name == nil) + keysym_name = "(no name)"; + + fmtprint(b, "%ud (keysym 0x%x \"%s\")", (int)ev->keycode, + (int)keysym_str, keysym_name); +} + +/* Returns the string equivalent of an atom or "None" */ +static void +TAtom(Fmt *b, va_list *ap) { + char *atom_name; + Atom atom; + + atom = va_arg(*ap, Atom); + atom_name = XGetAtomName(display, atom); + fmtprint(b, "%s", atom_name); + XFree(atom_name); +} + +#define _(m) #m, ev->m +#define TEnd nil +typedef void (*Tfn)(Fmt*, va_list*); + +static int +pevent(Fmt *fmt, void *e, ...) { + va_list ap; + Tfn fn; + XAnyEvent *ev; + char *key; + int n; + + ev = e; + fmtprint(fmt, "%3ld %-20s ", ev->serial, eventtype(ev->type)); + if(ev->send_event) + fmtstrcpy(fmt, "(sendevent) "); + + n = 0; + va_start(ap, e); + for(;;) { + fn = va_arg(ap, Tfn); + if(fn == TEnd) + break; + + if(n++ != 0) + fmtprint(fmt, "%s", sep); + + key = va_arg(ap, char*); + fmtprint(fmt, "%s=", key); + fn(fmt, &ap); + } + va_end(ap); + return 0; +} + +/*****************************************************************************/ +/*** Routines to print out readable values for the field of various events ***/ +/*****************************************************************************/ + +static int +VerbMotion(Fmt *fmt, XEvent *e) { + XMotionEvent *ev = &e->xmotion; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TModState, _(state), + TBool, _(same_screen), + TEnd + ); + //fprintf(stderr, "is_hint=%s%s", IsHint(ev->is_hint), sep); +} + +static int +VerbButton(Fmt *fmt, XEvent *e) { + XButtonEvent *ev = &e->xbutton; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TModState, _(state), + TModState, _(button), + TBool, _(same_screen), + TEnd + ); +} + +static int +VerbColormap(Fmt *fmt, XEvent *e) { + XColormapEvent *ev = &e->xcolormap; + + return pevent(fmt, ev, + TWindow, _(window), + TIntNone, _(colormap), + TBool, _(new), + TColMap, _(state), + TEnd + ); +} + +static int +VerbCrossing(Fmt *fmt, XEvent *e) { + XCrossingEvent *ev = &e->xcrossing; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TGrabMode, _(mode), + TXing, _(detail), + TBool, _(same_screen), + TBool, _(focus), + TModState, _(state), + TEnd + ); +} + +static int +VerbExpose(Fmt *fmt, XEvent *e) { + XExposeEvent *ev = &e->xexpose; + + return pevent(fmt, ev, + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(count), + TEnd + ); +} + +static int +VerbGraphicsExpose(Fmt *fmt, XEvent *e) { + XGraphicsExposeEvent *ev = &e->xgraphicsexpose; + + return pevent(fmt, ev, + TWindow, _(drawable), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TMajor, _(major_code), + TInt, _(minor_code), + TEnd + ); +} + +static int +VerbNoExpose(Fmt *fmt, XEvent *e) { + XNoExposeEvent *ev = &e->xnoexpose; + + return pevent(fmt, ev, + TWindow, _(drawable), + TMajor, _(major_code), + TInt, _(minor_code), + TEnd + ); +} + +static int +VerbFocus(Fmt *fmt, XEvent *e) { + XFocusChangeEvent *ev = &e->xfocus; + + return pevent(fmt, ev, + TWindow, _(window), + TGrabMode, _(mode), + TFocus, _(detail), + TEnd + ); +} + +static int +VerbKeymap(Fmt *fmt, XEvent *e) { + XKeymapEvent *ev = &e->xkeymap; + int i; + + fmtprint(fmt, "window=0x%x%s", (int)ev->window, sep); + fmtprint(fmt, "key_vector="); + for (i = 0; i < 32; i++) + fmtprint(fmt, "%02x", ev->key_vector[i]); + fmtprint(fmt, "\n"); + return 0; +} + +static int +VerbKey(Fmt *fmt, XEvent *e) { + XKeyEvent *ev = &e->xkey; + + return pevent(fmt, ev, + TWindow, _(window), + TWindow, _(root), + TWindow, _(subwindow), + TTime, _(time), + TInt, _(x), TInt, _(y), + TInt, _(x_root), TInt, _(y_root), + TModState, _(state), + TKeycode, "keycode", ev, + TBool, _(same_screen), + TEnd + ); +} + +static int +VerbProperty(Fmt *fmt, XEvent *e) { + XPropertyEvent *ev = &e->xproperty; + + return pevent(fmt, ev, + TWindow, _(window), + TAtom, _(atom), + TTime, _(time), + TPropState, _(state), + TEnd + ); +} + +static int +VerbResizeRequest(Fmt *fmt, XEvent *e) { + XResizeRequestEvent *ev = &e->xresizerequest; + + return pevent(fmt, ev, + TWindow, _(window), + TInt, _(width), TInt, _(height), + TEnd + ); +} + +static int +VerbCirculate(Fmt *fmt, XEvent *e) { + XCirculateEvent *ev = &e->xcirculate; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TPlace, _(place), + TEnd + ); +} + +static int +VerbConfigure(Fmt *fmt, XEvent *e) { + XConfigureEvent *ev = &e->xconfigure; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(border_width), + TIntNone, _(above), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbCreateWindow(Fmt *fmt, XEvent *e) { + XCreateWindowEvent *ev = &e->xcreatewindow; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(border_width), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbDestroyWindow(Fmt *fmt, XEvent *e) { + XDestroyWindowEvent *ev = &e->xdestroywindow; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TEnd + ); +} + +static int +VerbGravity(Fmt *fmt, XEvent *e) { + XGravityEvent *ev = &e->xgravity; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TEnd + ); +} + +static int +VerbMap(Fmt *fmt, XEvent *e) { + XMapEvent *ev = &e->xmap; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbReparent(Fmt *fmt, XEvent *e) { + XReparentEvent *ev = &e->xreparent; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TWindow, _(parent), + TInt, _(x), TInt, _(y), + TBool, _(override_redirect), + TEnd + ); +} + +static int +VerbUnmap(Fmt *fmt, XEvent *e) { + XUnmapEvent *ev = &e->xunmap; + + return pevent(fmt, ev, + TWindow, _(event), + TWindow, _(window), + TBool, _(from_configure), + TEnd + ); +} + +static int +VerbCirculateRequest(Fmt *fmt, XEvent *e) { + XCirculateRequestEvent *ev = &e->xcirculaterequest; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TPlace, _(place), + TEnd + ); +} + +static int +VerbConfigureRequest(Fmt *fmt, XEvent *e) { + XConfigureRequestEvent *ev = &e->xconfigurerequest; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TInt, _(x), TInt, _(y), + TInt, _(width), TInt, _(height), + TInt, _(border_width), + TIntNone, _(above), + TConfDetail, _(detail), + TConfMask, _(value_mask), + TEnd + ); +} + +static int +VerbMapRequest(Fmt *fmt, XEvent *e) { + XMapRequestEvent *ev = &e->xmaprequest; + + return pevent(fmt, ev, + TWindow, _(parent), + TWindow, _(window), + TEnd + ); +} + +static int +VerbClient(Fmt *fmt, XEvent *e) { + XClientMessageEvent *ev = &e->xclient; + + return pevent(fmt, ev, + TWindow, _(window), + TAtom, _(message_type), + TInt, _(format), + TData, "data (as longs)", &ev->data, + TEnd + ); +} + +static int +VerbMapping(Fmt *fmt, XEvent *e) { + XMappingEvent *ev = &e->xmapping; + + return pevent(fmt, ev, + TWindow, _(window), + TMapping, _(request), + TWindow, _(first_keycode), + TWindow, _(count), + TEnd + ); +} + +static int +VerbSelectionClear(Fmt *fmt, XEvent *e) { + XSelectionClearEvent *ev = &e->xselectionclear; + + return pevent(fmt, ev, + TWindow, _(window), + TAtom, _(selection), + TTime, _(time), + TEnd + ); +} + +static int +VerbSelection(Fmt *fmt, XEvent *e) { + XSelectionEvent *ev = &e->xselection; + + return pevent(fmt, ev, + TWindow, _(requestor), + TAtom, _(selection), + TAtom, _(target), + TAtom, _(property), + TTime, _(time), + TEnd + ); +} + +static int +VerbSelectionRequest(Fmt *fmt, XEvent *e) { + XSelectionRequestEvent *ev = &e->xselectionrequest; + + return pevent(fmt, ev, + TWindow, _(owner), + TWindow, _(requestor), + TAtom, _(selection), + TAtom, _(target), + TAtom, _(property), + TTime, _(time), + TEnd + ); +} + +static int +VerbVisibility(Fmt *fmt, XEvent *e) { + XVisibilityEvent *ev = &e->xvisibility; + + return pevent(fmt, ev, + TWindow, _(window), + TVis, _(state), + TEnd + ); +} + +/******************************************************************************/ +/**************** Print the values of all fields for any event ****************/ +/******************************************************************************/ + +typedef struct Handler Handler; +struct Handler { + int key; + int (*fn)(Fmt*, XEvent*); +}; + +int +fmtevent(Fmt *fmt) { + XEvent *e; + XAnyEvent *ev; + /* + fprintf(stderr, "type=%s%s", eventtype(e->xany.type), sep); + fprintf(stderr, "serial=%lu%s", ev->serial, sep); + fprintf(stderr, "send_event=%s%s", TorF(ev->send_event), sep); + fprintf(stderr, "display=0x%p%s", ev->display, sep); + */ + static Handler fns[] = { + {MotionNotify, VerbMotion}, + {ButtonPress, VerbButton}, + {ButtonRelease, VerbButton}, + {ColormapNotify, VerbColormap}, + {EnterNotify, VerbCrossing}, + {LeaveNotify, VerbCrossing}, + {Expose, VerbExpose}, + {GraphicsExpose, VerbGraphicsExpose}, + {NoExpose, VerbNoExpose}, + {FocusIn, VerbFocus}, + {FocusOut, VerbFocus}, + {KeymapNotify, VerbKeymap}, + {KeyPress, VerbKey}, + {KeyRelease, VerbKey}, + {PropertyNotify, VerbProperty}, + {ResizeRequest, VerbResizeRequest}, + {CirculateNotify, VerbCirculate}, + {ConfigureNotify, VerbConfigure}, + {CreateNotify, VerbCreateWindow}, + {DestroyNotify, VerbDestroyWindow}, + {GravityNotify, VerbGravity}, + {MapNotify, VerbMap}, + {ReparentNotify, VerbReparent}, + {UnmapNotify, VerbUnmap}, + {CirculateRequest, VerbCirculateRequest}, + {ConfigureRequest, VerbConfigureRequest}, + {MapRequest, VerbMapRequest}, + {ClientMessage, VerbClient}, + {MappingNotify, VerbMapping}, + {SelectionClear, VerbSelectionClear}, + {SelectionNotify, VerbSelection}, + {SelectionRequest, VerbSelectionRequest}, + {VisibilityNotify, VerbVisibility}, + {0, nil}, + }; + Handler *p; + + e = va_arg(fmt->args, XEvent*); + ev = &e->xany; + + for (p = fns; p->fn; p++) + if (p->key == ev->type) + return p->fn(fmt, e); + return 1; +} + diff --git a/lib/libstuff/printevent.h b/lib/libstuff/printevent.h @@ -0,0 +1,248 @@ +int fmtevent(Fmt *fmt); + +enum { + X_CreateWindow = 1, + X_ChangeWindowAttributes, + X_GetWindowAttributes, + X_DestroyWindow, + X_DestroySubwindows, + X_ChangeSaveSet, + X_ReparentWindow, + X_MapWindow, + X_MapSubwindows, + X_UnmapWindow, + X_UnmapSubwindows, + X_ConfigureWindow, + X_CirculateWindow, + X_GetGeometry, + X_QueryTree, + X_InternAtom, + X_GetAtomName, + X_ChangeProperty, + X_DeleteProperty, + X_GetProperty, + X_ListProperties, + X_SetSelectionOwner, + X_GetSelectionOwner, + X_ConvertSelection, + X_SendEvent, + X_GrabPointer, + X_UngrabPointer, + X_GrabButton, + X_UngrabButton, + X_ChangeActivePointerGrab, + X_GrabKeyboard, + X_UngrabKeyboard, + X_GrabKey, + X_UngrabKey, + X_AllowEvents, + X_GrabServer, + X_UngrabServer, + X_QueryPointer, + X_GetMotionEvents, + X_TranslateCoords, + X_WarpPointer, + X_SetInputFocus, + X_GetInputFocus, + X_QueryKeymap, + X_OpenFont, + X_CloseFont, + X_QueryFont, + X_QueryTextExtents, + X_ListFonts, + X_ListFontsWithInfo, + X_SetFontPath, + X_GetFontPath, + X_CreatePixmap, + X_FreePixmap, + X_CreateGC, + X_ChangeGC, + X_CopyGC, + X_SetDashes, + X_SetClipRectangles, + X_FreeGC, + X_ClearArea, + X_CopyArea, + X_CopyPlane, + X_PolyPoint, + X_PolyLine, + X_PolySegment, + X_PolyRectangle, + X_PolyArc, + X_FillPoly, + X_PolyFillRectangle, + X_PolyFillArc, + X_PutImage, + X_GetImage, + X_PolyText8, + X_PolyText16, + X_ImageText8, + X_ImageText16, + X_CreateColormap, + X_FreeColormap, + X_CopyColormapAndFree, + X_InstallColormap, + X_UninstallColormap, + X_ListInstalledColormaps, + X_AllocColor, + X_AllocNamedColor, + X_AllocColorCells, + X_AllocColorPlanes, + X_FreeColors, + X_StoreColors, + X_StoreNamedColor, + X_QueryColors, + X_LookupColor, + X_CreateCursor, + X_CreateGlyphCursor, + X_FreeCursor, + X_RecolorCursor, + X_QueryBestSize, + X_QueryExtension, + X_ListExtensions, + X_ChangeKeyboardMapping, + X_GetKeyboardMapping, + X_ChangeKeyboardControl, + X_GetKeyboardControl, + X_Bell, + X_ChangePointerControl, + X_GetPointerControl, + X_SetScreenSaver, + X_GetScreenSaver, + X_ChangeHosts, + X_ListHosts, + X_SetAccessControl, + X_SetCloseDownMode, + X_KillClient, + X_RotateProperties, + X_ForceScreenSaver, + X_SetPointerMapping, + X_GetPointerMapping, + X_SetModifierMapping, + X_GetModifierMapping, + X_NoOperation, +}; + +#define XMajors \ + "<nil>",\ + "CreateWindow",\ + "ChangeWindowAttributes",\ + "GetWindowAttributes",\ + "DestroyWindow",\ + "DestroySubwindows",\ + "ChangeSaveSet",\ + "ReparentWindow",\ + "MapWindow",\ + "MapSubwindows",\ + "UnmapWindow",\ + "UnmapSubwindows",\ + "ConfigureWindow",\ + "CirculateWindow",\ + "GetGeometry",\ + "QueryTree",\ + "InternAtom",\ + "GetAtomName",\ + "ChangeProperty",\ + "DeleteProperty",\ + "GetProperty",\ + "ListProperties",\ + "SetSelectionOwner",\ + "GetSelectionOwner",\ + "ConvertSelection",\ + "SendEvent",\ + "GrabPointer",\ + "UngrabPointer",\ + "GrabButton",\ + "UngrabButton",\ + "ChangeActivePointerGrab",\ + "GrabKeyboard",\ + "UngrabKeyboard",\ + "GrabKey",\ + "UngrabKey",\ + "AllowEvents",\ + "GrabServer",\ + "UngrabServer",\ + "QueryPointer",\ + "GetMotionEvents",\ + "TranslateCoords",\ + "WarpPointer",\ + "SetInputFocus",\ + "GetInputFocus",\ + "QueryKeymap",\ + "OpenFont",\ + "CloseFont",\ + "QueryFont",\ + "QueryTextExtents",\ + "ListFonts",\ + "ListFontsWithInfo",\ + "SetFontPath",\ + "GetFontPath",\ + "CreatePixmap",\ + "FreePixmap",\ + "CreateGC",\ + "ChangeGC",\ + "CopyGC",\ + "SetDashes",\ + "SetClipRectangles",\ + "FreeGC",\ + "ClearArea",\ + "CopyArea",\ + "CopyPlane",\ + "PolyPoint",\ + "PolyLine",\ + "PolySegment",\ + "PolyRectangle",\ + "PolyArc",\ + "FillPoly",\ + "PolyFillRectangle",\ + "PolyFillArc",\ + "PutImage",\ + "GetImage",\ + "PolyText8",\ + "PolyText16",\ + "ImageText8",\ + "ImageText16",\ + "CreateColormap",\ + "FreeColormap",\ + "CopyColormapAndFree",\ + "InstallColormap",\ + "UninstallColormap",\ + "ListInstalledColormaps",\ + "AllocColor",\ + "AllocNamedColor",\ + "AllocColorCells",\ + "AllocColorPlanes",\ + "FreeColors",\ + "StoreColors",\ + "StoreNamedColor",\ + "QueryColors",\ + "LookupColor",\ + "CreateCursor",\ + "CreateGlyphCursor",\ + "FreeCursor",\ + "RecolorCursor",\ + "QueryBestSize",\ + "QueryExtension",\ + "ListExtensions",\ + "ChangeKeyboardMapping",\ + "GetKeyboardMapping",\ + "ChangeKeyboardControl",\ + "GetKeyboardControl",\ + "Bell",\ + "ChangePointerControl",\ + "GetPointerControl",\ + "SetScreenSaver",\ + "GetScreenSaver",\ + "ChangeHosts",\ + "ListHosts",\ + "SetAccessControl",\ + "SetCloseDownMode",\ + "KillClient",\ + "RotateProperties",\ + "ForceScreenSaver",\ + "SetPointerMapping",\ + "GetPointerMapping",\ + "SetModifierMapping",\ + "GetModifierMapping",\ + "NoOperation",\ + diff --git a/lib/libstuff/util/_die.c b/lib/libstuff/util/_die.c @@ -0,0 +1,26 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <sys/types.h> +#include <signal.h> +#include <unistd.h> +#include <fmt.h> +#include "util.h" + +void +_die(char *file, int line, char *msg, ...) { + va_list ap; + + va_start(ap, msg); + fprint(2, "%s: dieing at %s:%d: %s\n", + argv0, file, line, + vsxprint(msg, ap)); + va_end(ap); + + kill(getpid(), SIGABRT); + abort(); /* Adds too many frames: + * _die() + * abort() + * raise(SIGABRT) + * kill(getpid(), SIGABRT) + */ +} diff --git a/lib/libstuff/util/backtrace.c b/lib/libstuff/util/backtrace.c @@ -0,0 +1,87 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <signal.h> + +#include <bio.h> +#include <plan9.h> +#undef nelem +#include <debug.h> +#include "util.h" + +#ifdef __linux__ +# define PROGTXT "exe" +#else +# define PROGTXT "file" +#endif + +static void +_backtrace(int pid, char *btarg) { + char *proc, *spid, *gdbcmd; + int fd[3], p[2]; + int status, cmdfd; + + gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX"); + if(pipe(p) < 0) + goto done; + closeexec(p[0]); + + cmdfd = mkstemp(gdbcmd); + if(cmdfd < 0) + goto done; + + fprint(cmdfd, "bt %s\n", btarg); + fprint(cmdfd, "detach\n"); + close(cmdfd); + + fd[0] = open("/dev/null", O_RDONLY); + fd[1] = p[1]; + fd[2] = dup(2); + + proc = sxprint("/proc/%d/" PROGTXT, pid); + spid = sxprint("%d", pid); + if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) { + unlink(gdbcmd); + goto done; + } + + Biobuf bp; + char *s; + + Binit(&bp, p[0], OREAD); + while((s = Brdstr(&bp, '\n', 1))) { + Dprint(DStack, "%s\n", s); + free(s); + } + unlink(gdbcmd); + +done: + free(gdbcmd); + kill(pid, SIGKILL); + waitpid(pid, &status, 0); +} + +void +backtrace(char *btarg) { + int pid; + + /* Fork so we can backtrace the child. Keep this stack + * frame minimal, so the trace is fairly clean. + */ + Debug(DStack) + switch(pid = fork()) { + case -1: + return; + case 0: + kill(getpid(), SIGSTOP); + _exit(0); + default: + _backtrace(pid, btarg); + break; + } + +} diff --git a/lib/libstuff/util/closeexec.c b/lib/libstuff/util/closeexec.c @@ -0,0 +1,12 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <unistd.h> +#include <fcntl.h> +#include "util.h" + +void +closeexec(int fd) { + if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + fatal("can't set %d close on exec: %r", fd); +} diff --git a/lib/libstuff/util/comm.c b/lib/libstuff/util/comm.c @@ -0,0 +1,42 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "util.h" +#include <stuff/x11.h> + + +char** +comm(int cols, char **toka, char **tokb) { + Vector_ptr vec; + char **ret; + int cmp; + + vector_pinit(&vec); + while(*toka || *tokb) { + if(!*toka) + cmp = 1; + else if(!*tokb) + cmp = -1; + else + cmp = strcmp(*toka, *tokb); + if(cmp < 0) { + if(cols & CLeft) + vector_ppush(&vec, *toka); + toka++; + }else if(cmp > 0) { + if(cols & CRight) + vector_ppush(&vec, *tokb); + tokb++; + }else { + if(cols & CCenter) + vector_ppush(&vec, *toka); + toka++; + tokb++; + } + } + vector_ppush(&vec, nil); + ret = strlistdup((char**)vec.ary); + free(vec.ary); + return ret; +} diff --git a/lib/libstuff/util/doublefork.c b/lib/libstuff/util/doublefork.c @@ -0,0 +1,30 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <sys/wait.h> +#include <unistd.h> +#include "util.h" + +int +doublefork(void) { + pid_t pid; + int status; + + switch(pid=fork()) { + case -1: + fatal("Can't fork(): %r"); + case 0: + switch(pid=fork()) { + case -1: + fatal("Can't fork(): %r"); + case 0: + return 0; + default: + exit(0); + } + default: + waitpid(pid, &status, 0); + return pid; + } + /* NOTREACHED */ +} diff --git a/lib/libstuff/util/emalloc.c b/lib/libstuff/util/emalloc.c @@ -0,0 +1,11 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +void * +emalloc(uint size) { + void *ret = malloc(size); + if(!ret) + mfatal("malloc", size); + return ret; +} diff --git a/lib/libstuff/util/emallocz.c b/lib/libstuff/util/emallocz.c @@ -0,0 +1,11 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +void* +emallocz(uint size) { + void *ret = emalloc(size); + memset(ret, 0, size); + return ret; +} diff --git a/lib/libstuff/util/erealloc.c b/lib/libstuff/util/erealloc.c @@ -0,0 +1,11 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +void * +erealloc(void *ptr, uint size) { + void *ret = realloc(ptr, size); + if(!ret) + mfatal("realloc", size); + return ret; +} diff --git a/lib/libstuff/util/estrdup.c b/lib/libstuff/util/estrdup.c @@ -0,0 +1,12 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +char* +estrdup(const char *str) { + void *ret = strdup(str); + if(!ret) + mfatal("strdup", strlen(str)); + return ret; +} diff --git a/lib/libstuff/util/estrndup.c b/lib/libstuff/util/estrndup.c @@ -0,0 +1,15 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +char* +estrndup(const char *str, uint len) { + char *ret; + + len = min(len, strlen(str)); + ret = emalloc(len + 1); + memcpy(ret, str, len); + ret[len] = '\0'; + return ret; +} diff --git a/lib/libstuff/util/fatal.c b/lib/libstuff/util/fatal.c @@ -0,0 +1,39 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <fmt.h> +#include "util.h" + +typedef struct VFmt VFmt; +struct VFmt { + const char *fmt; + va_list args; +}; + +#ifdef VARARGCK +# pragma varargck type "V" VFmt* +#endif + +static int +Vfmt(Fmt *f) { + VFmt *vf; + int i; + + vf = va_arg(f->args, VFmt*); + i = fmtvprint(f, vf->fmt, vf->args); + return i; +} + +void +fatal(const char *fmt, ...) { + VFmt fp; + + fmtinstall('V', Vfmt); + fmtinstall('', Vfmt); + + fp.fmt = fmt; + va_start(fp.args, fmt); + fprint(2, "%s: fatal: %V\n", argv0, &fp); + va_end(fp.args); + + exit(1); +} diff --git a/lib/libstuff/util/freelater.c b/lib/libstuff/util/freelater.c @@ -0,0 +1,15 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +void* +freelater(void *p) { + static char* obj[16]; + static long nobj; + int id; + + id = nobj++ % nelem(obj); + free(obj[id]); + obj[id] = p; + return p; +} diff --git a/lib/libstuff/util/getbase.c b/lib/libstuff/util/getbase.c @@ -0,0 +1,43 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <ctype.h> +#include <string.h> +#include <stuff/util.h> + +#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) +int +getbase(const char **s, long *sign) { + const char *p; + int ret; + + ret = 10; + *sign = 1; + if(**s == '-') { + *sign = -1; + *s += 1; + }else if(**s == '+') + *s += 1; + + p = *s; + if(!strbcmp(p, "0x")) { + *s += 2; + ret = 16; + } + else if(isdigit(p[0])) { + if(p[1] == 'r') { + *s += 2; + ret = p[0] - '0'; + } + else if(isdigit(p[1]) && p[2] == 'r') { + *s += 3; + ret = 10*(p[0]-'0') + (p[1]-'0'); + } + } + else if(p[0] == '0') { + ret = 8; + } + if(ret != 10 && (**s == '-' || **s == '+')) + *sign = 0; + return ret; +} diff --git a/lib/libstuff/util/getint.c b/lib/libstuff/util/getint.c @@ -0,0 +1,14 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/util.h> + +bool +getint(const char *s, int *ret) { + long l; + bool res; + + res = getlong(s, &l); + *ret = l; + return res; +} diff --git a/lib/libstuff/util/getlong.c b/lib/libstuff/util/getlong.c @@ -0,0 +1,23 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <stuff/util.h> + +bool +getlong(const char *s, long *ret) { + const char *end; + char *rend; + int base; + long sign; + + if(s == nil) + return false; + end = s+strlen(s); + base = getbase(&s, &sign); + if(sign == 0) + return false; + + *ret = sign * strtol(s, &rend, base); + return (end == rend); +} diff --git a/lib/libstuff/util/getulong.c b/lib/libstuff/util/getulong.c @@ -0,0 +1,23 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <stuff/util.h> + +bool +getulong(const char *s, ulong *ret) { + const char *end; + char *rend; + int base; + long sign; + + if(s == nil) + return false; + end = s+strlen(s); + base = getbase(&s, &sign); + if(sign < 1) + return false; + + *ret = strtoul(s, &rend, base); + return (end == rend); +} diff --git a/lib/libstuff/util/grep.c b/lib/libstuff/util/grep.c @@ -0,0 +1,22 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + + +void +grep(char **list, Reprog *re, int flags) { + char **p, **q; + int res; + + q = list; + for(p=q; *p; p++) { + res = 0; + if(re) + res = regexec(re, *p, nil, 0); + if(res && !(flags & GInvert) + || !res && (flags & GInvert)) + *q++ = *p; + } + *q = nil; +} diff --git a/lib/libstuff/util/join.c b/lib/libstuff/util/join.c @@ -0,0 +1,22 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <fmt.h> +#include "util.h" + +char* +join(char **list, char *sep) { + Fmt f; + char **p; + + if(fmtstrinit(&f) < 0) + abort(); + + for(p=list; *p; p++) { + if(p != list) + fmtstrcpy(&f, sep); + fmtstrcpy(&f, *p); + } + + return fmtstrflush(&f); +} diff --git a/lib/libstuff/util/max.c b/lib/libstuff/util/max.c @@ -0,0 +1,10 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +int +max(int a, int b) { + if(a > b) + return a; + return b; +} diff --git a/lib/libstuff/util/mfatal.c b/lib/libstuff/util/mfatal.c @@ -0,0 +1,33 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include <unistd.h> +#include "util.h" + +/* Can't malloc */ +void +mfatal(char *name, uint size) { + const char + couldnot[] = ": fatal: Could not ", + paren[] = "() ", + bytes[] = " bytes\n"; + char buf[1024]; + char sizestr[8]; + int i; + + i = sizeof sizestr; + do { + sizestr[--i] = '0' + (size%10); + size /= 10; + } while(size > 0); + + strlcat(buf, argv0, sizeof buf); + strlcat(buf, couldnot, sizeof buf); + strlcat(buf, name, sizeof buf); + strlcat(buf, paren, sizeof buf); + strlcat(buf, sizestr+i, sizeof buf); + strlcat(buf, bytes, sizeof buf); + write(2, buf, strlen(buf)); + + exit(1); +} diff --git a/lib/libstuff/util/min.c b/lib/libstuff/util/min.c @@ -0,0 +1,10 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +int +min(int a, int b) { + if(a < b) + return a; + return b; +} diff --git a/lib/libstuff/util/pathsearch.c b/lib/libstuff/util/pathsearch.c @@ -0,0 +1,32 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <unistd.h> +#include <fmt.h> +#include "util.h" + +char* +pathsearch(const char *path, const char *file, bool slashok) { + char *orig, *p, *s; + + if(!slashok && strchr(file, '/') > file) + file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file); + else if(!strncmp(file, "./", 2)) + file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file+2); + if(file[0] == '/') { + if(access(file, X_OK)) + return strdup(file); + return nil; + } + + orig = estrdup(path ? path : getenv("PATH")); + for(p=orig; (s=strtok(p, ":")); p=nil) { + s = smprint("%s/%s", s, file); + if(!access(s, X_OK)) + break; + free(s); + } + free(orig); + return s; +} diff --git a/lib/libstuff/util/refree.c b/lib/libstuff/util/refree.c @@ -0,0 +1,13 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + +void +refree(Regex *r) { + + free(r->regex); + free(r->regc); + r->regex = nil; + r->regc = nil; +} diff --git a/lib/libstuff/util/reinit.c b/lib/libstuff/util/reinit.c @@ -0,0 +1,16 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + + +void +reinit(Regex *r, char *regx) { + + refree(r); + + if(regx[0] != '\0') { + r->regex = estrdup(regx); + r->regc = regcomp(regx); + } +} diff --git a/lib/libstuff/util/spawn3.c b/lib/libstuff/util/spawn3.c @@ -0,0 +1,43 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <errno.h> +#include <unistd.h> +#include "util.h" + +int +spawn3(int fd[3], const char *file, char *argv[]) { + /* Some ideas from Russ Cox's libthread port. */ + int p[2]; + int pid; + + if(pipe(p) < 0) + return -1; + closeexec(p[1]); + + switch(pid = doublefork()) { + case 0: + dup2(fd[0], 0); + dup2(fd[1], 1); + dup2(fd[2], 2); + + execvp(file, argv); + write(p[1], &errno, sizeof errno); + exit(1); + break; + default: + close(p[1]); + if(read(p[0], &errno, sizeof errno) == sizeof errno) + pid = -1; + close(p[0]); + break; + case -1: /* can't happen */ + break; + } + + close(fd[0]); + /* These could fail if any of these was also a previous fd. */ + close(fd[1]); + close(fd[2]); + return pid; +} diff --git a/lib/libstuff/util/spawn3l.c b/lib/libstuff/util/spawn3l.c @@ -0,0 +1,28 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <fmt.h> +#include "util.h" + +int +spawn3l(int fd[3], const char *file, ...) { + va_list ap; + char **argv; + int i, n; + + va_start(ap, file); + for(n=0; va_arg(ap, char*); n++) + ; + va_end(ap); + + argv = emalloc((n+1) * sizeof *argv); + va_start(ap, file); + quotefmtinstall(); + for(i=0; i <= n; i++) + argv[i] = va_arg(ap, char*); + va_end(ap); + + i = spawn3(fd, file, argv); + free(argv); + return i; +} diff --git a/lib/libstuff/util/stokenize.c b/lib/libstuff/util/stokenize.c @@ -0,0 +1,22 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <string.h> +#include "util.h" + +uint +stokenize(char *res[], uint reslen, char *str, char *delim) { + char *s; + uint i; + + i = 0; + s = str; + while(i < reslen && *s) { + while(strchr(delim, *s)) + *(s++) = '\0'; + if(*s) + res[i++] = s; + while(*s && !strchr(delim, *s)) + s++; + } + return i; +} diff --git a/lib/libstuff/util/strcasestr.c b/lib/libstuff/util/strcasestr.c @@ -0,0 +1,25 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <ctype.h> +#include <stdint.h> +#include <string.h> +#include <strings.h> +#include "util.h" + +/* TODO: Make this UTF-8 compliant. */ +char* +strcasestr(const char *dst, const char *src) { + int dc, sc; + int len; + + len = strlen(src) - 1; + for(; (sc = *src) && *dst; src++) { + sc = tolower(dc); + for(; (dc = *dst); dst++) { + dc = tolower(dc); + if(sc == dc && !strncasecmp(dst+1, src+1, len)) + return (char*)(uintptr_t)dst; + } + } + return nil; +} diff --git a/lib/libstuff/util/strend.c b/lib/libstuff/util/strend.c @@ -0,0 +1,13 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <stuff/util.h> + +char* +strend(char *s, int n) { + int len; + + len = strlen(s); + return s + max(0, len - n); +} diff --git a/lib/libstuff/util/strlcat.c b/lib/libstuff/util/strlcat.c @@ -0,0 +1,26 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +uint +strlcat(char *dst, const char *src, uint size) { + const char *s; + char *d; + int n, len; + + d = dst; + s = src; + n = size; + while(n-- > 0 && *d != '\0') + d++; + len = n; + + while(*s != '\0') { + if(n-- > 0) + *d++ = *s; + s++; + } + if(len > 0) + *d = '\0'; + return size - n - 1; +} diff --git a/lib/libstuff/util/strlcatprint.c b/lib/libstuff/util/strlcatprint.c @@ -0,0 +1,19 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include <fmt.h> +#include "util.h" + +int +strlcatprint(char *buf, int len, const char *fmt, ...) { + va_list ap; + int buflen; + int ret; + + va_start(ap, fmt); + buflen = strlen(buf); + ret = vsnprint(buf+buflen, len-buflen, fmt, ap); + va_end(ap); + return ret; +} diff --git a/lib/libstuff/util/sxprint.c b/lib/libstuff/util/sxprint.c @@ -0,0 +1,14 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +char* +sxprint(const char *fmt, ...) { + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = vsxprint(fmt, ap); + va_end(ap); + return ret; +} diff --git a/lib/libstuff/util/tokenize.c b/lib/libstuff/util/tokenize.c @@ -0,0 +1,21 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +uint +tokenize(char *res[], uint reslen, char *str, char delim) { + char *s; + uint i; + + i = 0; + s = str; + while(i < reslen && *s) { + while(*s == delim) + *(s++) = '\0'; + if(*s) + res[i++] = s; + while(*s && *s != delim) + s++; + } + return i; +} diff --git a/lib/libstuff/util/uniq.c b/lib/libstuff/util/uniq.c @@ -0,0 +1,18 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "util.h" + +void +uniq(char **toks) { + char **p, **q; + + q = toks; + if(*q == nil) + return; + for(p=q+1; *p; p++) + if(strcmp(*q, *p)) + *++q = *p; + *++q = nil; +} diff --git a/lib/libstuff/util/unquote.c b/lib/libstuff/util/unquote.c @@ -0,0 +1,38 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "util.h" + +int +unquote(char *buf, char *toks[], int ntoks) { + char *s, *t; + bool inquote; + int n; + + n = 0; + s = buf; + while(*s && n < ntoks) { + while(*s && utfrune(" \t\r\n", *s)) + s++; + inquote = false; + toks[n] = s; + t = s; + while(*s && (inquote || !utfrune(" \t\r\n", *s))) { + if(*s == '\'') { + if(inquote && s[1] == '\'') + *t++ = *s++; + else + inquote = !inquote; + } + else + *t++ = *s; + s++; + } + if(*s) + s++; + *t = '\0'; + if(s != toks[n]) + n++; + } + return n; +} diff --git a/lib/libstuff/util/utflcpy.c b/lib/libstuff/util/utflcpy.c @@ -0,0 +1,11 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include "util.h" + +int +utflcpy(char *to, const char *from, int l) { + char *p; + + p = utfecpy(to, to+l, from); + return p-to; +} diff --git a/lib/libstuff/util/util.h b/lib/libstuff/util/util.h @@ -0,0 +1,5 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <stuff/util.h> + +void mfatal(char*, uint); diff --git a/lib/libstuff/util/vector.c b/lib/libstuff/util/vector.c @@ -0,0 +1,33 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "util.h" + +/* Blech. */ +#define VECTOR(type, nam, c) \ +void \ +vector_##c##init(Vector_##nam *v) { \ + memset(v, 0, sizeof *v); \ +} \ + \ +void \ +vector_##c##free(Vector_##nam *v) { \ + free(v->ary); \ + memset(v, 0, sizeof *v); \ +} \ + \ +void \ +vector_##c##push(Vector_##nam *v, type val) { \ + if(v->n == v->size) { \ + if(v->size == 0) \ + v->size = 2; \ + v->size <<= 2; \ + v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \ + } \ + v->ary[v->n++] = val; \ +} \ + +VECTOR(long, long, l) +VECTOR(Rectangle, rect, r) +VECTOR(void*, ptr, p) diff --git a/lib/libstuff/util/vsxprint.c b/lib/libstuff/util/vsxprint.c @@ -0,0 +1,13 @@ +/* Written by Kris Maglione <maglione.k at Gmail> */ +/* Public domain */ +#include <fmt.h> +#include "util.h" + +char* +vsxprint(const char *fmt, va_list ap) { + char *s; + + s = vsmprint(fmt, ap); + freelater(s); + return s; +} diff --git a/lib/libstuff/x11/colors/loadcolor.c b/lib/libstuff/x11/colors/loadcolor.c @@ -0,0 +1,18 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +bool +loadcolor(CTuple *c, char *str) { + char buf[24]; + + utflcpy(buf, str, sizeof buf); + memcpy(c->colstr, str, sizeof c->colstr); + + buf[7] = buf[15] = buf[23] = '\0'; + return namedcolor(buf, &c->fg) + && namedcolor(buf+8, &c->bg) + && namedcolor(buf+16, &c->border); +} diff --git a/lib/libstuff/x11/colors/namedcolor.c b/lib/libstuff/x11/colors/namedcolor.c @@ -0,0 +1,22 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +bool +namedcolor(char *name, Color *ret) { + XColor c, c2; + + if(XAllocNamedColor(display, scr.colormap, name, &c, &c2)) { + *ret = (Color) { + c.pixel, { + c.red, + c.green, + c.blue, + 0xffff + }, + }; + return true; + } + return false; +} diff --git a/lib/libstuff/x11/colors/xftcolor.c b/lib/libstuff/x11/colors/xftcolor.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XftColor* +xftcolor(Color col) { + XftColor *c; + + c = emallocz(sizeof *c); + *c = (XftColor) { + ((col.render.alpha&0xff00) << 24) + | ((col.render.red&0xff00) << 8) + | ((col.render.green&0xff00) << 0) + | ((col.render.blue&0xff00) >> 8), + col.render + }; + return freelater(c); +} diff --git a/lib/libstuff/x11/convpts.c b/lib/libstuff/x11/convpts.c @@ -0,0 +1,17 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +XPoint* +convpts(Point *pt, int np) { + XPoint *rp; + int i; + + rp = emalloc(np * sizeof *rp); + for(i = 0; i < np; i++) { + rp[i].x = pt[i].x; + rp[i].y = pt[i].y; + } + return rp; +} diff --git a/lib/libstuff/x11/drawing/border.c b/lib/libstuff/x11/drawing/border.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +border(Image *dst, Rectangle r, int w, Color col) { + if(w == 0) + return; + + r = insetrect(r, w/2); + r.max.x -= w%2; + r.max.y -= w%2; + + XSetLineAttributes(display, dst->gc, w, LineSolid, CapButt, JoinMiter); + setgccol(dst, col); + XDrawRectangle(display, dst->xid, dst->gc, + r.min.x, r.min.y, Dx(r), Dy(r)); +} diff --git a/lib/libstuff/x11/drawing/drawline.c b/lib/libstuff/x11/drawing/drawline.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +drawline(Image *dst, Point p1, Point p2, int cap, int w, Color col) { + XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); + setgccol(dst, col); + XDrawLine(display, dst->xid, dst->gc, p1.x, p1.y, p2.x, p2.y); +} diff --git a/lib/libstuff/x11/drawing/drawpoly.c b/lib/libstuff/x11/drawing/drawpoly.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +drawpoly(Image *dst, Point *pt, int np, int cap, int w, Color col) { + XPoint *xp; + + xp = convpts(pt, np); + XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); + setgccol(dst, col); + XDrawLines(display, dst->xid, dst->gc, xp, np, CoordModeOrigin); + free(xp); +} diff --git a/lib/libstuff/x11/drawing/drawstring.c b/lib/libstuff/x11/drawing/drawstring.c @@ -0,0 +1,89 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +uint +drawstring(Image *dst, Font *font, + Rectangle r, Align align, + char *text, Color col) { + Rectangle tr; + char *buf; + uint x, y, width, height, len; + int shortened; + + shortened = 0; + + len = strlen(text); + buf = emalloc(len+1); + memcpy(buf, text, len+1); + + r.max.y -= font->pad.min.y; + r.min.y += font->pad.max.y; + + height = font->ascent + font->descent; + y = r.min.y + Dy(r) / 2 - height / 2 + font->ascent; + + width = Dx(r) - font->pad.min.x - font->pad.max.x - (font->height & ~1); + + r.min.x += font->pad.min.x; + r.max.x -= font->pad.max.x; + + /* shorten text if necessary */ + tr = ZR; + while(len > 0) { + tr = textextents_l(font, buf, len + min(shortened, 3), nil); + if(Dx(tr) <= width) + break; + while(len > 0 && (buf[--len]&0xC0) == 0x80) + buf[len] = '.'; + buf[len] = '.'; + shortened++; + } + + if(len == 0 || Dx(tr) > width) + goto done; + + /* mark shortened info in the string */ + if(shortened) + len += min(shortened, 3); + + switch (align) { + case East: + x = r.max.x - (tr.max.x + (font->height / 2)); + break; + case Center: + x = r.min.x + (Dx(r) - Dx(tr)) / 2 - tr.min.x; + break; + default: + x = r.min.x + (font->height / 2) - tr.min.x; + break; + } + + setgccol(dst, col); + switch(font->type) { + case FFontSet: + Xutf8DrawString(display, dst->xid, + font->font.set, dst->gc, + x, y, + buf, len); + break; + case FXft: + xft->drawstring(xftdrawable(dst), xftcolor(col), + font->font.xft, + x, y, buf, len); + break; + case FX11: + XSetFont(display, dst->gc, font->font.x11->fid); + XDrawString(display, dst->xid, dst->gc, + x, y, buf, len); + break; + default: + die("Invalid font type."); + } + +done: + free(buf); + return Dx(tr); +} diff --git a/lib/libstuff/x11/drawing/fill.c b/lib/libstuff/x11/drawing/fill.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +fill(Image *dst, Rectangle r, Color col) { + setgccol(dst, col); + XFillRectangle(display, dst->xid, dst->gc, + r.min.x, r.min.y, Dx(r), Dy(r)); +} diff --git a/lib/libstuff/x11/drawing/fillpoly.c b/lib/libstuff/x11/drawing/fillpoly.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +fillpoly(Image *dst, Point *pt, int np, Color col) { + XPoint *xp; + + xp = convpts(pt, np); + setgccol(dst, col); + XFillPolygon(display, dst->xid, dst->gc, xp, np, Complex, CoordModeOrigin); + free(xp); +} diff --git a/lib/libstuff/x11/errors.c b/lib/libstuff/x11/errors.c @@ -0,0 +1,40 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +extern ErrorCode ignored_xerrors[]; +static bool _trap_errors; +static long nerrors; + +int +errorhandler(Display *dpy, XErrorEvent *error) { + ErrorCode *e; + + USED(dpy); + + if(_trap_errors) + nerrors++; + + e = ignored_xerrors; + if(e) + for(; e->rcode || e->ecode; e++) + if((e->rcode == 0 || e->rcode == error->request_code) + && (e->ecode == 0 || e->ecode == error->error_code)) + return 0; + + fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n", + argv0, error->request_code, error->error_code); + return xlib_errorhandler(display, error); /* calls exit() */ +} + +int +traperrors(bool enable) { + + sync(); + _trap_errors = enable; + if (enable) + nerrors = 0; + return nerrors; + +} diff --git a/lib/libstuff/x11/focus/getfocus.c b/lib/libstuff/x11/focus/getfocus.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XWindow +getfocus(void) { + XWindow ret; + int revert; + + XGetInputFocus(display, &ret, &revert); + return ret; +} diff --git a/lib/libstuff/x11/focus/setfocus.c b/lib/libstuff/x11/focus/setfocus.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setfocus(Window *w, int mode) { + XSetInputFocus(display, w->xid, mode, CurrentTime); +} diff --git a/lib/libstuff/x11/freestringlist.c b/lib/libstuff/x11/freestringlist.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +freestringlist(char *list[]) { + XFreeStringList(list); +} diff --git a/lib/libstuff/x11/geometry/XRect.c b/lib/libstuff/x11/geometry/XRect.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XRectangle +XRect(Rectangle r) { + XRectangle xr; + + xr.x = r.min.x; + xr.y = r.min.y; + xr.width = Dx(r); + xr.height = Dy(r); + return xr; +} diff --git a/lib/libstuff/x11/geometry/addpt.c b/lib/libstuff/x11/geometry/addpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +addpt(Point p, Point q) { + p.x += q.x; + p.y += q.y; + return p; +} diff --git a/lib/libstuff/x11/geometry/divpt.c b/lib/libstuff/x11/geometry/divpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +divpt(Point p, Point q) { + p.x /= q.x; + p.y /= q.y; + return p; +} diff --git a/lib/libstuff/x11/geometry/eqpt.c b/lib/libstuff/x11/geometry/eqpt.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +eqpt(Point p, Point q) { + return p.x==q.x && p.y==q.y; +} diff --git a/lib/libstuff/x11/geometry/eqrect.c b/lib/libstuff/x11/geometry/eqrect.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +eqrect(Rectangle a, Rectangle b) { + return a.min.x==b.min.x && a.max.x==b.max.x + && a.min.y==b.min.y && a.max.y==b.max.y; +} diff --git a/lib/libstuff/x11/geometry/insetrect.c b/lib/libstuff/x11/geometry/insetrect.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +insetrect(Rectangle r, int n) { + r.min.x += n; + r.min.y += n; + r.max.x -= n; + r.max.y -= n; + return r; +} diff --git a/lib/libstuff/x11/geometry/mulpt.c b/lib/libstuff/x11/geometry/mulpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +mulpt(Point p, Point q) { + p.x *= q.x; + p.y *= q.y; + return p; +} diff --git a/lib/libstuff/x11/geometry/rectaddpt.c b/lib/libstuff/x11/geometry/rectaddpt.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +rectaddpt(Rectangle r, Point p) { + r.min.x += p.x; + r.max.x += p.x; + r.min.y += p.y; + r.max.y += p.y; + return r; +} diff --git a/lib/libstuff/x11/geometry/rectsetorigin.c b/lib/libstuff/x11/geometry/rectsetorigin.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +rectsetorigin(Rectangle r, Point p) { + Rectangle ret; + + ret.min.x = p.x; + ret.min.y = p.y; + ret.max.x = p.x + Dx(r); + ret.max.y = p.y + Dy(r); + return ret; +} diff --git a/lib/libstuff/x11/geometry/rectsubpt.c b/lib/libstuff/x11/geometry/rectsubpt.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +rectsubpt(Rectangle r, Point p) { + r.min.x -= p.x; + r.max.x -= p.x; + r.min.y -= p.y; + r.max.y -= p.y; + return r; +} diff --git a/lib/libstuff/x11/geometry/subpt.c b/lib/libstuff/x11/geometry/subpt.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +subpt(Point p, Point q) { + p.x -= q.x; + p.y -= q.y; + return p; +} diff --git a/lib/libstuff/x11/ignored_xerrors.c b/lib/libstuff/x11/ignored_xerrors.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +ErrorCode ignored_xerrors[] = { + { 0, }, +}; + diff --git a/lib/libstuff/x11/images/allocimage.c b/lib/libstuff/x11/images/allocimage.c @@ -0,0 +1,21 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Image* +allocimage(int w, int h, int depth) { + Image *img; + + img = emallocz(sizeof *img); + img->type = WImage; + img->xid = XCreatePixmap(display, scr.root.xid, w, h, depth); + img->gc = XCreateGC(display, img->xid, 0, nil); + img->colormap = scr.colormap; + img->visual = scr.visual; + if(depth == 32) + img->visual = scr.visual32; + img->depth = depth; + img->r = Rect(0, 0, w, h); + return img; +} diff --git a/lib/libstuff/x11/images/copyimage.c b/lib/libstuff/x11/images/copyimage.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +copyimage(Image *dst, Rectangle r, Image *src, Point p) { + XCopyArea(display, + src->xid, dst->xid, + dst->gc, + r.min.x, r.min.y, Dx(r), Dy(r), + p.x, p.y); +} diff --git a/lib/libstuff/x11/images/freeimage.c b/lib/libstuff/x11/images/freeimage.c @@ -0,0 +1,18 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +freeimage(Image *img) { + if(img == nil) + return; + + assert(img->type == WImage); + + if(img->xft) + xft->drawdestroy(img->xft); + XFreePixmap(display, img->xid); + XFreeGC(display, img->gc); + free(img); +} diff --git a/lib/libstuff/x11/images/xftdrawable.c b/lib/libstuff/x11/images/xftdrawable.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +XftDraw* +xftdrawable(Image *img) { + if(img->xft == nil) + img->xft = xft->drawcreate(display, img->xid, img->visual, img->colormap); + return img->xft; +} diff --git a/lib/libstuff/x11/initdisplay.c b/lib/libstuff/x11/initdisplay.c @@ -0,0 +1,84 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +int (*xlib_errorhandler) (Display*, XErrorEvent*); + +Map windowmap; +Map atommap; +MapEnt* wbucket[137]; +MapEnt* abucket[137]; + +static int +Afmt(Fmt *f) { + Atom a; + char *s; + int i; + + a = va_arg(f->args, Atom); + s = XGetAtomName(display, a); + i = fmtprint(f, "%s", s); + free(s); + return i; +} + +static int +Pfmt(Fmt *f) { + Point p; + + p = va_arg(f->args, Point); + return fmtprint(f, "(%d,%d)", p.x, p.y); +} + +static int +Rfmt(Fmt *f) { + Rectangle r; + + r = va_arg(f->args, Rectangle); + return fmtprint(f, "%P+%dx%d", r.min, Dx(r), Dy(r)); +} + +static int +Wfmt(Fmt *f) { + Window *w; + + w = va_arg(f->args, Window*); + return fmtprint(f, "0x%ulx", w->xid); +} + +void +initdisplay(void) { + display = XOpenDisplay(nil); + if(display == nil) + fatal("Can't open display"); + scr.screen = DefaultScreen(display); + scr.colormap = DefaultColormap(display, scr.screen); + scr.visual = DefaultVisual(display, scr.screen); + scr.visual32 = DefaultVisual(display, scr.screen); + scr.gc = DefaultGC(display, scr.screen); + scr.depth = DefaultDepth(display, scr.screen); + + scr.white = WhitePixel(display, scr.screen); + scr.black = BlackPixel(display, scr.screen); + + scr.root.xid = RootWindow(display, scr.screen); + scr.root.r = Rect(0, 0, + DisplayWidth(display, scr.screen), + DisplayHeight(display, scr.screen)); + scr.rect = scr.root.r; + + scr.root.parent = &scr.root; + + windowmap.bucket = wbucket; + windowmap.nhash = nelem(wbucket); + atommap.bucket = abucket; + atommap.nhash = nelem(abucket); + + fmtinstall('A', Afmt); + fmtinstall('R', Rfmt); + fmtinstall('P', Pfmt); + fmtinstall('W', Wfmt); + + xlib_errorhandler = XSetErrorHandler(errorhandler); +} diff --git a/lib/libstuff/x11/insanity/gravitate.c b/lib/libstuff/x11/insanity/gravitate.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +gravitate(Rectangle rc, Rectangle rf, Point grav) { + Point d; + + /* Get delta between frame and client rectangles */ + d = subpt(subpt(rf.max, rf.min), + subpt(rc.max, rc.min)); + + /* Divide by 2 and apply gravity */ + d = divpt(d, Pt(2, 2)); + d = mulpt(d, grav); + + return rectsubpt(rc, d); +} diff --git a/lib/libstuff/x11/insanity/sethints.c b/lib/libstuff/x11/insanity/sethints.c @@ -0,0 +1,100 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +void +sethints(Window *w) { + XSizeHints xs; + XWMHints *wmh; + WinHints *h; + Point p; + long size; + + if(w->hints == nil) + w->hints = emalloc(sizeof *h); + + h = w->hints; + memset(h, 0, sizeof *h); + + h->max = Pt(INT_MAX, INT_MAX); + h->inc = Pt(1,1); + + wmh = XGetWMHints(display, w->xid); + if(wmh) { + if(wmh->flags & WindowGroupHint) + h->group = wmh->window_group; + free(wmh); + } + + if(!XGetWMNormalHints(display, w->xid, &xs, &size)) + return; + + if(xs.flags & PMinSize) { + h->min.x = xs.min_width; + h->min.y = xs.min_height; + } + if(xs.flags & PMaxSize) { + h->max.x = xs.max_width; + h->max.y = xs.max_height; + } + + /* Goddamn buggy clients. */ + if(h->max.x < h->min.x) + h->max.x = h->min.x; + if(h->max.y < h->min.y) + h->max.y = h->min.y; + + h->base = h->min; + if(xs.flags & PBaseSize) { + p.x = xs.base_width; + p.y = xs.base_height; + h->base = p; + h->baspect = p; + } + + if(xs.flags & PResizeInc) { + h->inc.x = max(xs.width_inc, 1); + h->inc.y = max(xs.height_inc, 1); + } + + if(xs.flags & PAspect) { + h->aspect.min.x = xs.min_aspect.x; + h->aspect.min.y = xs.min_aspect.y; + h->aspect.max.x = xs.max_aspect.x; + h->aspect.max.y = xs.max_aspect.y; + } + + h->position = (xs.flags & (USPosition|PPosition)) != 0; + + if(!(xs.flags & PWinGravity)) + xs.win_gravity = NorthWestGravity; + p = ZP; + switch (xs.win_gravity) { + case EastGravity: + case CenterGravity: + case WestGravity: + p.y = 1; + break; + case SouthEastGravity: + case SouthGravity: + case SouthWestGravity: + p.y = 2; + break; + } + switch (xs.win_gravity) { + case NorthGravity: + case CenterGravity: + case SouthGravity: + p.x = 1; + break; + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + p.x = 2; + break; + } + h->grav = p; + h->gravstatic = (xs.win_gravity == StaticGravity); +} diff --git a/lib/libstuff/x11/insanity/sizehint.c b/lib/libstuff/x11/insanity/sizehint.c @@ -0,0 +1,42 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +sizehint(WinHints *h, Rectangle r) { + Point p, aspect, origin; + + if(h == nil) + return r; + + origin = r.min; + r = rectsubpt(r, origin); + + /* Min/max */ + r.max.x = max(r.max.x, h->min.x); + r.max.y = max(r.max.y, h->min.y); + r.max.x = min(r.max.x, h->max.x); + r.max.y = min(r.max.y, h->max.y); + + /* Increment */ + p = subpt(r.max, h->base); + r.max.x -= p.x % h->inc.x; + r.max.y -= p.y % h->inc.y; + + /* Aspect */ + p = subpt(r.max, h->baspect); + p.y = max(p.y, 1); + + aspect = h->aspect.min; + if(p.x * aspect.y / p.y < aspect.x) + r.max.y = h->baspect.y + + p.x * aspect.y / aspect.x; + + aspect = h->aspect.max; + if(p.x * aspect.y / p.y > aspect.x) + r.max.x = h->baspect.x + + p.y * aspect.x / aspect.y; + + return rectaddpt(r, origin); +} diff --git a/lib/libstuff/x11/keyboard/grabkeyboard.c b/lib/libstuff/x11/keyboard/grabkeyboard.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +grabkeyboard(Window *w) { + + return XGrabKeyboard(display, w->xid, true /* owner events */, + GrabModeAsync, GrabModeAsync, CurrentTime + ) == GrabSuccess; +} diff --git a/lib/libstuff/x11/keyboard/ungrabkeyboard.c b/lib/libstuff/x11/keyboard/ungrabkeyboard.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +ungrabkeyboard(void) { + XUngrabKeyboard(display, CurrentTime); +} diff --git a/lib/libstuff/x11/keys/keycode.c b/lib/libstuff/x11/keys/keycode.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +KeyCode +keycode(char *name) { + return XKeysymToKeycode(display, XStringToKeysym(name)); +} diff --git a/lib/libstuff/x11/keys/parsekey.c b/lib/libstuff/x11/keys/parsekey.c @@ -0,0 +1,46 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +typedef struct KMask KMask; + +static struct KMask { + int mask; + const char* name; +} masks[] = { + {ShiftMask, "Shift"}, + {ControlMask, "Control"}, + {Mod1Mask, "Mod1"}, + {Mod2Mask, "Mod2"}, + {Mod3Mask, "Mod3"}, + {Mod4Mask, "Mod4"}, + {Mod5Mask, "Mod5"}, + {0,} +}; + +bool +parsekey(char *str, int *mask, char **key) { + static char *keys[16]; + KMask *m; + int i, nkeys; + + *mask = 0; + nkeys = tokenize(keys, nelem(keys), str, '-'); + for(i=0; i < nkeys; i++) { + for(m=masks; m->mask; m++) + if(!strcasecmp(m->name, keys[i])) { + *mask |= m->mask; + goto next; + } + break; + next: continue; + } + if(key) { + if(nkeys) + *key = keys[i]; + return i == nkeys - 1; + } + else + return i == nkeys; +} diff --git a/lib/libstuff/x11/mouse/grabpointer.c b/lib/libstuff/x11/mouse/grabpointer.c @@ -0,0 +1,16 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +grabpointer(Window *w, Window *confine, Cursor cur, int mask) { + XWindow cw; + + cw = None; + if(confine) + cw = confine->xid; + return XGrabPointer(display, w->xid, false /* owner events */, mask, + GrabModeAsync, GrabModeAsync, cw, cur, CurrentTime + ) == GrabSuccess; +} diff --git a/lib/libstuff/x11/mouse/pointerscreen.c b/lib/libstuff/x11/mouse/pointerscreen.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +pointerscreen(void) { + XWindow win; + Point pt; + uint ui; + int i; + + return XQueryPointer(display, scr.root.xid, &win, &win, &i, &i, + &pt.x, &pt.y, &ui); +} diff --git a/lib/libstuff/x11/mouse/querypointer.c b/lib/libstuff/x11/mouse/querypointer.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +querypointer(Window *w) { + XWindow win; + Point pt; + uint ui; + int i; + + XQueryPointer(display, w->xid, &win, &win, &i, &i, &pt.x, &pt.y, &ui); + return pt; +} diff --git a/lib/libstuff/x11/mouse/translate.c b/lib/libstuff/x11/mouse/translate.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Point +translate(Window *src, Window *dst, Point sp) { + Point pt; + XWindow w; + + XTranslateCoordinates(display, src->xid, dst->xid, sp.x, sp.y, + &pt.x, &pt.y, &w); + return pt; +} diff --git a/lib/libstuff/x11/mouse/ungrabpointer.c b/lib/libstuff/x11/mouse/ungrabpointer.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +ungrabpointer(void) { + XUngrabPointer(display, CurrentTime); +} diff --git a/lib/libstuff/x11/mouse/warppointer.c b/lib/libstuff/x11/mouse/warppointer.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +warppointer(Point pt) { + /* Nasty kludge for xephyr, xnest. */ + static int havereal = -1; + static char* real; + + if(havereal == -1) { + real = getenv("REALDISPLAY"); + havereal = real != nil; + } + if(havereal) + system(sxprint("DISPLAY=%s wiwarp %d %d", real, pt.x, pt.y)); + + XWarpPointer(display, + /* src, dest w */ None, scr.root.xid, + /* src_rect */ 0, 0, 0, 0, + /* target */ pt.x, pt.y); +} diff --git a/lib/libstuff/x11/properties/changeprop_char.c b/lib/libstuff/x11/properties/changeprop_char.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_char(Window *w, char *prop, char *type, char data[], int len) { + changeproperty(w, prop, type, 8, (uchar*)data, len); +} diff --git a/lib/libstuff/x11/properties/changeprop_long.c b/lib/libstuff/x11/properties/changeprop_long.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_long(Window *w, char *prop, char *type, long data[], int len) { + changeproperty(w, prop, type, 32, (uchar*)data, len); +} diff --git a/lib/libstuff/x11/properties/changeprop_short.c b/lib/libstuff/x11/properties/changeprop_short.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_short(Window *w, char *prop, char *type, short data[], int len) { + changeproperty(w, prop, type, 16, (uchar*)data, len); +} diff --git a/lib/libstuff/x11/properties/changeprop_string.c b/lib/libstuff/x11/properties/changeprop_string.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +void +changeprop_string(Window *w, char *prop, char *string) { + changeprop_char(w, prop, "UTF8_STRING", string, strlen(string)); +} diff --git a/lib/libstuff/x11/properties/changeprop_textlist.c b/lib/libstuff/x11/properties/changeprop_textlist.c @@ -0,0 +1,24 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +void +changeprop_textlist(Window *w, char *prop, char *type, char *data[]) { + char **p, *s, *t; + int len, n; + + len = 0; + for(p=data; *p; p++) + len += strlen(*p) + 1; + s = emalloc(len); + t = s; + for(p=data; *p; p++) { + n = strlen(*p) + 1; + memcpy(t, *p, n); + t += n; + } + changeprop_char(w, prop, type, s, len); + free(s); +} diff --git a/lib/libstuff/x11/properties/changeprop_ulong.c b/lib/libstuff/x11/properties/changeprop_ulong.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeprop_ulong(Window *w, char *prop, char *type, ulong data[], int len) { + changeproperty(w, prop, type, 32, (uchar*)data, len); +} diff --git a/lib/libstuff/x11/properties/changeproperty.c b/lib/libstuff/x11/properties/changeproperty.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +changeproperty(Window *w, char *prop, char *type, + int width, uchar data[], int n) { + XChangeProperty(display, w->xid, xatom(prop), xatom(type), width, + PropModeReplace, data, n); +} diff --git a/lib/libstuff/x11/properties/delproperty.c b/lib/libstuff/x11/properties/delproperty.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +delproperty(Window *w, char *prop) { + XDeleteProperty(display, w->xid, xatom(prop)); +} diff --git a/lib/libstuff/x11/properties/getprop.c b/lib/libstuff/x11/properties/getprop.c @@ -0,0 +1,28 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getprop(Window *w, char *prop, char *type, Atom *actual, int *format, + ulong offset, uchar **ret, ulong length) { + Atom typea; + ulong n, extra; + int status; + + typea = (type ? xatom(type) : 0L); + + status = XGetWindowProperty(display, w->xid, + xatom(prop), offset, length, false /* delete */, + typea, actual, format, &n, &extra, ret); + + if(status != Success) { + *ret = nil; + return 0; + } + if(n == 0) { + free(*ret); + *ret = nil; + } + return n; +} diff --git a/lib/libstuff/x11/properties/getprop_long.c b/lib/libstuff/x11/properties/getprop_long.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getprop_long(Window *w, char *prop, char *type, + ulong offset, long **ret, ulong length) { + Atom actual; + ulong n; + int format; + + n = getprop(w, prop, type, &actual, &format, offset, (uchar**)ret, length); + if(n == 0 || format == 32 && xatom(type) == actual) + return n; + free(*ret); + *ret = 0; + return 0; +} diff --git a/lib/libstuff/x11/properties/getprop_string.c b/lib/libstuff/x11/properties/getprop_string.c @@ -0,0 +1,19 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +char* +getprop_string(Window *w, char *name) { + char **list, *str; + int n; + + str = nil; + + n = getprop_textlist(w, name, &list); + if(n > 0) + str = estrdup(*list); + freestringlist(list); + + return str; +} diff --git a/lib/libstuff/x11/properties/getprop_textlist.c b/lib/libstuff/x11/properties/getprop_textlist.c @@ -0,0 +1,22 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +getprop_textlist(Window *w, char *name, char **ret[]) { + XTextProperty prop; + char **list; + int n; + + *ret = nil; + n = 0; + + XGetTextProperty(display, w->xid, &prop, xatom(name)); + if(prop.nitems > 0) { + if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success) + *ret = list; + XFree(prop.value); + } + return n; +} diff --git a/lib/libstuff/x11/properties/getprop_ulong.c b/lib/libstuff/x11/properties/getprop_ulong.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getprop_ulong(Window *w, char *prop, char *type, + ulong offset, ulong **ret, ulong length) { + return getprop_long(w, prop, type, offset, (long**)ret, length); +} diff --git a/lib/libstuff/x11/properties/getproperty.c b/lib/libstuff/x11/properties/getproperty.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +ulong +getproperty(Window *w, char *prop, char *type, Atom *actual, + ulong offset, uchar **ret, ulong length) { + int format; + + return getprop(w, prop, type, actual, &format, offset, ret, length); +} diff --git a/lib/libstuff/x11/properties/strlistdup.c b/lib/libstuff/x11/properties/strlistdup.c @@ -0,0 +1,29 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +char** +strlistdup(char *list[]) { + char **p; + char *q; + int i, m, n; + + n = 0; + m = 0; + for(p=list; *p; p++, n++) + m += strlen(*p) + 1; + + p = malloc((n+1) * sizeof(*p) + m); + q = (char*)&p[n+1]; + + for(i=0; i < n; i++) { + p[i] = q; + m = strlen(list[i]) + 1; + memcpy(q, list[i], m); + q += m; + } + p[n] = nil; + return p; +} diff --git a/lib/libstuff/x11/sendevent.c b/lib/libstuff/x11/sendevent.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +sendevent(Window *w, bool propegate, long mask, XEvent *e) { + XSendEvent(display, w->xid, propegate, mask, e); +} diff --git a/lib/libstuff/x11/sendmessage.c b/lib/libstuff/x11/sendmessage.c @@ -0,0 +1,20 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +sendmessage(Window *w, char *name, long l0, long l1, long l2, long l3, long l4) { + XClientMessageEvent e; + + e.type = ClientMessage; + e.window = w->xid; + e.message_type = xatom(name); + e.format = 32; + e.data.l[0] = l0; + e.data.l[1] = l1; + e.data.l[2] = l2; + e.data.l[3] = l3; + e.data.l[4] = l4; + sendevent(w, false, NoEventMask, (XEvent*)&e); +} diff --git a/lib/libstuff/x11/setgccol.c b/lib/libstuff/x11/setgccol.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +setgccol(Image *dst, Color col) { + XSetForeground(display, dst->gc, col.pixel); +} diff --git a/lib/libstuff/x11/shape/setshapemask.c b/lib/libstuff/x11/shape/setshapemask.c @@ -0,0 +1,11 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setshapemask(Window *dst, Image *src, Point pt) { + /* Assumes that we have the shape extension... */ + XShapeCombineMask (display, dst->xid, + ShapeBounding, pt.x, pt.y, src->xid, ShapeSet); +} diff --git a/lib/libstuff/x11/sync.c b/lib/libstuff/x11/sync.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +void +sync(void) { + XSync(display, false); +} diff --git a/lib/libstuff/x11/text/freefont.c b/lib/libstuff/x11/text/freefont.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +freefont(Font *f) { + switch(f->type) { + case FFontSet: + XFreeFontSet(display, f->font.set); + break; + case FXft: + xft->fontclose(display, f->font.xft); + break; + case FX11: + XFreeFont(display, f->font.x11); + break; + default: + break; + } + free(f->name); + free(f); +} diff --git a/lib/libstuff/x11/text/labelh.c b/lib/libstuff/x11/text/labelh.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +uint +labelh(Font *font) { + return max(font->height + font->descent + font->pad.min.y + font->pad.max.y, 1); +} diff --git a/lib/libstuff/x11/text/loadfont.c b/lib/libstuff/x11/text/loadfont.c @@ -0,0 +1,70 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +Font* +loadfont(char *name) { + XFontStruct **xfonts; + char **missing, **font_names; + Biobuf *b; + Font *f; + int n, i; + + missing = nil; + f = emallocz(sizeof *f); + f->name = estrdup(name); + if(!strncmp(f->name, "xft:", 4)) { + f->type = FXft; + + if(!havexft()) + goto error; + + f->font.xft = xft->fontopen(display, scr.screen, f->name + 4); + if(!f->font.xft) + f->font.xft = xft->fontopenname(display, scr.screen, f->name + 4); + if(!f->font.xft) + goto error; + + f->ascent = f->font.xft->ascent; + f->descent = f->font.xft->descent; + }else { + f->font.set = XCreateFontSet(display, name, &missing, &n, nil); + if(missing) { + if(false) { + b = Bfdopen(dup(2), O_WRONLY); + Bprint(b, "%s: note: missing fontset%s for '%s':", argv0, + (n > 1 ? "s" : ""), name); + for(i = 0; i < n; i++) + Bprint(b, "%s %s", (i ? "," : ""), missing[i]); + Bprint(b, "\n"); + Bterm(b); + } + freestringlist(missing); + } + + if(f->font.set) { + f->type = FFontSet; + XFontsOfFontSet(f->font.set, &xfonts, &font_names); + f->ascent = xfonts[0]->ascent; + f->descent = xfonts[0]->descent; + }else { + f->type = FX11; + f->font.x11 = XLoadQueryFont(display, name); + if(!f->font.x11) + goto error; + + f->ascent = f->font.x11->ascent; + f->descent = f->font.x11->descent; + } + } + f->height = f->ascent + f->descent; + return f; + +error: + fprint(2, "%s: cannot load font: %s\n", argv0, name); + f->type = 0; + freefont(f); + return nil; +} diff --git a/lib/libstuff/x11/text/textextents_l.c b/lib/libstuff/x11/text/textextents_l.c @@ -0,0 +1,34 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +textextents_l(Font *font, char *text, uint len, int *offset) { + Rectangle rect; + XRectangle r; + XGlyphInfo i; + int unused; + + if(!offset) + offset = &unused; + + switch(font->type) { + case FFontSet: + *offset = Xutf8TextExtents(font->font.set, text, len, &r, nil); + return Rect(r.x, -r.y - r.height, r.x + r.width, -r.y); + case FXft: + xft->textextents(display, font->font.xft, text, len, &i); + *offset = i.xOff; + return Rect(-i.x, i.y - i.height, -i.x + i.width, i.y); + case FX11: + rect = ZR; + rect.max.x = XTextWidth(font->font.x11, text, len); + rect.max.y = font->ascent; + *offset = rect.max.x; + return rect; + default: + die("Invalid font type"); + return ZR; /* shut up ken */ + } +} diff --git a/lib/libstuff/x11/text/textwidth.c b/lib/libstuff/x11/text/textwidth.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <string.h> +#include "../x11.h" + +uint +textwidth(Font *font, char *text) { + return textwidth_l(font, text, strlen(text)); +} diff --git a/lib/libstuff/x11/text/textwidth_l.c b/lib/libstuff/x11/text/textwidth_l.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +uint +textwidth_l(Font *font, char *text, uint len) { + Rectangle r; + + r = textextents_l(font, text, len, nil); + return Dx(r); +} diff --git a/lib/libstuff/x11/windows/configwin.c b/lib/libstuff/x11/windows/configwin.c @@ -0,0 +1,22 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +configwin(Window *w, Rectangle r, int border) { + XWindowChanges wc; + + if(eqrect(r, w->r) && border == w->border) + return; + + wc.x = r.min.x - border; + wc.y = r.min.y - border; + wc.width = Dx(r); + wc.height = Dy(r); + wc.border_width = border; + XConfigureWindow(display, w->xid, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + + w->r = r; + w->border = border; +} diff --git a/lib/libstuff/x11/windows/createwindow.c b/lib/libstuff/x11/windows/createwindow.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, int valmask) { + return createwindow_visual(parent, r, depth, scr.visual, class, wa, valmask); +} diff --git a/lib/libstuff/x11/windows/createwindow_visual.c b/lib/libstuff/x11/windows/createwindow_visual.c @@ -0,0 +1,33 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +createwindow_visual(Window *parent, Rectangle r, + int depth, Visual *vis, uint class, + WinAttr *wa, int valmask) { + Window *w; + + assert(parent->type == WWindow); + + w = emallocz(sizeof *w); + w->visual = vis; + w->type = WWindow; + w->parent = parent; + if(valmask & CWColormap) + w->colormap = wa->colormap; + + w->xid = XCreateWindow(display, parent->xid, r.min.x, r.min.y, Dx(r), Dy(r), + 0 /* border */, depth, class, vis, valmask, wa); +#if 0 + print("createwindow_visual(%W, %R, %d, %p, %ud, %p, %x) = %W\n", + parent, r, depth, vis, class, wa, valmask, w); +#endif + if(class != InputOnly) + w->gc = XCreateGC(display, w->xid, 0, nil); + + w->r = r; + w->depth = depth; + return w; +} diff --git a/lib/libstuff/x11/windows/destroywindow.c b/lib/libstuff/x11/windows/destroywindow.c @@ -0,0 +1,16 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +destroywindow(Window *w) { + assert(w->type == WWindow); + sethandler(w, nil); + if(w->xft) + xft->drawdestroy(w->xft); + if(w->gc) + XFreeGC(display, w->gc); + XDestroyWindow(display, w->xid); + free(w); +} diff --git a/lib/libstuff/x11/windows/findwin.c b/lib/libstuff/x11/windows/findwin.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +findwin(XWindow w) { + void **e; + + e = map_get(&windowmap, (ulong)w, false); + if(e) + return *e; + return nil; +} diff --git a/lib/libstuff/x11/windows/getwinrect.c b/lib/libstuff/x11/windows/getwinrect.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Rectangle +getwinrect(Window *w) { + XWindowAttributes wa; + Point p; + + if(!XGetWindowAttributes(display, w->xid, &wa)) + return ZR; + p = translate(w, &scr.root, ZP); + return rectaddpt(Rect(0, 0, wa.width, wa.height), p); +} diff --git a/lib/libstuff/x11/windows/lowerwin.c b/lib/libstuff/x11/windows/lowerwin.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +lowerwin(Window *w) { + assert(w->type == WWindow); + XLowerWindow(display, w->xid); +} diff --git a/lib/libstuff/x11/windows/mapwin.c b/lib/libstuff/x11/windows/mapwin.c @@ -0,0 +1,15 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +mapwin(Window *w) { + assert(w->type == WWindow); + if(!w->mapped) { + XMapWindow(display, w->xid); + w->mapped = 1; + return 1; + } + return 0; +} diff --git a/lib/libstuff/x11/windows/movewin.c b/lib/libstuff/x11/windows/movewin.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +movewin(Window *w, Point pt) { + Rectangle r; + + assert(w->type == WWindow); + r = rectsetorigin(w->r, pt); + reshapewin(w, r); +} diff --git a/lib/libstuff/x11/windows/raisewin.c b/lib/libstuff/x11/windows/raisewin.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +raisewin(Window *w) { + assert(w->type == WWindow); + XRaiseWindow(display, w->xid); +} diff --git a/lib/libstuff/x11/windows/reparentwindow.c b/lib/libstuff/x11/windows/reparentwindow.c @@ -0,0 +1,13 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +reparentwindow(Window *w, Window *par, Point p) { + assert(w->type == WWindow); + XReparentWindow(display, w->xid, par->xid, p.x, p.y); + w->parent = par; + w->r = rectsubpt(w->r, w->r.min); + w->r = rectaddpt(w->r, p); +} diff --git a/lib/libstuff/x11/windows/reshapewin.c b/lib/libstuff/x11/windows/reshapewin.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +reshapewin(Window *w, Rectangle r) { + assert(w->type == WWindow); + assert(Dx(r) > 0 && Dy(r) > 0); /* Rather than an X error. */ + + configwin(w, r, w->border); +} diff --git a/lib/libstuff/x11/windows/selectinput.c b/lib/libstuff/x11/windows/selectinput.c @@ -0,0 +1,9 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +selectinput(Window *w, long mask) { + XSelectInput(display, w->xid, mask); +} diff --git a/lib/libstuff/x11/windows/setborder.c b/lib/libstuff/x11/windows/setborder.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setborder(Window *w, int width, Color col) { + + assert(w->type == WWindow); + if(width) + XSetWindowBorder(display, w->xid, col.pixel); + if(width != w->border) + configwin(w, w->r, width); +} diff --git a/lib/libstuff/x11/windows/sethandler.c b/lib/libstuff/x11/windows/sethandler.c @@ -0,0 +1,23 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Handlers* +sethandler(Window *w, Handlers *new) { + Handlers *old; + void **e; + + assert(w->type == WWindow); + assert((w->prev != nil && w->next != nil) || w->next == w->prev); + + if(new == nil) + map_rm(&windowmap, (ulong)w->xid); + else { + e = map_get(&windowmap, (ulong)w->xid, true); + *e = w; + } + old = w->handler; + w->handler = new; + return old; +} diff --git a/lib/libstuff/x11/windows/setwinattr.c b/lib/libstuff/x11/windows/setwinattr.c @@ -0,0 +1,10 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +void +setwinattr(Window *w, WinAttr *wa, int valmask) { + assert(w->type == WWindow); + XChangeWindowAttributes(display, w->xid, valmask, wa); +} diff --git a/lib/libstuff/x11/windows/unmapwin.c b/lib/libstuff/x11/windows/unmapwin.c @@ -0,0 +1,16 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +int +unmapwin(Window *w) { + assert(w->type == WWindow); + if(w->mapped) { + XUnmapWindow(display, w->xid); + w->mapped = 0; + w->unmapped++; + return 1; + } + return 0; +} diff --git a/lib/libstuff/x11/windows/window.c b/lib/libstuff/x11/windows/window.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "../x11.h" + +Window* +window(XWindow xw) { + Window *w; + + w = malloc(sizeof *w); + w->type = WWindow; + w->xid = xw; + return freelater(w); +} diff --git a/lib/libstuff/x11/x11.c b/lib/libstuff/x11/x11.c @@ -0,0 +1,12 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +const Point ZP = {0, 0}; +const Rectangle ZR = {{0, 0}, {0, 0}}; + +const Window _pointerwin = { .xid = PointerRoot }; +Window* const pointerwin = (Window*)&_pointerwin; + + diff --git a/lib/libstuff/x11/x11.h b/lib/libstuff/x11/x11.h @@ -0,0 +1,31 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ + +#define _X11_VISIBLE +#define pointerwin __pointerwin +#include <assert.h> +#include <limits.h> +#include <math.h> +#include <strings.h> +#include <unistd.h> +#include <bio.h> +#include <stuff/x.h> +#include <stuff/util.h> +#undef pointerwin + +extern Map windowmap; +extern Map atommap; +extern MapEnt* wbucket[137]; +extern MapEnt* abucket[137]; + +extern int (*xlib_errorhandler) (Display*, XErrorEvent*); + +void configwin(Window*, Rectangle, int); +XPoint* convpts(Point*, int); +int errorhandler(Display*, XErrorEvent*); +ulong getprop(Window*, char*, char*, Atom*, int*, ulong, uchar**, ulong); +void setgccol(Image*, Color); +XftColor* xftcolor(Color); +XftDraw* xftdrawable(Image*); + diff --git a/lib/libstuff/x11/xatom.c b/lib/libstuff/x11/xatom.c @@ -0,0 +1,14 @@ +/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "x11.h" + +Atom +xatom(char *name) { + void **e; + + e = hash_get(&atommap, name, true); + if(*e == nil) + *e = (void*)XInternAtom(display, name, false); + return (Atom)*e; +} diff --git a/lib/libstuff/x11/xft.c b/lib/libstuff/x11/xft.c @@ -0,0 +1,39 @@ +/* Copyright ©2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <stuff/x.h> +#include <stuff/util.h> + +Xft *xft; + +#ifdef HAVE_RTLD +#include <dlfcn.h> + +bool +havexft(void) { + void *libxft; + + if(xft == nil) { + libxft = dlopen("libXft.so", RTLD_LAZY); + if(libxft == nil) + return false; + xft = emalloc(sizeof *xft); + *(void**)(uintptr_t)&xft->drawcreate = dlsym(libxft, "XftDrawCreate"); + *(void**)(uintptr_t)&xft->drawdestroy = dlsym(libxft, "XftDrawDestroy"); + *(void**)(uintptr_t)&xft->fontopen = dlsym(libxft, "XftFontOpenXlfd"); + *(void**)(uintptr_t)&xft->fontopenname = dlsym(libxft, "XftFontOpenName"); + *(void**)(uintptr_t)&xft->fontclose = dlsym(libxft, "XftFontClose"); + *(void**)(uintptr_t)&xft->textextents = dlsym(libxft, "XftTextExtentsUtf8"); + *(void**)(uintptr_t)&xft->drawstring = dlsym(libxft, "XftDrawStringUtf8"); + } + return xft && xft->drawcreate && xft->drawdestroy && xft->fontopen + && xft->fontopenname && xft->fontclose && xft->textextents && xft->drawstring; +} + +#else +bool +havexft(void) { + return false; +} +#endif + diff --git a/lib/libstuff/xext.c b/lib/libstuff/xext.c @@ -0,0 +1,161 @@ +/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#define _X11_VISIBLE +#include <stuff/x.h> +#include <stuff/util.h> +#include <X11/extensions/Xrender.h> +#include <X11/extensions/Xinerama.h> + +#if RANDR_MAJOR < 1 +# error XRandR versions less than 1.0 are not supported +#endif + +static void randr_screenchange(XRRScreenChangeNotifyEvent*); +static bool randr_event_p(XEvent *e); +static void randr_init(void); +static void render_init(void); +static void xinerama_init(void); + +typedef void (*EvHandler)(XEvent*); +static EvHandler randr_handlers[RRNumberEvents]; + +bool have_RandR; +bool have_render; +bool have_xinerama; +int randr_eventbase; +Visual* render_visual; + +static void +handle(XEvent *e, EvHandler h[], int base) { + + if(h[e->type-base]) + h[e->type-base](e); +} + +void +xext_init(void) { + randr_init(); + render_init(); + xinerama_init(); +} + +void +xext_event(XEvent *e) { + + if(randr_event_p(e)) + handle(e, randr_handlers, randr_eventbase); +} + +static void +randr_init(void) { + int errorbase, major, minor; + + have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase); + if(have_RandR) + if(XRRQueryVersion(display, &major, &minor) && major < 1) + have_RandR = false; + if(have_RandR) + XRRSelectInput(display, scr.root.xid, RRScreenChangeNotifyMask); +} + +static bool +randr_event_p(XEvent *e) { + return have_RandR + && (uint)e->type - randr_eventbase < RRNumberEvents; +} + +static void +randr_screenchange(XRRScreenChangeNotifyEvent *ev) { + + XRRUpdateConfiguration((XEvent*)ev); + if(ev->rotation*90 % 180) + scr.rect = Rect(0, 0, ev->width, ev->height); + else + scr.rect = Rect(0, 0, ev->height, ev->width); + init_screens(); +} + +static EvHandler randr_handlers[] = { + [RRScreenChangeNotify] = (EvHandler)randr_screenchange, +}; + +/* Ripped most graciously from ecore_x. XRender documentation + * is sparse. + */ +static void +render_init(void) { + XVisualInfo *vip; + XVisualInfo vi; + int base, i, n; + + have_render = XRenderQueryExtension(display, &base, &base); + if(!have_render) + return; + + vi.class = TrueColor; + vi.depth = 32; + vi.screen = scr.screen; + vip = XGetVisualInfo(display, VisualClassMask + | VisualDepthMask + | VisualScreenMask, + &vi, &n); + for(i=0; i < n; i++) + if(render_argb_p(vip[i].visual)) { + render_visual = vip[i].visual; + scr.visual32 = render_visual; + break; + } + XFree(vip); +} + +bool +render_argb_p(Visual *v) { + XRenderPictFormat *f; + + if(!have_render) + return false; + f = XRenderFindVisualFormat(display, v); + return f + && f->type == PictTypeDirect + && f->direct.alphaMask; +} + +static void +xinerama_init(void) { + int base; + + have_xinerama = XineramaQueryExtension(display, &base, &base); +} + +static bool +xinerama_active(void) { + return have_xinerama && XineramaIsActive(display); +} + +Rectangle* +xinerama_screens(int *np) { + static Rectangle *rects; + XineramaScreenInfo *res; + int i, n; + + if(!xinerama_active()) { + *np = 1; + return &scr.rect; + } + + free(rects); + res = XineramaQueryScreens(display, &n); + rects = emalloc(n * sizeof *rects); + for(i=0; i < n; i++) { + rects[i].min.x = res[i].x_org; + rects[i].min.y = res[i].y_org; + rects[i].max.x = res[i].x_org + res[i].width; + rects[i].max.y = res[i].y_org + res[i].height; + } + XFree(res); + + *np = n; + return rects; +} + diff --git a/lib/libutf/Makefile b/lib/libutf/Makefile @@ -0,0 +1,30 @@ +ROOT= ../.. +include $(ROOT)/mk/hdr.mk + +VERSION=2.0 +TARG=libutf + +OBJ=\ + rune\ + runestrcat\ + runestrchr\ + runestrcmp\ + runestrcpy\ + runestrdup\ + runestrlen\ + runestrecpy\ + runestrncat\ + runestrncmp\ + runestrncpy\ + runestrrchr\ + runestrstr\ + runetype\ + utfecpy\ + utflen\ + utfnlen\ + utfrrune\ + utfrune\ + utfutf + +include $(ROOT)/mk/lib.mk + diff --git a/lib/libutf/NOTICE b/lib/libutf/NOTICE @@ -0,0 +1,25 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. +*/ + +This is a Unix port of the Plan 9 formatted I/O package. + +Please send comments about the packaging +to Russ Cox <rsc@swtch.com>. + + +---- + +This software is also made available under the Lucent Public License +version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html + diff --git a/lib/libutf/README b/lib/libutf/README @@ -0,0 +1,5 @@ +This software was packaged for Unix by Russ Cox. +Please send comments to rsc@swtch.com. + +http://swtch.com/plan9port/unix + diff --git a/lib/libutf/isalpharune.3 b/lib/libutf/isalpharune.3 @@ -0,0 +1,57 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH ISALPHARUNE 3 +.SH NAME +isalpharune, islowerrune, isspacerune, istitlerune, isupperrune, tolowerrune, totitlerune, toupperrune \- Unicode character classes and cases +.SH SYNOPSIS +.B #include <utf.h> +.PP +.B +int isalpharune(Rune c) +.PP +.B +int islowerrune(Rune c) +.PP +.B +int isspacerune(Rune c) +.PP +.B +int istitlerune(Rune c) +.PP +.B +int isupperrune(Rune c) +.PP +.B +Rune tolowerrune(Rune c) +.PP +.B +Rune totitlerune(Rune c) +.PP +.B +Rune toupperrune(Rune c) +.SH DESCRIPTION +These routines examine and operate on Unicode characters, +in particular a subset of their properties as defined in the Unicode standard. +Unicode defines some characters as alphabetic and specifies three cases: +upper, lower, and title. +Analogously to +.IR isalpha (3) +for +.SM ASCII\c +, +these routines +test types and modify cases for Unicode characters. +The names are self-explanatory. +.PP +The case-conversion routines return the character unchanged if it has no case. +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH "SEE ALSO +.IR isalpha (3) , +.IR "The Unicode Standard" . diff --git a/lib/libutf/libutf.a b/lib/libutf/libutf.a Binary files differ. diff --git a/lib/libutf/rune.3 b/lib/libutf/rune.3 @@ -0,0 +1,194 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH RUNE 3 +.SH NAME +runetochar, chartorune, runelen, runenlen, fullrune, utfecpy, utflen, utfnlen, utfrune, utfrrune, utfutf \- rune/UTF conversion +.SH SYNOPSIS +.ta \w'\fLchar*xx'u +.B #include <utf.h> +.PP +.B +int runetochar(char *s, Rune *r) +.PP +.B +int chartorune(Rune *r, char *s) +.PP +.B +int runelen(long r) +.PP +.B +int runenlen(Rune *r, int n) +.PP +.B +int fullrune(char *s, int n) +.PP +.B +char* utfecpy(char *s1, char *es1, char *s2) +.PP +.B +int utflen(char *s) +.PP +.B +int utfnlen(char *s, long n) +.PP +.B +char* utfrune(char *s, long c) +.PP +.B +char* utfrrune(char *s, long c) +.PP +.B +char* utfutf(char *s1, char *s2) +.SH DESCRIPTION +These routines convert to and from a +.SM UTF +byte stream and runes. +.PP +.I Runetochar +copies one rune at +.I r +to at most +.B UTFmax +bytes starting at +.I s +and returns the number of bytes copied. +.BR UTFmax , +defined as +.B 3 +in +.BR <libc.h> , +is the maximum number of bytes required to represent a rune. +.PP +.I Chartorune +copies at most +.B UTFmax +bytes starting at +.I s +to one rune at +.I r +and returns the number of bytes copied. +If the input is not exactly in +.SM UTF +format, +.I chartorune +will convert to 0x80 and return 1. +.PP +.I Runelen +returns the number of bytes +required to convert +.I r +into +.SM UTF. +.PP +.I Runenlen +returns the number of bytes +required to convert the +.I n +runes pointed to by +.I r +into +.SM UTF. +.PP +.I Fullrune +returns 1 if the string +.I s +of length +.I n +is long enough to be decoded by +.I chartorune +and 0 otherwise. +This does not guarantee that the string +contains a legal +.SM UTF +encoding. +This routine is used by programs that +obtain input a byte at +a time and need to know when a full rune +has arrived. +.PP +The following routines are analogous to the +corresponding string routines with +.B utf +substituted for +.B str +and +.B rune +substituted for +.BR chr . +.PP +.I Utfecpy +copies UTF sequences until a null sequence has been copied, but writes no +sequences beyond +.IR es1 . +If any sequences are copied, +.I s1 +is terminated by a null sequence, and a pointer to that sequence is returned. +Otherwise, the original +.I s1 +is returned. +.PP +.I Utflen +returns the number of runes that +are represented by the +.SM UTF +string +.IR s . +.PP +.I Utfnlen +returns the number of complete runes that +are represented by the first +.I n +bytes of +.SM UTF +string +.IR s . +If the last few bytes of the string contain an incompletely coded rune, +.I utfnlen +will not count them; in this way, it differs from +.IR utflen , +which includes every byte of the string. +.PP +.I Utfrune +.RI ( utfrrune ) +returns a pointer to the first (last) +occurrence of rune +.I c +in the +.SM UTF +string +.IR s , +or 0 if +.I c +does not occur in the string. +The NUL byte terminating a string is considered to +be part of the string +.IR s . +.PP +.I Utfutf +returns a pointer to the first occurrence of +the +.SM UTF +string +.I s2 +as a +.SM UTF +substring of +.IR s1 , +or 0 if there is none. +If +.I s2 +is the null string, +.I utfutf +returns +.IR s1 . +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH SEE ALSO +.IR utf (7), +.IR tcs (1) diff --git a/lib/libutf/rune.c b/lib/libutf/rune.c @@ -0,0 +1,175 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +enum +{ + Bit1 = 7, + Bitx = 6, + Bit2 = 5, + Bit3 = 4, + Bit4 = 3, + + T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ + Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ + T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ + T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ + T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ + + Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ + Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ + Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ + + Maskx = (1<<Bitx)-1, /* 0011 1111 */ + Testx = Maskx ^ 0xFF, /* 1100 0000 */ + + Bad = Runeerror, +}; + +int +chartorune(Rune *rune, const char *str) +{ + int c, c1, c2; + long l; + + /* + * one character sequence + * 00000-0007F => T1 + */ + c = *(uchar*)str; + if(c < Tx) { + *rune = c; + return 1; + } + + /* + * two character sequence + * 0080-07FF => T2 Tx + */ + c1 = *(uchar*)(str+1) ^ Tx; + if(c1 & Testx) + goto bad; + if(c < T3) { + if(c < T2) + goto bad; + l = ((c << Bitx) | c1) & Rune2; + if(l <= Rune1) + goto bad; + *rune = l; + return 2; + } + + /* + * three character sequence + * 0800-FFFF => T3 Tx Tx + */ + c2 = *(uchar*)(str+2) ^ Tx; + if(c2 & Testx) + goto bad; + if(c < T4) { + l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; + if(l <= Rune2) + goto bad; + *rune = l; + return 3; + } + + /* + * bad decoding + */ +bad: + *rune = Bad; + return 1; +} + +int +runetochar(char *str, const Rune *rune) +{ + long c; + + /* + * one character sequence + * 00000-0007F => 00-7F + */ + c = *rune; + if(c <= Rune1) { + str[0] = c; + return 1; + } + + /* + * two character sequence + * 0080-07FF => T2 Tx + */ + if(c <= Rune2) { + str[0] = T2 | (c >> 1*Bitx); + str[1] = Tx | (c & Maskx); + return 2; + } + + /* + * three character sequence + * 0800-FFFF => T3 Tx Tx + */ + str[0] = T3 | (c >> 2*Bitx); + str[1] = Tx | ((c >> 1*Bitx) & Maskx); + str[2] = Tx | (c & Maskx); + return 3; +} + +int +runelen(Rune c) +{ + char str[10]; + + return runetochar(str, &c); +} + +int +runenlen(const Rune *r, int nrune) +{ + int nb, c; + + nb = 0; + while(nrune--) { + c = *r++; + if(c <= Rune1) + nb++; + else + if(c <= Rune2) + nb += 2; + else + nb += 3; + } + return nb; +} + +int +fullrune(const char *str, int n) +{ + int c; + + if(n > 0) { + c = *(uchar*)str; + if(c < Tx) + return 1; + if(n > 1) + if(c < T3 || n > 2) + return 1; + } + return 0; +} diff --git a/lib/libutf/runestrcat.3 b/lib/libutf/runestrcat.3 @@ -0,0 +1,74 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH RUNESTRCAT 3 +.SH NAME +runestrcat, +runestrncat, +runestrcmp, +runestrncmp, +runestrcpy, +runestrncpy, +runestrecpy, +runestrlen, +runestrchr, +runestrrchr, +runestrdup, +runestrstr \- rune string operations +.SH SYNOPSIS +.B #include <u.h> +.br +.B #include <libc.h> +.PP +.ta \w'\fLRune* \fP'u +.B +Rune* runestrcat(Rune *s1, Rune *s2) +.PP +.B +Rune* runestrncat(Rune *s1, Rune *s2, long n) +.PP +.B +int runestrcmp(Rune *s1, Rune *s2) +.PP +.B +int runestrncmp(Rune *s1, Rune *s2, long n) +.PP +.B +Rune* runestrcpy(Rune *s1, Rune *s2) +.PP +.B +Rune* runestrncpy(Rune *s1, Rune *s2, long n) +.PP +.B +Rune* runestrecpy(Rune *s1, Rune *es1, Rune *s2) +.PP +.B +long runestrlen(Rune *s) +.PP +.B +Rune* runestrchr(Rune *s, Rune c) +.PP +.B +Rune* runestrrchr(Rune *s, Rune c) +.PP +.B +Rune* runestrdup(Rune *s) +.PP +.B +Rune* runestrstr(Rune *s1, Rune *s2) +.SH DESCRIPTION +These functions are rune string analogues of +the corresponding functions in +.IR strcat (3). +.SH SOURCE +.B http://swtch.com/plan9port/unix +.SH SEE ALSO +.IR rune (3), +.IR strcat (3) +.SH BUGS +The outcome of overlapping moves varies among implementations. diff --git a/lib/libutf/runestrcat.c b/lib/libutf/runestrcat.c @@ -0,0 +1,24 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include <plan9.h> + +Rune* +runestrcat(Rune *s1, const Rune *s2) +{ + + runestrcpy(runestrchr(s1, 0), s2); + return s1; +} diff --git a/lib/libutf/runestrchr.c b/lib/libutf/runestrchr.c @@ -0,0 +1,35 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +Rune* +runestrchr(const Rune *s, Rune c) +{ + Rune c0 = c; + Rune c1; + + if(c == 0) { + while(*s++) + ; + return (Rune*)s-1; + } + + while(c1 = *s++) + if(c1 == c0) + return (Rune*)s-1; + return 0; +} diff --git a/lib/libutf/runestrcmp.c b/lib/libutf/runestrcmp.c @@ -0,0 +1,35 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +int +runestrcmp(const Rune *s1, const Rune *s2) +{ + Rune c1, c2; + + for(;;) { + c1 = *s1++; + c2 = *s2++; + if(c1 != c2) { + if(c1 > c2) + return 1; + return -1; + } + if(c1 == 0) + return 0; + } +} diff --git a/lib/libutf/runestrcpy.c b/lib/libutf/runestrcpy.c @@ -0,0 +1,28 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +Rune* +runestrcpy(Rune *s1, const Rune *s2) +{ + Rune *os1; + + os1 = s1; + while(*s1++ = *s2++) + ; + return os1; +} diff --git a/lib/libutf/runestrdup.c b/lib/libutf/runestrdup.c @@ -0,0 +1,27 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdlib.h> +#include <plan9.h> + +Rune* +runestrdup(const Rune *s) +{ + Rune *ns; + + ns = malloc(sizeof(Rune)*(runestrlen(s) + 1)); + if(ns == 0) + return 0; + + return runestrcpy(ns, s); +} diff --git a/lib/libutf/runestrecpy.c b/lib/libutf/runestrecpy.c @@ -0,0 +1,32 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +Rune* +runestrecpy(Rune *s1, Rune *es1, const Rune *s2) +{ + if(s1 >= es1) + return s1; + + while(*s1++ = *s2++){ + if(s1 == es1){ + *--s1 = '\0'; + break; + } + } + return s1; +} diff --git a/lib/libutf/runestrlen.c b/lib/libutf/runestrlen.c @@ -0,0 +1,21 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <plan9.h> + +long +runestrlen(const Rune *s) +{ + + return runestrchr(s, 0) - s; +} diff --git a/lib/libutf/runestrncat.c b/lib/libutf/runestrncat.c @@ -0,0 +1,32 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +Rune* +runestrncat(Rune *s1, const Rune *s2, long n) +{ + Rune *os1; + + os1 = s1; + s1 = runestrchr(s1, 0); + while(*s1++ = *s2++) + if(--n < 0) { + s1[-1] = 0; + break; + } + return os1; +} diff --git a/lib/libutf/runestrncmp.c b/lib/libutf/runestrncmp.c @@ -0,0 +1,37 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +int +runestrncmp(const Rune *s1, const Rune *s2, long n) +{ + Rune c1, c2; + + while(n > 0) { + c1 = *s1++; + c2 = *s2++; + n--; + if(c1 != c2) { + if(c1 > c2) + return 1; + return -1; + } + if(c1 == 0) + break; + } + return 0; +} diff --git a/lib/libutf/runestrncpy.c b/lib/libutf/runestrncpy.c @@ -0,0 +1,33 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +Rune* +runestrncpy(Rune *s1, const Rune *s2, long n) +{ + int i; + Rune *os1; + + os1 = s1; + for(i = 0; i < n; i++) + if((*s1++ = *s2++) == 0) { + while(++i < n) + *s1++ = 0; + return os1; + } + return os1; +} diff --git a/lib/libutf/runestrrchr.c b/lib/libutf/runestrrchr.c @@ -0,0 +1,30 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +Rune* +runestrrchr(const Rune *s, Rune c) +{ + const Rune *r; + + if(c == 0) + return runestrchr(s, 0); + r = 0; + while(s = runestrchr(s, c)) + r = s++; + return (Rune*)r; +} diff --git a/lib/libutf/runestrstr.c b/lib/libutf/runestrstr.c @@ -0,0 +1,45 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +/* + * Return pointer to first occurrence of s2 in s1, + * 0 if none + */ +Rune* +runestrstr(const Rune *s1, const Rune *s2) +{ + const Rune *pa, *pb; + Rune *p; + int c0, c; + + c0 = *s2; + if(c0 == 0) + return (Rune*)s1; + s2++; + for(p=runestrchr(s1, c0); p; p=runestrchr(p+1, c0)) { + pa = p; + for(pb=s2;; pb++) { + c = *pb; + if(c == 0) + return p; + if(c != *++pa) + break; + } + } + return 0; +} diff --git a/lib/libutf/runetype.c b/lib/libutf/runetype.c @@ -0,0 +1,1151 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +/* + * alpha ranges - + * only covers ranges not in lower||upper + */ +static +Rune __alpha2[] = +{ + 0x00d8, 0x00f6, /* Ø - ö */ + 0x00f8, 0x01f5, /* ø - ǵ */ + 0x0250, 0x02a8, /* ɐ - ʨ */ + 0x038e, 0x03a1, /* Ύ - Ρ */ + 0x03a3, 0x03ce, /* Σ - ώ */ + 0x03d0, 0x03d6, /* ϐ - ϖ */ + 0x03e2, 0x03f3, /* Ϣ - ϳ */ + 0x0490, 0x04c4, /* Ґ - ӄ */ + 0x0561, 0x0587, /* ա - և */ + 0x05d0, 0x05ea, /* א - ת */ + 0x05f0, 0x05f2, /* װ - ײ */ + 0x0621, 0x063a, /* ء - غ */ + 0x0640, 0x064a, /* ـ - ي */ + 0x0671, 0x06b7, /* ٱ - ڷ */ + 0x06ba, 0x06be, /* ں - ھ */ + 0x06c0, 0x06ce, /* ۀ - ێ */ + 0x06d0, 0x06d3, /* ې - ۓ */ + 0x0905, 0x0939, /* अ - ह */ + 0x0958, 0x0961, /* क़ - ॡ */ + 0x0985, 0x098c, /* অ - ঌ */ + 0x098f, 0x0990, /* এ - ঐ */ + 0x0993, 0x09a8, /* ও - ন */ + 0x09aa, 0x09b0, /* প - র */ + 0x09b6, 0x09b9, /* শ - হ */ + 0x09dc, 0x09dd, /* ড় - ঢ় */ + 0x09df, 0x09e1, /* য় - ৡ */ + 0x09f0, 0x09f1, /* ৰ - ৱ */ + 0x0a05, 0x0a0a, /* ਅ - ਊ */ + 0x0a0f, 0x0a10, /* ਏ - ਐ */ + 0x0a13, 0x0a28, /* ਓ - ਨ */ + 0x0a2a, 0x0a30, /* ਪ - ਰ */ + 0x0a32, 0x0a33, /* ਲ - ਲ਼ */ + 0x0a35, 0x0a36, /* ਵ - ਸ਼ */ + 0x0a38, 0x0a39, /* ਸ - ਹ */ + 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */ + 0x0a85, 0x0a8b, /* અ - ઋ */ + 0x0a8f, 0x0a91, /* એ - ઑ */ + 0x0a93, 0x0aa8, /* ઓ - ન */ + 0x0aaa, 0x0ab0, /* પ - ર */ + 0x0ab2, 0x0ab3, /* લ - ળ */ + 0x0ab5, 0x0ab9, /* વ - હ */ + 0x0b05, 0x0b0c, /* ଅ - ଌ */ + 0x0b0f, 0x0b10, /* ଏ - ଐ */ + 0x0b13, 0x0b28, /* ଓ - ନ */ + 0x0b2a, 0x0b30, /* ପ - ର */ + 0x0b32, 0x0b33, /* ଲ - ଳ */ + 0x0b36, 0x0b39, /* ଶ - ହ */ + 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */ + 0x0b5f, 0x0b61, /* ୟ - ୡ */ + 0x0b85, 0x0b8a, /* அ - ஊ */ + 0x0b8e, 0x0b90, /* எ - ஐ */ + 0x0b92, 0x0b95, /* ஒ - க */ + 0x0b99, 0x0b9a, /* ங - ச */ + 0x0b9e, 0x0b9f, /* ஞ - ட */ + 0x0ba3, 0x0ba4, /* ண - த */ + 0x0ba8, 0x0baa, /* ந - ப */ + 0x0bae, 0x0bb5, /* ம - வ */ + 0x0bb7, 0x0bb9, /* ஷ - ஹ */ + 0x0c05, 0x0c0c, /* అ - ఌ */ + 0x0c0e, 0x0c10, /* ఎ - ఐ */ + 0x0c12, 0x0c28, /* ఒ - న */ + 0x0c2a, 0x0c33, /* ప - ళ */ + 0x0c35, 0x0c39, /* వ - హ */ + 0x0c60, 0x0c61, /* ౠ - ౡ */ + 0x0c85, 0x0c8c, /* ಅ - ಌ */ + 0x0c8e, 0x0c90, /* ಎ - ಐ */ + 0x0c92, 0x0ca8, /* ಒ - ನ */ + 0x0caa, 0x0cb3, /* ಪ - ಳ */ + 0x0cb5, 0x0cb9, /* ವ - ಹ */ + 0x0ce0, 0x0ce1, /* ೠ - ೡ */ + 0x0d05, 0x0d0c, /* അ - ഌ */ + 0x0d0e, 0x0d10, /* എ - ഐ */ + 0x0d12, 0x0d28, /* ഒ - ന */ + 0x0d2a, 0x0d39, /* പ - ഹ */ + 0x0d60, 0x0d61, /* ൠ - ൡ */ + 0x0e01, 0x0e30, /* ก - ะ */ + 0x0e32, 0x0e33, /* า - ำ */ + 0x0e40, 0x0e46, /* เ - ๆ */ + 0x0e5a, 0x0e5b, /* ๚ - ๛ */ + 0x0e81, 0x0e82, /* ກ - ຂ */ + 0x0e87, 0x0e88, /* ງ - ຈ */ + 0x0e94, 0x0e97, /* ດ - ທ */ + 0x0e99, 0x0e9f, /* ນ - ຟ */ + 0x0ea1, 0x0ea3, /* ມ - ຣ */ + 0x0eaa, 0x0eab, /* ສ - ຫ */ + 0x0ead, 0x0eae, /* ອ - ຮ */ + 0x0eb2, 0x0eb3, /* າ - ຳ */ + 0x0ec0, 0x0ec4, /* ເ - ໄ */ + 0x0edc, 0x0edd, /* ໜ - ໝ */ + 0x0f18, 0x0f19, /* ༘ - ༙ */ + 0x0f40, 0x0f47, /* ཀ - ཇ */ + 0x0f49, 0x0f69, /* ཉ - ཀྵ */ + 0x10d0, 0x10f6, /* ა - ჶ */ + 0x1100, 0x1159, /* ᄀ - ᅙ */ + 0x115f, 0x11a2, /* ᅟ - ᆢ */ + 0x11a8, 0x11f9, /* ᆨ - ᇹ */ + 0x1e00, 0x1e9b, /* Ḁ - ẛ */ + 0x1f50, 0x1f57, /* ὐ - ὗ */ + 0x1f80, 0x1fb4, /* ᾀ - ᾴ */ + 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */ + 0x1fc2, 0x1fc4, /* ῂ - ῄ */ + 0x1fc6, 0x1fcc, /* ῆ - ῌ */ + 0x1fd0, 0x1fd3, /* ῐ - ΐ */ + 0x1fd6, 0x1fdb, /* ῖ - Ί */ + 0x1fe0, 0x1fec, /* ῠ - Ῥ */ + 0x1ff2, 0x1ff4, /* ῲ - ῴ */ + 0x1ff6, 0x1ffc, /* ῶ - ῼ */ + 0x210a, 0x2113, /* ℊ - ℓ */ + 0x2115, 0x211d, /* ℕ - ℝ */ + 0x2120, 0x2122, /* ℠ - ™ */ + 0x212a, 0x2131, /* K - ℱ */ + 0x2133, 0x2138, /* ℳ - ℸ */ + 0x3041, 0x3094, /* ぁ - ゔ */ + 0x30a1, 0x30fa, /* ァ - ヺ */ + 0x3105, 0x312c, /* ㄅ - ㄬ */ + 0x3131, 0x318e, /* ㄱ - ㆎ */ + 0x3192, 0x319f, /* ㆒ - ㆟ */ + 0x3260, 0x327b, /* ㉠ - ㉻ */ + 0x328a, 0x32b0, /* ㊊ - ㊰ */ + 0x32d0, 0x32fe, /* ㋐ - ㋾ */ + 0x3300, 0x3357, /* ㌀ - ㍗ */ + 0x3371, 0x3376, /* ㍱ - ㍶ */ + 0x337b, 0x3394, /* ㍻ - ㎔ */ + 0x3399, 0x339e, /* ㎙ - ㎞ */ + 0x33a9, 0x33ad, /* ㎩ - ㎭ */ + 0x33b0, 0x33c1, /* ㎰ - ㏁ */ + 0x33c3, 0x33c5, /* ㏃ - ㏅ */ + 0x33c7, 0x33d7, /* ㏇ - ㏗ */ + 0x33d9, 0x33dd, /* ㏙ - ㏝ */ + 0x4e00, 0x9fff, /* 一 - 鿿 */ + 0xac00, 0xd7a3, /* 가 - 힣 */ + 0xf900, 0xfb06, /* 豈 - st */ + 0xfb13, 0xfb17, /* ﬓ - ﬗ */ + 0xfb1f, 0xfb28, /* ײַ - ﬨ */ + 0xfb2a, 0xfb36, /* שׁ - זּ */ + 0xfb38, 0xfb3c, /* טּ - לּ */ + 0xfb40, 0xfb41, /* נּ - סּ */ + 0xfb43, 0xfb44, /* ףּ - פּ */ + 0xfb46, 0xfbb1, /* צּ - ﮱ */ + 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */ + 0xfd50, 0xfd8f, /* ﵐ - ﶏ */ + 0xfd92, 0xfdc7, /* ﶒ - ﷇ */ + 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */ + 0xfe70, 0xfe72, /* ﹰ - ﹲ */ + 0xfe76, 0xfefc, /* ﹶ - ﻼ */ + 0xff66, 0xff6f, /* ヲ - ッ */ + 0xff71, 0xff9d, /* ア - ン */ + 0xffa0, 0xffbe, /* ᅠ - ᄒ */ + 0xffc2, 0xffc7, /* ᅡ - ᅦ */ + 0xffca, 0xffcf, /* ᅧ - ᅬ */ + 0xffd2, 0xffd7, /* ᅭ - ᅲ */ + 0xffda, 0xffdc, /* ᅳ - ᅵ */ +}; + +/* + * alpha singlets - + * only covers ranges not in lower||upper + */ +static +Rune __alpha1[] = +{ + 0x00aa, /* ª */ + 0x00b5, /* µ */ + 0x00ba, /* º */ + 0x03da, /* Ϛ */ + 0x03dc, /* Ϝ */ + 0x03de, /* Ϟ */ + 0x03e0, /* Ϡ */ + 0x06d5, /* ە */ + 0x09b2, /* ল */ + 0x0a5e, /* ਫ਼ */ + 0x0a8d, /* ઍ */ + 0x0ae0, /* ૠ */ + 0x0b9c, /* ஜ */ + 0x0cde, /* ೞ */ + 0x0e4f, /* ๏ */ + 0x0e84, /* ຄ */ + 0x0e8a, /* ຊ */ + 0x0e8d, /* ຍ */ + 0x0ea5, /* ລ */ + 0x0ea7, /* ວ */ + 0x0eb0, /* ະ */ + 0x0ebd, /* ຽ */ + 0x1fbe, /* ι */ + 0x207f, /* ⁿ */ + 0x20a8, /* ₨ */ + 0x2102, /* ℂ */ + 0x2107, /* ℇ */ + 0x2124, /* ℤ */ + 0x2126, /* Ω */ + 0x2128, /* ℨ */ + 0xfb3e, /* מּ */ + 0xfe74, /* ﹴ */ +}; + +/* + * space ranges + */ +static +Rune __space2[] = +{ + 0x0009, 0x000a, /* tab and newline */ + 0x0020, 0x0020, /* space */ + 0x00a0, 0x00a0, /*   */ + 0x2000, 0x200b, /*   - ​ */ + 0x2028, 0x2029, /* 
 - 
 */ + 0x3000, 0x3000, /*   */ + 0xfeff, 0xfeff, /*  */ +}; + +/* + * lower case ranges + * 3rd col is conversion excess 500 + */ +static +Rune __toupper2[] = +{ + 0x0061, 0x007a, 468, /* a-z A-Z */ + 0x00e0, 0x00f6, 468, /* à-ö À-Ö */ + 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */ + 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */ + 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */ + 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */ + 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */ + 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */ + 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */ + 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */ + 0x0430, 0x044f, 468, /* а-я А-Я */ + 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */ + 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */ + 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */ + 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */ + 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */ + 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */ + 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */ + 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */ + 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */ + 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */ + 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */ + 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */ + 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */ + 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */ + 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */ + 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */ + 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */ + 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */ + 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */ + 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */ + 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */ + 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */ + 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */ + 0xff41, 0xff5a, 468, /* a-z A-Z */ +}; + +/* + * lower case singlets + * 2nd col is conversion excess 500 + */ +static +Rune __toupper1[] = +{ + 0x00ff, 621, /* ÿ Ÿ */ + 0x0101, 499, /* ā Ā */ + 0x0103, 499, /* ă Ă */ + 0x0105, 499, /* ą Ą */ + 0x0107, 499, /* ć Ć */ + 0x0109, 499, /* ĉ Ĉ */ + 0x010b, 499, /* ċ Ċ */ + 0x010d, 499, /* č Č */ + 0x010f, 499, /* ď Ď */ + 0x0111, 499, /* đ Đ */ + 0x0113, 499, /* ē Ē */ + 0x0115, 499, /* ĕ Ĕ */ + 0x0117, 499, /* ė Ė */ + 0x0119, 499, /* ę Ę */ + 0x011b, 499, /* ě Ě */ + 0x011d, 499, /* ĝ Ĝ */ + 0x011f, 499, /* ğ Ğ */ + 0x0121, 499, /* ġ Ġ */ + 0x0123, 499, /* ģ Ģ */ + 0x0125, 499, /* ĥ Ĥ */ + 0x0127, 499, /* ħ Ħ */ + 0x0129, 499, /* ĩ Ĩ */ + 0x012b, 499, /* ī Ī */ + 0x012d, 499, /* ĭ Ĭ */ + 0x012f, 499, /* į Į */ + 0x0131, 268, /* ı I */ + 0x0133, 499, /* ij IJ */ + 0x0135, 499, /* ĵ Ĵ */ + 0x0137, 499, /* ķ Ķ */ + 0x013a, 499, /* ĺ Ĺ */ + 0x013c, 499, /* ļ Ļ */ + 0x013e, 499, /* ľ Ľ */ + 0x0140, 499, /* ŀ Ŀ */ + 0x0142, 499, /* ł Ł */ + 0x0144, 499, /* ń Ń */ + 0x0146, 499, /* ņ Ņ */ + 0x0148, 499, /* ň Ň */ + 0x014b, 499, /* ŋ Ŋ */ + 0x014d, 499, /* ō Ō */ + 0x014f, 499, /* ŏ Ŏ */ + 0x0151, 499, /* ő Ő */ + 0x0153, 499, /* œ Œ */ + 0x0155, 499, /* ŕ Ŕ */ + 0x0157, 499, /* ŗ Ŗ */ + 0x0159, 499, /* ř Ř */ + 0x015b, 499, /* ś Ś */ + 0x015d, 499, /* ŝ Ŝ */ + 0x015f, 499, /* ş Ş */ + 0x0161, 499, /* š Š */ + 0x0163, 499, /* ţ Ţ */ + 0x0165, 499, /* ť Ť */ + 0x0167, 499, /* ŧ Ŧ */ + 0x0169, 499, /* ũ Ũ */ + 0x016b, 499, /* ū Ū */ + 0x016d, 499, /* ŭ Ŭ */ + 0x016f, 499, /* ů Ů */ + 0x0171, 499, /* ű Ű */ + 0x0173, 499, /* ų Ų */ + 0x0175, 499, /* ŵ Ŵ */ + 0x0177, 499, /* ŷ Ŷ */ + 0x017a, 499, /* ź Ź */ + 0x017c, 499, /* ż Ż */ + 0x017e, 499, /* ž Ž */ + 0x017f, 200, /* ſ S */ + 0x0183, 499, /* ƃ Ƃ */ + 0x0185, 499, /* ƅ Ƅ */ + 0x0188, 499, /* ƈ Ƈ */ + 0x018c, 499, /* ƌ Ƌ */ + 0x0192, 499, /* ƒ Ƒ */ + 0x0199, 499, /* ƙ Ƙ */ + 0x01a1, 499, /* ơ Ơ */ + 0x01a3, 499, /* ƣ Ƣ */ + 0x01a5, 499, /* ƥ Ƥ */ + 0x01a8, 499, /* ƨ Ƨ */ + 0x01ad, 499, /* ƭ Ƭ */ + 0x01b0, 499, /* ư Ư */ + 0x01b4, 499, /* ƴ Ƴ */ + 0x01b6, 499, /* ƶ Ƶ */ + 0x01b9, 499, /* ƹ Ƹ */ + 0x01bd, 499, /* ƽ Ƽ */ + 0x01c5, 499, /* Dž DŽ */ + 0x01c6, 498, /* dž DŽ */ + 0x01c8, 499, /* Lj LJ */ + 0x01c9, 498, /* lj LJ */ + 0x01cb, 499, /* Nj NJ */ + 0x01cc, 498, /* nj NJ */ + 0x01ce, 499, /* ǎ Ǎ */ + 0x01d0, 499, /* ǐ Ǐ */ + 0x01d2, 499, /* ǒ Ǒ */ + 0x01d4, 499, /* ǔ Ǔ */ + 0x01d6, 499, /* ǖ Ǖ */ + 0x01d8, 499, /* ǘ Ǘ */ + 0x01da, 499, /* ǚ Ǚ */ + 0x01dc, 499, /* ǜ Ǜ */ + 0x01df, 499, /* ǟ Ǟ */ + 0x01e1, 499, /* ǡ Ǡ */ + 0x01e3, 499, /* ǣ Ǣ */ + 0x01e5, 499, /* ǥ Ǥ */ + 0x01e7, 499, /* ǧ Ǧ */ + 0x01e9, 499, /* ǩ Ǩ */ + 0x01eb, 499, /* ǫ Ǫ */ + 0x01ed, 499, /* ǭ Ǭ */ + 0x01ef, 499, /* ǯ Ǯ */ + 0x01f2, 499, /* Dz DZ */ + 0x01f3, 498, /* dz DZ */ + 0x01f5, 499, /* ǵ Ǵ */ + 0x01fb, 499, /* ǻ Ǻ */ + 0x01fd, 499, /* ǽ Ǽ */ + 0x01ff, 499, /* ǿ Ǿ */ + 0x0201, 499, /* ȁ Ȁ */ + 0x0203, 499, /* ȃ Ȃ */ + 0x0205, 499, /* ȅ Ȅ */ + 0x0207, 499, /* ȇ Ȇ */ + 0x0209, 499, /* ȉ Ȉ */ + 0x020b, 499, /* ȋ Ȋ */ + 0x020d, 499, /* ȍ Ȍ */ + 0x020f, 499, /* ȏ Ȏ */ + 0x0211, 499, /* ȑ Ȑ */ + 0x0213, 499, /* ȓ Ȓ */ + 0x0215, 499, /* ȕ Ȕ */ + 0x0217, 499, /* ȗ Ȗ */ + 0x0253, 290, /* ɓ Ɓ */ + 0x0254, 294, /* ɔ Ɔ */ + 0x025b, 297, /* ɛ Ɛ */ + 0x0260, 295, /* ɠ Ɠ */ + 0x0263, 293, /* ɣ Ɣ */ + 0x0268, 291, /* ɨ Ɨ */ + 0x0269, 289, /* ɩ Ɩ */ + 0x026f, 289, /* ɯ Ɯ */ + 0x0272, 287, /* ɲ Ɲ */ + 0x0283, 282, /* ʃ Ʃ */ + 0x0288, 282, /* ʈ Ʈ */ + 0x0292, 281, /* ʒ Ʒ */ + 0x03ac, 462, /* ά Ά */ + 0x03cc, 436, /* ό Ό */ + 0x03d0, 438, /* ϐ Β */ + 0x03d1, 443, /* ϑ Θ */ + 0x03d5, 453, /* ϕ Φ */ + 0x03d6, 446, /* ϖ Π */ + 0x03e3, 499, /* ϣ Ϣ */ + 0x03e5, 499, /* ϥ Ϥ */ + 0x03e7, 499, /* ϧ Ϧ */ + 0x03e9, 499, /* ϩ Ϩ */ + 0x03eb, 499, /* ϫ Ϫ */ + 0x03ed, 499, /* ϭ Ϭ */ + 0x03ef, 499, /* ϯ Ϯ */ + 0x03f0, 414, /* ϰ Κ */ + 0x03f1, 420, /* ϱ Ρ */ + 0x0461, 499, /* ѡ Ѡ */ + 0x0463, 499, /* ѣ Ѣ */ + 0x0465, 499, /* ѥ Ѥ */ + 0x0467, 499, /* ѧ Ѧ */ + 0x0469, 499, /* ѩ Ѩ */ + 0x046b, 499, /* ѫ Ѫ */ + 0x046d, 499, /* ѭ Ѭ */ + 0x046f, 499, /* ѯ Ѯ */ + 0x0471, 499, /* ѱ Ѱ */ + 0x0473, 499, /* ѳ Ѳ */ + 0x0475, 499, /* ѵ Ѵ */ + 0x0477, 499, /* ѷ Ѷ */ + 0x0479, 499, /* ѹ Ѹ */ + 0x047b, 499, /* ѻ Ѻ */ + 0x047d, 499, /* ѽ Ѽ */ + 0x047f, 499, /* ѿ Ѿ */ + 0x0481, 499, /* ҁ Ҁ */ + 0x0491, 499, /* ґ Ґ */ + 0x0493, 499, /* ғ Ғ */ + 0x0495, 499, /* ҕ Ҕ */ + 0x0497, 499, /* җ Җ */ + 0x0499, 499, /* ҙ Ҙ */ + 0x049b, 499, /* қ Қ */ + 0x049d, 499, /* ҝ Ҝ */ + 0x049f, 499, /* ҟ Ҟ */ + 0x04a1, 499, /* ҡ Ҡ */ + 0x04a3, 499, /* ң Ң */ + 0x04a5, 499, /* ҥ Ҥ */ + 0x04a7, 499, /* ҧ Ҧ */ + 0x04a9, 499, /* ҩ Ҩ */ + 0x04ab, 499, /* ҫ Ҫ */ + 0x04ad, 499, /* ҭ Ҭ */ + 0x04af, 499, /* ү Ү */ + 0x04b1, 499, /* ұ Ұ */ + 0x04b3, 499, /* ҳ Ҳ */ + 0x04b5, 499, /* ҵ Ҵ */ + 0x04b7, 499, /* ҷ Ҷ */ + 0x04b9, 499, /* ҹ Ҹ */ + 0x04bb, 499, /* һ Һ */ + 0x04bd, 499, /* ҽ Ҽ */ + 0x04bf, 499, /* ҿ Ҿ */ + 0x04c2, 499, /* ӂ Ӂ */ + 0x04c4, 499, /* ӄ Ӄ */ + 0x04c8, 499, /* ӈ Ӈ */ + 0x04cc, 499, /* ӌ Ӌ */ + 0x04d1, 499, /* ӑ Ӑ */ + 0x04d3, 499, /* ӓ Ӓ */ + 0x04d5, 499, /* ӕ Ӕ */ + 0x04d7, 499, /* ӗ Ӗ */ + 0x04d9, 499, /* ә Ә */ + 0x04db, 499, /* ӛ Ӛ */ + 0x04dd, 499, /* ӝ Ӝ */ + 0x04df, 499, /* ӟ Ӟ */ + 0x04e1, 499, /* ӡ Ӡ */ + 0x04e3, 499, /* ӣ Ӣ */ + 0x04e5, 499, /* ӥ Ӥ */ + 0x04e7, 499, /* ӧ Ӧ */ + 0x04e9, 499, /* ө Ө */ + 0x04eb, 499, /* ӫ Ӫ */ + 0x04ef, 499, /* ӯ Ӯ */ + 0x04f1, 499, /* ӱ Ӱ */ + 0x04f3, 499, /* ӳ Ӳ */ + 0x04f5, 499, /* ӵ Ӵ */ + 0x04f9, 499, /* ӹ Ӹ */ + 0x1e01, 499, /* ḁ Ḁ */ + 0x1e03, 499, /* ḃ Ḃ */ + 0x1e05, 499, /* ḅ Ḅ */ + 0x1e07, 499, /* ḇ Ḇ */ + 0x1e09, 499, /* ḉ Ḉ */ + 0x1e0b, 499, /* ḋ Ḋ */ + 0x1e0d, 499, /* ḍ Ḍ */ + 0x1e0f, 499, /* ḏ Ḏ */ + 0x1e11, 499, /* ḑ Ḑ */ + 0x1e13, 499, /* ḓ Ḓ */ + 0x1e15, 499, /* ḕ Ḕ */ + 0x1e17, 499, /* ḗ Ḗ */ + 0x1e19, 499, /* ḙ Ḙ */ + 0x1e1b, 499, /* ḛ Ḛ */ + 0x1e1d, 499, /* ḝ Ḝ */ + 0x1e1f, 499, /* ḟ Ḟ */ + 0x1e21, 499, /* ḡ Ḡ */ + 0x1e23, 499, /* ḣ Ḣ */ + 0x1e25, 499, /* ḥ Ḥ */ + 0x1e27, 499, /* ḧ Ḧ */ + 0x1e29, 499, /* ḩ Ḩ */ + 0x1e2b, 499, /* ḫ Ḫ */ + 0x1e2d, 499, /* ḭ Ḭ */ + 0x1e2f, 499, /* ḯ Ḯ */ + 0x1e31, 499, /* ḱ Ḱ */ + 0x1e33, 499, /* ḳ Ḳ */ + 0x1e35, 499, /* ḵ Ḵ */ + 0x1e37, 499, /* ḷ Ḷ */ + 0x1e39, 499, /* ḹ Ḹ */ + 0x1e3b, 499, /* ḻ Ḻ */ + 0x1e3d, 499, /* ḽ Ḽ */ + 0x1e3f, 499, /* ḿ Ḿ */ + 0x1e41, 499, /* ṁ Ṁ */ + 0x1e43, 499, /* ṃ Ṃ */ + 0x1e45, 499, /* ṅ Ṅ */ + 0x1e47, 499, /* ṇ Ṇ */ + 0x1e49, 499, /* ṉ Ṉ */ + 0x1e4b, 499, /* ṋ Ṋ */ + 0x1e4d, 499, /* ṍ Ṍ */ + 0x1e4f, 499, /* ṏ Ṏ */ + 0x1e51, 499, /* ṑ Ṑ */ + 0x1e53, 499, /* ṓ Ṓ */ + 0x1e55, 499, /* ṕ Ṕ */ + 0x1e57, 499, /* ṗ Ṗ */ + 0x1e59, 499, /* ṙ Ṙ */ + 0x1e5b, 499, /* ṛ Ṛ */ + 0x1e5d, 499, /* ṝ Ṝ */ + 0x1e5f, 499, /* ṟ Ṟ */ + 0x1e61, 499, /* ṡ Ṡ */ + 0x1e63, 499, /* ṣ Ṣ */ + 0x1e65, 499, /* ṥ Ṥ */ + 0x1e67, 499, /* ṧ Ṧ */ + 0x1e69, 499, /* ṩ Ṩ */ + 0x1e6b, 499, /* ṫ Ṫ */ + 0x1e6d, 499, /* ṭ Ṭ */ + 0x1e6f, 499, /* ṯ Ṯ */ + 0x1e71, 499, /* ṱ Ṱ */ + 0x1e73, 499, /* ṳ Ṳ */ + 0x1e75, 499, /* ṵ Ṵ */ + 0x1e77, 499, /* ṷ Ṷ */ + 0x1e79, 499, /* ṹ Ṹ */ + 0x1e7b, 499, /* ṻ Ṻ */ + 0x1e7d, 499, /* ṽ Ṽ */ + 0x1e7f, 499, /* ṿ Ṿ */ + 0x1e81, 499, /* ẁ Ẁ */ + 0x1e83, 499, /* ẃ Ẃ */ + 0x1e85, 499, /* ẅ Ẅ */ + 0x1e87, 499, /* ẇ Ẇ */ + 0x1e89, 499, /* ẉ Ẉ */ + 0x1e8b, 499, /* ẋ Ẋ */ + 0x1e8d, 499, /* ẍ Ẍ */ + 0x1e8f, 499, /* ẏ Ẏ */ + 0x1e91, 499, /* ẑ Ẑ */ + 0x1e93, 499, /* ẓ Ẓ */ + 0x1e95, 499, /* ẕ Ẕ */ + 0x1ea1, 499, /* ạ Ạ */ + 0x1ea3, 499, /* ả Ả */ + 0x1ea5, 499, /* ấ Ấ */ + 0x1ea7, 499, /* ầ Ầ */ + 0x1ea9, 499, /* ẩ Ẩ */ + 0x1eab, 499, /* ẫ Ẫ */ + 0x1ead, 499, /* ậ Ậ */ + 0x1eaf, 499, /* ắ Ắ */ + 0x1eb1, 499, /* ằ Ằ */ + 0x1eb3, 499, /* ẳ Ẳ */ + 0x1eb5, 499, /* ẵ Ẵ */ + 0x1eb7, 499, /* ặ Ặ */ + 0x1eb9, 499, /* ẹ Ẹ */ + 0x1ebb, 499, /* ẻ Ẻ */ + 0x1ebd, 499, /* ẽ Ẽ */ + 0x1ebf, 499, /* ế Ế */ + 0x1ec1, 499, /* ề Ề */ + 0x1ec3, 499, /* ể Ể */ + 0x1ec5, 499, /* ễ Ễ */ + 0x1ec7, 499, /* ệ Ệ */ + 0x1ec9, 499, /* ỉ Ỉ */ + 0x1ecb, 499, /* ị Ị */ + 0x1ecd, 499, /* ọ Ọ */ + 0x1ecf, 499, /* ỏ Ỏ */ + 0x1ed1, 499, /* ố Ố */ + 0x1ed3, 499, /* ồ Ồ */ + 0x1ed5, 499, /* ổ Ổ */ + 0x1ed7, 499, /* ỗ Ỗ */ + 0x1ed9, 499, /* ộ Ộ */ + 0x1edb, 499, /* ớ Ớ */ + 0x1edd, 499, /* ờ Ờ */ + 0x1edf, 499, /* ở Ở */ + 0x1ee1, 499, /* ỡ Ỡ */ + 0x1ee3, 499, /* ợ Ợ */ + 0x1ee5, 499, /* ụ Ụ */ + 0x1ee7, 499, /* ủ Ủ */ + 0x1ee9, 499, /* ứ Ứ */ + 0x1eeb, 499, /* ừ Ừ */ + 0x1eed, 499, /* ử Ử */ + 0x1eef, 499, /* ữ Ữ */ + 0x1ef1, 499, /* ự Ự */ + 0x1ef3, 499, /* ỳ Ỳ */ + 0x1ef5, 499, /* ỵ Ỵ */ + 0x1ef7, 499, /* ỷ Ỷ */ + 0x1ef9, 499, /* ỹ Ỹ */ + 0x1f51, 508, /* ὑ Ὑ */ + 0x1f53, 508, /* ὓ Ὓ */ + 0x1f55, 508, /* ὕ Ὕ */ + 0x1f57, 508, /* ὗ Ὗ */ + 0x1fb3, 509, /* ᾳ ᾼ */ + 0x1fc3, 509, /* ῃ ῌ */ + 0x1fe5, 507, /* ῥ Ῥ */ + 0x1ff3, 509, /* ῳ ῼ */ +}; + +/* + * upper case ranges + * 3rd col is conversion excess 500 + */ +static +Rune __tolower2[] = +{ + 0x0041, 0x005a, 532, /* A-Z a-z */ + 0x00c0, 0x00d6, 532, /* À-Ö à-ö */ + 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */ + 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */ + 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */ + 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */ + 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */ + 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */ + 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */ + 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */ + 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */ + 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */ + 0x0410, 0x042f, 532, /* А-Я а-я */ + 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */ + 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */ + 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */ + 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */ + 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */ + 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */ + 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */ + 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */ + 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */ + 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */ + 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */ + 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */ + 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */ + 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */ + 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */ + 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */ + 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */ + 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */ + 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */ + 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */ + 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */ + 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */ + 0xff21, 0xff3a, 532, /* A-Z a-z */ +}; + +/* + * upper case singlets + * 2nd col is conversion excess 500 + */ +static +Rune __tolower1[] = +{ + 0x0100, 501, /* Ā ā */ + 0x0102, 501, /* Ă ă */ + 0x0104, 501, /* Ą ą */ + 0x0106, 501, /* Ć ć */ + 0x0108, 501, /* Ĉ ĉ */ + 0x010a, 501, /* Ċ ċ */ + 0x010c, 501, /* Č č */ + 0x010e, 501, /* Ď ď */ + 0x0110, 501, /* Đ đ */ + 0x0112, 501, /* Ē ē */ + 0x0114, 501, /* Ĕ ĕ */ + 0x0116, 501, /* Ė ė */ + 0x0118, 501, /* Ę ę */ + 0x011a, 501, /* Ě ě */ + 0x011c, 501, /* Ĝ ĝ */ + 0x011e, 501, /* Ğ ğ */ + 0x0120, 501, /* Ġ ġ */ + 0x0122, 501, /* Ģ ģ */ + 0x0124, 501, /* Ĥ ĥ */ + 0x0126, 501, /* Ħ ħ */ + 0x0128, 501, /* Ĩ ĩ */ + 0x012a, 501, /* Ī ī */ + 0x012c, 501, /* Ĭ ĭ */ + 0x012e, 501, /* Į į */ + 0x0130, 301, /* İ i */ + 0x0132, 501, /* IJ ij */ + 0x0134, 501, /* Ĵ ĵ */ + 0x0136, 501, /* Ķ ķ */ + 0x0139, 501, /* Ĺ ĺ */ + 0x013b, 501, /* Ļ ļ */ + 0x013d, 501, /* Ľ ľ */ + 0x013f, 501, /* Ŀ ŀ */ + 0x0141, 501, /* Ł ł */ + 0x0143, 501, /* Ń ń */ + 0x0145, 501, /* Ņ ņ */ + 0x0147, 501, /* Ň ň */ + 0x014a, 501, /* Ŋ ŋ */ + 0x014c, 501, /* Ō ō */ + 0x014e, 501, /* Ŏ ŏ */ + 0x0150, 501, /* Ő ő */ + 0x0152, 501, /* Œ œ */ + 0x0154, 501, /* Ŕ ŕ */ + 0x0156, 501, /* Ŗ ŗ */ + 0x0158, 501, /* Ř ř */ + 0x015a, 501, /* Ś ś */ + 0x015c, 501, /* Ŝ ŝ */ + 0x015e, 501, /* Ş ş */ + 0x0160, 501, /* Š š */ + 0x0162, 501, /* Ţ ţ */ + 0x0164, 501, /* Ť ť */ + 0x0166, 501, /* Ŧ ŧ */ + 0x0168, 501, /* Ũ ũ */ + 0x016a, 501, /* Ū ū */ + 0x016c, 501, /* Ŭ ŭ */ + 0x016e, 501, /* Ů ů */ + 0x0170, 501, /* Ű ű */ + 0x0172, 501, /* Ų ų */ + 0x0174, 501, /* Ŵ ŵ */ + 0x0176, 501, /* Ŷ ŷ */ + 0x0178, 379, /* Ÿ ÿ */ + 0x0179, 501, /* Ź ź */ + 0x017b, 501, /* Ż ż */ + 0x017d, 501, /* Ž ž */ + 0x0181, 710, /* Ɓ ɓ */ + 0x0182, 501, /* Ƃ ƃ */ + 0x0184, 501, /* Ƅ ƅ */ + 0x0186, 706, /* Ɔ ɔ */ + 0x0187, 501, /* Ƈ ƈ */ + 0x018b, 501, /* Ƌ ƌ */ + 0x0190, 703, /* Ɛ ɛ */ + 0x0191, 501, /* Ƒ ƒ */ + 0x0193, 705, /* Ɠ ɠ */ + 0x0194, 707, /* Ɣ ɣ */ + 0x0196, 711, /* Ɩ ɩ */ + 0x0197, 709, /* Ɨ ɨ */ + 0x0198, 501, /* Ƙ ƙ */ + 0x019c, 711, /* Ɯ ɯ */ + 0x019d, 713, /* Ɲ ɲ */ + 0x01a0, 501, /* Ơ ơ */ + 0x01a2, 501, /* Ƣ ƣ */ + 0x01a4, 501, /* Ƥ ƥ */ + 0x01a7, 501, /* Ƨ ƨ */ + 0x01a9, 718, /* Ʃ ʃ */ + 0x01ac, 501, /* Ƭ ƭ */ + 0x01ae, 718, /* Ʈ ʈ */ + 0x01af, 501, /* Ư ư */ + 0x01b3, 501, /* Ƴ ƴ */ + 0x01b5, 501, /* Ƶ ƶ */ + 0x01b7, 719, /* Ʒ ʒ */ + 0x01b8, 501, /* Ƹ ƹ */ + 0x01bc, 501, /* Ƽ ƽ */ + 0x01c4, 502, /* DŽ dž */ + 0x01c5, 501, /* Dž dž */ + 0x01c7, 502, /* LJ lj */ + 0x01c8, 501, /* Lj lj */ + 0x01ca, 502, /* NJ nj */ + 0x01cb, 501, /* Nj nj */ + 0x01cd, 501, /* Ǎ ǎ */ + 0x01cf, 501, /* Ǐ ǐ */ + 0x01d1, 501, /* Ǒ ǒ */ + 0x01d3, 501, /* Ǔ ǔ */ + 0x01d5, 501, /* Ǖ ǖ */ + 0x01d7, 501, /* Ǘ ǘ */ + 0x01d9, 501, /* Ǚ ǚ */ + 0x01db, 501, /* Ǜ ǜ */ + 0x01de, 501, /* Ǟ ǟ */ + 0x01e0, 501, /* Ǡ ǡ */ + 0x01e2, 501, /* Ǣ ǣ */ + 0x01e4, 501, /* Ǥ ǥ */ + 0x01e6, 501, /* Ǧ ǧ */ + 0x01e8, 501, /* Ǩ ǩ */ + 0x01ea, 501, /* Ǫ ǫ */ + 0x01ec, 501, /* Ǭ ǭ */ + 0x01ee, 501, /* Ǯ ǯ */ + 0x01f1, 502, /* DZ dz */ + 0x01f2, 501, /* Dz dz */ + 0x01f4, 501, /* Ǵ ǵ */ + 0x01fa, 501, /* Ǻ ǻ */ + 0x01fc, 501, /* Ǽ ǽ */ + 0x01fe, 501, /* Ǿ ǿ */ + 0x0200, 501, /* Ȁ ȁ */ + 0x0202, 501, /* Ȃ ȃ */ + 0x0204, 501, /* Ȅ ȅ */ + 0x0206, 501, /* Ȇ ȇ */ + 0x0208, 501, /* Ȉ ȉ */ + 0x020a, 501, /* Ȋ ȋ */ + 0x020c, 501, /* Ȍ ȍ */ + 0x020e, 501, /* Ȏ ȏ */ + 0x0210, 501, /* Ȑ ȑ */ + 0x0212, 501, /* Ȓ ȓ */ + 0x0214, 501, /* Ȕ ȕ */ + 0x0216, 501, /* Ȗ ȗ */ + 0x0386, 538, /* Ά ά */ + 0x038c, 564, /* Ό ό */ + 0x03e2, 501, /* Ϣ ϣ */ + 0x03e4, 501, /* Ϥ ϥ */ + 0x03e6, 501, /* Ϧ ϧ */ + 0x03e8, 501, /* Ϩ ϩ */ + 0x03ea, 501, /* Ϫ ϫ */ + 0x03ec, 501, /* Ϭ ϭ */ + 0x03ee, 501, /* Ϯ ϯ */ + 0x0460, 501, /* Ѡ ѡ */ + 0x0462, 501, /* Ѣ ѣ */ + 0x0464, 501, /* Ѥ ѥ */ + 0x0466, 501, /* Ѧ ѧ */ + 0x0468, 501, /* Ѩ ѩ */ + 0x046a, 501, /* Ѫ ѫ */ + 0x046c, 501, /* Ѭ ѭ */ + 0x046e, 501, /* Ѯ ѯ */ + 0x0470, 501, /* Ѱ ѱ */ + 0x0472, 501, /* Ѳ ѳ */ + 0x0474, 501, /* Ѵ ѵ */ + 0x0476, 501, /* Ѷ ѷ */ + 0x0478, 501, /* Ѹ ѹ */ + 0x047a, 501, /* Ѻ ѻ */ + 0x047c, 501, /* Ѽ ѽ */ + 0x047e, 501, /* Ѿ ѿ */ + 0x0480, 501, /* Ҁ ҁ */ + 0x0490, 501, /* Ґ ґ */ + 0x0492, 501, /* Ғ ғ */ + 0x0494, 501, /* Ҕ ҕ */ + 0x0496, 501, /* Җ җ */ + 0x0498, 501, /* Ҙ ҙ */ + 0x049a, 501, /* Қ қ */ + 0x049c, 501, /* Ҝ ҝ */ + 0x049e, 501, /* Ҟ ҟ */ + 0x04a0, 501, /* Ҡ ҡ */ + 0x04a2, 501, /* Ң ң */ + 0x04a4, 501, /* Ҥ ҥ */ + 0x04a6, 501, /* Ҧ ҧ */ + 0x04a8, 501, /* Ҩ ҩ */ + 0x04aa, 501, /* Ҫ ҫ */ + 0x04ac, 501, /* Ҭ ҭ */ + 0x04ae, 501, /* Ү ү */ + 0x04b0, 501, /* Ұ ұ */ + 0x04b2, 501, /* Ҳ ҳ */ + 0x04b4, 501, /* Ҵ ҵ */ + 0x04b6, 501, /* Ҷ ҷ */ + 0x04b8, 501, /* Ҹ ҹ */ + 0x04ba, 501, /* Һ һ */ + 0x04bc, 501, /* Ҽ ҽ */ + 0x04be, 501, /* Ҿ ҿ */ + 0x04c1, 501, /* Ӂ ӂ */ + 0x04c3, 501, /* Ӄ ӄ */ + 0x04c7, 501, /* Ӈ ӈ */ + 0x04cb, 501, /* Ӌ ӌ */ + 0x04d0, 501, /* Ӑ ӑ */ + 0x04d2, 501, /* Ӓ ӓ */ + 0x04d4, 501, /* Ӕ ӕ */ + 0x04d6, 501, /* Ӗ ӗ */ + 0x04d8, 501, /* Ә ә */ + 0x04da, 501, /* Ӛ ӛ */ + 0x04dc, 501, /* Ӝ ӝ */ + 0x04de, 501, /* Ӟ ӟ */ + 0x04e0, 501, /* Ӡ ӡ */ + 0x04e2, 501, /* Ӣ ӣ */ + 0x04e4, 501, /* Ӥ ӥ */ + 0x04e6, 501, /* Ӧ ӧ */ + 0x04e8, 501, /* Ө ө */ + 0x04ea, 501, /* Ӫ ӫ */ + 0x04ee, 501, /* Ӯ ӯ */ + 0x04f0, 501, /* Ӱ ӱ */ + 0x04f2, 501, /* Ӳ ӳ */ + 0x04f4, 501, /* Ӵ ӵ */ + 0x04f8, 501, /* Ӹ ӹ */ + 0x1e00, 501, /* Ḁ ḁ */ + 0x1e02, 501, /* Ḃ ḃ */ + 0x1e04, 501, /* Ḅ ḅ */ + 0x1e06, 501, /* Ḇ ḇ */ + 0x1e08, 501, /* Ḉ ḉ */ + 0x1e0a, 501, /* Ḋ ḋ */ + 0x1e0c, 501, /* Ḍ ḍ */ + 0x1e0e, 501, /* Ḏ ḏ */ + 0x1e10, 501, /* Ḑ ḑ */ + 0x1e12, 501, /* Ḓ ḓ */ + 0x1e14, 501, /* Ḕ ḕ */ + 0x1e16, 501, /* Ḗ ḗ */ + 0x1e18, 501, /* Ḙ ḙ */ + 0x1e1a, 501, /* Ḛ ḛ */ + 0x1e1c, 501, /* Ḝ ḝ */ + 0x1e1e, 501, /* Ḟ ḟ */ + 0x1e20, 501, /* Ḡ ḡ */ + 0x1e22, 501, /* Ḣ ḣ */ + 0x1e24, 501, /* Ḥ ḥ */ + 0x1e26, 501, /* Ḧ ḧ */ + 0x1e28, 501, /* Ḩ ḩ */ + 0x1e2a, 501, /* Ḫ ḫ */ + 0x1e2c, 501, /* Ḭ ḭ */ + 0x1e2e, 501, /* Ḯ ḯ */ + 0x1e30, 501, /* Ḱ ḱ */ + 0x1e32, 501, /* Ḳ ḳ */ + 0x1e34, 501, /* Ḵ ḵ */ + 0x1e36, 501, /* Ḷ ḷ */ + 0x1e38, 501, /* Ḹ ḹ */ + 0x1e3a, 501, /* Ḻ ḻ */ + 0x1e3c, 501, /* Ḽ ḽ */ + 0x1e3e, 501, /* Ḿ ḿ */ + 0x1e40, 501, /* Ṁ ṁ */ + 0x1e42, 501, /* Ṃ ṃ */ + 0x1e44, 501, /* Ṅ ṅ */ + 0x1e46, 501, /* Ṇ ṇ */ + 0x1e48, 501, /* Ṉ ṉ */ + 0x1e4a, 501, /* Ṋ ṋ */ + 0x1e4c, 501, /* Ṍ ṍ */ + 0x1e4e, 501, /* Ṏ ṏ */ + 0x1e50, 501, /* Ṑ ṑ */ + 0x1e52, 501, /* Ṓ ṓ */ + 0x1e54, 501, /* Ṕ ṕ */ + 0x1e56, 501, /* Ṗ ṗ */ + 0x1e58, 501, /* Ṙ ṙ */ + 0x1e5a, 501, /* Ṛ ṛ */ + 0x1e5c, 501, /* Ṝ ṝ */ + 0x1e5e, 501, /* Ṟ ṟ */ + 0x1e60, 501, /* Ṡ ṡ */ + 0x1e62, 501, /* Ṣ ṣ */ + 0x1e64, 501, /* Ṥ ṥ */ + 0x1e66, 501, /* Ṧ ṧ */ + 0x1e68, 501, /* Ṩ ṩ */ + 0x1e6a, 501, /* Ṫ ṫ */ + 0x1e6c, 501, /* Ṭ ṭ */ + 0x1e6e, 501, /* Ṯ ṯ */ + 0x1e70, 501, /* Ṱ ṱ */ + 0x1e72, 501, /* Ṳ ṳ */ + 0x1e74, 501, /* Ṵ ṵ */ + 0x1e76, 501, /* Ṷ ṷ */ + 0x1e78, 501, /* Ṹ ṹ */ + 0x1e7a, 501, /* Ṻ ṻ */ + 0x1e7c, 501, /* Ṽ ṽ */ + 0x1e7e, 501, /* Ṿ ṿ */ + 0x1e80, 501, /* Ẁ ẁ */ + 0x1e82, 501, /* Ẃ ẃ */ + 0x1e84, 501, /* Ẅ ẅ */ + 0x1e86, 501, /* Ẇ ẇ */ + 0x1e88, 501, /* Ẉ ẉ */ + 0x1e8a, 501, /* Ẋ ẋ */ + 0x1e8c, 501, /* Ẍ ẍ */ + 0x1e8e, 501, /* Ẏ ẏ */ + 0x1e90, 501, /* Ẑ ẑ */ + 0x1e92, 501, /* Ẓ ẓ */ + 0x1e94, 501, /* Ẕ ẕ */ + 0x1ea0, 501, /* Ạ ạ */ + 0x1ea2, 501, /* Ả ả */ + 0x1ea4, 501, /* Ấ ấ */ + 0x1ea6, 501, /* Ầ ầ */ + 0x1ea8, 501, /* Ẩ ẩ */ + 0x1eaa, 501, /* Ẫ ẫ */ + 0x1eac, 501, /* Ậ ậ */ + 0x1eae, 501, /* Ắ ắ */ + 0x1eb0, 501, /* Ằ ằ */ + 0x1eb2, 501, /* Ẳ ẳ */ + 0x1eb4, 501, /* Ẵ ẵ */ + 0x1eb6, 501, /* Ặ ặ */ + 0x1eb8, 501, /* Ẹ ẹ */ + 0x1eba, 501, /* Ẻ ẻ */ + 0x1ebc, 501, /* Ẽ ẽ */ + 0x1ebe, 501, /* Ế ế */ + 0x1ec0, 501, /* Ề ề */ + 0x1ec2, 501, /* Ể ể */ + 0x1ec4, 501, /* Ễ ễ */ + 0x1ec6, 501, /* Ệ ệ */ + 0x1ec8, 501, /* Ỉ ỉ */ + 0x1eca, 501, /* Ị ị */ + 0x1ecc, 501, /* Ọ ọ */ + 0x1ece, 501, /* Ỏ ỏ */ + 0x1ed0, 501, /* Ố ố */ + 0x1ed2, 501, /* Ồ ồ */ + 0x1ed4, 501, /* Ổ ổ */ + 0x1ed6, 501, /* Ỗ ỗ */ + 0x1ed8, 501, /* Ộ ộ */ + 0x1eda, 501, /* Ớ ớ */ + 0x1edc, 501, /* Ờ ờ */ + 0x1ede, 501, /* Ở ở */ + 0x1ee0, 501, /* Ỡ ỡ */ + 0x1ee2, 501, /* Ợ ợ */ + 0x1ee4, 501, /* Ụ ụ */ + 0x1ee6, 501, /* Ủ ủ */ + 0x1ee8, 501, /* Ứ ứ */ + 0x1eea, 501, /* Ừ ừ */ + 0x1eec, 501, /* Ử ử */ + 0x1eee, 501, /* Ữ ữ */ + 0x1ef0, 501, /* Ự ự */ + 0x1ef2, 501, /* Ỳ ỳ */ + 0x1ef4, 501, /* Ỵ ỵ */ + 0x1ef6, 501, /* Ỷ ỷ */ + 0x1ef8, 501, /* Ỹ ỹ */ + 0x1f59, 492, /* Ὑ ὑ */ + 0x1f5b, 492, /* Ὓ ὓ */ + 0x1f5d, 492, /* Ὕ ὕ */ + 0x1f5f, 492, /* Ὗ ὗ */ + 0x1fbc, 491, /* ᾼ ᾳ */ + 0x1fcc, 491, /* ῌ ῃ */ + 0x1fec, 493, /* Ῥ ῥ */ + 0x1ffc, 491, /* ῼ ῳ */ +}; + +/* + * title characters are those between + * upper and lower case. ie DZ Dz dz + */ +static +Rune __totitle1[] = +{ + 0x01c4, 501, /* DŽ Dž */ + 0x01c6, 499, /* dž Dž */ + 0x01c7, 501, /* LJ Lj */ + 0x01c9, 499, /* lj Lj */ + 0x01ca, 501, /* NJ Nj */ + 0x01cc, 499, /* nj Nj */ + 0x01f1, 501, /* DZ Dz */ + 0x01f3, 499, /* dz Dz */ +}; + +static Rune* +bsearch(Rune c, Rune *t, int n, int ne) +{ + Rune *p; + int m; + + while(n > 1) { + m = n/2; + p = t + m*ne; + if(c >= p[0]) { + t = p; + n = n-m; + } else + n = m; + } + if(n && c >= t[0]) + return t; + return 0; +} + +Rune +tolowerrune(Rune c) +{ + Rune *p; + + p = bsearch(c, __tolower2, nelem(__tolower2)/3, 3); + if(p && c >= p[0] && c <= p[1]) + return c + p[2] - 500; + p = bsearch(c, __tolower1, nelem(__tolower1)/2, 2); + if(p && c == p[0]) + return c + p[1] - 500; + return c; +} + +Rune +toupperrune(Rune c) +{ + Rune *p; + + p = bsearch(c, __toupper2, nelem(__toupper2)/3, 3); + if(p && c >= p[0] && c <= p[1]) + return c + p[2] - 500; + p = bsearch(c, __toupper1, nelem(__toupper1)/2, 2); + if(p && c == p[0]) + return c + p[1] - 500; + return c; +} + +Rune +totitlerune(Rune c) +{ + Rune *p; + + p = bsearch(c, __totitle1, nelem(__totitle1)/2, 2); + if(p && c == p[0]) + return c + p[1] - 500; + return c; +} + +int +islowerrune(Rune c) +{ + Rune *p; + + p = bsearch(c, __toupper2, nelem(__toupper2)/3, 3); + if(p && c >= p[0] && c <= p[1]) + return 1; + p = bsearch(c, __toupper1, nelem(__toupper1)/2, 2); + if(p && c == p[0]) + return 1; + return 0; +} + +int +isupperrune(Rune c) +{ + Rune *p; + + p = bsearch(c, __tolower2, nelem(__tolower2)/3, 3); + if(p && c >= p[0] && c <= p[1]) + return 1; + p = bsearch(c, __tolower1, nelem(__tolower1)/2, 2); + if(p && c == p[0]) + return 1; + return 0; +} + +int +isalpharune(Rune c) +{ + Rune *p; + + if(isupperrune(c) || islowerrune(c)) + return 1; + p = bsearch(c, __alpha2, nelem(__alpha2)/2, 2); + if(p && c >= p[0] && c <= p[1]) + return 1; + p = bsearch(c, __alpha1, nelem(__alpha1), 1); + if(p && c == p[0]) + return 1; + return 0; +} + +int +istitlerune(Rune c) +{ + return isupperrune(c) && islowerrune(c); +} + +int +isspacerune(Rune c) +{ + Rune *p; + + p = bsearch(c, __space2, nelem(__space2)/2, 2); + if(p && c >= p[0] && c <= p[1]) + return 1; + return 0; +} diff --git a/lib/libutf/utf.7 b/lib/libutf/utf.7 @@ -0,0 +1,99 @@ +.deEX +.ift .ft5 +.nf +.. +.deEE +.ft1 +.fi +.. +.TH UTF 7 +.SH NAME +UTF, Unicode, ASCII, rune \- character set and format +.SH DESCRIPTION +The Plan 9 character set and representation are +based on the Unicode Standard and on the ISO multibyte +.SM UTF-8 +encoding (Universal Character +Set Transformation Format, 8 bits wide). +The Unicode Standard represents its characters in 16 +bits; +.SM UTF-8 +represents such +values in an 8-bit byte stream. +Throughout this manual, +.SM UTF-8 +is shortened to +.SM UTF. +.PP +In Plan 9, a +.I rune +is a 16-bit quantity representing a Unicode character. +Internally, programs may store characters as runes. +However, any external manifestation of textual information, +in files or at the interface between programs, uses a +machine-independent, byte-stream encoding called +.SM UTF. +.PP +.SM UTF +is designed so the 7-bit +.SM ASCII +set (values hexadecimal 00 to 7F), +appear only as themselves +in the encoding. +Runes with values above 7F appear as sequences of two or more +bytes with values only from 80 to FF. +.PP +The +.SM UTF +encoding of the Unicode Standard is backward compatible with +.SM ASCII\c +: +programs presented only with +.SM ASCII +work on Plan 9 +even if not written to deal with +.SM UTF, +as do +programs that deal with uninterpreted byte streams. +However, programs that perform semantic processing on +.SM ASCII +graphic +characters must convert from +.SM UTF +to runes +in order to work properly with non-\c +.SM ASCII +input. +See +.IR rune (3). +.PP +Letting numbers be binary, +a rune x is converted to a multibyte +.SM UTF +sequence +as follows: +.PP +01. x in [00000000.0bbbbbbb] → 0bbbbbbb +.br +10. x in [00000bbb.bbbbbbbb] → 110bbbbb, 10bbbbbb +.br +11. x in [bbbbbbbb.bbbbbbbb] → 1110bbbb, 10bbbbbb, 10bbbbbb +.br +.PP +Conversion 01 provides a one-byte sequence that spans the +.SM ASCII +character set in a compatible way. +Conversions 10 and 11 represent higher-valued characters +as sequences of two or three bytes with the high bit set. +Plan 9 does not support the 4, 5, and 6 byte sequences proposed by X-Open. +When there are multiple ways to encode a value, for example rune 0, +the shortest encoding is used. +.PP +In the inverse mapping, +any sequence except those described above +is incorrect and is converted to rune hexadecimal 0080. +.SH "SEE ALSO" +.IR ascii (1), +.IR tcs (1), +.IR rune (3), +.IR "The Unicode Standard" . diff --git a/lib/libutf/utfecpy.c b/lib/libutf/utfecpy.c @@ -0,0 +1,36 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +char* +utfecpy(char *to, char *e, const char *from) +{ + char *end; + + if(to >= e) + return to; + end = memccpy(to, from, '\0', e - to); + if(end == nil){ + end = e-1; + while(end>to && (*--end&0xC0)==0x80) + ; + *end = '\0'; + }else{ + end--; + } + return end; +} diff --git a/lib/libutf/utflen.c b/lib/libutf/utflen.c @@ -0,0 +1,37 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +int +utflen(const char *s) +{ + int c; + long n; + Rune rune; + + n = 0; + for(;;) { + c = *(uchar*)s; + if(c < Runeself) { + if(c == 0) + return n; + s++; + } else + s += chartorune(&rune, s); + n++; + } +} diff --git a/lib/libutf/utfnlen.c b/lib/libutf/utfnlen.c @@ -0,0 +1,41 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +int +utfnlen(const char *s, long m) +{ + int c; + long n; + Rune rune; + const char *es; + + es = s + m; + for(n = 0; s < es; n++) { + c = *(uchar*)s; + if(c < Runeself){ + if(c == '\0') + break; + s++; + continue; + } + if(!fullrune(s, es-s)) + break; + s += chartorune(&rune, s); + } + return n; +} diff --git a/lib/libutf/utfrrune.c b/lib/libutf/utfrrune.c @@ -0,0 +1,45 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +char* +utfrrune(const char *s, long c) +{ + long c1; + Rune r; + const char *s1; + + if(c < Runesync) /* not part of utf sequence */ + return strrchr(s, c); + + s1 = 0; + for(;;) { + c1 = *(uchar*)s; + if(c1 < Runeself) { /* one byte rune */ + if(c1 == 0) + return (char*)s1; + if(c1 == c) + s1 = s; + s++; + continue; + } + c1 = chartorune(&r, s); + if(r == c) + s1 = s; + s += c1; + } +} diff --git a/lib/libutf/utfrune.c b/lib/libutf/utfrune.c @@ -0,0 +1,44 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + +char* +utfrune(const char *s, long c) +{ + long c1; + Rune r; + int n; + + if(c < Runesync) /* not part of utf sequence */ + return strchr(s, c); + + for(;;) { + c1 = *(uchar*)s; + if(c1 < Runeself) { /* one byte rune */ + if(c1 == 0) + return 0; + if(c1 == c) + return (char*)s; + s++; + continue; + } + n = chartorune(&r, s); + if(r == c) + return (char*)s; + s += n; + } +} diff --git a/lib/libutf/utfutf.c b/lib/libutf/utfutf.c @@ -0,0 +1,41 @@ +/* + * The authors of this software are Rob Pike and Ken Thompson. + * Copyright (c) 2002 by Lucent Technologies. + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE + * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ +#include <stdarg.h> +#include <string.h> +#include "plan9.h" +#include "utf.h" + + +/* + * Return pointer to first occurrence of s2 in s1, + * 0 if none + */ +char* +utfutf(const char *s1, const char *s2) +{ + const char *p; + long f, n1, n2; + Rune r; + + n1 = chartorune(&r, s2); + f = r; + if(f <= Runesync) /* represents self */ + return strstr(s1, s2); + + n2 = strlen(s2); + for(p=s1; p=utfrune(p, f); p+=n1) + if(strncmp(p, s2, n2) == 0) + return (char*)p; + return 0; +} diff --git a/lib/libwmii_hack/Makefile b/lib/libwmii_hack/Makefile @@ -0,0 +1,17 @@ +ROOT= ../.. +include $(ROOT)/mk/hdr.mk + +hack.o hack.o_pic: util.c hack.h x11.h + +CFLAGS += $(INCX11) +SOLDFLAGS += $(LIBX11) + +TARG = libwmii_hack +# Can't just link libstuff here. We need PIC objects. +OBJ = hack \ + ../libstuff/util/getbase \ + ../libstuff/util/getlong \ + ../libstuff/util/tokenize + +include $(ROOT)/mk/so.mk + diff --git a/lib/libwmii_hack/hack.c b/lib/libwmii_hack/hack.c @@ -0,0 +1,133 @@ +/* Copyright ©2008 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include "hack.h" +#include <dlfcn.h> +#include <stdbool.h> +#include <stdio.h> +#include <sys/time.h> +#include <sys/types.h> +#include <time.h> +#include <unistd.h> + +#include "util.c" +#include "x11.c" + +enum { + Timeout = 10, +}; + +static void* xlib; + +static long transient; +static Atom types[32]; +static long ntypes; +static char** tags; +static long pid; +static long stime; +static char hostname[256]; +static long nsec; + +typedef Window (*mapfn)(Display*, Window); + +static Window (*mapwindow)(Display*, Window); +static Window (*mapraised)(Display*, Window); + +static void +init(Display *d) { /* Hrm... assumes one display... */ + char *toks[nelem(types)]; + char *s, *p; + long n; + int i; + + xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY); + if(xlib == nil) + return; + mapwindow = (mapfn)(uintptr_t)dlsym(xlib, "XMapWindow"); + mapraised = (mapfn)(uintptr_t)dlsym(xlib, "XMapRaised"); + + unsetenv("LD_PRELOAD"); + + if((s = getenv("WMII_HACK_TRANSIENT"))) { + if(getlong(s, &n)) + transient = n; + unsetenv("WMII_HACK_TRANSIENT"); + } + if((s = getenv("WMII_HACK_TYPE"))) { + s = strdup(s); + unsetenv("WMII_HACK_TYPE"); + + n = tokenize(toks, nelem(toks), s, ','); + for(i=0; i < n; i++) { + for(p=toks[i]; *p; p++) + if(*p >= 'a' && *p <= 'z') + *p += 'A' - 'a'; + toks[i] = smprint("_NET_WM_WINDOW_TYPE_%s", toks[i]); + } + XInternAtoms(d, toks, n, false, types); + ntypes = n; + for(i=0; i < n; i++) + free(toks[i]); + free(s); + } + if((s = getenv("WMII_HACK_TAGS"))) { + s = strdup(s); + unsetenv("WMII_HACK_TAGS"); + + n = tokenize(toks, nelem(toks)-1, s, '+'); + tags = strlistdup(toks, n); + free(s); + } + if((s = getenv("WMII_HACK_TIME"))) { + getlong(s, &stime); + unsetenv("WMII_HACK_TIME"); + } + + pid = getpid(); + gethostname(hostname, sizeof hostname); +} + +static void +setprops(Display *d, Window w) { + long *l; + + if(!xlib) + init(d); + + if(getprop_long(d, w, "_NET_WM_PID", "CARDINAL", 0L, &l, 1L)) + free(l); + else { + changeprop_long(d, w, "_NET_WM_PID", "CARDINAL", &pid, 1); + changeprop_string(d, w, "WM_CLIENT_MACHINE", hostname); + } + + /* Kludge. */ + if(nsec == 0) + nsec = time(0); + else if(time(0) > nsec + Timeout) + return; + + if(transient) + changeprop_long(d, w, "WM_TRANSIENT_FOR", "WINDOW", &transient, 1); + if(ntypes) + changeprop_long(d, w, "_NET_WM_WINDOW_TYPE", "ATOM", (long*)types, ntypes); + if(tags) + changeprop_textlist(d, w, "_WMII_TAGS", "UTF8_STRING", tags); + if(stime) + changeprop_long(d, w, "_WMII_LAUNCH_TIME", "CARDINAL", &stime, 1); +} + +int +XMapWindow(Display *d, Window w) { + + setprops(d, w); + return mapwindow(d, w); +} + +int +XMapRaised(Display *d, Window w) { + + setprops(d, w); + return mapraised(d, w); +} + diff --git a/lib/libwmii_hack/hack.h b/lib/libwmii_hack/hack.h @@ -0,0 +1,28 @@ + +typedef unsigned long ulong; +typedef unsigned int uint; +typedef unsigned char uchar; + +#define _XOPEN_SOURCE 600 +#define IXP_P9_STRUCTS +#define IXP_NO_P9_ +#include <assert.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stuff/util.h> +#include <X11/Xlib.h> + +#define strdup my_strdup +#define smprint my_smprint +#define vsmprint my_vsmprint + +static char* smprint(const char*, ...); +static char* vsmprint(const char*, va_list); +static char* strdup(const char*); + +#define nil ((void*)0) +#define nelem(ary) (sizeof(ary) / sizeof(*ary)) + diff --git a/lib/libwmii_hack/util.c b/lib/libwmii_hack/util.c @@ -0,0 +1,43 @@ +#include <ctype.h> +#include <stdio.h> +#include <string.h> + +static char* +vsmprint(const char *fmt, va_list ap) { + va_list al; + char *buf = ""; + int n; + + va_copy(al, ap); + n = vsnprintf(buf, 0, fmt, al); + va_end(al); + + buf = malloc(++n); + if(buf) + vsnprintf(buf, n, fmt, ap); + return buf; +} + +static char* +smprint(const char *fmt, ...) { + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = vsmprint(fmt, ap); + va_end(ap); + return ret; +} + +static char* +strdup(const char *s) { + char *ret; + int len; + + len = strlen(s)+1; + ret = malloc(len); + if(ret) + memcpy(ret, s, len); + return ret; +} + diff --git a/lib/libwmii_hack/x11.c b/lib/libwmii_hack/x11.c @@ -0,0 +1,213 @@ +/* Copyright ©2007 Kris Maglione <maglione.k at Gmail> + * See LICENSE file for license details. + */ +#include <assert.h> +#include "x11.h" + +/* Misc */ +static Atom +xatom(Display *display, char *name) { + /* Blech. I don't trust Xlib's cacheing. + MapEnt *e; + + e = hash_get(&amap, name, 1); + if(e->val == nil) + e->val = (void*)XInternAtom(display, name, False); + return (Atom)e->val; + */ + return XInternAtom(display, name, False); +} +/* Properties */ +#if 0 +static void +delproperty(Display *display, Window w, char *prop) { + XDeleteProperty(display, w, xatom(display, prop)); +} +#endif + +static void +changeproperty(Display *display, Window w, char *prop, char *type, int width, uchar data[], int n) { + XChangeProperty(display, w, xatom(display, prop), xatom(display, type), width, PropModeReplace, data, n); +} + +static void +changeprop_string(Display *display, Window w, char *prop, char *string) { + changeprop_char(display, w, prop, "UTF8_STRING", string, strlen(string)); +} + +static void +changeprop_char(Display *display, Window w, char *prop, char *type, char data[], int len) { + changeproperty(display, w, prop, type, 8, (uchar*)data, len); +} + +#if 0 +static void +changeprop_short(Display *display, Window w, char *prop, char *type, short data[], int len) { + changeproperty(display, w, prop, type, 16, (uchar*)data, len); +} +#endif + +static void +changeprop_long(Display *display, Window w, char *prop, char *type, long data[], int len) { + changeproperty(display, w, prop, type, 32, (uchar*)data, len); +} + +static void +changeprop_textlist(Display *display, Window w, char *prop, char *type, char *data[]) { + char **p, *s, *t; + int len, n; + + len = 0; + for(p=data; *p; p++) + len += strlen(*p) + 1; + s = malloc(len); + if(s == nil) + return; + t = s; + for(p=data; *p; p++) { + n = strlen(*p) + 1; + memcpy(t, *p, n); + t += n; + } + changeprop_char(display, w, prop, type, s, len); + free(s); +} + +#if 0 +static void +freestringlist(char *list[]) { + XFreeStringList(list); +} +#endif + +static ulong +getprop(Display *display, Window w, char *prop, char *type, Atom *actual, int *format, ulong offset, uchar **ret, ulong length) { + Atom typea; + ulong n, extra; + int status; + + typea = (type ? xatom(display, type) : 0L); + + status = XGetWindowProperty(display, w, + xatom(display, prop), offset, length, False /* delete */, + typea, actual, format, &n, &extra, ret); + + if(status != Success) { + *ret = nil; + return 0; + } + if(n == 0) { + free(*ret); + *ret = nil; + } + return n; +} + +#if 0 +static ulong +getproperty(Display *display, Window w, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length) { + int format; + + return getprop(display, w, prop, type, actual, &format, offset, ret, length); +} +#endif + +static ulong +getprop_long(Display *display, Window w, char *prop, char *type, ulong offset, long **ret, ulong length) { + Atom actual; + ulong n; + int format; + + n = getprop(display, w, prop, type, &actual, &format, offset, (uchar**)ret, length); + if(n == 0 || format == 32 && xatom(display, type) == actual) + return n; + free(*ret); + *ret = 0; + return 0; +} + +#ifdef notdef +static char** +strlistdup(char *list[], int n) { + char **p, *q; + int i, m; + + for(i=0, m=0; i < n; i++) + m += strlen(list[i])+1; + + p = malloc((n+1)*sizeof(char*) + m); + if(p == nil) + return nil; + q = (char*)&p[n+1]; + + for(i=0; i < n; i++) { + p[i] = q; + m = strlen(list[i])+1; + memcpy(q, list[i], m); + q += m; + } + p[n] = nil; + return p; +} +#endif + +static char** +strlistdup(char *list[], int n) { + char **p, *q; + int i, m; + + m = 0; + for(i=0; i < n; i++) + m += strlen(list[i]) + 1; + + p = malloc((n+1) * sizeof(*p) + m); + q = (char*)&p[n+1]; + + for(i=0; i < n; i++) { + p[i] = q; + m = strlen(list[i]) + 1; + memcpy(q, list[i], m); + q += m; + } + p[n] = nil; + return p; +} + +#if 0 +static int +getprop_textlist(Display *display, Window w, char *name, char **ret[]) { + XTextProperty prop; + char **list; + int n; + + n = 0; + + XGetTextProperty(display, w, &prop, xatom(display, name)); + if(prop.nitems > 0) { + if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success) { + *ret = strlistdup(list, n); + XFreeStringList(list); + } + XFree(prop.value); + } + return n; +} +#endif + +#if 0 +static char* +getprop_string(Display *display, Window w, char *name) { + char **list, *str; + int n; + + str = nil; + + n = getprop_textlist(display, w, name, &list); + if(n > 0) + str = strdup(*list); + freestringlist(list); + + return str; +} +#endif + diff --git a/lib/libwmii_hack/x11.h b/lib/libwmii_hack/x11.h @@ -0,0 +1,18 @@ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +static void changeprop_char(Display*, Window, char*, char*, char[], int); +static void changeprop_long(Display*, Window, char*, char*, long[], int); +/* static void changeprop_short(Display*, Window, char*, char*, short[], int); */ +static void changeprop_string(Display*, Window, char*, char*); +static void changeprop_textlist(Display*, Window, char*, char*, char*[]); +static void changeproperty(Display*, Window, char*, char*, int width, uchar*, int); +/* static void delproperty(Display*, Window, char*); */ +/* static void freestringlist(char**); */ +static ulong getprop_long(Display*, Window, char*, char*, ulong, long**, ulong); +/* static char* getprop_string(Display*, Window, char*); */ +/* static int getprop_textlist(Display*, Window, char*, char**[]); */ +/* static ulong getproperty(Display*, Window, char*, char*, Atom*, ulong, uchar**, ulong); */ +static Atom xatom(Display*, char*); + diff --git a/libbio/Makefile b/libbio/Makefile @@ -1,27 +0,0 @@ -ROOT= .. -include ${ROOT}/mk/hdr.mk - -VERSION=2.0 -TARG=libbio - -OBJ=\ - bbuffered\ - bfildes\ - bflush\ - bgetc\ - bgetd\ - bgetrune\ - binit\ - boffset\ - bprint\ - bvprint\ - bputc\ - bputrune\ - brdline\ - brdstr\ - bread\ - bseek\ - bwrite - -include ${ROOT}/mk/lib.mk - diff --git a/libbio/NOTICE b/libbio/NOTICE @@ -1,34 +0,0 @@ -This copyright NOTICE applies to all files in this directory and -subdirectories, unless another copyright notice appears in a given -file or subdirectory. If you take substantial code from this software to use in -other programs, you must somehow include with it an appropriate -copyright notice that includes the copyright notice and the other -notices below. It is fine (and often tidier) to do that in a separate -file such as NOTICE, LICENCE or COPYING. - - Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. - Revisions Copyright © 2000-2005 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----- - -This software is also made available under the Lucent Public License -version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html - diff --git a/libbio/README b/libbio/README @@ -1,5 +0,0 @@ -This software was packaged for Unix by Russ Cox. -Please send comments to rsc@swtch.com. - -http://swtch.com/plan9port/unix - diff --git a/libbio/bbuffered.c b/libbio/bbuffered.c @@ -1,20 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -int -Bbuffered(Biobuf *bp) -{ - switch(bp->state) { - case Bracteof: - case Bractive: - return -bp->icount; - - case Bwactive: - return bp->bsize + bp->ocount; - - case Binactive: - return 0; - } - fprint(2, "Bbuffered: unknown state %d\n", bp->state); - return 0; -} diff --git a/libbio/bcat.c b/libbio/bcat.c @@ -1,46 +0,0 @@ -#include <fmt.h> -#include "bio.h" - -Biobuf bout; - -void -bcat(Biobuf *b, char *name) -{ - char buf[1000]; - int n; - - while((n = Bread(b, buf, sizeof buf)) > 0){ - if(Bwrite(&bout, buf, n) < 0) - fprint(2, "writing during %s: %r\n", name); - } - if(n < 0) - fprint(2, "reading %s: %r\n", name); -} - -int -main(int argc, char **argv) -{ - int i; - Biobuf b, *bp; - Fmt fmt; - - Binit(&bout, 1, O_WRONLY); - Bfmtinit(&fmt, &bout); - fmtprint(&fmt, "hello, world\n"); - Bfmtflush(&fmt); - - if(argc == 1){ - Binit(&b, 0, O_RDONLY); - bcat(&b, "<stdin>"); - }else{ - for(i=1; i<argc; i++){ - if((bp = Bopen(argv[i], O_RDONLY)) == 0){ - fprint(2, "Bopen %s: %r\n", argv[i]); - continue; - } - bcat(bp, argv[i]); - Bterm(bp); - } - } - exit(0); -} diff --git a/libbio/bfildes.c b/libbio/bfildes.c @@ -1,9 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -int -Bfildes(Biobuf *bp) -{ - - return bp->fid; -} diff --git a/libbio/bflush.c b/libbio/bflush.c @@ -1,33 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -int -Bflush(Biobuf *bp) -{ - int n, c; - - switch(bp->state) { - case Bwactive: - n = bp->bsize+bp->ocount; - if(n == 0) - return 0; - c = write(bp->fid, bp->bbuf, n); - if(n == c) { - bp->offset += n; - bp->ocount = -bp->bsize; - return 0; - } - bp->state = Binactive; - bp->ocount = 0; - break; - - case Bracteof: - bp->state = Bractive; - - case Bractive: - bp->icount = 0; - bp->gbuf = bp->ebuf; - return 0; - } - return Beof; -} diff --git a/libbio/bgetc.c b/libbio/bgetc.c @@ -1,53 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -int -Bgetc(Biobuf *bp) -{ - int i; - -loop: - i = bp->icount; - if(i != 0) { - bp->icount = i+1; - return bp->ebuf[i]; - } - if(bp->state != Bractive) { - if(bp->state == Bracteof) - bp->state = Bractive; - return Beof; - } - /* - * get next buffer, try to keep Bungetsize - * characters pre-catenated from the previous - * buffer to allow that many ungets. - */ - memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize); - i = read(bp->fid, bp->bbuf, bp->bsize); - bp->gbuf = bp->bbuf; - if(i <= 0) { - bp->state = Bracteof; - if(i < 0) - bp->state = Binactive; - return Beof; - } - if(i < bp->bsize) { - memmove(bp->ebuf-i-Bungetsize, bp->bbuf-Bungetsize, i+Bungetsize); - bp->gbuf = bp->ebuf-i; - } - bp->icount = -i; - bp->offset += i; - goto loop; -} - -int -Bungetc(Biobuf *bp) -{ - - if(bp->state == Bracteof) - bp->state = Bractive; - if(bp->state != Bractive) - return Beof; - bp->icount--; - return 1; -} diff --git a/libbio/bgetd.c b/libbio/bgetd.c @@ -1,36 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -struct bgetd -{ - Biobuf* b; - int eof; -}; - -static int -Bgetdf(void *vp) -{ - int c; - struct bgetd *bg = vp; - - c = Bgetc(bg->b); - if(c == Beof) - bg->eof = 1; - return c; -} - -int -Bgetd(Biobuf *bp, double *dp) -{ - double d; - struct bgetd b; - - b.b = bp; - b.eof = 0; - d = fmtcharstod(Bgetdf, &b); - if(b.eof) - return -1; - Bungetc(bp); - *dp = d; - return 1; -} diff --git a/libbio/bgetrune.c b/libbio/bgetrune.c @@ -1,47 +0,0 @@ -#include "plan9.h" -#include <bio.h> -#include <utf.h> - -long -Bgetrune(Biobuf *bp) -{ - int c, i; - Rune rune; - char str[4]; - - c = Bgetc(bp); - if(c < Runeself) { /* one char */ - bp->runesize = 1; - return c; - } - str[0] = c; - - for(i=1;;) { - c = Bgetc(bp); - if(c < 0) - return c; - str[i++] = c; - - if(fullrune(str, i)) { - bp->runesize = chartorune(&rune, str); - while(i > bp->runesize) { - Bungetc(bp); - i--; - } - return rune; - } - } -} - -int -Bungetrune(Biobuf *bp) -{ - - if(bp->state == Bracteof) - bp->state = Bractive; - if(bp->state != Bractive) - return Beof; - bp->icount -= bp->runesize; - bp->runesize = 0; - return 1; -} diff --git a/libbio/binit.c b/libbio/binit.c @@ -1,154 +0,0 @@ -#include <stdlib.h> -#include <plan9.h> -#include <bio.h> - -enum -{ - MAXBUFS = 20 -}; - -static Biobuf* wbufs[MAXBUFS]; -static int atexitflag; - -static -void -batexit(void) -{ - Biobuf *bp; - int i; - - for(i=0; i<MAXBUFS; i++) { - bp = wbufs[i]; - if(bp != 0) { - wbufs[i] = 0; - Bflush(bp); - } - } -} - -static -void -deinstall(Biobuf *bp) -{ - int i; - - for(i=0; i<MAXBUFS; i++) - if(wbufs[i] == bp) - wbufs[i] = 0; -} - -static -void -install(Biobuf *bp) -{ - int i; - - deinstall(bp); - for(i=0; i<MAXBUFS; i++) - if(wbufs[i] == 0) { - wbufs[i] = bp; - break; - } - if(atexitflag == 0) { - atexitflag = 1; - atexit(batexit); - } -} - -int -Binits(Biobuf *bp, int f, int mode, unsigned char *p, int size) -{ - - p += Bungetsize; /* make room for Bungets */ - size -= Bungetsize; - - switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) { - default: - fprint(2, "Bopen: unknown mode %d\n", mode); - return Beof; - - case OREAD: - bp->state = Bractive; - bp->ocount = 0; - break; - - case OWRITE: - install(bp); - bp->state = Bwactive; - bp->ocount = -size; - break; - } - bp->bbuf = p; - bp->ebuf = p+size; - bp->bsize = size; - bp->icount = 0; - bp->gbuf = bp->ebuf; - bp->fid = f; - bp->flag = 0; - bp->rdline = 0; - bp->offset = 0; - bp->runesize = 0; - return 0; -} - - -int -Binit(Biobuf *bp, int f, int mode) -{ - return Binits(bp, f, mode, bp->b, sizeof(bp->b)); -} - -Biobuf* -Bfdopen(int f, int mode) -{ - Biobuf *bp; - - bp = malloc(sizeof(Biobuf)); - if(bp == 0) - return 0; - Binits(bp, f, mode, bp->b, sizeof(bp->b)); - bp->flag = Bmagic; - return bp; -} - -Biobuf* -Bopen(const char *name, int mode) -{ - Biobuf *bp; - int f; - - switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) { - default: - fprint(2, "Bopen: unknown mode %d\n", mode); - return 0; - - case OREAD: - f = open(name, OREAD); - if(f < 0) - return 0; - break; - - case OWRITE: - f = creat(name, 0666); - if(f < 0) - return 0; - } - bp = Bfdopen(f, mode); - if(bp == 0) - close(f); - return bp; -} - -int -Bterm(Biobuf *bp) -{ - - deinstall(bp); - Bflush(bp); - if(bp->flag == Bmagic) { - bp->flag = 0; - close(bp->fid); - free(bp); - } - return 0; -} diff --git a/libbio/bio.3 b/libbio/bio.3 @@ -1,371 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH BIO 3 -.SH NAME -Bopen, Bfdopen, Binit, Binits, Brdline, Brdstr, Bgetc, Bgetrune, Bgetd, Bungetc, Bungetrune, Bread, Bseek, Boffset, Bfildes, Blinelen, Bputc, Bputrune, Bprint, Bvprint, Bwrite, Bflush, Bterm, Bbuffered \- buffered input/output -.SH SYNOPSIS -.ta \w'\fLBiobuf* 'u -.B #include <utf.h> -.br -.B #include <fmt.h> -.br -.B #include <bio.h> -.PP -.B -Biobuf* Bopen(char *file, int mode) -.PP -.B -Biobuf* Bfdopen(int fd, int mode) -.PP -.B -int Binit(Biobuf *bp, int fd, int mode) -.PP -.B -int Binits(Biobufhdr *bp, int fd, int mode, uchar *buf, int size) -.PP -.B -int Bterm(Biobufhdr *bp) -.PP -.B -int Bprint(Biobufhdr *bp, char *format, ...) -.PP -.B -int Bvprint(Biobufhdr *bp, char *format, va_list arglist); -.PP -.B -void* Brdline(Biobufhdr *bp, int delim) -.PP -.B -char* Brdstr(Biobufhdr *bp, int delim, int nulldelim) -.PP -.B -int Blinelen(Biobufhdr *bp) -.PP -.B -vlong Boffset(Biobufhdr *bp) -.PP -.B -int Bfildes(Biobufhdr *bp) -.PP -.B -int Bgetc(Biobufhdr *bp) -.PP -.B -long Bgetrune(Biobufhdr *bp) -.PP -.B -int Bgetd(Biobufhdr *bp, double *d) -.PP -.B -int Bungetc(Biobufhdr *bp) -.PP -.B -int Bungetrune(Biobufhdr *bp) -.PP -.B -vlong Bseek(Biobufhdr *bp, vlong n, int type) -.PP -.B -int Bputc(Biobufhdr *bp, int c) -.PP -.B -int Bputrune(Biobufhdr *bp, long c) -.PP -.B -long Bread(Biobufhdr *bp, void *addr, long nbytes) -.PP -.B -long Bwrite(Biobufhdr *bp, void *addr, long nbytes) -.PP -.B -int Bflush(Biobufhdr *bp) -.PP -.B -int Bbuffered(Biobufhdr *bp) -.PP -.SH DESCRIPTION -These routines implement fast buffered I/O. -I/O on different file descriptors is independent. -.PP -.I Bopen -opens -.I file -for mode -.B O_RDONLY -or creates for mode -.BR O_WRONLY . -It calls -.IR malloc (3) -to allocate a buffer. -.PP -.I Bfdopen -allocates a buffer for the already-open file descriptor -.I fd -for mode -.B O_RDONLY -or -.BR O_WRONLY . -It calls -.IR malloc (3) -to allocate a buffer. -.PP -.I Binit -initializes a standard size buffer, type -.IR Biobuf , -with the open file descriptor passed in -by the user. -.I Binits -initializes a non-standard size buffer, type -.IR Biobufhdr , -with the open file descriptor, -buffer area, and buffer size passed in -by the user. -.I Biobuf -and -.I Biobufhdr -are related by the declaration: -.IP -.EX -typedef struct Biobuf Biobuf; -struct Biobuf -{ - Biobufhdr; - uchar b[Bungetsize+Bsize]; -}; -.EE -.PP -Arguments -of types pointer to Biobuf and pointer to Biobufhdr -can be used interchangeably in the following routines. -.PP -.IR Bopen , -.IR Binit , -or -.I Binits -should be called before any of the -other routines on that buffer. -.I Bfildes -returns the integer file descriptor of the associated open file. -.PP -.I Bterm -flushes the buffer for -.IR bp . -If the buffer was allocated by -.IR Bopen , -the buffer is -.I freed -and the file is closed. -.PP -.I Brdline -reads a string from the file associated with -.I bp -up to and including the first -.I delim -character. -The delimiter character at the end of the line is -not altered. -.I Brdline -returns a pointer to the start of the line or -.L 0 -on end-of-file or read error. -.I Blinelen -returns the length (including the delimiter) -of the most recent string returned by -.IR Brdline . -.PP -.I Brdstr -returns a -.IR malloc (3)-allocated -buffer containing the next line of input delimited by -.IR delim , -terminated by a NUL (0) byte. -Unlike -.IR Brdline , -which returns when its buffer is full even if no delimiter has been found, -.I Brdstr -will return an arbitrarily long line in a single call. -If -.I nulldelim -is set, the terminal delimiter will be overwritten with a NUL. -After a successful call to -.IR Brdstr , -the return value of -.I Blinelen -will be the length of the returned buffer, excluding the NUL. -.PP -.I Bgetc -returns the next character from -.IR bp , -or a negative value -at end of file. -.I Bungetc -may be called immediately after -.I Bgetc -to allow the same character to be reread. -.PP -.I Bgetrune -calls -.I Bgetc -to read the bytes of the next -.SM UTF -sequence in the input stream and returns the value of the rune -represented by the sequence. -It returns a negative value -at end of file. -.I Bungetrune -may be called immediately after -.I Bgetrune -to allow the same -.SM UTF -sequence to be reread as either bytes or a rune. -.I Bungetc -and -.I Bungetrune -may back up a maximum of five bytes. -.PP -.I Bgetd -uses -.I fmtcharstod -(see -.IR fmtstrtod (3)) -and -.I Bgetc -to read the formatted -floating-point number in the input stream, -skipping initial blanks and tabs. -The value is stored in -.BR *d. -.PP -.I Bread -reads -.I nbytes -of data from -.I bp -into memory starting at -.IR addr . -The number of bytes read is returned on success -and a negative value is returned if a read error occurred. -.PP -.I Bseek -applies -.IR lseek (2) -to -.IR bp . -It returns the new file offset. -.I Boffset -returns the file offset of the next character to be processed. -.PP -.I Bputc -outputs the low order 8 bits of -.I c -on -.IR bp . -If this causes a -.IR write -to occur and there is an error, -a negative value is returned. -Otherwise, a zero is returned. -.PP -.I Bputrune -calls -.I Bputc -to output the low order -16 bits of -.I c -as a rune -in -.SM UTF -format -on the output stream. -.PP -.I Bprint -is a buffered interface to -.IR print (3). -If this causes a -.IR write -to occur and there is an error, -a negative value -.RB ( Beof ) -is returned. -Otherwise, the number of bytes output is returned. -.I Bvprint -does the same except it takes as argument a -.B va_list -parameter, so it can be called within a variadic function. -.PP -.I Bwrite -outputs -.I nbytes -of data starting at -.I addr -to -.IR bp . -If this causes a -.IR write -to occur and there is an error, -a negative value is returned. -Otherwise, the number of bytes written is returned. -.PP -.I Bflush -causes any buffered output associated with -.I bp -to be written. -The return is as for -.IR Bputc . -.I Bflush -is called on -exit for every buffer still open -for writing. -.PP -.I Bbuffered -returns the number of bytes in the buffer. -When reading, this is the number of bytes still available from the last -read on the file; when writing, it is the number of bytes ready to be -written. -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH SEE ALSO -.IR open (2), -.IR print (3), -.IR atexit (3), -.IR utf (7), -.SH DIAGNOSTICS -.I Bio -routines that return integers yield -.B Beof -if -.I bp -is not the descriptor of an open file. -.I Bopen -returns zero if the file cannot be opened in the given mode. -All routines set -.I errstr -on error. -.SH BUGS -.I Brdline -returns an error on strings longer than the buffer associated -with the file -and also if the end-of-file is encountered -before a delimiter. -.I Blinelen -will tell how many characters are available -in these cases. -In the case of a true end-of-file, -.I Blinelen -will return zero. -At the cost of allocating a buffer, -.I Brdstr -sidesteps these issues. -.PP -The data returned by -.I Brdline -may be overwritten by calls to any other -.I bio -routine on the same -.IR bp. diff --git a/libbio/boffset.c b/libbio/boffset.c @@ -1,25 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -off_t -Boffset(Biobuf *bp) -{ - off_t n; - - switch(bp->state) { - default: - fprint(2, "Boffset: unknown state %d\n", bp->state); - n = Beof; - break; - - case Bracteof: - case Bractive: - n = bp->offset + bp->icount; - break; - - case Bwactive: - n = bp->offset + (bp->bsize + bp->ocount); - break; - } - return n; -} diff --git a/libbio/bprint.c b/libbio/bprint.c @@ -1,14 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -int -Bprint(Biobuf *bp, const char *fmt, ...) -{ - int n; - va_list arg; - - va_start(arg, fmt); - n = Bvprint(bp, fmt, arg); - va_end(arg); - return n; -} diff --git a/libbio/bputc.c b/libbio/bputc.c @@ -1,20 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -int -Bputc(Biobuf *bp, int c) -{ - int i; - - for(;;) { - i = bp->ocount; - if(i) { - bp->ebuf[i++] = c; - bp->ocount = i; - return 0; - } - if(Bflush(bp) == Beof) - break; - } - return Beof; -} diff --git a/libbio/bputrune.c b/libbio/bputrune.c @@ -1,23 +0,0 @@ -#include "plan9.h" -#include <bio.h> -#include <utf.h> - -int -Bputrune(Biobuf *bp, long c) -{ - Rune rune; - char str[4]; - int n; - - rune = c; - if(rune < Runeself) { - Bputc(bp, rune); - return 1; - } - n = runetochar(str, &rune); - if(n == 0) - return Bbad; - if(Bwrite(bp, str, n) != n) - return Beof; - return n; -} diff --git a/libbio/brdline.c b/libbio/brdline.c @@ -1,94 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -void* -Brdline(Biobuf *bp, int delim) -{ - char *ip, *ep; - int i, j; - - i = -bp->icount; - if(i == 0) { - /* - * eof or other error - */ - if(bp->state != Bractive) { - if(bp->state == Bracteof) - bp->state = Bractive; - bp->rdline = 0; - bp->gbuf = bp->ebuf; - return 0; - } - } - - /* - * first try in remainder of buffer (gbuf doesn't change) - */ - ip = (char*)bp->ebuf - i; - ep = memchr(ip, delim, i); - if(ep) { - j = (ep - ip) + 1; - bp->rdline = j; - bp->icount += j; - return ip; - } - - /* - * copy data to beginning of buffer - */ - if(i < bp->bsize) - memmove(bp->bbuf, ip, i); - bp->gbuf = bp->bbuf; - - /* - * append to buffer looking for the delim - */ - ip = (char*)bp->bbuf + i; - while(i < bp->bsize) { - j = read(bp->fid, ip, bp->bsize-i); - if(j <= 0) { - /* - * end of file with no delim - */ - memmove(bp->ebuf-i, bp->bbuf, i); - bp->rdline = i; - bp->icount = -i; - bp->gbuf = bp->ebuf-i; - return 0; - } - bp->offset += j; - i += j; - ep = memchr(ip, delim, j); - if(ep) { - /* - * found in new piece - * copy back up and reset everything - */ - ip = (char*)bp->ebuf - i; - if(i < bp->bsize){ - memmove(ip, bp->bbuf, i); - bp->gbuf = (unsigned char*)ip; - } - j = (ep - (char*)bp->bbuf) + 1; - bp->rdline = j; - bp->icount = j - i; - return ip; - } - ip += j; - } - - /* - * full buffer without finding - */ - bp->rdline = bp->bsize; - bp->icount = -bp->bsize; - bp->gbuf = bp->bbuf; - return 0; -} - -int -Blinelen(Biobuf *bp) -{ - - return bp->rdline; -} diff --git a/libbio/brdstr.c b/libbio/brdstr.c @@ -1,112 +0,0 @@ -#include <stdlib.h> -#include <plan9.h> -#include <bio.h> - -static char* -badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim) -{ - int n; - - n = *np; - p = realloc(p, n+ndata+1); - if(p){ - memmove(p+n, data, ndata); - n += ndata; - if(n>0 && nulldelim && p[n-1]==delim) - p[--n] = '\0'; - else - p[n] = '\0'; - *np = n; - } - return p; -} - -char* -Brdstr(Biobuf *bp, int delim, int nulldelim) -{ - char *ip, *ep, *p; - int i, j; - - i = -bp->icount; - bp->rdline = 0; - if(i == 0) { - /* - * eof or other error - */ - if(bp->state != Bractive) { - if(bp->state == Bracteof) - bp->state = Bractive; - bp->gbuf = bp->ebuf; - return nil; - } - } - - /* - * first try in remainder of buffer (gbuf doesn't change) - */ - ip = (char*)bp->ebuf - i; - ep = memchr(ip, delim, i); - if(ep) { - j = (ep - ip) + 1; - bp->icount += j; - return badd(nil, &bp->rdline, ip, j, delim, nulldelim); - } - - /* - * copy data to beginning of buffer - */ - if(i < bp->bsize) - memmove(bp->bbuf, ip, i); - bp->gbuf = bp->bbuf; - - /* - * append to buffer looking for the delim - */ - p = nil; - for(;;){ - ip = (char*)bp->bbuf + i; - while(i < bp->bsize) { - j = read(bp->fid, ip, bp->bsize-i); - if(j <= 0 && i == 0) - return p; - if(j <= 0 && i > 0){ - /* - * end of file but no delim. pretend we got a delim - * by making the delim \0 and smashing it with nulldelim. - */ - j = 1; - ep = ip; - delim = '\0'; - nulldelim = 1; - *ep = delim; /* there will be room for this */ - }else{ - bp->offset += j; - ep = memchr(ip, delim, j); - } - i += j; - if(ep) { - /* - * found in new piece - * copy back up and reset everything - */ - ip = (char*)bp->ebuf - i; - if(i < bp->bsize){ - memmove(ip, bp->bbuf, i); - bp->gbuf = (unsigned char*)ip; - } - j = (ep - (char*)bp->bbuf) + 1; - bp->icount = j - i; - return badd(p, &bp->rdline, ip, j, delim, nulldelim); - } - ip += j; - } - - /* - * full buffer without finding; add to user string and continue - */ - p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0); - i = 0; - bp->icount = 0; - bp->gbuf = bp->ebuf; - } -} diff --git a/libbio/bread.c b/libbio/bread.c @@ -1,45 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -long -Bread(Biobuf *bp, void *ap, long count) -{ - long c; - unsigned char *p; - int i, n, ic; - - p = ap; - c = count; - ic = bp->icount; - - while(c > 0) { - n = -ic; - if(n > c) - n = c; - if(n == 0) { - if(bp->state != Bractive) - break; - i = read(bp->fid, bp->bbuf, bp->bsize); - if(i <= 0) { - bp->state = Bracteof; - if(i < 0) - bp->state = Binactive; - break; - } - bp->gbuf = bp->bbuf; - bp->offset += i; - if(i < bp->bsize) { - memmove(bp->ebuf-i, bp->bbuf, i); - bp->gbuf = bp->ebuf-i; - } - ic = -i; - continue; - } - memmove(p, bp->ebuf+ic, n); - c -= n; - ic += n; - p += n; - } - bp->icount = ic; - return count-c; -} diff --git a/libbio/bseek.c b/libbio/bseek.c @@ -1,60 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -off_t -Bseek(Biobuf *bp, off_t offset, int base) -{ - vlong n, d; - int bufsz; - - switch(bp->state) { - default: - fprint(2, "Bseek: unknown state %d\n", bp->state); - return Beof; - - case Bracteof: - bp->state = Bractive; - bp->icount = 0; - bp->gbuf = bp->ebuf; - - case Bractive: - n = offset; - if(base == 1) { - n += Boffset(bp); - base = 0; - } - - /* - * try to seek within buffer - */ - if(base == 0) { - d = n - Boffset(bp); - bufsz = bp->ebuf - bp->gbuf; - if(-bufsz <= d && d <= bufsz){ - bp->icount += d; - if(d >= 0) { - if(bp->icount <= 0) - return n; - } else { - if(bp->ebuf - bp->gbuf >= -bp->icount) - return n; - } - } - } - - /* - * reset the buffer - */ - n = lseek(bp->fid, n, base); - bp->icount = 0; - bp->gbuf = bp->ebuf; - break; - - case Bwactive: - Bflush(bp); - n = lseek(bp->fid, offset, base); - break; - } - bp->offset = n; - return n; -} diff --git a/libbio/bvprint.c b/libbio/bvprint.c @@ -1,36 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -static int -fmtBflush(Fmt *f) -{ - Biobuf *bp; - - bp = f->farg; - bp->ocount = (char*)f->to - (char*)f->stop; - if(Bflush(bp) < 0) - return 0; - f->stop = bp->ebuf; - f->to = (char*)f->stop + bp->ocount; - f->start = f->to; - return 1; -} - -int -Bvprint(Biobuf *bp, const char *fmt, va_list arg) -{ - int n; - Fmt f; - - f.runes = 0; - f.stop = bp->ebuf; - f.start = (char*)f.stop + bp->ocount; - f.to = f.start; - f.flush = fmtBflush; - f.farg = bp; - f.nfmt = 0; - n = fmtvprint(&f, fmt, arg); - bp->ocount = (char*)f.to - (char*)f.stop; - return n; -} - diff --git a/libbio/bwrite.c b/libbio/bwrite.c @@ -1,38 +0,0 @@ -#include "plan9.h" -#include <bio.h> - -long -Bwrite(Biobuf *bp, void *ap, long count) -{ - long c; - unsigned char *p; - int i, n, oc; - - p = ap; - c = count; - oc = bp->ocount; - - while(c > 0) { - n = -oc; - if(n > c) - n = c; - if(n == 0) { - if(bp->state != Bwactive) - return Beof; - i = write(bp->fid, bp->bbuf, bp->bsize); - if(i != bp->bsize) { - bp->state = Binactive; - return Beof; - } - bp->offset += i; - oc = -bp->bsize; - continue; - } - memmove(bp->ebuf+oc, p, n); - oc += n; - c -= n; - p += n; - } - bp->ocount = oc; - return count-c; -} diff --git a/libfmt/Makefile b/libfmt/Makefile @@ -1,48 +0,0 @@ -ROOT= .. -include ${ROOT}/mk/hdr.mk - -VERSION=2.0 -TARG=libfmt - -NUM=\ - charstod\ - pow10\ - nan64 - -OBJ=\ - dofmt\ - dorfmt\ - errfmt\ - fltfmt\ - fmt\ - fmtfd\ - fmtfdflush\ - fmtlock\ - fmtprint\ - fmtquote\ - fmtrune\ - fmtstr\ - fmtvprint\ - fprint\ - print\ - runefmtstr\ - runeseprint\ - runesmprint\ - runesnprint\ - runesprint\ - runevseprint\ - runevsmprint\ - runevsnprint\ - seprint\ - smprint\ - snprint\ - sprint\ - strtod\ - vfprint\ - vseprint\ - vsmprint\ - vsnprint\ - $(NUM) - -include ${ROOT}/mk/lib.mk - diff --git a/libfmt/NOTICE b/libfmt/NOTICE @@ -1,25 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -This is a Unix port of the Plan 9 formatted I/O package. - -Please send comments about the packaging -to Russ Cox <rsc@swtch.com>. - - ----- - -This software is also made available under the Lucent Public License -version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html - diff --git a/libfmt/README b/libfmt/README @@ -1,5 +0,0 @@ -This software was packaged for Unix by Russ Cox. -Please send comments to rsc@swtch.com. - -http://swtch.com/plan9port/unix - diff --git a/libfmt/charstod.c b/libfmt/charstod.c @@ -1,85 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* - * Reads a floating-point number by interpreting successive characters - * returned by (*f)(vp). The last call it makes to f terminates the - * scan, so is not a character in the number. It may therefore be - * necessary to back up the input stream up one byte after calling charstod. - */ - -double -fmtcharstod(int(*f)(void*), void *vp) -{ - double num, dem; - int neg, eneg, dig, exp, c; - - num = 0; - neg = 0; - dig = 0; - exp = 0; - eneg = 0; - - c = (*f)(vp); - while(c == ' ' || c == '\t') - c = (*f)(vp); - if(c == '-' || c == '+'){ - if(c == '-') - neg = 1; - c = (*f)(vp); - } - while(c >= '0' && c <= '9'){ - num = num*10 + c-'0'; - c = (*f)(vp); - } - if(c == '.') - c = (*f)(vp); - while(c >= '0' && c <= '9'){ - num = num*10 + c-'0'; - dig++; - c = (*f)(vp); - } - if(c == 'e' || c == 'E'){ - c = (*f)(vp); - if(c == '-' || c == '+'){ - if(c == '-'){ - dig = -dig; - eneg = 1; - } - c = (*f)(vp); - } - while(c >= '0' && c <= '9'){ - exp = exp*10 + c-'0'; - c = (*f)(vp); - } - } - exp -= dig; - if(exp < 0){ - exp = -exp; - eneg = !eneg; - } - dem = __fmtpow10(exp); - if(eneg) - num /= dem; - else - num *= dem; - if(neg) - return -num; - return num; -} diff --git a/libfmt/dofmt.c b/libfmt/dofmt.c @@ -1,537 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* format the output into f->to and return the number of characters fmted */ -int -dofmt(Fmt *f, const char *fmt) -{ - Rune rune, *rt, *rs; - int r; - char *t, *s; - int n, nfmt; - - nfmt = f->nfmt; - for(;;){ - if(f->runes){ - rt = (Rune*)f->to; - rs = (Rune*)f->stop; - while((r = *(uchar*)fmt) && r != '%'){ - if(r < Runeself) - fmt++; - else{ - fmt += chartorune(&rune, fmt); - r = rune; - } - FMTRCHAR(f, rt, rs, r); - } - fmt++; - f->nfmt += rt - (Rune *)f->to; - f->to = rt; - if(!r) - return f->nfmt - nfmt; - f->stop = rs; - }else{ - t = (char*)f->to; - s = (char*)f->stop; - while((r = *(uchar*)fmt) && r != '%'){ - if(r < Runeself){ - FMTCHAR(f, t, s, r); - fmt++; - }else{ - n = chartorune(&rune, fmt); - if(t + n > s){ - t = (char*)__fmtflush(f, t, n); - if(t != nil) - s = (char*)f->stop; - else - return -1; - } - while(n--) - *t++ = *fmt++; - } - } - fmt++; - f->nfmt += t - (char *)f->to; - f->to = t; - if(!r) - return f->nfmt - nfmt; - f->stop = s; - } - - fmt = (char*)__fmtdispatch(f, fmt, 0); - if(fmt == nil) - return -1; - } -} - -void * -__fmtflush(Fmt *f, void *t, int len) -{ - if(f->runes) - f->nfmt += (Rune*)t - (Rune*)f->to; - else - f->nfmt += (char*)t - (char *)f->to; - f->to = t; - if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){ - f->stop = f->to; - return nil; - } - return f->to; -} - -/* - * put a formatted block of memory sz bytes long of n runes into the output buffer, - * left/right justified in a field of at least f->width charactes - */ -int -__fmtpad(Fmt *f, int n) -{ - char *t, *s; - int i; - - t = (char*)f->to; - s = (char*)f->stop; - for(i = 0; i < n; i++) - FMTCHAR(f, t, s, ' '); - f->nfmt += t - (char *)f->to; - f->to = t; - return 0; -} - -int -__rfmtpad(Fmt *f, int n) -{ - Rune *t, *s; - int i; - - t = (Rune*)f->to; - s = (Rune*)f->stop; - for(i = 0; i < n; i++) - FMTRCHAR(f, t, s, ' '); - f->nfmt += t - (Rune *)f->to; - f->to = t; - return 0; -} - -int -__fmtcpy(Fmt *f, const void *vm, int n, int sz) -{ - Rune *rt, *rs, r; - char *t, *s, *m, *me; - ulong fl; - int nc, w; - - m = (char*)vm; - me = m + sz; - w = f->width; - fl = f->flags; - if((fl & FmtPrec) && n > f->prec) - n = f->prec; - if(f->runes){ - if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) - return -1; - rt = (Rune*)f->to; - rs = (Rune*)f->stop; - for(nc = n; nc > 0; nc--){ - r = *(uchar*)m; - if(r < Runeself) - m++; - else if((me - m) >= UTFmax || fullrune(m, me-m)) - m += chartorune(&r, m); - else - break; - FMTRCHAR(f, rt, rs, r); - } - f->nfmt += rt - (Rune *)f->to; - f->to = rt; - if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) - return -1; - }else{ - if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) - return -1; - t = (char*)f->to; - s = (char*)f->stop; - for(nc = n; nc > 0; nc--){ - r = *(uchar*)m; - if(r < Runeself) - m++; - else if((me - m) >= UTFmax || fullrune(m, me-m)) - m += chartorune(&r, m); - else - break; - FMTRUNE(f, t, s, r); - } - f->nfmt += t - (char *)f->to; - f->to = t; - if(fl & FmtLeft && __fmtpad(f, w - n) < 0) - return -1; - } - return 0; -} - -int -__fmtrcpy(Fmt *f, const void *vm, int n) -{ - Rune r, *m, *me, *rt, *rs; - char *t, *s; - ulong fl; - int w; - - m = (Rune*)vm; - w = f->width; - fl = f->flags; - if((fl & FmtPrec) && n > f->prec) - n = f->prec; - if(f->runes){ - if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) - return -1; - rt = (Rune*)f->to; - rs = (Rune*)f->stop; - for(me = m + n; m < me; m++) - FMTRCHAR(f, rt, rs, *m); - f->nfmt += rt - (Rune *)f->to; - f->to = rt; - if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) - return -1; - }else{ - if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) - return -1; - t = (char*)f->to; - s = (char*)f->stop; - for(me = m + n; m < me; m++){ - r = *m; - FMTRUNE(f, t, s, r); - } - f->nfmt += t - (char *)f->to; - f->to = t; - if(fl & FmtLeft && __fmtpad(f, w - n) < 0) - return -1; - } - return 0; -} - -/* fmt out one character */ -int -__charfmt(Fmt *f) -{ - char x[1]; - - x[0] = va_arg(f->args, int); - f->prec = 1; - return __fmtcpy(f, (const char*)x, 1, 1); -} - -/* fmt out one rune */ -int -__runefmt(Fmt *f) -{ - Rune x[1]; - - x[0] = va_arg(f->args, int); - return __fmtrcpy(f, (const void*)x, 1); -} - -/* public helper routine: fmt out a null terminated string already in hand */ -int -fmtstrcpy(Fmt *f, const char *s) -{ - int i, j; - Rune r; - - if(!s) - return __fmtcpy(f, "<nil>", 5, 5); - /* if precision is specified, make sure we don't wander off the end */ - if(f->flags & FmtPrec){ - i = 0; - for(j=0; j<f->prec && s[i]; j++) - i += chartorune(&r, s+i); - return __fmtcpy(f, s, j, i); - } - return __fmtcpy(f, s, utflen(s), strlen(s)); -} - -/* fmt out a null terminated utf string */ -int -__strfmt(Fmt *f) -{ - char *s; - - s = va_arg(f->args, char *); - return fmtstrcpy(f, s); -} - -/* public helper routine: fmt out a null terminated rune string already in hand */ -int -fmtrunestrcpy(Fmt *f, Rune *s) -{ - Rune *e; - int n, p; - - if(!s) - return __fmtcpy(f, "<nil>", 5, 5); - /* if precision is specified, make sure we don't wander off the end */ - if(f->flags & FmtPrec){ - p = f->prec; - for(n = 0; n < p; n++) - if(s[n] == 0) - break; - }else{ - for(e = s; *e; e++) - ; - n = e - s; - } - return __fmtrcpy(f, s, n); -} - -/* fmt out a null terminated rune string */ -int -__runesfmt(Fmt *f) -{ - Rune *s; - - s = va_arg(f->args, Rune *); - return fmtrunestrcpy(f, s); -} - -/* fmt a % */ -int -__percentfmt(Fmt *f) -{ - Rune x[1]; - - x[0] = f->r; - f->prec = 1; - return __fmtrcpy(f, (const void*)x, 1); -} - -/* fmt an integer */ -int -__ifmt(Fmt *f) -{ - char buf[70], *p, *conv; - uvlong vu; - ulong u; - int neg, base, i, n, fl, w, isv; - - neg = 0; - fl = f->flags; - isv = 0; - vu = 0; - u = 0; - if(f->r == 'p'){ - u = (ulong)va_arg(f->args, void*); - f->r = 'x'; - fl |= FmtUnsigned; - }else if(fl & FmtVLong){ - isv = 1; - if(fl & FmtUnsigned) - vu = va_arg(f->args, uvlong); - else - vu = va_arg(f->args, vlong); - }else if(fl & FmtLong){ - if(fl & FmtUnsigned) - u = va_arg(f->args, ulong); - else - u = va_arg(f->args, long); - }else if(fl & FmtByte){ - if(fl & FmtUnsigned) - u = (uchar)va_arg(f->args, int); - else - u = (char)va_arg(f->args, int); - }else if(fl & FmtShort){ - if(fl & FmtUnsigned) - u = (ushort)va_arg(f->args, int); - else - u = (short)va_arg(f->args, int); - }else{ - if(fl & FmtUnsigned) - u = va_arg(f->args, uint); - else - u = va_arg(f->args, int); - } - conv = "0123456789abcdef"; - switch(f->r){ - case 'd': - case 'i': - case 'u': - base = 10; - break; - case 'x': - base = 16; - break; - case 'X': - base = 16; - conv = "0123456789ABCDEF"; - break; - case 'b': - base = 2; - break; - case 'o': - base = 8; - break; - default: - return -1; - } - if(!(fl & FmtUnsigned)){ - if(isv && (vlong)vu < 0){ - vu = -(vlong)vu; - neg = 1; - }else if(!isv && (long)u < 0){ - u = -(long)u; - neg = 1; - } - } - p = buf + sizeof buf - 1; - n = 0; - if(isv){ - while(vu){ - i = vu % base; - vu /= base; - if((fl & FmtComma) && n % 4 == 3){ - *p-- = ','; - n++; - } - *p-- = conv[i]; - n++; - } - }else{ - while(u){ - i = u % base; - u /= base; - if((fl & FmtComma) && n % 4 == 3){ - *p-- = ','; - n++; - } - *p-- = conv[i]; - n++; - } - } - if(n == 0){ - *p-- = '0'; - n = 1; - } - for(w = f->prec; n < w && p > buf+3; n++) - *p-- = '0'; - if(neg || (fl & (FmtSign|FmtSpace))) - n++; - if(fl & FmtSharp){ - if(base == 16) - n += 2; - else if(base == 8){ - if(p[1] == '0') - fl &= ~FmtSharp; - else - n++; - } - } - if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){ - for(w = f->width; n < w && p > buf+3; n++) - *p-- = '0'; - f->width = 0; - } - if(fl & FmtSharp){ - if(base == 16) - *p-- = f->r; - if(base == 16 || base == 8) - *p-- = '0'; - } - if(neg) - *p-- = '-'; - else if(fl & FmtSign) - *p-- = '+'; - else if(fl & FmtSpace) - *p-- = ' '; - f->flags &= ~FmtPrec; - return __fmtcpy(f, p + 1, n, n); -} - -int -__countfmt(Fmt *f) -{ - void *p; - ulong fl; - - fl = f->flags; - p = va_arg(f->args, void*); - if(fl & FmtVLong){ - *(vlong*)p = f->nfmt; - }else if(fl & FmtLong){ - *(long*)p = f->nfmt; - }else if(fl & FmtByte){ - *(char*)p = f->nfmt; - }else if(fl & FmtShort){ - *(short*)p = f->nfmt; - }else{ - *(int*)p = f->nfmt; - } - return 0; -} - -int -__flagfmt(Fmt *f) -{ - switch(f->r){ - case ',': - f->flags |= FmtComma; - break; - case '-': - f->flags |= FmtLeft; - break; - case '+': - f->flags |= FmtSign; - break; - case '#': - f->flags |= FmtSharp; - break; - case ' ': - f->flags |= FmtSpace; - break; - case 'u': - f->flags |= FmtUnsigned; - break; - case 'h': - if(f->flags & FmtShort) - f->flags |= FmtByte; - f->flags |= FmtShort; - break; - case 'L': - f->flags |= FmtLDouble; - break; - case 'l': - if(f->flags & FmtLong) - f->flags |= FmtVLong; - f->flags |= FmtLong; - break; - } - return 1; -} - -/* default error format */ -int -__badfmt(Fmt *f) -{ - char x[3]; - - x[0] = '%'; - x[1] = f->r; - x[2] = '%'; - f->prec = 3; - __fmtcpy(f, (const void*)x, 3, 3); - return 0; -} diff --git a/libfmt/dorfmt.c b/libfmt/dorfmt.c @@ -1,60 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* format the output into f->to and return the number of characters fmted */ - -int -dorfmt(Fmt *f, const Rune *fmt) -{ - Rune *rt, *rs; - int r; - char *t, *s; - int nfmt; - - nfmt = f->nfmt; - for(;;){ - if(f->runes){ - rt = f->to; - rs = f->stop; - while((r = *fmt++) && r != '%'){ - FMTRCHAR(f, rt, rs, r); - } - f->nfmt += rt - (Rune *)f->to; - f->to = rt; - if(!r) - return f->nfmt - nfmt; - f->stop = rs; - }else{ - t = f->to; - s = f->stop; - while((r = *fmt++) && r != '%'){ - FMTRUNE(f, t, f->stop, r); - } - f->nfmt += t - (char *)f->to; - f->to = t; - if(!r) - return f->nfmt - nfmt; - f->stop = s; - } - - fmt = __fmtdispatch(f, (Rune*)fmt, 1); - if(fmt == nil) - return -1; - } -} diff --git a/libfmt/errfmt.c b/libfmt/errfmt.c @@ -1,28 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -__errfmt(Fmt *f) -{ - char *s; - - s = strerror(errno); - return fmtstrcpy(f, s); -} diff --git a/libfmt/fltfmt.c b/libfmt/fltfmt.c @@ -1,392 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdio.h> -#include <math.h> -#include <float.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <stdarg.h> -#include <ctype.h> -#include "plan9.h" -#include "fmtdef.h" - -enum -{ - FDIGIT = 30, - FDEFLT = 6, - NSIGNIF = 17 -}; - -/* - * first few powers of 10, enough for about 1/2 of the - * total space for doubles. - */ -static double pows10[] = -{ - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, - 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, - 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, - 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, - 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, - 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, - 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, - 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, - 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, - 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, - 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, - 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, - 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, - 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, -}; - -#define pow10(x) fmtpow10(x) - -static double -pow10(int n) -{ - double d; - int neg; - - neg = 0; - if(n < 0){ - if(n < DBL_MIN_10_EXP){ - return 0.; - } - neg = 1; - n = -n; - }else if(n > DBL_MAX_10_EXP){ - return HUGE_VAL; - } - if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))) - d = pows10[n]; - else{ - d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1]; - for(;;){ - n -= sizeof(pows10)/sizeof(pows10[0]) - 1; - if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){ - d *= pows10[n]; - break; - } - d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1]; - } - } - if(neg){ - return 1./d; - } - return d; -} - -static int -xadd(char *a, int n, int v) -{ - char *b; - int c; - - if(n < 0 || n >= NSIGNIF) - return 0; - for(b = a+n; b >= a; b--) { - c = *b + v; - if(c <= '9') { - *b = c; - return 0; - } - *b = '0'; - v = 1; - } - *a = '1'; /* overflow adding */ - return 1; -} - -static int -xsub(char *a, int n, int v) -{ - char *b; - int c; - - for(b = a+n; b >= a; b--) { - c = *b - v; - if(c >= '0') { - *b = c; - return 0; - } - *b = '9'; - v = 1; - } - *a = '9'; /* underflow subtracting */ - return 1; -} - -static void -xdtoa(Fmt *fmt, char *s2, double f) -{ - char s1[NSIGNIF+10]; - double g, h; - int e, d, i, n; - int c1, c2, c3, c4, ucase, sign, chr, prec; - - prec = FDEFLT; - if(fmt->flags & FmtPrec) - prec = fmt->prec; - if(prec > FDIGIT) - prec = FDIGIT; - if(__isNaN(f)) { - strcpy(s2, "NaN"); - return; - } - if(__isInf(f, 1)) { - strcpy(s2, "+Inf"); - return; - } - if(__isInf(f, -1)) { - strcpy(s2, "-Inf"); - return; - } - sign = 0; - if(f < 0) { - f = -f; - sign++; - } - ucase = 0; - chr = fmt->r; - if(isupper(chr)) { - ucase = 1; - chr = tolower(chr); - } - - e = 0; - g = f; - if(g != 0) { - frexp(f, &e); - e = e * .301029995664; - if(e >= -150 && e <= +150) { - d = 0; - h = f; - } else { - d = e/2; - h = f * pow10(-d); - } - g = h * pow10(d-e); - while(g < 1) { - e--; - g = h * pow10(d-e); - } - while(g >= 10) { - e++; - g = h * pow10(d-e); - } - } - - /* - * convert NSIGNIF digits and convert - * back to get accuracy. - */ - for(i=0; i<NSIGNIF; i++) { - d = g; - s1[i] = d + '0'; - g = (g - d) * 10; - } - s1[i] = 0; - - /* - * try decimal rounding to eliminate 9s - */ - c2 = prec + 1; - if(chr == 'f') - c2 += e; - if(c2 >= NSIGNIF-2) { - strcpy(s2, s1); - d = e; - s1[NSIGNIF-2] = '0'; - s1[NSIGNIF-1] = '0'; - sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); - g = strtod(s1, nil); - if(g == f) - goto found; - if(xadd(s1, NSIGNIF-3, 1)) { - e++; - sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); - } - g = strtod(s1, nil); - if(g == f) - goto found; - strcpy(s1, s2); - e = d; - } - - /* - * convert back so s1 gets exact answer - */ - for(;;) { - sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); - g = strtod(s1, nil); - if(f > g) { - if(xadd(s1, NSIGNIF-1, 1)) - e--; - continue; - } - if(f < g) { - if(xsub(s1, NSIGNIF-1, 1)) - e++; - continue; - } - break; - } - -found: - /* - * sign - */ - d = 0; - i = 0; - if(sign) - s2[d++] = '-'; - else if(fmt->flags & FmtSign) - s2[d++] = '+'; - else if(fmt->flags & FmtSpace) - s2[d++] = ' '; - - /* - * copy into final place - * c1 digits of leading '0' - * c2 digits from conversion - * c3 digits of trailing '0' - * c4 digits after '.' - */ - c1 = 0; - c2 = prec + 1; - c3 = 0; - c4 = prec; - switch(chr) { - default: - if(xadd(s1, c2, 5)) - e++; - break; - case 'g': - /* - * decide on 'e' of 'f' style convers - */ - if(xadd(s1, c2, 5)) - e++; - if(e >= -5 && e <= prec) { - c1 = -e - 1; - c4 = prec - e; - chr = 'h'; // flag for 'f' style - } - break; - case 'f': - if(xadd(s1, c2+e, 5)) - e++; - c1 = -e; - if(c1 > prec) - c1 = c2; - c2 += e; - break; - } - - /* - * clean up c1 c2 and c3 - */ - if(c1 < 0) - c1 = 0; - if(c2 < 0) - c2 = 0; - if(c2 > NSIGNIF) { - c3 = c2-NSIGNIF; - c2 = NSIGNIF; - } - - /* - * copy digits - */ - while(c1 > 0) { - if(c1+c2+c3 == c4) - s2[d++] = '.'; - s2[d++] = '0'; - c1--; - } - while(c2 > 0) { - if(c2+c3 == c4) - s2[d++] = '.'; - s2[d++] = s1[i++]; - c2--; - } - while(c3 > 0) { - if(c3 == c4) - s2[d++] = '.'; - s2[d++] = '0'; - c3--; - } - - /* - * strip trailing '0' on g conv - */ - if(fmt->flags & FmtSharp) { - if(0 == c4) - s2[d++] = '.'; - } else - if(chr == 'g' || chr == 'h') { - for(n=d-1; n>=0; n--) - if(s2[n] != '0') - break; - for(i=n; i>=0; i--) - if(s2[i] == '.') { - d = n; - if(i != n) - d++; - break; - } - } - if(chr == 'e' || chr == 'g') { - if(ucase) - s2[d++] = 'E'; - else - s2[d++] = 'e'; - c1 = e; - if(c1 < 0) { - s2[d++] = '-'; - c1 = -c1; - } else - s2[d++] = '+'; - if(c1 >= 100) { - s2[d++] = c1/100 + '0'; - c1 = c1%100; - } - s2[d++] = c1/10 + '0'; - s2[d++] = c1%10 + '0'; - } - s2[d] = 0; -} - -static int -floatfmt(Fmt *fmt, double f) -{ - char s[FDIGIT+10]; - - xdtoa(fmt, s, f); - fmt->flags &= FmtWidth|FmtLeft; - __fmtcpy(fmt, s, strlen(s), strlen(s)); - return 0; -} - -int -__efgfmt(Fmt *f) -{ - double d; - - d = va_arg(f->args, double); - return floatfmt(f, d); -} diff --git a/libfmt/fmt.c b/libfmt/fmt.c @@ -1,218 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -enum -{ - Maxfmt = 64 -}; - -typedef struct Convfmt Convfmt; -struct Convfmt -{ - int c; - volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */ -}; - -struct -{ - /* lock by calling __fmtlock, __fmtunlock */ - int nfmt; - Convfmt fmt[Maxfmt]; -} fmtalloc; - -static Convfmt knownfmt[] = { - ' ', __flagfmt, - '#', __flagfmt, - '%', __percentfmt, - '+', __flagfmt, - ',', __flagfmt, - '-', __flagfmt, - 'C', __runefmt, /* Plan 9 addition */ - 'E', __efgfmt, - 'G', __efgfmt, - 'S', __runesfmt, /* Plan 9 addition */ - 'X', __ifmt, - 'b', __ifmt, /* Plan 9 addition */ - 'c', __charfmt, - 'd', __ifmt, - 'e', __efgfmt, - 'f', __efgfmt, - 'g', __efgfmt, - 'h', __flagfmt, - 'l', __flagfmt, - 'n', __countfmt, - 'o', __ifmt, - 'p', __ifmt, - 'r', __errfmt, - 's', __strfmt, - 'u', __flagfmt, - 'x', __ifmt, - 0, nil, -}; - - -int (*fmtdoquote)(int); - -/* - * __fmtlock() must be set - */ -static int -__fmtinstall(int c, Fmts f) -{ - Convfmt *p, *ep; - - if(c<=0 || c>=65536) - return -1; - if(!f) - f = __badfmt; - - ep = &fmtalloc.fmt[fmtalloc.nfmt]; - for(p=fmtalloc.fmt; p<ep; p++) - if(p->c == c) - break; - - if(p == &fmtalloc.fmt[Maxfmt]) - return -1; - - p->fmt = f; - if(p == ep){ /* installing a new format character */ - fmtalloc.nfmt++; - p->c = c; - } - - return 0; -} - -int -fmtinstall(int c, int (*f)(Fmt*)) -{ - int ret; - - __fmtlock(); - ret = __fmtinstall(c, f); - __fmtunlock(); - return ret; -} - -static Fmts -fmtfmt(int c) -{ - Convfmt *p, *ep; - - ep = &fmtalloc.fmt[fmtalloc.nfmt]; - for(p=fmtalloc.fmt; p<ep; p++) - if(p->c == c){ - while(p->fmt == nil) /* loop until value is updated */ - ; - return p->fmt; - } - - /* is this a predefined format char? */ - __fmtlock(); - for(p=knownfmt; p->c; p++) - if(p->c == c){ - __fmtinstall(p->c, p->fmt); - __fmtunlock(); - return p->fmt; - } - __fmtunlock(); - - return __badfmt; -} - -void* -__fmtdispatch(Fmt *f, const void *fmt, int isrunes) -{ - Rune rune, r; - int i, n; - - f->flags = 0; - f->width = f->prec = 0; - - for(;;){ - if(isrunes){ - r = *(Rune*)fmt; - fmt = (Rune*)fmt + 1; - }else{ - fmt = (char*)fmt + chartorune(&rune, (char*)fmt); - r = rune; - } - f->r = r; - switch(r){ - case '\0': - return nil; - case '.': - f->flags |= FmtWidth|FmtPrec; - continue; - case '0': - if(!(f->flags & FmtWidth)){ - f->flags |= FmtZero; - continue; - } - /* fall through */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - i = 0; - while(r >= '0' && r <= '9'){ - i = i * 10 + r - '0'; - if(isrunes){ - r = *(Rune*)fmt; - fmt = (Rune*)fmt + 1; - }else{ - r = *(char*)fmt; - fmt = (char*)fmt + 1; - } - } - if(isrunes) - fmt = (Rune*)fmt - 1; - else - fmt = (char*)fmt - 1; - numflag: - if(f->flags & FmtWidth){ - f->flags |= FmtPrec; - f->prec = i; - }else{ - f->flags |= FmtWidth; - f->width = i; - } - continue; - case '*': - i = va_arg(f->args, int); - if(i < 0){ - /* - * negative precision => - * ignore the precision. - */ - if(f->flags & FmtPrec){ - f->flags &= ~FmtPrec; - f->prec = 0; - continue; - } - i = -i; - f->flags |= FmtLeft; - } - goto numflag; - } - n = (*fmtfmt(r))(f); - if(n < 0) - return nil; - if(n == 0) - return (void*)fmt; - } -} diff --git a/libfmt/fmtdef.h b/libfmt/fmtdef.h @@ -1,112 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ - -/* - * dofmt -- format to a buffer - * the number of characters formatted is returned, - * or -1 if there was an error. - * if the buffer is ever filled, flush is called. - * it should reset the buffer and return whether formatting should continue. - */ - -typedef int (*Fmts)(Fmt*); - -typedef struct Quoteinfo Quoteinfo; -struct Quoteinfo -{ - int quoted; /* if set, string must be quoted */ - int nrunesin; /* number of input runes that can be accepted */ - int nbytesin; /* number of input bytes that can be accepted */ - int nrunesout; /* number of runes that will be generated */ - int nbytesout; /* number of bytes that will be generated */ -}; - -/* Edit .+1,/^$/ |cfn |grep -v static | grep __ */ -double __Inf(int sign); -double __NaN(void); -int __badfmt(Fmt *f); -int __charfmt(Fmt *f); -int __countfmt(Fmt *f); -int __efgfmt(Fmt *fmt); -int __errfmt(Fmt *f); -int __flagfmt(Fmt *f); -int __fmtFdFlush(Fmt *f); -int __fmtcpy(Fmt *f, const void *vm, int n, int sz); -void* __fmtdispatch(Fmt *f, const void *fmt, int isrunes); -void * __fmtflush(Fmt *f, void *t, int len); -void __fmtlock(void); -int __fmtpad(Fmt *f, int n); -double __fmtpow10(int n); -int __fmtrcpy(Fmt *f, const void *vm, int n); -void __fmtunlock(void); -int __ifmt(Fmt *f); -int __isInf(double d, int sign); -int __isNaN(double d); -int __needsquotes(char *s, int *quotelenp); -int __percentfmt(Fmt *f); -void __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout); -int __quotestrfmt(int runesin, Fmt *f); -int __rfmtpad(Fmt *f, int n); -int __runefmt(Fmt *f); -int __runeneedsquotes(Rune *r, int *quotelenp); -int __runesfmt(Fmt *f); -int __strfmt(Fmt *f); - -#define FMTCHAR(f, t, s, c)\ - do{\ - if(t + 1 > (char*)s){\ - t = __fmtflush(f, t, 1);\ - if(t != nil)\ - s = f->stop;\ - else\ - return -1;\ - }\ - *t++ = c;\ - }while(0) - -#define FMTRCHAR(f, t, s, c)\ - do{\ - if(t + 1 > (Rune*)s){\ - t = __fmtflush(f, t, sizeof(Rune));\ - if(t != nil)\ - s = f->stop;\ - else\ - return -1;\ - }\ - *t++ = c;\ - }while(0) - -#define FMTRUNE(f, t, s, r)\ - do{\ - Rune _rune;\ - int _runelen;\ - if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\ - t = __fmtflush(f, t, _runelen);\ - if(t != nil)\ - s = f->stop;\ - else\ - return -1;\ - }\ - if(r < Runeself)\ - *t++ = r;\ - else{\ - _rune = r;\ - t += runetochar(t, &_rune);\ - }\ - }while(0) - -#ifndef va_copy -# define va_copy(a,b) (a) = (b) -#endif - diff --git a/libfmt/fmtfd.c b/libfmt/fmtfd.c @@ -1,46 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* - * public routine for final flush of a formatting buffer - * to a file descriptor; returns total char count. - */ -int -fmtfdflush(Fmt *f) -{ - if(__fmtFdFlush(f) <= 0) - return -1; - return f->nfmt; -} - -/* - * initialize an output buffer for buffered printing - */ -int -fmtfdinit(Fmt *f, int fd, char *buf, int size) -{ - f->runes = 0; - f->start = buf; - f->to = buf; - f->stop = buf + size; - f->flush = __fmtFdFlush; - f->farg = (void*)(uintptr_t)fd; - f->nfmt = 0; - return 0; -} diff --git a/libfmt/fmtfdflush.c b/libfmt/fmtfdflush.c @@ -1,34 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <unistd.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* - * generic routine for flushing a formatting buffer - * to a file descriptor - */ -int -__fmtFdFlush(Fmt *f) -{ - int n; - - n = (char*)f->to - (char*)f->start; - if(n && write((uintptr_t)f->farg, f->start, n) != n) - return 0; - f->to = f->start; - return 1; -} diff --git a/libfmt/fmtinstall.3 b/libfmt/fmtinstall.3 @@ -1,379 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH FMTINSTALL 3 -.SH NAME -fmtinstall, dofmt, dorfmt, fmtprint, fmtvprint, fmtrune, fmtstrcpy, fmtrunestrcpy, fmtfdinit, fmtfdflush, fmtstrinit, fmtstrflush, runefmtstrinit, runefmtstrflush, errfmt \- support for user-defined print formats and output routines -.SH SYNOPSIS -.B #include <utf.h> -.br -.B #include <fmt.h> -.PP -.ft L -.nf -.ta \w' 'u +\w' 'u +\w' 'u +\w' 'u +\w' 'u -typedef struct Fmt Fmt; -struct Fmt{ - uchar runes; /* output buffer is runes or chars? */ - void *start; /* of buffer */ - void *to; /* current place in the buffer */ - void *stop; /* end of the buffer; overwritten if flush fails */ - int (*flush)(Fmt*); /* called when to == stop */ - void *farg; /* to make flush a closure */ - int nfmt; /* num chars formatted so far */ - va_list args; /* args passed to dofmt */ - int r; /* % format Rune */ - int width; - int prec; - ulong flags; -}; - -enum{ - FmtWidth = 1, - FmtLeft = FmtWidth << 1, - FmtPrec = FmtLeft << 1, - FmtSharp = FmtPrec << 1, - FmtSpace = FmtSharp << 1, - FmtSign = FmtSpace << 1, - FmtZero = FmtSign << 1, - FmtUnsigned = FmtZero << 1, - FmtShort = FmtUnsigned << 1, - FmtLong = FmtShort << 1, - FmtVLong = FmtLong << 1, - FmtComma = FmtVLong << 1, - - FmtFlag = FmtComma << 1 -}; -.fi -.PP -.B -.ta \w'\fLchar* 'u - -.PP -.B -int fmtfdinit(Fmt *f, int fd, char *buf, int nbuf); -.PP -.B -int fmtfdflush(Fmt *f); -.PP -.B -int fmtstrinit(Fmt *f); -.PP -.B -char* fmtstrflush(Fmt *f); -.PP -.B -int runefmtstrinit(Fmt *f); -.PP -.B -Rune* runefmtstrflush(Fmt *f); - -.PP -.B -int fmtinstall(int c, int (*fn)(Fmt*)); -.PP -.B -int dofmt(Fmt *f, char *fmt); -.PP -.B -int dorfmt(Fmt*, Rune *fmt); -.PP -.B -int fmtprint(Fmt *f, char *fmt, ...); -.PP -.B -int fmtvprint(Fmt *f, char *fmt, va_list v); -.PP -.B -int fmtrune(Fmt *f, int r); -.PP -.B -int fmtstrcpy(Fmt *f, char *s); -.PP -.B -int fmtrunestrcpy(Fmt *f, Rune *s); -.PP -.B -int errfmt(Fmt *f); -.SH DESCRIPTION -The interface described here allows the construction of custom -.IR print (3) -verbs and output routines. -In essence, they provide access to the workings of the formatted print code. -.PP -The -.IR print (3) -suite maintains its state with a data structure called -.BR Fmt . -A typical call to -.IR print (3) -or its relatives initializes a -.B Fmt -structure, passes it to subsidiary routines to process the output, -and finishes by emitting any saved state recorded in the -.BR Fmt . -The details of the -.B Fmt -are unimportant to outside users, except insofar as the general -design influences the interface. -The -.B Fmt -records whether the output is in runes or bytes, -the verb being processed, its precision and width, -and buffering parameters. -Most important, it also records a -.I flush -routine that the library will call if a buffer overflows. -When printing to a file descriptor, the flush routine will -emit saved characters and reset the buffer; when printing -to an allocated string, it will resize the string to receive more output. -The flush routine is nil when printing to fixed-size buffers. -User code need never provide a flush routine; this is done internally -by the library. -.SS Custom output routines -To write a custom output routine, such as an error handler that -formats and prints custom error messages, the output sequence can be run -from outside the library using the routines described here. -There are two main cases: output to an open file descriptor -and output to a string. -.PP -To write to a file descriptor, call -.I fmtfdinit -to initialize the local -.B Fmt -structure -.IR f , -giving the file descriptor -.IR fd , -the buffer -.IR buf , -and its size -.IR nbuf . -Then call -.IR fmtprint -or -.IR fmtvprint -to generate the output. -These behave like -.B fprint -(see -.IR print (3)) -or -.B vfprint -except that the characters are buffered until -.I fmtfdflush -is called and the return value is either 0 or \-1. -A typical example of this sequence appears in the Examples section. -.PP -The same basic sequence applies when outputting to an allocated string: -call -.I fmtstrinit -to initialize the -.BR Fmt , -then call -.I fmtprint -and -.I fmtvprint -to generate the output. -Finally, -.I fmtstrflush -will return the allocated string, which should be freed after use. -To output to a rune string, use -.I runefmtstrinit -and -.IR runefmtstrflush . -Regardless of the output style or type, -.I fmtprint -or -.I fmtvprint -generates the characters. -.SS Custom format verbs -.I Fmtinstall -is used to install custom verbs and flags labeled by character -.IR c , -which may be any non-zero Unicode character. -.I Fn -should be declared as -.IP -.EX -int fn(Fmt*) -.EE -.PP -.IB Fp ->r -is the flag or verb character to cause -.I fn -to be called. -In -.IR fn , -.IB fp ->width , -.IB fp ->prec -are the width and precision, and -.IB fp ->flags -the decoded flags for the verb (see -.IR print (3) -for a description of these items). -The standard flag values are: -.B FmtSign -.RB ( + ), -.B FmtLeft -.RB ( - ), -.B FmtSpace -.RB ( '\ ' ), -.B FmtSharp -.RB ( # ), -.B FmtComma -.RB ( , ), -.B FmtLong -.RB ( l ), -.B FmtShort -.RB ( h ), -.B FmtUnsigned -.RB ( u ), -and -.B FmtVLong -.RB ( ll ). -The flag bits -.B FmtWidth -and -.B FmtPrec -identify whether a width and precision were specified. -.PP -.I Fn -is passed a pointer to the -.B Fmt -structure recording the state of the output. -If -.IB fp ->r -is a verb (rather than a flag), -.I fn -should use -.B Fmt->args -to fetch its argument from the list, -then format it, and return zero. -If -.IB fp ->r -is a flag, -.I fn -should return one. -All interpretation of -.IB fp ->width\f1, -.IB fp ->prec\f1, -and -.IB fp-> flags -is left up to the conversion routine. -.I Fmtinstall -returns 0 if the installation succeeds, \-1 if it fails. -.PP -.IR Fmtprint -and -.IR fmtvprint -may be called to -help prepare output in custom conversion routines. -However, these functions clear the width, precision, and flags. -Both functions return 0 for success and \-1 for failure. -.PP -The functions -.I dofmt -and -.I dorfmt -are the underlying formatters; they -use the existing contents of -.B Fmt -and should be called only by sophisticated conversion routines. -These routines return the number of characters (bytes of UTF or runes) -produced. -.PP -Some internal functions may be useful to format primitive types. -They honor the width, precision and flags as described in -.IR print (3). -.I Fmtrune -formats a single character -.BR r . -.I Fmtstrcpy -formats a string -.BR s ; -.I fmtrunestrcpy -formats a rune string -.BR s . -.I Errfmt -formats the system error string. -All these routines return zero for successful execution. -Conversion routines that call these functions will work properly -regardless of whether the output is bytes or runes. -.\" .PP -.\" .IR 2c (1) -.\" describes the C directive -.\" .B #pragma -.\" .B varargck -.\" that can be used to provide type-checking for custom print verbs and output routines. -.SH EXAMPLES -This function prints an error message with a variable -number of arguments and then quits. -Compared to the corresponding example in -.IR print (3), -this version uses a smaller buffer, will never truncate -the output message, but might generate multiple -.B write -system calls to produce its output. -.IP -.EX -.ta 6n +6n +6n +6n +6n +6n +6n +6n +6n -#pragma varargck argpos error 1 - -void fatal(char *fmt, ...) -{ - Fmt f; - char buf[64]; - va_list arg; - - fmtfdinit(&f, 1, buf, sizeof buf); - fmtprint(&f, "fatal: "); - va_start(arg, fmt); - fmtvprint(&f, fmt, arg); - va_end(arg); - fmtprint(&f, "\en"); - fmtfdflush(&f); - exits("fatal error"); -} -.EE -.PP -This example adds a verb to print complex numbers. -.IP -.EX -typedef -struct { - double r, i; -} Complex; - -#pragma varargck type "X" Complex - -int -Xfmt(Fmt *f) -{ - Complex c; - - c = va_arg(f->args, Complex); - return fmtprint(f, "(%g,%g)", c.r, c.i); -} - -main(...) -{ - Complex x = (Complex){ 1.5, -2.3 }; - - fmtinstall('X', Xfmt); - print("x = %X\en", x); -} -.EE -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH SEE ALSO -.IR print (3), -.IR utf (7) -.SH DIAGNOSTICS -These routines return negative numbers or nil for errors and set -.IR errstr . diff --git a/libfmt/fmtlock.c b/libfmt/fmtlock.c @@ -1,27 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -void -__fmtlock(void) -{ -} - -void -__fmtunlock(void) -{ -} diff --git a/libfmt/fmtprint.c b/libfmt/fmtprint.c @@ -1,48 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* - * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags - */ -int -fmtprint(Fmt *f, const char *fmt, ...) -{ - va_list va; - int n; - - f->flags = 0; - f->width = 0; - f->prec = 0; - va_copy(va, f->args); - va_end(f->args); - va_start(f->args, fmt); - n = dofmt(f, fmt); - va_end(f->args); - f->flags = 0; - f->width = 0; - f->prec = 0; - va_copy(f->args,va); - va_end(va); - if(n >= 0) - return 0; - return n; -} - diff --git a/libfmt/fmtquote.c b/libfmt/fmtquote.c @@ -1,264 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* - * How many bytes of output UTF will be produced by quoting (if necessary) this string? - * How many runes? How much of the input will be consumed? - * The parameter q is filled in by __quotesetup. - * The string may be UTF or Runes (s or r). - * Return count does not include NUL. - * Terminate the scan at the first of: - * NUL in input - * count exceeded in input - * count exceeded on output - * *ninp is set to number of input bytes accepted. - * nin may be <0 initially, to avoid checking input by count. - */ -void -__quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout) -{ - int w; - Rune c; - - q->quoted = 0; - q->nbytesout = 0; - q->nrunesout = 0; - q->nbytesin = 0; - q->nrunesin = 0; - if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){ - if(nout < 2) - return; - q->quoted = 1; - q->nbytesout = 2; - q->nrunesout = 2; - } - for(; nin!=0; nin--){ - if(s) - w = chartorune(&c, s); - else{ - c = *r; - w = runelen(c); - } - - if(c == '\0') - break; - if(runesout){ - if(q->nrunesout+1 > nout) - break; - }else{ - if(q->nbytesout+w > nout) - break; - } - - if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){ - if(!q->quoted){ - if(runesout){ - if(1+q->nrunesout+1+1 > nout) /* no room for quotes */ - break; - }else{ - if(1+q->nbytesout+w+1 > nout) /* no room for quotes */ - break; - } - q->nrunesout += 2; /* include quotes */ - q->nbytesout += 2; /* include quotes */ - q->quoted = 1; - } - if(c == '\'') { - if(runesout){ - if(1+q->nrunesout+1 > nout) /* no room for quotes */ - break; - }else{ - if(1+q->nbytesout+w > nout) /* no room for quotes */ - break; - } - q->nbytesout++; - q->nrunesout++; /* quotes reproduce as two characters */ - } - } - - /* advance input */ - if(s) - s += w; - else - r++; - q->nbytesin += w; - q->nrunesin++; - - /* advance output */ - q->nbytesout += w; - q->nrunesout++; - } -} - -static int -qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f) -{ - Rune r, *rm, *rme; - char *t, *s, *m, *me; - Rune *rt, *rs; - ulong fl; - int nc, w; - - m = sin; - me = m + q->nbytesin; - rm = rin; - rme = rm + q->nrunesin; - - w = f->width; - fl = f->flags; - if(f->runes){ - if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0) - return -1; - }else{ - if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) - return -1; - } - t = (char*)f->to; - s = (char*)f->stop; - rt = (Rune*)f->to; - rs = (Rune*)f->stop; - if(f->runes) - FMTRCHAR(f, rt, rs, '\''); - else - FMTRUNE(f, t, s, '\''); - for(nc = q->nrunesin; nc > 0; nc--){ - if(sin){ - r = *(uchar*)m; - if(r < Runeself) - m++; - else if((me - m) >= UTFmax || fullrune(m, me-m)) - m += chartorune(&r, m); - else - break; - }else{ - if(rm >= rme) - break; - r = *(uchar*)rm++; - } - if(f->runes){ - FMTRCHAR(f, rt, rs, r); - if(r == '\'') - FMTRCHAR(f, rt, rs, r); - }else{ - FMTRUNE(f, t, s, r); - if(r == '\'') - FMTRUNE(f, t, s, r); - } - } - - if(f->runes){ - FMTRCHAR(f, rt, rs, '\''); - USED(rs); - f->nfmt += rt - (Rune *)f->to; - f->to = rt; - if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0) - return -1; - }else{ - FMTRUNE(f, t, s, '\''); - USED(s); - f->nfmt += t - (char *)f->to; - f->to = t; - if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0) - return -1; - } - return 0; -} - -int -__quotestrfmt(int runesin, Fmt *f) -{ - int nin, outlen; - Rune *r; - char *s; - Quoteinfo q; - - nin = -1; - if(f->flags&FmtPrec) - nin = f->prec; - if(runesin){ - r = va_arg(f->args, Rune *); - s = nil; - }else{ - s = va_arg(f->args, char *); - r = nil; - } - if(!s && !r) - return __fmtcpy(f, (void*)"<nil>", 5, 5); - - if(f->flush) - outlen = 0x7FFFFFFF; /* if we can flush, no output limit */ - else if(f->runes) - outlen = (Rune*)f->stop - (Rune*)f->to; - else - outlen = (char*)f->stop - (char*)f->to; - - __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes); -//print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); - - if(runesin){ - if(!q.quoted) - return __fmtrcpy(f, r, q.nrunesin); - return qstrfmt(nil, r, &q, f); - } - - if(!q.quoted) - return __fmtcpy(f, s, q.nrunesin, q.nbytesin); - return qstrfmt(s, nil, &q, f); -} - -int -quotestrfmt(Fmt *f) -{ - return __quotestrfmt(0, f); -} - -int -quoterunestrfmt(Fmt *f) -{ - return __quotestrfmt(1, f); -} - -void -quotefmtinstall(void) -{ - fmtinstall('q', quotestrfmt); - fmtinstall('Q', quoterunestrfmt); -} - -int -__needsquotes(char *s, int *quotelenp) -{ - Quoteinfo q; - - __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0); - *quotelenp = q.nbytesout; - - return q.quoted; -} - -int -__runeneedsquotes(Rune *r, int *quotelenp) -{ - Quoteinfo q; - - __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0); - *quotelenp = q.nrunesout; - - return q.quoted; -} diff --git a/libfmt/fmtrune.c b/libfmt/fmtrune.c @@ -1,40 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -fmtrune(Fmt *f, int r) -{ - Rune *rt; - char *t; - int n; - - if(f->runes){ - rt = (Rune*)f->to; - FMTRCHAR(f, rt, f->stop, r); - f->to = rt; - n = 1; - }else{ - t = (char*)f->to; - FMTRUNE(f, t, f->stop, r); - n = t - (char*)f->to; - f->to = t; - } - f->nfmt += n; - return 0; -} diff --git a/libfmt/fmtstr.c b/libfmt/fmtstr.c @@ -1,27 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdlib.h> -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -char* -fmtstrflush(Fmt *f) -{ - if(f->start == nil) - return nil; - *(char*)f->to = '\0'; - return (char*)f->start; -} diff --git a/libfmt/fmtvprint.c b/libfmt/fmtvprint.c @@ -1,49 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - - -/* - * format a string into the output buffer - * designed for formats which themselves call fmt, - * but ignore any width flags - */ -int -fmtvprint(Fmt *f, const char *fmt, va_list args) -{ - va_list va; - int n; - - f->flags = 0; - f->width = 0; - f->prec = 0; - va_copy(va,f->args); - va_end(f->args); - va_copy(f->args,args); - n = dofmt(f, fmt); - f->flags = 0; - f->width = 0; - f->prec = 0; - va_end(f->args); - va_copy(f->args,va); - va_end(va); - if(n >= 0) - return 0; - return n; -} - diff --git a/libfmt/fprint.c b/libfmt/fprint.c @@ -1,29 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -fprint(int fd, const char *fmt, ...) -{ - int n; - va_list args; - - va_start(args, fmt); - n = vfprint(fd, fmt, args); - va_end(args); - return n; -} diff --git a/libfmt/libfmt.a b/libfmt/libfmt.a Binary files differ. diff --git a/libfmt/nan64.c b/libfmt/nan64.c @@ -1,67 +0,0 @@ -/* - * 64-bit IEEE not-a-number routines. - * This is big/little-endian portable assuming that - * the 64-bit doubles and 64-bit integers have the - * same byte ordering. - */ - -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -#if defined (__APPLE__) || (__powerpc__) -#define _NEEDLL -#endif - -static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001; -static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000; -static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000; - -double -__NaN(void) -{ - uvlong *p; - - /* gcc complains about "return *(double*)&uvnan;" */ - p = &uvnan; - return *(double*)p; -} - -int -__isNaN(double d) -{ - uvlong x; - double *p; - - p = &d; - x = *(uvlong*)p; - return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0); -} - -double -__Inf(int sign) -{ - uvlong *p; - - if(sign < 0) - p = &uvinf; - else - p = &uvneginf; - return *(double*)p; -} - -int -__isInf(double d, int sign) -{ - uvlong x; - double *p; - - p = &d; - x = *(uvlong*)p; - if(sign == 0) - return x==uvinf || x==uvneginf; - else if(sign > 0) - return x==uvinf; - else - return x==uvneginf; -} diff --git a/libfmt/pow10.c b/libfmt/pow10.c @@ -1,57 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -/* - * this table might overflow 127-bit exponent representations. - * in that case, truncate it after 1.0e38. - * it is important to get all one can from this - * routine since it is used in atof to scale numbers. - * the presumption is that C converts fp numbers better - * than multipication of lower powers of 10. - */ - -static -double tab[] = -{ - 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, - 1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19, - 1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29, - 1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39, - 1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49, - 1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59, - 1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69, -}; - -double -__fmtpow10(int n) -{ - int m; - - if(n < 0) { - n = -n; - if(n < (int)(sizeof(tab)/sizeof(tab[0]))) - return 1/tab[n]; - m = n/2; - return __fmtpow10(-m) * __fmtpow10(m-n); - } - if(n < (int)(sizeof(tab)/sizeof(tab[0]))) - return tab[n]; - m = n/2; - return __fmtpow10(m) * __fmtpow10(n-m); -} diff --git a/libfmt/print.3 b/libfmt/print.3 @@ -1,482 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.\" diffs from /usr/local/plan9/man/man3/print.3: -.\" -.\" - include different headers -.\" - drop reference to bio(3) -.\" - change exits to exit -.\" - text about unsigned verbs -.\" - source pointer -.\" -.TH PRINT 3 -.SH NAME -print, fprint, sprint, snprint, seprint, smprint, runesprint, runesnprint, runeseprint, runesmprint, vfprint, vsnprint, vseprint, vsmprint, runevsnprint, runevseprint, runevsmprint \- print formatted output -.SH SYNOPSIS -.B #include <utf.h> -.PP -.B #include <fmt.h> -.PP -.ta \w'\fLchar* 'u -.B -int print(char *format, ...) -.PP -.B -int fprint(int fd, char *format, ...) -.PP -.B -int sprint(char *s, char *format, ...) -.PP -.B -int snprint(char *s, int len, char *format, ...) -.PP -.B -char* seprint(char *s, char *e, char *format, ...) -.PP -.B -char* smprint(char *format, ...) -.PP -.B -int runesprint(Rune *s, char *format, ...) -.PP -.B -int runesnprint(Rune *s, int len, char *format, ...) -.PP -.B -Rune* runeseprint(Rune *s, Rune *e, char *format, ...) -.PP -.B -Rune* runesmprint(char *format, ...) -.PP -.B -int vfprint(int fd, char *format, va_list v) -.PP -.B -int vsnprint(char *s, int len, char *format, va_list v) -.PP -.B -char* vseprint(char *s, char *e, char *format, va_list v) -.PP -.B -char* vsmprint(char *format, va_list v) -.PP -.B -int runevsnprint(Rune *s, int len, char *format, va_list v) -.PP -.B -Rune* runevseprint(Rune *s, Rune *e, char *format, va_list v) -.PP -.B -Rune* runevsmprint(Rune *format, va_list v) -.PP -.B -.SH DESCRIPTION -.I Print -writes text to the standard output. -.I Fprint -writes to the named output -file descriptor: -a buffered form -is described in -.IR bio (3). -.I Sprint -places text -followed by the NUL character -.RB ( \e0 ) -in consecutive bytes starting at -.IR s ; -it is the user's responsibility to ensure that -enough storage is available. -Each function returns the number of bytes -transmitted (not including the NUL -in the case of -.IR sprint ), -or -a negative value if an output error was encountered. -.PP -.I Snprint -is like -.IR sprint , -but will not place more than -.I len -bytes in -.IR s . -Its result is always NUL-terminated and holds the maximal -number of complete UTF-8 characters that can fit. -.I Seprint -is like -.IR snprint , -except that the end is indicated by a pointer -.I e -rather than a count and the return value points to the terminating NUL of the -resulting string. -.I Smprint -is like -.IR sprint , -except that it prints into and returns a string of the required length, which is -allocated by -.IR malloc (3). -.PP -The routines -.IR runesprint , -.IR runesnprint , -.IR runeseprint , -and -.I runesmprint -are the same as -.IR sprint , -.IR snprint , -.IR seprint -and -.I smprint -except that their output is rune strings instead of byte strings. -.PP -Finally, the routines -.IR vfprint , -.IR vsnprint , -.IR vseprint , -.IR vsmprint , -.IR runevsnprint , -.IR runevseprint , -and -.I runevsmprint -are like their -.BR v-less -relatives except they take as arguments a -.B va_list -parameter, so they can be called within a variadic function. -The Example section shows a representative usage. -.PP -Each of these functions -converts, formats, and prints its -trailing arguments -under control of a -.IR format -string. -The -format -contains two types of objects: -plain characters, which are simply copied to the -output stream, -and conversion specifications, -each of which results in fetching of -zero or more -arguments. -The results are undefined if there are arguments of the -wrong type or too few -arguments for the format. -If the format is exhausted while -arguments remain, the excess -is ignored. -.PP -Each conversion specification has the following format: -.IP -.B "% [flags] verb -.PP -The verb is a single character and each flag is a single character or a -(decimal) numeric string. -Up to two numeric strings may be used; -the first is called -.IR width , -the second -.IR precision . -A period can be used to separate them, and if the period is -present then -.I width -and -.I precision -are taken to be zero if missing, otherwise they are `omitted'. -Either or both of the numbers may be replaced with the character -.BR * , -meaning that the actual number will be obtained from the argument list -as an integer. -The flags and numbers are arguments to -the -.I verb -described below. -.PP -The numeric verbs -.BR d , -.BR i , -.BR u , -.BR o , -.BR b , -.BR x , -and -.B X -format their arguments in decimal, decimal, -unsigned decimal, octal, binary, hexadecimal, and upper case hexadecimal. -Each interprets the flags -.BR 0 , -.BR h , -.BR hh , -.BR l , -.BR + , -.BR - , -.BR , , -and -.B # -to mean pad with zeros, -short, byte, long, always print a sign, left justified, commas every three digits, -and alternate format. -Also, a space character in the flag -position is like -.BR + , -but prints a space instead of a plus sign for non-negative values. -If neither -short nor long is specified, -then the argument is an -.BR int . -If an unsigned verb is specified, -then the argument is interpreted as a -positive number and no sign is output; -space and -.B + -flags are ignored for unsigned verbs. -If two -.B l -flags are given, -then the argument is interpreted as a -.B vlong -(usually an 8-byte, sometimes a 4-byte integer). -If -.I precision -is not omitted, the number is padded on the left with zeros -until at least -.I precision -digits appear. -If -.I precision -is explicitly 0, and the number is 0, -no digits are generated, and alternate formatting -does not apply. -Then, if alternate format is specified, -for -.B o -conversion, the number is preceded by a -.B 0 -if it doesn't already begin with one. -For non-zero numbers and -.B x -conversion, the number is preceded by -.BR 0x ; -for -.B X -conversion, the number is preceded by -.BR 0X . -Finally, if -.I width -is not omitted, the number is padded on the left (or right, if -left justification is specified) with enough blanks to -make the field at least -.I width -characters long. -.PP -The floating point verbs -.BR f , -.BR e , -.BR E , -.BR g , -and -.B G -take a -.B double -argument. -Each interprets the flags -.BR 0 , -.BR L -.BR + , -.BR - , -and -.B # -to mean pad with zeros, -long double argument, -always print a sign, -left justified, -and -alternate format. -.I Width -is the minimum field width and, -if the converted value takes up less than -.I width -characters, it is padded on the left (or right, if `left justified') -with spaces. -.I Precision -is the number of digits that are converted after the decimal place for -.BR e , -.BR E , -and -.B f -conversions, -and -.I precision -is the maximum number of significant digits for -.B g -and -.B G -conversions. -The -.B f -verb produces output of the form -.RB [ - ] digits [ .digits\fR]. -.B E -conversion appends an exponent -.BR E [ - ] digits , -and -.B e -conversion appends an exponent -.BR e [ - ] digits . -The -.B g -verb will output the argument in either -.B e -or -.B f -with the goal of producing the smallest output. -Also, trailing zeros are omitted from the fraction part of -the output, and a trailing decimal point appears only if it is followed -by a digit. -The -.B G -verb is similar, but uses -.B E -format instead of -.BR e . -When alternate format is specified, the result will always contain a decimal point, -and for -.B g -and -.B G -conversions, trailing zeros are not removed. -.PP -The -.B s -verb copies a string -(pointer to -.BR char ) -to the output. -The number of characters copied -.RI ( n ) -is the minimum -of the size of the string and -.IR precision . -These -.I n -characters are justified within a field of -.I width -characters as described above. -If a -.I precision -is given, it is safe for the string not to be nul-terminated -as long as it is at least -.I precision -characters (not bytes!) long. -The -.B S -verb is similar, but it interprets its pointer as an array -of runes (see -.IR utf (7)); -the runes are converted to -.SM UTF -before output. -.PP -The -.B c -verb copies a single -.B char -(promoted to -.BR int ) -justified within a field of -.I width -characters as described above. -The -.B C -verb is similar, but works on runes. -.PP -The -.B p -verb formats a pointer value. -At the moment, it is a synonym for -.BR x , -but that will change if pointers and integers are different sizes. -.PP -The -.B r -verb takes no arguments; it copies the error string returned by a call to -.IR strerror (3) -with an argument of -.IR errno. -.PP -Custom verbs may be installed using -.IR fmtinstall (3). -.SH EXAMPLE -This function prints an error message with a variable -number of arguments and then quits. -.IP -.EX -.ta 6n +6n +6n -void fatal(char *msg, ...) -{ - char buf[1024], *out; - va_list arg; - - out = seprint(buf, buf+sizeof buf, "Fatal error: "); - va_start(arg, msg); - out = vseprint(out, buf+sizeof buf, msg, arg); - va_end(arg); - write(2, buf, out-buf); - exit(1); -} -.EE -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH SEE ALSO -.IR fmtinstall (3), -.IR fprintf (3), -.IR utf (7) -.SH DIAGNOSTICS -Routines that write to a file descriptor or call -.IR malloc -set -.IR errstr . -.SH BUGS -The formatting is close to that specified for ANSI -.IR fprintf (3); -the main difference is that -.B b -and -.B r -are not in ANSI and some -.B C9X -verbs and syntax are missing. -Also, and distinctly not a bug, -.I print -and friends generate -.SM UTF -rather than -.SM ASCII. -.PP -There is no -.IR runeprint , -.IR runefprint , -etc. because runes are byte-order dependent and should not be written directly to a file; use the -UTF output of -.I print -or -.I fprint -instead. -Also, -.I sprint -is deprecated for safety reasons; use -.IR snprint , -.IR seprint , -or -.I smprint -instead. -Safety also precludes the existence of -.IR runesprint . diff --git a/libfmt/print.c b/libfmt/print.c @@ -1,29 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -print(const char *fmt, ...) -{ - int n; - va_list args; - - va_start(args, fmt); - n = vfprint(1, fmt, args); - va_end(args); - return n; -} diff --git a/libfmt/runefmtstr.c b/libfmt/runefmtstr.c @@ -1,27 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <stdlib.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -Rune* -runefmtstrflush(Fmt *f) -{ - if(f->start == nil) - return nil; - *(Rune*)f->to = '\0'; - return f->start; -} diff --git a/libfmt/runeseprint.c b/libfmt/runeseprint.c @@ -1,30 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -Rune* -runeseprint(Rune *buf, Rune *e, const char *fmt, ...) -{ - Rune *p; - va_list args; - - va_start(args, fmt); - p = runevseprint(buf, e, fmt, args); - va_end(args); - return p; -} diff --git a/libfmt/runesmprint.c b/libfmt/runesmprint.c @@ -1,30 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -Rune* -runesmprint(const char *fmt, ...) -{ - va_list args; - Rune *p; - - va_start(args, fmt); - p = runevsmprint(fmt, args); - va_end(args); - return p; -} diff --git a/libfmt/runesnprint.c b/libfmt/runesnprint.c @@ -1,31 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -runesnprint(Rune *buf, int len, const char *fmt, ...) -{ - int n; - va_list args; - - va_start(args, fmt); - n = runevsnprint(buf, len, fmt, args); - va_end(args); - return n; -} - diff --git a/libfmt/runesprint.c b/libfmt/runesprint.c @@ -1,30 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -runesprint(Rune *buf, const char *fmt, ...) -{ - int n; - va_list args; - - va_start(args, fmt); - n = runevsnprint(buf, 256, fmt, args); - va_end(args); - return n; -} diff --git a/libfmt/runevseprint.c b/libfmt/runevseprint.c @@ -1,40 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -Rune* -runevseprint(Rune *buf, Rune *e, const char *fmt, va_list args) -{ - Fmt f; - - if(e <= buf) - return nil; - f.runes = 1; - f.start = buf; - f.to = buf; - f.stop = e - 1; - f.flush = nil; - f.farg = nil; - f.nfmt = 0; - va_copy(f.args,args); - dofmt(&f, fmt); - va_end(f.args); - *(Rune*)f.to = '\0'; - return (Rune*)f.to; -} - diff --git a/libfmt/runevsmprint.c b/libfmt/runevsmprint.c @@ -1,91 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -/* - * Plan 9 port version must include libc.h in order to - * get Plan 9 debugging malloc, which sometimes returns - * different pointers than the standard malloc. - */ -#include <stdlib.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -static int -runeFmtStrFlush(Fmt *f) -{ - Rune *s; - int n; - - if(f->start == nil) - return 0; - n = (uintptr_t)f->farg; - n *= 2; - s = (Rune*)f->start; - f->start = realloc(s, sizeof(Rune)*n); - if(f->start == nil){ - f->farg = nil; - f->to = nil; - f->stop = nil; - free(s); - return 0; - } - f->farg = (void*)(uintptr_t)n; - f->to = (Rune*)f->start + ((Rune*)f->to - s); - f->stop = (Rune*)f->start + n - 1; - return 1; -} - -int -runefmtstrinit(Fmt *f) -{ - int n; - - memset(f, 0, sizeof *f); - f->runes = 1; - n = 32; - f->start = malloc(sizeof(Rune)*n); - if(f->start == nil) - return -1; - f->to = f->start; - f->stop = (Rune*)f->start + n - 1; - f->flush = runeFmtStrFlush; - f->farg = (void*)(uintptr_t)n; - f->nfmt = 0; - return 0; -} - -/* - * print into an allocated string buffer - */ -Rune* -runevsmprint(const char *fmt, va_list args) -{ - Fmt f; - int n; - - if(runefmtstrinit(&f) < 0) - return nil; - va_copy(f.args,args); - n = dofmt(&f, fmt); - va_end(f.args); - if(f.start == nil) - return nil; - if(n < 0){ - free(f.start); - return nil; - } - *(Rune*)f.to = '\0'; - return (Rune*)f.start; -} diff --git a/libfmt/runevsnprint.c b/libfmt/runevsnprint.c @@ -1,39 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -runevsnprint(Rune *buf, int len, const char *fmt, va_list args) -{ - Fmt f; - - if(len <= 0) - return -1; - f.runes = 1; - f.start = buf; - f.to = buf; - f.stop = buf + len - 1; - f.flush = nil; - f.farg = nil; - f.nfmt = 0; - va_copy(f.args,args); - dofmt(&f, fmt); - va_end(f.args); - *(Rune*)f.to = '\0'; - return (Rune*)f.to - buf; -} diff --git a/libfmt/seprint.c b/libfmt/seprint.c @@ -1,29 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -char* -seprint(char *buf, char *e, const char *fmt, ...) -{ - char *p; - va_list args; - - va_start(args, fmt); - p = vseprint(buf, e, fmt, args); - va_end(args); - return p; -} diff --git a/libfmt/smprint.c b/libfmt/smprint.c @@ -1,29 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -char* -smprint(const char *fmt, ...) -{ - va_list args; - char *p; - - va_start(args, fmt); - p = vsmprint(fmt, args); - va_end(args); - return p; -} diff --git a/libfmt/snprint.c b/libfmt/snprint.c @@ -1,30 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -snprint(char *buf, int len, const char *fmt, ...) -{ - int n; - va_list args; - - va_start(args, fmt); - n = vsnprint(buf, len, fmt, args); - va_end(args); - return n; -} - diff --git a/libfmt/sprint.c b/libfmt/sprint.c @@ -1,37 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmtdef.h" - -int -sprint(char *buf, const char *fmt, ...) -{ - int n; - uint len; - va_list args; - - len = 1<<30; /* big number, but sprint is deprecated anyway */ - /* - * on PowerPC, the stack is near the top of memory, so - * we must be sure not to overflow a 32-bit pointer. - */ - if(buf+len < buf) - len = -(uintptr_t)buf-1; - - va_start(args, fmt); - n = vsnprint(buf, len, fmt, args); - va_end(args); - return n; -} diff --git a/libfmt/strtod.c b/libfmt/strtod.c @@ -1,532 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdlib.h> -#include <math.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -static ulong -umuldiv(ulong a, ulong b, ulong c) -{ - double d; - - d = ((double)a * (double)b) / (double)c; - if(d >= 4294967295.) - d = 4294967295.; - return (ulong)d; -} - -/* - * This routine will convert to arbitrary precision - * floating point entirely in multi-precision fixed. - * The answer is the closest floating point number to - * the given decimal number. Exactly half way are - * rounded ala ieee rules. - * Method is to scale input decimal between .500 and .999... - * with external power of 2, then binary search for the - * closest mantissa to this decimal number. - * Nmant is is the required precision. (53 for ieee dp) - * Nbits is the max number of bits/word. (must be <= 28) - * Prec is calculated - the number of words of fixed mantissa. - */ -enum -{ - Nbits = 28, /* bits safely represented in a ulong */ - Nmant = 53, /* bits of precision required */ - Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */ - Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */ - Ndig = 1500, - One = (ulong)(1<<Nbits), - Half = (ulong)(One>>1), - Maxe = 310, - - Fsign = 1<<0, /* found - */ - Fesign = 1<<1, /* found e- */ - Fdpoint = 1<<2, /* found . */ - - S0 = 0, /* _ _S0 +S1 #S2 .S3 */ - S1, /* _+ #S2 .S3 */ - S2, /* _+# #S2 .S4 eS5 */ - S3, /* _+. #S4 */ - S4, /* _+#.# #S4 eS5 */ - S5, /* _+#.#e +S6 #S7 */ - S6, /* _+#.#e+ #S7 */ - S7, /* _+#.#e+# #S7 */ -}; - -static int xcmp(char*, char*); -static int fpcmp(char*, ulong*); -static void frnorm(ulong*); -static void divascii(char*, int*, int*, int*); -static void mulascii(char*, int*, int*, int*); - -typedef struct Tab Tab; -struct Tab -{ - int bp; - int siz; - char* cmp; -}; - -double -fmtstrtod(const char *as, char **aas) -{ - int na, ex, dp, bp, c, i, flag, state; - ulong low[Prec], hig[Prec], mid[Prec]; - double d; - char *s, a[Ndig]; - - flag = 0; /* Fsign, Fesign, Fdpoint */ - na = 0; /* number of digits of a[] */ - dp = 0; /* na of decimal point */ - ex = 0; /* exonent */ - - state = S0; - for(s=(char*)as;; s++) { - c = *s; - if(c >= '0' && c <= '9') { - switch(state) { - case S0: - case S1: - case S2: - state = S2; - break; - case S3: - case S4: - state = S4; - break; - - case S5: - case S6: - case S7: - state = S7; - ex = ex*10 + (c-'0'); - continue; - } - if(na == 0 && c == '0') { - dp--; - continue; - } - if(na < Ndig-50) - a[na++] = c; - continue; - } - switch(c) { - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - if(state == S0) - continue; - break; - case '-': - if(state == S0) - flag |= Fsign; - else - flag |= Fesign; - case '+': - if(state == S0) - state = S1; - else - if(state == S5) - state = S6; - else - break; /* syntax */ - continue; - case '.': - flag |= Fdpoint; - dp = na; - if(state == S0 || state == S1) { - state = S3; - continue; - } - if(state == S2) { - state = S4; - continue; - } - break; - case 'e': - case 'E': - if(state == S2 || state == S4) { - state = S5; - continue; - } - break; - } - break; - } - - /* - * clean up return char-pointer - */ - switch(state) { - case S0: - if(xcmp(s, "nan") == 0) { - if(aas != nil) - *aas = s+3; - goto retnan; - } - case S1: - if(xcmp(s, "infinity") == 0) { - if(aas != nil) - *aas = s+8; - goto retinf; - } - if(xcmp(s, "inf") == 0) { - if(aas != nil) - *aas = s+3; - goto retinf; - } - case S3: - if(aas != nil) - *aas = (char*)as; - goto ret0; /* no digits found */ - case S6: - s--; /* back over +- */ - case S5: - s--; /* back over e */ - break; - } - if(aas != nil) - *aas = s; - - if(flag & Fdpoint) - while(na > 0 && a[na-1] == '0') - na--; - if(na == 0) - goto ret0; /* zero */ - a[na] = 0; - if(!(flag & Fdpoint)) - dp = na; - if(flag & Fesign) - ex = -ex; - dp += ex; - if(dp < -Maxe){ - errno = ERANGE; - goto ret0; /* underflow by exp */ - } else - if(dp > +Maxe) - goto retinf; /* overflow by exp */ - - /* - * normalize the decimal ascii number - * to range .[5-9][0-9]* e0 - */ - bp = 0; /* binary exponent */ - while(dp > 0) - divascii(a, &na, &dp, &bp); - while(dp < 0 || a[0] < '5') - mulascii(a, &na, &dp, &bp); - - /* close approx by naive conversion */ - mid[0] = 0; - mid[1] = 1; - for(i=0; c=a[i]; i++) { - mid[0] = mid[0]*10 + (c-'0'); - mid[1] = mid[1]*10; - if(i >= 8) - break; - } - low[0] = umuldiv(mid[0], One, mid[1]); - hig[0] = umuldiv(mid[0]+1, One, mid[1]); - for(i=1; i<Prec; i++) { - low[i] = 0; - hig[i] = One-1; - } - - /* binary search for closest mantissa */ - for(;;) { - /* mid = (hig + low) / 2 */ - c = 0; - for(i=0; i<Prec; i++) { - mid[i] = hig[i] + low[i]; - if(c) - mid[i] += One; - c = mid[i] & 1; - mid[i] >>= 1; - } - frnorm(mid); - - /* compare */ - c = fpcmp(a, mid); - if(c > 0) { - c = 1; - for(i=0; i<Prec; i++) - if(low[i] != mid[i]) { - c = 0; - low[i] = mid[i]; - } - if(c) - break; /* between mid and hig */ - continue; - } - if(c < 0) { - for(i=0; i<Prec; i++) - hig[i] = mid[i]; - continue; - } - - /* only hard part is if even/odd roundings wants to go up */ - c = mid[Prec-1] & (Sigbit-1); - if(c == Sigbit/2 && (mid[Prec-1]&Sigbit) == 0) - mid[Prec-1] -= c; - break; /* exactly mid */ - } - - /* normal rounding applies */ - c = mid[Prec-1] & (Sigbit-1); - mid[Prec-1] -= c; - if(c >= Sigbit/2) { - mid[Prec-1] += Sigbit; - frnorm(mid); - } - goto out; - -ret0: - return 0; - -retnan: - return __NaN(); - -retinf: - /* - * Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */ - errno = ERANGE; - if(flag & Fsign) - return -HUGE_VAL; - return HUGE_VAL; - -out: - d = 0; - for(i=0; i<Prec; i++) - d = d*One + mid[i]; - if(flag & Fsign) - d = -d; - d = ldexp(d, bp - Prec*Nbits); - if(d == 0){ /* underflow */ - errno = ERANGE; - } - return d; -} - -static void -frnorm(ulong *f) -{ - int i, c; - - c = 0; - for(i=Prec-1; i>0; i--) { - f[i] += c; - c = f[i] >> Nbits; - f[i] &= One-1; - } - f[0] += c; -} - -static int -fpcmp(char *a, ulong* f) -{ - ulong tf[Prec]; - int i, d, c; - - for(i=0; i<Prec; i++) - tf[i] = f[i]; - - for(;;) { - /* tf *= 10 */ - for(i=0; i<Prec; i++) - tf[i] = tf[i]*10; - frnorm(tf); - d = (tf[0] >> Nbits) + '0'; - tf[0] &= One-1; - - /* compare next digit */ - c = *a; - if(c == 0) { - if('0' < d) - return -1; - if(tf[0] != 0) - goto cont; - for(i=1; i<Prec; i++) - if(tf[i] != 0) - goto cont; - return 0; - } - if(c > d) - return +1; - if(c < d) - return -1; - a++; - cont:; - } -} - -static void -divby(char *a, int *na, int b) -{ - int n, c; - char *p; - - p = a; - n = 0; - while(n>>b == 0) { - c = *a++; - if(c == 0) { - while(n) { - c = n*10; - if(c>>b) - break; - n = c; - } - goto xx; - } - n = n*10 + c-'0'; - (*na)--; - } - for(;;) { - c = n>>b; - n -= c<<b; - *p++ = c + '0'; - c = *a++; - if(c == 0) - break; - n = n*10 + c-'0'; - } - (*na)++; -xx: - while(n) { - n = n*10; - c = n>>b; - n -= c<<b; - *p++ = c + '0'; - (*na)++; - } - *p = 0; -} - -static Tab tab1[] = -{ - 1, 0, "", - 3, 1, "7", - 6, 2, "63", - 9, 3, "511", - 13, 4, "8191", - 16, 5, "65535", - 19, 6, "524287", - 23, 7, "8388607", - 26, 8, "67108863", - 27, 9, "134217727", -}; - -static void -divascii(char *a, int *na, int *dp, int *bp) -{ - int b, d; - Tab *t; - - d = *dp; - if(d >= (int)(nelem(tab1))) - d = (int)(nelem(tab1))-1; - t = tab1 + d; - b = t->bp; - if(memcmp(a, t->cmp, t->siz) > 0) - d--; - *dp -= d; - *bp += b; - divby(a, na, b); -} - -static void -mulby(char *a, char *p, char *q, int b) -{ - int n, c; - - n = 0; - *p = 0; - for(;;) { - q--; - if(q < a) - break; - c = *q - '0'; - c = (c<<b) + n; - n = c/10; - c -= n*10; - p--; - *p = c + '0'; - } - while(n) { - c = n; - n = c/10; - c -= n*10; - p--; - *p = c + '0'; - } -} - -static Tab tab2[] = -{ - 1, 1, "", /* dp = 0-0 */ - 3, 3, "125", - 6, 5, "15625", - 9, 7, "1953125", - 13, 10, "1220703125", - 16, 12, "152587890625", - 19, 14, "19073486328125", - 23, 17, "11920928955078125", - 26, 19, "1490116119384765625", - 27, 19, "7450580596923828125", /* dp 8-9 */ -}; - -static void -mulascii(char *a, int *na, int *dp, int *bp) -{ - char *p; - int d, b; - Tab *t; - - d = -*dp; - if(d >= (int)(nelem(tab2))) - d = (int)(nelem(tab2))-1; - t = tab2 + d; - b = t->bp; - if(memcmp(a, t->cmp, t->siz) < 0) - d--; - p = a + *na; - *bp -= b; - *dp += d; - *na += d; - mulby(a, p+d, p, b); -} - -static int -xcmp(char *a, char *b) -{ - int c1, c2; - - while(c1 = *b++) { - c2 = *a++; - if(isupper(c2)) - c2 = tolower(c2); - if(c1 != c2) - return 1; - } - return 0; -} diff --git a/libfmt/test.c b/libfmt/test.c @@ -1,44 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdio.h> -#include <stdarg.h> -#include <utf.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -main(int argc, char *argv[]) -{ - quotefmtinstall(); - print("hello world\n"); - print("x: %x\n", 0x87654321); - print("u: %u\n", 0x87654321); - print("d: %d\n", 0x87654321); - print("s: %s\n", "hi there"); - print("q: %q\n", "hi i'm here"); - print("c: %c\n", '!'); - print("g: %g %g %g\n", 3.14159, 3.14159e10, 3.14159e-10); - print("e: %e %e %e\n", 3.14159, 3.14159e10, 3.14159e-10); - print("f: %f %f %f\n", 3.14159, 3.14159e10, 3.14159e-10); - print("smiley: %C\n", (Rune)0x263a); - print("%g %.18g\n", 2e25, 2e25); - print("%2.18g\n", 1.0); - print("%2.18f\n", 1.0); - print("%f\n", 3.1415927/4); - print("%d\n", 23); - print("%i\n", 23); - print("%0.10d\n", 12345); - return 0; -} diff --git a/libfmt/test2.c b/libfmt/test2.c @@ -1,9 +0,0 @@ -#include <stdarg.h> -#include <utf.h> -#include <fmt.h> - -int -main(int argc, char **argv) -{ - print("%020.10d\n", 100); -} diff --git a/libfmt/test3.c b/libfmt/test3.c @@ -1,52 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <stdio.h> - -void -test(char *fmt, ...) -{ - va_list arg; - char fmtbuf[100], stdbuf[100]; - - va_start(arg, fmt); - vsnprint(fmtbuf, sizeof fmtbuf, fmt, arg); - va_end(arg); - - va_start(arg, fmt); - vsnprint(stdbuf, sizeof stdbuf, fmt, arg); - va_end(arg); - - if(strcmp(fmtbuf, stdbuf) != 0) - print("fmt %s: fmt=\"%s\" std=\"%s\"\n", fmt, fmtbuf, stdbuf); - - print("fmt %s: %s\n", fmt, fmtbuf); -} - - -int -main(int argc, char *argv[]) -{ - test("%f", 3.14159); - test("%f", 3.14159e10); - test("%f", 3.14159e-10); - - test("%e", 3.14159); - test("%e", 3.14159e10); - test("%e", 3.14159e-10); - - test("%g", 3.14159); - test("%g", 3.14159e10); - test("%g", 3.14159e-10); - - test("%g", 2e25); - test("%.18g", 2e25); - - test("%2.18g", 1.0); - test("%2.18f", 1.0); - test("%f", 3.1415927/4); - - test("%20.10d", 12345); - test("%0.10d", 12345); - - return 0; -} diff --git a/libfmt/vfprint.c b/libfmt/vfprint.c @@ -1,33 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -vfprint(int fd, const char *fmt, va_list args) -{ - Fmt f; - char buf[256]; - int n; - - fmtfdinit(&f, fd, buf, sizeof(buf)); - va_copy(f.args,args); - n = dofmt(&f, fmt); - va_end(f.args); - if(n > 0 && __fmtFdFlush(&f) == 0) - return -1; - return n; -} diff --git a/libfmt/vseprint.c b/libfmt/vseprint.c @@ -1,39 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -char* -vseprint(char *buf, char *e, const char *fmt, va_list args) -{ - Fmt f; - - if(e <= buf) - return nil; - f.runes = 0; - f.start = buf; - f.to = buf; - f.stop = e - 1; - f.flush = 0; - f.farg = nil; - f.nfmt = 0; - va_copy(f.args,args); - dofmt(&f, fmt); - va_end(f.args); - *(char*)f.to = '\0'; - return (char*)f.to; -} - diff --git a/libfmt/vsmprint.c b/libfmt/vsmprint.c @@ -1,88 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -/* - * Plan 9 port version must include libc.h in order to - * get Plan 9 debugging malloc, which sometimes returns - * different pointers than the standard malloc. - */ -#include <stdlib.h> -#include <string.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -static int -fmtStrFlush(Fmt *f) -{ - char *s; - int n; - - if(f->start == nil) - return 0; - n = (uintptr_t)f->farg; - n *= 2; - s = (char*)f->start; - f->start = realloc(s, n); - if(f->start == nil){ - f->farg = nil; - f->to = nil; - f->stop = nil; - free(s); - return 0; - } - f->farg = (void*)(uintptr_t)n; - f->to = (char*)f->start + ((char*)f->to - s); - f->stop = (char*)f->start + n - 1; - return 1; -} - -int -fmtstrinit(Fmt *f) -{ - int n; - - memset(f, 0, sizeof *f); - f->runes = 0; - n = 32; - f->start = malloc(n); - if(f->start == nil) - return -1; - f->to = f->start; - f->stop = (char*)f->start + n - 1; - f->flush = fmtStrFlush; - f->farg = (void*)(uintptr_t)n; - f->nfmt = 0; - return 0; -} - -/* - * print into an allocated string buffer - */ -char* -vsmprint(const char *fmt, va_list args) -{ - Fmt f; - int n; - - if(fmtstrinit(&f) < 0) - return nil; - va_copy(f.args,args); - n = dofmt(&f, fmt); - va_end(f.args); - if(n < 0){ - free(f.start); - return nil; - } - return fmtstrflush(&f); -} diff --git a/libfmt/vsnprint.c b/libfmt/vsnprint.c @@ -1,39 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdlib.h> -#include <stdarg.h> -#include "plan9.h" -#include "fmt.h" -#include "fmtdef.h" - -int -vsnprint(char *buf, int len, const char *fmt, va_list args) -{ - Fmt f; - - if(len <= 0) - return -1; - f.runes = 0; - f.start = buf; - f.to = buf; - f.stop = buf + len - 1; - f.flush = 0; - f.farg = nil; - f.nfmt = 0; - va_copy(f.args,args); - dofmt(&f, fmt); - va_end(f.args); - *(char*)f.to = '\0'; - return (char*)f.to - buf; -} diff --git a/libregexp/Makefile b/libregexp/Makefile @@ -1,17 +0,0 @@ -ROOT= .. -include ${ROOT}/mk/hdr.mk - -VERSION=2.0 -TARG=libregexp9 - -OBJ=\ - regcomp\ - regerror\ - regexec\ - regsub\ - regaux\ - rregexec\ - rregsub - -include ${ROOT}/mk/lib.mk - diff --git a/libregexp/NOTICE b/libregexp/NOTICE @@ -1,25 +0,0 @@ -/* - * The authors of this software is Rob Pike. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -This is a Unix port of the Plan 9 regular expression library. - -Please send comments about the packaging -to Russ Cox <rsc@swtch.com>. - - ----- - -This software is also made available under the Lucent Public License -version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html - diff --git a/libregexp/README b/libregexp/README @@ -1,5 +0,0 @@ -This software was packaged for Unix by Russ Cox. -Please send comments to rsc@swtch.com. - -http://swtch.com/plan9port/unix - diff --git a/libregexp/regaux.c b/libregexp/regaux.c @@ -1,112 +0,0 @@ -#include "plan9.h" -#include "regexp9.h" -#include "regcomp.h" - - -/* - * save a new match in mp - */ -extern void -_renewmatch(Resub *mp, int ms, Resublist *sp) -{ - int i; - - if(mp==0 || ms<=0) - return; - if(mp[0].s.sp==0 || sp->m[0].s.sp<mp[0].s.sp || - (sp->m[0].s.sp==mp[0].s.sp && sp->m[0].e.ep>mp[0].e.ep)){ - for(i=0; i<ms && i<NSUBEXP; i++) - mp[i] = sp->m[i]; - for(; i<ms; i++) - mp[i].s.sp = mp[i].e.ep = 0; - } -} - -/* - * Note optimization in _renewthread: - * *lp must be pending when _renewthread called; if *l has been looked - * at already, the optimization is a bug. - */ -extern Relist* -_renewthread(Relist *lp, /* _relist to add to */ - Reinst *ip, /* instruction to add */ - int ms, - Resublist *sep) /* pointers to subexpressions */ -{ - Relist *p; - - for(p=lp; p->inst; p++){ - if(p->inst == ip){ - if(sep->m[0].s.sp < p->se.m[0].s.sp){ - if(ms > 1) - p->se = *sep; - else - p->se.m[0] = sep->m[0]; - } - return 0; - } - } - p->inst = ip; - if(ms > 1) - p->se = *sep; - else - p->se.m[0] = sep->m[0]; - (++p)->inst = 0; - return p; -} - -/* - * same as renewthread, but called with - * initial empty start pointer. - */ -extern Relist* -_renewemptythread(Relist *lp, /* _relist to add to */ - Reinst *ip, /* instruction to add */ - int ms, - char *sp) /* pointers to subexpressions */ -{ - Relist *p; - - for(p=lp; p->inst; p++){ - if(p->inst == ip){ - if(sp < p->se.m[0].s.sp) { - if(ms > 1) - memset(&p->se, 0, sizeof(p->se)); - p->se.m[0].s.sp = sp; - } - return 0; - } - } - p->inst = ip; - if(ms > 1) - memset(&p->se, 0, sizeof(p->se)); - p->se.m[0].s.sp = sp; - (++p)->inst = 0; - return p; -} - -extern Relist* -_rrenewemptythread(Relist *lp, /* _relist to add to */ - Reinst *ip, /* instruction to add */ - int ms, - Rune *rsp) /* pointers to subexpressions */ -{ - Relist *p; - - for(p=lp; p->inst; p++){ - if(p->inst == ip){ - if(rsp < p->se.m[0].s.rsp) { - if(ms > 1) - memset(&p->se, 0, sizeof(p->se)); - p->se.m[0].s.rsp = rsp; - } - return 0; - } - } - p->inst = ip; - if(ms > 1) - memset(&p->se, 0, sizeof(p->se)); - p->se.m[0].s.rsp = rsp; - (++p)->inst = 0; - return p; -} diff --git a/libregexp/regcomp.c b/libregexp/regcomp.c @@ -1,559 +0,0 @@ -#include <setjmp.h> -#include <stdlib.h> -#include "plan9.h" -#include "regexp9.h" -#include "regcomp.h" - -enum { - FALSE, - TRUE, -}; - -/* - * Parser Information - */ -typedef struct Node Node; -struct Node -{ - Reinst* first; - Reinst* last; -}; - -#define NSTACK 20 -static Node andstack[NSTACK]; -static Node *andp; -static int atorstack[NSTACK]; -static int* atorp; -static int cursubid; /* id of current subexpression */ -static int subidstack[NSTACK]; /* parallel to atorstack */ -static int* subidp; -static int lastwasand; /* Last token was operand */ -static int nbra; -static char* exprp; /* pointer to next character in source expression */ -static int lexdone; -static int nclass; -static Reclass*classp; -static Reinst* freep; -static int errors; -static Rune yyrune; /* last lex'd rune */ -static Reclass*yyclassp; /* last lex'd class */ - -/* predeclared crap */ -static void operator(int); -static void pushand(Reinst*, Reinst*); -static void pushator(int); -static void evaluntil(int); -static int bldcclass(void); - -static jmp_buf regkaboom; - -static void -rcerror(char *s) -{ - errors++; - regerror(s); - longjmp(regkaboom, 1); -} - -static Reinst* -newinst(int t) -{ - freep->type = t; - freep->u2.left = 0; - freep->u1.right = 0; - return freep++; -} - -static void -operand(int t) -{ - Reinst *i; - - if(lastwasand) - operator(CAT); /* catenate is implicit */ - i = newinst(t); - - if(t == CCLASS || t == NCCLASS) - i->u1.cp = yyclassp; - if(t == RUNE) - i->u1.r = yyrune; - - pushand(i, i); - lastwasand = TRUE; -} - -static void -operator(int t) -{ - if(t==RBRA && --nbra<0) - rcerror("unmatched right paren"); - if(t==LBRA){ - if(++cursubid >= NSUBEXP) - rcerror ("too many subexpressions"); - nbra++; - if(lastwasand) - operator(CAT); - } else - evaluntil(t); - if(t != RBRA) - pushator(t); - lastwasand = FALSE; - if(t==STAR || t==QUEST || t==PLUS || t==RBRA) - lastwasand = TRUE; /* these look like operands */ -} - -static void -regerr2(char *s, int c) -{ - char buf[100]; - char *cp = buf; - while(*s) - *cp++ = *s++; - *cp++ = c; - *cp = '\0'; - rcerror(buf); -} - -static void -cant(char *s) -{ - char buf[100]; - strcpy(buf, "can't happen: "); - strcat(buf, s); - rcerror(buf); -} - -static void -pushand(Reinst *f, Reinst *l) -{ - if(andp >= &andstack[NSTACK]) - cant("operand stack overflow"); - andp->first = f; - andp->last = l; - andp++; -} - -static void -pushator(int t) -{ - if(atorp >= &atorstack[NSTACK]) - cant("operator stack overflow"); - *atorp++ = t; - *subidp++ = cursubid; -} - -static Node* -popand(int op) -{ - Reinst *inst; - - if(andp <= &andstack[0]){ - regerr2("missing operand for ", op); - inst = newinst(NOP); - pushand(inst,inst); - } - return --andp; -} - -static int -popator(void) -{ - if(atorp <= &atorstack[0]) - cant("operator stack underflow"); - --subidp; - return *--atorp; -} - -static void -evaluntil(int pri) -{ - Node *op1, *op2; - Reinst *inst1, *inst2; - - while(pri==RBRA || atorp[-1]>=pri){ - switch(popator()){ - default: - rcerror("unknown operator in evaluntil"); - break; - case LBRA: /* must have been RBRA */ - op1 = popand('('); - inst2 = newinst(RBRA); - inst2->u1.subid = *subidp; - op1->last->u2.next = inst2; - inst1 = newinst(LBRA); - inst1->u1.subid = *subidp; - inst1->u2.next = op1->first; - pushand(inst1, inst2); - return; - case OR: - op2 = popand('|'); - op1 = popand('|'); - inst2 = newinst(NOP); - op2->last->u2.next = inst2; - op1->last->u2.next = inst2; - inst1 = newinst(OR); - inst1->u1.right = op1->first; - inst1->u2.left = op2->first; - pushand(inst1, inst2); - break; - case CAT: - op2 = popand(0); - op1 = popand(0); - op1->last->u2.next = op2->first; - pushand(op1->first, op2->last); - break; - case STAR: - op2 = popand('*'); - inst1 = newinst(OR); - op2->last->u2.next = inst1; - inst1->u1.right = op2->first; - pushand(inst1, inst1); - break; - case PLUS: - op2 = popand('+'); - inst1 = newinst(OR); - op2->last->u2.next = inst1; - inst1->u1.right = op2->first; - pushand(op2->first, inst1); - break; - case QUEST: - op2 = popand('?'); - inst1 = newinst(OR); - inst2 = newinst(NOP); - inst1->u2.left = inst2; - inst1->u1.right = op2->first; - op2->last->u2.next = inst2; - pushand(inst1, inst2); - break; - } - } -} - -static Reprog* -optimize(Reprog *pp) -{ - Reinst *inst, *target; - int size; - Reprog *npp; - Reclass *cl; - int diff; - - /* - * get rid of NOOP chains - */ - for(inst=pp->firstinst; inst->type!=END; inst++){ - target = inst->u2.next; - while(target->type == NOP) - target = target->u2.next; - inst->u2.next = target; - } - - /* - * The original allocation is for an area larger than - * necessary. Reallocate to the actual space used - * and then relocate the code. - */ - size = sizeof(Reprog) + (freep - pp->firstinst)*sizeof(Reinst); - npp = realloc(pp, size); - if(npp==0 || npp==pp) - return pp; - diff = (char *)npp - (char *)pp; - freep = (Reinst *)((char *)freep + diff); - for(inst=npp->firstinst; inst<freep; inst++){ - switch(inst->type){ - case OR: - case STAR: - case PLUS: - case QUEST: - *(char **)&inst->u1.right += diff; - break; - case CCLASS: - case NCCLASS: - *(char **)&inst->u1.right += diff; - cl = inst->u1.cp; - *(char **)&cl->end += diff; - break; - } - *(char **)&inst->u2.left += diff; - } - *(char **)&npp->startinst += diff; - return npp; -} - -#ifdef DEBUG -static void -dumpstack(void){ - Node *stk; - int *ip; - - print("operators\n"); - for(ip=atorstack; ip<atorp; ip++) - print("0%o\n", *ip); - print("operands\n"); - for(stk=andstack; stk<andp; stk++) - print("0%o\t0%o\n", stk->first->type, stk->last->type); -} - -static void -dump(Reprog *pp) -{ - Reinst *l; - Rune *p; - - l = pp->firstinst; - do{ - print("%d:\t0%o\t%d\t%d", l-pp->firstinst, l->type, - l->u2.left-pp->firstinst, l->u1.right-pp->firstinst); - if(l->type == RUNE) - print("\t%C\n", l->u1.r); - else if(l->type == CCLASS || l->type == NCCLASS){ - print("\t["); - if(l->type == NCCLASS) - print("^"); - for(p = l->u1.cp->spans; p < l->u1.cp->end; p += 2) - if(p[0] == p[1]) - print("%C", p[0]); - else - print("%C-%C", p[0], p[1]); - print("]\n"); - } else - print("\n"); - }while(l++->type); -} -#endif - -static Reclass* -newclass(void) -{ - if(nclass >= NCLASS) - regerr2("too many character classes; limit", NCLASS+'0'); - return &(classp[nclass++]); -} - -static int -nextc(Rune *rp) -{ - if(lexdone){ - *rp = 0; - return 1; - } - exprp += chartorune(rp, exprp); - if(*rp == '\\'){ - exprp += chartorune(rp, exprp); - return 1; - } - if(*rp == 0) - lexdone = 1; - return 0; -} - -static int -lex(int literal, int dot_type) -{ - int quoted; - - quoted = nextc(&yyrune); - if(literal || quoted){ - if(yyrune == 0) - return END; - return RUNE; - } - - switch(yyrune){ - case 0: - return END; - case '*': - return STAR; - case '?': - return QUEST; - case '+': - return PLUS; - case '|': - return OR; - case '.': - return dot_type; - case '(': - return LBRA; - case ')': - return RBRA; - case '^': - return BOL; - case '$': - return EOL; - case '[': - return bldcclass(); - } - return RUNE; -} - -static int -bldcclass(void) -{ - int type; - Rune r[NCCRUNE]; - Rune *p, *ep, *np; - Rune rune; - int quoted; - - /* we have already seen the '[' */ - type = CCLASS; - yyclassp = newclass(); - - /* look ahead for negation */ - /* SPECIAL CASE!!! negated classes don't match \n */ - ep = r; - quoted = nextc(&rune); - if(!quoted && rune == '^'){ - type = NCCLASS; - quoted = nextc(&rune); - *ep++ = '\n'; - *ep++ = '\n'; - } - - /* parse class into a set of spans */ - for(; ep<&r[NCCRUNE];){ - if(rune == 0){ - rcerror("malformed '[]'"); - return 0; - } - if(!quoted && rune == ']') - break; - if(!quoted && rune == '-'){ - if(ep == r){ - rcerror("malformed '[]'"); - return 0; - } - quoted = nextc(&rune); - if((!quoted && rune == ']') || rune == 0){ - rcerror("malformed '[]'"); - return 0; - } - *(ep-1) = rune; - } else { - *ep++ = rune; - *ep++ = rune; - } - quoted = nextc(&rune); - } - - /* sort on span start */ - for(p = r; p < ep; p += 2){ - for(np = p; np < ep; np += 2) - if(*np < *p){ - rune = np[0]; - np[0] = p[0]; - p[0] = rune; - rune = np[1]; - np[1] = p[1]; - p[1] = rune; - } - } - - /* merge spans */ - np = yyclassp->spans; - p = r; - if(r == ep) - yyclassp->end = np; - else { - np[0] = *p++; - np[1] = *p++; - for(; p < ep; p += 2) - if(p[0] <= np[1]){ - if(p[1] > np[1]) - np[1] = p[1]; - } else { - np += 2; - np[0] = p[0]; - np[1] = p[1]; - } - yyclassp->end = np+2; - } - - return type; -} - -static Reprog* -regcomp1(char *s, int literal, int dot_type) -{ - int token; - Reprog *volatile pp; - - /* get memory for the program */ - pp = malloc(sizeof(Reprog) + 6*sizeof(Reinst)*strlen(s)); - if(pp == 0){ - regerror("out of memory"); - return 0; - } - freep = pp->firstinst; - classp = pp->class; - errors = 0; - - if(setjmp(regkaboom)) - goto out; - - /* go compile the sucker */ - lexdone = 0; - exprp = s; - nclass = 0; - nbra = 0; - atorp = atorstack; - andp = andstack; - subidp = subidstack; - lastwasand = FALSE; - cursubid = 0; - - /* Start with a low priority operator to prime parser */ - pushator(START-1); - while((token = lex(literal, dot_type)) != END){ - if((token&0300) == OPERATOR) - operator(token); - else - operand(token); - } - - /* Close with a low priority operator */ - evaluntil(START); - - /* Force END */ - operand(END); - evaluntil(START); -#ifdef DEBUG - dumpstack(); -#endif - if(nbra) - rcerror("unmatched left paren"); - --andp; /* points to first and only operand */ - pp->startinst = andp->first; -#ifdef DEBUG - dump(pp); -#endif - pp = optimize(pp); -#ifdef DEBUG - print("start: %d\n", andp->first-pp->firstinst); - dump(pp); -#endif -out: - if(errors){ - free(pp); - pp = 0; - } - return pp; -} - -extern Reprog* -regcomp(char *s) -{ - return regcomp1(s, 0, ANY); -} - -extern Reprog* -regcomplit(char *s) -{ - return regcomp1(s, 1, ANY); -} - -extern Reprog* -regcompnl(char *s) -{ - return regcomp1(s, 0, ANYNL); -} diff --git a/libregexp/regerror.c b/libregexp/regerror.c @@ -1,15 +0,0 @@ -#include <stdlib.h> -#include <plan9.h> -#include <regexp9.h> - -void -regerror(char *s) -{ - char buf[132]; - - strcpy(buf, "regerror: "); - strcat(buf, s); - strcat(buf, "\n"); - write(2, buf, strlen(buf)); - exits("regerr"); -} diff --git a/libregexp/regexec.c b/libregexp/regexec.c @@ -1,232 +0,0 @@ -#include <stdlib.h> -#include "plan9.h" -#include "regexp9.h" -#include "regcomp.h" - - -/* - * return 0 if no match - * >0 if a match - * <0 if we ran out of _relist space - */ -static int -regexec1(Reprog *progp, /* program to run */ - char *bol, /* string to run machine on */ - Resub *mp, /* subexpression elements */ - int ms, /* number of elements at mp */ - Reljunk *j -) -{ - int flag=0; - Reinst *inst; - Relist *tlp; - char *s; - int i, checkstart; - Rune r, *rp, *ep; - int n; - Relist* tl; /* This list, next list */ - Relist* nl; - Relist* tle; /* ends of this and next list */ - Relist* nle; - int match; - char *p; - - match = 0; - checkstart = j->starttype; - if(mp) - for(i=0; i<ms; i++) { - mp[i].s.sp = 0; - mp[i].e.ep = 0; - } - j->relist[0][0].inst = 0; - j->relist[1][0].inst = 0; - - /* Execute machine once for each character, including terminal NUL */ - s = j->starts; - do{ - /* fast check for first char */ - if(checkstart) { - switch(j->starttype) { - case RUNE: - p = utfrune(s, j->startchar); - if(p == 0 || s == j->eol) - return match; - s = p; - break; - case BOL: - if(s == bol) - break; - p = utfrune(s, '\n'); - if(p == 0 || s == j->eol) - return match; - s = p; - break; - } - } - r = *(uchar*)s; - if(r < Runeself) - n = 1; - else - n = chartorune(&r, s); - - /* switch run lists */ - tl = j->relist[flag]; - tle = j->reliste[flag]; - nl = j->relist[flag^=1]; - nle = j->reliste[flag]; - nl->inst = 0; - - /* Add first instruction to current list */ - if(match == 0) - _renewemptythread(tl, progp->startinst, ms, s); - - /* Execute machine until current list is empty */ - for(tlp=tl; tlp->inst; tlp++){ /* assignment = */ - for(inst = tlp->inst; ; inst = inst->u2.next){ - switch(inst->type){ - case RUNE: /* regular character */ - if(inst->u1.r == r){ - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - } - break; - case LBRA: - tlp->se.m[inst->u1.subid].s.sp = s; - continue; - case RBRA: - tlp->se.m[inst->u1.subid].e.ep = s; - continue; - case ANY: - if(r != '\n') - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case ANYNL: - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case BOL: - if(s == bol || *(s-1) == '\n') - continue; - break; - case EOL: - if(s == j->eol || r == 0 || r == '\n') - continue; - break; - case CCLASS: - ep = inst->u1.cp->end; - for(rp = inst->u1.cp->spans; rp < ep; rp += 2) - if(r >= rp[0] && r <= rp[1]){ - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - } - break; - case NCCLASS: - ep = inst->u1.cp->end; - for(rp = inst->u1.cp->spans; rp < ep; rp += 2) - if(r >= rp[0] && r <= rp[1]) - break; - if(rp == ep) - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case OR: - /* evaluate right choice later */ - if(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle) - return -1; - /* efficiency: advance and re-evaluate */ - continue; - case END: /* Match! */ - match = 1; - tlp->se.m[0].e.ep = s; - if(mp != 0) - _renewmatch(mp, ms, &tlp->se); - break; - } - break; - } - } - if(s == j->eol) - break; - checkstart = j->starttype && nl->inst==0; - s += n; - }while(r); - return match; -} - -static int -regexec2(Reprog *progp, /* program to run */ - char *bol, /* string to run machine on */ - Resub *mp, /* subexpression elements */ - int ms, /* number of elements at mp */ - Reljunk *j -) -{ - int rv; - Relist *relist0, *relist1; - - /* mark space */ - relist0 = malloc(BIGLISTSIZE*sizeof(Relist)); - if(relist0 == nil) - return -1; - relist1 = malloc(BIGLISTSIZE*sizeof(Relist)); - if(relist1 == nil){ - free(relist1); - return -1; - } - j->relist[0] = relist0; - j->relist[1] = relist1; - j->reliste[0] = relist0 + BIGLISTSIZE - 2; - j->reliste[1] = relist1 + BIGLISTSIZE - 2; - - rv = regexec1(progp, bol, mp, ms, j); - free(relist0); - free(relist1); - return rv; -} - -extern int -regexec(Reprog *progp, /* program to run */ - char *bol, /* string to run machine on */ - Resub *mp, /* subexpression elements */ - int ms) /* number of elements at mp */ -{ - Reljunk j; - Relist relist0[LISTSIZE], relist1[LISTSIZE]; - int rv; - - /* - * use user-specified starting/ending location if specified - */ - j.starts = bol; - j.eol = 0; - if(mp && ms>0){ - if(mp->s.sp) - j.starts = mp->s.sp; - if(mp->e.ep) - j.eol = mp->e.ep; - } - j.starttype = 0; - j.startchar = 0; - if(progp->startinst->type == RUNE && progp->startinst->u1.r < Runeself) { - j.starttype = RUNE; - j.startchar = progp->startinst->u1.r; - } - if(progp->startinst->type == BOL) - j.starttype = BOL; - - /* mark space */ - j.relist[0] = relist0; - j.relist[1] = relist1; - j.reliste[0] = relist0 + nelem(relist0) - 2; - j.reliste[1] = relist1 + nelem(relist1) - 2; - - rv = regexec1(progp, bol, mp, ms, &j); - if(rv >= 0) - return rv; - rv = regexec2(progp, bol, mp, ms, &j); - if(rv >= 0) - return rv; - return -1; -} diff --git a/libregexp/regexp9.3 b/libregexp/regexp9.3 @@ -1,220 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH REGEXP9 3 -.SH NAME -regcomp, regcomplit, regcompnl, regexec, regsub, rregexec, rregsub, regerror \- regular expression -.SH SYNOPSIS -.B #include <utf.h> -.br -.B #include <fmt.h> -.br -.B #include <regexp9.h> -.PP -.ta \w'\fLRegprog 'u -.B -Reprog *regcomp(char *exp) -.PP -.B -Reprog *regcomplit(char *exp) -.PP -.B -Reprog *regcompnl(char *exp) -.PP -.nf -.B -int regexec(Reprog *prog, char *string, Resub *match, int msize) -.PP -.nf -.B -void regsub(char *source, char *dest, int dlen, Resub *match, int msize) -.PP -.nf -.B -int rregexec(Reprog *prog, Rune *string, Resub *match, int msize) -.PP -.nf -.B -void rregsub(Rune *source, Rune *dest, int dlen, Resub *match, int msize) -.PP -.B -void regerror(char *msg) -.SH DESCRIPTION -.I Regcomp -compiles a -regular expression and returns -a pointer to the generated description. -The space is allocated by -.IR malloc (3) -and may be released by -.IR free . -Regular expressions are exactly as in -.IR regexp9 (7). -.PP -.I Regcomplit -is like -.I regcomp -except that all characters are treated literally. -.I Regcompnl -is like -.I regcomp -except that the -.B . -metacharacter matches all characters, including newlines. -.PP -.I Regexec -matches a null-terminated -.I string -against the compiled regular expression in -.IR prog . -If it matches, -.I regexec -returns -.B 1 -and fills in the array -.I match -with character pointers to the substrings of -.I string -that correspond to the -parenthesized subexpressions of -.IR exp : -.BI match[ i ].sp -points to the beginning and -.BI match[ i ].ep -points just beyond -the end of the -.IR i th -substring. -(Subexpression -.I i -begins at the -.IR i th -left parenthesis, counting from 1.) -Pointers in -.B match[0] -pick out the substring that corresponds to -the whole regular expression. -Unused elements of -.I match -are filled with zeros. -Matches involving -.LR * , -.LR + , -and -.L ? -are extended as far as possible. -The number of array elements in -.I match -is given by -.IR msize . -The structure of elements of -.I match -is: -.IP -.EX -typedef struct { - union { - char *sp; - Rune *rsp; - }; - union { - char *ep; - Rune *rep; - }; -} Resub; -.EE -.LP -If -.B match[0].sp -is nonzero on entry, -.I regexec -starts matching at that point within -.IR string . -If -.B match[0].ep -is nonzero on entry, -the last character matched is the one -preceding that point. -.PP -.I Regsub -places in -.I dest -a substitution instance of -.I source -in the context of the last -.I regexec -performed using -.IR match . -Each instance of -.BI \e n\f1, -where -.I n -is a digit, is replaced by the -string delimited by -.BI match[ n ].sp -and -.BI match[ n ].ep\f1. -Each instance of -.L & -is replaced by the string delimited by -.B match[0].sp -and -.BR match[0].ep . -The substitution will always be null terminated and -trimmed to fit into dlen bytes. -.PP -.IR Regerror , -called whenever an error is detected in -.IR regcomp , -writes the string -.I msg -on the standard error file and exits. -.I Regerror -can be replaced to perform -special error processing. -If the user supplied -.I regerror -returns rather than exits, -.I regcomp -will return 0. -.PP -.I Rregexec -and -.I rregsub -are variants of -.I regexec -and -.I regsub -that use strings of -.B Runes -instead of strings of -.BR chars . -With these routines, the -.I rsp -and -.I rep -fields of the -.I match -array elements should be used. -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH "SEE ALSO" -.IR grep (1) -.SH DIAGNOSTICS -.I Regcomp -returns -.B 0 -for an illegal expression -or other failure. -.I Regexec -returns 0 -if -.I string -is not matched. -.SH BUGS -There is no way to specify or match a NUL character; NULs terminate patterns and strings. diff --git a/libregexp/regexp9.7 b/libregexp/regexp9.7 @@ -1,141 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH REGEXP9 7 -.SH NAME -regexp \- Plan 9 regular expression notation -.SH DESCRIPTION -This manual page describes the regular expression -syntax used by the Plan 9 regular expression library -.IR regexp9 (3). -It is the form used by -.IR egrep (1) -before -.I egrep -got complicated. -.PP -A -.I "regular expression" -specifies -a set of strings of characters. -A member of this set of strings is said to be -.I matched -by the regular expression. In many applications -a delimiter character, commonly -.LR / , -bounds a regular expression. -In the following specification for regular expressions -the word `character' means any character (rune) but newline. -.PP -The syntax for a regular expression -.B e0 -is -.IP -.EX -e3: literal | charclass | '.' | '^' | '$' | '(' e0 ')' - -e2: e3 - | e2 REP - -REP: '*' | '+' | '?' - -e1: e2 - | e1 e2 - -e0: e1 - | e0 '|' e1 -.EE -.PP -A -.B literal -is any non-metacharacter, or a metacharacter -(one of -.BR .*+?[]()|\e^$ ), -or the delimiter -preceded by -.LR \e . -.PP -A -.B charclass -is a nonempty string -.I s -bracketed -.BI [ \|s\| ] -(or -.BI [^ s\| ]\fR); -it matches any character in (or not in) -.IR s . -A negated character class never -matches newline. -A substring -.IB a - b\f1, -with -.I a -and -.I b -in ascending -order, stands for the inclusive -range of -characters between -.I a -and -.IR b . -In -.IR s , -the metacharacters -.LR - , -.LR ] , -an initial -.LR ^ , -and the regular expression delimiter -must be preceded by a -.LR \e ; -other metacharacters -have no special meaning and -may appear unescaped. -.PP -A -.L . -matches any character. -.PP -A -.L ^ -matches the beginning of a line; -.L $ -matches the end of the line. -.PP -The -.B REP -operators match zero or more -.RB ( * ), -one or more -.RB ( + ), -zero or one -.RB ( ? ), -instances respectively of the preceding regular expression -.BR e2 . -.PP -A concatenated regular expression, -.BR "e1\|e2" , -matches a match to -.B e1 -followed by a match to -.BR e2 . -.PP -An alternative regular expression, -.BR "e0\||\|e1" , -matches either a match to -.B e0 -or a match to -.BR e1 . -.PP -A match to any part of a regular expression -extends as far as possible without preventing -a match to the remainder of the regular expression. -.SH "SEE ALSO -.IR regexp9 (3) diff --git a/libregexp/regsub.c b/libregexp/regsub.c @@ -1,63 +0,0 @@ -#include "plan9.h" -#include "regexp9.h" - -/* substitute into one string using the matches from the last regexec() */ -extern void -regsub(char *sp, /* source string */ - char *dp, /* destination string */ - int dlen, - Resub *mp, /* subexpression elements */ - int ms) /* number of elements pointed to by mp */ -{ - char *ssp, *ep; - int i; - - ep = dp+dlen-1; - while(*sp != '\0'){ - if(*sp == '\\'){ - switch(*++sp){ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - i = *sp-'0'; - if(mp[i].s.sp != 0 && mp!=0 && ms>i) - for(ssp = mp[i].s.sp; - ssp < mp[i].e.ep; - ssp++) - if(dp < ep) - *dp++ = *ssp; - break; - case '\\': - if(dp < ep) - *dp++ = '\\'; - break; - case '\0': - sp--; - break; - default: - if(dp < ep) - *dp++ = *sp; - break; - } - }else if(*sp == '&'){ - if(mp[0].s.sp != 0 && mp!=0 && ms>0) - if(mp[0].s.sp != 0) - for(ssp = mp[0].s.sp; - ssp < mp[0].e.ep; ssp++) - if(dp < ep) - *dp++ = *ssp; - }else{ - if(dp < ep) - *dp++ = *sp; - } - sp++; - } - *dp = '\0'; -} diff --git a/libregexp/rregexec.c b/libregexp/rregexec.c @@ -1,213 +0,0 @@ -#include "plan9.h" -#include "regexp9.h" -#include "regcomp.h" - -/* - * return 0 if no match - * >0 if a match - * <0 if we ran out of _relist space - */ -static int -rregexec1(Reprog *progp, /* program to run */ - Rune *bol, /* string to run machine on */ - Resub *mp, /* subexpression elements */ - int ms, /* number of elements at mp */ - Reljunk *j) -{ - int flag=0; - Reinst *inst; - Relist *tlp; - Rune *s; - int i, checkstart; - Rune r, *rp, *ep; - Relist* tl; /* This list, next list */ - Relist* nl; - Relist* tle; /* ends of this and next list */ - Relist* nle; - int match; - - match = 0; - checkstart = j->startchar; - if(mp) - for(i=0; i<ms; i++) { - mp[i].s.rsp = 0; - mp[i].e.rep = 0; - } - j->relist[0][0].inst = 0; - j->relist[1][0].inst = 0; - - /* Execute machine once for each character, including terminal NUL */ - s = j->rstarts; - do{ - - /* fast check for first char */ - if(checkstart) { - switch(j->starttype) { - case RUNE: - while(*s != j->startchar) { - if(*s == 0 || s == j->reol) - return match; - s++; - } - break; - case BOL: - if(s == bol) - break; - while(*s != '\n') { - if(*s == 0 || s == j->reol) - return match; - s++; - } - break; - } - } - - r = *s; - - /* switch run lists */ - tl = j->relist[flag]; - tle = j->reliste[flag]; - nl = j->relist[flag^=1]; - nle = j->reliste[flag]; - nl->inst = 0; - - /* Add first instruction to current list */ - _rrenewemptythread(tl, progp->startinst, ms, s); - - /* Execute machine until current list is empty */ - for(tlp=tl; tlp->inst; tlp++){ - for(inst=tlp->inst; ; inst = inst->u2.next){ - switch(inst->type){ - case RUNE: /* regular character */ - if(inst->u1.r == r) - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case LBRA: - tlp->se.m[inst->u1.subid].s.rsp = s; - continue; - case RBRA: - tlp->se.m[inst->u1.subid].e.rep = s; - continue; - case ANY: - if(r != '\n') - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case ANYNL: - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case BOL: - if(s == bol || *(s-1) == '\n') - continue; - break; - case EOL: - if(s == j->reol || r == 0 || r == '\n') - continue; - break; - case CCLASS: - ep = inst->u1.cp->end; - for(rp = inst->u1.cp->spans; rp < ep; rp += 2) - if(r >= rp[0] && r <= rp[1]){ - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - } - break; - case NCCLASS: - ep = inst->u1.cp->end; - for(rp = inst->u1.cp->spans; rp < ep; rp += 2) - if(r >= rp[0] && r <= rp[1]) - break; - if(rp == ep) - if(_renewthread(nl, inst->u2.next, ms, &tlp->se)==nle) - return -1; - break; - case OR: - /* evaluate right choice later */ - if(_renewthread(tlp, inst->u1.right, ms, &tlp->se) == tle) - return -1; - /* efficiency: advance and re-evaluate */ - continue; - case END: /* Match! */ - match = 1; - tlp->se.m[0].e.rep = s; - if(mp != 0) - _renewmatch(mp, ms, &tlp->se); - break; - } - break; - } - } - if(s == j->reol) - break; - checkstart = j->startchar && nl->inst==0; - s++; - }while(r); - return match; -} - -static int -rregexec2(Reprog *progp, /* program to run */ - Rune *bol, /* string to run machine on */ - Resub *mp, /* subexpression elements */ - int ms, /* number of elements at mp */ - Reljunk *j -) -{ - Relist relist0[5*LISTSIZE], relist1[5*LISTSIZE]; - - /* mark space */ - j->relist[0] = relist0; - j->relist[1] = relist1; - j->reliste[0] = relist0 + nelem(relist0) - 2; - j->reliste[1] = relist1 + nelem(relist1) - 2; - - return rregexec1(progp, bol, mp, ms, j); -} - -extern int -rregexec(Reprog *progp, /* program to run */ - Rune *bol, /* string to run machine on */ - Resub *mp, /* subexpression elements */ - int ms) /* number of elements at mp */ -{ - Reljunk j; - Relist relist0[LISTSIZE], relist1[LISTSIZE]; - int rv; - - /* - * use user-specified starting/ending location if specified - */ - j.rstarts = bol; - j.reol = 0; - if(mp && ms>0){ - if(mp->s.sp) - j.rstarts = mp->s.rsp; - if(mp->e.ep) - j.reol = mp->e.rep; - } - j.starttype = 0; - j.startchar = 0; - if(progp->startinst->type == RUNE && progp->startinst->u1.r < Runeself) { - j.starttype = RUNE; - j.startchar = progp->startinst->u1.r; - } - if(progp->startinst->type == BOL) - j.starttype = BOL; - - /* mark space */ - j.relist[0] = relist0; - j.relist[1] = relist1; - j.reliste[0] = relist0 + nelem(relist0) - 2; - j.reliste[1] = relist1 + nelem(relist1) - 2; - - rv = rregexec1(progp, bol, mp, ms, &j); - if(rv >= 0) - return rv; - rv = rregexec2(progp, bol, mp, ms, &j); - if(rv >= 0) - return rv; - return -1; -} diff --git a/libregexp/rregsub.c b/libregexp/rregsub.c @@ -1,63 +0,0 @@ -#include "plan9.h" -#include "regexp9.h" - -/* substitute into one string using the matches from the last regexec() */ -extern void -rregsub(Rune *sp, /* source string */ - Rune *dp, /* destination string */ - int dlen, - Resub *mp, /* subexpression elements */ - int ms) /* number of elements pointed to by mp */ -{ - Rune *ssp, *ep; - int i; - - ep = dp+(dlen/sizeof(Rune))-1; - while(*sp != '\0'){ - if(*sp == '\\'){ - switch(*++sp){ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - i = *sp-'0'; - if(mp[i].s.rsp != 0 && mp!=0 && ms>i) - for(ssp = mp[i].s.rsp; - ssp < mp[i].e.rep; - ssp++) - if(dp < ep) - *dp++ = *ssp; - break; - case '\\': - if(dp < ep) - *dp++ = '\\'; - break; - case '\0': - sp--; - break; - default: - if(dp < ep) - *dp++ = *sp; - break; - } - }else if(*sp == '&'){ - if(mp[0].s.rsp != 0 && mp!=0 && ms>0) - if(mp[0].s.rsp != 0) - for(ssp = mp[0].s.rsp; - ssp < mp[0].e.rep; ssp++) - if(dp < ep) - *dp++ = *ssp; - }else{ - if(dp < ep) - *dp++ = *sp; - } - sp++; - } - *dp = '\0'; -} diff --git a/libregexp/test.c b/libregexp/test.c @@ -1,46 +0,0 @@ -#include "plan9.h" -#include <regexp9.h> - -struct x -{ - char *re; - char *s; - Reprog *p; -}; - -struct x t[] = { - { "^[^!@]+$", "/bin/upas/aliasmail '&'", 0 }, - { "^local!(.*)$", "/mail/box/\\1/mbox", 0 }, - { "^plan9!(.*)$", "\\1", 0 }, - { "^helix!(.*)$", "\\1", 0 }, - { "^([^!]+)@([^!@]+)$", "\\2!\\1", 0 }, - { "^(uk\\.[^!]*)(!.*)$", "/bin/upas/uk2uk '\\1' '\\2'", 0 }, - { "^[^!]*\\.[^!]*!.*$", "inet!&", 0 }, - { "^\xE2\x98\xBA$", "smiley", 0 }, - { "^(coma|research|pipe|pyxis|inet|hunny|gauss)!(.*)$", "/mail/lib/qmail '\\s' 'net!\\1' '\\2'", 0 }, - { "^.*$", "/mail/lib/qmail '\\s' 'net!research' '&'", 0 }, - { 0, 0, 0 }, -}; - -main(int ac, char **av) -{ - Resub rs[10]; - char dst[128]; - int n; - struct x *tp; - - for(tp = t; tp->re; tp++) - tp->p = regcomp(tp->re); - - - for(tp = t; tp->re; tp++){ - print("%s VIA %s", av[1], tp->re); - memset(rs, 0, sizeof rs); - if(regexec(tp->p, av[1], rs, 10)){ - regsub(tp->s, dst, sizeof dst, rs, 10); - print(" sub %s -> %s", tp->s, dst); - } - print("\n"); - } - exit(0); -} diff --git a/libregexp/test2.c b/libregexp/test2.c @@ -1,20 +0,0 @@ -#include "plan9.h" -#include <regexp9.h> - - -main(int ac, char **av) -{ - Resub rs[10]; - Reprog *p; - char *s; - int i; - - p = regcomp("[^a-z]"); - s = "\n"; - if(regexec(p, s, rs, 10)) - print("%s %lux %lux %lux\n", s, s, rs[0].sp, rs[0].ep); - s = "0"; - if(regexec(p, s, rs, 10)) - print("%s %lux %lux %lux\n", s, s, rs[0].sp, rs[0].ep); - exit(0); -} diff --git a/libstuff/Makefile b/libstuff/Makefile @@ -1,172 +0,0 @@ -ROOT= .. -include ${ROOT}/mk/hdr.mk - -TARG=libstuff - -PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama - -OBJ=\ - buffer \ - clientutil \ - event/buttonpress \ - event/buttonrelease \ - event/clientmessage \ - event/configurenotify \ - event/configurerequest \ - event/destroynotify \ - event/enternotify \ - event/event \ - event/expose \ - event/focusin \ - event/focusout \ - event/keypress \ - event/leavenotify \ - event/mapnotify \ - event/maprequest \ - event/mappingnotify \ - event/motionnotify \ - event/propertynotify \ - event/unmapnotify \ - event/xtime \ - geom/get_sticky \ - geom/quadrant \ - geom/rect_contains_p \ - geom/rect_haspoint_p \ - geom/rect_intersect_p \ - geom/rect_intersection \ - init_screens \ - map \ - printevent \ - util/_die \ - util/backtrace \ - util/closeexec \ - util/comm \ - util/doublefork \ - util/emalloc \ - util/emallocz \ - util/erealloc \ - util/estrdup \ - util/estrndup \ - util/fatal \ - util/freelater \ - util/getbase \ - util/getint \ - util/getlong \ - util/getulong \ - util/grep \ - util/join \ - util/max \ - util/mfatal \ - util/min \ - util/pathsearch \ - util/refree \ - util/reinit \ - util/spawn3 \ - util/spawn3l \ - util/stokenize \ - util/strcasestr \ - util/strend \ - util/strlcat \ - util/strlcatprint \ - util/sxprint \ - util/tokenize \ - util/uniq \ - util/unquote \ - util/utflcpy \ - util/vector \ - util/vsxprint \ - x11/convpts \ - x11/errors \ - x11/ignored_xerrors \ - x11/freestringlist \ - x11/initdisplay \ - x11/sendevent \ - x11/sendmessage \ - x11/setgccol \ - x11/sync \ - x11/x11 \ - x11/xatom \ - x11/xft \ - x11/colors/loadcolor \ - x11/colors/namedcolor \ - x11/colors/xftcolor \ - x11/drawing/border \ - x11/drawing/drawline \ - x11/drawing/drawpoly \ - x11/drawing/drawstring \ - x11/drawing/fill \ - x11/drawing/fillpoly \ - x11/focus/getfocus \ - x11/focus/setfocus \ - x11/geometry/XRect \ - x11/geometry/addpt \ - x11/geometry/divpt \ - x11/geometry/eqpt \ - x11/geometry/eqrect \ - x11/geometry/insetrect \ - x11/geometry/mulpt \ - x11/geometry/rectaddpt \ - x11/geometry/rectsetorigin \ - x11/geometry/rectsubpt \ - x11/geometry/subpt \ - x11/images/allocimage \ - x11/images/copyimage \ - x11/images/freeimage \ - x11/images/xftdrawable \ - x11/insanity/gravitate \ - x11/insanity/sethints \ - x11/insanity/sizehint \ - x11/keyboard/grabkeyboard \ - x11/keyboard/ungrabkeyboard \ - x11/keys/keycode \ - x11/keys/parsekey \ - x11/mouse/grabpointer \ - x11/mouse/pointerscreen \ - x11/mouse/querypointer \ - x11/mouse/translate \ - x11/mouse/ungrabpointer \ - x11/mouse/warppointer \ - x11/properties/changeprop_char \ - x11/properties/changeprop_long \ - x11/properties/changeprop_short \ - x11/properties/changeprop_string \ - x11/properties/changeprop_textlist \ - x11/properties/changeprop_ulong \ - x11/properties/changeproperty \ - x11/properties/delproperty \ - x11/properties/getprop \ - x11/properties/getprop_long \ - x11/properties/getprop_string \ - x11/properties/getprop_textlist \ - x11/properties/getprop_ulong \ - x11/properties/getproperty \ - x11/properties/strlistdup \ - x11/shape/setshapemask \ - x11/text/freefont \ - x11/text/labelh \ - x11/text/loadfont \ - x11/text/textextents_l \ - x11/text/textwidth \ - x11/text/textwidth_l \ - x11/windows/configwin \ - x11/windows/createwindow \ - x11/windows/createwindow_visual \ - x11/windows/destroywindow \ - x11/windows/findwin \ - x11/windows/getwinrect \ - x11/windows/lowerwin \ - x11/windows/mapwin \ - x11/windows/movewin \ - x11/windows/raisewin \ - x11/windows/reparentwindow \ - x11/windows/reshapewin \ - x11/windows/selectinput \ - x11/windows/setborder \ - x11/windows/sethandler \ - x11/windows/setwinattr \ - x11/windows/unmapwin \ - x11/windows/window \ - xext - -include ${ROOT}/mk/lib.mk - diff --git a/libstuff/buffer.c b/libstuff/buffer.c @@ -1,8 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ - -char buffer[8092]; -char* _buffer; -char* const _buf_end = buffer + sizeof buffer; - diff --git a/libstuff/clientutil.c b/libstuff/clientutil.c @@ -1,50 +0,0 @@ -#define IXP_NO_P9_ -#define IXP_P9_STRUCTS -#define CLIENTEXTERN -#include <string.h> -#include <ixp.h> -#include <stuff/clientutil.h> -#include <stuff/util.h> - -static IxpCFid* ctlfid; -static char ctl[1024]; -static char* ectl; - -char* -readctl(char *key) { - char *s, *p; - int nkey, n; - - if(ctlfid == nil) { - ctlfid = ixp_open(client, "ctl", OREAD); - n = ixp_read(ctlfid, ctl, 1023); - ectl = ctl + n; - ixp_close(ctlfid); - } - - nkey = strlen(key); - p = ctl - 1; - do { - p++; - if(!strncmp(p, key, nkey)) { - p += nkey; - s = strchr(p, '\n'); - n = (s ? s : ectl) - p; - s = freelater(emalloc(n + 1)); - s[n] = '\0'; - return strncpy(s, p, n); - } - } while((p = strchr(p, '\n'))); - return ""; -} - -void -client_init(char* address) { - if(address && *address) - client = ixp_mount(address); - else - client = ixp_nsmount("wmii"); - if(client == nil) - fatal("can't mount: %r\n"); -} - diff --git a/libstuff/event/buttonpress.c b/libstuff/event/buttonpress.c @@ -1,14 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_buttonpress(XButtonPressedEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, bdown, ev); - else - XAllowEvents(display, ReplayPointer, ev->time); -} diff --git a/libstuff/event/buttonrelease.c b/libstuff/event/buttonrelease.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_buttonrelease(XButtonPressedEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, bup, ev); -} diff --git a/libstuff/event/clientmessage.c b/libstuff/event/clientmessage.c @@ -1,10 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_clientmessage(XClientMessageEvent *ev) { - - USED(ev); -} diff --git a/libstuff/event/configurenotify.c b/libstuff/event/configurenotify.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_configurenotify(XConfigureEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, config, ev); -} diff --git a/libstuff/event/configurerequest.c b/libstuff/event/configurerequest.c @@ -1,24 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_configurerequest(XConfigureRequestEvent *ev) { - XWindowChanges wc; - Window *w; - - if((w = findwin(ev->window))) - handle(w, configreq, ev); - else{ - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(display, ev->window, ev->value_mask, &wc); - } -} - diff --git a/libstuff/event/destroynotify.c b/libstuff/event/destroynotify.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_destroynotify(XDestroyWindowEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, destroy, ev); -} diff --git a/libstuff/event/enternotify.c b/libstuff/event/enternotify.c @@ -1,16 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_enternotify(XCrossingEvent *ev) { - Window *w; - - event_xtime = ev->time; - if(ev->mode != NotifyNormal) - return; - - if((w = findwin(ev->window))) - handle(w, enter, ev); -} diff --git a/libstuff/event/event.c b/libstuff/event/event.c @@ -1,107 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void (*event_debug)(XEvent*); -long event_xtime; -bool event_looprunning; - -EventHandler event_handler[LASTEvent] = { - [ButtonPress] = (EventHandler)event_buttonpress, - [ButtonRelease] = (EventHandler)event_buttonrelease, - [ClientMessage] = (EventHandler)event_clientmessage, - [ConfigureNotify] = (EventHandler)event_configurenotify, - [ConfigureRequest] = (EventHandler)event_configurerequest, - [DestroyNotify] = (EventHandler)event_destroynotify, - [EnterNotify] = (EventHandler)event_enternotify, - [Expose] = (EventHandler)event_expose, - [FocusIn] = (EventHandler)event_focusin, - [FocusOut] = (EventHandler)event_focusout, - [KeyPress] = (EventHandler)event_keypress, - [LeaveNotify] = (EventHandler)event_leavenotify, - [MapNotify] = (EventHandler)event_mapnotify, - [MapRequest] = (EventHandler)event_maprequest, - [MappingNotify] = (EventHandler)event_mappingnotify, - [MotionNotify] = (EventHandler)event_motionnotify, - [PropertyNotify] = (EventHandler)event_propertynotify, - [UnmapNotify] = (EventHandler)event_unmapnotify, -}; - -void -event_dispatch(XEvent *e) { - if(event_debug) - event_debug(e); - - if(e->type < nelem(event_handler)) { - if(event_handler[e->type]) - event_handler[e->type](e); - }else - xext_event(e); -} - -void -event_check(void) { - XEvent ev; - - while(XPending(display)) { - XNextEvent(display, &ev); - event_dispatch(&ev); - } -} - -void -event_loop(void) { - XEvent ev; - - while(event_looprunning) { - XNextEvent(display, &ev); - event_dispatch(&ev); - } -} - -uint -event_flush(long event_mask, bool dispatch) { - XEvent ev; - uint n = 0; - - while(XCheckMaskEvent(display, event_mask, &ev)) { - if(dispatch) - event_dispatch(&ev); - n++; - } - return n; -} - -static int -findenter(Display *d, XEvent *e, XPointer v) { - long *l; - - USED(d); - l = (long*)v; - if(*l) - return false; - if(e->type == EnterNotify) - return true; - if(e->type == MotionNotify) - (*l)++; - return false; -} - -/* This isn't perfect. If there were motion events in the queue - * before this was called, then it flushes nothing. If we don't - * check for them, we might lose a legitamate enter event. - */ -uint -event_flushenter(void) { - XEvent e; - long l; - int n; - - l = 0; - n = 0; - while(XCheckIfEvent(display, &e, findenter, (void*)&l)) - n++; - return n; -} - diff --git a/libstuff/event/event.h b/libstuff/event/event.h @@ -1,9 +0,0 @@ -#include <stuff/x.h> - -typedef void (*EventHandler)(XEvent*); - -#define handle(w, fn, ev) \ - BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev)) - -extern EventHandler event_handler[LASTEvent]; - diff --git a/libstuff/event/expose.c b/libstuff/event/expose.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_expose(XExposeEvent *ev) { - Window *w; - - if(ev->count == 0 && (w = findwin(ev->window))) - handle(w, expose, ev); -} diff --git a/libstuff/event/focusin.c b/libstuff/event/focusin.c @@ -1,27 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_focusin(XFocusChangeEvent *ev) { - Window *w; - - /* Yes, we're focusing in on nothing, here. */ - if(ev->detail == NotifyDetailNone) { - /* FIXME: Do something. */ - return; - } - - if(!((ev->detail == NotifyNonlinear) - ||(ev->detail == NotifyNonlinearVirtual) - ||(ev->detail == NotifyVirtual) - ||(ev->detail == NotifyInferior) - ||(ev->detail == NotifyAncestor))) - return; - if((ev->mode == NotifyWhileGrabbed)) - return; - - if((w = findwin(ev->window))) - handle(w, focusin, ev); -} diff --git a/libstuff/event/focusout.c b/libstuff/event/focusout.c @@ -1,19 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_focusout(XFocusChangeEvent *ev) { - Window *w; - - if(!((ev->detail == NotifyNonlinear) - ||(ev->detail == NotifyNonlinearVirtual) - ||(ev->detail == NotifyVirtual) - ||(ev->detail == NotifyInferior) - ||(ev->detail == NotifyAncestor))) - return; - - if((w = findwin(ev->window))) - handle(w, focusout, ev); -} diff --git a/libstuff/event/keypress.c b/libstuff/event/keypress.c @@ -1,13 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_keypress(XKeyEvent *ev) { - Window *w; - - event_xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, kdown, ev); -} diff --git a/libstuff/event/leavenotify.c b/libstuff/event/leavenotify.c @@ -1,13 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_leavenotify(XCrossingEvent *ev) { - Window *w; - - event_xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, leave, ev); -} diff --git a/libstuff/event/mapnotify.c b/libstuff/event/mapnotify.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_mapnotify(XMapEvent *ev) { - Window *w; - - if((w = findwin(ev->window))) - handle(w, map, ev); -} diff --git a/libstuff/event/mappingnotify.c b/libstuff/event/mappingnotify.c @@ -1,11 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_mappingnotify(XMappingEvent *ev) { - - /* Why do you need me to tell you this? */ - XRefreshKeyboardMapping(ev); -} diff --git a/libstuff/event/maprequest.c b/libstuff/event/maprequest.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_maprequest(XMapRequestEvent *ev) { - Window *w; - - if((w = findwin(ev->parent))) - handle(w, mapreq, ev); -} diff --git a/libstuff/event/motionnotify.c b/libstuff/event/motionnotify.c @@ -1,13 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_motionnotify(XMotionEvent *ev) { - Window *w; - - event_xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, motion, ev); -} diff --git a/libstuff/event/propertynotify.c b/libstuff/event/propertynotify.c @@ -1,13 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_propertynotify(XPropertyEvent *ev) { - Window *w; - - event_xtime = ev->time; - if((w = findwin(ev->window))) - handle(w, property, ev); -} diff --git a/libstuff/event/unmapnotify.c b/libstuff/event/unmapnotify.c @@ -1,15 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "event.h" - -void -event_unmapnotify(XUnmapEvent *ev) { - Window *w; - - if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) { - w->mapped = false; - if(w->parent && (ev->send_event || w->unmapped-- == 0)) - handle(w, unmap, ev); - } -} diff --git a/libstuff/event/xtime.c b/libstuff/event/xtime.c @@ -1,33 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/x.h> - -static int -findtime(Display *d, XEvent *e, XPointer v) { - Window *w; - - w = (Window*)v; - if(e->type == PropertyNotify && e->xproperty.window == w->xid) { - event_xtime = e->xproperty.time; - return true; - } - return false; -} - -void -event_updatextime(void) { - Window *w; - WinAttr wa; - XEvent e; - long l; - - w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0); - - XSelectInput(display, w->xid, PropertyChangeMask); - changeprop_long(w, "ATOM", "ATOM", &l, 0); - XIfEvent(display, &e, findtime, (void*)w); - - destroywindow(w); -} - diff --git a/libstuff/geom/get_sticky.c b/libstuff/geom/get_sticky.c @@ -1,24 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/geom.h> - -Align -get_sticky(Rectangle src, Rectangle dst) { - Align corner; - - corner = 0; - if(src.min.x != dst.min.x - && src.max.x == dst.max.x) - corner |= East; - else - corner |= West; - - if(src.min.y != dst.min.y - && src.max.y == dst.max.y) - corner |= South; - else - corner |= North; - - return corner; -} diff --git a/libstuff/geom/quadrant.c b/libstuff/geom/quadrant.c @@ -1,23 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/geom.h> - -Align -quadrant(Rectangle r, Point pt) { - Align ret; - - pt = subpt(pt, r.min); - ret = 0; - - if(pt.x >= Dx(r) * .5) - ret |= East; - if(pt.x <= Dx(r) * .5) - ret |= West; - if(pt.y <= Dy(r) * .5) - ret |= North; - if(pt.y >= Dy(r) * .5) - ret |= South; - - return ret; -} diff --git a/libstuff/geom/rect_contains_p.c b/libstuff/geom/rect_contains_p.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/geom.h> - -bool -rect_contains_p(Rectangle r, Rectangle r2) { - return r2.min.x >= r.min.x - && r2.max.x <= r.max.x - && r2.min.y >= r.min.y - && r2.max.y <= r.max.y; -} diff --git a/libstuff/geom/rect_haspoint_p.c b/libstuff/geom/rect_haspoint_p.c @@ -1,10 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/geom.h> - -bool -rect_haspoint_p(Point pt, Rectangle r) { - return (pt.x >= r.min.x) && (pt.x < r.max.x) - && (pt.y >= r.min.y) && (pt.y < r.max.y); -} diff --git a/libstuff/geom/rect_intersect_p.c b/libstuff/geom/rect_intersect_p.c @@ -1,12 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/geom.h> - -bool -rect_intersect_p(Rectangle r, Rectangle r2) { - return r.min.x <= r2.max.x - && r.max.x >= r2.min.x - && r.min.y <= r2.max.y - && r.max.y >= r2.min.y; -} diff --git a/libstuff/geom/rect_intersection.c b/libstuff/geom/rect_intersection.c @@ -1,17 +0,0 @@ -/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/geom.h> -#include <stuff/util.h> - -Rectangle -rect_intersection(Rectangle r, Rectangle r2) { - Rectangle ret; - - /* ret != canonrect(ret) ≡ no intersection. */ - ret.min.x = max(r.min.x, r2.min.x); - ret.max.x = min(r.max.x, r2.max.x); - ret.min.y = max(r.min.y, r2.min.y); - ret.max.y = min(r.max.y, r2.max.y); - return ret; -} diff --git a/libstuff/init_screens.c b/libstuff/init_screens.c @@ -1,9 +0,0 @@ -/* Copyright ©2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ - -void init_screens(void); -void -init_screens(void) { -} - diff --git a/libstuff/map.c b/libstuff/map.c @@ -1,126 +0,0 @@ -/* Written by Kris Maglione */ -/* Public domain */ -#include <string.h> -#include <stuff/util.h> - -/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */ - -struct MapEnt { - ulong hash; - const char* key; - void* val; - MapEnt* next; -}; - -MapEnt *NM; - -/* By Dan Bernstein. Public domain. */ -static ulong -hash(const char *str) { - ulong h; - - h = 5381; - while (*str != '\0') { - h += h << 5; /* h *= 33 */ - h ^= *str++; - } - return h; -} - -static void -insert(MapEnt **e, ulong val, const char *key) { - MapEnt *te; - - te = emallocz(sizeof *te); - te->hash = val; - te->key = key; - te->next = *e; - *e = te; -} - -static MapEnt** -map_getp(Map *map, ulong val, int create) { - MapEnt **e; - - e = &map->bucket[val%map->nhash]; - for(; *e; e = &(*e)->next) - if((*e)->hash >= val) break; - if(*e == nil || (*e)->hash != val) { - if(create) - insert(e, val, nil); - else - e = &NM; - } - return e; -} - -static MapEnt** -hash_getp(Map *map, const char *str, int create) { - MapEnt **e; - ulong h; - int cmp; - - h = hash(str); - e = map_getp(map, h, create); - if(*e && (*e)->key == nil) - (*e)->key = str; - else { - SET(cmp); - for(; *e; e = &(*e)->next) - if((*e)->hash > h || (cmp = strcmp((*e)->key, str)) >= 0) - break; - if(*e == nil || (*e)->hash > h || cmp > 0) - if(create) - insert(e, h, str); - } - return e; -} - -void** -map_get(Map *map, ulong val, bool create) { - MapEnt *e; - - e = *map_getp(map, val, create); - return e ? &e->val : nil; -} - -void** -hash_get(Map *map, const char *str, bool create) { - MapEnt *e; - - e = *hash_getp(map, str, create); - return e ? &e->val : nil; -} - -void* -map_rm(Map *map, ulong val) { - MapEnt **e, *te; - void *ret; - - ret = nil; - e = map_getp(map, val, 0); - if(*e) { - te = *e; - ret = te->val; - *e = te->next; - free(te); - } - return ret; -} - -void* -hash_rm(Map *map, const char *str) { - MapEnt **e, *te; - void *ret; - - ret = nil; - e = hash_getp(map, str, 0); - if(*e) { - te = *e; - ret = te->val; - *e = te->next; - free(te); - } - return ret; -} - diff --git a/libstuff/printevent.c b/libstuff/printevent.c @@ -1,994 +0,0 @@ -/* - * Original code posted to comp.sources.x - * Modifications by Russ Cox <rsc@swtch.com>. - * Further modifications by Kris Maglione <maglione.k at Gmail> - */ - -/* - * Path: uunet!wyse!mikew From: mikew@wyse.wyse.com (Mike Wexler) Newsgroups: - * comp.sources.x Subject: v02i056: subroutine to print events in human - * readable form, Part01/01 Message-ID: <1935@wyse.wyse.com> Date: 22 Dec 88 - * 19:28:25 GMT Organization: Wyse Technology, San Jose Lines: 1093 Approved: - * mikew@wyse.com - * - * Submitted-by: richsun!darkstar!ken Posting-number: Volume 2, Issue 56 - * Archive-name: showevent/part01 - * - * - * There are times during debugging when it would be real useful to be able to - * print the fields of an event in a human readable form. Too many times I - * found myself scrounging around in section 8 of the Xlib manual looking for - * the valid fields for the events I wanted to see, then adding printf's to - * display the numeric values of the fields, and then scanning through X.h - * trying to decode the cryptic detail and state fields. After playing with - * xev, I decided to write a couple of standard functions that I could keep - * in a library and call on whenever I needed a little debugging verbosity. - * The first function, GetType(), is useful for returning the string - * representation of the type of an event. The second function, ShowEvent(), - * is used to display all the fields of an event in a readable format. The - * functions are not complicated, in fact, they are mind-numbingly boring - - * but that's just the point nobody wants to spend the time writing functions - * like this, they just want to have them when they need them. - * - * A simple, sample program is included which does little else but to - * demonstrate the use of these two functions. These functions have saved me - * many an hour during debugging and I hope you find some benefit to these. - * If you have any comments, suggestions, improvements, or if you find any - * blithering errors you can get it touch with me at the following location: - * - * ken@richsun.UUCP - */ - -#include <stdarg.h> -#include <bio.h> -#include <stuff/x.h> -#include <stuff/util.h> -#include "printevent.h" -#define Window XWindow - -#define nil ((void*)0) - -typedef struct Pair Pair; - -struct Pair { - int key; - char *val; -}; - -static char* sep = " "; - -static char * -search(Pair *lst, int key, char *(*def)(int)) { - for(; lst->val; lst++) - if(lst->key == key) - return lst->val; - return def(key); -} - -static char* -unmask(Pair *list, uint val) -{ - Pair *p; - char *s, *end; - int n; - - buffer[0] = '\0'; - end = buffer + sizeof buffer; - s = buffer; - - n = 0; - s = utfecpy(s, end, "("); - for (p = list; p->val; p++) - if (val & p->key) { - if(n++) - s = utfecpy(s, end, "|"); - s = utfecpy(s, end, p->val); - } - utfecpy(s, end, ")"); - - return buffer; -} - -static char * -strhex(int key) { - sprint(buffer, "0x%x", key); - return buffer; -} - -static char * -strdec(int key) { - sprint(buffer, "%d", key); - return buffer; -} - -static char * -strign(int key) { - USED(key); - - return "?"; -} - -/******************************************************************************/ -/**** Miscellaneous routines to convert values to their string equivalents ****/ -/******************************************************************************/ - -static void -TInt(Fmt *b, va_list *ap) { - fmtprint(b, "%d", va_arg(*ap, int)); -} - -static void -TWindow(Fmt *b, va_list *ap) { - Window w; - - w = va_arg(*ap, Window); - fmtprint(b, "0x%ux", (uint)w); -} - -static void -TData(Fmt *b, va_list *ap) { - long *l; - int i; - - l = va_arg(*ap, long*); - fmtprint(b, "{"); - for (i = 0; i < 5; i++) { - if(i > 0) - fmtprint(b, ", "); - fmtprint(b, "0x%08lx", l[i]); - } - fmtprint(b, "}"); -} - -/* Returns the string equivalent of a timestamp */ -static void -TTime(Fmt *b, va_list *ap) { - ldiv_t d; - ulong msec; - ulong sec; - ulong min; - ulong hr; - ulong day; - Time time; - - time = va_arg(*ap, Time); - - msec = time/1000; - d = ldiv(msec, 60); - msec = time-msec*1000; - - sec = d.rem; - d = ldiv(d.quot, 60); - min = d.rem; - d = ldiv(d.quot, 24); - hr = d.rem; - day = d.quot; - -#ifdef notdef - sprintf(buffer, "%lu day%s %02lu:%02lu:%02lu.%03lu", - day, day == 1 ? "" : "(s)", hr, min, sec, msec); -#endif - - fmtprint(b, "%ludd_%ludh_%ludm_%lud.%03luds", day, hr, min, sec, msec); -} - -/* Returns the string equivalent of a boolean parameter */ -static void -TBool(Fmt *b, va_list *ap) { - static Pair list[] = { - {True, "True"}, - {False, "False"}, - {0, nil}, - }; - Bool key; - - key = va_arg(*ap, Bool); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a property notify state */ -static void -TPropState(Fmt *b, va_list *ap) { - static Pair list[] = { - {PropertyNewValue, "PropertyNewValue"}, - {PropertyDelete, "PropertyDelete"}, - {0, nil}, - }; - uint key; - - key = va_arg(*ap, uint); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a visibility notify state */ -static void -TVis(Fmt *b, va_list *ap) { - static Pair list[] = { - {VisibilityUnobscured, "VisibilityUnobscured"}, - {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"}, - {VisibilityFullyObscured, "VisibilityFullyObscured"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a mask of buttons and/or modifier keys */ -static void -TModState(Fmt *b, va_list *ap) { - static Pair list[] = { - {Button1Mask, "Button1Mask"}, - {Button2Mask, "Button2Mask"}, - {Button3Mask, "Button3Mask"}, - {Button4Mask, "Button4Mask"}, - {Button5Mask, "Button5Mask"}, - {ShiftMask, "ShiftMask"}, - {LockMask, "LockMask"}, - {ControlMask, "ControlMask"}, - {Mod1Mask, "Mod1Mask"}, - {Mod2Mask, "Mod2Mask"}, - {Mod3Mask, "Mod3Mask"}, - {Mod4Mask, "Mod4Mask"}, - {Mod5Mask, "Mod5Mask"}, - {0, nil}, - }; - uint state; - - state = va_arg(*ap, uint); - fmtprint(b, "%s", unmask(list, state)); -} - -/* Returns the string equivalent of a mask of configure window values */ -static void -TConfMask(Fmt *b, va_list *ap) { - static Pair list[] = { - {CWX, "CWX"}, - {CWY, "CWY"}, - {CWWidth, "CWWidth"}, - {CWHeight, "CWHeight"}, - {CWBorderWidth, "CWBorderWidth"}, - {CWSibling, "CWSibling"}, - {CWStackMode, "CWStackMode"}, - {0, nil}, - }; - uint valuemask; - - valuemask = va_arg(*ap, uint); - fmtprint(b, "%s", unmask(list, valuemask)); -} - -/* Returns the string equivalent of a motion hint */ -#if 0 -static void -IsHint(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyNormal, "NotifyNormal"}, - {NotifyHint, "NotifyHint"}, - {0, nil}, - }; - char key; - - key = va_arg(*ap, char); - fmtprint(b, "%s", search(list, key, strign)); -} -#endif - -/* Returns the string equivalent of an id or the value "None" */ -static void -TIntNone(Fmt *b, va_list *ap) { - static Pair list[] = { - {None, "None"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strhex)); -} - -/* Returns the string equivalent of a colormap state */ -static void -TColMap(Fmt *b, va_list *ap) { - static Pair list[] = { - {ColormapInstalled, "ColormapInstalled"}, - {ColormapUninstalled, "ColormapUninstalled"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a crossing detail */ -static void -TXing(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyAncestor, "NotifyAncestor"}, - {NotifyInferior, "NotifyInferior"}, - {NotifyVirtual, "NotifyVirtual"}, - {NotifyNonlinear, "NotifyNonlinear"}, - {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a focus change detail */ -static void -TFocus(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyAncestor, "NotifyAncestor"}, - {NotifyInferior, "NotifyInferior"}, - {NotifyVirtual, "NotifyVirtual"}, - {NotifyNonlinear, "NotifyNonlinear"}, - {NotifyNonlinearVirtual, "NotifyNonlinearVirtual"}, - {NotifyPointer, "NotifyPointer"}, - {NotifyPointerRoot, "NotifyPointerRoot"}, - {NotifyDetailNone, "NotifyDetailNone"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a configure detail */ -static void -TConfDetail(Fmt *b, va_list *ap) { - static Pair list[] = { - {Above, "Above"}, - {Below, "Below"}, - {TopIf, "TopIf"}, - {BottomIf, "BottomIf"}, - {Opposite, "Opposite"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a grab mode */ -static void -TGrabMode(Fmt *b, va_list *ap) { - static Pair list[] = { - {NotifyNormal, "NotifyNormal"}, - {NotifyGrab, "NotifyGrab"}, - {NotifyUngrab, "NotifyUngrab"}, - {NotifyWhileGrabbed, "NotifyWhileGrabbed"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a mapping request */ -static void -TMapping(Fmt *b, va_list *ap) { - static Pair list[] = { - {MappingModifier, "MappingModifier"}, - {MappingKeyboard, "MappingKeyboard"}, - {MappingPointer, "MappingPointer"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a stacking order place */ -static void -TPlace(Fmt *b, va_list *ap) { - static Pair list[] = { - {PlaceOnTop, "PlaceOnTop"}, - {PlaceOnBottom, "PlaceOnBottom"}, - {0, nil}, - }; - int key; - - key = va_arg(*ap, int); - fmtprint(b, "%s", search(list, key, strign)); -} - -/* Returns the string equivalent of a major code */ -static void -TMajor(Fmt *b, va_list *ap) { - static char *list[] = { XMajors }; - char *s; - uint key; - - key = va_arg(*ap, uint); - s = "<nil>"; - if(key < nelem(list)) - s = list[key]; - fmtprint(b, "%s", s); -} - -static char* -eventtype(int key) { - static Pair list[] = { - {ButtonPress, "ButtonPress"}, - {ButtonRelease, "ButtonRelease"}, - {CirculateNotify, "CirculateNotify"}, - {CirculateRequest, "CirculateRequest"}, - {ClientMessage, "ClientMessage"}, - {ColormapNotify, "ColormapNotify"}, - {ConfigureNotify, "ConfigureNotify"}, - {ConfigureRequest, "ConfigureRequest"}, - {CreateNotify, "CreateNotify"}, - {DestroyNotify, "DestroyNotify"}, - {EnterNotify, "EnterNotify"}, - {Expose, "Expose"}, - {FocusIn, "FocusIn"}, - {FocusOut, "FocusOut"}, - {GraphicsExpose, "GraphicsExpose"}, - {GravityNotify, "GravityNotify"}, - {KeyPress, "KeyPress"}, - {KeyRelease, "KeyRelease"}, - {KeymapNotify, "KeymapNotify"}, - {LeaveNotify, "LeaveNotify"}, - {MapNotify, "MapNotify"}, - {MapRequest, "MapRequest"}, - {MappingNotify, "MappingNotify"}, - {MotionNotify, "MotionNotify"}, - {NoExpose, "NoExpose"}, - {PropertyNotify, "PropertyNotify"}, - {ReparentNotify, "ReparentNotify"}, - {ResizeRequest, "ResizeRequest"}, - {SelectionClear, "SelectionClear"}, - {SelectionNotify, "SelectionNotify"}, - {SelectionRequest, "SelectionRequest"}, - {UnmapNotify, "UnmapNotify"}, - {VisibilityNotify, "VisibilityNotify"}, - {0, nil}, - }; - return search(list, key, strdec); -} -/* Returns the string equivalent the keycode contained in the key event */ -static void -TKeycode(Fmt *b, va_list *ap) { - KeySym keysym_str; - XKeyEvent *ev; - char *keysym_name; - - ev = va_arg(*ap, XKeyEvent*); - - XLookupString(ev, buffer, sizeof buffer, &keysym_str, nil); - - if (keysym_str == NoSymbol) - keysym_name = "NoSymbol"; - else - keysym_name = XKeysymToString(keysym_str); - if(keysym_name == nil) - keysym_name = "(no name)"; - - fmtprint(b, "%ud (keysym 0x%x \"%s\")", (int)ev->keycode, - (int)keysym_str, keysym_name); -} - -/* Returns the string equivalent of an atom or "None" */ -static void -TAtom(Fmt *b, va_list *ap) { - char *atom_name; - Atom atom; - - atom = va_arg(*ap, Atom); - atom_name = XGetAtomName(display, atom); - fmtprint(b, "%s", atom_name); - XFree(atom_name); -} - -#define _(m) #m, ev->m -#define TEnd nil -typedef void (*Tfn)(Fmt*, va_list*); - -static int -pevent(Fmt *fmt, void *e, ...) { - va_list ap; - Tfn fn; - XAnyEvent *ev; - char *key; - int n; - - ev = e; - fmtprint(fmt, "%3ld %-20s ", ev->serial, eventtype(ev->type)); - if(ev->send_event) - fmtstrcpy(fmt, "(sendevent) "); - - n = 0; - va_start(ap, e); - for(;;) { - fn = va_arg(ap, Tfn); - if(fn == TEnd) - break; - - if(n++ != 0) - fmtprint(fmt, "%s", sep); - - key = va_arg(ap, char*); - fmtprint(fmt, "%s=", key); - fn(fmt, &ap); - } - va_end(ap); - return 0; -} - -/*****************************************************************************/ -/*** Routines to print out readable values for the field of various events ***/ -/*****************************************************************************/ - -static int -VerbMotion(Fmt *fmt, XEvent *e) { - XMotionEvent *ev = &e->xmotion; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TModState, _(state), - TBool, _(same_screen), - TEnd - ); - //fprintf(stderr, "is_hint=%s%s", IsHint(ev->is_hint), sep); -} - -static int -VerbButton(Fmt *fmt, XEvent *e) { - XButtonEvent *ev = &e->xbutton; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TModState, _(state), - TModState, _(button), - TBool, _(same_screen), - TEnd - ); -} - -static int -VerbColormap(Fmt *fmt, XEvent *e) { - XColormapEvent *ev = &e->xcolormap; - - return pevent(fmt, ev, - TWindow, _(window), - TIntNone, _(colormap), - TBool, _(new), - TColMap, _(state), - TEnd - ); -} - -static int -VerbCrossing(Fmt *fmt, XEvent *e) { - XCrossingEvent *ev = &e->xcrossing; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TGrabMode, _(mode), - TXing, _(detail), - TBool, _(same_screen), - TBool, _(focus), - TModState, _(state), - TEnd - ); -} - -static int -VerbExpose(Fmt *fmt, XEvent *e) { - XExposeEvent *ev = &e->xexpose; - - return pevent(fmt, ev, - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(count), - TEnd - ); -} - -static int -VerbGraphicsExpose(Fmt *fmt, XEvent *e) { - XGraphicsExposeEvent *ev = &e->xgraphicsexpose; - - return pevent(fmt, ev, - TWindow, _(drawable), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TMajor, _(major_code), - TInt, _(minor_code), - TEnd - ); -} - -static int -VerbNoExpose(Fmt *fmt, XEvent *e) { - XNoExposeEvent *ev = &e->xnoexpose; - - return pevent(fmt, ev, - TWindow, _(drawable), - TMajor, _(major_code), - TInt, _(minor_code), - TEnd - ); -} - -static int -VerbFocus(Fmt *fmt, XEvent *e) { - XFocusChangeEvent *ev = &e->xfocus; - - return pevent(fmt, ev, - TWindow, _(window), - TGrabMode, _(mode), - TFocus, _(detail), - TEnd - ); -} - -static int -VerbKeymap(Fmt *fmt, XEvent *e) { - XKeymapEvent *ev = &e->xkeymap; - int i; - - fmtprint(fmt, "window=0x%x%s", (int)ev->window, sep); - fmtprint(fmt, "key_vector="); - for (i = 0; i < 32; i++) - fmtprint(fmt, "%02x", ev->key_vector[i]); - fmtprint(fmt, "\n"); - return 0; -} - -static int -VerbKey(Fmt *fmt, XEvent *e) { - XKeyEvent *ev = &e->xkey; - - return pevent(fmt, ev, - TWindow, _(window), - TWindow, _(root), - TWindow, _(subwindow), - TTime, _(time), - TInt, _(x), TInt, _(y), - TInt, _(x_root), TInt, _(y_root), - TModState, _(state), - TKeycode, "keycode", ev, - TBool, _(same_screen), - TEnd - ); -} - -static int -VerbProperty(Fmt *fmt, XEvent *e) { - XPropertyEvent *ev = &e->xproperty; - - return pevent(fmt, ev, - TWindow, _(window), - TAtom, _(atom), - TTime, _(time), - TPropState, _(state), - TEnd - ); -} - -static int -VerbResizeRequest(Fmt *fmt, XEvent *e) { - XResizeRequestEvent *ev = &e->xresizerequest; - - return pevent(fmt, ev, - TWindow, _(window), - TInt, _(width), TInt, _(height), - TEnd - ); -} - -static int -VerbCirculate(Fmt *fmt, XEvent *e) { - XCirculateEvent *ev = &e->xcirculate; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TPlace, _(place), - TEnd - ); -} - -static int -VerbConfigure(Fmt *fmt, XEvent *e) { - XConfigureEvent *ev = &e->xconfigure; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(border_width), - TIntNone, _(above), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbCreateWindow(Fmt *fmt, XEvent *e) { - XCreateWindowEvent *ev = &e->xcreatewindow; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(border_width), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbDestroyWindow(Fmt *fmt, XEvent *e) { - XDestroyWindowEvent *ev = &e->xdestroywindow; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TEnd - ); -} - -static int -VerbGravity(Fmt *fmt, XEvent *e) { - XGravityEvent *ev = &e->xgravity; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TEnd - ); -} - -static int -VerbMap(Fmt *fmt, XEvent *e) { - XMapEvent *ev = &e->xmap; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbReparent(Fmt *fmt, XEvent *e) { - XReparentEvent *ev = &e->xreparent; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TWindow, _(parent), - TInt, _(x), TInt, _(y), - TBool, _(override_redirect), - TEnd - ); -} - -static int -VerbUnmap(Fmt *fmt, XEvent *e) { - XUnmapEvent *ev = &e->xunmap; - - return pevent(fmt, ev, - TWindow, _(event), - TWindow, _(window), - TBool, _(from_configure), - TEnd - ); -} - -static int -VerbCirculateRequest(Fmt *fmt, XEvent *e) { - XCirculateRequestEvent *ev = &e->xcirculaterequest; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TPlace, _(place), - TEnd - ); -} - -static int -VerbConfigureRequest(Fmt *fmt, XEvent *e) { - XConfigureRequestEvent *ev = &e->xconfigurerequest; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TInt, _(x), TInt, _(y), - TInt, _(width), TInt, _(height), - TInt, _(border_width), - TIntNone, _(above), - TConfDetail, _(detail), - TConfMask, _(value_mask), - TEnd - ); -} - -static int -VerbMapRequest(Fmt *fmt, XEvent *e) { - XMapRequestEvent *ev = &e->xmaprequest; - - return pevent(fmt, ev, - TWindow, _(parent), - TWindow, _(window), - TEnd - ); -} - -static int -VerbClient(Fmt *fmt, XEvent *e) { - XClientMessageEvent *ev = &e->xclient; - - return pevent(fmt, ev, - TWindow, _(window), - TAtom, _(message_type), - TInt, _(format), - TData, "data (as longs)", &ev->data, - TEnd - ); -} - -static int -VerbMapping(Fmt *fmt, XEvent *e) { - XMappingEvent *ev = &e->xmapping; - - return pevent(fmt, ev, - TWindow, _(window), - TMapping, _(request), - TWindow, _(first_keycode), - TWindow, _(count), - TEnd - ); -} - -static int -VerbSelectionClear(Fmt *fmt, XEvent *e) { - XSelectionClearEvent *ev = &e->xselectionclear; - - return pevent(fmt, ev, - TWindow, _(window), - TAtom, _(selection), - TTime, _(time), - TEnd - ); -} - -static int -VerbSelection(Fmt *fmt, XEvent *e) { - XSelectionEvent *ev = &e->xselection; - - return pevent(fmt, ev, - TWindow, _(requestor), - TAtom, _(selection), - TAtom, _(target), - TAtom, _(property), - TTime, _(time), - TEnd - ); -} - -static int -VerbSelectionRequest(Fmt *fmt, XEvent *e) { - XSelectionRequestEvent *ev = &e->xselectionrequest; - - return pevent(fmt, ev, - TWindow, _(owner), - TWindow, _(requestor), - TAtom, _(selection), - TAtom, _(target), - TAtom, _(property), - TTime, _(time), - TEnd - ); -} - -static int -VerbVisibility(Fmt *fmt, XEvent *e) { - XVisibilityEvent *ev = &e->xvisibility; - - return pevent(fmt, ev, - TWindow, _(window), - TVis, _(state), - TEnd - ); -} - -/******************************************************************************/ -/**************** Print the values of all fields for any event ****************/ -/******************************************************************************/ - -typedef struct Handler Handler; -struct Handler { - int key; - int (*fn)(Fmt*, XEvent*); -}; - -int -fmtevent(Fmt *fmt) { - XEvent *e; - XAnyEvent *ev; - /* - fprintf(stderr, "type=%s%s", eventtype(e->xany.type), sep); - fprintf(stderr, "serial=%lu%s", ev->serial, sep); - fprintf(stderr, "send_event=%s%s", TorF(ev->send_event), sep); - fprintf(stderr, "display=0x%p%s", ev->display, sep); - */ - static Handler fns[] = { - {MotionNotify, VerbMotion}, - {ButtonPress, VerbButton}, - {ButtonRelease, VerbButton}, - {ColormapNotify, VerbColormap}, - {EnterNotify, VerbCrossing}, - {LeaveNotify, VerbCrossing}, - {Expose, VerbExpose}, - {GraphicsExpose, VerbGraphicsExpose}, - {NoExpose, VerbNoExpose}, - {FocusIn, VerbFocus}, - {FocusOut, VerbFocus}, - {KeymapNotify, VerbKeymap}, - {KeyPress, VerbKey}, - {KeyRelease, VerbKey}, - {PropertyNotify, VerbProperty}, - {ResizeRequest, VerbResizeRequest}, - {CirculateNotify, VerbCirculate}, - {ConfigureNotify, VerbConfigure}, - {CreateNotify, VerbCreateWindow}, - {DestroyNotify, VerbDestroyWindow}, - {GravityNotify, VerbGravity}, - {MapNotify, VerbMap}, - {ReparentNotify, VerbReparent}, - {UnmapNotify, VerbUnmap}, - {CirculateRequest, VerbCirculateRequest}, - {ConfigureRequest, VerbConfigureRequest}, - {MapRequest, VerbMapRequest}, - {ClientMessage, VerbClient}, - {MappingNotify, VerbMapping}, - {SelectionClear, VerbSelectionClear}, - {SelectionNotify, VerbSelection}, - {SelectionRequest, VerbSelectionRequest}, - {VisibilityNotify, VerbVisibility}, - {0, nil}, - }; - Handler *p; - - e = va_arg(fmt->args, XEvent*); - ev = &e->xany; - - for (p = fns; p->fn; p++) - if (p->key == ev->type) - return p->fn(fmt, e); - return 1; -} - diff --git a/libstuff/printevent.h b/libstuff/printevent.h @@ -1,248 +0,0 @@ -int fmtevent(Fmt *fmt); - -enum { - X_CreateWindow = 1, - X_ChangeWindowAttributes, - X_GetWindowAttributes, - X_DestroyWindow, - X_DestroySubwindows, - X_ChangeSaveSet, - X_ReparentWindow, - X_MapWindow, - X_MapSubwindows, - X_UnmapWindow, - X_UnmapSubwindows, - X_ConfigureWindow, - X_CirculateWindow, - X_GetGeometry, - X_QueryTree, - X_InternAtom, - X_GetAtomName, - X_ChangeProperty, - X_DeleteProperty, - X_GetProperty, - X_ListProperties, - X_SetSelectionOwner, - X_GetSelectionOwner, - X_ConvertSelection, - X_SendEvent, - X_GrabPointer, - X_UngrabPointer, - X_GrabButton, - X_UngrabButton, - X_ChangeActivePointerGrab, - X_GrabKeyboard, - X_UngrabKeyboard, - X_GrabKey, - X_UngrabKey, - X_AllowEvents, - X_GrabServer, - X_UngrabServer, - X_QueryPointer, - X_GetMotionEvents, - X_TranslateCoords, - X_WarpPointer, - X_SetInputFocus, - X_GetInputFocus, - X_QueryKeymap, - X_OpenFont, - X_CloseFont, - X_QueryFont, - X_QueryTextExtents, - X_ListFonts, - X_ListFontsWithInfo, - X_SetFontPath, - X_GetFontPath, - X_CreatePixmap, - X_FreePixmap, - X_CreateGC, - X_ChangeGC, - X_CopyGC, - X_SetDashes, - X_SetClipRectangles, - X_FreeGC, - X_ClearArea, - X_CopyArea, - X_CopyPlane, - X_PolyPoint, - X_PolyLine, - X_PolySegment, - X_PolyRectangle, - X_PolyArc, - X_FillPoly, - X_PolyFillRectangle, - X_PolyFillArc, - X_PutImage, - X_GetImage, - X_PolyText8, - X_PolyText16, - X_ImageText8, - X_ImageText16, - X_CreateColormap, - X_FreeColormap, - X_CopyColormapAndFree, - X_InstallColormap, - X_UninstallColormap, - X_ListInstalledColormaps, - X_AllocColor, - X_AllocNamedColor, - X_AllocColorCells, - X_AllocColorPlanes, - X_FreeColors, - X_StoreColors, - X_StoreNamedColor, - X_QueryColors, - X_LookupColor, - X_CreateCursor, - X_CreateGlyphCursor, - X_FreeCursor, - X_RecolorCursor, - X_QueryBestSize, - X_QueryExtension, - X_ListExtensions, - X_ChangeKeyboardMapping, - X_GetKeyboardMapping, - X_ChangeKeyboardControl, - X_GetKeyboardControl, - X_Bell, - X_ChangePointerControl, - X_GetPointerControl, - X_SetScreenSaver, - X_GetScreenSaver, - X_ChangeHosts, - X_ListHosts, - X_SetAccessControl, - X_SetCloseDownMode, - X_KillClient, - X_RotateProperties, - X_ForceScreenSaver, - X_SetPointerMapping, - X_GetPointerMapping, - X_SetModifierMapping, - X_GetModifierMapping, - X_NoOperation, -}; - -#define XMajors \ - "<nil>",\ - "CreateWindow",\ - "ChangeWindowAttributes",\ - "GetWindowAttributes",\ - "DestroyWindow",\ - "DestroySubwindows",\ - "ChangeSaveSet",\ - "ReparentWindow",\ - "MapWindow",\ - "MapSubwindows",\ - "UnmapWindow",\ - "UnmapSubwindows",\ - "ConfigureWindow",\ - "CirculateWindow",\ - "GetGeometry",\ - "QueryTree",\ - "InternAtom",\ - "GetAtomName",\ - "ChangeProperty",\ - "DeleteProperty",\ - "GetProperty",\ - "ListProperties",\ - "SetSelectionOwner",\ - "GetSelectionOwner",\ - "ConvertSelection",\ - "SendEvent",\ - "GrabPointer",\ - "UngrabPointer",\ - "GrabButton",\ - "UngrabButton",\ - "ChangeActivePointerGrab",\ - "GrabKeyboard",\ - "UngrabKeyboard",\ - "GrabKey",\ - "UngrabKey",\ - "AllowEvents",\ - "GrabServer",\ - "UngrabServer",\ - "QueryPointer",\ - "GetMotionEvents",\ - "TranslateCoords",\ - "WarpPointer",\ - "SetInputFocus",\ - "GetInputFocus",\ - "QueryKeymap",\ - "OpenFont",\ - "CloseFont",\ - "QueryFont",\ - "QueryTextExtents",\ - "ListFonts",\ - "ListFontsWithInfo",\ - "SetFontPath",\ - "GetFontPath",\ - "CreatePixmap",\ - "FreePixmap",\ - "CreateGC",\ - "ChangeGC",\ - "CopyGC",\ - "SetDashes",\ - "SetClipRectangles",\ - "FreeGC",\ - "ClearArea",\ - "CopyArea",\ - "CopyPlane",\ - "PolyPoint",\ - "PolyLine",\ - "PolySegment",\ - "PolyRectangle",\ - "PolyArc",\ - "FillPoly",\ - "PolyFillRectangle",\ - "PolyFillArc",\ - "PutImage",\ - "GetImage",\ - "PolyText8",\ - "PolyText16",\ - "ImageText8",\ - "ImageText16",\ - "CreateColormap",\ - "FreeColormap",\ - "CopyColormapAndFree",\ - "InstallColormap",\ - "UninstallColormap",\ - "ListInstalledColormaps",\ - "AllocColor",\ - "AllocNamedColor",\ - "AllocColorCells",\ - "AllocColorPlanes",\ - "FreeColors",\ - "StoreColors",\ - "StoreNamedColor",\ - "QueryColors",\ - "LookupColor",\ - "CreateCursor",\ - "CreateGlyphCursor",\ - "FreeCursor",\ - "RecolorCursor",\ - "QueryBestSize",\ - "QueryExtension",\ - "ListExtensions",\ - "ChangeKeyboardMapping",\ - "GetKeyboardMapping",\ - "ChangeKeyboardControl",\ - "GetKeyboardControl",\ - "Bell",\ - "ChangePointerControl",\ - "GetPointerControl",\ - "SetScreenSaver",\ - "GetScreenSaver",\ - "ChangeHosts",\ - "ListHosts",\ - "SetAccessControl",\ - "SetCloseDownMode",\ - "KillClient",\ - "RotateProperties",\ - "ForceScreenSaver",\ - "SetPointerMapping",\ - "GetPointerMapping",\ - "SetModifierMapping",\ - "GetModifierMapping",\ - "NoOperation",\ - diff --git a/libstuff/util/_die.c b/libstuff/util/_die.c @@ -1,26 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <sys/types.h> -#include <signal.h> -#include <unistd.h> -#include <fmt.h> -#include "util.h" - -void -_die(char *file, int line, char *msg, ...) { - va_list ap; - - va_start(ap, msg); - fprint(2, "%s: dieing at %s:%d: %s\n", - argv0, file, line, - vsxprint(msg, ap)); - va_end(ap); - - kill(getpid(), SIGABRT); - abort(); /* Adds too many frames: - * _die() - * abort() - * raise(SIGABRT) - * kill(getpid(), SIGABRT) - */ -} diff --git a/libstuff/util/backtrace.c b/libstuff/util/backtrace.c @@ -1,87 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <signal.h> - -#include <bio.h> -#include <plan9.h> -#undef nelem -#include <debug.h> -#include "util.h" - -#ifdef __linux__ -# define PROGTXT "exe" -#else -# define PROGTXT "file" -#endif - -static void -_backtrace(int pid, char *btarg) { - char *proc, *spid, *gdbcmd; - int fd[3], p[2]; - int status, cmdfd; - - gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX"); - if(pipe(p) < 0) - goto done; - closeexec(p[0]); - - cmdfd = mkstemp(gdbcmd); - if(cmdfd < 0) - goto done; - - fprint(cmdfd, "bt %s\n", btarg); - fprint(cmdfd, "detach\n"); - close(cmdfd); - - fd[0] = open("/dev/null", O_RDONLY); - fd[1] = p[1]; - fd[2] = dup(2); - - proc = sxprint("/proc/%d/" PROGTXT, pid); - spid = sxprint("%d", pid); - if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) { - unlink(gdbcmd); - goto done; - } - - Biobuf bp; - char *s; - - Binit(&bp, p[0], OREAD); - while((s = Brdstr(&bp, '\n', 1))) { - Dprint(DStack, "%s\n", s); - free(s); - } - unlink(gdbcmd); - -done: - free(gdbcmd); - kill(pid, SIGKILL); - waitpid(pid, &status, 0); -} - -void -backtrace(char *btarg) { - int pid; - - /* Fork so we can backtrace the child. Keep this stack - * frame minimal, so the trace is fairly clean. - */ - Debug(DStack) - switch(pid = fork()) { - case -1: - return; - case 0: - kill(getpid(), SIGSTOP); - _exit(0); - default: - _backtrace(pid, btarg); - break; - } - -} diff --git a/libstuff/util/closeexec.c b/libstuff/util/closeexec.c @@ -1,12 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <unistd.h> -#include <fcntl.h> -#include "util.h" - -void -closeexec(int fd) { - if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - fatal("can't set %d close on exec: %r", fd); -} diff --git a/libstuff/util/comm.c b/libstuff/util/comm.c @@ -1,42 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "util.h" -#include <stuff/x11.h> - - -char** -comm(int cols, char **toka, char **tokb) { - Vector_ptr vec; - char **ret; - int cmp; - - vector_pinit(&vec); - while(*toka || *tokb) { - if(!*toka) - cmp = 1; - else if(!*tokb) - cmp = -1; - else - cmp = strcmp(*toka, *tokb); - if(cmp < 0) { - if(cols & CLeft) - vector_ppush(&vec, *toka); - toka++; - }else if(cmp > 0) { - if(cols & CRight) - vector_ppush(&vec, *tokb); - tokb++; - }else { - if(cols & CCenter) - vector_ppush(&vec, *toka); - toka++; - tokb++; - } - } - vector_ppush(&vec, nil); - ret = strlistdup((char**)vec.ary); - free(vec.ary); - return ret; -} diff --git a/libstuff/util/doublefork.c b/libstuff/util/doublefork.c @@ -1,30 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <sys/wait.h> -#include <unistd.h> -#include "util.h" - -int -doublefork(void) { - pid_t pid; - int status; - - switch(pid=fork()) { - case -1: - fatal("Can't fork(): %r"); - case 0: - switch(pid=fork()) { - case -1: - fatal("Can't fork(): %r"); - case 0: - return 0; - default: - exit(0); - } - default: - waitpid(pid, &status, 0); - return pid; - } - /* NOTREACHED */ -} diff --git a/libstuff/util/emalloc.c b/libstuff/util/emalloc.c @@ -1,11 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -void * -emalloc(uint size) { - void *ret = malloc(size); - if(!ret) - mfatal("malloc", size); - return ret; -} diff --git a/libstuff/util/emallocz.c b/libstuff/util/emallocz.c @@ -1,11 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <string.h> -#include "util.h" - -void* -emallocz(uint size) { - void *ret = emalloc(size); - memset(ret, 0, size); - return ret; -} diff --git a/libstuff/util/erealloc.c b/libstuff/util/erealloc.c @@ -1,11 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -void * -erealloc(void *ptr, uint size) { - void *ret = realloc(ptr, size); - if(!ret) - mfatal("realloc", size); - return ret; -} diff --git a/libstuff/util/estrdup.c b/libstuff/util/estrdup.c @@ -1,12 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <string.h> -#include "util.h" - -char* -estrdup(const char *str) { - void *ret = strdup(str); - if(!ret) - mfatal("strdup", strlen(str)); - return ret; -} diff --git a/libstuff/util/estrndup.c b/libstuff/util/estrndup.c @@ -1,15 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <string.h> -#include "util.h" - -char* -estrndup(const char *str, uint len) { - char *ret; - - len = min(len, strlen(str)); - ret = emalloc(len + 1); - memcpy(ret, str, len); - ret[len] = '\0'; - return ret; -} diff --git a/libstuff/util/fatal.c b/libstuff/util/fatal.c @@ -1,39 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <fmt.h> -#include "util.h" - -typedef struct VFmt VFmt; -struct VFmt { - const char *fmt; - va_list args; -}; - -#ifdef VARARGCK -# pragma varargck type "V" VFmt* -#endif - -static int -Vfmt(Fmt *f) { - VFmt *vf; - int i; - - vf = va_arg(f->args, VFmt*); - i = fmtvprint(f, vf->fmt, vf->args); - return i; -} - -void -fatal(const char *fmt, ...) { - VFmt fp; - - fmtinstall('V', Vfmt); - fmtinstall('', Vfmt); - - fp.fmt = fmt; - va_start(fp.args, fmt); - fprint(2, "%s: fatal: %V\n", argv0, &fp); - va_end(fp.args); - - exit(1); -} diff --git a/libstuff/util/freelater.c b/libstuff/util/freelater.c @@ -1,15 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -void* -freelater(void *p) { - static char* obj[16]; - static long nobj; - int id; - - id = nobj++ % nelem(obj); - free(obj[id]); - obj[id] = p; - return p; -} diff --git a/libstuff/util/getbase.c b/libstuff/util/getbase.c @@ -1,43 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <ctype.h> -#include <string.h> -#include <stuff/util.h> - -#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1)) -int -getbase(const char **s, long *sign) { - const char *p; - int ret; - - ret = 10; - *sign = 1; - if(**s == '-') { - *sign = -1; - *s += 1; - }else if(**s == '+') - *s += 1; - - p = *s; - if(!strbcmp(p, "0x")) { - *s += 2; - ret = 16; - } - else if(isdigit(p[0])) { - if(p[1] == 'r') { - *s += 2; - ret = p[0] - '0'; - } - else if(isdigit(p[1]) && p[2] == 'r') { - *s += 3; - ret = 10*(p[0]-'0') + (p[1]-'0'); - } - } - else if(p[0] == '0') { - ret = 8; - } - if(ret != 10 && (**s == '-' || **s == '+')) - *sign = 0; - return ret; -} diff --git a/libstuff/util/getint.c b/libstuff/util/getint.c @@ -1,14 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/util.h> - -bool -getint(const char *s, int *ret) { - long l; - bool res; - - res = getlong(s, &l); - *ret = l; - return res; -} diff --git a/libstuff/util/getlong.c b/libstuff/util/getlong.c @@ -1,23 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include <stuff/util.h> - -bool -getlong(const char *s, long *ret) { - const char *end; - char *rend; - int base; - long sign; - - if(s == nil) - return false; - end = s+strlen(s); - base = getbase(&s, &sign); - if(sign == 0) - return false; - - *ret = sign * strtol(s, &rend, base); - return (end == rend); -} diff --git a/libstuff/util/getulong.c b/libstuff/util/getulong.c @@ -1,23 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include <stuff/util.h> - -bool -getulong(const char *s, ulong *ret) { - const char *end; - char *rend; - int base; - long sign; - - if(s == nil) - return false; - end = s+strlen(s); - base = getbase(&s, &sign); - if(sign < 1) - return false; - - *ret = strtoul(s, &rend, base); - return (end == rend); -} diff --git a/libstuff/util/grep.c b/libstuff/util/grep.c @@ -1,22 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "util.h" - - -void -grep(char **list, Reprog *re, int flags) { - char **p, **q; - int res; - - q = list; - for(p=q; *p; p++) { - res = 0; - if(re) - res = regexec(re, *p, nil, 0); - if(res && !(flags & GInvert) - || !res && (flags & GInvert)) - *q++ = *p; - } - *q = nil; -} diff --git a/libstuff/util/join.c b/libstuff/util/join.c @@ -1,22 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <fmt.h> -#include "util.h" - -char* -join(char **list, char *sep) { - Fmt f; - char **p; - - if(fmtstrinit(&f) < 0) - abort(); - - for(p=list; *p; p++) { - if(p != list) - fmtstrcpy(&f, sep); - fmtstrcpy(&f, *p); - } - - return fmtstrflush(&f); -} diff --git a/libstuff/util/max.c b/libstuff/util/max.c @@ -1,10 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -int -max(int a, int b) { - if(a > b) - return a; - return b; -} diff --git a/libstuff/util/mfatal.c b/libstuff/util/mfatal.c @@ -1,33 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <string.h> -#include <unistd.h> -#include "util.h" - -/* Can't malloc */ -void -mfatal(char *name, uint size) { - const char - couldnot[] = ": fatal: Could not ", - paren[] = "() ", - bytes[] = " bytes\n"; - char buf[1024]; - char sizestr[8]; - int i; - - i = sizeof sizestr; - do { - sizestr[--i] = '0' + (size%10); - size /= 10; - } while(size > 0); - - strlcat(buf, argv0, sizeof buf); - strlcat(buf, couldnot, sizeof buf); - strlcat(buf, name, sizeof buf); - strlcat(buf, paren, sizeof buf); - strlcat(buf, sizestr+i, sizeof buf); - strlcat(buf, bytes, sizeof buf); - write(2, buf, strlen(buf)); - - exit(1); -} diff --git a/libstuff/util/min.c b/libstuff/util/min.c @@ -1,10 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -int -min(int a, int b) { - if(a < b) - return a; - return b; -} diff --git a/libstuff/util/pathsearch.c b/libstuff/util/pathsearch.c @@ -1,32 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include <unistd.h> -#include <fmt.h> -#include "util.h" - -char* -pathsearch(const char *path, const char *file, bool slashok) { - char *orig, *p, *s; - - if(!slashok && strchr(file, '/') > file) - file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file); - else if(!strncmp(file, "./", 2)) - file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file+2); - if(file[0] == '/') { - if(access(file, X_OK)) - return strdup(file); - return nil; - } - - orig = estrdup(path ? path : getenv("PATH")); - for(p=orig; (s=strtok(p, ":")); p=nil) { - s = smprint("%s/%s", s, file); - if(!access(s, X_OK)) - break; - free(s); - } - free(orig); - return s; -} diff --git a/libstuff/util/refree.c b/libstuff/util/refree.c @@ -1,13 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "util.h" - -void -refree(Regex *r) { - - free(r->regex); - free(r->regc); - r->regex = nil; - r->regc = nil; -} diff --git a/libstuff/util/reinit.c b/libstuff/util/reinit.c @@ -1,16 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "util.h" - - -void -reinit(Regex *r, char *regx) { - - refree(r); - - if(regx[0] != '\0') { - r->regex = estrdup(regx); - r->regc = regcomp(regx); - } -} diff --git a/libstuff/util/spawn3.c b/libstuff/util/spawn3.c @@ -1,43 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <errno.h> -#include <unistd.h> -#include "util.h" - -int -spawn3(int fd[3], const char *file, char *argv[]) { - /* Some ideas from Russ Cox's libthread port. */ - int p[2]; - int pid; - - if(pipe(p) < 0) - return -1; - closeexec(p[1]); - - switch(pid = doublefork()) { - case 0: - dup2(fd[0], 0); - dup2(fd[1], 1); - dup2(fd[2], 2); - - execvp(file, argv); - write(p[1], &errno, sizeof errno); - exit(1); - break; - default: - close(p[1]); - if(read(p[0], &errno, sizeof errno) == sizeof errno) - pid = -1; - close(p[0]); - break; - case -1: /* can't happen */ - break; - } - - close(fd[0]); - /* These could fail if any of these was also a previous fd. */ - close(fd[1]); - close(fd[2]); - return pid; -} diff --git a/libstuff/util/spawn3l.c b/libstuff/util/spawn3l.c @@ -1,28 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <fmt.h> -#include "util.h" - -int -spawn3l(int fd[3], const char *file, ...) { - va_list ap; - char **argv; - int i, n; - - va_start(ap, file); - for(n=0; va_arg(ap, char*); n++) - ; - va_end(ap); - - argv = emalloc((n+1) * sizeof *argv); - va_start(ap, file); - quotefmtinstall(); - for(i=0; i <= n; i++) - argv[i] = va_arg(ap, char*); - va_end(ap); - - i = spawn3(fd, file, argv); - free(argv); - return i; -} diff --git a/libstuff/util/stokenize.c b/libstuff/util/stokenize.c @@ -1,22 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <string.h> -#include "util.h" - -uint -stokenize(char *res[], uint reslen, char *str, char *delim) { - char *s; - uint i; - - i = 0; - s = str; - while(i < reslen && *s) { - while(strchr(delim, *s)) - *(s++) = '\0'; - if(*s) - res[i++] = s; - while(*s && !strchr(delim, *s)) - s++; - } - return i; -} diff --git a/libstuff/util/strcasestr.c b/libstuff/util/strcasestr.c @@ -1,25 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <ctype.h> -#include <stdint.h> -#include <string.h> -#include <strings.h> -#include "util.h" - -/* TODO: Make this UTF-8 compliant. */ -char* -strcasestr(const char *dst, const char *src) { - int dc, sc; - int len; - - len = strlen(src) - 1; - for(; (sc = *src) && *dst; src++) { - sc = tolower(dc); - for(; (dc = *dst); dst++) { - dc = tolower(dc); - if(sc == dc && !strncasecmp(dst+1, src+1, len)) - return (char*)(uintptr_t)dst; - } - } - return nil; -} diff --git a/libstuff/util/strend.c b/libstuff/util/strend.c @@ -1,13 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include <stuff/util.h> - -char* -strend(char *s, int n) { - int len; - - len = strlen(s); - return s + max(0, len - n); -} diff --git a/libstuff/util/strlcat.c b/libstuff/util/strlcat.c @@ -1,26 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -uint -strlcat(char *dst, const char *src, uint size) { - const char *s; - char *d; - int n, len; - - d = dst; - s = src; - n = size; - while(n-- > 0 && *d != '\0') - d++; - len = n; - - while(*s != '\0') { - if(n-- > 0) - *d++ = *s; - s++; - } - if(len > 0) - *d = '\0'; - return size - n - 1; -} diff --git a/libstuff/util/strlcatprint.c b/libstuff/util/strlcatprint.c @@ -1,19 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include <fmt.h> -#include "util.h" - -int -strlcatprint(char *buf, int len, const char *fmt, ...) { - va_list ap; - int buflen; - int ret; - - va_start(ap, fmt); - buflen = strlen(buf); - ret = vsnprint(buf+buflen, len-buflen, fmt, ap); - va_end(ap); - return ret; -} diff --git a/libstuff/util/sxprint.c b/libstuff/util/sxprint.c @@ -1,14 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -char* -sxprint(const char *fmt, ...) { - va_list ap; - char *ret; - - va_start(ap, fmt); - ret = vsxprint(fmt, ap); - va_end(ap); - return ret; -} diff --git a/libstuff/util/tokenize.c b/libstuff/util/tokenize.c @@ -1,21 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -uint -tokenize(char *res[], uint reslen, char *str, char delim) { - char *s; - uint i; - - i = 0; - s = str; - while(i < reslen && *s) { - while(*s == delim) - *(s++) = '\0'; - if(*s) - res[i++] = s; - while(*s && *s != delim) - s++; - } - return i; -} diff --git a/libstuff/util/uniq.c b/libstuff/util/uniq.c @@ -1,18 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "util.h" - -void -uniq(char **toks) { - char **p, **q; - - q = toks; - if(*q == nil) - return; - for(p=q+1; *p; p++) - if(strcmp(*q, *p)) - *++q = *p; - *++q = nil; -} diff --git a/libstuff/util/unquote.c b/libstuff/util/unquote.c @@ -1,38 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "util.h" - -int -unquote(char *buf, char *toks[], int ntoks) { - char *s, *t; - bool inquote; - int n; - - n = 0; - s = buf; - while(*s && n < ntoks) { - while(*s && utfrune(" \t\r\n", *s)) - s++; - inquote = false; - toks[n] = s; - t = s; - while(*s && (inquote || !utfrune(" \t\r\n", *s))) { - if(*s == '\'') { - if(inquote && s[1] == '\'') - *t++ = *s++; - else - inquote = !inquote; - } - else - *t++ = *s; - s++; - } - if(*s) - s++; - *t = '\0'; - if(s != toks[n]) - n++; - } - return n; -} diff --git a/libstuff/util/utflcpy.c b/libstuff/util/utflcpy.c @@ -1,11 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include "util.h" - -int -utflcpy(char *to, const char *from, int l) { - char *p; - - p = utfecpy(to, to+l, from); - return p-to; -} diff --git a/libstuff/util/util.h b/libstuff/util/util.h @@ -1,5 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <stuff/util.h> - -void mfatal(char*, uint); diff --git a/libstuff/util/vector.c b/libstuff/util/vector.c @@ -1,33 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "util.h" - -/* Blech. */ -#define VECTOR(type, nam, c) \ -void \ -vector_##c##init(Vector_##nam *v) { \ - memset(v, 0, sizeof *v); \ -} \ - \ -void \ -vector_##c##free(Vector_##nam *v) { \ - free(v->ary); \ - memset(v, 0, sizeof *v); \ -} \ - \ -void \ -vector_##c##push(Vector_##nam *v, type val) { \ - if(v->n == v->size) { \ - if(v->size == 0) \ - v->size = 2; \ - v->size <<= 2; \ - v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \ - } \ - v->ary[v->n++] = val; \ -} \ - -VECTOR(long, long, l) -VECTOR(Rectangle, rect, r) -VECTOR(void*, ptr, p) diff --git a/libstuff/util/vsxprint.c b/libstuff/util/vsxprint.c @@ -1,13 +0,0 @@ -/* Written by Kris Maglione <maglione.k at Gmail> */ -/* Public domain */ -#include <fmt.h> -#include "util.h" - -char* -vsxprint(const char *fmt, va_list ap) { - char *s; - - s = vsmprint(fmt, ap); - freelater(s); - return s; -} diff --git a/libstuff/x11/colors/loadcolor.c b/libstuff/x11/colors/loadcolor.c @@ -1,18 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -bool -loadcolor(CTuple *c, char *str) { - char buf[24]; - - utflcpy(buf, str, sizeof buf); - memcpy(c->colstr, str, sizeof c->colstr); - - buf[7] = buf[15] = buf[23] = '\0'; - return namedcolor(buf, &c->fg) - && namedcolor(buf+8, &c->bg) - && namedcolor(buf+16, &c->border); -} diff --git a/libstuff/x11/colors/namedcolor.c b/libstuff/x11/colors/namedcolor.c @@ -1,22 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -bool -namedcolor(char *name, Color *ret) { - XColor c, c2; - - if(XAllocNamedColor(display, scr.colormap, name, &c, &c2)) { - *ret = (Color) { - c.pixel, { - c.red, - c.green, - c.blue, - 0xffff - }, - }; - return true; - } - return false; -} diff --git a/libstuff/x11/colors/xftcolor.c b/libstuff/x11/colors/xftcolor.c @@ -1,19 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -XftColor* -xftcolor(Color col) { - XftColor *c; - - c = emallocz(sizeof *c); - *c = (XftColor) { - ((col.render.alpha&0xff00) << 24) - | ((col.render.red&0xff00) << 8) - | ((col.render.green&0xff00) << 0) - | ((col.render.blue&0xff00) >> 8), - col.render - }; - return freelater(c); -} diff --git a/libstuff/x11/convpts.c b/libstuff/x11/convpts.c @@ -1,17 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -XPoint* -convpts(Point *pt, int np) { - XPoint *rp; - int i; - - rp = emalloc(np * sizeof *rp); - for(i = 0; i < np; i++) { - rp[i].x = pt[i].x; - rp[i].y = pt[i].y; - } - return rp; -} diff --git a/libstuff/x11/drawing/border.c b/libstuff/x11/drawing/border.c @@ -1,19 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -border(Image *dst, Rectangle r, int w, Color col) { - if(w == 0) - return; - - r = insetrect(r, w/2); - r.max.x -= w%2; - r.max.y -= w%2; - - XSetLineAttributes(display, dst->gc, w, LineSolid, CapButt, JoinMiter); - setgccol(dst, col); - XDrawRectangle(display, dst->xid, dst->gc, - r.min.x, r.min.y, Dx(r), Dy(r)); -} diff --git a/libstuff/x11/drawing/drawline.c b/libstuff/x11/drawing/drawline.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -drawline(Image *dst, Point p1, Point p2, int cap, int w, Color col) { - XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); - setgccol(dst, col); - XDrawLine(display, dst->xid, dst->gc, p1.x, p1.y, p2.x, p2.y); -} diff --git a/libstuff/x11/drawing/drawpoly.c b/libstuff/x11/drawing/drawpoly.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -drawpoly(Image *dst, Point *pt, int np, int cap, int w, Color col) { - XPoint *xp; - - xp = convpts(pt, np); - XSetLineAttributes(display, dst->gc, w, LineSolid, cap, JoinMiter); - setgccol(dst, col); - XDrawLines(display, dst->xid, dst->gc, xp, np, CoordModeOrigin); - free(xp); -} diff --git a/libstuff/x11/drawing/drawstring.c b/libstuff/x11/drawing/drawstring.c @@ -1,89 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -uint -drawstring(Image *dst, Font *font, - Rectangle r, Align align, - char *text, Color col) { - Rectangle tr; - char *buf; - uint x, y, width, height, len; - int shortened; - - shortened = 0; - - len = strlen(text); - buf = emalloc(len+1); - memcpy(buf, text, len+1); - - r.max.y -= font->pad.min.y; - r.min.y += font->pad.max.y; - - height = font->ascent + font->descent; - y = r.min.y + Dy(r) / 2 - height / 2 + font->ascent; - - width = Dx(r) - font->pad.min.x - font->pad.max.x - (font->height & ~1); - - r.min.x += font->pad.min.x; - r.max.x -= font->pad.max.x; - - /* shorten text if necessary */ - tr = ZR; - while(len > 0) { - tr = textextents_l(font, buf, len + min(shortened, 3), nil); - if(Dx(tr) <= width) - break; - while(len > 0 && (buf[--len]&0xC0) == 0x80) - buf[len] = '.'; - buf[len] = '.'; - shortened++; - } - - if(len == 0 || Dx(tr) > width) - goto done; - - /* mark shortened info in the string */ - if(shortened) - len += min(shortened, 3); - - switch (align) { - case East: - x = r.max.x - (tr.max.x + (font->height / 2)); - break; - case Center: - x = r.min.x + (Dx(r) - Dx(tr)) / 2 - tr.min.x; - break; - default: - x = r.min.x + (font->height / 2) - tr.min.x; - break; - } - - setgccol(dst, col); - switch(font->type) { - case FFontSet: - Xutf8DrawString(display, dst->xid, - font->font.set, dst->gc, - x, y, - buf, len); - break; - case FXft: - xft->drawstring(xftdrawable(dst), xftcolor(col), - font->font.xft, - x, y, buf, len); - break; - case FX11: - XSetFont(display, dst->gc, font->font.x11->fid); - XDrawString(display, dst->xid, dst->gc, - x, y, buf, len); - break; - default: - die("Invalid font type."); - } - -done: - free(buf); - return Dx(tr); -} diff --git a/libstuff/x11/drawing/fill.c b/libstuff/x11/drawing/fill.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -fill(Image *dst, Rectangle r, Color col) { - setgccol(dst, col); - XFillRectangle(display, dst->xid, dst->gc, - r.min.x, r.min.y, Dx(r), Dy(r)); -} diff --git a/libstuff/x11/drawing/fillpoly.c b/libstuff/x11/drawing/fillpoly.c @@ -1,14 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -fillpoly(Image *dst, Point *pt, int np, Color col) { - XPoint *xp; - - xp = convpts(pt, np); - setgccol(dst, col); - XFillPolygon(display, dst->xid, dst->gc, xp, np, Complex, CoordModeOrigin); - free(xp); -} diff --git a/libstuff/x11/errors.c b/libstuff/x11/errors.c @@ -1,40 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -extern ErrorCode ignored_xerrors[]; -static bool _trap_errors; -static long nerrors; - -int -errorhandler(Display *dpy, XErrorEvent *error) { - ErrorCode *e; - - USED(dpy); - - if(_trap_errors) - nerrors++; - - e = ignored_xerrors; - if(e) - for(; e->rcode || e->ecode; e++) - if((e->rcode == 0 || e->rcode == error->request_code) - && (e->ecode == 0 || e->ecode == error->error_code)) - return 0; - - fprint(2, "%s: fatal error: Xrequest code=%d, Xerror code=%d\n", - argv0, error->request_code, error->error_code); - return xlib_errorhandler(display, error); /* calls exit() */ -} - -int -traperrors(bool enable) { - - sync(); - _trap_errors = enable; - if (enable) - nerrors = 0; - return nerrors; - -} diff --git a/libstuff/x11/focus/getfocus.c b/libstuff/x11/focus/getfocus.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -XWindow -getfocus(void) { - XWindow ret; - int revert; - - XGetInputFocus(display, &ret, &revert); - return ret; -} diff --git a/libstuff/x11/focus/setfocus.c b/libstuff/x11/focus/setfocus.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -setfocus(Window *w, int mode) { - XSetInputFocus(display, w->xid, mode, CurrentTime); -} diff --git a/libstuff/x11/freestringlist.c b/libstuff/x11/freestringlist.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -void -freestringlist(char *list[]) { - XFreeStringList(list); -} diff --git a/libstuff/x11/geometry/XRect.c b/libstuff/x11/geometry/XRect.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -XRectangle -XRect(Rectangle r) { - XRectangle xr; - - xr.x = r.min.x; - xr.y = r.min.y; - xr.width = Dx(r); - xr.height = Dy(r); - return xr; -} diff --git a/libstuff/x11/geometry/addpt.c b/libstuff/x11/geometry/addpt.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Point -addpt(Point p, Point q) { - p.x += q.x; - p.y += q.y; - return p; -} diff --git a/libstuff/x11/geometry/divpt.c b/libstuff/x11/geometry/divpt.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Point -divpt(Point p, Point q) { - p.x /= q.x; - p.y /= q.y; - return p; -} diff --git a/libstuff/x11/geometry/eqpt.c b/libstuff/x11/geometry/eqpt.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -eqpt(Point p, Point q) { - return p.x==q.x && p.y==q.y; -} diff --git a/libstuff/x11/geometry/eqrect.c b/libstuff/x11/geometry/eqrect.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -eqrect(Rectangle a, Rectangle b) { - return a.min.x==b.min.x && a.max.x==b.max.x - && a.min.y==b.min.y && a.max.y==b.max.y; -} diff --git a/libstuff/x11/geometry/insetrect.c b/libstuff/x11/geometry/insetrect.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -insetrect(Rectangle r, int n) { - r.min.x += n; - r.min.y += n; - r.max.x -= n; - r.max.y -= n; - return r; -} diff --git a/libstuff/x11/geometry/mulpt.c b/libstuff/x11/geometry/mulpt.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Point -mulpt(Point p, Point q) { - p.x *= q.x; - p.y *= q.y; - return p; -} diff --git a/libstuff/x11/geometry/rectaddpt.c b/libstuff/x11/geometry/rectaddpt.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -rectaddpt(Rectangle r, Point p) { - r.min.x += p.x; - r.max.x += p.x; - r.min.y += p.y; - r.max.y += p.y; - return r; -} diff --git a/libstuff/x11/geometry/rectsetorigin.c b/libstuff/x11/geometry/rectsetorigin.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -rectsetorigin(Rectangle r, Point p) { - Rectangle ret; - - ret.min.x = p.x; - ret.min.y = p.y; - ret.max.x = p.x + Dx(r); - ret.max.y = p.y + Dy(r); - return ret; -} diff --git a/libstuff/x11/geometry/rectsubpt.c b/libstuff/x11/geometry/rectsubpt.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -rectsubpt(Rectangle r, Point p) { - r.min.x -= p.x; - r.max.x -= p.x; - r.min.y -= p.y; - r.max.y -= p.y; - return r; -} diff --git a/libstuff/x11/geometry/subpt.c b/libstuff/x11/geometry/subpt.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Point -subpt(Point p, Point q) { - p.x -= q.x; - p.y -= q.y; - return p; -} diff --git a/libstuff/x11/ignored_xerrors.c b/libstuff/x11/ignored_xerrors.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -ErrorCode ignored_xerrors[] = { - { 0, }, -}; - diff --git a/libstuff/x11/images/allocimage.c b/libstuff/x11/images/allocimage.c @@ -1,21 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Image* -allocimage(int w, int h, int depth) { - Image *img; - - img = emallocz(sizeof *img); - img->type = WImage; - img->xid = XCreatePixmap(display, scr.root.xid, w, h, depth); - img->gc = XCreateGC(display, img->xid, 0, nil); - img->colormap = scr.colormap; - img->visual = scr.visual; - if(depth == 32) - img->visual = scr.visual32; - img->depth = depth; - img->r = Rect(0, 0, w, h); - return img; -} diff --git a/libstuff/x11/images/copyimage.c b/libstuff/x11/images/copyimage.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -copyimage(Image *dst, Rectangle r, Image *src, Point p) { - XCopyArea(display, - src->xid, dst->xid, - dst->gc, - r.min.x, r.min.y, Dx(r), Dy(r), - p.x, p.y); -} diff --git a/libstuff/x11/images/freeimage.c b/libstuff/x11/images/freeimage.c @@ -1,18 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -freeimage(Image *img) { - if(img == nil) - return; - - assert(img->type == WImage); - - if(img->xft) - xft->drawdestroy(img->xft); - XFreePixmap(display, img->xid); - XFreeGC(display, img->gc); - free(img); -} diff --git a/libstuff/x11/images/xftdrawable.c b/libstuff/x11/images/xftdrawable.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -XftDraw* -xftdrawable(Image *img) { - if(img->xft == nil) - img->xft = xft->drawcreate(display, img->xid, img->visual, img->colormap); - return img->xft; -} diff --git a/libstuff/x11/initdisplay.c b/libstuff/x11/initdisplay.c @@ -1,84 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -int (*xlib_errorhandler) (Display*, XErrorEvent*); - -Map windowmap; -Map atommap; -MapEnt* wbucket[137]; -MapEnt* abucket[137]; - -static int -Afmt(Fmt *f) { - Atom a; - char *s; - int i; - - a = va_arg(f->args, Atom); - s = XGetAtomName(display, a); - i = fmtprint(f, "%s", s); - free(s); - return i; -} - -static int -Pfmt(Fmt *f) { - Point p; - - p = va_arg(f->args, Point); - return fmtprint(f, "(%d,%d)", p.x, p.y); -} - -static int -Rfmt(Fmt *f) { - Rectangle r; - - r = va_arg(f->args, Rectangle); - return fmtprint(f, "%P+%dx%d", r.min, Dx(r), Dy(r)); -} - -static int -Wfmt(Fmt *f) { - Window *w; - - w = va_arg(f->args, Window*); - return fmtprint(f, "0x%ulx", w->xid); -} - -void -initdisplay(void) { - display = XOpenDisplay(nil); - if(display == nil) - fatal("Can't open display"); - scr.screen = DefaultScreen(display); - scr.colormap = DefaultColormap(display, scr.screen); - scr.visual = DefaultVisual(display, scr.screen); - scr.visual32 = DefaultVisual(display, scr.screen); - scr.gc = DefaultGC(display, scr.screen); - scr.depth = DefaultDepth(display, scr.screen); - - scr.white = WhitePixel(display, scr.screen); - scr.black = BlackPixel(display, scr.screen); - - scr.root.xid = RootWindow(display, scr.screen); - scr.root.r = Rect(0, 0, - DisplayWidth(display, scr.screen), - DisplayHeight(display, scr.screen)); - scr.rect = scr.root.r; - - scr.root.parent = &scr.root; - - windowmap.bucket = wbucket; - windowmap.nhash = nelem(wbucket); - atommap.bucket = abucket; - atommap.nhash = nelem(abucket); - - fmtinstall('A', Afmt); - fmtinstall('R', Rfmt); - fmtinstall('P', Pfmt); - fmtinstall('W', Wfmt); - - xlib_errorhandler = XSetErrorHandler(errorhandler); -} diff --git a/libstuff/x11/insanity/gravitate.c b/libstuff/x11/insanity/gravitate.c @@ -1,19 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -gravitate(Rectangle rc, Rectangle rf, Point grav) { - Point d; - - /* Get delta between frame and client rectangles */ - d = subpt(subpt(rf.max, rf.min), - subpt(rc.max, rc.min)); - - /* Divide by 2 and apply gravity */ - d = divpt(d, Pt(2, 2)); - d = mulpt(d, grav); - - return rectsubpt(rc, d); -} diff --git a/libstuff/x11/insanity/sethints.c b/libstuff/x11/insanity/sethints.c @@ -1,100 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -void -sethints(Window *w) { - XSizeHints xs; - XWMHints *wmh; - WinHints *h; - Point p; - long size; - - if(w->hints == nil) - w->hints = emalloc(sizeof *h); - - h = w->hints; - memset(h, 0, sizeof *h); - - h->max = Pt(INT_MAX, INT_MAX); - h->inc = Pt(1,1); - - wmh = XGetWMHints(display, w->xid); - if(wmh) { - if(wmh->flags & WindowGroupHint) - h->group = wmh->window_group; - free(wmh); - } - - if(!XGetWMNormalHints(display, w->xid, &xs, &size)) - return; - - if(xs.flags & PMinSize) { - h->min.x = xs.min_width; - h->min.y = xs.min_height; - } - if(xs.flags & PMaxSize) { - h->max.x = xs.max_width; - h->max.y = xs.max_height; - } - - /* Goddamn buggy clients. */ - if(h->max.x < h->min.x) - h->max.x = h->min.x; - if(h->max.y < h->min.y) - h->max.y = h->min.y; - - h->base = h->min; - if(xs.flags & PBaseSize) { - p.x = xs.base_width; - p.y = xs.base_height; - h->base = p; - h->baspect = p; - } - - if(xs.flags & PResizeInc) { - h->inc.x = max(xs.width_inc, 1); - h->inc.y = max(xs.height_inc, 1); - } - - if(xs.flags & PAspect) { - h->aspect.min.x = xs.min_aspect.x; - h->aspect.min.y = xs.min_aspect.y; - h->aspect.max.x = xs.max_aspect.x; - h->aspect.max.y = xs.max_aspect.y; - } - - h->position = (xs.flags & (USPosition|PPosition)) != 0; - - if(!(xs.flags & PWinGravity)) - xs.win_gravity = NorthWestGravity; - p = ZP; - switch (xs.win_gravity) { - case EastGravity: - case CenterGravity: - case WestGravity: - p.y = 1; - break; - case SouthEastGravity: - case SouthGravity: - case SouthWestGravity: - p.y = 2; - break; - } - switch (xs.win_gravity) { - case NorthGravity: - case CenterGravity: - case SouthGravity: - p.x = 1; - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - p.x = 2; - break; - } - h->grav = p; - h->gravstatic = (xs.win_gravity == StaticGravity); -} diff --git a/libstuff/x11/insanity/sizehint.c b/libstuff/x11/insanity/sizehint.c @@ -1,42 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -sizehint(WinHints *h, Rectangle r) { - Point p, aspect, origin; - - if(h == nil) - return r; - - origin = r.min; - r = rectsubpt(r, origin); - - /* Min/max */ - r.max.x = max(r.max.x, h->min.x); - r.max.y = max(r.max.y, h->min.y); - r.max.x = min(r.max.x, h->max.x); - r.max.y = min(r.max.y, h->max.y); - - /* Increment */ - p = subpt(r.max, h->base); - r.max.x -= p.x % h->inc.x; - r.max.y -= p.y % h->inc.y; - - /* Aspect */ - p = subpt(r.max, h->baspect); - p.y = max(p.y, 1); - - aspect = h->aspect.min; - if(p.x * aspect.y / p.y < aspect.x) - r.max.y = h->baspect.y - + p.x * aspect.y / aspect.x; - - aspect = h->aspect.max; - if(p.x * aspect.y / p.y > aspect.x) - r.max.x = h->baspect.x - + p.y * aspect.x / aspect.y; - - return rectaddpt(r, origin); -} diff --git a/libstuff/x11/keyboard/grabkeyboard.c b/libstuff/x11/keyboard/grabkeyboard.c @@ -1,12 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -grabkeyboard(Window *w) { - - return XGrabKeyboard(display, w->xid, true /* owner events */, - GrabModeAsync, GrabModeAsync, CurrentTime - ) == GrabSuccess; -} diff --git a/libstuff/x11/keyboard/ungrabkeyboard.c b/libstuff/x11/keyboard/ungrabkeyboard.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -ungrabkeyboard(void) { - XUngrabKeyboard(display, CurrentTime); -} diff --git a/libstuff/x11/keys/keycode.c b/libstuff/x11/keys/keycode.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -KeyCode -keycode(char *name) { - return XKeysymToKeycode(display, XStringToKeysym(name)); -} diff --git a/libstuff/x11/keys/parsekey.c b/libstuff/x11/keys/parsekey.c @@ -1,46 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -typedef struct KMask KMask; - -static struct KMask { - int mask; - const char* name; -} masks[] = { - {ShiftMask, "Shift"}, - {ControlMask, "Control"}, - {Mod1Mask, "Mod1"}, - {Mod2Mask, "Mod2"}, - {Mod3Mask, "Mod3"}, - {Mod4Mask, "Mod4"}, - {Mod5Mask, "Mod5"}, - {0,} -}; - -bool -parsekey(char *str, int *mask, char **key) { - static char *keys[16]; - KMask *m; - int i, nkeys; - - *mask = 0; - nkeys = tokenize(keys, nelem(keys), str, '-'); - for(i=0; i < nkeys; i++) { - for(m=masks; m->mask; m++) - if(!strcasecmp(m->name, keys[i])) { - *mask |= m->mask; - goto next; - } - break; - next: continue; - } - if(key) { - if(nkeys) - *key = keys[i]; - return i == nkeys - 1; - } - else - return i == nkeys; -} diff --git a/libstuff/x11/mouse/grabpointer.c b/libstuff/x11/mouse/grabpointer.c @@ -1,16 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -grabpointer(Window *w, Window *confine, Cursor cur, int mask) { - XWindow cw; - - cw = None; - if(confine) - cw = confine->xid; - return XGrabPointer(display, w->xid, false /* owner events */, mask, - GrabModeAsync, GrabModeAsync, cw, cur, CurrentTime - ) == GrabSuccess; -} diff --git a/libstuff/x11/mouse/pointerscreen.c b/libstuff/x11/mouse/pointerscreen.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -pointerscreen(void) { - XWindow win; - Point pt; - uint ui; - int i; - - return XQueryPointer(display, scr.root.xid, &win, &win, &i, &i, - &pt.x, &pt.y, &ui); -} diff --git a/libstuff/x11/mouse/querypointer.c b/libstuff/x11/mouse/querypointer.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Point -querypointer(Window *w) { - XWindow win; - Point pt; - uint ui; - int i; - - XQueryPointer(display, w->xid, &win, &win, &i, &i, &pt.x, &pt.y, &ui); - return pt; -} diff --git a/libstuff/x11/mouse/translate.c b/libstuff/x11/mouse/translate.c @@ -1,14 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Point -translate(Window *src, Window *dst, Point sp) { - Point pt; - XWindow w; - - XTranslateCoordinates(display, src->xid, dst->xid, sp.x, sp.y, - &pt.x, &pt.y, &w); - return pt; -} diff --git a/libstuff/x11/mouse/ungrabpointer.c b/libstuff/x11/mouse/ungrabpointer.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -ungrabpointer(void) { - XUngrabPointer(display, CurrentTime); -} diff --git a/libstuff/x11/mouse/warppointer.c b/libstuff/x11/mouse/warppointer.c @@ -1,23 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -warppointer(Point pt) { - /* Nasty kludge for xephyr, xnest. */ - static int havereal = -1; - static char* real; - - if(havereal == -1) { - real = getenv("REALDISPLAY"); - havereal = real != nil; - } - if(havereal) - system(sxprint("DISPLAY=%s wiwarp %d %d", real, pt.x, pt.y)); - - XWarpPointer(display, - /* src, dest w */ None, scr.root.xid, - /* src_rect */ 0, 0, 0, 0, - /* target */ pt.x, pt.y); -} diff --git a/libstuff/x11/properties/changeprop_char.c b/libstuff/x11/properties/changeprop_char.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -changeprop_char(Window *w, char *prop, char *type, char data[], int len) { - changeproperty(w, prop, type, 8, (uchar*)data, len); -} diff --git a/libstuff/x11/properties/changeprop_long.c b/libstuff/x11/properties/changeprop_long.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -changeprop_long(Window *w, char *prop, char *type, long data[], int len) { - changeproperty(w, prop, type, 32, (uchar*)data, len); -} diff --git a/libstuff/x11/properties/changeprop_short.c b/libstuff/x11/properties/changeprop_short.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -changeprop_short(Window *w, char *prop, char *type, short data[], int len) { - changeproperty(w, prop, type, 16, (uchar*)data, len); -} diff --git a/libstuff/x11/properties/changeprop_string.c b/libstuff/x11/properties/changeprop_string.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -void -changeprop_string(Window *w, char *prop, char *string) { - changeprop_char(w, prop, "UTF8_STRING", string, strlen(string)); -} diff --git a/libstuff/x11/properties/changeprop_textlist.c b/libstuff/x11/properties/changeprop_textlist.c @@ -1,24 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -void -changeprop_textlist(Window *w, char *prop, char *type, char *data[]) { - char **p, *s, *t; - int len, n; - - len = 0; - for(p=data; *p; p++) - len += strlen(*p) + 1; - s = emalloc(len); - t = s; - for(p=data; *p; p++) { - n = strlen(*p) + 1; - memcpy(t, *p, n); - t += n; - } - changeprop_char(w, prop, type, s, len); - free(s); -} diff --git a/libstuff/x11/properties/changeprop_ulong.c b/libstuff/x11/properties/changeprop_ulong.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -changeprop_ulong(Window *w, char *prop, char *type, ulong data[], int len) { - changeproperty(w, prop, type, 32, (uchar*)data, len); -} diff --git a/libstuff/x11/properties/changeproperty.c b/libstuff/x11/properties/changeproperty.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -changeproperty(Window *w, char *prop, char *type, - int width, uchar data[], int n) { - XChangeProperty(display, w->xid, xatom(prop), xatom(type), width, - PropModeReplace, data, n); -} diff --git a/libstuff/x11/properties/delproperty.c b/libstuff/x11/properties/delproperty.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -delproperty(Window *w, char *prop) { - XDeleteProperty(display, w->xid, xatom(prop)); -} diff --git a/libstuff/x11/properties/getprop.c b/libstuff/x11/properties/getprop.c @@ -1,28 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -ulong -getprop(Window *w, char *prop, char *type, Atom *actual, int *format, - ulong offset, uchar **ret, ulong length) { - Atom typea; - ulong n, extra; - int status; - - typea = (type ? xatom(type) : 0L); - - status = XGetWindowProperty(display, w->xid, - xatom(prop), offset, length, false /* delete */, - typea, actual, format, &n, &extra, ret); - - if(status != Success) { - *ret = nil; - return 0; - } - if(n == 0) { - free(*ret); - *ret = nil; - } - return n; -} diff --git a/libstuff/x11/properties/getprop_long.c b/libstuff/x11/properties/getprop_long.c @@ -1,19 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -ulong -getprop_long(Window *w, char *prop, char *type, - ulong offset, long **ret, ulong length) { - Atom actual; - ulong n; - int format; - - n = getprop(w, prop, type, &actual, &format, offset, (uchar**)ret, length); - if(n == 0 || format == 32 && xatom(type) == actual) - return n; - free(*ret); - *ret = 0; - return 0; -} diff --git a/libstuff/x11/properties/getprop_string.c b/libstuff/x11/properties/getprop_string.c @@ -1,19 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -char* -getprop_string(Window *w, char *name) { - char **list, *str; - int n; - - str = nil; - - n = getprop_textlist(w, name, &list); - if(n > 0) - str = estrdup(*list); - freestringlist(list); - - return str; -} diff --git a/libstuff/x11/properties/getprop_textlist.c b/libstuff/x11/properties/getprop_textlist.c @@ -1,22 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -getprop_textlist(Window *w, char *name, char **ret[]) { - XTextProperty prop; - char **list; - int n; - - *ret = nil; - n = 0; - - XGetTextProperty(display, w->xid, &prop, xatom(name)); - if(prop.nitems > 0) { - if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success) - *ret = list; - XFree(prop.value); - } - return n; -} diff --git a/libstuff/x11/properties/getprop_ulong.c b/libstuff/x11/properties/getprop_ulong.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -ulong -getprop_ulong(Window *w, char *prop, char *type, - ulong offset, ulong **ret, ulong length) { - return getprop_long(w, prop, type, offset, (long**)ret, length); -} diff --git a/libstuff/x11/properties/getproperty.c b/libstuff/x11/properties/getproperty.c @@ -1,12 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -ulong -getproperty(Window *w, char *prop, char *type, Atom *actual, - ulong offset, uchar **ret, ulong length) { - int format; - - return getprop(w, prop, type, actual, &format, offset, ret, length); -} diff --git a/libstuff/x11/properties/strlistdup.c b/libstuff/x11/properties/strlistdup.c @@ -1,29 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -char** -strlistdup(char *list[]) { - char **p; - char *q; - int i, m, n; - - n = 0; - m = 0; - for(p=list; *p; p++, n++) - m += strlen(*p) + 1; - - p = malloc((n+1) * sizeof(*p) + m); - q = (char*)&p[n+1]; - - for(i=0; i < n; i++) { - p[i] = q; - m = strlen(list[i]) + 1; - memcpy(q, list[i], m); - q += m; - } - p[n] = nil; - return p; -} diff --git a/libstuff/x11/sendevent.c b/libstuff/x11/sendevent.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -void -sendevent(Window *w, bool propegate, long mask, XEvent *e) { - XSendEvent(display, w->xid, propegate, mask, e); -} diff --git a/libstuff/x11/sendmessage.c b/libstuff/x11/sendmessage.c @@ -1,20 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -void -sendmessage(Window *w, char *name, long l0, long l1, long l2, long l3, long l4) { - XClientMessageEvent e; - - e.type = ClientMessage; - e.window = w->xid; - e.message_type = xatom(name); - e.format = 32; - e.data.l[0] = l0; - e.data.l[1] = l1; - e.data.l[2] = l2; - e.data.l[3] = l3; - e.data.l[4] = l4; - sendevent(w, false, NoEventMask, (XEvent*)&e); -} diff --git a/libstuff/x11/setgccol.c b/libstuff/x11/setgccol.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -void -setgccol(Image *dst, Color col) { - XSetForeground(display, dst->gc, col.pixel); -} diff --git a/libstuff/x11/shape/setshapemask.c b/libstuff/x11/shape/setshapemask.c @@ -1,11 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -setshapemask(Window *dst, Image *src, Point pt) { - /* Assumes that we have the shape extension... */ - XShapeCombineMask (display, dst->xid, - ShapeBounding, pt.x, pt.y, src->xid, ShapeSet); -} diff --git a/libstuff/x11/sync.c b/libstuff/x11/sync.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -void -sync(void) { - XSync(display, false); -} diff --git a/libstuff/x11/text/freefont.c b/libstuff/x11/text/freefont.c @@ -1,23 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -freefont(Font *f) { - switch(f->type) { - case FFontSet: - XFreeFontSet(display, f->font.set); - break; - case FXft: - xft->fontclose(display, f->font.xft); - break; - case FX11: - XFreeFont(display, f->font.x11); - break; - default: - break; - } - free(f->name); - free(f); -} diff --git a/libstuff/x11/text/labelh.c b/libstuff/x11/text/labelh.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -uint -labelh(Font *font) { - return max(font->height + font->descent + font->pad.min.y + font->pad.max.y, 1); -} diff --git a/libstuff/x11/text/loadfont.c b/libstuff/x11/text/loadfont.c @@ -1,70 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -Font* -loadfont(char *name) { - XFontStruct **xfonts; - char **missing, **font_names; - Biobuf *b; - Font *f; - int n, i; - - missing = nil; - f = emallocz(sizeof *f); - f->name = estrdup(name); - if(!strncmp(f->name, "xft:", 4)) { - f->type = FXft; - - if(!havexft()) - goto error; - - f->font.xft = xft->fontopen(display, scr.screen, f->name + 4); - if(!f->font.xft) - f->font.xft = xft->fontopenname(display, scr.screen, f->name + 4); - if(!f->font.xft) - goto error; - - f->ascent = f->font.xft->ascent; - f->descent = f->font.xft->descent; - }else { - f->font.set = XCreateFontSet(display, name, &missing, &n, nil); - if(missing) { - if(false) { - b = Bfdopen(dup(2), O_WRONLY); - Bprint(b, "%s: note: missing fontset%s for '%s':", argv0, - (n > 1 ? "s" : ""), name); - for(i = 0; i < n; i++) - Bprint(b, "%s %s", (i ? "," : ""), missing[i]); - Bprint(b, "\n"); - Bterm(b); - } - freestringlist(missing); - } - - if(f->font.set) { - f->type = FFontSet; - XFontsOfFontSet(f->font.set, &xfonts, &font_names); - f->ascent = xfonts[0]->ascent; - f->descent = xfonts[0]->descent; - }else { - f->type = FX11; - f->font.x11 = XLoadQueryFont(display, name); - if(!f->font.x11) - goto error; - - f->ascent = f->font.x11->ascent; - f->descent = f->font.x11->descent; - } - } - f->height = f->ascent + f->descent; - return f; - -error: - fprint(2, "%s: cannot load font: %s\n", argv0, name); - f->type = 0; - freefont(f); - return nil; -} diff --git a/libstuff/x11/text/textextents_l.c b/libstuff/x11/text/textextents_l.c @@ -1,34 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -textextents_l(Font *font, char *text, uint len, int *offset) { - Rectangle rect; - XRectangle r; - XGlyphInfo i; - int unused; - - if(!offset) - offset = &unused; - - switch(font->type) { - case FFontSet: - *offset = Xutf8TextExtents(font->font.set, text, len, &r, nil); - return Rect(r.x, -r.y - r.height, r.x + r.width, -r.y); - case FXft: - xft->textextents(display, font->font.xft, text, len, &i); - *offset = i.xOff; - return Rect(-i.x, i.y - i.height, -i.x + i.width, i.y); - case FX11: - rect = ZR; - rect.max.x = XTextWidth(font->font.x11, text, len); - rect.max.y = font->ascent; - *offset = rect.max.x; - return rect; - default: - die("Invalid font type"); - return ZR; /* shut up ken */ - } -} diff --git a/libstuff/x11/text/textwidth.c b/libstuff/x11/text/textwidth.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <string.h> -#include "../x11.h" - -uint -textwidth(Font *font, char *text) { - return textwidth_l(font, text, strlen(text)); -} diff --git a/libstuff/x11/text/textwidth_l.c b/libstuff/x11/text/textwidth_l.c @@ -1,12 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -uint -textwidth_l(Font *font, char *text, uint len) { - Rectangle r; - - r = textextents_l(font, text, len, nil); - return Dx(r); -} diff --git a/libstuff/x11/windows/configwin.c b/libstuff/x11/windows/configwin.c @@ -1,22 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -configwin(Window *w, Rectangle r, int border) { - XWindowChanges wc; - - if(eqrect(r, w->r) && border == w->border) - return; - - wc.x = r.min.x - border; - wc.y = r.min.y - border; - wc.width = Dx(r); - wc.height = Dy(r); - wc.border_width = border; - XConfigureWindow(display, w->xid, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - - w->r = r; - w->border = border; -} diff --git a/libstuff/x11/windows/createwindow.c b/libstuff/x11/windows/createwindow.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Window* -createwindow(Window *parent, Rectangle r, int depth, uint class, WinAttr *wa, int valmask) { - return createwindow_visual(parent, r, depth, scr.visual, class, wa, valmask); -} diff --git a/libstuff/x11/windows/createwindow_visual.c b/libstuff/x11/windows/createwindow_visual.c @@ -1,33 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Window* -createwindow_visual(Window *parent, Rectangle r, - int depth, Visual *vis, uint class, - WinAttr *wa, int valmask) { - Window *w; - - assert(parent->type == WWindow); - - w = emallocz(sizeof *w); - w->visual = vis; - w->type = WWindow; - w->parent = parent; - if(valmask & CWColormap) - w->colormap = wa->colormap; - - w->xid = XCreateWindow(display, parent->xid, r.min.x, r.min.y, Dx(r), Dy(r), - 0 /* border */, depth, class, vis, valmask, wa); -#if 0 - print("createwindow_visual(%W, %R, %d, %p, %ud, %p, %x) = %W\n", - parent, r, depth, vis, class, wa, valmask, w); -#endif - if(class != InputOnly) - w->gc = XCreateGC(display, w->xid, 0, nil); - - w->r = r; - w->depth = depth; - return w; -} diff --git a/libstuff/x11/windows/destroywindow.c b/libstuff/x11/windows/destroywindow.c @@ -1,16 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -destroywindow(Window *w) { - assert(w->type == WWindow); - sethandler(w, nil); - if(w->xft) - xft->drawdestroy(w->xft); - if(w->gc) - XFreeGC(display, w->gc); - XDestroyWindow(display, w->xid); - free(w); -} diff --git a/libstuff/x11/windows/findwin.c b/libstuff/x11/windows/findwin.c @@ -1,14 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Window* -findwin(XWindow w) { - void **e; - - e = map_get(&windowmap, (ulong)w, false); - if(e) - return *e; - return nil; -} diff --git a/libstuff/x11/windows/getwinrect.c b/libstuff/x11/windows/getwinrect.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Rectangle -getwinrect(Window *w) { - XWindowAttributes wa; - Point p; - - if(!XGetWindowAttributes(display, w->xid, &wa)) - return ZR; - p = translate(w, &scr.root, ZP); - return rectaddpt(Rect(0, 0, wa.width, wa.height), p); -} diff --git a/libstuff/x11/windows/lowerwin.c b/libstuff/x11/windows/lowerwin.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -lowerwin(Window *w) { - assert(w->type == WWindow); - XLowerWindow(display, w->xid); -} diff --git a/libstuff/x11/windows/mapwin.c b/libstuff/x11/windows/mapwin.c @@ -1,15 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -mapwin(Window *w) { - assert(w->type == WWindow); - if(!w->mapped) { - XMapWindow(display, w->xid); - w->mapped = 1; - return 1; - } - return 0; -} diff --git a/libstuff/x11/windows/movewin.c b/libstuff/x11/windows/movewin.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -movewin(Window *w, Point pt) { - Rectangle r; - - assert(w->type == WWindow); - r = rectsetorigin(w->r, pt); - reshapewin(w, r); -} diff --git a/libstuff/x11/windows/raisewin.c b/libstuff/x11/windows/raisewin.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -raisewin(Window *w) { - assert(w->type == WWindow); - XRaiseWindow(display, w->xid); -} diff --git a/libstuff/x11/windows/reparentwindow.c b/libstuff/x11/windows/reparentwindow.c @@ -1,13 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -reparentwindow(Window *w, Window *par, Point p) { - assert(w->type == WWindow); - XReparentWindow(display, w->xid, par->xid, p.x, p.y); - w->parent = par; - w->r = rectsubpt(w->r, w->r.min); - w->r = rectaddpt(w->r, p); -} diff --git a/libstuff/x11/windows/reshapewin.c b/libstuff/x11/windows/reshapewin.c @@ -1,12 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -reshapewin(Window *w, Rectangle r) { - assert(w->type == WWindow); - assert(Dx(r) > 0 && Dy(r) > 0); /* Rather than an X error. */ - - configwin(w, r, w->border); -} diff --git a/libstuff/x11/windows/selectinput.c b/libstuff/x11/windows/selectinput.c @@ -1,9 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -selectinput(Window *w, long mask) { - XSelectInput(display, w->xid, mask); -} diff --git a/libstuff/x11/windows/setborder.c b/libstuff/x11/windows/setborder.c @@ -1,14 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -setborder(Window *w, int width, Color col) { - - assert(w->type == WWindow); - if(width) - XSetWindowBorder(display, w->xid, col.pixel); - if(width != w->border) - configwin(w, w->r, width); -} diff --git a/libstuff/x11/windows/sethandler.c b/libstuff/x11/windows/sethandler.c @@ -1,23 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Handlers* -sethandler(Window *w, Handlers *new) { - Handlers *old; - void **e; - - assert(w->type == WWindow); - assert((w->prev != nil && w->next != nil) || w->next == w->prev); - - if(new == nil) - map_rm(&windowmap, (ulong)w->xid); - else { - e = map_get(&windowmap, (ulong)w->xid, true); - *e = w; - } - old = w->handler; - w->handler = new; - return old; -} diff --git a/libstuff/x11/windows/setwinattr.c b/libstuff/x11/windows/setwinattr.c @@ -1,10 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -void -setwinattr(Window *w, WinAttr *wa, int valmask) { - assert(w->type == WWindow); - XChangeWindowAttributes(display, w->xid, valmask, wa); -} diff --git a/libstuff/x11/windows/unmapwin.c b/libstuff/x11/windows/unmapwin.c @@ -1,16 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -int -unmapwin(Window *w) { - assert(w->type == WWindow); - if(w->mapped) { - XUnmapWindow(display, w->xid); - w->mapped = 0; - w->unmapped++; - return 1; - } - return 0; -} diff --git a/libstuff/x11/windows/window.c b/libstuff/x11/windows/window.c @@ -1,14 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "../x11.h" - -Window* -window(XWindow xw) { - Window *w; - - w = malloc(sizeof *w); - w->type = WWindow; - w->xid = xw; - return freelater(w); -} diff --git a/libstuff/x11/x11.c b/libstuff/x11/x11.c @@ -1,12 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -const Point ZP = {0, 0}; -const Rectangle ZR = {{0, 0}, {0, 0}}; - -const Window _pointerwin = { .xid = PointerRoot }; -Window* const pointerwin = (Window*)&_pointerwin; - - diff --git a/libstuff/x11/x11.h b/libstuff/x11/x11.h @@ -1,31 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ - -#define _X11_VISIBLE -#define pointerwin __pointerwin -#include <assert.h> -#include <limits.h> -#include <math.h> -#include <strings.h> -#include <unistd.h> -#include <bio.h> -#include <stuff/x.h> -#include <stuff/util.h> -#undef pointerwin - -extern Map windowmap; -extern Map atommap; -extern MapEnt* wbucket[137]; -extern MapEnt* abucket[137]; - -extern int (*xlib_errorhandler) (Display*, XErrorEvent*); - -void configwin(Window*, Rectangle, int); -XPoint* convpts(Point*, int); -int errorhandler(Display*, XErrorEvent*); -ulong getprop(Window*, char*, char*, Atom*, int*, ulong, uchar**, ulong); -void setgccol(Image*, Color); -XftColor* xftcolor(Color); -XftDraw* xftdrawable(Image*); - diff --git a/libstuff/x11/xatom.c b/libstuff/x11/xatom.c @@ -1,14 +0,0 @@ -/* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "x11.h" - -Atom -xatom(char *name) { - void **e; - - e = hash_get(&atommap, name, true); - if(*e == nil) - *e = (void*)XInternAtom(display, name, false); - return (Atom)*e; -} diff --git a/libstuff/x11/xft.c b/libstuff/x11/xft.c @@ -1,39 +0,0 @@ -/* Copyright ©2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <stuff/x.h> -#include <stuff/util.h> - -Xft *xft; - -#ifdef HAVE_RTLD -#include <dlfcn.h> - -bool -havexft(void) { - void *libxft; - - if(xft == nil) { - libxft = dlopen("libXft.so", RTLD_LAZY); - if(libxft == nil) - return false; - xft = emalloc(sizeof *xft); - *(void**)(uintptr_t)&xft->drawcreate = dlsym(libxft, "XftDrawCreate"); - *(void**)(uintptr_t)&xft->drawdestroy = dlsym(libxft, "XftDrawDestroy"); - *(void**)(uintptr_t)&xft->fontopen = dlsym(libxft, "XftFontOpenXlfd"); - *(void**)(uintptr_t)&xft->fontopenname = dlsym(libxft, "XftFontOpenName"); - *(void**)(uintptr_t)&xft->fontclose = dlsym(libxft, "XftFontClose"); - *(void**)(uintptr_t)&xft->textextents = dlsym(libxft, "XftTextExtentsUtf8"); - *(void**)(uintptr_t)&xft->drawstring = dlsym(libxft, "XftDrawStringUtf8"); - } - return xft && xft->drawcreate && xft->drawdestroy && xft->fontopen - && xft->fontopenname && xft->fontclose && xft->textextents && xft->drawstring; -} - -#else -bool -havexft(void) { - return false; -} -#endif - diff --git a/libstuff/xext.c b/libstuff/xext.c @@ -1,161 +0,0 @@ -/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#define _X11_VISIBLE -#include <stuff/x.h> -#include <stuff/util.h> -#include <X11/extensions/Xrender.h> -#include <X11/extensions/Xinerama.h> - -#if RANDR_MAJOR < 1 -# error XRandR versions less than 1.0 are not supported -#endif - -static void randr_screenchange(XRRScreenChangeNotifyEvent*); -static bool randr_event_p(XEvent *e); -static void randr_init(void); -static void render_init(void); -static void xinerama_init(void); - -typedef void (*EvHandler)(XEvent*); -static EvHandler randr_handlers[RRNumberEvents]; - -bool have_RandR; -bool have_render; -bool have_xinerama; -int randr_eventbase; -Visual* render_visual; - -static void -handle(XEvent *e, EvHandler h[], int base) { - - if(h[e->type-base]) - h[e->type-base](e); -} - -void -xext_init(void) { - randr_init(); - render_init(); - xinerama_init(); -} - -void -xext_event(XEvent *e) { - - if(randr_event_p(e)) - handle(e, randr_handlers, randr_eventbase); -} - -static void -randr_init(void) { - int errorbase, major, minor; - - have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase); - if(have_RandR) - if(XRRQueryVersion(display, &major, &minor) && major < 1) - have_RandR = false; - if(have_RandR) - XRRSelectInput(display, scr.root.xid, RRScreenChangeNotifyMask); -} - -static bool -randr_event_p(XEvent *e) { - return have_RandR - && (uint)e->type - randr_eventbase < RRNumberEvents; -} - -static void -randr_screenchange(XRRScreenChangeNotifyEvent *ev) { - - XRRUpdateConfiguration((XEvent*)ev); - if(ev->rotation*90 % 180) - scr.rect = Rect(0, 0, ev->width, ev->height); - else - scr.rect = Rect(0, 0, ev->height, ev->width); - init_screens(); -} - -static EvHandler randr_handlers[] = { - [RRScreenChangeNotify] = (EvHandler)randr_screenchange, -}; - -/* Ripped most graciously from ecore_x. XRender documentation - * is sparse. - */ -static void -render_init(void) { - XVisualInfo *vip; - XVisualInfo vi; - int base, i, n; - - have_render = XRenderQueryExtension(display, &base, &base); - if(!have_render) - return; - - vi.class = TrueColor; - vi.depth = 32; - vi.screen = scr.screen; - vip = XGetVisualInfo(display, VisualClassMask - | VisualDepthMask - | VisualScreenMask, - &vi, &n); - for(i=0; i < n; i++) - if(render_argb_p(vip[i].visual)) { - render_visual = vip[i].visual; - scr.visual32 = render_visual; - break; - } - XFree(vip); -} - -bool -render_argb_p(Visual *v) { - XRenderPictFormat *f; - - if(!have_render) - return false; - f = XRenderFindVisualFormat(display, v); - return f - && f->type == PictTypeDirect - && f->direct.alphaMask; -} - -static void -xinerama_init(void) { - int base; - - have_xinerama = XineramaQueryExtension(display, &base, &base); -} - -static bool -xinerama_active(void) { - return have_xinerama && XineramaIsActive(display); -} - -Rectangle* -xinerama_screens(int *np) { - static Rectangle *rects; - XineramaScreenInfo *res; - int i, n; - - if(!xinerama_active()) { - *np = 1; - return &scr.rect; - } - - free(rects); - res = XineramaQueryScreens(display, &n); - rects = emalloc(n * sizeof *rects); - for(i=0; i < n; i++) { - rects[i].min.x = res[i].x_org; - rects[i].min.y = res[i].y_org; - rects[i].max.x = res[i].x_org + res[i].width; - rects[i].max.y = res[i].y_org + res[i].height; - } - XFree(res); - - *np = n; - return rects; -} - diff --git a/libutf/Makefile b/libutf/Makefile @@ -1,30 +0,0 @@ -ROOT= .. -include ${ROOT}/mk/hdr.mk - -VERSION=2.0 -TARG=libutf - -OBJ=\ - rune\ - runestrcat\ - runestrchr\ - runestrcmp\ - runestrcpy\ - runestrdup\ - runestrlen\ - runestrecpy\ - runestrncat\ - runestrncmp\ - runestrncpy\ - runestrrchr\ - runestrstr\ - runetype\ - utfecpy\ - utflen\ - utfnlen\ - utfrrune\ - utfrune\ - utfutf - -include ${ROOT}/mk/lib.mk - diff --git a/libutf/NOTICE b/libutf/NOTICE @@ -1,25 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -*/ - -This is a Unix port of the Plan 9 formatted I/O package. - -Please send comments about the packaging -to Russ Cox <rsc@swtch.com>. - - ----- - -This software is also made available under the Lucent Public License -version 1.02; see http://plan9.bell-labs.com/plan9dist/license.html - diff --git a/libutf/README b/libutf/README @@ -1,5 +0,0 @@ -This software was packaged for Unix by Russ Cox. -Please send comments to rsc@swtch.com. - -http://swtch.com/plan9port/unix - diff --git a/libutf/isalpharune.3 b/libutf/isalpharune.3 @@ -1,57 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH ISALPHARUNE 3 -.SH NAME -isalpharune, islowerrune, isspacerune, istitlerune, isupperrune, tolowerrune, totitlerune, toupperrune \- Unicode character classes and cases -.SH SYNOPSIS -.B #include <utf.h> -.PP -.B -int isalpharune(Rune c) -.PP -.B -int islowerrune(Rune c) -.PP -.B -int isspacerune(Rune c) -.PP -.B -int istitlerune(Rune c) -.PP -.B -int isupperrune(Rune c) -.PP -.B -Rune tolowerrune(Rune c) -.PP -.B -Rune totitlerune(Rune c) -.PP -.B -Rune toupperrune(Rune c) -.SH DESCRIPTION -These routines examine and operate on Unicode characters, -in particular a subset of their properties as defined in the Unicode standard. -Unicode defines some characters as alphabetic and specifies three cases: -upper, lower, and title. -Analogously to -.IR isalpha (3) -for -.SM ASCII\c -, -these routines -test types and modify cases for Unicode characters. -The names are self-explanatory. -.PP -The case-conversion routines return the character unchanged if it has no case. -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH "SEE ALSO -.IR isalpha (3) , -.IR "The Unicode Standard" . diff --git a/libutf/libutf.a b/libutf/libutf.a Binary files differ. diff --git a/libutf/rune.3 b/libutf/rune.3 @@ -1,194 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH RUNE 3 -.SH NAME -runetochar, chartorune, runelen, runenlen, fullrune, utfecpy, utflen, utfnlen, utfrune, utfrrune, utfutf \- rune/UTF conversion -.SH SYNOPSIS -.ta \w'\fLchar*xx'u -.B #include <utf.h> -.PP -.B -int runetochar(char *s, Rune *r) -.PP -.B -int chartorune(Rune *r, char *s) -.PP -.B -int runelen(long r) -.PP -.B -int runenlen(Rune *r, int n) -.PP -.B -int fullrune(char *s, int n) -.PP -.B -char* utfecpy(char *s1, char *es1, char *s2) -.PP -.B -int utflen(char *s) -.PP -.B -int utfnlen(char *s, long n) -.PP -.B -char* utfrune(char *s, long c) -.PP -.B -char* utfrrune(char *s, long c) -.PP -.B -char* utfutf(char *s1, char *s2) -.SH DESCRIPTION -These routines convert to and from a -.SM UTF -byte stream and runes. -.PP -.I Runetochar -copies one rune at -.I r -to at most -.B UTFmax -bytes starting at -.I s -and returns the number of bytes copied. -.BR UTFmax , -defined as -.B 3 -in -.BR <libc.h> , -is the maximum number of bytes required to represent a rune. -.PP -.I Chartorune -copies at most -.B UTFmax -bytes starting at -.I s -to one rune at -.I r -and returns the number of bytes copied. -If the input is not exactly in -.SM UTF -format, -.I chartorune -will convert to 0x80 and return 1. -.PP -.I Runelen -returns the number of bytes -required to convert -.I r -into -.SM UTF. -.PP -.I Runenlen -returns the number of bytes -required to convert the -.I n -runes pointed to by -.I r -into -.SM UTF. -.PP -.I Fullrune -returns 1 if the string -.I s -of length -.I n -is long enough to be decoded by -.I chartorune -and 0 otherwise. -This does not guarantee that the string -contains a legal -.SM UTF -encoding. -This routine is used by programs that -obtain input a byte at -a time and need to know when a full rune -has arrived. -.PP -The following routines are analogous to the -corresponding string routines with -.B utf -substituted for -.B str -and -.B rune -substituted for -.BR chr . -.PP -.I Utfecpy -copies UTF sequences until a null sequence has been copied, but writes no -sequences beyond -.IR es1 . -If any sequences are copied, -.I s1 -is terminated by a null sequence, and a pointer to that sequence is returned. -Otherwise, the original -.I s1 -is returned. -.PP -.I Utflen -returns the number of runes that -are represented by the -.SM UTF -string -.IR s . -.PP -.I Utfnlen -returns the number of complete runes that -are represented by the first -.I n -bytes of -.SM UTF -string -.IR s . -If the last few bytes of the string contain an incompletely coded rune, -.I utfnlen -will not count them; in this way, it differs from -.IR utflen , -which includes every byte of the string. -.PP -.I Utfrune -.RI ( utfrrune ) -returns a pointer to the first (last) -occurrence of rune -.I c -in the -.SM UTF -string -.IR s , -or 0 if -.I c -does not occur in the string. -The NUL byte terminating a string is considered to -be part of the string -.IR s . -.PP -.I Utfutf -returns a pointer to the first occurrence of -the -.SM UTF -string -.I s2 -as a -.SM UTF -substring of -.IR s1 , -or 0 if there is none. -If -.I s2 -is the null string, -.I utfutf -returns -.IR s1 . -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH SEE ALSO -.IR utf (7), -.IR tcs (1) diff --git a/libutf/rune.c b/libutf/rune.c @@ -1,175 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -enum -{ - Bit1 = 7, - Bitx = 6, - Bit2 = 5, - Bit3 = 4, - Bit4 = 3, - - T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ - Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ - T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ - T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ - T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ - - Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ - Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ - Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ - - Maskx = (1<<Bitx)-1, /* 0011 1111 */ - Testx = Maskx ^ 0xFF, /* 1100 0000 */ - - Bad = Runeerror, -}; - -int -chartorune(Rune *rune, const char *str) -{ - int c, c1, c2; - long l; - - /* - * one character sequence - * 00000-0007F => T1 - */ - c = *(uchar*)str; - if(c < Tx) { - *rune = c; - return 1; - } - - /* - * two character sequence - * 0080-07FF => T2 Tx - */ - c1 = *(uchar*)(str+1) ^ Tx; - if(c1 & Testx) - goto bad; - if(c < T3) { - if(c < T2) - goto bad; - l = ((c << Bitx) | c1) & Rune2; - if(l <= Rune1) - goto bad; - *rune = l; - return 2; - } - - /* - * three character sequence - * 0800-FFFF => T3 Tx Tx - */ - c2 = *(uchar*)(str+2) ^ Tx; - if(c2 & Testx) - goto bad; - if(c < T4) { - l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; - if(l <= Rune2) - goto bad; - *rune = l; - return 3; - } - - /* - * bad decoding - */ -bad: - *rune = Bad; - return 1; -} - -int -runetochar(char *str, const Rune *rune) -{ - long c; - - /* - * one character sequence - * 00000-0007F => 00-7F - */ - c = *rune; - if(c <= Rune1) { - str[0] = c; - return 1; - } - - /* - * two character sequence - * 0080-07FF => T2 Tx - */ - if(c <= Rune2) { - str[0] = T2 | (c >> 1*Bitx); - str[1] = Tx | (c & Maskx); - return 2; - } - - /* - * three character sequence - * 0800-FFFF => T3 Tx Tx - */ - str[0] = T3 | (c >> 2*Bitx); - str[1] = Tx | ((c >> 1*Bitx) & Maskx); - str[2] = Tx | (c & Maskx); - return 3; -} - -int -runelen(Rune c) -{ - char str[10]; - - return runetochar(str, &c); -} - -int -runenlen(const Rune *r, int nrune) -{ - int nb, c; - - nb = 0; - while(nrune--) { - c = *r++; - if(c <= Rune1) - nb++; - else - if(c <= Rune2) - nb += 2; - else - nb += 3; - } - return nb; -} - -int -fullrune(const char *str, int n) -{ - int c; - - if(n > 0) { - c = *(uchar*)str; - if(c < Tx) - return 1; - if(n > 1) - if(c < T3 || n > 2) - return 1; - } - return 0; -} diff --git a/libutf/runestrcat.3 b/libutf/runestrcat.3 @@ -1,74 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH RUNESTRCAT 3 -.SH NAME -runestrcat, -runestrncat, -runestrcmp, -runestrncmp, -runestrcpy, -runestrncpy, -runestrecpy, -runestrlen, -runestrchr, -runestrrchr, -runestrdup, -runestrstr \- rune string operations -.SH SYNOPSIS -.B #include <u.h> -.br -.B #include <libc.h> -.PP -.ta \w'\fLRune* \fP'u -.B -Rune* runestrcat(Rune *s1, Rune *s2) -.PP -.B -Rune* runestrncat(Rune *s1, Rune *s2, long n) -.PP -.B -int runestrcmp(Rune *s1, Rune *s2) -.PP -.B -int runestrncmp(Rune *s1, Rune *s2, long n) -.PP -.B -Rune* runestrcpy(Rune *s1, Rune *s2) -.PP -.B -Rune* runestrncpy(Rune *s1, Rune *s2, long n) -.PP -.B -Rune* runestrecpy(Rune *s1, Rune *es1, Rune *s2) -.PP -.B -long runestrlen(Rune *s) -.PP -.B -Rune* runestrchr(Rune *s, Rune c) -.PP -.B -Rune* runestrrchr(Rune *s, Rune c) -.PP -.B -Rune* runestrdup(Rune *s) -.PP -.B -Rune* runestrstr(Rune *s1, Rune *s2) -.SH DESCRIPTION -These functions are rune string analogues of -the corresponding functions in -.IR strcat (3). -.SH SOURCE -.B http://swtch.com/plan9port/unix -.SH SEE ALSO -.IR rune (3), -.IR strcat (3) -.SH BUGS -The outcome of overlapping moves varies among implementations. diff --git a/libutf/runestrcat.c b/libutf/runestrcat.c @@ -1,24 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include <plan9.h> - -Rune* -runestrcat(Rune *s1, const Rune *s2) -{ - - runestrcpy(runestrchr(s1, 0), s2); - return s1; -} diff --git a/libutf/runestrchr.c b/libutf/runestrchr.c @@ -1,35 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -Rune* -runestrchr(const Rune *s, Rune c) -{ - Rune c0 = c; - Rune c1; - - if(c == 0) { - while(*s++) - ; - return (Rune*)s-1; - } - - while(c1 = *s++) - if(c1 == c0) - return (Rune*)s-1; - return 0; -} diff --git a/libutf/runestrcmp.c b/libutf/runestrcmp.c @@ -1,35 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -int -runestrcmp(const Rune *s1, const Rune *s2) -{ - Rune c1, c2; - - for(;;) { - c1 = *s1++; - c2 = *s2++; - if(c1 != c2) { - if(c1 > c2) - return 1; - return -1; - } - if(c1 == 0) - return 0; - } -} diff --git a/libutf/runestrcpy.c b/libutf/runestrcpy.c @@ -1,28 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -Rune* -runestrcpy(Rune *s1, const Rune *s2) -{ - Rune *os1; - - os1 = s1; - while(*s1++ = *s2++) - ; - return os1; -} diff --git a/libutf/runestrdup.c b/libutf/runestrdup.c @@ -1,27 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdlib.h> -#include <plan9.h> - -Rune* -runestrdup(const Rune *s) -{ - Rune *ns; - - ns = malloc(sizeof(Rune)*(runestrlen(s) + 1)); - if(ns == 0) - return 0; - - return runestrcpy(ns, s); -} diff --git a/libutf/runestrecpy.c b/libutf/runestrecpy.c @@ -1,32 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -Rune* -runestrecpy(Rune *s1, Rune *es1, const Rune *s2) -{ - if(s1 >= es1) - return s1; - - while(*s1++ = *s2++){ - if(s1 == es1){ - *--s1 = '\0'; - break; - } - } - return s1; -} diff --git a/libutf/runestrlen.c b/libutf/runestrlen.c @@ -1,21 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <plan9.h> - -long -runestrlen(const Rune *s) -{ - - return runestrchr(s, 0) - s; -} diff --git a/libutf/runestrncat.c b/libutf/runestrncat.c @@ -1,32 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -Rune* -runestrncat(Rune *s1, const Rune *s2, long n) -{ - Rune *os1; - - os1 = s1; - s1 = runestrchr(s1, 0); - while(*s1++ = *s2++) - if(--n < 0) { - s1[-1] = 0; - break; - } - return os1; -} diff --git a/libutf/runestrncmp.c b/libutf/runestrncmp.c @@ -1,37 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -int -runestrncmp(const Rune *s1, const Rune *s2, long n) -{ - Rune c1, c2; - - while(n > 0) { - c1 = *s1++; - c2 = *s2++; - n--; - if(c1 != c2) { - if(c1 > c2) - return 1; - return -1; - } - if(c1 == 0) - break; - } - return 0; -} diff --git a/libutf/runestrncpy.c b/libutf/runestrncpy.c @@ -1,33 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -Rune* -runestrncpy(Rune *s1, const Rune *s2, long n) -{ - int i; - Rune *os1; - - os1 = s1; - for(i = 0; i < n; i++) - if((*s1++ = *s2++) == 0) { - while(++i < n) - *s1++ = 0; - return os1; - } - return os1; -} diff --git a/libutf/runestrrchr.c b/libutf/runestrrchr.c @@ -1,30 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -Rune* -runestrrchr(const Rune *s, Rune c) -{ - const Rune *r; - - if(c == 0) - return runestrchr(s, 0); - r = 0; - while(s = runestrchr(s, c)) - r = s++; - return (Rune*)r; -} diff --git a/libutf/runestrstr.c b/libutf/runestrstr.c @@ -1,45 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -/* - * Return pointer to first occurrence of s2 in s1, - * 0 if none - */ -Rune* -runestrstr(const Rune *s1, const Rune *s2) -{ - const Rune *pa, *pb; - Rune *p; - int c0, c; - - c0 = *s2; - if(c0 == 0) - return (Rune*)s1; - s2++; - for(p=runestrchr(s1, c0); p; p=runestrchr(p+1, c0)) { - pa = p; - for(pb=s2;; pb++) { - c = *pb; - if(c == 0) - return p; - if(c != *++pa) - break; - } - } - return 0; -} diff --git a/libutf/runetype.c b/libutf/runetype.c @@ -1,1151 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -/* - * alpha ranges - - * only covers ranges not in lower||upper - */ -static -Rune __alpha2[] = -{ - 0x00d8, 0x00f6, /* Ø - ö */ - 0x00f8, 0x01f5, /* ø - ǵ */ - 0x0250, 0x02a8, /* ɐ - ʨ */ - 0x038e, 0x03a1, /* Ύ - Ρ */ - 0x03a3, 0x03ce, /* Σ - ώ */ - 0x03d0, 0x03d6, /* ϐ - ϖ */ - 0x03e2, 0x03f3, /* Ϣ - ϳ */ - 0x0490, 0x04c4, /* Ґ - ӄ */ - 0x0561, 0x0587, /* ա - և */ - 0x05d0, 0x05ea, /* א - ת */ - 0x05f0, 0x05f2, /* װ - ײ */ - 0x0621, 0x063a, /* ء - غ */ - 0x0640, 0x064a, /* ـ - ي */ - 0x0671, 0x06b7, /* ٱ - ڷ */ - 0x06ba, 0x06be, /* ں - ھ */ - 0x06c0, 0x06ce, /* ۀ - ێ */ - 0x06d0, 0x06d3, /* ې - ۓ */ - 0x0905, 0x0939, /* अ - ह */ - 0x0958, 0x0961, /* क़ - ॡ */ - 0x0985, 0x098c, /* অ - ঌ */ - 0x098f, 0x0990, /* এ - ঐ */ - 0x0993, 0x09a8, /* ও - ন */ - 0x09aa, 0x09b0, /* প - র */ - 0x09b6, 0x09b9, /* শ - হ */ - 0x09dc, 0x09dd, /* ড় - ঢ় */ - 0x09df, 0x09e1, /* য় - ৡ */ - 0x09f0, 0x09f1, /* ৰ - ৱ */ - 0x0a05, 0x0a0a, /* ਅ - ਊ */ - 0x0a0f, 0x0a10, /* ਏ - ਐ */ - 0x0a13, 0x0a28, /* ਓ - ਨ */ - 0x0a2a, 0x0a30, /* ਪ - ਰ */ - 0x0a32, 0x0a33, /* ਲ - ਲ਼ */ - 0x0a35, 0x0a36, /* ਵ - ਸ਼ */ - 0x0a38, 0x0a39, /* ਸ - ਹ */ - 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */ - 0x0a85, 0x0a8b, /* અ - ઋ */ - 0x0a8f, 0x0a91, /* એ - ઑ */ - 0x0a93, 0x0aa8, /* ઓ - ન */ - 0x0aaa, 0x0ab0, /* પ - ર */ - 0x0ab2, 0x0ab3, /* લ - ળ */ - 0x0ab5, 0x0ab9, /* વ - હ */ - 0x0b05, 0x0b0c, /* ଅ - ଌ */ - 0x0b0f, 0x0b10, /* ଏ - ଐ */ - 0x0b13, 0x0b28, /* ଓ - ନ */ - 0x0b2a, 0x0b30, /* ପ - ର */ - 0x0b32, 0x0b33, /* ଲ - ଳ */ - 0x0b36, 0x0b39, /* ଶ - ହ */ - 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */ - 0x0b5f, 0x0b61, /* ୟ - ୡ */ - 0x0b85, 0x0b8a, /* அ - ஊ */ - 0x0b8e, 0x0b90, /* எ - ஐ */ - 0x0b92, 0x0b95, /* ஒ - க */ - 0x0b99, 0x0b9a, /* ங - ச */ - 0x0b9e, 0x0b9f, /* ஞ - ட */ - 0x0ba3, 0x0ba4, /* ண - த */ - 0x0ba8, 0x0baa, /* ந - ப */ - 0x0bae, 0x0bb5, /* ம - வ */ - 0x0bb7, 0x0bb9, /* ஷ - ஹ */ - 0x0c05, 0x0c0c, /* అ - ఌ */ - 0x0c0e, 0x0c10, /* ఎ - ఐ */ - 0x0c12, 0x0c28, /* ఒ - న */ - 0x0c2a, 0x0c33, /* ప - ళ */ - 0x0c35, 0x0c39, /* వ - హ */ - 0x0c60, 0x0c61, /* ౠ - ౡ */ - 0x0c85, 0x0c8c, /* ಅ - ಌ */ - 0x0c8e, 0x0c90, /* ಎ - ಐ */ - 0x0c92, 0x0ca8, /* ಒ - ನ */ - 0x0caa, 0x0cb3, /* ಪ - ಳ */ - 0x0cb5, 0x0cb9, /* ವ - ಹ */ - 0x0ce0, 0x0ce1, /* ೠ - ೡ */ - 0x0d05, 0x0d0c, /* അ - ഌ */ - 0x0d0e, 0x0d10, /* എ - ഐ */ - 0x0d12, 0x0d28, /* ഒ - ന */ - 0x0d2a, 0x0d39, /* പ - ഹ */ - 0x0d60, 0x0d61, /* ൠ - ൡ */ - 0x0e01, 0x0e30, /* ก - ะ */ - 0x0e32, 0x0e33, /* า - ำ */ - 0x0e40, 0x0e46, /* เ - ๆ */ - 0x0e5a, 0x0e5b, /* ๚ - ๛ */ - 0x0e81, 0x0e82, /* ກ - ຂ */ - 0x0e87, 0x0e88, /* ງ - ຈ */ - 0x0e94, 0x0e97, /* ດ - ທ */ - 0x0e99, 0x0e9f, /* ນ - ຟ */ - 0x0ea1, 0x0ea3, /* ມ - ຣ */ - 0x0eaa, 0x0eab, /* ສ - ຫ */ - 0x0ead, 0x0eae, /* ອ - ຮ */ - 0x0eb2, 0x0eb3, /* າ - ຳ */ - 0x0ec0, 0x0ec4, /* ເ - ໄ */ - 0x0edc, 0x0edd, /* ໜ - ໝ */ - 0x0f18, 0x0f19, /* ༘ - ༙ */ - 0x0f40, 0x0f47, /* ཀ - ཇ */ - 0x0f49, 0x0f69, /* ཉ - ཀྵ */ - 0x10d0, 0x10f6, /* ა - ჶ */ - 0x1100, 0x1159, /* ᄀ - ᅙ */ - 0x115f, 0x11a2, /* ᅟ - ᆢ */ - 0x11a8, 0x11f9, /* ᆨ - ᇹ */ - 0x1e00, 0x1e9b, /* Ḁ - ẛ */ - 0x1f50, 0x1f57, /* ὐ - ὗ */ - 0x1f80, 0x1fb4, /* ᾀ - ᾴ */ - 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */ - 0x1fc2, 0x1fc4, /* ῂ - ῄ */ - 0x1fc6, 0x1fcc, /* ῆ - ῌ */ - 0x1fd0, 0x1fd3, /* ῐ - ΐ */ - 0x1fd6, 0x1fdb, /* ῖ - Ί */ - 0x1fe0, 0x1fec, /* ῠ - Ῥ */ - 0x1ff2, 0x1ff4, /* ῲ - ῴ */ - 0x1ff6, 0x1ffc, /* ῶ - ῼ */ - 0x210a, 0x2113, /* ℊ - ℓ */ - 0x2115, 0x211d, /* ℕ - ℝ */ - 0x2120, 0x2122, /* ℠ - ™ */ - 0x212a, 0x2131, /* K - ℱ */ - 0x2133, 0x2138, /* ℳ - ℸ */ - 0x3041, 0x3094, /* ぁ - ゔ */ - 0x30a1, 0x30fa, /* ァ - ヺ */ - 0x3105, 0x312c, /* ㄅ - ㄬ */ - 0x3131, 0x318e, /* ㄱ - ㆎ */ - 0x3192, 0x319f, /* ㆒ - ㆟ */ - 0x3260, 0x327b, /* ㉠ - ㉻ */ - 0x328a, 0x32b0, /* ㊊ - ㊰ */ - 0x32d0, 0x32fe, /* ㋐ - ㋾ */ - 0x3300, 0x3357, /* ㌀ - ㍗ */ - 0x3371, 0x3376, /* ㍱ - ㍶ */ - 0x337b, 0x3394, /* ㍻ - ㎔ */ - 0x3399, 0x339e, /* ㎙ - ㎞ */ - 0x33a9, 0x33ad, /* ㎩ - ㎭ */ - 0x33b0, 0x33c1, /* ㎰ - ㏁ */ - 0x33c3, 0x33c5, /* ㏃ - ㏅ */ - 0x33c7, 0x33d7, /* ㏇ - ㏗ */ - 0x33d9, 0x33dd, /* ㏙ - ㏝ */ - 0x4e00, 0x9fff, /* 一 - 鿿 */ - 0xac00, 0xd7a3, /* 가 - 힣 */ - 0xf900, 0xfb06, /* 豈 - st */ - 0xfb13, 0xfb17, /* ﬓ - ﬗ */ - 0xfb1f, 0xfb28, /* ײַ - ﬨ */ - 0xfb2a, 0xfb36, /* שׁ - זּ */ - 0xfb38, 0xfb3c, /* טּ - לּ */ - 0xfb40, 0xfb41, /* נּ - סּ */ - 0xfb43, 0xfb44, /* ףּ - פּ */ - 0xfb46, 0xfbb1, /* צּ - ﮱ */ - 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */ - 0xfd50, 0xfd8f, /* ﵐ - ﶏ */ - 0xfd92, 0xfdc7, /* ﶒ - ﷇ */ - 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */ - 0xfe70, 0xfe72, /* ﹰ - ﹲ */ - 0xfe76, 0xfefc, /* ﹶ - ﻼ */ - 0xff66, 0xff6f, /* ヲ - ッ */ - 0xff71, 0xff9d, /* ア - ン */ - 0xffa0, 0xffbe, /* ᅠ - ᄒ */ - 0xffc2, 0xffc7, /* ᅡ - ᅦ */ - 0xffca, 0xffcf, /* ᅧ - ᅬ */ - 0xffd2, 0xffd7, /* ᅭ - ᅲ */ - 0xffda, 0xffdc, /* ᅳ - ᅵ */ -}; - -/* - * alpha singlets - - * only covers ranges not in lower||upper - */ -static -Rune __alpha1[] = -{ - 0x00aa, /* ª */ - 0x00b5, /* µ */ - 0x00ba, /* º */ - 0x03da, /* Ϛ */ - 0x03dc, /* Ϝ */ - 0x03de, /* Ϟ */ - 0x03e0, /* Ϡ */ - 0x06d5, /* ە */ - 0x09b2, /* ল */ - 0x0a5e, /* ਫ਼ */ - 0x0a8d, /* ઍ */ - 0x0ae0, /* ૠ */ - 0x0b9c, /* ஜ */ - 0x0cde, /* ೞ */ - 0x0e4f, /* ๏ */ - 0x0e84, /* ຄ */ - 0x0e8a, /* ຊ */ - 0x0e8d, /* ຍ */ - 0x0ea5, /* ລ */ - 0x0ea7, /* ວ */ - 0x0eb0, /* ະ */ - 0x0ebd, /* ຽ */ - 0x1fbe, /* ι */ - 0x207f, /* ⁿ */ - 0x20a8, /* ₨ */ - 0x2102, /* ℂ */ - 0x2107, /* ℇ */ - 0x2124, /* ℤ */ - 0x2126, /* Ω */ - 0x2128, /* ℨ */ - 0xfb3e, /* מּ */ - 0xfe74, /* ﹴ */ -}; - -/* - * space ranges - */ -static -Rune __space2[] = -{ - 0x0009, 0x000a, /* tab and newline */ - 0x0020, 0x0020, /* space */ - 0x00a0, 0x00a0, /*   */ - 0x2000, 0x200b, /*   - ​ */ - 0x2028, 0x2029, /* 
 - 
 */ - 0x3000, 0x3000, /*   */ - 0xfeff, 0xfeff, /*  */ -}; - -/* - * lower case ranges - * 3rd col is conversion excess 500 - */ -static -Rune __toupper2[] = -{ - 0x0061, 0x007a, 468, /* a-z A-Z */ - 0x00e0, 0x00f6, 468, /* à-ö À-Ö */ - 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */ - 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */ - 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */ - 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */ - 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */ - 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */ - 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */ - 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */ - 0x0430, 0x044f, 468, /* а-я А-Я */ - 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */ - 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */ - 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */ - 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */ - 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */ - 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */ - 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */ - 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */ - 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */ - 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */ - 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */ - 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */ - 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */ - 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */ - 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */ - 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */ - 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */ - 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */ - 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */ - 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */ - 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */ - 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */ - 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */ - 0xff41, 0xff5a, 468, /* a-z A-Z */ -}; - -/* - * lower case singlets - * 2nd col is conversion excess 500 - */ -static -Rune __toupper1[] = -{ - 0x00ff, 621, /* ÿ Ÿ */ - 0x0101, 499, /* ā Ā */ - 0x0103, 499, /* ă Ă */ - 0x0105, 499, /* ą Ą */ - 0x0107, 499, /* ć Ć */ - 0x0109, 499, /* ĉ Ĉ */ - 0x010b, 499, /* ċ Ċ */ - 0x010d, 499, /* č Č */ - 0x010f, 499, /* ď Ď */ - 0x0111, 499, /* đ Đ */ - 0x0113, 499, /* ē Ē */ - 0x0115, 499, /* ĕ Ĕ */ - 0x0117, 499, /* ė Ė */ - 0x0119, 499, /* ę Ę */ - 0x011b, 499, /* ě Ě */ - 0x011d, 499, /* ĝ Ĝ */ - 0x011f, 499, /* ğ Ğ */ - 0x0121, 499, /* ġ Ġ */ - 0x0123, 499, /* ģ Ģ */ - 0x0125, 499, /* ĥ Ĥ */ - 0x0127, 499, /* ħ Ħ */ - 0x0129, 499, /* ĩ Ĩ */ - 0x012b, 499, /* ī Ī */ - 0x012d, 499, /* ĭ Ĭ */ - 0x012f, 499, /* į Į */ - 0x0131, 268, /* ı I */ - 0x0133, 499, /* ij IJ */ - 0x0135, 499, /* ĵ Ĵ */ - 0x0137, 499, /* ķ Ķ */ - 0x013a, 499, /* ĺ Ĺ */ - 0x013c, 499, /* ļ Ļ */ - 0x013e, 499, /* ľ Ľ */ - 0x0140, 499, /* ŀ Ŀ */ - 0x0142, 499, /* ł Ł */ - 0x0144, 499, /* ń Ń */ - 0x0146, 499, /* ņ Ņ */ - 0x0148, 499, /* ň Ň */ - 0x014b, 499, /* ŋ Ŋ */ - 0x014d, 499, /* ō Ō */ - 0x014f, 499, /* ŏ Ŏ */ - 0x0151, 499, /* ő Ő */ - 0x0153, 499, /* œ Œ */ - 0x0155, 499, /* ŕ Ŕ */ - 0x0157, 499, /* ŗ Ŗ */ - 0x0159, 499, /* ř Ř */ - 0x015b, 499, /* ś Ś */ - 0x015d, 499, /* ŝ Ŝ */ - 0x015f, 499, /* ş Ş */ - 0x0161, 499, /* š Š */ - 0x0163, 499, /* ţ Ţ */ - 0x0165, 499, /* ť Ť */ - 0x0167, 499, /* ŧ Ŧ */ - 0x0169, 499, /* ũ Ũ */ - 0x016b, 499, /* ū Ū */ - 0x016d, 499, /* ŭ Ŭ */ - 0x016f, 499, /* ů Ů */ - 0x0171, 499, /* ű Ű */ - 0x0173, 499, /* ų Ų */ - 0x0175, 499, /* ŵ Ŵ */ - 0x0177, 499, /* ŷ Ŷ */ - 0x017a, 499, /* ź Ź */ - 0x017c, 499, /* ż Ż */ - 0x017e, 499, /* ž Ž */ - 0x017f, 200, /* ſ S */ - 0x0183, 499, /* ƃ Ƃ */ - 0x0185, 499, /* ƅ Ƅ */ - 0x0188, 499, /* ƈ Ƈ */ - 0x018c, 499, /* ƌ Ƌ */ - 0x0192, 499, /* ƒ Ƒ */ - 0x0199, 499, /* ƙ Ƙ */ - 0x01a1, 499, /* ơ Ơ */ - 0x01a3, 499, /* ƣ Ƣ */ - 0x01a5, 499, /* ƥ Ƥ */ - 0x01a8, 499, /* ƨ Ƨ */ - 0x01ad, 499, /* ƭ Ƭ */ - 0x01b0, 499, /* ư Ư */ - 0x01b4, 499, /* ƴ Ƴ */ - 0x01b6, 499, /* ƶ Ƶ */ - 0x01b9, 499, /* ƹ Ƹ */ - 0x01bd, 499, /* ƽ Ƽ */ - 0x01c5, 499, /* Dž DŽ */ - 0x01c6, 498, /* dž DŽ */ - 0x01c8, 499, /* Lj LJ */ - 0x01c9, 498, /* lj LJ */ - 0x01cb, 499, /* Nj NJ */ - 0x01cc, 498, /* nj NJ */ - 0x01ce, 499, /* ǎ Ǎ */ - 0x01d0, 499, /* ǐ Ǐ */ - 0x01d2, 499, /* ǒ Ǒ */ - 0x01d4, 499, /* ǔ Ǔ */ - 0x01d6, 499, /* ǖ Ǖ */ - 0x01d8, 499, /* ǘ Ǘ */ - 0x01da, 499, /* ǚ Ǚ */ - 0x01dc, 499, /* ǜ Ǜ */ - 0x01df, 499, /* ǟ Ǟ */ - 0x01e1, 499, /* ǡ Ǡ */ - 0x01e3, 499, /* ǣ Ǣ */ - 0x01e5, 499, /* ǥ Ǥ */ - 0x01e7, 499, /* ǧ Ǧ */ - 0x01e9, 499, /* ǩ Ǩ */ - 0x01eb, 499, /* ǫ Ǫ */ - 0x01ed, 499, /* ǭ Ǭ */ - 0x01ef, 499, /* ǯ Ǯ */ - 0x01f2, 499, /* Dz DZ */ - 0x01f3, 498, /* dz DZ */ - 0x01f5, 499, /* ǵ Ǵ */ - 0x01fb, 499, /* ǻ Ǻ */ - 0x01fd, 499, /* ǽ Ǽ */ - 0x01ff, 499, /* ǿ Ǿ */ - 0x0201, 499, /* ȁ Ȁ */ - 0x0203, 499, /* ȃ Ȃ */ - 0x0205, 499, /* ȅ Ȅ */ - 0x0207, 499, /* ȇ Ȇ */ - 0x0209, 499, /* ȉ Ȉ */ - 0x020b, 499, /* ȋ Ȋ */ - 0x020d, 499, /* ȍ Ȍ */ - 0x020f, 499, /* ȏ Ȏ */ - 0x0211, 499, /* ȑ Ȑ */ - 0x0213, 499, /* ȓ Ȓ */ - 0x0215, 499, /* ȕ Ȕ */ - 0x0217, 499, /* ȗ Ȗ */ - 0x0253, 290, /* ɓ Ɓ */ - 0x0254, 294, /* ɔ Ɔ */ - 0x025b, 297, /* ɛ Ɛ */ - 0x0260, 295, /* ɠ Ɠ */ - 0x0263, 293, /* ɣ Ɣ */ - 0x0268, 291, /* ɨ Ɨ */ - 0x0269, 289, /* ɩ Ɩ */ - 0x026f, 289, /* ɯ Ɯ */ - 0x0272, 287, /* ɲ Ɲ */ - 0x0283, 282, /* ʃ Ʃ */ - 0x0288, 282, /* ʈ Ʈ */ - 0x0292, 281, /* ʒ Ʒ */ - 0x03ac, 462, /* ά Ά */ - 0x03cc, 436, /* ό Ό */ - 0x03d0, 438, /* ϐ Β */ - 0x03d1, 443, /* ϑ Θ */ - 0x03d5, 453, /* ϕ Φ */ - 0x03d6, 446, /* ϖ Π */ - 0x03e3, 499, /* ϣ Ϣ */ - 0x03e5, 499, /* ϥ Ϥ */ - 0x03e7, 499, /* ϧ Ϧ */ - 0x03e9, 499, /* ϩ Ϩ */ - 0x03eb, 499, /* ϫ Ϫ */ - 0x03ed, 499, /* ϭ Ϭ */ - 0x03ef, 499, /* ϯ Ϯ */ - 0x03f0, 414, /* ϰ Κ */ - 0x03f1, 420, /* ϱ Ρ */ - 0x0461, 499, /* ѡ Ѡ */ - 0x0463, 499, /* ѣ Ѣ */ - 0x0465, 499, /* ѥ Ѥ */ - 0x0467, 499, /* ѧ Ѧ */ - 0x0469, 499, /* ѩ Ѩ */ - 0x046b, 499, /* ѫ Ѫ */ - 0x046d, 499, /* ѭ Ѭ */ - 0x046f, 499, /* ѯ Ѯ */ - 0x0471, 499, /* ѱ Ѱ */ - 0x0473, 499, /* ѳ Ѳ */ - 0x0475, 499, /* ѵ Ѵ */ - 0x0477, 499, /* ѷ Ѷ */ - 0x0479, 499, /* ѹ Ѹ */ - 0x047b, 499, /* ѻ Ѻ */ - 0x047d, 499, /* ѽ Ѽ */ - 0x047f, 499, /* ѿ Ѿ */ - 0x0481, 499, /* ҁ Ҁ */ - 0x0491, 499, /* ґ Ґ */ - 0x0493, 499, /* ғ Ғ */ - 0x0495, 499, /* ҕ Ҕ */ - 0x0497, 499, /* җ Җ */ - 0x0499, 499, /* ҙ Ҙ */ - 0x049b, 499, /* қ Қ */ - 0x049d, 499, /* ҝ Ҝ */ - 0x049f, 499, /* ҟ Ҟ */ - 0x04a1, 499, /* ҡ Ҡ */ - 0x04a3, 499, /* ң Ң */ - 0x04a5, 499, /* ҥ Ҥ */ - 0x04a7, 499, /* ҧ Ҧ */ - 0x04a9, 499, /* ҩ Ҩ */ - 0x04ab, 499, /* ҫ Ҫ */ - 0x04ad, 499, /* ҭ Ҭ */ - 0x04af, 499, /* ү Ү */ - 0x04b1, 499, /* ұ Ұ */ - 0x04b3, 499, /* ҳ Ҳ */ - 0x04b5, 499, /* ҵ Ҵ */ - 0x04b7, 499, /* ҷ Ҷ */ - 0x04b9, 499, /* ҹ Ҹ */ - 0x04bb, 499, /* һ Һ */ - 0x04bd, 499, /* ҽ Ҽ */ - 0x04bf, 499, /* ҿ Ҿ */ - 0x04c2, 499, /* ӂ Ӂ */ - 0x04c4, 499, /* ӄ Ӄ */ - 0x04c8, 499, /* ӈ Ӈ */ - 0x04cc, 499, /* ӌ Ӌ */ - 0x04d1, 499, /* ӑ Ӑ */ - 0x04d3, 499, /* ӓ Ӓ */ - 0x04d5, 499, /* ӕ Ӕ */ - 0x04d7, 499, /* ӗ Ӗ */ - 0x04d9, 499, /* ә Ә */ - 0x04db, 499, /* ӛ Ӛ */ - 0x04dd, 499, /* ӝ Ӝ */ - 0x04df, 499, /* ӟ Ӟ */ - 0x04e1, 499, /* ӡ Ӡ */ - 0x04e3, 499, /* ӣ Ӣ */ - 0x04e5, 499, /* ӥ Ӥ */ - 0x04e7, 499, /* ӧ Ӧ */ - 0x04e9, 499, /* ө Ө */ - 0x04eb, 499, /* ӫ Ӫ */ - 0x04ef, 499, /* ӯ Ӯ */ - 0x04f1, 499, /* ӱ Ӱ */ - 0x04f3, 499, /* ӳ Ӳ */ - 0x04f5, 499, /* ӵ Ӵ */ - 0x04f9, 499, /* ӹ Ӹ */ - 0x1e01, 499, /* ḁ Ḁ */ - 0x1e03, 499, /* ḃ Ḃ */ - 0x1e05, 499, /* ḅ Ḅ */ - 0x1e07, 499, /* ḇ Ḇ */ - 0x1e09, 499, /* ḉ Ḉ */ - 0x1e0b, 499, /* ḋ Ḋ */ - 0x1e0d, 499, /* ḍ Ḍ */ - 0x1e0f, 499, /* ḏ Ḏ */ - 0x1e11, 499, /* ḑ Ḑ */ - 0x1e13, 499, /* ḓ Ḓ */ - 0x1e15, 499, /* ḕ Ḕ */ - 0x1e17, 499, /* ḗ Ḗ */ - 0x1e19, 499, /* ḙ Ḙ */ - 0x1e1b, 499, /* ḛ Ḛ */ - 0x1e1d, 499, /* ḝ Ḝ */ - 0x1e1f, 499, /* ḟ Ḟ */ - 0x1e21, 499, /* ḡ Ḡ */ - 0x1e23, 499, /* ḣ Ḣ */ - 0x1e25, 499, /* ḥ Ḥ */ - 0x1e27, 499, /* ḧ Ḧ */ - 0x1e29, 499, /* ḩ Ḩ */ - 0x1e2b, 499, /* ḫ Ḫ */ - 0x1e2d, 499, /* ḭ Ḭ */ - 0x1e2f, 499, /* ḯ Ḯ */ - 0x1e31, 499, /* ḱ Ḱ */ - 0x1e33, 499, /* ḳ Ḳ */ - 0x1e35, 499, /* ḵ Ḵ */ - 0x1e37, 499, /* ḷ Ḷ */ - 0x1e39, 499, /* ḹ Ḹ */ - 0x1e3b, 499, /* ḻ Ḻ */ - 0x1e3d, 499, /* ḽ Ḽ */ - 0x1e3f, 499, /* ḿ Ḿ */ - 0x1e41, 499, /* ṁ Ṁ */ - 0x1e43, 499, /* ṃ Ṃ */ - 0x1e45, 499, /* ṅ Ṅ */ - 0x1e47, 499, /* ṇ Ṇ */ - 0x1e49, 499, /* ṉ Ṉ */ - 0x1e4b, 499, /* ṋ Ṋ */ - 0x1e4d, 499, /* ṍ Ṍ */ - 0x1e4f, 499, /* ṏ Ṏ */ - 0x1e51, 499, /* ṑ Ṑ */ - 0x1e53, 499, /* ṓ Ṓ */ - 0x1e55, 499, /* ṕ Ṕ */ - 0x1e57, 499, /* ṗ Ṗ */ - 0x1e59, 499, /* ṙ Ṙ */ - 0x1e5b, 499, /* ṛ Ṛ */ - 0x1e5d, 499, /* ṝ Ṝ */ - 0x1e5f, 499, /* ṟ Ṟ */ - 0x1e61, 499, /* ṡ Ṡ */ - 0x1e63, 499, /* ṣ Ṣ */ - 0x1e65, 499, /* ṥ Ṥ */ - 0x1e67, 499, /* ṧ Ṧ */ - 0x1e69, 499, /* ṩ Ṩ */ - 0x1e6b, 499, /* ṫ Ṫ */ - 0x1e6d, 499, /* ṭ Ṭ */ - 0x1e6f, 499, /* ṯ Ṯ */ - 0x1e71, 499, /* ṱ Ṱ */ - 0x1e73, 499, /* ṳ Ṳ */ - 0x1e75, 499, /* ṵ Ṵ */ - 0x1e77, 499, /* ṷ Ṷ */ - 0x1e79, 499, /* ṹ Ṹ */ - 0x1e7b, 499, /* ṻ Ṻ */ - 0x1e7d, 499, /* ṽ Ṽ */ - 0x1e7f, 499, /* ṿ Ṿ */ - 0x1e81, 499, /* ẁ Ẁ */ - 0x1e83, 499, /* ẃ Ẃ */ - 0x1e85, 499, /* ẅ Ẅ */ - 0x1e87, 499, /* ẇ Ẇ */ - 0x1e89, 499, /* ẉ Ẉ */ - 0x1e8b, 499, /* ẋ Ẋ */ - 0x1e8d, 499, /* ẍ Ẍ */ - 0x1e8f, 499, /* ẏ Ẏ */ - 0x1e91, 499, /* ẑ Ẑ */ - 0x1e93, 499, /* ẓ Ẓ */ - 0x1e95, 499, /* ẕ Ẕ */ - 0x1ea1, 499, /* ạ Ạ */ - 0x1ea3, 499, /* ả Ả */ - 0x1ea5, 499, /* ấ Ấ */ - 0x1ea7, 499, /* ầ Ầ */ - 0x1ea9, 499, /* ẩ Ẩ */ - 0x1eab, 499, /* ẫ Ẫ */ - 0x1ead, 499, /* ậ Ậ */ - 0x1eaf, 499, /* ắ Ắ */ - 0x1eb1, 499, /* ằ Ằ */ - 0x1eb3, 499, /* ẳ Ẳ */ - 0x1eb5, 499, /* ẵ Ẵ */ - 0x1eb7, 499, /* ặ Ặ */ - 0x1eb9, 499, /* ẹ Ẹ */ - 0x1ebb, 499, /* ẻ Ẻ */ - 0x1ebd, 499, /* ẽ Ẽ */ - 0x1ebf, 499, /* ế Ế */ - 0x1ec1, 499, /* ề Ề */ - 0x1ec3, 499, /* ể Ể */ - 0x1ec5, 499, /* ễ Ễ */ - 0x1ec7, 499, /* ệ Ệ */ - 0x1ec9, 499, /* ỉ Ỉ */ - 0x1ecb, 499, /* ị Ị */ - 0x1ecd, 499, /* ọ Ọ */ - 0x1ecf, 499, /* ỏ Ỏ */ - 0x1ed1, 499, /* ố Ố */ - 0x1ed3, 499, /* ồ Ồ */ - 0x1ed5, 499, /* ổ Ổ */ - 0x1ed7, 499, /* ỗ Ỗ */ - 0x1ed9, 499, /* ộ Ộ */ - 0x1edb, 499, /* ớ Ớ */ - 0x1edd, 499, /* ờ Ờ */ - 0x1edf, 499, /* ở Ở */ - 0x1ee1, 499, /* ỡ Ỡ */ - 0x1ee3, 499, /* ợ Ợ */ - 0x1ee5, 499, /* ụ Ụ */ - 0x1ee7, 499, /* ủ Ủ */ - 0x1ee9, 499, /* ứ Ứ */ - 0x1eeb, 499, /* ừ Ừ */ - 0x1eed, 499, /* ử Ử */ - 0x1eef, 499, /* ữ Ữ */ - 0x1ef1, 499, /* ự Ự */ - 0x1ef3, 499, /* ỳ Ỳ */ - 0x1ef5, 499, /* ỵ Ỵ */ - 0x1ef7, 499, /* ỷ Ỷ */ - 0x1ef9, 499, /* ỹ Ỹ */ - 0x1f51, 508, /* ὑ Ὑ */ - 0x1f53, 508, /* ὓ Ὓ */ - 0x1f55, 508, /* ὕ Ὕ */ - 0x1f57, 508, /* ὗ Ὗ */ - 0x1fb3, 509, /* ᾳ ᾼ */ - 0x1fc3, 509, /* ῃ ῌ */ - 0x1fe5, 507, /* ῥ Ῥ */ - 0x1ff3, 509, /* ῳ ῼ */ -}; - -/* - * upper case ranges - * 3rd col is conversion excess 500 - */ -static -Rune __tolower2[] = -{ - 0x0041, 0x005a, 532, /* A-Z a-z */ - 0x00c0, 0x00d6, 532, /* À-Ö à-ö */ - 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */ - 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */ - 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */ - 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */ - 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */ - 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */ - 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */ - 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */ - 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */ - 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */ - 0x0410, 0x042f, 532, /* А-Я а-я */ - 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */ - 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */ - 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */ - 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */ - 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */ - 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */ - 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */ - 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */ - 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */ - 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */ - 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */ - 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */ - 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */ - 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */ - 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */ - 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */ - 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */ - 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */ - 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */ - 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */ - 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */ - 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */ - 0xff21, 0xff3a, 532, /* A-Z a-z */ -}; - -/* - * upper case singlets - * 2nd col is conversion excess 500 - */ -static -Rune __tolower1[] = -{ - 0x0100, 501, /* Ā ā */ - 0x0102, 501, /* Ă ă */ - 0x0104, 501, /* Ą ą */ - 0x0106, 501, /* Ć ć */ - 0x0108, 501, /* Ĉ ĉ */ - 0x010a, 501, /* Ċ ċ */ - 0x010c, 501, /* Č č */ - 0x010e, 501, /* Ď ď */ - 0x0110, 501, /* Đ đ */ - 0x0112, 501, /* Ē ē */ - 0x0114, 501, /* Ĕ ĕ */ - 0x0116, 501, /* Ė ė */ - 0x0118, 501, /* Ę ę */ - 0x011a, 501, /* Ě ě */ - 0x011c, 501, /* Ĝ ĝ */ - 0x011e, 501, /* Ğ ğ */ - 0x0120, 501, /* Ġ ġ */ - 0x0122, 501, /* Ģ ģ */ - 0x0124, 501, /* Ĥ ĥ */ - 0x0126, 501, /* Ħ ħ */ - 0x0128, 501, /* Ĩ ĩ */ - 0x012a, 501, /* Ī ī */ - 0x012c, 501, /* Ĭ ĭ */ - 0x012e, 501, /* Į į */ - 0x0130, 301, /* İ i */ - 0x0132, 501, /* IJ ij */ - 0x0134, 501, /* Ĵ ĵ */ - 0x0136, 501, /* Ķ ķ */ - 0x0139, 501, /* Ĺ ĺ */ - 0x013b, 501, /* Ļ ļ */ - 0x013d, 501, /* Ľ ľ */ - 0x013f, 501, /* Ŀ ŀ */ - 0x0141, 501, /* Ł ł */ - 0x0143, 501, /* Ń ń */ - 0x0145, 501, /* Ņ ņ */ - 0x0147, 501, /* Ň ň */ - 0x014a, 501, /* Ŋ ŋ */ - 0x014c, 501, /* Ō ō */ - 0x014e, 501, /* Ŏ ŏ */ - 0x0150, 501, /* Ő ő */ - 0x0152, 501, /* Œ œ */ - 0x0154, 501, /* Ŕ ŕ */ - 0x0156, 501, /* Ŗ ŗ */ - 0x0158, 501, /* Ř ř */ - 0x015a, 501, /* Ś ś */ - 0x015c, 501, /* Ŝ ŝ */ - 0x015e, 501, /* Ş ş */ - 0x0160, 501, /* Š š */ - 0x0162, 501, /* Ţ ţ */ - 0x0164, 501, /* Ť ť */ - 0x0166, 501, /* Ŧ ŧ */ - 0x0168, 501, /* Ũ ũ */ - 0x016a, 501, /* Ū ū */ - 0x016c, 501, /* Ŭ ŭ */ - 0x016e, 501, /* Ů ů */ - 0x0170, 501, /* Ű ű */ - 0x0172, 501, /* Ų ų */ - 0x0174, 501, /* Ŵ ŵ */ - 0x0176, 501, /* Ŷ ŷ */ - 0x0178, 379, /* Ÿ ÿ */ - 0x0179, 501, /* Ź ź */ - 0x017b, 501, /* Ż ż */ - 0x017d, 501, /* Ž ž */ - 0x0181, 710, /* Ɓ ɓ */ - 0x0182, 501, /* Ƃ ƃ */ - 0x0184, 501, /* Ƅ ƅ */ - 0x0186, 706, /* Ɔ ɔ */ - 0x0187, 501, /* Ƈ ƈ */ - 0x018b, 501, /* Ƌ ƌ */ - 0x0190, 703, /* Ɛ ɛ */ - 0x0191, 501, /* Ƒ ƒ */ - 0x0193, 705, /* Ɠ ɠ */ - 0x0194, 707, /* Ɣ ɣ */ - 0x0196, 711, /* Ɩ ɩ */ - 0x0197, 709, /* Ɨ ɨ */ - 0x0198, 501, /* Ƙ ƙ */ - 0x019c, 711, /* Ɯ ɯ */ - 0x019d, 713, /* Ɲ ɲ */ - 0x01a0, 501, /* Ơ ơ */ - 0x01a2, 501, /* Ƣ ƣ */ - 0x01a4, 501, /* Ƥ ƥ */ - 0x01a7, 501, /* Ƨ ƨ */ - 0x01a9, 718, /* Ʃ ʃ */ - 0x01ac, 501, /* Ƭ ƭ */ - 0x01ae, 718, /* Ʈ ʈ */ - 0x01af, 501, /* Ư ư */ - 0x01b3, 501, /* Ƴ ƴ */ - 0x01b5, 501, /* Ƶ ƶ */ - 0x01b7, 719, /* Ʒ ʒ */ - 0x01b8, 501, /* Ƹ ƹ */ - 0x01bc, 501, /* Ƽ ƽ */ - 0x01c4, 502, /* DŽ dž */ - 0x01c5, 501, /* Dž dž */ - 0x01c7, 502, /* LJ lj */ - 0x01c8, 501, /* Lj lj */ - 0x01ca, 502, /* NJ nj */ - 0x01cb, 501, /* Nj nj */ - 0x01cd, 501, /* Ǎ ǎ */ - 0x01cf, 501, /* Ǐ ǐ */ - 0x01d1, 501, /* Ǒ ǒ */ - 0x01d3, 501, /* Ǔ ǔ */ - 0x01d5, 501, /* Ǖ ǖ */ - 0x01d7, 501, /* Ǘ ǘ */ - 0x01d9, 501, /* Ǚ ǚ */ - 0x01db, 501, /* Ǜ ǜ */ - 0x01de, 501, /* Ǟ ǟ */ - 0x01e0, 501, /* Ǡ ǡ */ - 0x01e2, 501, /* Ǣ ǣ */ - 0x01e4, 501, /* Ǥ ǥ */ - 0x01e6, 501, /* Ǧ ǧ */ - 0x01e8, 501, /* Ǩ ǩ */ - 0x01ea, 501, /* Ǫ ǫ */ - 0x01ec, 501, /* Ǭ ǭ */ - 0x01ee, 501, /* Ǯ ǯ */ - 0x01f1, 502, /* DZ dz */ - 0x01f2, 501, /* Dz dz */ - 0x01f4, 501, /* Ǵ ǵ */ - 0x01fa, 501, /* Ǻ ǻ */ - 0x01fc, 501, /* Ǽ ǽ */ - 0x01fe, 501, /* Ǿ ǿ */ - 0x0200, 501, /* Ȁ ȁ */ - 0x0202, 501, /* Ȃ ȃ */ - 0x0204, 501, /* Ȅ ȅ */ - 0x0206, 501, /* Ȇ ȇ */ - 0x0208, 501, /* Ȉ ȉ */ - 0x020a, 501, /* Ȋ ȋ */ - 0x020c, 501, /* Ȍ ȍ */ - 0x020e, 501, /* Ȏ ȏ */ - 0x0210, 501, /* Ȑ ȑ */ - 0x0212, 501, /* Ȓ ȓ */ - 0x0214, 501, /* Ȕ ȕ */ - 0x0216, 501, /* Ȗ ȗ */ - 0x0386, 538, /* Ά ά */ - 0x038c, 564, /* Ό ό */ - 0x03e2, 501, /* Ϣ ϣ */ - 0x03e4, 501, /* Ϥ ϥ */ - 0x03e6, 501, /* Ϧ ϧ */ - 0x03e8, 501, /* Ϩ ϩ */ - 0x03ea, 501, /* Ϫ ϫ */ - 0x03ec, 501, /* Ϭ ϭ */ - 0x03ee, 501, /* Ϯ ϯ */ - 0x0460, 501, /* Ѡ ѡ */ - 0x0462, 501, /* Ѣ ѣ */ - 0x0464, 501, /* Ѥ ѥ */ - 0x0466, 501, /* Ѧ ѧ */ - 0x0468, 501, /* Ѩ ѩ */ - 0x046a, 501, /* Ѫ ѫ */ - 0x046c, 501, /* Ѭ ѭ */ - 0x046e, 501, /* Ѯ ѯ */ - 0x0470, 501, /* Ѱ ѱ */ - 0x0472, 501, /* Ѳ ѳ */ - 0x0474, 501, /* Ѵ ѵ */ - 0x0476, 501, /* Ѷ ѷ */ - 0x0478, 501, /* Ѹ ѹ */ - 0x047a, 501, /* Ѻ ѻ */ - 0x047c, 501, /* Ѽ ѽ */ - 0x047e, 501, /* Ѿ ѿ */ - 0x0480, 501, /* Ҁ ҁ */ - 0x0490, 501, /* Ґ ґ */ - 0x0492, 501, /* Ғ ғ */ - 0x0494, 501, /* Ҕ ҕ */ - 0x0496, 501, /* Җ җ */ - 0x0498, 501, /* Ҙ ҙ */ - 0x049a, 501, /* Қ қ */ - 0x049c, 501, /* Ҝ ҝ */ - 0x049e, 501, /* Ҟ ҟ */ - 0x04a0, 501, /* Ҡ ҡ */ - 0x04a2, 501, /* Ң ң */ - 0x04a4, 501, /* Ҥ ҥ */ - 0x04a6, 501, /* Ҧ ҧ */ - 0x04a8, 501, /* Ҩ ҩ */ - 0x04aa, 501, /* Ҫ ҫ */ - 0x04ac, 501, /* Ҭ ҭ */ - 0x04ae, 501, /* Ү ү */ - 0x04b0, 501, /* Ұ ұ */ - 0x04b2, 501, /* Ҳ ҳ */ - 0x04b4, 501, /* Ҵ ҵ */ - 0x04b6, 501, /* Ҷ ҷ */ - 0x04b8, 501, /* Ҹ ҹ */ - 0x04ba, 501, /* Һ һ */ - 0x04bc, 501, /* Ҽ ҽ */ - 0x04be, 501, /* Ҿ ҿ */ - 0x04c1, 501, /* Ӂ ӂ */ - 0x04c3, 501, /* Ӄ ӄ */ - 0x04c7, 501, /* Ӈ ӈ */ - 0x04cb, 501, /* Ӌ ӌ */ - 0x04d0, 501, /* Ӑ ӑ */ - 0x04d2, 501, /* Ӓ ӓ */ - 0x04d4, 501, /* Ӕ ӕ */ - 0x04d6, 501, /* Ӗ ӗ */ - 0x04d8, 501, /* Ә ә */ - 0x04da, 501, /* Ӛ ӛ */ - 0x04dc, 501, /* Ӝ ӝ */ - 0x04de, 501, /* Ӟ ӟ */ - 0x04e0, 501, /* Ӡ ӡ */ - 0x04e2, 501, /* Ӣ ӣ */ - 0x04e4, 501, /* Ӥ ӥ */ - 0x04e6, 501, /* Ӧ ӧ */ - 0x04e8, 501, /* Ө ө */ - 0x04ea, 501, /* Ӫ ӫ */ - 0x04ee, 501, /* Ӯ ӯ */ - 0x04f0, 501, /* Ӱ ӱ */ - 0x04f2, 501, /* Ӳ ӳ */ - 0x04f4, 501, /* Ӵ ӵ */ - 0x04f8, 501, /* Ӹ ӹ */ - 0x1e00, 501, /* Ḁ ḁ */ - 0x1e02, 501, /* Ḃ ḃ */ - 0x1e04, 501, /* Ḅ ḅ */ - 0x1e06, 501, /* Ḇ ḇ */ - 0x1e08, 501, /* Ḉ ḉ */ - 0x1e0a, 501, /* Ḋ ḋ */ - 0x1e0c, 501, /* Ḍ ḍ */ - 0x1e0e, 501, /* Ḏ ḏ */ - 0x1e10, 501, /* Ḑ ḑ */ - 0x1e12, 501, /* Ḓ ḓ */ - 0x1e14, 501, /* Ḕ ḕ */ - 0x1e16, 501, /* Ḗ ḗ */ - 0x1e18, 501, /* Ḙ ḙ */ - 0x1e1a, 501, /* Ḛ ḛ */ - 0x1e1c, 501, /* Ḝ ḝ */ - 0x1e1e, 501, /* Ḟ ḟ */ - 0x1e20, 501, /* Ḡ ḡ */ - 0x1e22, 501, /* Ḣ ḣ */ - 0x1e24, 501, /* Ḥ ḥ */ - 0x1e26, 501, /* Ḧ ḧ */ - 0x1e28, 501, /* Ḩ ḩ */ - 0x1e2a, 501, /* Ḫ ḫ */ - 0x1e2c, 501, /* Ḭ ḭ */ - 0x1e2e, 501, /* Ḯ ḯ */ - 0x1e30, 501, /* Ḱ ḱ */ - 0x1e32, 501, /* Ḳ ḳ */ - 0x1e34, 501, /* Ḵ ḵ */ - 0x1e36, 501, /* Ḷ ḷ */ - 0x1e38, 501, /* Ḹ ḹ */ - 0x1e3a, 501, /* Ḻ ḻ */ - 0x1e3c, 501, /* Ḽ ḽ */ - 0x1e3e, 501, /* Ḿ ḿ */ - 0x1e40, 501, /* Ṁ ṁ */ - 0x1e42, 501, /* Ṃ ṃ */ - 0x1e44, 501, /* Ṅ ṅ */ - 0x1e46, 501, /* Ṇ ṇ */ - 0x1e48, 501, /* Ṉ ṉ */ - 0x1e4a, 501, /* Ṋ ṋ */ - 0x1e4c, 501, /* Ṍ ṍ */ - 0x1e4e, 501, /* Ṏ ṏ */ - 0x1e50, 501, /* Ṑ ṑ */ - 0x1e52, 501, /* Ṓ ṓ */ - 0x1e54, 501, /* Ṕ ṕ */ - 0x1e56, 501, /* Ṗ ṗ */ - 0x1e58, 501, /* Ṙ ṙ */ - 0x1e5a, 501, /* Ṛ ṛ */ - 0x1e5c, 501, /* Ṝ ṝ */ - 0x1e5e, 501, /* Ṟ ṟ */ - 0x1e60, 501, /* Ṡ ṡ */ - 0x1e62, 501, /* Ṣ ṣ */ - 0x1e64, 501, /* Ṥ ṥ */ - 0x1e66, 501, /* Ṧ ṧ */ - 0x1e68, 501, /* Ṩ ṩ */ - 0x1e6a, 501, /* Ṫ ṫ */ - 0x1e6c, 501, /* Ṭ ṭ */ - 0x1e6e, 501, /* Ṯ ṯ */ - 0x1e70, 501, /* Ṱ ṱ */ - 0x1e72, 501, /* Ṳ ṳ */ - 0x1e74, 501, /* Ṵ ṵ */ - 0x1e76, 501, /* Ṷ ṷ */ - 0x1e78, 501, /* Ṹ ṹ */ - 0x1e7a, 501, /* Ṻ ṻ */ - 0x1e7c, 501, /* Ṽ ṽ */ - 0x1e7e, 501, /* Ṿ ṿ */ - 0x1e80, 501, /* Ẁ ẁ */ - 0x1e82, 501, /* Ẃ ẃ */ - 0x1e84, 501, /* Ẅ ẅ */ - 0x1e86, 501, /* Ẇ ẇ */ - 0x1e88, 501, /* Ẉ ẉ */ - 0x1e8a, 501, /* Ẋ ẋ */ - 0x1e8c, 501, /* Ẍ ẍ */ - 0x1e8e, 501, /* Ẏ ẏ */ - 0x1e90, 501, /* Ẑ ẑ */ - 0x1e92, 501, /* Ẓ ẓ */ - 0x1e94, 501, /* Ẕ ẕ */ - 0x1ea0, 501, /* Ạ ạ */ - 0x1ea2, 501, /* Ả ả */ - 0x1ea4, 501, /* Ấ ấ */ - 0x1ea6, 501, /* Ầ ầ */ - 0x1ea8, 501, /* Ẩ ẩ */ - 0x1eaa, 501, /* Ẫ ẫ */ - 0x1eac, 501, /* Ậ ậ */ - 0x1eae, 501, /* Ắ ắ */ - 0x1eb0, 501, /* Ằ ằ */ - 0x1eb2, 501, /* Ẳ ẳ */ - 0x1eb4, 501, /* Ẵ ẵ */ - 0x1eb6, 501, /* Ặ ặ */ - 0x1eb8, 501, /* Ẹ ẹ */ - 0x1eba, 501, /* Ẻ ẻ */ - 0x1ebc, 501, /* Ẽ ẽ */ - 0x1ebe, 501, /* Ế ế */ - 0x1ec0, 501, /* Ề ề */ - 0x1ec2, 501, /* Ể ể */ - 0x1ec4, 501, /* Ễ ễ */ - 0x1ec6, 501, /* Ệ ệ */ - 0x1ec8, 501, /* Ỉ ỉ */ - 0x1eca, 501, /* Ị ị */ - 0x1ecc, 501, /* Ọ ọ */ - 0x1ece, 501, /* Ỏ ỏ */ - 0x1ed0, 501, /* Ố ố */ - 0x1ed2, 501, /* Ồ ồ */ - 0x1ed4, 501, /* Ổ ổ */ - 0x1ed6, 501, /* Ỗ ỗ */ - 0x1ed8, 501, /* Ộ ộ */ - 0x1eda, 501, /* Ớ ớ */ - 0x1edc, 501, /* Ờ ờ */ - 0x1ede, 501, /* Ở ở */ - 0x1ee0, 501, /* Ỡ ỡ */ - 0x1ee2, 501, /* Ợ ợ */ - 0x1ee4, 501, /* Ụ ụ */ - 0x1ee6, 501, /* Ủ ủ */ - 0x1ee8, 501, /* Ứ ứ */ - 0x1eea, 501, /* Ừ ừ */ - 0x1eec, 501, /* Ử ử */ - 0x1eee, 501, /* Ữ ữ */ - 0x1ef0, 501, /* Ự ự */ - 0x1ef2, 501, /* Ỳ ỳ */ - 0x1ef4, 501, /* Ỵ ỵ */ - 0x1ef6, 501, /* Ỷ ỷ */ - 0x1ef8, 501, /* Ỹ ỹ */ - 0x1f59, 492, /* Ὑ ὑ */ - 0x1f5b, 492, /* Ὓ ὓ */ - 0x1f5d, 492, /* Ὕ ὕ */ - 0x1f5f, 492, /* Ὗ ὗ */ - 0x1fbc, 491, /* ᾼ ᾳ */ - 0x1fcc, 491, /* ῌ ῃ */ - 0x1fec, 493, /* Ῥ ῥ */ - 0x1ffc, 491, /* ῼ ῳ */ -}; - -/* - * title characters are those between - * upper and lower case. ie DZ Dz dz - */ -static -Rune __totitle1[] = -{ - 0x01c4, 501, /* DŽ Dž */ - 0x01c6, 499, /* dž Dž */ - 0x01c7, 501, /* LJ Lj */ - 0x01c9, 499, /* lj Lj */ - 0x01ca, 501, /* NJ Nj */ - 0x01cc, 499, /* nj Nj */ - 0x01f1, 501, /* DZ Dz */ - 0x01f3, 499, /* dz Dz */ -}; - -static Rune* -bsearch(Rune c, Rune *t, int n, int ne) -{ - Rune *p; - int m; - - while(n > 1) { - m = n/2; - p = t + m*ne; - if(c >= p[0]) { - t = p; - n = n-m; - } else - n = m; - } - if(n && c >= t[0]) - return t; - return 0; -} - -Rune -tolowerrune(Rune c) -{ - Rune *p; - - p = bsearch(c, __tolower2, nelem(__tolower2)/3, 3); - if(p && c >= p[0] && c <= p[1]) - return c + p[2] - 500; - p = bsearch(c, __tolower1, nelem(__tolower1)/2, 2); - if(p && c == p[0]) - return c + p[1] - 500; - return c; -} - -Rune -toupperrune(Rune c) -{ - Rune *p; - - p = bsearch(c, __toupper2, nelem(__toupper2)/3, 3); - if(p && c >= p[0] && c <= p[1]) - return c + p[2] - 500; - p = bsearch(c, __toupper1, nelem(__toupper1)/2, 2); - if(p && c == p[0]) - return c + p[1] - 500; - return c; -} - -Rune -totitlerune(Rune c) -{ - Rune *p; - - p = bsearch(c, __totitle1, nelem(__totitle1)/2, 2); - if(p && c == p[0]) - return c + p[1] - 500; - return c; -} - -int -islowerrune(Rune c) -{ - Rune *p; - - p = bsearch(c, __toupper2, nelem(__toupper2)/3, 3); - if(p && c >= p[0] && c <= p[1]) - return 1; - p = bsearch(c, __toupper1, nelem(__toupper1)/2, 2); - if(p && c == p[0]) - return 1; - return 0; -} - -int -isupperrune(Rune c) -{ - Rune *p; - - p = bsearch(c, __tolower2, nelem(__tolower2)/3, 3); - if(p && c >= p[0] && c <= p[1]) - return 1; - p = bsearch(c, __tolower1, nelem(__tolower1)/2, 2); - if(p && c == p[0]) - return 1; - return 0; -} - -int -isalpharune(Rune c) -{ - Rune *p; - - if(isupperrune(c) || islowerrune(c)) - return 1; - p = bsearch(c, __alpha2, nelem(__alpha2)/2, 2); - if(p && c >= p[0] && c <= p[1]) - return 1; - p = bsearch(c, __alpha1, nelem(__alpha1), 1); - if(p && c == p[0]) - return 1; - return 0; -} - -int -istitlerune(Rune c) -{ - return isupperrune(c) && islowerrune(c); -} - -int -isspacerune(Rune c) -{ - Rune *p; - - p = bsearch(c, __space2, nelem(__space2)/2, 2); - if(p && c >= p[0] && c <= p[1]) - return 1; - return 0; -} diff --git a/libutf/utf.7 b/libutf/utf.7 @@ -1,99 +0,0 @@ -.deEX -.ift .ft5 -.nf -.. -.deEE -.ft1 -.fi -.. -.TH UTF 7 -.SH NAME -UTF, Unicode, ASCII, rune \- character set and format -.SH DESCRIPTION -The Plan 9 character set and representation are -based on the Unicode Standard and on the ISO multibyte -.SM UTF-8 -encoding (Universal Character -Set Transformation Format, 8 bits wide). -The Unicode Standard represents its characters in 16 -bits; -.SM UTF-8 -represents such -values in an 8-bit byte stream. -Throughout this manual, -.SM UTF-8 -is shortened to -.SM UTF. -.PP -In Plan 9, a -.I rune -is a 16-bit quantity representing a Unicode character. -Internally, programs may store characters as runes. -However, any external manifestation of textual information, -in files or at the interface between programs, uses a -machine-independent, byte-stream encoding called -.SM UTF. -.PP -.SM UTF -is designed so the 7-bit -.SM ASCII -set (values hexadecimal 00 to 7F), -appear only as themselves -in the encoding. -Runes with values above 7F appear as sequences of two or more -bytes with values only from 80 to FF. -.PP -The -.SM UTF -encoding of the Unicode Standard is backward compatible with -.SM ASCII\c -: -programs presented only with -.SM ASCII -work on Plan 9 -even if not written to deal with -.SM UTF, -as do -programs that deal with uninterpreted byte streams. -However, programs that perform semantic processing on -.SM ASCII -graphic -characters must convert from -.SM UTF -to runes -in order to work properly with non-\c -.SM ASCII -input. -See -.IR rune (3). -.PP -Letting numbers be binary, -a rune x is converted to a multibyte -.SM UTF -sequence -as follows: -.PP -01. x in [00000000.0bbbbbbb] → 0bbbbbbb -.br -10. x in [00000bbb.bbbbbbbb] → 110bbbbb, 10bbbbbb -.br -11. x in [bbbbbbbb.bbbbbbbb] → 1110bbbb, 10bbbbbb, 10bbbbbb -.br -.PP -Conversion 01 provides a one-byte sequence that spans the -.SM ASCII -character set in a compatible way. -Conversions 10 and 11 represent higher-valued characters -as sequences of two or three bytes with the high bit set. -Plan 9 does not support the 4, 5, and 6 byte sequences proposed by X-Open. -When there are multiple ways to encode a value, for example rune 0, -the shortest encoding is used. -.PP -In the inverse mapping, -any sequence except those described above -is incorrect and is converted to rune hexadecimal 0080. -.SH "SEE ALSO" -.IR ascii (1), -.IR tcs (1), -.IR rune (3), -.IR "The Unicode Standard" . diff --git a/libutf/utfecpy.c b/libutf/utfecpy.c @@ -1,36 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -char* -utfecpy(char *to, char *e, const char *from) -{ - char *end; - - if(to >= e) - return to; - end = memccpy(to, from, '\0', e - to); - if(end == nil){ - end = e-1; - while(end>to && (*--end&0xC0)==0x80) - ; - *end = '\0'; - }else{ - end--; - } - return end; -} diff --git a/libutf/utflen.c b/libutf/utflen.c @@ -1,37 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -int -utflen(const char *s) -{ - int c; - long n; - Rune rune; - - n = 0; - for(;;) { - c = *(uchar*)s; - if(c < Runeself) { - if(c == 0) - return n; - s++; - } else - s += chartorune(&rune, s); - n++; - } -} diff --git a/libutf/utfnlen.c b/libutf/utfnlen.c @@ -1,41 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -int -utfnlen(const char *s, long m) -{ - int c; - long n; - Rune rune; - const char *es; - - es = s + m; - for(n = 0; s < es; n++) { - c = *(uchar*)s; - if(c < Runeself){ - if(c == '\0') - break; - s++; - continue; - } - if(!fullrune(s, es-s)) - break; - s += chartorune(&rune, s); - } - return n; -} diff --git a/libutf/utfrrune.c b/libutf/utfrrune.c @@ -1,45 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -char* -utfrrune(const char *s, long c) -{ - long c1; - Rune r; - const char *s1; - - if(c < Runesync) /* not part of utf sequence */ - return strrchr(s, c); - - s1 = 0; - for(;;) { - c1 = *(uchar*)s; - if(c1 < Runeself) { /* one byte rune */ - if(c1 == 0) - return (char*)s1; - if(c1 == c) - s1 = s; - s++; - continue; - } - c1 = chartorune(&r, s); - if(r == c) - s1 = s; - s += c1; - } -} diff --git a/libutf/utfrune.c b/libutf/utfrune.c @@ -1,44 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - -char* -utfrune(const char *s, long c) -{ - long c1; - Rune r; - int n; - - if(c < Runesync) /* not part of utf sequence */ - return strchr(s, c); - - for(;;) { - c1 = *(uchar*)s; - if(c1 < Runeself) { /* one byte rune */ - if(c1 == 0) - return 0; - if(c1 == c) - return (char*)s; - s++; - continue; - } - n = chartorune(&r, s); - if(r == c) - return (char*)s; - s += n; - } -} diff --git a/libutf/utfutf.c b/libutf/utfutf.c @@ -1,41 +0,0 @@ -/* - * The authors of this software are Rob Pike and Ken Thompson. - * Copyright (c) 2002 by Lucent Technologies. - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE - * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - */ -#include <stdarg.h> -#include <string.h> -#include "plan9.h" -#include "utf.h" - - -/* - * Return pointer to first occurrence of s2 in s1, - * 0 if none - */ -char* -utfutf(const char *s1, const char *s2) -{ - const char *p; - long f, n1, n2; - Rune r; - - n1 = chartorune(&r, s2); - f = r; - if(f <= Runesync) /* represents self */ - return strstr(s1, s2); - - n2 = strlen(s2); - for(p=s1; p=utfrune(p, f); p+=n1) - if(strncmp(p, s2, n2) == 0) - return (char*)p; - return 0; -} diff --git a/libwmii_hack/Makefile b/libwmii_hack/Makefile @@ -1,17 +0,0 @@ -ROOT= .. -include ${ROOT}/mk/hdr.mk - -hack.o hack.o_pic: util.c hack.h x11.h - -CFLAGS += $(INCX11) -SOLDFLAGS += $(LIBX11) - -TARG = libwmii_hack -# Can't just link libstuff here. We need PIC objects. -OBJ = hack \ - ../libstuff/util/getbase \ - ../libstuff/util/getlong \ - ../libstuff/util/tokenize - -include ${ROOT}/mk/so.mk - diff --git a/libwmii_hack/hack.c b/libwmii_hack/hack.c @@ -1,133 +0,0 @@ -/* Copyright ©2008 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include "hack.h" -#include <dlfcn.h> -#include <stdbool.h> -#include <stdio.h> -#include <sys/time.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> - -#include "util.c" -#include "x11.c" - -enum { - Timeout = 10, -}; - -static void* xlib; - -static long transient; -static Atom types[32]; -static long ntypes; -static char** tags; -static long pid; -static long stime; -static char hostname[256]; -static long nsec; - -typedef Window (*mapfn)(Display*, Window); - -static Window (*mapwindow)(Display*, Window); -static Window (*mapraised)(Display*, Window); - -static void -init(Display *d) { /* Hrm... assumes one display... */ - char *toks[nelem(types)]; - char *s, *p; - long n; - int i; - - xlib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY); - if(xlib == nil) - return; - mapwindow = (mapfn)(uintptr_t)dlsym(xlib, "XMapWindow"); - mapraised = (mapfn)(uintptr_t)dlsym(xlib, "XMapRaised"); - - unsetenv("LD_PRELOAD"); - - if((s = getenv("WMII_HACK_TRANSIENT"))) { - if(getlong(s, &n)) - transient = n; - unsetenv("WMII_HACK_TRANSIENT"); - } - if((s = getenv("WMII_HACK_TYPE"))) { - s = strdup(s); - unsetenv("WMII_HACK_TYPE"); - - n = tokenize(toks, nelem(toks), s, ','); - for(i=0; i < n; i++) { - for(p=toks[i]; *p; p++) - if(*p >= 'a' && *p <= 'z') - *p += 'A' - 'a'; - toks[i] = smprint("_NET_WM_WINDOW_TYPE_%s", toks[i]); - } - XInternAtoms(d, toks, n, false, types); - ntypes = n; - for(i=0; i < n; i++) - free(toks[i]); - free(s); - } - if((s = getenv("WMII_HACK_TAGS"))) { - s = strdup(s); - unsetenv("WMII_HACK_TAGS"); - - n = tokenize(toks, nelem(toks)-1, s, '+'); - tags = strlistdup(toks, n); - free(s); - } - if((s = getenv("WMII_HACK_TIME"))) { - getlong(s, &stime); - unsetenv("WMII_HACK_TIME"); - } - - pid = getpid(); - gethostname(hostname, sizeof hostname); -} - -static void -setprops(Display *d, Window w) { - long *l; - - if(!xlib) - init(d); - - if(getprop_long(d, w, "_NET_WM_PID", "CARDINAL", 0L, &l, 1L)) - free(l); - else { - changeprop_long(d, w, "_NET_WM_PID", "CARDINAL", &pid, 1); - changeprop_string(d, w, "WM_CLIENT_MACHINE", hostname); - } - - /* Kludge. */ - if(nsec == 0) - nsec = time(0); - else if(time(0) > nsec + Timeout) - return; - - if(transient) - changeprop_long(d, w, "WM_TRANSIENT_FOR", "WINDOW", &transient, 1); - if(ntypes) - changeprop_long(d, w, "_NET_WM_WINDOW_TYPE", "ATOM", (long*)types, ntypes); - if(tags) - changeprop_textlist(d, w, "_WMII_TAGS", "UTF8_STRING", tags); - if(stime) - changeprop_long(d, w, "_WMII_LAUNCH_TIME", "CARDINAL", &stime, 1); -} - -int -XMapWindow(Display *d, Window w) { - - setprops(d, w); - return mapwindow(d, w); -} - -int -XMapRaised(Display *d, Window w) { - - setprops(d, w); - return mapraised(d, w); -} - diff --git a/libwmii_hack/hack.h b/libwmii_hack/hack.h @@ -1,28 +0,0 @@ - -typedef unsigned long ulong; -typedef unsigned int uint; -typedef unsigned char uchar; - -#define _XOPEN_SOURCE 600 -#define IXP_P9_STRUCTS -#define IXP_NO_P9_ -#include <assert.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <stuff/util.h> -#include <X11/Xlib.h> - -#define strdup my_strdup -#define smprint my_smprint -#define vsmprint my_vsmprint - -static char* smprint(const char*, ...); -static char* vsmprint(const char*, va_list); -static char* strdup(const char*); - -#define nil ((void*)0) -#define nelem(ary) (sizeof(ary) / sizeof(*ary)) - diff --git a/libwmii_hack/util.c b/libwmii_hack/util.c @@ -1,43 +0,0 @@ -#include <ctype.h> -#include <stdio.h> -#include <string.h> - -static char* -vsmprint(const char *fmt, va_list ap) { - va_list al; - char *buf = ""; - int n; - - va_copy(al, ap); - n = vsnprintf(buf, 0, fmt, al); - va_end(al); - - buf = malloc(++n); - if(buf) - vsnprintf(buf, n, fmt, ap); - return buf; -} - -static char* -smprint(const char *fmt, ...) { - va_list ap; - char *ret; - - va_start(ap, fmt); - ret = vsmprint(fmt, ap); - va_end(ap); - return ret; -} - -static char* -strdup(const char *s) { - char *ret; - int len; - - len = strlen(s)+1; - ret = malloc(len); - if(ret) - memcpy(ret, s, len); - return ret; -} - diff --git a/libwmii_hack/x11.c b/libwmii_hack/x11.c @@ -1,213 +0,0 @@ -/* Copyright ©2007 Kris Maglione <maglione.k at Gmail> - * See LICENSE file for license details. - */ -#include <assert.h> -#include "x11.h" - -/* Misc */ -static Atom -xatom(Display *display, char *name) { - /* Blech. I don't trust Xlib's cacheing. - MapEnt *e; - - e = hash_get(&amap, name, 1); - if(e->val == nil) - e->val = (void*)XInternAtom(display, name, False); - return (Atom)e->val; - */ - return XInternAtom(display, name, False); -} -/* Properties */ -#if 0 -static void -delproperty(Display *display, Window w, char *prop) { - XDeleteProperty(display, w, xatom(display, prop)); -} -#endif - -static void -changeproperty(Display *display, Window w, char *prop, char *type, int width, uchar data[], int n) { - XChangeProperty(display, w, xatom(display, prop), xatom(display, type), width, PropModeReplace, data, n); -} - -static void -changeprop_string(Display *display, Window w, char *prop, char *string) { - changeprop_char(display, w, prop, "UTF8_STRING", string, strlen(string)); -} - -static void -changeprop_char(Display *display, Window w, char *prop, char *type, char data[], int len) { - changeproperty(display, w, prop, type, 8, (uchar*)data, len); -} - -#if 0 -static void -changeprop_short(Display *display, Window w, char *prop, char *type, short data[], int len) { - changeproperty(display, w, prop, type, 16, (uchar*)data, len); -} -#endif - -static void -changeprop_long(Display *display, Window w, char *prop, char *type, long data[], int len) { - changeproperty(display, w, prop, type, 32, (uchar*)data, len); -} - -static void -changeprop_textlist(Display *display, Window w, char *prop, char *type, char *data[]) { - char **p, *s, *t; - int len, n; - - len = 0; - for(p=data; *p; p++) - len += strlen(*p) + 1; - s = malloc(len); - if(s == nil) - return; - t = s; - for(p=data; *p; p++) { - n = strlen(*p) + 1; - memcpy(t, *p, n); - t += n; - } - changeprop_char(display, w, prop, type, s, len); - free(s); -} - -#if 0 -static void -freestringlist(char *list[]) { - XFreeStringList(list); -} -#endif - -static ulong -getprop(Display *display, Window w, char *prop, char *type, Atom *actual, int *format, ulong offset, uchar **ret, ulong length) { - Atom typea; - ulong n, extra; - int status; - - typea = (type ? xatom(display, type) : 0L); - - status = XGetWindowProperty(display, w, - xatom(display, prop), offset, length, False /* delete */, - typea, actual, format, &n, &extra, ret); - - if(status != Success) { - *ret = nil; - return 0; - } - if(n == 0) { - free(*ret); - *ret = nil; - } - return n; -} - -#if 0 -static ulong -getproperty(Display *display, Window w, char *prop, char *type, Atom *actual, ulong offset, uchar **ret, ulong length) { - int format; - - return getprop(display, w, prop, type, actual, &format, offset, ret, length); -} -#endif - -static ulong -getprop_long(Display *display, Window w, char *prop, char *type, ulong offset, long **ret, ulong length) { - Atom actual; - ulong n; - int format; - - n = getprop(display, w, prop, type, &actual, &format, offset, (uchar**)ret, length); - if(n == 0 || format == 32 && xatom(display, type) == actual) - return n; - free(*ret); - *ret = 0; - return 0; -} - -#ifdef notdef -static char** -strlistdup(char *list[], int n) { - char **p, *q; - int i, m; - - for(i=0, m=0; i < n; i++) - m += strlen(list[i])+1; - - p = malloc((n+1)*sizeof(char*) + m); - if(p == nil) - return nil; - q = (char*)&p[n+1]; - - for(i=0; i < n; i++) { - p[i] = q; - m = strlen(list[i])+1; - memcpy(q, list[i], m); - q += m; - } - p[n] = nil; - return p; -} -#endif - -static char** -strlistdup(char *list[], int n) { - char **p, *q; - int i, m; - - m = 0; - for(i=0; i < n; i++) - m += strlen(list[i]) + 1; - - p = malloc((n+1) * sizeof(*p) + m); - q = (char*)&p[n+1]; - - for(i=0; i < n; i++) { - p[i] = q; - m = strlen(list[i]) + 1; - memcpy(q, list[i], m); - q += m; - } - p[n] = nil; - return p; -} - -#if 0 -static int -getprop_textlist(Display *display, Window w, char *name, char **ret[]) { - XTextProperty prop; - char **list; - int n; - - n = 0; - - XGetTextProperty(display, w, &prop, xatom(display, name)); - if(prop.nitems > 0) { - if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success) { - *ret = strlistdup(list, n); - XFreeStringList(list); - } - XFree(prop.value); - } - return n; -} -#endif - -#if 0 -static char* -getprop_string(Display *display, Window w, char *name) { - char **list, *str; - int n; - - str = nil; - - n = getprop_textlist(display, w, name, &list); - if(n > 0) - str = strdup(*list); - freestringlist(list); - - return str; -} -#endif - diff --git a/libwmii_hack/x11.h b/libwmii_hack/x11.h @@ -1,18 +0,0 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> - -static void changeprop_char(Display*, Window, char*, char*, char[], int); -static void changeprop_long(Display*, Window, char*, char*, long[], int); -/* static void changeprop_short(Display*, Window, char*, char*, short[], int); */ -static void changeprop_string(Display*, Window, char*, char*); -static void changeprop_textlist(Display*, Window, char*, char*, char*[]); -static void changeproperty(Display*, Window, char*, char*, int width, uchar*, int); -/* static void delproperty(Display*, Window, char*); */ -/* static void freestringlist(char**); */ -static ulong getprop_long(Display*, Window, char*, char*, ulong, long**, ulong); -/* static char* getprop_string(Display*, Window, char*); */ -/* static int getprop_textlist(Display*, Window, char*, char**[]); */ -/* static ulong getproperty(Display*, Window, char*, char*, Atom*, ulong, uchar**, ulong); */ -static Atom xatom(Display*, char*); - diff --git a/man/Makefile b/man/Makefile @@ -1,6 +1,6 @@ ROOT=.. -include ${ROOT}/mk/hdr.mk -include ${ROOT}/mk/wmii.mk +include $(ROOT)/mk/hdr.mk +include $(ROOT)/mk/wmii.mk TARG = wmii.1 \ wmiir.1 \ @@ -9,5 +9,5 @@ TARG = wmii.1 \ $(TARG): Makefile $(ROOT)/mk/wmii.mk header.t2t -include ${ROOT}/mk/man.mk +include $(ROOT)/mk/man.mk diff --git a/mk/hdr.mk b/mk/hdr.mk @@ -62,7 +62,7 @@ all: MAKEFILES=.depend .c.depend: echo MKDEP $< - [ -n "${noisycc}" ] && echo $(MKDEP) $(COMPILE_FLAGS) $< || true + [ -n "$(noisycc)" ] && echo $(MKDEP) $(COMPILE_FLAGS) $< || true eval "$(MKDEP) $(COMPILE_FLAGS)" $< >>.depend .sh.depend .rc.depend .1.depend .awk.depend: @@ -76,20 +76,20 @@ MAKEFILES=.depend .o.out: $(LINK) $@ $< .c.out: - $(COMPILE) ${<:.c=.o} $< - $(LINK) $@ ${<:.c=.o} + $(COMPILE) $(<:.c=.o) $< + $(LINK) $@ $(<:.c=.o) .rc.out .awk.out .sh.out: echo FILTER $(BASE)$< - [ -n "${<:%.sh=}" ] || $(BINSH) -n $< + [ -n "$(<:%.sh=)" ] || $(BINSH) -n $< set -e; \ - [ -n "${noisycc}" ] && set -x; \ + [ -n "$(noisycc)" ] && set -x; \ $(FILTER) $< >$@; \ chmod 0755 $@ .man1.1: echo TXT2TAGS $(BASE)$< - [ -n "${noisycc}" ] && set -x; \ + [ -n "$(noisycc)" ] && set -x; \ txt2tags -o- $< >$@ INSTALL= _install() { set -e; \ @@ -97,7 +97,7 @@ INSTALL= _install() { set -e; \ d=$$(dirname $$3); \ if [ ! -d $(DESTDIR)$$d ]; then echo MKDIR $$d; mkdir -p $(DESTDIR)$$d; fi; \ echo INSTALL $$($(CLEANNAME) $(BASE)$$2); \ - [ -n "${noisycc}" ] && set -x; \ + [ -n "$(noisycc)" ] && set -x; \ if [ "$$dashb" = -b ]; \ then cp -f $$2 $(DESTDIR)$$3; \ else $(FILTER) <$$2 >$(DESTDIR)$$3; \ @@ -107,7 +107,7 @@ INSTALL= _install() { set -e; \ }; _install UNINSTALL= _uninstall() { set -e; \ echo UNINSTALL $$($(CLEANNAME) $(BASE)$$2); \ - [ -n "${noisycc}" ] && set -x; \ + [ -n "$(noisycc)" ] && set -x; \ rm -f $(DESTDIR)$$3; \ }; _uninstall @@ -131,12 +131,12 @@ UNINSTALL= _uninstall() { set -e; \ .pdf.uninstall: $(UNINSTALL) $< $(DOC)/$< -INSTALMAN= _installman() { man=$${1\#\#*.}; $(INSTALL) 0644 $$1 $(MAN)/man$$man/$$1; }; _installman -UNINSTALLMAN=_uninstallman() { man=$${1\#\#*.}; $(UNINSTALL) $$1 $(MAN)/man$$man/$$1; }; _uninstallman +INSTALMAN= _installman() { man=$$(1\#\#*.); $(INSTALL) 0644 $$1 $(MAN)/man$$man/$$1; }; _installman +UNINSTALLMAN=_uninstallman() { man=$$(1\#\#*.); $(UNINSTALL) $$1 $(MAN)/man$$man/$$1; }; _uninstallman MANSECTIONS=1 2 3 4 5 6 7 8 9 -${MANSECTIONS:%=.%.install}: +$(MANSECTIONS:%=.%.install): $(INSTALMAN) $< -${MANSECTIONS:%=.%.uninstall}: +$(MANSECTIONS:%=.%.uninstall): $(UNINSTALL) $< .out.clean: diff --git a/mk/lib.mk b/mk/lib.mk @@ -1,13 +1,13 @@ PTARG = $(ROOT)/lib/$(TARG) LIB = $(PTARG).a -OFILES = ${OBJ:=.o} +OFILES = $(OBJ:=.o) all: $(HFILES) $(LIB) install: $(PTARG).install uninstall: $(PTARG).uninstall clean: libclean -depend: ${OBJ:=.depend} +depend: $(OBJ:=.depend) libclean: for i in $(LIB) $(OFILES); do \ @@ -26,7 +26,7 @@ $(LIB): $(OFILES) $(AR) $@ $(OFILES) SOMKSH=case "$(MAKESO)" in 1|[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) echo $(ROOT)/mk/so.mk;; *) echo /dev/null;; esac -SOMK:=${shell $(SOMKSH)} +SOMK:=$(shell $(SOMKSH)) SOMK!=$(SOMKSH) include $(SOMK) diff --git a/mk/man.mk b/mk/man.mk @@ -1,7 +1,7 @@ all: $(TARG) -install: ${TARG:.1=.install} -uninstall: ${TARG:.1=.uninstall} +install: $(TARG:.1=.install) +uninstall: $(TARG:.1=.uninstall) printinstall: echo 'Install directories:' diff --git a/mk/many.mk b/mk/many.mk @@ -1,10 +1,10 @@ -PROGS = ${TARG:=.out} +PROGS = $(TARG:=.out) all: $(OFILES) $(PROGS) -install: ${TARG:=.install} -uninstall: ${TARG:=.uninstall} -depend: ${OFILES:.o=.depend} ${TARG:=.depend} +install: $(TARG:=.install) +uninstall: $(TARG:=.uninstall) +depend: $(OFILES:.o=.depend) $(TARG:=.depend) clean: manyclean printinstall: @@ -12,7 +12,7 @@ printinstall: echo ' Bin: $(BIN)' manyclean: - for i in ${TARG:=.o} ${TARG:=.out} $(OFILES); do \ + for i in $(TARG:=.o) $(TARG:=.out) $(OFILES); do \ [ -e $$i ] && \ echo CLEAN $$($(CLEANNAME) $(BASE)$$i); \ rm -f $$i; \ diff --git a/mk/one.mk b/mk/one.mk @@ -1,12 +1,12 @@ PROG = $(TARG).out -OFILES = ${OBJ:=.o} +OFILES = $(OBJ:=.o) all: $(PROG) install: $(TARG).install uninstall: $(TARG).uninstall clean: oneclean -depend: ${OBJ:=.depend} +depend: $(OBJ:=.depend) printinstall: echo 'Install directories:' diff --git a/mk/so.mk b/mk/so.mk @@ -1,14 +1,14 @@ SOPTARG = $(ROOT)/lib/$(TARG) SO = $(SOPTARG).$(SOEXT) SONAME = $(TARG).$(SOEXT) -OFILES_PIC = ${OBJ:=.o_pic} +OFILES_PIC = $(OBJ:=.o_pic) all: $(HFILES) $(SO) install: $(SOPTARG).install uninstall: $(SOPTARG).uninstall clean: soclean -depend: ${OBJ:=.depend} +depend: $(OBJ:=.depend) soclean: for i in $(SO) $(OFILES_PIC); do \