From 8c20c4b329cc491b7faef0defe1b445ca73dd482 Mon Sep 17 00:00:00 2001 From: Kevin Lahey Date: Sun, 4 Apr 1993 00:00:00 +0000 Subject: [PATCH] Add the source code for /usr/src/usr.bin from the Net/2 tape This patch adds the source code for the /usr/src/usr.bin from the Net/2 release tape. It adds the following programs: error fpr fsplit gprof indent lastcomm look mt quota sccs tcopy tset vgrind vmstat window Kevin Lahey provided the fixes for most of the memory counters in vmstat, his work was based upon the work by Warren Toomey who wrote vstat. Rodney Grimes provided the interrupt counters and other fixes. It also includes the arnej patch for tset. AUTHOR: Rodney W. Grimes (rgrimes@agora.rain.com) AUTHOR: arnej ??? (tset fixes) AUTHOR: Kevin Lahey (kml%rokkaku.UUCP@mathcs.emory.edu) (vmstat memory counters) AUTHOR: Paul Kranenburg (pk@cs.few.eur.nl) vmstat dk_stat fix 386BSD-Patchkit: patch00124 --- usr/src/usr.bin/Makefile | 30 +- usr/src/usr.bin/error/Makefile | 6 + usr/src/usr.bin/error/error.1 | 304 +++++ usr/src/usr.bin/error/error.h | 224 ++++ usr/src/usr.bin/error/filter.c | 194 +++ usr/src/usr.bin/error/input.c | 548 ++++++++ usr/src/usr.bin/error/main.c | 287 +++++ usr/src/usr.bin/error/pathnames.h | 43 + usr/src/usr.bin/error/pi.c | 404 ++++++ usr/src/usr.bin/error/subr.c | 423 ++++++ usr/src/usr.bin/error/touch.c | 768 +++++++++++ usr/src/usr.bin/fpr/Makefile | 5 + usr/src/usr.bin/fpr/fpr.1 | 83 ++ usr/src/usr.bin/fpr/fpr.c | 410 ++++++ usr/src/usr.bin/fsplit/Makefile | 5 + usr/src/usr.bin/fsplit/fsplit.1 | 103 ++ usr/src/usr.bin/fsplit/fsplit.c | 408 ++++++ usr/src/usr.bin/gprof/Makefile | 13 + usr/src/usr.bin/gprof/arcs.c | 581 +++++++++ usr/src/usr.bin/gprof/dfn.c | 316 +++++ usr/src/usr.bin/gprof/gprof.1 | 273 ++++ usr/src/usr.bin/gprof/gprof.c | 710 +++++++++++ usr/src/usr.bin/gprof/gprof.callg | 108 ++ usr/src/usr.bin/gprof/gprof.flat | 32 + usr/src/usr.bin/gprof/gprof.h | 303 +++++ usr/src/usr.bin/gprof/hertz.c | 59 + usr/src/usr.bin/gprof/hp300.c | 11 + usr/src/usr.bin/gprof/hp300.h | 44 + usr/src/usr.bin/gprof/i386.c | 11 + usr/src/usr.bin/gprof/i386.h | 44 + usr/src/usr.bin/gprof/lookup.c | 110 ++ usr/src/usr.bin/gprof/pathnames.h | 38 + usr/src/usr.bin/gprof/printgprof.c | 718 +++++++++++ usr/src/usr.bin/gprof/printlist.c | 91 ++ usr/src/usr.bin/gprof/tahoe.c | 349 +++++ usr/src/usr.bin/gprof/tahoe.h | 59 + usr/src/usr.bin/gprof/vax.c | 347 +++++ usr/src/usr.bin/gprof/vax.h | 65 + usr/src/usr.bin/indent/Makefile | 6 + usr/src/usr.bin/indent/README | 97 ++ usr/src/usr.bin/indent/args.c | 300 +++++ usr/src/usr.bin/indent/indent.1 | 452 +++++++ usr/src/usr.bin/indent/indent.c | 1181 +++++++++++++++++ usr/src/usr.bin/indent/indent_codes.h | 69 + usr/src/usr.bin/indent/indent_globs.h | 310 +++++ usr/src/usr.bin/indent/io.c | 625 +++++++++ usr/src/usr.bin/indent/lexi.c | 559 ++++++++ usr/src/usr.bin/indent/parse.c | 324 +++++ usr/src/usr.bin/indent/pr_comment.c | 418 ++++++ usr/src/usr.bin/lastcomm/Makefile | 7 + usr/src/usr.bin/lastcomm/lastcomm.1 | 124 ++ usr/src/usr.bin/lastcomm/lastcomm.c | 271 ++++ usr/src/usr.bin/lastcomm/pathnames.h | 38 + usr/src/usr.bin/look/Makefile | 5 + usr/src/usr.bin/look/look.1 | 96 ++ usr/src/usr.bin/look/look.c | 340 +++++ usr/src/usr.bin/look/pathnames.h | 36 + usr/src/usr.bin/mt/Makefile | 6 + usr/src/usr.bin/mt/mt.1 | 130 ++ usr/src/usr.bin/mt/mt.c | 226 ++++ usr/src/usr.bin/quota/Makefile | 7 + usr/src/usr.bin/quota/quota.1 | 131 ++ usr/src/usr.bin/quota/quota.c | 510 ++++++++ usr/src/usr.bin/sccs/Makefile | 5 + usr/src/usr.bin/sccs/pathnames.h | 51 + usr/src/usr.bin/sccs/sccs.1 | 398 ++++++ usr/src/usr.bin/sccs/sccs.c | 1623 ++++++++++++++++++++++++ usr/src/usr.bin/tcopy/Makefile | 5 + usr/src/usr.bin/tcopy/pathnames.h | 36 + usr/src/usr.bin/tcopy/tcopy.1 | 83 ++ usr/src/usr.bin/tcopy/tcopy.c | 312 +++++ usr/src/usr.bin/tset/Makefile | 11 + usr/src/usr.bin/tset/extern.h | 60 + usr/src/usr.bin/tset/map.c | 263 ++++ usr/src/usr.bin/tset/misc.c | 98 ++ usr/src/usr.bin/tset/set.c | 320 +++++ usr/src/usr.bin/tset/term.c | 138 ++ usr/src/usr.bin/tset/tset.1 | 370 ++++++ usr/src/usr.bin/tset/tset.c | 304 +++++ usr/src/usr.bin/tset/wrterm.c | 112 ++ usr/src/usr.bin/vgrind/Makefile | 17 + usr/src/usr.bin/vgrind/pathnames.h | 36 + usr/src/usr.bin/vgrind/regexp.c | 582 +++++++++ usr/src/usr.bin/vgrind/retest/Makefile | 10 + usr/src/usr.bin/vgrind/retest/retest.c | 105 ++ usr/src/usr.bin/vgrind/tmac.vgrind | 68 + usr/src/usr.bin/vgrind/vfontedpr.c | 703 ++++++++++ usr/src/usr.bin/vgrind/vgrind.1 | 225 ++++ usr/src/usr.bin/vgrind/vgrind.sh | 143 +++ usr/src/usr.bin/vgrind/vgrindefs.5 | 158 +++ usr/src/usr.bin/vgrind/vgrindefs.c | 326 +++++ usr/src/usr.bin/vgrind/vgrindefs.src | 146 +++ usr/src/usr.bin/vmstat/Makefile | 11 + usr/src/usr.bin/vmstat/names.c | 221 ++++ usr/src/usr.bin/vmstat/vmstat.8 | 206 +++ usr/src/usr.bin/vmstat/vmstat.c | 868 +++++++++++++ usr/src/usr.bin/window/:tt | 11 + usr/src/usr.bin/window/:tty | 6 + usr/src/usr.bin/window/:var | 2 + usr/src/usr.bin/window/:ww | 19 + usr/src/usr.bin/window/Makefile | 21 + usr/src/usr.bin/window/README | 194 +++ usr/src/usr.bin/window/alias.h | 52 + usr/src/usr.bin/window/char.c | 150 +++ usr/src/usr.bin/window/char.h | 61 + usr/src/usr.bin/window/cmd.c | 293 +++++ usr/src/usr.bin/window/cmd1.c | 172 +++ usr/src/usr.bin/window/cmd2.c | 152 +++ usr/src/usr.bin/window/cmd3.c | 65 + usr/src/usr.bin/window/cmd4.c | 56 + usr/src/usr.bin/window/cmd5.c | 129 ++ usr/src/usr.bin/window/cmd6.c | 110 ++ usr/src/usr.bin/window/cmd7.c | 84 ++ usr/src/usr.bin/window/compress.c | 889 +++++++++++++ usr/src/usr.bin/window/context.c | 129 ++ usr/src/usr.bin/window/context.h | 83 ++ usr/src/usr.bin/window/defs.h | 71 ++ usr/src/usr.bin/window/error.c | 95 ++ usr/src/usr.bin/window/lcmd.c | 154 +++ usr/src/usr.bin/window/lcmd.h | 61 + usr/src/usr.bin/window/lcmd1.c | 429 +++++++ usr/src/usr.bin/window/lcmd2.c | 395 ++++++ usr/src/usr.bin/window/local.h | 45 + usr/src/usr.bin/window/main.c | 196 +++ usr/src/usr.bin/window/mloop.c | 77 ++ usr/src/usr.bin/window/parser.h | 47 + usr/src/usr.bin/window/parser1.c | 222 ++++ usr/src/usr.bin/window/parser2.c | 231 ++++ usr/src/usr.bin/window/parser3.c | 191 +++ usr/src/usr.bin/window/parser4.c | 296 +++++ usr/src/usr.bin/window/parser5.c | 201 +++ usr/src/usr.bin/window/scanner.c | 572 +++++++++ usr/src/usr.bin/window/startup.c | 92 ++ usr/src/usr.bin/window/string.c | 153 +++ usr/src/usr.bin/window/string.h | 65 + usr/src/usr.bin/window/token.h | 83 ++ usr/src/usr.bin/window/tt.h | 147 +++ usr/src/usr.bin/window/ttf100.c | 69 + usr/src/usr.bin/window/ttgeneric.c | 549 ++++++++ usr/src/usr.bin/window/tth19.c | 278 ++++ usr/src/usr.bin/window/tth29.c | 94 ++ usr/src/usr.bin/window/ttinit.c | 121 ++ usr/src/usr.bin/window/ttoutput.c | 138 ++ usr/src/usr.bin/window/tttermcap.c | 117 ++ usr/src/usr.bin/window/tttvi925.c | 64 + usr/src/usr.bin/window/ttwyse60.c | 76 ++ usr/src/usr.bin/window/ttwyse75.c | 76 ++ usr/src/usr.bin/window/ttzapple.c | 365 ++++++ usr/src/usr.bin/window/ttzentec.c | 66 + usr/src/usr.bin/window/value.h | 53 + usr/src/usr.bin/window/var.c | 157 +++ usr/src/usr.bin/window/var.h | 58 + usr/src/usr.bin/window/win.c | 370 ++++++ usr/src/usr.bin/window/window.1 | 940 ++++++++++++++ usr/src/usr.bin/window/windowrc | 85 ++ usr/src/usr.bin/window/ww.h | 310 +++++ usr/src/usr.bin/window/wwadd.c | 88 ++ usr/src/usr.bin/window/wwalloc.c | 71 ++ usr/src/usr.bin/window/wwbox.c | 66 + usr/src/usr.bin/window/wwchild.c | 71 ++ usr/src/usr.bin/window/wwclose.c | 59 + usr/src/usr.bin/window/wwclreol.c | 95 ++ usr/src/usr.bin/window/wwclreos.c | 55 + usr/src/usr.bin/window/wwcursor.c | 92 ++ usr/src/usr.bin/window/wwdata.c | 39 + usr/src/usr.bin/window/wwdelchar.c | 123 ++ usr/src/usr.bin/window/wwdelete.c | 139 ++ usr/src/usr.bin/window/wwdelline.c | 88 ++ usr/src/usr.bin/window/wwdump.c | 114 ++ usr/src/usr.bin/window/wwend.c | 48 + usr/src/usr.bin/window/wwenviron.c | 103 ++ usr/src/usr.bin/window/wwerror.c | 69 + usr/src/usr.bin/window/wwflush.c | 58 + usr/src/usr.bin/window/wwframe.c | 249 ++++ usr/src/usr.bin/window/wwgets.c | 109 ++ usr/src/usr.bin/window/wwinit.c | 332 +++++ usr/src/usr.bin/window/wwinschar.c | 130 ++ usr/src/usr.bin/window/wwinsline.c | 88 ++ usr/src/usr.bin/window/wwiomux.c | 199 +++ usr/src/usr.bin/window/wwlabel.c | 96 ++ usr/src/usr.bin/window/wwmisc.c | 67 + usr/src/usr.bin/window/wwmove.c | 98 ++ usr/src/usr.bin/window/wwopen.c | 185 +++ usr/src/usr.bin/window/wwprintf.c | 57 + usr/src/usr.bin/window/wwpty.c | 85 ++ usr/src/usr.bin/window/wwputc.c | 48 + usr/src/usr.bin/window/wwputs.c | 52 + usr/src/usr.bin/window/wwredraw.c | 56 + usr/src/usr.bin/window/wwredrawwin.c | 73 ++ usr/src/usr.bin/window/wwrint.c | 73 ++ usr/src/usr.bin/window/wwscroll.c | 234 ++++ usr/src/usr.bin/window/wwsize.c | 191 +++ usr/src/usr.bin/window/wwspawn.c | 85 ++ usr/src/usr.bin/window/wwsuspend.c | 59 + usr/src/usr.bin/window/wwtty.c | 180 +++ usr/src/usr.bin/window/wwunframe.c | 76 ++ usr/src/usr.bin/window/wwupdate.c | 271 ++++ usr/src/usr.bin/window/wwwrite.c | 298 +++++ usr/src/usr.bin/window/xx.c | 244 ++++ usr/src/usr.bin/window/xx.h | 58 + usr/src/usr.bin/window/xxflush.c | 196 +++ 201 files changed, 38551 insertions(+), 12 deletions(-) create mode 100644 usr/src/usr.bin/error/Makefile create mode 100644 usr/src/usr.bin/error/error.1 create mode 100644 usr/src/usr.bin/error/error.h create mode 100644 usr/src/usr.bin/error/filter.c create mode 100644 usr/src/usr.bin/error/input.c create mode 100644 usr/src/usr.bin/error/main.c create mode 100644 usr/src/usr.bin/error/pathnames.h create mode 100644 usr/src/usr.bin/error/pi.c create mode 100644 usr/src/usr.bin/error/subr.c create mode 100644 usr/src/usr.bin/error/touch.c create mode 100644 usr/src/usr.bin/fpr/Makefile create mode 100644 usr/src/usr.bin/fpr/fpr.1 create mode 100644 usr/src/usr.bin/fpr/fpr.c create mode 100644 usr/src/usr.bin/fsplit/Makefile create mode 100644 usr/src/usr.bin/fsplit/fsplit.1 create mode 100644 usr/src/usr.bin/fsplit/fsplit.c create mode 100644 usr/src/usr.bin/gprof/Makefile create mode 100644 usr/src/usr.bin/gprof/arcs.c create mode 100644 usr/src/usr.bin/gprof/dfn.c create mode 100644 usr/src/usr.bin/gprof/gprof.1 create mode 100644 usr/src/usr.bin/gprof/gprof.c create mode 100644 usr/src/usr.bin/gprof/gprof.callg create mode 100644 usr/src/usr.bin/gprof/gprof.flat create mode 100644 usr/src/usr.bin/gprof/gprof.h create mode 100644 usr/src/usr.bin/gprof/hertz.c create mode 100644 usr/src/usr.bin/gprof/hp300.c create mode 100644 usr/src/usr.bin/gprof/hp300.h create mode 100644 usr/src/usr.bin/gprof/i386.c create mode 100644 usr/src/usr.bin/gprof/i386.h create mode 100644 usr/src/usr.bin/gprof/lookup.c create mode 100644 usr/src/usr.bin/gprof/pathnames.h create mode 100644 usr/src/usr.bin/gprof/printgprof.c create mode 100644 usr/src/usr.bin/gprof/printlist.c create mode 100644 usr/src/usr.bin/gprof/tahoe.c create mode 100644 usr/src/usr.bin/gprof/tahoe.h create mode 100644 usr/src/usr.bin/gprof/vax.c create mode 100644 usr/src/usr.bin/gprof/vax.h create mode 100644 usr/src/usr.bin/indent/Makefile create mode 100644 usr/src/usr.bin/indent/README create mode 100644 usr/src/usr.bin/indent/args.c create mode 100644 usr/src/usr.bin/indent/indent.1 create mode 100644 usr/src/usr.bin/indent/indent.c create mode 100644 usr/src/usr.bin/indent/indent_codes.h create mode 100644 usr/src/usr.bin/indent/indent_globs.h create mode 100644 usr/src/usr.bin/indent/io.c create mode 100644 usr/src/usr.bin/indent/lexi.c create mode 100644 usr/src/usr.bin/indent/parse.c create mode 100644 usr/src/usr.bin/indent/pr_comment.c create mode 100644 usr/src/usr.bin/lastcomm/Makefile create mode 100644 usr/src/usr.bin/lastcomm/lastcomm.1 create mode 100644 usr/src/usr.bin/lastcomm/lastcomm.c create mode 100644 usr/src/usr.bin/lastcomm/pathnames.h create mode 100644 usr/src/usr.bin/look/Makefile create mode 100644 usr/src/usr.bin/look/look.1 create mode 100644 usr/src/usr.bin/look/look.c create mode 100644 usr/src/usr.bin/look/pathnames.h create mode 100644 usr/src/usr.bin/mt/Makefile create mode 100644 usr/src/usr.bin/mt/mt.1 create mode 100644 usr/src/usr.bin/mt/mt.c create mode 100644 usr/src/usr.bin/quota/Makefile create mode 100644 usr/src/usr.bin/quota/quota.1 create mode 100644 usr/src/usr.bin/quota/quota.c create mode 100644 usr/src/usr.bin/sccs/Makefile create mode 100644 usr/src/usr.bin/sccs/pathnames.h create mode 100644 usr/src/usr.bin/sccs/sccs.1 create mode 100644 usr/src/usr.bin/sccs/sccs.c create mode 100644 usr/src/usr.bin/tcopy/Makefile create mode 100644 usr/src/usr.bin/tcopy/pathnames.h create mode 100644 usr/src/usr.bin/tcopy/tcopy.1 create mode 100644 usr/src/usr.bin/tcopy/tcopy.c create mode 100644 usr/src/usr.bin/tset/Makefile create mode 100644 usr/src/usr.bin/tset/extern.h create mode 100644 usr/src/usr.bin/tset/map.c create mode 100644 usr/src/usr.bin/tset/misc.c create mode 100644 usr/src/usr.bin/tset/set.c create mode 100644 usr/src/usr.bin/tset/term.c create mode 100644 usr/src/usr.bin/tset/tset.1 create mode 100644 usr/src/usr.bin/tset/tset.c create mode 100644 usr/src/usr.bin/tset/wrterm.c create mode 100644 usr/src/usr.bin/vgrind/Makefile create mode 100644 usr/src/usr.bin/vgrind/pathnames.h create mode 100644 usr/src/usr.bin/vgrind/regexp.c create mode 100644 usr/src/usr.bin/vgrind/retest/Makefile create mode 100644 usr/src/usr.bin/vgrind/retest/retest.c create mode 100644 usr/src/usr.bin/vgrind/tmac.vgrind create mode 100644 usr/src/usr.bin/vgrind/vfontedpr.c create mode 100644 usr/src/usr.bin/vgrind/vgrind.1 create mode 100644 usr/src/usr.bin/vgrind/vgrind.sh create mode 100644 usr/src/usr.bin/vgrind/vgrindefs.5 create mode 100644 usr/src/usr.bin/vgrind/vgrindefs.c create mode 100644 usr/src/usr.bin/vgrind/vgrindefs.src create mode 100644 usr/src/usr.bin/vmstat/Makefile create mode 100644 usr/src/usr.bin/vmstat/names.c create mode 100644 usr/src/usr.bin/vmstat/vmstat.8 create mode 100644 usr/src/usr.bin/vmstat/vmstat.c create mode 100644 usr/src/usr.bin/window/:tt create mode 100644 usr/src/usr.bin/window/:tty create mode 100644 usr/src/usr.bin/window/:var create mode 100644 usr/src/usr.bin/window/:ww create mode 100644 usr/src/usr.bin/window/Makefile create mode 100644 usr/src/usr.bin/window/README create mode 100644 usr/src/usr.bin/window/alias.h create mode 100644 usr/src/usr.bin/window/char.c create mode 100644 usr/src/usr.bin/window/char.h create mode 100644 usr/src/usr.bin/window/cmd.c create mode 100644 usr/src/usr.bin/window/cmd1.c create mode 100644 usr/src/usr.bin/window/cmd2.c create mode 100644 usr/src/usr.bin/window/cmd3.c create mode 100644 usr/src/usr.bin/window/cmd4.c create mode 100644 usr/src/usr.bin/window/cmd5.c create mode 100644 usr/src/usr.bin/window/cmd6.c create mode 100644 usr/src/usr.bin/window/cmd7.c create mode 100644 usr/src/usr.bin/window/compress.c create mode 100644 usr/src/usr.bin/window/context.c create mode 100644 usr/src/usr.bin/window/context.h create mode 100644 usr/src/usr.bin/window/defs.h create mode 100644 usr/src/usr.bin/window/error.c create mode 100644 usr/src/usr.bin/window/lcmd.c create mode 100644 usr/src/usr.bin/window/lcmd.h create mode 100644 usr/src/usr.bin/window/lcmd1.c create mode 100644 usr/src/usr.bin/window/lcmd2.c create mode 100644 usr/src/usr.bin/window/local.h create mode 100644 usr/src/usr.bin/window/main.c create mode 100644 usr/src/usr.bin/window/mloop.c create mode 100644 usr/src/usr.bin/window/parser.h create mode 100644 usr/src/usr.bin/window/parser1.c create mode 100644 usr/src/usr.bin/window/parser2.c create mode 100644 usr/src/usr.bin/window/parser3.c create mode 100644 usr/src/usr.bin/window/parser4.c create mode 100644 usr/src/usr.bin/window/parser5.c create mode 100644 usr/src/usr.bin/window/scanner.c create mode 100644 usr/src/usr.bin/window/startup.c create mode 100644 usr/src/usr.bin/window/string.c create mode 100644 usr/src/usr.bin/window/string.h create mode 100644 usr/src/usr.bin/window/token.h create mode 100644 usr/src/usr.bin/window/tt.h create mode 100644 usr/src/usr.bin/window/ttf100.c create mode 100644 usr/src/usr.bin/window/ttgeneric.c create mode 100644 usr/src/usr.bin/window/tth19.c create mode 100644 usr/src/usr.bin/window/tth29.c create mode 100644 usr/src/usr.bin/window/ttinit.c create mode 100644 usr/src/usr.bin/window/ttoutput.c create mode 100644 usr/src/usr.bin/window/tttermcap.c create mode 100644 usr/src/usr.bin/window/tttvi925.c create mode 100644 usr/src/usr.bin/window/ttwyse60.c create mode 100644 usr/src/usr.bin/window/ttwyse75.c create mode 100644 usr/src/usr.bin/window/ttzapple.c create mode 100644 usr/src/usr.bin/window/ttzentec.c create mode 100644 usr/src/usr.bin/window/value.h create mode 100644 usr/src/usr.bin/window/var.c create mode 100644 usr/src/usr.bin/window/var.h create mode 100644 usr/src/usr.bin/window/win.c create mode 100644 usr/src/usr.bin/window/window.1 create mode 100644 usr/src/usr.bin/window/windowrc create mode 100644 usr/src/usr.bin/window/ww.h create mode 100644 usr/src/usr.bin/window/wwadd.c create mode 100644 usr/src/usr.bin/window/wwalloc.c create mode 100644 usr/src/usr.bin/window/wwbox.c create mode 100644 usr/src/usr.bin/window/wwchild.c create mode 100644 usr/src/usr.bin/window/wwclose.c create mode 100644 usr/src/usr.bin/window/wwclreol.c create mode 100644 usr/src/usr.bin/window/wwclreos.c create mode 100644 usr/src/usr.bin/window/wwcursor.c create mode 100644 usr/src/usr.bin/window/wwdata.c create mode 100644 usr/src/usr.bin/window/wwdelchar.c create mode 100644 usr/src/usr.bin/window/wwdelete.c create mode 100644 usr/src/usr.bin/window/wwdelline.c create mode 100644 usr/src/usr.bin/window/wwdump.c create mode 100644 usr/src/usr.bin/window/wwend.c create mode 100644 usr/src/usr.bin/window/wwenviron.c create mode 100644 usr/src/usr.bin/window/wwerror.c create mode 100644 usr/src/usr.bin/window/wwflush.c create mode 100644 usr/src/usr.bin/window/wwframe.c create mode 100644 usr/src/usr.bin/window/wwgets.c create mode 100644 usr/src/usr.bin/window/wwinit.c create mode 100644 usr/src/usr.bin/window/wwinschar.c create mode 100644 usr/src/usr.bin/window/wwinsline.c create mode 100644 usr/src/usr.bin/window/wwiomux.c create mode 100644 usr/src/usr.bin/window/wwlabel.c create mode 100644 usr/src/usr.bin/window/wwmisc.c create mode 100644 usr/src/usr.bin/window/wwmove.c create mode 100644 usr/src/usr.bin/window/wwopen.c create mode 100644 usr/src/usr.bin/window/wwprintf.c create mode 100644 usr/src/usr.bin/window/wwpty.c create mode 100644 usr/src/usr.bin/window/wwputc.c create mode 100644 usr/src/usr.bin/window/wwputs.c create mode 100644 usr/src/usr.bin/window/wwredraw.c create mode 100644 usr/src/usr.bin/window/wwredrawwin.c create mode 100644 usr/src/usr.bin/window/wwrint.c create mode 100644 usr/src/usr.bin/window/wwscroll.c create mode 100644 usr/src/usr.bin/window/wwsize.c create mode 100644 usr/src/usr.bin/window/wwspawn.c create mode 100644 usr/src/usr.bin/window/wwsuspend.c create mode 100644 usr/src/usr.bin/window/wwtty.c create mode 100644 usr/src/usr.bin/window/wwunframe.c create mode 100644 usr/src/usr.bin/window/wwupdate.c create mode 100644 usr/src/usr.bin/window/wwwrite.c create mode 100644 usr/src/usr.bin/window/xx.c create mode 100644 usr/src/usr.bin/window/xx.h create mode 100644 usr/src/usr.bin/window/xxflush.c diff --git a/usr/src/usr.bin/Makefile b/usr/src/usr.bin/Makefile index 021b2ceee8..283ca98827 100644 --- a/usr/src/usr.bin/Makefile +++ b/usr/src/usr.bin/Makefile @@ -2,28 +2,34 @@ # # PATCHES MAGIC LEVEL PATCH THAT GOT US HERE # -------------------- ----- ---------------------- -# CURRENT PATCH LEVEL: 1 00087 +# CURRENT PATCH LEVEL: 2 00124 # -------------------- ----- ---------------------- # # 09 Mar 93 Rodney W. Grimes Added netstat, rwho, and ruptime # to SUBDIR +# 04 Apr 93 Rodney W. Grimes Added 15 programs, disabled tn3270, +# enable msgs # SUBDIR= ar awk biff basename cal calendar \ checknr chpass cksum cmp col colcrt colrm column comm compress \ cpio crontab ctags cut diff diff3 dirname du egrep elvis elvisrecover \ - env expand false fgrep file find finger fmt fold from fstat ftp \ - g++ gas gcc gdb grep groff groups head hexdump id join \ - ktrace last ld leave lex locate lock logger \ - login logname lorder m4 machine mail make man mesg mkdep mkfifo \ - mkstr more netstat nfsstat nice nm nohup pagesize \ - passwd paste pr printenv printf ranlib rcs \ - rdist renice rlogin rsh ruptime rwho script sed \ + env error expand false fgrep file find finger fmt fold fpr from fsplit \ + fstat ftp \ + g++ gas gcc gdb grep gprof groff groups head hexdump id indent join \ + ktrace last lastcomm ld leave lex locate lock logger \ + login logname look lorder m4 machine mail make man mesg mkdep mkfifo \ + mkstr more msgs mt netstat nfsstat nice nm nohup pagesize \ + passwd paste pr printenv printf quota ranlib rcs \ + rdist renice rlogin rsh ruptime rwho sccs script sed \ shar showmount size soelim sort split strings \ - strip su symorder tail talk tar tee telnet tftp time \ - tip tn3270 touch tput tr true tsort tty ul unexpand unifdef uniq \ - unvis users uudecode uuencode vacation vis \ + strip su symorder tail talk tar tcopy tee telnet tftp time \ + tip touch tput tr true tset tsort tty ul unexpand unifdef uniq \ + unvis users uudecode uuencode vacation vgrind vis vmstat \ w wall wc what whereis which who whoami whois \ - write xargs xinstall xstr yacc yes + window write xargs xinstall xstr yacc yes + + +# disabled tn3270 .include diff --git a/usr/src/usr.bin/error/Makefile b/usr/src/usr.bin/error/Makefile new file mode 100644 index 0000000000..d137b50d94 --- /dev/null +++ b/usr/src/usr.bin/error/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 5.9 (Berkeley) 2/26/91 + +PROG= error +SRCS= main.c input.c pi.c subr.c filter.c touch.c + +.include diff --git a/usr/src/usr.bin/error/error.1 b/usr/src/usr.bin/error/error.1 new file mode 100644 index 0000000000..87456f692b --- /dev/null +++ b/usr/src/usr.bin/error/error.1 @@ -0,0 +1,304 @@ +.\" Copyright (c) 1980, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)error.1 6.7 (Berkeley) 7/24/91 +.\" +.Dd July 24, 1991 +.Dt ERROR 1 +.Os BSD 4 +.Sh NAME +.Nm error +.Nd analyze and disperse compiler error messages +.Sh SYNOPSIS +.Nm error +.Op Fl n +.Op Fl s +.Op Fl q +.Op Fl v +.Op Fl t Ar suffixlist +.Op Fl I Ar ignorefile +.Op name +.Sh DESCRIPTION +.Nm Error +analyzes and optionally disperses the diagnostic error messages +produced by a number of compilers and language processors to the source +file and line where the errors occurred. It can replace the painful, +traditional methods of scribbling abbreviations of errors on paper, and +permits error messages and source code to be viewed simultaneously +without machinations of multiple windows in a screen editor. +.Pp +Options are: +.Bl -tag -width Ds +.It Fl n +Do +.Em not +touch any files; all error messages are sent to the +standard output. +.It Fl q +The user is +.Ar queried +whether s/he wants to touch the file. +A ``y'' or ``n'' to the question is necessary to continue. +Absence of the +.Fl q +option implies that all referenced files +(except those referring to discarded error messages) +are to be touched. +.It Fl v +After all files have been touched, +overlay the visual editor +.Xr \&vi 1 +with it set up to edit all files touched, +and positioned in the first touched file at the first error. +If +.Xr \&vi 1 +can't be found, try +.Xr \&ex 1 +or +.Xr \&ed 1 +from standard places. +.It Fl t +Take the following argument as a suffix list. +Files whose suffixes do not appear in the suffix list are not touched. +The suffix list is dot separated, and ``*'' wildcards work. +Thus the suffix list: +.Pp +.Dl ".c.y.foo*.h" +.Pp +allows +.Nm error +to touch files ending with ``.c'', ``.y'', ``.foo*'' and ``.y''. +.It Fl s +Print out +.Em statistics +regarding the error categorization. +Not too useful. +.El +.Pp +.Nm Error +looks at the error messages, +either from the specified file +.Ar name +or from the standard input, +and attempts to determine which +language processor produced each error message, +determines the source file and line number to which the error message refers, +determines if the error message is to be ignored or not, +and inserts the (possibly slightly modified) error message into +the source file as a comment on the line preceding to which the +line the error message refers. +Error messages which can't be categorized by language processor +or content are not inserted into any file, +but are sent to the standard output. +.Nm Error +touches source files only after all input has been read. +.Pp +.Nm Error +is intended to be run +with its standard input +connected via a pipe to the error message source. +Some language processors put error messages on their standard error file; +others put their messages on the standard output. +Hence, both error sources should be piped together into +.Nm error . +For example, when using the +.Xr csh 1 +syntax, +.Pp +.Dl make \-s lint \&| error \-q \-v +.Pp +will analyze all the error messages produced +by whatever programs +.Xr make 1 +runs when making lint. +.Pp +.Nm Error +knows about the error messages produced by: +.Xr make 1 , +.Xr \&cc 1 , +.Xr cpp 1 , +.Xr ccom 1 , +.Xr \&as 1 , +.Xr \&ld 1 , +.Xr lint 1 , +.Xr \&pi 1 , +.Xr \&pc 1 , +.Xr f77 1 , +and +.Em DEC Western Research Modula\-2 . +.Nm Error +knows a standard format for error messages produced by +the language processors, +so is sensitive to changes in these formats. +For all languages except +.Em Pascal , +error messages are restricted to be on one line. +Some error messages refer to more than one line in more than +one files; +.Nm error +will duplicate the error message and insert it at +all of the places referenced. +.Pp +.Nm Error +will do one of six things with error messages. +.Bl -tag -width Em synchronize +.It Em synchronize +Some language processors produce short errors describing +which file it is processing. +.Nm Error +uses these to determine the file name for languages that +don't include the file name in each error message. +These synchronization messages are consumed entirely by +.Nm error . +.It Em discard +Error messages from +.Xr lint 1 +that refer to one of the two +.Xr lint 1 +libraries, +.Pa /usr/libdata/lint/llib-lc +and +.Pa /usr/libdata/lint/llib-port +are discarded, +to prevent accidently touching these libraries. +Again, these error messages are consumed entirely by +.Nm error . +.It Em nullify +Error messages from +.Xr lint 1 +can be nullified if they refer to a specific function, +which is known to generate diagnostics which are not interesting. +Nullified error messages are not inserted into the source file, +but are written to the standard output. +The names of functions to ignore are taken from +either the file named +.Pa .errorrc +in the users's home directory, +or from the file named by the +.Fl I +option. +If the file does not exist, +no error messages are nullified. +If the file does exist, there must be one function +name per line. +.It Em not file specific +Error messages that can't be intuited are grouped together, +and written to the standard output before any files are touched. +They will not be inserted into any source file. +.It Em file specific +Error message that refer to a specific file, +but to no specific line, +are written to the standard output when +that file is touched. +.It Em true errors +Error messages that can be intuited are candidates for +insertion into the file to which they refer. +.El +.Pp +Only true error messages are candidates for inserting into +the file they refer to. +Other error messages are consumed entirely by +.Nm error +or are written to the standard output. +.Nm Error +inserts the error messages into the source file on the line +preceding the line the language processor found in error. +Each error message is turned into a one line comment for the +language, +and is internally flagged +with the string ``###'' at +the beginning of the error, +and ``%%%'' at the end of the error. +This makes pattern searching for errors easier with an editor, +and allows the messages to be easily removed. +In addition, each error message contains the source line number +for the line the message refers to. +A reasonably formatted source program can be recompiled +with the error messages still in it, +without having the error messages themselves cause future errors. +For poorly formatted source programs in free format languages, +such as C or Pascal, +it is possible to insert a comment into another comment, +which can wreak havoc with a future compilation. +To avoid this, programs with comments and source +on the same line should be formatted +so that language statements appear before comments. +.Pp +.Nm Error +catches interrupt and terminate signals, +and if in the insertion phase, +will orderly terminate what it is doing. +.Sh FILES +.Bl -tag -width ~/.errorrc -compact +.It Pa ~/.errorrc +function names to ignore for +.Xr lint 1 +error messages +.It Pa /dev/tty +user's teletype +.El +.Sh HISTORY +The +.Nm error +command +appeared in +.Bx 4.0 . +.Sh AUTHOR +Robert Henry +.Sh BUGS +.Pp +Opens the teletype directly to do user querying. +.Pp +Source files with links make a new copy of the file with +only one link to it. +.Pp +Changing a language processor's format of error messages +may cause +.Nm error +to not understand the error message. +.Pp +.Nm Error , +since it is purely mechanical, +will not filter out subsequent errors caused by `floodgating' +initiated by one syntactically trivial error. +Humans are still much better at discarding these related errors. +.Pp +Pascal error messages belong after the lines affected +(error puts them before). The alignment of the `\\' marking +the point of error is also disturbed by +.Nm error . +.Pp +.Nm Error +was designed for work on +.Tn CRT Ns 's +at reasonably high speed. +It is less pleasant on slow speed terminals, and has never been +used on hardcopy terminals. diff --git a/usr/src/usr.bin/error/error.h b/usr/src/usr.bin/error/error.h new file mode 100644 index 0000000000..b3f3d965c2 --- /dev/null +++ b/usr/src/usr.bin/error/error.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)error.h 5.5 (Berkeley) 6/1/90 + */ + +typedef int boolean; +#define reg register + +#define TRUE 1 +#define FALSE 0 + +#define true 1 +#define false 0 +/* + * Descriptors for the various languages we know about. + * If you touch these, also touch lang_table + */ +#define INUNKNOWN 0 +#define INCPP 1 +#define INCC 2 +#define INAS 3 +#define INLD 4 +#define INLINT 5 +#define INF77 6 +#define INPI 7 +#define INPC 8 +#define INFRANZ 9 +#define INLISP 10 +#define INVAXIMA 11 +#define INRATFOR 12 +#define INLEX 13 +#define INYACC 14 +#define INAPL 15 +#define INMAKE 16 +#define INRI 17 +#define INTROFF 18 +#define INMOD2 19 + +extern int language; +/* + * We analyze each line in the error message file, and + * attempt to categorize it by type, as well as language. + * Here are the type descriptors. + */ +typedef int Errorclass; + +#define C_FIRST 0 /* first error category */ +#define C_UNKNOWN 0 /* must be zero */ +#define C_IGNORE 1 /* ignore the message; used for pi */ +#define C_SYNC 2 /* synchronization errors */ +#define C_DISCARD 3 /* touches dangerous files, so discard */ +#define C_NONSPEC 4 /* not specific to any file */ +#define C_THISFILE 5 /* specific to this file, but at no line */ +#define C_NULLED 6 /* refers to special func; so null */ +#define C_TRUE 7 /* fits into true error format */ +#define C_DUPL 8 /* sub class only; duplicated error message */ +#define C_LAST 9 /* last error category */ + +#define SORTABLE(x) (!(NOTSORTABLE(x))) +#define NOTSORTABLE(x) (x <= C_NONSPEC) +/* + * Resources to count and print out the error categories + */ +extern char *class_table[]; +extern int class_count[]; + +#define nunknown class_count[C_UNKNOWN] +#define nignore class_count[C_IGNORE] +#define nsyncerrors class_count[C_SYNC] +#define ndiscard class_count[C_DISCARD] +#define nnonspec class_count[C_NONSPEC] +#define nthisfile class_count[C_THISFILE] +#define nnulled class_count[C_NULLED] +#define ntrue class_count[C_TRUE] +#define ndupl class_count[C_DUPL] + +/* places to put the error complaints */ + +#define TOTHEFILE 1 /* touch the file */ +#define TOSTDOUT 2 /* just print them out (ho-hum) */ + +FILE *errorfile; /* where error file comes from */ +FILE *queryfile; /* where the query responses from the user come from*/ + +extern char *currentfilename; +extern char *processname; +extern char *scriptname; + +extern boolean query; +extern boolean terse; +int inquire(); /* inquire for yes/no */ +/* + * codes for inquire() to return + */ +#define Q_NO 1 /* 'N' */ +#define Q_no 2 /* 'n' */ +#define Q_YES 3 /* 'Y' */ +#define Q_yes 4 /* 'y' */ + +int probethisfile(); +/* + * codes for probethisfile to return + */ +#define F_NOTEXIST 1 +#define F_NOTREAD 2 +#define F_NOTWRITE 3 +#define F_TOUCHIT 4 + +/* + * Describes attributes about a language + */ +struct lang_desc{ + char *lang_name; + char *lang_incomment; /* one of the following defines */ + char *lang_outcomment; /* one of the following defines */ +}; +extern struct lang_desc lang_table[]; + +#define CINCOMMENT "/*###" +#define COUTCOMMENT "%%%*/\n" +#define FINCOMMENT "C###" +#define FOUTCOMMENT "%%%\n" +#define NEWLINE "%%%\n" +#define PIINCOMMENT "(*###" +#define PIOUTCOMMENT "%%%*)\n" +#define LISPINCOMMENT ";###" +#define ASINCOMMENT "####" +#define RIINCOMMENT CINCOMMENT +#define RIOUTCOMMENT COUTCOMMENT +#define TROFFINCOMMENT ".\\\"###" +#define TROFFOUTCOMMENT NEWLINE +#define MOD2INCOMMENT "(*###" +#define MOD2OUTCOMMENT "%%%*)\n" +/* + * Defines and resources for determing if a given line + * is to be discarded because it refers to a file not to + * be touched, or if the function reference is to a + * function the user doesn't want recorded. + */ + +#define ERRORNAME "/.errorrc" +int nignored; +char **names_ignored; +/* + * Structure definition for a full error + */ +typedef struct edesc Edesc; +typedef Edesc *Eptr; + +struct edesc{ + Eptr error_next; /*linked together*/ + int error_lgtext; /* how many on the right hand side*/ + char **error_text; /* the right hand side proper*/ + Errorclass error_e_class; /* error category of this error*/ + Errorclass error_s_class; /* sub descriptor of error_e_class*/ + int error_language; /* the language for this error*/ + int error_position; /* oridinal position */ + int error_line; /* discovered line number*/ + int error_no; /* sequence number on input */ +}; +/* + * Resources for the true errors + */ +extern int nerrors; +extern Eptr er_head; +extern Eptr *errors; +/* + * Resources for each of the files mentioned + */ +extern int nfiles; +extern Eptr **files; /* array of pointers into errors*/ +boolean *touchedfiles; /* which files we touched */ +/* + * The langauge the compilation is in, as intuited from + * the flavor of error messages analyzed. + */ +extern int langauge; +extern char *currentfilename; +/* + * Functional forwards + */ +char *Calloc(); +char *strsave(); +char *clobberfirst(); +char lastchar(); +char firstchar(); +char next_lastchar(); +char **wordvsplice(); +int wordvcmp(); +boolean persperdexplode(); +/* + * Printing hacks + */ +char *plural(), *verbform(); diff --git a/usr/src/usr.bin/error/filter.c b/usr/src/usr.bin/error/filter.c new file mode 100644 index 0000000000..7c4871b651 --- /dev/null +++ b/usr/src/usr.bin/error/filter.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)filter.c 5.7 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "pathnames.h" + +char *lint_libs[] = { + IG_FILE1, + IG_FILE2, + IG_FILE3, + IG_FILE4, + 0 +}; +extern char* processname; +int lexsort(); +/* + * Read the file ERRORNAME of the names of functions in lint + * to ignore complaints about. + */ +getignored(auxname) + char *auxname; +{ + reg int i; + FILE *fyle; + char inbuffer[256]; + int uid; + char filename[128]; + char *username; + struct passwd *passwdentry; + + nignored = 0; + if (auxname == 0){ /* use the default */ + if ( (username = (char *)getlogin()) == NULL){ + username = "Unknown"; + uid = getuid(); + if ( (passwdentry = (struct passwd *)getpwuid(uid)) == NULL){ + return; + } + } else { + if ( (passwdentry = (struct passwd *)getpwnam(username)) == NULL) + return; + } + strcpy(filename, passwdentry->pw_dir); + (void)strcat(filename, ERRORNAME); + } else + (void)strcpy(filename, auxname); +#ifdef FULLDEBUG + printf("Opening file \"%s\" to read names to ignore.\n", + filename); +#endif + if ( (fyle = fopen(filename, "r")) == NULL){ +#ifdef FULLDEBUG + fprintf(stderr, "%s: Can't open file \"%s\"\n", + processname, filename); +#endif + return; + } + /* + * Make the first pass through the file, counting lines + */ + for (nignored = 0; fgets(inbuffer, 255, fyle) != NULL; nignored++) + continue; + names_ignored = (char **)Calloc(nignored+1, sizeof (char *)); + fclose(fyle); + if (freopen(filename, "r", fyle) == NULL){ +#ifdef FULLDEBUG + fprintf(stderr, "%s: Failure to open \"%s\" for second read.\n", + processname, filename); +#endif + nignored = 0; + return; + } + for (i=0; i < nignored && (fgets (inbuffer, 255, fyle) != NULL); i++){ + names_ignored[i] = strsave(inbuffer); + (void)substitute(names_ignored[i], '\n', '\0'); + } + qsort(names_ignored, nignored, sizeof *names_ignored, lexsort); +#ifdef FULLDEBUG + printf("Names to ignore follow.\n"); + for (i=0; i < nignored; i++){ + printf("\tIgnore: %s\n", names_ignored[i]); + } +#endif +} + +int lexsort(cpp1, cpp2) + char **cpp1, **cpp2; +{ + return(strcmp(*cpp1, *cpp2)); +} + +int search_ignore(key) + char *key; +{ + reg int ub, lb; + reg int halfway; + int order; + + if (nignored == 0) + return(-1); + for(lb = 0, ub = nignored - 1; ub >= lb; ){ + halfway = (ub + lb)/2; + if ( (order = strcmp(key, names_ignored[halfway])) == 0) + return(halfway); + if (order < 0) /*key is less than probe, throw away above*/ + ub = halfway - 1; + else + lb = halfway + 1; + } + return(-1); +} + +/* + * Tell if the error text is to be ignored. + * The error must have been canonicalized, with + * the file name the zeroth entry in the errorv, + * and the linenumber the second. + * Return the new categorization of the error class. + */ +Errorclass discardit(errorp) + reg Eptr errorp; +{ + int language; + reg int i; + Errorclass errorclass = errorp->error_e_class; + + switch(errorclass){ + case C_SYNC: + case C_NONSPEC: + case C_UNKNOWN: return(errorclass); + default: ; + } + if(errorp->error_lgtext < 2){ + return(C_NONSPEC); + } + language = errorp->error_language; + if(language == INLINT){ + if (errorclass != C_NONSPEC){ /* no file */ + for(i=0; lint_libs[i] != 0; i++){ + if (strcmp(errorp->error_text[0], lint_libs[i]) == 0){ + return(C_DISCARD); + } + } + } + /* check if the argument to the error message is to be ignored*/ + if (ispunct(lastchar(errorp->error_text[2]))) + clob_last(errorp->error_text[2], '\0'); + if (search_ignore(errorp->error_text[errorclass == C_NONSPEC ? 0 : 2]) >= 0){ + return(C_NULLED); + } + } + return(errorclass); +} diff --git a/usr/src/usr.bin/error/input.c b/usr/src/usr.bin/error/input.c new file mode 100644 index 0000000000..1a7525df57 --- /dev/null +++ b/usr/src/usr.bin/error/input.c @@ -0,0 +1,548 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)input.c 5.5 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "error.h" + +int wordc; /* how long the current error message is */ +char **wordv; /* the actual error message */ + +int nerrors; +int language; + +Errorclass onelong(); +Errorclass cpp(); +Errorclass pccccom(); /* Portable C Compiler C Compiler */ +Errorclass richieccom(); /* Richie Compiler for 11 */ +Errorclass lint0(); +Errorclass lint1(); +Errorclass lint2(); +Errorclass lint3(); +Errorclass make(); +Errorclass f77(); +Errorclass pi(); +Errorclass ri(); +Errorclass troff(); +Errorclass mod2(); +/* + * Eat all of the lines in the input file, attempting to categorize + * them by their various flavors + */ +static char inbuffer[BUFSIZ]; + +eaterrors(r_errorc, r_errorv) + int *r_errorc; + Eptr **r_errorv; +{ + extern boolean piflag; + Errorclass errorclass = C_SYNC; + + for (;;){ + if (fgets(inbuffer, BUFSIZ, errorfile) == NULL) + break; + wordvbuild(inbuffer, &wordc, &wordv); + /* + * for convience, convert wordv to be 1 based, instead + * of 0 based. + */ + wordv -= 1; + if ( wordc > 0 && + ((( errorclass = onelong() ) != C_UNKNOWN) + || (( errorclass = cpp() ) != C_UNKNOWN) + || (( errorclass = pccccom() ) != C_UNKNOWN) + || (( errorclass = richieccom() ) != C_UNKNOWN) + || (( errorclass = lint0() ) != C_UNKNOWN) + || (( errorclass = lint1() ) != C_UNKNOWN) + || (( errorclass = lint2() ) != C_UNKNOWN) + || (( errorclass = lint3() ) != C_UNKNOWN) + || (( errorclass = make() ) != C_UNKNOWN) + || (( errorclass = f77() ) != C_UNKNOWN) + || ((errorclass = pi() ) != C_UNKNOWN) + || (( errorclass = ri() )!= C_UNKNOWN) + || (( errorclass = mod2() )!= C_UNKNOWN) + || (( errorclass = troff() )!= C_UNKNOWN)) + ) ; + else + errorclass = catchall(); + if (wordc) + erroradd(wordc, wordv+1, errorclass, C_UNKNOWN); + } +#ifdef FULLDEBUG + printf("%d errorentrys\n", nerrors); +#endif + arrayify(r_errorc, r_errorv, er_head); +} + +/* + * create a new error entry, given a zero based array and count + */ +erroradd(errorlength, errorv, errorclass, errorsubclass) + int errorlength; + char **errorv; + Errorclass errorclass; + Errorclass errorsubclass; +{ + reg Eptr newerror; + reg char *cp; + + if (errorclass == C_TRUE){ + /* check canonicalization of the second argument*/ + for(cp = errorv[1]; *cp && isdigit(*cp); cp++) + continue; + errorclass = (*cp == '\0') ? C_TRUE : C_NONSPEC; +#ifdef FULLDEBUG + if (errorclass != C_TRUE) + printf("The 2nd word, \"%s\" is not a number.\n", + errorv[1]); +#endif + } + if (errorlength > 0){ + newerror = (Eptr)Calloc(1, sizeof(Edesc)); + newerror->error_language = language; /* language is global */ + newerror->error_text = errorv; + newerror->error_lgtext = errorlength; + if (errorclass == C_TRUE) + newerror->error_line = atoi(errorv[1]); + newerror->error_e_class = errorclass; + newerror->error_s_class = errorsubclass; + switch(newerror->error_e_class = discardit(newerror)){ + case C_SYNC: nsyncerrors++; break; + case C_DISCARD: ndiscard++; break; + case C_NULLED: nnulled++; break; + case C_NONSPEC: nnonspec++; break; + case C_THISFILE: nthisfile++; break; + case C_TRUE: ntrue++; break; + case C_UNKNOWN: nunknown++; break; + case C_IGNORE: nignore++; break; + } + newerror->error_next = er_head; + er_head = newerror; + newerror->error_no = nerrors++; + } /* length > 0 */ +} + +Errorclass onelong() +{ + char **nwordv; + if ( (wordc == 1) && (language != INLD) ){ + /* + * We have either: + * a) file name from cc + * b) Assembler telling world that it is complaining + * c) Noise from make ("Stop.") + * c) Random noise + */ + wordc = 0; + if (strcmp(wordv[1], "Stop.") == 0){ + language = INMAKE; return(C_SYNC); + } + if (strcmp(wordv[1], "Assembler:") == 0){ + /* assembler always alerts us to what happened*/ + language = INAS; return(C_SYNC); + } else + if (strcmp(wordv[1], "Undefined:") == 0){ + /* loader complains about unknown symbols*/ + language = INLD; return(C_SYNC); + } + if (lastchar(wordv[1]) == ':'){ + /* cc tells us what file we are in */ + currentfilename = wordv[1]; + (void)substitute(currentfilename, ':', '\0'); + language = INCC; return(C_SYNC); + } + } else + if ( (wordc == 1) && (language == INLD) ){ + nwordv = (char **)Calloc(4, sizeof(char *)); + nwordv[0] = "ld:"; + nwordv[1] = wordv[1]; + nwordv[2] = "is"; + nwordv[3] = "undefined."; + wordc = 4; + wordv = nwordv - 1; + return(C_NONSPEC); + } else + if (wordc == 1){ + return(C_SYNC); + } + return(C_UNKNOWN); +} /* end of one long */ + +Errorclass cpp() +{ + /* + * Now attempt a cpp error message match + * Examples: + * ./morse.h: 23: undefined control + * morsesend.c: 229: MAGNIBBL: argument mismatch + * morsesend.c: 237: MAGNIBBL: argument mismatch + * test1.c: 6: undefined control + */ + if ( (language != INLD) /* loader errors have almost same fmt*/ + && (lastchar(wordv[1]) == ':') + && (isdigit(firstchar(wordv[2]))) + && (lastchar(wordv[2]) == ':') ){ + language = INCPP; + clob_last(wordv[1], '\0'); + clob_last(wordv[2], '\0'); + return(C_TRUE); + } + return(C_UNKNOWN); +} /*end of cpp*/ + +Errorclass pccccom() +{ + /* + * Now attempt a ccom error message match: + * Examples: + * "morsesend.c", line 237: operands of & have incompatible types + * "test.c", line 7: warning: old-fashioned initialization: use = + * "subdir.d/foo2.h", line 1: illegal initialization + */ + if ( (firstchar(wordv[1]) == '"') + && (lastchar(wordv[1]) == ',') + && (next_lastchar(wordv[1]) == '"') + && (strcmp(wordv[2],"line") == 0) + && (isdigit(firstchar(wordv[3]))) + && (lastchar(wordv[3]) == ':') ){ + clob_last(wordv[1], '\0'); /* drop last , */ + clob_last(wordv[1], '\0'); /* drop last " */ + wordv[1]++; /* drop first " */ + clob_last(wordv[3], '\0'); /* drop : on line number */ + wordv[2] = wordv[1]; /* overwrite "line" */ + wordv++; /*compensate*/ + wordc--; + currentfilename = wordv[1]; + language = INCC; + return(C_TRUE); + } + return(C_UNKNOWN); +} /* end of ccom */ +/* + * Do the error message from the Richie C Compiler for the PDP11, + * which has this source: + * + * if (filename[0]) + * fprintf(stderr, "%s:", filename); + * fprintf(stderr, "%d: ", line); + * + */ +Errorclass richieccom() +{ + reg char *cp; + reg char **nwordv; + char *file; + + if (lastchar(wordv[1]) == ':'){ + cp = wordv[1] + strlen(wordv[1]) - 1; + while (isdigit(*--cp)) + continue; + if (*cp == ':'){ + clob_last(wordv[1], '\0'); /* last : */ + *cp = '\0'; /* first : */ + file = wordv[1]; + nwordv = wordvsplice(1, wordc, wordv+1); + nwordv[0] = file; + nwordv[1] = cp + 1; + wordc += 1; + wordv = nwordv - 1; + language = INCC; + currentfilename = wordv[1]; + return(C_TRUE); + } + } + return(C_UNKNOWN); +} + +Errorclass lint0() +{ + reg char **nwordv; + char *line, *file; + /* + * Attempt a match for the new lint style normal compiler + * error messages, of the form + * + * printf("%s(%d): %s\n", filename, linenumber, message); + */ + if (wordc >= 2){ + if ( (lastchar(wordv[1]) == ':') + && (next_lastchar(wordv[1]) == ')') + ) { + clob_last(wordv[1], '\0'); /* colon */ + if (persperdexplode(wordv[1], &line, &file)){ + nwordv = wordvsplice(1, wordc, wordv+1); + nwordv[0] = file; /* file name */ + nwordv[1] = line; /* line number */ + wordc += 1; + wordv = nwordv - 1; + language = INLINT; + return(C_TRUE); + } + wordv[1][strlen(wordv[1])] = ':'; + } + } + return (C_UNKNOWN); +} + +Errorclass lint1() +{ + char *line1, *line2; + char *file1, *file2; + char **nwordv1, **nwordv2; + + /* + * Now, attempt a match for the various errors that lint + * can complain about. + * + * Look first for type 1 lint errors + */ + if (wordc > 1 && strcmp(wordv[wordc-1], "::") == 0){ + /* + * %.7s, arg. %d used inconsistently %s(%d) :: %s(%d) + * %.7s value used inconsistently %s(%d) :: %s(%d) + * %.7s multiply declared %s(%d) :: %s(%d) + * %.7s value declared inconsistently %s(%d) :: %s(%d) + * %.7s function value type must be declared before use %s(%d) :: %s(%d) + */ + language = INLINT; + if (wordc > 2 + && (persperdexplode(wordv[wordc], &line2, &file2)) + && (persperdexplode(wordv[wordc-2], &line1, &file1)) ){ + nwordv1 = wordvsplice(2, wordc, wordv+1); + nwordv2 = wordvsplice(2, wordc, wordv+1); + nwordv1[0] = file1; nwordv1[1] = line1; + erroradd(wordc+2, nwordv1, C_TRUE, C_DUPL); /* takes 0 based*/ + nwordv2[0] = file2; nwordv2[1] = line2; + wordc = wordc + 2; + wordv = nwordv2 - 1; /* 1 based */ + return(C_TRUE); + } + } + return(C_UNKNOWN); +} /* end of lint 1*/ + +Errorclass lint2() +{ + char *file; + char *line; + char **nwordv; + /* + * Look for type 2 lint errors + * + * %.7s used( %s(%d) ), but not defined + * %.7s defined( %s(%d) ), but never used + * %.7s declared( %s(%d) ), but never used or defined + * + * bufp defined( "./metric.h"(10) ), but never used + */ + if ( (lastchar(wordv[2]) == '(' /* ')' */ ) + && (strcmp(wordv[4], "),") == 0) ){ + language = INLINT; + if (persperdexplode(wordv[3], &line, &file)){ + nwordv = wordvsplice(2, wordc, wordv+1); + nwordv[0] = file; nwordv[1] = line; + wordc = wordc + 2; + wordv = nwordv - 1; /* 1 based */ + return(C_TRUE); + } + } + return(C_UNKNOWN); +} /* end of lint 2*/ + +char *Lint31[4] = {"returns", "value", "which", "is"}; +char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"}; +Errorclass lint3() +{ + if ( (wordvcmp(wordv+2, 4, Lint31) == 0) + || (wordvcmp(wordv+2, 6, Lint32) == 0) ){ + language = INLINT; + return(C_NONSPEC); + } + return(C_UNKNOWN); +} + +/* + * Special word vectors for use by F77 recognition + */ +char *F77_fatal[3] = {"Compiler", "error", "line"}; +char *F77_error[3] = {"Error", "on", "line"}; +char *F77_warning[3] = {"Warning", "on", "line"}; +char *F77_no_ass[3] = {"Error.","No","assembly."}; +f77() +{ + char **nwordv; + /* + * look for f77 errors: + * Error messages from /usr/src/cmd/f77/error.c, with + * these printf formats: + * + * Compiler error line %d of %s: %s + * Error on line %d of %s: %s + * Warning on line %d of %s: %s + * Error. No assembly. + */ + if (wordc == 3 && wordvcmp(wordv+1, 3, F77_no_ass) == 0) { + wordc = 0; + return(C_SYNC); + } + if (wordc < 6) + return(C_UNKNOWN); + if ( (lastchar(wordv[6]) == ':') + &&( + (wordvcmp(wordv+1, 3, F77_fatal) == 0) + || (wordvcmp(wordv+1, 3, F77_error) == 0) + || (wordvcmp(wordv+1, 3, F77_warning) == 0) ) + ){ + language = INF77; + nwordv = wordvsplice(2, wordc, wordv+1); + nwordv[0] = wordv[6]; + clob_last(nwordv[0],'\0'); + nwordv[1] = wordv[4]; + wordc += 2; + wordv = nwordv - 1; /* 1 based */ + return(C_TRUE); + } + return(C_UNKNOWN); +} /* end of f77 */ + +char *Make_Croak[3] = {"***", "Error", "code"}; +char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"}; +Errorclass make() +{ + if (wordvcmp(wordv+1, 3, Make_Croak) == 0){ + language = INMAKE; + return(C_SYNC); + } + if (wordvcmp(wordv+2, 5, Make_NotRemade) == 0){ + language = INMAKE; + return(C_SYNC); + } + return(C_UNKNOWN); +} +Errorclass ri() +{ +/* + * Match an error message produced by ri; here is the + * procedure yanked from the distributed version of ri + * April 24, 1980. + * + * serror(str, x1, x2, x3) + * char str[]; + * char *x1, *x2, *x3; + * { + * extern int yylineno; + * + * putc('"', stdout); + * fputs(srcfile, stdout); + * putc('"', stdout); + * fprintf(stdout, " %d: ", yylineno); + * fprintf(stdout, str, x1, x2, x3); + * fprintf(stdout, "\n"); + * synerrs++; + * } + */ + if ( (firstchar(wordv[1]) == '"') + &&(lastchar(wordv[1]) == '"') + &&(lastchar(wordv[2]) == ':') + &&(isdigit(firstchar(wordv[2]))) ){ + clob_last(wordv[1], '\0'); /* drop the last " */ + wordv[1]++; /* skip over the first " */ + clob_last(wordv[2], '\0'); + language = INRI; + return(C_TRUE); + } + return(C_UNKNOWN); +} + +Errorclass catchall() +{ + /* + * Catches random things. + */ + language = INUNKNOWN; + return(C_NONSPEC); +} /* end of catch all*/ + +Errorclass troff() +{ + /* + * troff source error message, from eqn, bib, tbl... + * Just like pcc ccom, except uses `' + */ + if ( (firstchar(wordv[1]) == '`') + && (lastchar(wordv[1]) == ',') + && (next_lastchar(wordv[1]) == '\'') + && (strcmp(wordv[2],"line") == 0) + && (isdigit(firstchar(wordv[3]))) + && (lastchar(wordv[3]) == ':') ){ + clob_last(wordv[1], '\0'); /* drop last , */ + clob_last(wordv[1], '\0'); /* drop last " */ + wordv[1]++; /* drop first " */ + clob_last(wordv[3], '\0'); /* drop : on line number */ + wordv[2] = wordv[1]; /* overwrite "line" */ + wordv++; /*compensate*/ + currentfilename = wordv[1]; + language = INTROFF; + return(C_TRUE); + } + return(C_UNKNOWN); +} +Errorclass mod2() +{ + /* + * for decwrl modula2 compiler (powell) + */ + if ( ( (strcmp(wordv[1], "!!!") == 0) /* early version */ + ||(strcmp(wordv[1], "File") == 0)) /* later version */ + && (lastchar(wordv[2]) == ',') /* file name */ + && (strcmp(wordv[3], "line") == 0) + && (isdigit(firstchar(wordv[4]))) /* line number */ + && (lastchar(wordv[4]) == ':') /* line number */ + ){ + clob_last(wordv[2], '\0'); /* drop last , on file name */ + clob_last(wordv[4], '\0'); /* drop last : on line number */ + wordv[3] = wordv[2]; /* file name on top of "line" */ + wordv += 2; + wordc -= 2; + currentfilename = wordv[1]; + language = INMOD2; + return(C_TRUE); + } + return(C_UNKNOWN); +} diff --git a/usr/src/usr.bin/error/main.c b/usr/src/usr.bin/error/main.c new file mode 100644 index 0000000000..ea4a66049c --- /dev/null +++ b/usr/src/usr.bin/error/main.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 5.6 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "pathnames.h" + +int nerrors = 0; +Eptr er_head; +Eptr *errors; + +int nfiles = 0; +Eptr **files; /* array of pointers into errors*/ +int language = INCC; + +char *currentfilename = "????"; +char *processname; +char im_on[] = _PATH_TTY; /* my tty name */ + +boolean query = FALSE; /* query the operator if touch files */ +boolean notouch = FALSE; /* don't touch ANY files */ +boolean piflag = FALSE; /* this is not pi */ +boolean terse = FALSE; /* Terse output */ + +char *suffixlist = ".*"; /* initially, can touch any file */ + +int errorsort(); +void onintr(); +/* + * error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile] + * + * -T: terse output + * + * -I: the following name, `ignorename' contains a list of + * function names that are not to be treated as hard errors. + * Default: ~/.errorsrc + * + * -n: don't touch ANY files! + * + * -q: The user is to be queried before touching each + * file; if not specified, all files with hard, non + * ignorable errors are touched (assuming they can be). + * + * -t: touch only files ending with the list of suffices, each + * suffix preceded by a dot. + * eg, -t .c.y.l + * will touch only files ending with .c, .y or .l + * + * -s: print a summary of the error's categories. + * + * -v: after touching all files, overlay vi(1), ex(1) or ed(1) + * on top of error, entered in the first file with + * an error in it, with the appropriate editor + * set up to use the "next" command to get the other + * files containing errors. + * + * -p: (obsolete: for older versions of pi without bug + * fix regarding printing out the name of the main file + * with an error in it) + * Take the following argument and use it as the name of + * the pascal source file, suffix .p + * + * -E: show the errors in sorted order; intended for + * debugging. + * + * -S: show the errors in unsorted order + * (as they come from the error file) + * + * infile: The error messages come from this file. + * Default: stdin + */ +main(argc, argv) + int argc; + char *argv[]; +{ + char *cp; + char *ignorename = 0; + int ed_argc; + char **ed_argv; /*return from touchfiles*/ + boolean show_errors = FALSE; + boolean Show_Errors = FALSE; + boolean pr_summary = FALSE; + boolean edit_files = FALSE; + + processname = argv[0]; + + errorfile = stdin; + if (argc > 1) for(; (argc > 1) && (argv[1][0] == '-'); argc--, argv++){ + for (cp = argv[1] + 1; *cp; cp++) switch(*cp){ + default: + fprintf(stderr, "%s: -%c: Unknown flag\n", + processname, *cp); + break; + + case 'n': notouch = TRUE; break; + case 'q': query = TRUE; break; + case 'S': Show_Errors = TRUE; break; + case 's': pr_summary = TRUE; break; + case 'v': edit_files = TRUE; break; + case 'T': terse = TRUE; break; + case 't': + *cp-- = 0; argv++; argc--; + if (argc > 1){ + suffixlist = argv[1]; + } + break; + case 'I': /*ignore file name*/ + *cp-- = 0; argv++; argc--; + if (argc > 1) + ignorename = argv[1]; + break; + } + } + if (notouch) + suffixlist = 0; + if (argc > 1){ + if (argc > 3){ + fprintf(stderr, "%s: Only takes 0 or 1 arguments\n", + processname); + exit(3); + } + if ( (errorfile = fopen(argv[1], "r")) == NULL){ + fprintf(stderr, "%s: %s: No such file or directory for reading errors.\n", + processname, argv[1]); + exit(4); + } + } + if ( (queryfile = fopen(im_on, "r")) == NULL){ + if (query){ + fprintf(stderr, + "%s: Can't open \"%s\" to query the user.\n", + processname, im_on); + exit(9); + } + } + if (signal(SIGINT, onintr) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if (signal(SIGTERM, onintr) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + getignored(ignorename); + eaterrors(&nerrors, &errors); + if (Show_Errors) + printerrors(TRUE, nerrors, errors); + qsort(errors, nerrors, sizeof(Eptr), errorsort); + if (show_errors) + printerrors(FALSE, nerrors, errors); + findfiles(nerrors, errors, &nfiles, &files); +#define P(msg, arg) fprintf(stdout, msg, arg) + if (pr_summary){ + if (nunknown) + P("%d Errors are unclassifiable.\n", nunknown); + if (nignore) + P("%d Errors are classifiable, but totally discarded.\n",nignore); + if (nsyncerrors) + P("%d Errors are synchronization errors.\n", nsyncerrors); + if (nignore) + P("%d Errors are discarded because they refer to sacrosinct files.\n", ndiscard); + if (nnulled) + P("%d Errors are nulled because they refer to specific functions.\n", nnulled); + if (nnonspec) + P("%d Errors are not specific to any file.\n", nnonspec); + if (nthisfile) + P("%d Errors are specific to a given file, but not to a line.\n", nthisfile); + if (ntrue) + P("%d Errors are true errors, and can be inserted into the files.\n", ntrue); + } + filenames(nfiles, files); + fflush(stdout); + if (touchfiles(nfiles, files, &ed_argc, &ed_argv) && edit_files) + forkvi(ed_argc, ed_argv); +} + +forkvi(argc, argv) + int argc; + char **argv; +{ + if (query){ + switch(inquire(terse + ? "Edit? " + : "Do you still want to edit the files you touched? ")){ + case Q_NO: + case Q_no: + return; + default: + break; + } + } + /* + * ed_agument's first argument is + * a vi/ex compatabile search argument + * to find the first occurance of ### + */ + try("vi", argc, argv); + try("ex", argc, argv); + try("ed", argc-1, argv+1); + fprintf(stdout, "Can't find any editors.\n"); +} + +try(name, argc, argv) + char *name; + int argc; + char **argv; +{ + argv[0] = name; + wordvprint(stdout, argc, argv); + fprintf(stdout, "\n"); + fflush(stderr); + fflush(stdout); + sleep(2); + if (freopen(im_on, "r", stdin) == NULL) + return; + if (freopen(im_on, "w", stdout) == NULL) + return; + execvp(name, argv); +} + +int errorsort(epp1, epp2) + Eptr *epp1, *epp2; +{ + reg Eptr ep1, ep2; + int order; + /* + * Sort by: + * 1) synchronization, non specific, discarded errors first; + * 2) nulled and true errors last + * a) grouped by similar file names + * 1) grouped in ascending line number + */ + ep1 = *epp1; ep2 = *epp2; + if (ep1 == 0 || ep2 == 0) + return(0); + if ( (NOTSORTABLE(ep1->error_e_class)) ^ (NOTSORTABLE(ep2->error_e_class))){ + return(NOTSORTABLE(ep1->error_e_class) ? -1 : 1); + } + if (NOTSORTABLE(ep1->error_e_class)) /* then both are */ + return(ep1->error_no - ep2->error_no); + order = strcmp(ep1->error_text[0], ep2->error_text[0]); + if (order == 0){ + return(ep1->error_line - ep2->error_line); + } + return(order); +} diff --git a/usr/src/usr.bin/error/pathnames.h b/usr/src/usr.bin/error/pathnames.h new file mode 100644 index 0000000000..3d74889568 --- /dev/null +++ b/usr/src/usr.bin/error/pathnames.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.2 (Berkeley) 6/1/90 + */ + +#include + +#define IG_FILE1 "llib-lc" +#define IG_FILE2 "llib-port" +#define IG_FILE3 "/usr/lib/llib-lc" +#define IG_FILE4 "/usr/lib/llib-port" +#undef _PATH_TMP +#define _PATH_TMP "/tmp/ErrorXXXXXX" diff --git a/usr/src/usr.bin/error/pi.c b/usr/src/usr.bin/error/pi.c new file mode 100644 index 0000000000..38e080ab4e --- /dev/null +++ b/usr/src/usr.bin/error/pi.c @@ -0,0 +1,404 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)pi.c 5.5 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include "error.h" + +extern char *currentfilename; +static char *c_linenumber; +static char *unk_hdr[] = {"In", "program", "???"}; +static char **c_header = &unk_hdr[0]; + +/* + * Attempt to handle error messages produced by pi (and by pc) + * + * problem #1: There is no file name available when a file does not + * use a #include; this will have to be given to error + * in the command line. + * problem #2: pi doesn't always tell you what line number + * a error refers to; for example during the tree + * walk phase of code generation and error detection, + * an error can refer to "variable foo in procedure bletch" + * without giving a line number + * problem #3: line numbers, when available, are attached to + * the source line, along with the source line itself + * These line numbers must be extracted, and + * the source line thrown away. + * problem #4: Some error messages produce more than one line number + * on the same message. + * There are only two (I think): + * %s undefined on line%s + * %s improperly used on line%s + * here, the %s makes line plural or singular. + * + * Here are the error strings used in pi version 1.2 that can refer + * to a file name or line number: + * + * Multiply defined label in case, lines %d and %d + * Goto %s from line %d is into a structured statement + * End matched %s on line %d + * Inserted keyword end matching %s on line %d + * + * Here are the general pi patterns recognized: + * define piptr == -.*^-.* + * define msg = .* + * define digit = [0-9] + * definename = .* + * define date_format letter*3 letter*3 (digit | (digit digit)) + * (digit | (digit digit)):digit*2 digit*4 + * + * {e,E} (piptr) (msg) Encounter an error during textual scan + * E {digit}* - (msg) Have an error message that refers to a new line + * E - msg Have an error message that refers to current + * function, program or procedure + * (date_format) (name): When switch compilation files + * ... (msg) When refer to the previous line + * 'In' ('procedure'|'function'|'program') (name): + * pi is now complaining about 2nd pass errors. + * + * Here is the output from a compilation + * + * + * 2 var i:integer; + * e --------------^--- Inserted ';' + * E 2 - All variables must be declared in one var part + * E 5 - Include filename must end in .i + * Mon Apr 21 15:56 1980 test.h: + * 2 begin + * e ------^--- Inserted ';' + * Mon Apr 21 16:06 1980 test.p: + * E 2 - Function type must be specified + * 6 procedure foo(var x:real); + * e ------^--- Inserted ';' + * In function bletch: + * E - No assignment to the function variable + * w - variable x is never used + * E 6 - foo is already defined in this block + * In procedure foo: + * w - variable x is neither used nor set + * 9 z : = 23; + * E --------------^--- Undefined variable + * 10 y = [1]; + * e ----------------^--- Inserted ':' + * 13 z := 345.; + * e -----------------------^--- Digits required after decimal point + * E 10 - Constant set involved in non set context + * E 11 - Type clash: real is incompatible with integer + * ... Type of expression clashed with type of variable in assignment + * E 12 - Parameter type not identical to type of var parameter x of foo + * In program mung: + * w - variable y is never used + * w - type foo is never used + * w - function bletch is never used + * E - z undefined on lines 9 13 + */ +char *Months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct","Nov", "Dec", + 0 +}; +char *Days[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0 +}; +char *Piroutines[] = { + "program", "function", "procedure", 0 +}; + + +static boolean structured, multiple; + +char *pi_Endmatched[] = {"End", "matched"}; +char *pi_Inserted[] = {"Inserted", "keyword", "end", "matching"}; + +char *pi_multiple[] = {"Mutiply", "defined", "label", "in", "case,", "line"}; +char *pi_structured[] = {"is", "into", "a", "structured", "statement"}; + +char *pi_und1[] = {"undefined", "on", "line"}; +char *pi_und2[] = {"undefined", "on", "lines"}; +char *pi_imp1[] = {"improperly", "used", "on", "line"}; +char *pi_imp2[] = {"improperly", "used", "on", "lines"}; + +boolean alldigits(string) + reg char *string; +{ + for (; *string && isdigit(*string); string++) + continue; + return(*string == '\0'); +} +boolean instringset(member, set) + char *member; + reg char **set; +{ + for(; *set; set++){ + if (strcmp(*set, member) == 0) + return(TRUE); + } + return(FALSE); +} + +boolean isdateformat(wordc, wordv) + int wordc; + char **wordv; +{ + return( + (wordc == 5) + && (instringset(wordv[0], Days)) + && (instringset(wordv[1], Months)) + && (alldigits(wordv[2])) + && (alldigits(wordv[4])) ); +} + +boolean piptr(string) + reg char *string; +{ + if (*string != '-') + return(FALSE); + while (*string && *string == '-') + string++; + if (*string != '^') + return(FALSE); + string++; + while (*string && *string == '-') + string++; + return(*string == '\0'); +} + +extern int wordc; +extern char **wordv; + +Errorclass pi() +{ + char **nwordv; + + if (wordc < 2) + return (C_UNKNOWN); + if ( ( strlen(wordv[1]) == 1) + && ( (wordv[1][0] == 'e') || (wordv[1][0] == 'E') ) + && ( piptr(wordv[2]) ) + ) { + boolean longpiptr = 0; + /* + * We have recognized a first pass error of the form: + * letter ------^---- message + * + * turn into an error message of the form: + * + * file line 'pascal errortype' letter \n |---- message + * or of the form: + * file line letter |---- message + * when there are strlen("(*[pi]") or more + * preceding '-' on the error pointer. + * + * Where the | is intended to be a down arrow, so that + * the pi error messages can be inserted above the + * line in error, instead of below. (All of the other + * langauges put thier messages before the source line, + * instead of after it as does pi.) + * + * where the pointer to the error has been truncated + * by 6 characters to account for the fact that + * the pointer points into a tab preceded input line. + */ + language = INPI; + (void)substitute(wordv[2], '^', '|'); + longpiptr = position(wordv[2],'|') > (6+8); + nwordv = wordvsplice(longpiptr ? 2 : 4, wordc, wordv+1); + nwordv[0] = strsave(currentfilename); + nwordv[1] = strsave(c_linenumber); + if (!longpiptr){ + nwordv[2] = "pascal errortype"; + nwordv[3] = wordv[1]; + nwordv[4] = strsave("%%%\n"); + if (strlen(nwordv[5]) > (8-2)) /* this is the pointer */ + nwordv[5] += (8-2); /* bump over 6 characters */ + } + wordv = nwordv - 1; /* convert to 1 based */ + wordc += longpiptr ? 2 : 4; + return(C_TRUE); + } + if ( (wordc >= 4) + && (strlen(wordv[1]) == 1) + && ( (*wordv[1] == 'E') || (*wordv[1] == 'w') || (*wordv[1] == 'e') ) + && (alldigits(wordv[2])) + && (strlen(wordv[3]) == 1) + && (wordv[3][0] == '-') + ){ + /* + * Message of the form: letter linenumber - message + * Turn into form: filename linenumber letter - message + */ + language = INPI; + nwordv = wordvsplice(1, wordc, wordv + 1); + nwordv[0] = strsave(currentfilename); + nwordv[1] = wordv[2]; + nwordv[2] = wordv[1]; + c_linenumber = wordv[2]; + wordc += 1; + wordv = nwordv - 1; + return(C_TRUE); + } + if ( (wordc >= 3) + && (strlen(wordv[1]) == 1) + && ( (*(wordv[1]) == 'E') || (*(wordv[1]) == 'w') || (*(wordv[1]) == 'e') ) + && (strlen(wordv[2]) == 1) + && (wordv[2][0] == '-') + ) { + /* + * Message of the form: letter - message + * This happens only when we are traversing the tree + * during the second pass of pi, and discover semantic + * errors. + * + * We have already (presumably) saved the header message + * and can now construct a nulled error message for the + * current file. + * + * Turns into a message of the form: + * filename (header) letter - message + * + * First, see if it is a message referring to more than + * one line number. Only of the form: + * %s undefined on line%s + * %s improperly used on line%s + */ + boolean undefined = 0; + int wordindex; + + language = INPI; + if ( (undefined = (wordvcmp(wordv+2, 3, pi_und1) == 0) ) + || (undefined = (wordvcmp(wordv+2, 3, pi_und2) == 0) ) + || (wordvcmp(wordv+2, 4, pi_imp1) == 0) + || (wordvcmp(wordv+2, 4, pi_imp2) == 0) + ){ + for (wordindex = undefined ? 5 : 6; wordindex <= wordc; + wordindex++){ + nwordv = wordvsplice(2, undefined ? 2 : 3, wordv+1); + nwordv[0] = strsave(currentfilename); + nwordv[1] = wordv[wordindex]; + if (wordindex != wordc) + erroradd(undefined ? 4 : 5, nwordv, + C_TRUE, C_UNKNOWN); + } + wordc = undefined ? 4 : 5; + wordv = nwordv - 1; + return(C_TRUE); + } + + nwordv = wordvsplice(1+3, wordc, wordv+1); + nwordv[0] = strsave(currentfilename); + nwordv[1] = strsave(c_header[0]); + nwordv[2] = strsave(c_header[1]); + nwordv[3] = strsave(c_header[2]); + wordv = nwordv - 1; + wordc += 1 + 3; + return(C_THISFILE); + } + if (strcmp(wordv[1], "...") == 0){ + /* + * have a continuation error message + * of the form: ... message + * Turn into form : filename linenumber message + */ + language = INPI; + nwordv = wordvsplice(1, wordc, wordv+1); + nwordv[0] = strsave(currentfilename); + nwordv[1] = strsave(c_linenumber); + wordv = nwordv - 1; + wordc += 1; + return(C_TRUE); + } + if( (wordc == 6) + && (lastchar(wordv[6]) == ':') + && (isdateformat(5, wordv + 1)) + ){ + /* + * Have message that tells us we have changed files + */ + language = INPI; + currentfilename = strsave(wordv[6]); + clob_last(currentfilename, '\0'); + return(C_SYNC); + } + if( (wordc == 3) + && (strcmp(wordv[1], "In") == 0) + && (lastchar(wordv[3]) == ':') + && (instringset(wordv[2], Piroutines)) + ) { + language = INPI; + c_header = wordvsplice(0, wordc, wordv+1); + return(C_SYNC); + } + /* + * now, check for just the line number followed by the text + */ + if (alldigits(wordv[1])){ + language = INPI; + c_linenumber = wordv[1]; + return(C_IGNORE); + } + /* + * Attempt to match messages refering to a line number + * + * Multiply defined label in case, lines %d and %d + * Goto %s from line %d is into a structured statement + * End matched %s on line %d + * Inserted keyword end matching %s on line %d + */ + multiple = structured = 0; + if ( + ( (wordc == 6) && (wordvcmp(wordv+1, 2, pi_Endmatched) == 0)) + || ( (wordc == 8) && (wordvcmp(wordv+1, 4, pi_Inserted) == 0)) + || ( multiple = ((wordc == 9) && (wordvcmp(wordv+1,6, pi_multiple) == 0) ) ) + || ( structured = ((wordc == 10) && (wordvcmp(wordv+6,5, pi_structured) == 0 ) )) + ){ + language = INPI; + nwordv = wordvsplice(2, wordc, wordv+1); + nwordv[0] = strsave(currentfilename); + nwordv[1] = structured ? wordv [5] : wordv[wordc]; + wordc += 2; + wordv = nwordv - 1; + if (!multiple) + return(C_TRUE); + erroradd(wordc, nwordv, C_TRUE, C_UNKNOWN); + nwordv = wordvsplice(0, wordc, nwordv); + nwordv[1] = wordv[wordc - 2]; + return(C_TRUE); + } + return(C_UNKNOWN); +} diff --git a/usr/src/usr.bin/error/subr.c b/usr/src/usr.bin/error/subr.c new file mode 100644 index 0000000000..584c016ec4 --- /dev/null +++ b/usr/src/usr.bin/error/subr.c @@ -0,0 +1,423 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)subr.c 5.5 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "error.h" +/* + * Arrayify a list of rules + */ +arrayify(e_length, e_array, header) + int *e_length; + Eptr **e_array; + Eptr header; +{ + reg Eptr errorp; + reg Eptr *array; + reg int listlength; + reg int listindex; + + for (errorp = header, listlength = 0; + errorp; errorp = errorp->error_next, listlength++) + continue; + array = (Eptr*)Calloc(listlength+1, sizeof (Eptr)); + for(listindex = 0, errorp = header; + listindex < listlength; + listindex++, errorp = errorp->error_next){ + array[listindex] = errorp; + errorp->error_position = listindex; + } + array[listindex] = (Eptr)0; + *e_length = listlength; + *e_array = array; +} + +/*VARARGS1*/ +error(msg, a1, a2, a3) + char *msg; +{ + fprintf(stderr, "Error: "); + fprintf(stderr, msg, a1, a2, a3); + fprintf(stderr, "\n"); + fflush(stdout); + fflush(stderr); + exit(6); +} +/*ARGSUSED*/ +char *Calloc(nelements, size) + int nelements; + int size; +{ + char *back; + if ( (back = (char *)calloc(nelements, size)) == (char *)NULL){ + error("Ran out of memory.\n"); + exit(1); + } + return(back); +} + +char *strsave(instring) + char *instring; +{ + char *outstring; + (void)strcpy(outstring = (char *)Calloc(1, strlen(instring) + 1), + instring); + return(outstring); +} +/* + * find the position of a given character in a string + * (one based) + */ +int position(string, ch) + reg char *string; + reg char ch; +{ + reg int i; + if (string) + for (i=1; *string; string++, i++){ + if (*string == ch) + return(i); + } + return(-1); +} +/* + * clobber the first occurance of ch in string by the new character + */ +char *substitute(string, chold, chnew) + char *string; + char chold, chnew; +{ + reg char *cp = string; + + if (cp) + while (*cp){ + if (*cp == chold){ + *cp = chnew; + break; + } + cp++; + } + return(string); +} + +char lastchar(string) + char *string; +{ + int length; + if (string == 0) return('\0'); + length = strlen(string); + if (length >= 1) + return(string[length-1]); + else + return('\0'); +} + +char firstchar(string) + char *string; +{ + if (string) + return(string[0]); + else + return('\0'); +} + +char next_lastchar(string) + char *string; +{ + int length; + if (string == 0) return('\0'); + length = strlen(string); + if (length >= 2) + return(string[length - 2]); + else + return('\0'); +} + +clob_last(string, newstuff) + char *string, newstuff; +{ + int length = 0; + if (string) + length = strlen(string); + if (length >= 1) + string[length - 1] = newstuff; +} + +/* + * parse a string that is the result of a format %s(%d) + * return TRUE if this is of the proper format + */ +boolean persperdexplode(string, r_perd, r_pers) + char *string; + char **r_perd, **r_pers; +{ + reg char *cp; + int length = 0; + + if (string) + length = strlen(string); + if ( (length >= 4) + && (string[length - 1] == ')' ) ){ + for (cp = &string[length - 2]; + (isdigit(*cp)) && (*cp != '('); + --cp) + continue; + if (*cp == '('){ + string[length - 1] = '\0'; /* clobber the ) */ + *r_perd = strsave(cp+1); + string[length - 1] = ')'; + *cp = '\0'; /* clobber the ( */ + *r_pers = strsave(string); + *cp = '('; + return(TRUE); + } + } + return(FALSE); +} +/* + * parse a quoted string that is the result of a format \"%s\"(%d) + * return TRUE if this is of the proper format + */ +boolean qpersperdexplode(string, r_perd, r_pers) + char *string; + char **r_perd, **r_pers; +{ + reg char *cp; + int length = 0; + + if (string) + length = strlen(string); + if ( (length >= 4) + && (string[length - 1] == ')' ) ){ + for (cp = &string[length - 2]; + (isdigit(*cp)) && (*cp != '('); + --cp) + continue; + if (*cp == '(' && *(cp - 1) == '"'){ + string[length - 1] = '\0'; + *r_perd = strsave(cp+1); + string[length - 1] = ')'; + *(cp - 1) = '\0'; /* clobber the " */ + *r_pers = strsave(string + 1); + *(cp - 1) = '"'; + return(TRUE); + } + } + return(FALSE); +} + +static char cincomment[] = CINCOMMENT; +static char coutcomment[] = COUTCOMMENT; +static char fincomment[] = FINCOMMENT; +static char foutcomment[] = FOUTCOMMENT; +static char newline[] = NEWLINE; +static char piincomment[] = PIINCOMMENT; +static char pioutcomment[] = PIOUTCOMMENT; +static char lispincomment[] = LISPINCOMMENT; +static char riincomment[] = RIINCOMMENT; +static char rioutcomment[] = RIOUTCOMMENT; +static char troffincomment[] = TROFFINCOMMENT; +static char troffoutcomment[] = TROFFOUTCOMMENT; +static char mod2incomment[] = MOD2INCOMMENT; +static char mod2outcomment[] = MOD2OUTCOMMENT; + +struct lang_desc lang_table[] = { + /*INUNKNOWN 0*/ "unknown", cincomment, coutcomment, + /*INCPP 1*/ "cpp", cincomment, coutcomment, + /*INCC 2*/ "cc", cincomment, coutcomment, + /*INAS 3*/ "as", ASINCOMMENT, newline, + /*INLD 4*/ "ld", cincomment, coutcomment, + /*INLINT 5*/ "lint", cincomment, coutcomment, + /*INF77 6*/ "f77", fincomment, foutcomment, + /*INPI 7*/ "pi", piincomment, pioutcomment, + /*INPC 8*/ "pc", piincomment, pioutcomment, + /*INFRANZ 9*/ "franz",lispincomment, newline, + /*INLISP 10*/ "lisp", lispincomment, newline, + /*INVAXIMA 11*/ "vaxima",lispincomment,newline, + /*INRATFOR 12*/ "ratfor",fincomment, foutcomment, + /*INLEX 13*/ "lex", cincomment, coutcomment, + /*INYACC 14*/ "yacc", cincomment, coutcomment, + /*INAPL 15*/ "apl", ".lm", newline, + /*INMAKE 16*/ "make", ASINCOMMENT, newline, + /*INRI 17*/ "ri", riincomment, rioutcomment, + /*INTROFF 18*/ "troff",troffincomment,troffoutcomment, + /*INMOD2 19*/ "mod2", mod2incomment, mod2outcomment, + 0, 0, 0 +}; + +printerrors(look_at_subclass, errorc, errorv) + boolean look_at_subclass; + int errorc; + Eptr errorv[]; +{ + reg int i; + reg Eptr errorp; + + for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]){ + if (errorp->error_e_class == C_IGNORE) + continue; + if (look_at_subclass && errorp->error_s_class == C_DUPL) + continue; + printf("Error %d, (%s error) [%s], text = \"", + i, + class_table[errorp->error_e_class], + lang_table[errorp->error_language].lang_name); + wordvprint(stdout,errorp->error_lgtext,errorp->error_text); + printf("\"\n"); + } +} + +wordvprint(fyle, wordc, wordv) + FILE *fyle; + int wordc; + char *wordv[]; +{ + int i; + char *sep = ""; + + for(i = 0; i < wordc; i++) + if (wordv[i]) { + fprintf(fyle, "%s%s",sep,wordv[i]); + sep = " "; + } +} + +/* + * Given a string, parse it into a number of words, and build + * a wordc wordv combination pointing into it. + */ +wordvbuild(string, r_wordc, r_wordv) + char *string; + int *r_wordc; + char ***r_wordv; +{ + reg char *cp; + char *saltedbuffer; + char **wordv; + int wordcount; + int wordindex; + + saltedbuffer = strsave(string); + for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++){ + while (*cp && isspace(*cp)) + cp++; + if (*cp == 0) + break; + while (!isspace(*cp)) + cp++; + } + wordv = (char **)Calloc(wordcount + 1, sizeof (char *)); + for (cp=saltedbuffer,wordindex=0; wordcount; wordindex++,--wordcount){ + while (*cp && isspace(*cp)) + cp++; + if (*cp == 0) + break; + wordv[wordindex] = cp; + while(!isspace(*cp)) + cp++; + *cp++ = '\0'; + } + if (wordcount != 0) + error("Initial miscount of the number of words in a line\n"); + wordv[wordindex] = (char *)0; +#ifdef FULLDEBUG + for (wordcount = 0; wordcount < wordindex; wordcount++) + printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]); + printf("\n"); +#endif + *r_wordc = wordindex; + *r_wordv = wordv; +} +/* + * Compare two 0 based wordvectors + */ +int wordvcmp(wordv1, wordc, wordv2) + char **wordv1; + int wordc; + char **wordv2; +{ + reg int i; + int back; + for (i = 0; i < wordc; i++){ + if (wordv1[i] == 0 || wordv2[i] == 0) + return(-1); + if (back = strcmp(wordv1[i], wordv2[i])){ + return(back); + } + } + return(0); /* they are equal */ +} + +/* + * splice a 0 basedword vector onto the tail of a + * new wordv, allowing the first emptyhead slots to be empty + */ +char **wordvsplice(emptyhead, wordc, wordv) + int emptyhead; + int wordc; + char **wordv; +{ + reg char **nwordv; + int nwordc = emptyhead + wordc; + reg int i; + + nwordv = (char **)Calloc(nwordc, sizeof (char *)); + for (i = 0; i < emptyhead; i++) + nwordv[i] = 0; + for(i = emptyhead; i < nwordc; i++){ + nwordv[i] = wordv[i-emptyhead]; + } + return(nwordv); +} +/* + * plural'ize and verb forms + */ +static char *S = "s"; +static char *N = ""; +char *plural(n) + int n; +{ + return( n > 1 ? S : N); +} +char *verbform(n) + int n; +{ + return( n > 1 ? N : S); +} + diff --git a/usr/src/usr.bin/error/touch.c b/usr/src/usr.bin/error/touch.c new file mode 100644 index 0000000000..9a72b85ae2 --- /dev/null +++ b/usr/src/usr.bin/error/touch.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)touch.c 5.7 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "pathnames.h" + +/* + * Iterate through errors + */ +#define EITERATE(p, fv, i) for (p = fv[i]; p < fv[i+1]; p++) +#define ECITERATE(ei, p, lb) for (ei = lb; p = errors[ei],ei < nerrors; ei++) + +#define FILEITERATE(fi, lb) for (fi = lb; fi <= nfiles; fi++) +int touchstatus = Q_YES; + +findfiles(nerrors, errors, r_nfiles, r_files) + int nerrors; + Eptr *errors; + int *r_nfiles; + Eptr ***r_files; +{ + int nfiles; + Eptr **files; + + char *name; + reg int ei; + int fi; + reg Eptr errorp; + + nfiles = countfiles(errors); + + files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*)); + touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean)); + /* + * Now, partition off the error messages + * into those that are synchronization, discarded or + * not specific to any file, and those that were + * nulled or true errors. + */ + files[0] = &errors[0]; + ECITERATE(ei, errorp, 0){ + if ( ! (NOTSORTABLE(errorp->error_e_class))) + break; + } + /* + * Now, and partition off all error messages + * for a given file. + */ + files[1] = &errors[ei]; + touchedfiles[0] = touchedfiles[1] = FALSE; + name = "\1"; + fi = 1; + ECITERATE(ei, errorp, ei){ + if ( (errorp->error_e_class == C_NULLED) + || (errorp->error_e_class == C_TRUE) ){ + if (strcmp(errorp->error_text[0], name) != 0){ + name = errorp->error_text[0]; + touchedfiles[fi] = FALSE; + files[fi] = &errors[ei]; + fi++; + } + } + } + files[fi] = &errors[nerrors]; + *r_nfiles = nfiles; + *r_files = files; +} + +int countfiles(errors) + Eptr *errors; +{ + char *name; + int ei; + reg Eptr errorp; + + int nfiles; + nfiles = 0; + name = "\1"; + ECITERATE(ei, errorp, 0){ + if (SORTABLE(errorp->error_e_class)){ + if (strcmp(errorp->error_text[0],name) != 0){ + nfiles++; + name = errorp->error_text[0]; + } + } + } + return(nfiles); +} +char *class_table[] = { + /*C_UNKNOWN 0 */ "Unknown", + /*C_IGNORE 1 */ "ignore", + /*C_SYNC 2 */ "synchronization", + /*C_DISCARD 3 */ "discarded", + /*C_NONSPEC 4 */ "non specific", + /*C_THISFILE 5 */ "specific to this file", + /*C_NULLED 6 */ "nulled", + /*C_TRUE 7 */ "true", + /*C_DUPL 8 */ "duplicated" +}; + +int class_count[C_LAST - C_FIRST] = {0}; + +filenames(nfiles, files) + int nfiles; + Eptr **files; +{ + reg int fi; + char *sep = " "; + extern char *class_table[]; + int someerrors; + + /* + * first, simply dump out errors that + * don't pertain to any file + */ + someerrors = nopertain(files); + + if (nfiles){ + someerrors++; + fprintf(stdout, terse + ? "%d file%s" + : "%d file%s contain%s errors", + nfiles, plural(nfiles), verbform(nfiles)); + if (!terse){ + FILEITERATE(fi, 1){ + fprintf(stdout, "%s\"%s\" (%d)", + sep, (*files[fi])->error_text[0], + files[fi+1] - files[fi]); + sep = ", "; + } + } + fprintf(stdout, "\n"); + } + if (!someerrors) + fprintf(stdout, "No errors.\n"); +} + +/* + * Dump out errors that don't pertain to any file + */ +int nopertain(files) + Eptr **files; +{ + int type; + int someerrors = 0; + reg Eptr *erpp; + reg Eptr errorp; + + if (files[1] - files[0] <= 0) + return(0); + for(type = C_UNKNOWN; NOTSORTABLE(type); type++){ + if (class_count[type] <= 0) + continue; + if (type > C_SYNC) + someerrors++; + if (terse){ + fprintf(stdout, "\t%d %s errors NOT PRINTED\n", + class_count[type], class_table[type]); + } else { + fprintf(stdout, "\n\t%d %s errors follow\n", + class_count[type], class_table[type]); + EITERATE(erpp, files, 0){ + errorp = *erpp; + if (errorp->error_e_class == type){ + errorprint(stdout, errorp, TRUE); + } + } + } + } + return(someerrors); +} + +extern boolean notouch; + +boolean touchfiles(nfiles, files, r_edargc, r_edargv) + int nfiles; + Eptr **files; + int *r_edargc; + char ***r_edargv; +{ + char *name; + reg Eptr errorp; + reg int fi; + reg Eptr *erpp; + int ntrueerrors; + boolean scribbled; + int n_pissed_on; /* # of file touched*/ + int spread; + + FILEITERATE(fi, 1){ + name = (*files[fi])->error_text[0]; + spread = files[fi+1] - files[fi]; + fprintf(stdout, terse + ? "\"%s\" has %d error%s, " + : "\nFile \"%s\" has %d error%s.\n" + , name ,spread ,plural(spread)); + /* + * First, iterate through all error messages in this file + * to see how many of the error messages really will + * get inserted into the file. + */ + ntrueerrors = 0; + EITERATE(erpp, files, fi){ + errorp = *erpp; + if (errorp->error_e_class == C_TRUE) + ntrueerrors++; + } + fprintf(stdout, terse + ? "insert %d\n" + : "\t%d of these errors can be inserted into the file.\n", + ntrueerrors); + + hackfile(name, files, fi, ntrueerrors); + } + scribbled = FALSE; + n_pissed_on = 0; + FILEITERATE(fi, 1){ + scribbled |= touchedfiles[fi]; + n_pissed_on++; + } + if (scribbled){ + /* + * Construct an execv argument + */ + execvarg(n_pissed_on, r_edargc, r_edargv); + return(TRUE); + } else { + if (!terse) + fprintf(stdout, "You didn't touch any files.\n"); + return(FALSE); + } +} + +hackfile(name, files, ix, nerrors) + char *name; + Eptr **files; + int ix; +{ + boolean previewed; + int errordest; /* where errors go*/ + + if (!oktotouch(name)) { + previewed = FALSE; + errordest = TOSTDOUT; + } else { + previewed = preview(name, nerrors, files, ix); + errordest = settotouch(name); + } + + if (errordest != TOSTDOUT) + touchedfiles[ix] = TRUE; + + if (previewed && (errordest == TOSTDOUT)) + return; + + diverterrors(name, errordest, files, ix, previewed, nerrors); + + if (errordest == TOTHEFILE){ + /* + * overwrite the original file + */ + writetouched(1); + } +} + +boolean preview(name, nerrors, files, ix) + char *name; + int nerrors; + Eptr **files; + int ix; +{ + int back; + reg Eptr *erpp; + + if (nerrors <= 0) + return(FALSE); + back = FALSE; + if(query){ + switch(inquire(terse + ? "Preview? " + : "Do you want to preview the errors first? ")){ + case Q_YES: + case Q_yes: + back = TRUE; + EITERATE(erpp, files, ix){ + errorprint(stdout, *erpp, TRUE); + } + if (!terse) + fprintf(stdout, "\n"); + default: + break; + } + } + return(back); +} + +int settotouch(name) + char *name; +{ + int dest = TOSTDOUT; + + if (query){ + switch(touchstatus = inquire(terse + ? "Touch? " + : "Do you want to touch file \"%s\"? ", + name)){ + case Q_NO: + case Q_no: + return(dest); + default: + break; + } + } + + switch(probethisfile(name)){ + case F_NOTREAD: + dest = TOSTDOUT; + fprintf(stdout, terse + ? "\"%s\" unreadable\n" + : "File \"%s\" is unreadable\n", + name); + break; + case F_NOTWRITE: + dest = TOSTDOUT; + fprintf(stdout, terse + ? "\"%s\" unwritable\n" + : "File \"%s\" is unwritable\n", + name); + break; + case F_NOTEXIST: + dest = TOSTDOUT; + fprintf(stdout, terse + ? "\"%s\" not found\n" + : "Can't find file \"%s\" to insert error messages into.\n", + name); + break; + default: + dest = edit(name) ? TOSTDOUT : TOTHEFILE; + break; + } + return(dest); +} + +diverterrors(name, dest, files, ix, previewed, nterrors) + char *name; + int dest; + Eptr **files; + int ix; + boolean previewed; + int nterrors; +{ + int nerrors; + reg Eptr *erpp; + reg Eptr errorp; + + nerrors = files[ix+1] - files[ix]; + + if ( (nerrors != nterrors) + && (!previewed) ){ + fprintf(stdout, terse + ? "Uninserted errors\n" + : ">>Uninserted errors for file \"%s\" follow.\n", + name); + } + + EITERATE(erpp, files, ix){ + errorp = *erpp; + if (errorp->error_e_class != C_TRUE){ + if (previewed || touchstatus == Q_NO) + continue; + errorprint(stdout, errorp, TRUE); + continue; + } + switch (dest){ + case TOSTDOUT: + if (previewed || touchstatus == Q_NO) + continue; + errorprint(stdout,errorp, TRUE); + break; + case TOTHEFILE: + insert(errorp->error_line); + text(errorp, FALSE); + break; + } + } +} + +int oktotouch(filename) + char *filename; +{ + extern char *suffixlist; + reg char *src; + reg char *pat; + char *osrc; + + pat = suffixlist; + if (pat == 0) + return(0); + if (*pat == '*') + return(1); + while (*pat++ != '.') + continue; + --pat; /* point to the period */ + + for (src = &filename[strlen(filename)], --src; + (src > filename) && (*src != '.'); --src) + continue; + if (*src != '.') + return(0); + + for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){ + for (; *src /* not at end of the source */ + && *pat /* not off end of pattern */ + && *pat != '.' /* not off end of sub pattern */ + && *pat != '*' /* not wild card */ + && *src == *pat; /* and equal... */ + src++, pat++) + continue; + if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*')) + return(1); + if (*src != 0 && *pat == '*') + return(1); + while (*pat && *pat != '.') + pat++; + if (! *pat) + return(0); + } + return(0); +} +/* + * Construct an execv argument + * We need 1 argument for the editor's name + * We need 1 argument for the initial search string + * We need n_pissed_on arguments for the file names + * We need 1 argument that is a null for execv. + * The caller fills in the editor's name. + * We fill in the initial search string. + * We fill in the arguments, and the null. + */ +execvarg(n_pissed_on, r_argc, r_argv) + int n_pissed_on; + int *r_argc; + char ***r_argv; +{ + Eptr p; + char *sep; + int fi; + + (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *)); + (*r_argc) = n_pissed_on + 2; + (*r_argv)[1] = "+1;/###/"; + n_pissed_on = 2; + if (!terse){ + fprintf(stdout, "You touched file(s):"); + sep = " "; + } + FILEITERATE(fi, 1){ + if (!touchedfiles[fi]) + continue; + p = *(files[fi]); + if (!terse){ + fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]); + sep = ", "; + } + (*r_argv)[n_pissed_on++] = p->error_text[0]; + } + if (!terse) + fprintf(stdout, "\n"); + (*r_argv)[n_pissed_on] = 0; +} + +FILE *o_touchedfile; /* the old file */ +FILE *n_touchedfile; /* the new file */ +char *o_name; +char n_name[64]; +char *canon_name = _PATH_TMP; +int o_lineno; +int n_lineno; +boolean tempfileopen = FALSE; +/* + * open the file; guaranteed to be both readable and writable + * Well, if it isn't, then return TRUE if something failed + */ +boolean edit(name) + char *name; +{ + o_name = name; + if ( (o_touchedfile = fopen(name, "r")) == NULL){ + fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n", + processname, name); + return(TRUE); + } + (void)strcpy(n_name, canon_name); + (void)mktemp(n_name); + if ( (n_touchedfile = fopen(n_name, "w")) == NULL){ + fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n", + processname, name); + return(TRUE); + } + tempfileopen = TRUE; + n_lineno = 0; + o_lineno = 0; + return(FALSE); +} +/* + * Position to the line (before, after) the line given by place + */ +char edbuf[BUFSIZ]; +insert(place) + int place; +{ + --place; /* always insert messages before the offending line*/ + for(; o_lineno < place; o_lineno++, n_lineno++){ + if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL) + return; + fputs(edbuf, n_touchedfile); + } +} + +text(p, use_all) + reg Eptr p; + boolean use_all; +{ + int offset = use_all ? 0 : 2; + + fputs(lang_table[p->error_language].lang_incomment, n_touchedfile); + fprintf(n_touchedfile, "%d [%s] ", + p->error_line, + lang_table[p->error_language].lang_name); + wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset); + fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile); + n_lineno++; +} + +/* + * write the touched file to its temporary copy, + * then bring the temporary in over the local file + */ +writetouched(overwrite) + int overwrite; +{ + reg int nread; + reg FILE *localfile; + reg FILE *tmpfile; + int botch; + int oktorm; + + botch = 0; + oktorm = 1; + while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){ + if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){ + /* + * Catastrophe in temporary area: file system full? + */ + botch = 1; + fprintf(stderr, + "%s: write failure: No errors inserted in \"%s\"\n", + processname, o_name); + } + } + fclose(n_touchedfile); + fclose(o_touchedfile); + /* + * Now, copy the temp file back over the original + * file, thus preserving links, etc + */ + if (botch == 0 && overwrite){ + botch = 0; + localfile = NULL; + tmpfile = NULL; + if ((localfile = fopen(o_name, "w")) == NULL){ + fprintf(stderr, + "%s: Can't open file \"%s\" to overwrite.\n", + processname, o_name); + botch++; + } + if ((tmpfile = fopen(n_name, "r")) == NULL){ + fprintf(stderr, "%s: Can't open file \"%s\" to read.\n", + processname, n_name); + botch++; + } + if (!botch) + oktorm = mustoverwrite(localfile, tmpfile); + if (localfile != NULL) + fclose(localfile); + if (tmpfile != NULL) + fclose(tmpfile); + } + if (oktorm == 0){ + fprintf(stderr, "%s: Catastrophe: A copy of \"%s\": was saved in \"%s\"\n", + processname, o_name, n_name); + exit(1); + } + /* + * Kiss the temp file good bye + */ + unlink(n_name); + tempfileopen = FALSE; + return(TRUE); +} +/* + * return 1 if the tmpfile can be removed after writing it out + */ +int mustoverwrite(preciousfile, tmpfile) + FILE *preciousfile; + FILE *tmpfile; +{ + int nread; + + while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){ + if (mustwrite(edbuf, nread, preciousfile) == 0) + return(0); + } + return(1); +} +/* + * return 0 on catastrophe + */ +mustwrite(base, n, preciousfile) + char *base; + int n; + FILE *preciousfile; +{ + int nwrote; + + if (n <= 0) + return(1); + nwrote = fwrite(base, 1, n, preciousfile); + if (nwrote == n) + return(1); + perror(processname); + switch(inquire(terse + ? "Botch overwriting: retry? " + : "Botch overwriting the source file: retry? ")){ + case Q_YES: + case Q_yes: + mustwrite(base + nwrote, n - nwrote, preciousfile); + return(1); + case Q_NO: + case Q_no: + switch(inquire("Are you sure? ")){ + case Q_YES: + case Q_yes: + return(0); + case Q_NO: + case Q_no: + mustwrite(base + nwrote, n - nwrote, preciousfile); + return(1); + } + default: + return(0); + } +} + +void +onintr() +{ + switch(inquire(terse + ? "\nContinue? " + : "\nInterrupt: Do you want to continue? ")){ + case Q_YES: + case Q_yes: + signal(SIGINT, onintr); + return; + default: + if (tempfileopen){ + /* + * Don't overwrite the original file! + */ + writetouched(0); + } + exit(1); + } + /*NOTREACHED*/ +} + +errorprint(place, errorp, print_all) + FILE *place; + Eptr errorp; + boolean print_all; +{ + int offset = print_all ? 0 : 2; + + if (errorp->error_e_class == C_IGNORE) + return; + fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name); + wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset); + putc('\n', place); +} + +int inquire(fmt, a1, a2) + char *fmt; + /*VARARGS1*/ +{ + char buffer[128]; + + if (queryfile == NULL) + return(0); + for(;;){ + do{ + fflush(stdout); + fprintf(stderr, fmt, a1, a2); + fflush(stderr); + } while (fgets(buffer, 127, queryfile) == NULL); + switch(buffer[0]){ + case 'Y': return(Q_YES); + case 'y': return(Q_yes); + case 'N': return(Q_NO); + case 'n': return(Q_no); + default: fprintf(stderr, "Yes or No only!\n"); + } + } +} + +int probethisfile(name) + char *name; +{ + struct stat statbuf; + if (stat(name, &statbuf) < 0) + return(F_NOTEXIST); + if((statbuf.st_mode & S_IREAD) == 0) + return(F_NOTREAD); + if((statbuf.st_mode & S_IWRITE) == 0) + return(F_NOTWRITE); + return(F_TOUCHIT); +} diff --git a/usr/src/usr.bin/fpr/Makefile b/usr/src/usr.bin/fpr/Makefile new file mode 100644 index 0000000000..914d743ea3 --- /dev/null +++ b/usr/src/usr.bin/fpr/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 5.4 (Berkeley) 5/11/90 + +PROG= fpr + +.include diff --git a/usr/src/usr.bin/fpr/fpr.1 b/usr/src/usr.bin/fpr/fpr.1 new file mode 100644 index 0000000000..4a9f7e3fc6 --- /dev/null +++ b/usr/src/usr.bin/fpr/fpr.1 @@ -0,0 +1,83 @@ +.\" Copyright (c) 1989, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Robert Corbett. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)fpr.1 6.9 (Berkeley) 7/24/91 +.\" +.Dd July 24, 1991 +.Dt FPR 1 +.Os BSD 4.2 +.Sh NAME +.Nm fpr +.Nd print Fortran file +.Sh SYNOPSIS +.Nm fpr +.Sh DESCRIPTION +.Nm Fpr +is a filter that transforms files formatted according to +Fortran's carriage control conventions into files formatted +according to +.Ux +line printer conventions. +.Pp +.Nm Fpr +copies its input onto its output, replacing the carriage +control characters with characters that will produce the intended +effects when printed using +.Xr lpr 1 . +The first character of each line determines the vertical spacing as follows: +.Bd -ragged -offset indent -compact +.Bl -column Character +.It Blank One line +.It 0 Two lines +.It 1 To first line of next page +.It + No advance +.El +.Ed +.Pp +A blank line is treated as if its first +character is a blank. A blank that appears as a carriage control +character is deleted. A zero is changed to a newline. A one is +changed to a form feed. The effects of a "+" are simulated using +backspaces. +.Sh EXAMPLES +.Dl a.out \&| fpr \&| lpr +.Pp +.Dl fpr \&< f77.output \&| lpr +.Sh HISTORY +The +.Nm fpr +command +appeared in +.Bx 4.2 . +.Sh BUGS +Results are undefined for input lines longer than 170 characters. diff --git a/usr/src/usr.bin/fpr/fpr.c b/usr/src/usr.bin/fpr/fpr.c new file mode 100644 index 0000000000..109d8e06f1 --- /dev/null +++ b/usr/src/usr.bin/fpr/fpr.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Corbett. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)fpr.c 5.4 (Berkeley) 2/6/91"; +#endif /* not lint */ + +#include + +#define BLANK ' ' +#define TAB '\t' +#define NUL '\000' +#define FF '\f' +#define BS '\b' +#define CR '\r' +#define VTAB '\013' +#define EOL '\n' + +#define TRUE 1 +#define FALSE 0 + +#define MAXCOL 170 +#define TABSIZE 8 +#define INITWIDTH 8 + +typedef + struct column + { + int count; + int width; + char *str; + } + COLUMN; + +char cc; +char saved; +int length; +char *text; +int highcol; +COLUMN *line; +int maxpos; +int maxcol; + +extern char *malloc(); +extern char *calloc(); +extern char *realloc(); + + + +main() +{ + register int ch; + register char ateof; + register int i; + register int errorcount; + + + init(); + errorcount = 0; + ateof = FALSE; + + ch = getchar(); + if (ch == EOF) + exit(0); + + if (ch == EOL) + { + cc = NUL; + ungetc((int) EOL, stdin); + } + else if (ch == BLANK) + cc = NUL; + else if (ch == '1') + cc = FF; + else if (ch == '0') + cc = EOL; + else if (ch == '+') + cc = CR; + else + { + errorcount = 1; + cc = NUL; + ungetc(ch, stdin); + } + + while ( ! ateof) + { + gettext(); + ch = getchar(); + if (ch == EOF) + { + flush(); + ateof = TRUE; + } + else if (ch == EOL) + { + flush(); + cc = NUL; + ungetc((int) EOL, stdin); + } + else if (ch == BLANK) + { + flush(); + cc = NUL; + } + else if (ch == '1') + { + flush(); + cc = FF; + } + else if (ch == '0') + { + flush(); + cc = EOL; + } + else if (ch == '+') + { + for (i = 0; i < length; i++) + savech(i); + } + else + { + errorcount++; + flush(); + cc = NUL; + ungetc(ch, stdin); + } + } + + if (errorcount == 1) + fprintf(stderr, "Illegal carriage control - 1 line.\n"); + else if (errorcount > 1) + fprintf(stderr, "Illegal carriage control - %d lines.\n", errorcount); + + exit(0); +} + + + +init() +{ + register COLUMN *cp; + register COLUMN *cend; + register char *sp; + + + length = 0; + maxpos = MAXCOL; + sp = malloc((unsigned) maxpos); + if (sp == NULL) + nospace(); + text = sp; + + highcol = -1; + maxcol = MAXCOL; + line = (COLUMN *) calloc(maxcol, (unsigned) sizeof(COLUMN)); + if (line == NULL) + nospace(); + cp = line; + cend = line + (maxcol-1); + while (cp <= cend) + { + cp->width = INITWIDTH; + sp = calloc(INITWIDTH, (unsigned) sizeof(char)); + if (sp == NULL) + nospace(); + cp->str = sp; + cp++; + } +} + + + +gettext() +{ + register int i; + register char ateol; + register int ch; + register int pos; + + + i = 0; + ateol = FALSE; + + while ( ! ateol) + { + ch = getchar(); + if (ch == EOL || ch == EOF) + ateol = TRUE; + else if (ch == TAB) + { + pos = (1 + i/TABSIZE) * TABSIZE; + if (pos > maxpos) + { + maxpos = pos + 10; + text = realloc(text, (unsigned) maxpos); + if (text == NULL) + nospace(); + } + while (i < pos) + { + text[i] = BLANK; + i++; + } + } + else if (ch == BS) + { + if (i > 0) + { + i--; + savech(i); + } + } + else if (ch == CR) + { + while (i > 0) + { + i--; + savech(i); + } + } + else if (ch == FF || ch == VTAB) + { + flush(); + cc = ch; + i = 0; + } + else + { + if (i >= maxpos) + { + maxpos = i + 10; + text = realloc(text, (unsigned) maxpos); + if (text == NULL) + nospace(); + } + text[i] = ch; + i++; + } + } + + length = i; +} + + + +savech(col) +int col; +{ + register char ch; + register int oldmax; + register COLUMN *cp; + register COLUMN *cend; + register char *sp; + register int newcount; + + + ch = text[col]; + if (ch == BLANK) + return; + + saved = TRUE; + + if (col >= highcol) + highcol = col; + + if (col >= maxcol) + { + oldmax = maxcol; + maxcol = col + 10; + line = (COLUMN *) realloc(line, (unsigned) maxcol*sizeof(COLUMN)); + if (line == NULL) + nospace(); + cp = line + oldmax; + cend = line + (maxcol - 1); + while (cp <= cend) + { + cp->width = INITWIDTH; + cp->count = 0; + sp = calloc(INITWIDTH, (unsigned) sizeof(char)); + if (sp == NULL) + nospace(); + cp->str = sp; + cp++; + } + } + + cp = line + col; + newcount = cp->count + 1; + if (newcount > cp->width) + { + cp->width = newcount; + sp = realloc(cp->str, (unsigned) newcount*sizeof(char)); + if (sp == NULL) + nospace(); + cp->str = sp; + } + cp->count = newcount; + cp->str[newcount-1] = ch; +} + + + +flush() +{ + register int i; + register int anchor; + register int height; + register int j; + + + if (cc != NUL) + putchar(cc); + + if ( ! saved) + { + i = length; + while (i > 0 && text[i-1] == BLANK) + i--; + length = i; + for (i = 0; i < length; i++) + putchar(text[i]); + putchar(EOL); + return; + } + + for (i =0; i < length; i++) + savech(i); + + anchor = 0; + while (anchor <= highcol) + { + height = line[anchor].count; + if (height == 0) + { + putchar(BLANK); + anchor++; + } + else if (height == 1) + { + putchar( *(line[anchor].str) ); + line[anchor].count = 0; + anchor++; + } + else + { + i = anchor; + while (i < highcol && line[i+1].count > 1) + i++; + for (j = anchor; j <= i; j++) + { + height = line[j].count - 1; + putchar(line[j].str[height]); + line[j].count = height; + } + for (j = anchor; j <= i; j++) + putchar(BS); + } + } + + putchar(EOL); + highcol = -1; +} + + + +nospace() +{ + fputs("Storage limit exceeded.\n", stderr); + exit(1); +} diff --git a/usr/src/usr.bin/fsplit/Makefile b/usr/src/usr.bin/fsplit/Makefile new file mode 100644 index 0000000000..b904fef1cd --- /dev/null +++ b/usr/src/usr.bin/fsplit/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 5.5 (Berkeley) 5/11/90 + +PROG= fsplit + +.include diff --git a/usr/src/usr.bin/fsplit/fsplit.1 b/usr/src/usr.bin/fsplit/fsplit.1 new file mode 100644 index 0000000000..196ee2ecce --- /dev/null +++ b/usr/src/usr.bin/fsplit/fsplit.1 @@ -0,0 +1,103 @@ +.\" Copyright (c) 1983, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Asa Romberger and Jerry Berkman. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)fsplit.1 6.7 (Berkeley) 7/24/91 +.\" +.Dd July 24, 1991 +.Dt FSPLIT 1 +.Os BSD 4.2 +.Sh NAME +.Nm fsplit +.Nd split a multi-routine Fortran file into individual files +.Sh SYNOPSIS +.Nm fsplit +.Op Fl e Ar efile +\&... +.Op Ar file +.Sh DESCRIPTION +.Nm Fsplit +takes as input either a file or standard input containing Fortran source code. +It attempts to split the input into separate routine files of the +form +.Ar name.f , +where +.Ar name +is the name of the program unit (e.g. function, subroutine, block data or +program). The name for unnamed block data subprograms has the form +.Ar blkdtaNNN.f +where NNN is three digits and a file of this name does not already exist. +For unnamed main programs the name has the form +.Ar mainNNN.f . +If there is an error in classifying a program unit, or if +.Ar name.f +already exists, +the program unit will be put in a file of the form +.Ar zzzNNN.f +where +.Ar zzzNNN.f +does not already exist. +.Pp +.Bl -tag -width Fl +.It Fl e Ar efile +Normally each subprogram unit is split into a separate file. When the +.Fl e +option is used, only the specified subprogram units are split into separate +files. E.g.: +.Pp +.Dl fsplit -e readit -e doit prog.f +.Pp +will split readit and doit into separate files. +.El +.Sh DIAGNOSTICS +If names specified via the +.Fl e +option are not found, a diagnostic is written to +standard error. +.Sh HISTORY +The +.Nm fsplit +command +appeared in +.Bx 4.2 . +.Sh AUTHORS +Asa Romberger and Jerry Berkman +.Sh BUGS +.Nm Fsplit +assumes the subprogram name is on the first noncomment line of the subprogram +unit. Nonstandard source formats may confuse +.Nm fsplit . +.Pp +It is hard to use +.Fl e +for unnamed main programs and block data subprograms since you must +predict the created file name. diff --git a/usr/src/usr.bin/fsplit/fsplit.c b/usr/src/usr.bin/fsplit/fsplit.c new file mode 100644 index 0000000000..6e5ddb61ce --- /dev/null +++ b/usr/src/usr.bin/fsplit/fsplit.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 1983 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Asa Romberger and Jerry Berkman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1983 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)fsplit.c 5.5 (Berkeley) 3/12/91"; +#endif /* not lint */ + +#include +#include +#include +#include + +/* + * usage: fsplit [-e efile] ... [file] + * + * split single file containing source for several fortran programs + * and/or subprograms into files each containing one + * subprogram unit. + * each separate file will be named using the corresponding subroutine, + * function, block data or program name if one is found; otherwise + * the name will be of the form mainNNN.f or blkdtaNNN.f . + * If a file of that name exists, it is saved in a name of the + * form zzz000.f . + * If -e option is used, then only those subprograms named in the -e + * option are split off; e.g.: + * fsplit -esub1 -e sub2 prog.f + * isolates sub1 and sub2 in sub1.f and sub2.f. The space + * after -e is optional. + * + * Modified Feb., 1983 by Jerry Berkman, Computing Services, U.C. Berkeley. + * - added comments + * - more function types: double complex, character*(*), etc. + * - fixed minor bugs + * - instead of all unnamed going into zNNN.f, put mains in + * mainNNN.f, block datas in blkdtaNNN.f, dups in zzzNNN.f . + */ + +#define BSZ 512 +char buf[BSZ]; +FILE *ifp; +char x[]="zzz000.f", + mainp[]="main000.f", + blkp[]="blkdta000.f"; +char *look(), *skiplab(), *functs(); + +#define TRUE 1 +#define FALSE 0 +int extr = FALSE, + extrknt = -1, + extrfnd[100]; +char extrbuf[1000], + *extrnames[100]; +struct stat sbuf; + +#define trim(p) while (*p == ' ' || *p == '\t') p++ + +main(argc, argv) +char **argv; +{ + register FILE *ofp; /* output file */ + register rv; /* 1 if got card in output file, 0 otherwise */ + register char *ptr; + int nflag, /* 1 if got name of subprog., 0 otherwise */ + retval, + i; + char name[20], + *extrptr = extrbuf; + + /* scan -e options */ + while ( argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e') { + extr = TRUE; + ptr = argv[1] + 2; + if(!*ptr) { + argc--; + argv++; + if(argc <= 1) badparms(); + ptr = argv[1]; + } + extrknt = extrknt + 1; + extrnames[extrknt] = extrptr; + extrfnd[extrknt] = FALSE; + while(*ptr) *extrptr++ = *ptr++; + *extrptr++ = 0; + argc--; + argv++; + } + + if (argc > 2) + badparms(); + else if (argc == 2) { + if ((ifp = fopen(argv[1], "r")) == NULL) { + fprintf(stderr, "fsplit: cannot open %s\n", argv[1]); + exit(1); + } + } + else + ifp = stdin; + for(;;) { + /* look for a temp file that doesn't correspond to an existing file */ + get_name(x, 3); + ofp = fopen(x, "w"); + nflag = 0; + rv = 0; + while (getline() > 0) { + rv = 1; + fprintf(ofp, "%s", buf); + if (lend()) /* look for an 'end' statement */ + break; + if (nflag == 0) /* if no name yet, try and find one */ + nflag = lname(name); + } + fclose(ofp); + if (rv == 0) { /* no lines in file, forget the file */ + unlink(x); + retval = 0; + for ( i = 0; i <= extrknt; i++ ) + if(!extrfnd[i]) { + retval = 1; + fprintf( stderr, "fsplit: %s not found\n", + extrnames[i]); + } + exit( retval ); + } + if (nflag) { /* rename the file */ + if(saveit(name)) { + if (stat(name, &sbuf) < 0 ) { + link(x, name); + unlink(x); + printf("%s\n", name); + continue; + } else if (strcmp(name, x) == 0) { + printf("%s\n", x); + continue; + } + printf("%s already exists, put in %s\n", name, x); + continue; + } else + unlink(x); + continue; + } + if(!extr) + printf("%s\n", x); + else + unlink(x); + } +} + +badparms() +{ + fprintf(stderr, "fsplit: usage: fsplit [-e efile] ... [file] \n"); + exit(1); +} + +saveit(name) +char *name; +{ + int i; + char fname[50], + *fptr = fname; + + if(!extr) return(1); + while(*name) *fptr++ = *name++; + *--fptr = 0; + *--fptr = 0; + for ( i=0 ; i<=extrknt; i++ ) + if( strcmp(fname, extrnames[i]) == 0 ) { + extrfnd[i] = TRUE; + return(1); + } + return(0); +} + +get_name(name, letters) +char *name; +int letters; +{ + register char *ptr; + + while (stat(name, &sbuf) >= 0) { + for (ptr = name + letters + 2; ptr >= name + letters; ptr--) { + (*ptr)++; + if (*ptr <= '9') + break; + *ptr = '0'; + } + if(ptr < name + letters) { + fprintf( stderr, "fsplit: ran out of file names\n"); + exit(1); + } + } +} + +getline() +{ + register char *ptr; + + for (ptr = buf; ptr < &buf[BSZ]; ) { + *ptr = getc(ifp); + if (feof(ifp)) + return (-1); + if (*ptr++ == '\n') { + *ptr = 0; + return (1); + } + } + while (getc(ifp) != '\n' && feof(ifp) == 0) ; + fprintf(stderr, "line truncated to %d characters\n", BSZ); + return (1); +} + +/* return 1 for 'end' alone on card (up to col. 72), 0 otherwise */ +lend() +{ + register char *p; + + if ((p = skiplab(buf)) == 0) + return (0); + trim(p); + if (*p != 'e' && *p != 'E') return(0); + p++; + trim(p); + if (*p != 'n' && *p != 'N') return(0); + p++; + trim(p); + if (*p != 'd' && *p != 'D') return(0); + p++; + trim(p); + if (p - buf >= 72 || *p == '\n') + return (1); + return (0); +} + +/* check for keywords for subprograms + return 0 if comment card, 1 if found + name and put in arg string. invent name for unnamed + block datas and main programs. */ +lname(s) +char *s; +{ +# define LINESIZE 80 + register char *ptr, *p, *sptr; + char line[LINESIZE], *iptr = line; + + /* first check for comment cards */ + if(buf[0] == 'c' || buf[0] == 'C' || buf[0] == '*') return(0); + ptr = buf; + while (*ptr == ' ' || *ptr == '\t') ptr++; + if(*ptr == '\n') return(0); + + + ptr = skiplab(buf); + if (ptr == 0) + return (0); + + + /* copy to buffer and converting to lower case */ + p = ptr; + while (*p && p <= &buf[71] ) { + *iptr = isupper(*p) ? tolower(*p) : *p; + iptr++; + p++; + } + *iptr = '\n'; + + if ((ptr = look(line, "subroutine")) != 0 || + (ptr = look(line, "function")) != 0 || + (ptr = functs(line)) != 0) { + if(scan_name(s, ptr)) return(1); + strcpy( s, x); + } else if((ptr = look(line, "program")) != 0) { + if(scan_name(s, ptr)) return(1); + get_name( mainp, 4); + strcpy( s, mainp); + } else if((ptr = look(line, "blockdata")) != 0) { + if(scan_name(s, ptr)) return(1); + get_name( blkp, 6); + strcpy( s, blkp); + } else if((ptr = functs(line)) != 0) { + if(scan_name(s, ptr)) return(1); + strcpy( s, x); + } else { + get_name( mainp, 4); + strcpy( s, mainp); + } + return(1); +} + +scan_name(s, ptr) +char *s, *ptr; +{ + char *sptr; + + /* scan off the name */ + trim(ptr); + sptr = s; + while (*ptr != '(' && *ptr != '\n') { + if (*ptr != ' ' && *ptr != '\t') + *sptr++ = *ptr; + ptr++; + } + + if (sptr == s) return(0); + + *sptr++ = '.'; + *sptr++ = 'f'; + *sptr++ = 0; + return(1); +} + +char *functs(p) +char *p; +{ + register char *ptr; + +/* look for typed functions such as: real*8 function, + character*16 function, character*(*) function */ + + if((ptr = look(p,"character")) != 0 || + (ptr = look(p,"logical")) != 0 || + (ptr = look(p,"real")) != 0 || + (ptr = look(p,"integer")) != 0 || + (ptr = look(p,"doubleprecision")) != 0 || + (ptr = look(p,"complex")) != 0 || + (ptr = look(p,"doublecomplex")) != 0 ) { + while ( *ptr == ' ' || *ptr == '\t' || *ptr == '*' + || (*ptr >= '0' && *ptr <= '9') + || *ptr == '(' || *ptr == ')') ptr++; + ptr = look(ptr,"function"); + return(ptr); + } + else + return(0); +} + +/* if first 6 col. blank, return ptr to col. 7, + if blanks and then tab, return ptr after tab, + else return 0 (labelled statement, comment or continuation */ +char *skiplab(p) +char *p; +{ + register char *ptr; + + for (ptr = p; ptr < &p[6]; ptr++) { + if (*ptr == ' ') + continue; + if (*ptr == '\t') { + ptr++; + break; + } + return (0); + } + return (ptr); +} + +/* return 0 if m doesn't match initial part of s; + otherwise return ptr to next char after m in s */ +char *look(s, m) +char *s, *m; +{ + register char *sp, *mp; + + sp = s; mp = m; + while (*mp) { + trim(sp); + if (*sp++ != *mp++) + return (0); + } + return (sp); +} diff --git a/usr/src/usr.bin/gprof/Makefile b/usr/src/usr.bin/gprof/Makefile new file mode 100644 index 0000000000..ba6d081a3a --- /dev/null +++ b/usr/src/usr.bin/gprof/Makefile @@ -0,0 +1,13 @@ +# @(#)Makefile 5.17 (Berkeley) 5/11/90 + +PROG= gprof +SRCS= gprof.c arcs.c dfn.c lookup.c ${MACHINE}.c hertz.c \ + printgprof.c printlist.c +CFLAGS+=-I${.CURDIR}/../../lib/csu.${MACHINE} + +beforeinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/gprof.flat ${.CURDIR}/gprof.callg \ + ${DESTDIR}/usr/share/misc + +.include diff --git a/usr/src/usr.bin/gprof/arcs.c b/usr/src/usr.bin/gprof/arcs.c new file mode 100644 index 0000000000..42c25ff6bb --- /dev/null +++ b/usr/src/usr.bin/gprof/arcs.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)arcs.c 5.6 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include "gprof.h" + + /* + * add (or just increment) an arc + */ +addarc( parentp , childp , count ) + nltype *parentp; + nltype *childp; + long count; +{ + arctype *calloc(); + arctype *arcp; + +# ifdef DEBUG + if ( debug & TALLYDEBUG ) { + printf( "[addarc] %d arcs from %s to %s\n" , + count , parentp -> name , childp -> name ); + } +# endif DEBUG + arcp = arclookup( parentp , childp ); + if ( arcp != 0 ) { + /* + * a hit: just increment the count. + */ +# ifdef DEBUG + if ( debug & TALLYDEBUG ) { + printf( "[tally] hit %d += %d\n" , + arcp -> arc_count , count ); + } +# endif DEBUG + arcp -> arc_count += count; + return; + } + arcp = calloc( 1 , sizeof *arcp ); + arcp -> arc_parentp = parentp; + arcp -> arc_childp = childp; + arcp -> arc_count = count; + /* + * prepend this child to the children of this parent + */ + arcp -> arc_childlist = parentp -> children; + parentp -> children = arcp; + /* + * prepend this parent to the parents of this child + */ + arcp -> arc_parentlist = childp -> parents; + childp -> parents = arcp; +} + + /* + * the code below topologically sorts the graph (collapsing cycles), + * and propagates time bottom up and flags top down. + */ + + /* + * the topologically sorted name list pointers + */ +nltype **topsortnlp; + +topcmp( npp1 , npp2 ) + nltype **npp1; + nltype **npp2; +{ + return (*npp1) -> toporder - (*npp2) -> toporder; +} + +nltype ** +doarcs() +{ + nltype *parentp, **timesortnlp; + arctype *arcp; + long index; + + /* + * initialize various things: + * zero out child times. + * count self-recursive calls. + * indicate that nothing is on cycles. + */ + for ( parentp = nl ; parentp < npe ; parentp++ ) { + parentp -> childtime = 0.0; + arcp = arclookup( parentp , parentp ); + if ( arcp != 0 ) { + parentp -> ncall -= arcp -> arc_count; + parentp -> selfcalls = arcp -> arc_count; + } else { + parentp -> selfcalls = 0; + } + parentp -> propfraction = 0.0; + parentp -> propself = 0.0; + parentp -> propchild = 0.0; + parentp -> printflag = FALSE; + parentp -> toporder = DFN_NAN; + parentp -> cycleno = 0; + parentp -> cyclehead = parentp; + parentp -> cnext = 0; + if ( cflag ) { + findcall( parentp , parentp -> value , (parentp+1) -> value ); + } + } + /* + * topologically order things + * if any node is unnumbered, + * number it and any of its descendents. + */ + for ( parentp = nl ; parentp < npe ; parentp++ ) { + if ( parentp -> toporder == DFN_NAN ) { + dfn( parentp ); + } + } + /* + * link together nodes on the same cycle + */ + cyclelink(); + /* + * Sort the symbol table in reverse topological order + */ + topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); + if ( topsortnlp == (nltype **) 0 ) { + fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); + } + for ( index = 0 ; index < nname ; index += 1 ) { + topsortnlp[ index ] = &nl[ index ]; + } + qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[doarcs] topological sort listing\n" ); + for ( index = 0 ; index < nname ; index += 1 ) { + printf( "[doarcs] " ); + printf( "%d:" , topsortnlp[ index ] -> toporder ); + printname( topsortnlp[ index ] ); + printf( "\n" ); + } + } +# endif DEBUG + /* + * starting from the topological top, + * propagate print flags to children. + * also, calculate propagation fractions. + * this happens before time propagation + * since time propagation uses the fractions. + */ + doflags(); + /* + * starting from the topological bottom, + * propogate children times up to parents. + */ + dotime(); + /* + * Now, sort by propself + propchild. + * sorting both the regular function names + * and cycle headers. + */ + timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); + if ( timesortnlp == (nltype **) 0 ) { + fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); + } + for ( index = 0 ; index < nname ; index++ ) { + timesortnlp[index] = &nl[index]; + } + for ( index = 1 ; index <= ncycle ; index++ ) { + timesortnlp[nname+index-1] = &cyclenl[index]; + } + qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); + for ( index = 0 ; index < nname + ncycle ; index++ ) { + timesortnlp[ index ] -> index = index + 1; + } + return( timesortnlp ); +} + +dotime() +{ + int index; + + cycletime(); + for ( index = 0 ; index < nname ; index += 1 ) { + timepropagate( topsortnlp[ index ] ); + } +} + +timepropagate( parentp ) + nltype *parentp; +{ + arctype *arcp; + nltype *childp; + double share; + double propshare; + + if ( parentp -> propfraction == 0.0 ) { + return; + } + /* + * gather time from children of this parent. + */ + for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { + childp = arcp -> arc_childp; + if ( arcp -> arc_count == 0 ) { + continue; + } + if ( childp == parentp ) { + continue; + } + if ( childp -> propfraction == 0.0 ) { + continue; + } + if ( childp -> cyclehead != childp ) { + if ( parentp -> cycleno == childp -> cycleno ) { + continue; + } + if ( parentp -> toporder <= childp -> toporder ) { + fprintf( stderr , "[propagate] toporder botches\n" ); + } + childp = childp -> cyclehead; + } else { + if ( parentp -> toporder <= childp -> toporder ) { + fprintf( stderr , "[propagate] toporder botches\n" ); + continue; + } + } + if ( childp -> ncall == 0 ) { + continue; + } + /* + * distribute time for this arc + */ + arcp -> arc_time = childp -> time + * ( ( (double) arcp -> arc_count ) / + ( (double) childp -> ncall ) ); + arcp -> arc_childtime = childp -> childtime + * ( ( (double) arcp -> arc_count ) / + ( (double) childp -> ncall ) ); + share = arcp -> arc_time + arcp -> arc_childtime; + parentp -> childtime += share; + /* + * ( 1 - propfraction ) gets lost along the way + */ + propshare = parentp -> propfraction * share; + /* + * fix things for printing + */ + parentp -> propchild += propshare; + arcp -> arc_time *= parentp -> propfraction; + arcp -> arc_childtime *= parentp -> propfraction; + /* + * add this share to the parent's cycle header, if any. + */ + if ( parentp -> cyclehead != parentp ) { + parentp -> cyclehead -> childtime += share; + parentp -> cyclehead -> propchild += propshare; + } +# ifdef DEBUG + if ( debug & PROPDEBUG ) { + printf( "[dotime] child \t" ); + printname( childp ); + printf( " with %f %f %d/%d\n" , + childp -> time , childp -> childtime , + arcp -> arc_count , childp -> ncall ); + printf( "[dotime] parent\t" ); + printname( parentp ); + printf( "\n[dotime] share %f\n" , share ); + } +# endif DEBUG + } +} + +cyclelink() +{ + register nltype *nlp; + register nltype *cyclenlp; + int cycle; + nltype *memberp; + arctype *arcp; + + /* + * Count the number of cycles, and initialze the cycle lists + */ + ncycle = 0; + for ( nlp = nl ; nlp < npe ; nlp++ ) { + /* + * this is how you find unattached cycles + */ + if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { + ncycle += 1; + } + } + /* + * cyclenl is indexed by cycle number: + * i.e. it is origin 1, not origin 0. + */ + cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); + if ( cyclenl == 0 ) { + fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" , + whoami , ( ncycle + 1 ) * sizeof( nltype ) ); + done(); + } + /* + * now link cycles to true cycleheads, + * number them, accumulate the data for the cycle + */ + cycle = 0; + for ( nlp = nl ; nlp < npe ; nlp++ ) { + if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { + continue; + } + cycle += 1; + cyclenlp = &cyclenl[cycle]; + cyclenlp -> name = 0; /* the name */ + cyclenlp -> value = 0; /* the pc entry point */ + cyclenlp -> time = 0.0; /* ticks in this routine */ + cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ + cyclenlp -> ncall = 0; /* how many times called */ + cyclenlp -> selfcalls = 0; /* how many calls to self */ + cyclenlp -> propfraction = 0.0; /* what % of time propagates */ + cyclenlp -> propself = 0.0; /* how much self time propagates */ + cyclenlp -> propchild = 0.0; /* how much child time propagates */ + cyclenlp -> printflag = TRUE; /* should this be printed? */ + cyclenlp -> index = 0; /* index in the graph list */ + cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ + cyclenlp -> cycleno = cycle; /* internal number of cycle on */ + cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ + cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ + cyclenlp -> parents = 0; /* list of caller arcs */ + cyclenlp -> children = 0; /* list of callee arcs */ +# ifdef DEBUG + if ( debug & CYCLEDEBUG ) { + printf( "[cyclelink] " ); + printname( nlp ); + printf( " is the head of cycle %d\n" , cycle ); + } +# endif DEBUG + /* + * link members to cycle header + */ + for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { + memberp -> cycleno = cycle; + memberp -> cyclehead = cyclenlp; + } + /* + * count calls from outside the cycle + * and those among cycle members + */ + for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { + for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { + if ( arcp -> arc_parentp == memberp ) { + continue; + } + if ( arcp -> arc_parentp -> cycleno == cycle ) { + cyclenlp -> selfcalls += arcp -> arc_count; + } else { + cyclenlp -> ncall += arcp -> arc_count; + } + } + } + } +} + +cycletime() +{ + int cycle; + nltype *cyclenlp; + nltype *childp; + + for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { + cyclenlp = &cyclenl[ cycle ]; + for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { + if ( childp -> propfraction == 0.0 ) { + /* + * all members have the same propfraction except those + * that were excluded with -E + */ + continue; + } + cyclenlp -> time += childp -> time; + } + cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; + } +} + + /* + * in one top to bottom pass over the topologically sorted namelist + * propagate: + * printflag as the union of parents' printflags + * propfraction as the sum of fractional parents' propfractions + * and while we're here, sum time for functions. + */ +doflags() +{ + int index; + nltype *childp; + nltype *oldhead; + + oldhead = 0; + for ( index = nname-1 ; index >= 0 ; index -= 1 ) { + childp = topsortnlp[ index ]; + /* + * if we haven't done this function or cycle, + * inherit things from parent. + * this way, we are linear in the number of arcs + * since we do all members of a cycle (and the cycle itself) + * as we hit the first member of the cycle. + */ + if ( childp -> cyclehead != oldhead ) { + oldhead = childp -> cyclehead; + inheritflags( childp ); + } +# ifdef DEBUG + if ( debug & PROPDEBUG ) { + printf( "[doflags] " ); + printname( childp ); + printf( " inherits printflag %d and propfraction %f\n" , + childp -> printflag , childp -> propfraction ); + } +# endif DEBUG + if ( ! childp -> printflag ) { + /* + * printflag is off + * it gets turned on by + * being on -f list, + * or there not being any -f list and not being on -e list. + */ + if ( onlist( flist , childp -> name ) + || ( !fflag && !onlist( elist , childp -> name ) ) ) { + childp -> printflag = TRUE; + } + } else { + /* + * this function has printing parents: + * maybe someone wants to shut it up + * by putting it on -e list. (but favor -f over -e) + */ + if ( ( !onlist( flist , childp -> name ) ) + && onlist( elist , childp -> name ) ) { + childp -> printflag = FALSE; + } + } + if ( childp -> propfraction == 0.0 ) { + /* + * no parents to pass time to. + * collect time from children if + * its on -F list, + * or there isn't any -F list and its not on -E list. + */ + if ( onlist( Flist , childp -> name ) + || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { + childp -> propfraction = 1.0; + } + } else { + /* + * it has parents to pass time to, + * but maybe someone wants to shut it up + * by puttting it on -E list. (but favor -F over -E) + */ + if ( !onlist( Flist , childp -> name ) + && onlist( Elist , childp -> name ) ) { + childp -> propfraction = 0.0; + } + } + childp -> propself = childp -> time * childp -> propfraction; + printtime += childp -> propself; +# ifdef DEBUG + if ( debug & PROPDEBUG ) { + printf( "[doflags] " ); + printname( childp ); + printf( " ends up with printflag %d and propfraction %f\n" , + childp -> printflag , childp -> propfraction ); + printf( "time %f propself %f printtime %f\n" , + childp -> time , childp -> propself , printtime ); + } +# endif DEBUG + } +} + + /* + * check if any parent of this child + * (or outside parents of this cycle) + * have their print flags on and set the + * print flag of the child (cycle) appropriately. + * similarly, deal with propagation fractions from parents. + */ +inheritflags( childp ) + nltype *childp; +{ + nltype *headp; + arctype *arcp; + nltype *parentp; + nltype *memp; + + headp = childp -> cyclehead; + if ( childp == headp ) { + /* + * just a regular child, check its parents + */ + childp -> printflag = FALSE; + childp -> propfraction = 0.0; + for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { + parentp = arcp -> arc_parentp; + if ( childp == parentp ) { + continue; + } + childp -> printflag |= parentp -> printflag; + /* + * if the child was never actually called + * (e.g. this arc is static (and all others are, too)) + * no time propagates along this arc. + */ + if ( childp -> ncall ) { + childp -> propfraction += parentp -> propfraction + * ( ( (double) arcp -> arc_count ) + / ( (double) childp -> ncall ) ); + } + } + } else { + /* + * its a member of a cycle, look at all parents from + * outside the cycle + */ + headp -> printflag = FALSE; + headp -> propfraction = 0.0; + for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { + for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { + if ( arcp -> arc_parentp -> cyclehead == headp ) { + continue; + } + parentp = arcp -> arc_parentp; + headp -> printflag |= parentp -> printflag; + /* + * if the cycle was never actually called + * (e.g. this arc is static (and all others are, too)) + * no time propagates along this arc. + */ + if ( headp -> ncall ) { + headp -> propfraction += parentp -> propfraction + * ( ( (double) arcp -> arc_count ) + / ( (double) headp -> ncall ) ); + } + } + } + for ( memp = headp ; memp ; memp = memp -> cnext ) { + memp -> printflag = headp -> printflag; + memp -> propfraction = headp -> propfraction; + } + } +} diff --git a/usr/src/usr.bin/gprof/dfn.c b/usr/src/usr.bin/gprof/dfn.c new file mode 100644 index 0000000000..f2c3d880c3 --- /dev/null +++ b/usr/src/usr.bin/gprof/dfn.c @@ -0,0 +1,316 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)dfn.c 5.4 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include +#include "gprof.h" + +#define DFN_DEPTH 100 +struct dfnstruct { + nltype *nlentryp; + int cycletop; +}; +typedef struct dfnstruct dfntype; + +dfntype dfn_stack[ DFN_DEPTH ]; +int dfn_depth = 0; + +int dfn_counter = DFN_NAN; + + /* + * given this parent, depth first number its children. + */ +dfn( parentp ) + nltype *parentp; +{ + arctype *arcp; + +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn] dfn(" ); + printname( parentp ); + printf( ")\n" ); + } +# endif DEBUG + /* + * if we're already numbered, no need to look any furthur. + */ + if ( dfn_numbered( parentp ) ) { + return; + } + /* + * if we're already busy, must be a cycle + */ + if ( dfn_busy( parentp ) ) { + dfn_findcycle( parentp ); + return; + } + /* + * visit yourself before your children + */ + dfn_pre_visit( parentp ); + /* + * visit children + */ + for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { + dfn( arcp -> arc_childp ); + } + /* + * visit yourself after your children + */ + dfn_post_visit( parentp ); +} + + /* + * push a parent onto the stack and mark it busy + */ +dfn_pre_visit( parentp ) + nltype *parentp; +{ + + dfn_depth += 1; + if ( dfn_depth >= DFN_DEPTH ) { + fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" ); + exit( 1 ); + } + dfn_stack[ dfn_depth ].nlentryp = parentp; + dfn_stack[ dfn_depth ].cycletop = dfn_depth; + parentp -> toporder = DFN_BUSY; +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth ); + printname( parentp ); + printf( "\n" ); + } +# endif DEBUG +} + + /* + * are we already numbered? + */ +bool +dfn_numbered( childp ) + nltype *childp; +{ + + return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY ); +} + + /* + * are we already busy? + */ +bool +dfn_busy( childp ) + nltype *childp; +{ + + if ( childp -> toporder == DFN_NAN ) { + return FALSE; + } + return TRUE; +} + + /* + * MISSING: an explanation + */ +dfn_findcycle( childp ) + nltype *childp; +{ + int cycletop; + nltype *cycleheadp; + nltype *tailp; + int index; + + for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) { + cycleheadp = dfn_stack[ cycletop ].nlentryp; + if ( childp == cycleheadp ) { + break; + } + if ( childp -> cyclehead != childp && + childp -> cyclehead == cycleheadp ) { + break; + } + } + if ( cycletop <= 0 ) { + fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" ); + exit( 1 ); + } +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_findcycle] dfn_depth %d cycletop %d " , + dfn_depth , cycletop ); + printname( cycleheadp ); + printf( "\n" ); + } +# endif DEBUG + if ( cycletop == dfn_depth ) { + /* + * this is previous function, e.g. this calls itself + * sort of boring + */ + dfn_self_cycle( childp ); + } else { + /* + * glom intervening functions that aren't already + * glommed into this cycle. + * things have been glommed when their cyclehead field + * points to the head of the cycle they are glommed into. + */ + for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) { + /* void: chase down to tail of things already glommed */ +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_findcycle] tail " ); + printname( tailp ); + printf( "\n" ); + } +# endif DEBUG + } + /* + * if what we think is the top of the cycle + * has a cyclehead field, then it's not really the + * head of the cycle, which is really what we want + */ + if ( cycleheadp -> cyclehead != cycleheadp ) { + cycleheadp = cycleheadp -> cyclehead; +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_findcycle] new cyclehead " ); + printname( cycleheadp ); + printf( "\n" ); + } +# endif DEBUG + } + for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) { + childp = dfn_stack[ index ].nlentryp; + if ( childp -> cyclehead == childp ) { + /* + * not yet glommed anywhere, glom it + * and fix any children it has glommed + */ + tailp -> cnext = childp; + childp -> cyclehead = cycleheadp; +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_findcycle] glomming " ); + printname( childp ); + printf( " onto " ); + printname( cycleheadp ); + printf( "\n" ); + } +# endif DEBUG + for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) { + tailp -> cnext -> cyclehead = cycleheadp; +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_findcycle] and its tail " ); + printname( tailp -> cnext ); + printf( " onto " ); + printname( cycleheadp ); + printf( "\n" ); + } +# endif DEBUG + } + } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) { + fprintf( stderr , + "[dfn_busy] glommed, but not to cyclehead\n" ); + } + } + } +} + + /* + * deal with self-cycles + * for lint: ARGSUSED + */ +dfn_self_cycle( parentp ) + nltype *parentp; +{ + /* + * since we are taking out self-cycles elsewhere + * no need for the special case, here. + */ +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_self_cycle] " ); + printname( parentp ); + printf( "\n" ); + } +# endif DEBUG +} + + /* + * visit a node after all its children + * [MISSING: an explanation] + * and pop it off the stack + */ +dfn_post_visit( parentp ) + nltype *parentp; +{ + nltype *memberp; + +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_post_visit]\t%d: " , dfn_depth ); + printname( parentp ); + printf( "\n" ); + } +# endif DEBUG + /* + * number functions and things in their cycles + * unless the function is itself part of a cycle + */ + if ( parentp -> cyclehead == parentp ) { + dfn_counter += 1; + for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) { + memberp -> toporder = dfn_counter; +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_post_visit]\t\tmember " ); + printname( memberp ); + printf( " -> toporder = %d\n" , dfn_counter ); + } +# endif DEBUG + } + } else { +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "[dfn_post_visit]\t\tis part of a cycle\n" ); + } +# endif DEBUG + } + dfn_depth -= 1; +} diff --git a/usr/src/usr.bin/gprof/gprof.1 b/usr/src/usr.bin/gprof/gprof.1 new file mode 100644 index 0000000000..443d959a93 --- /dev/null +++ b/usr/src/usr.bin/gprof/gprof.1 @@ -0,0 +1,273 @@ +.\" Copyright (c) 1983, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)gprof.1 6.8 (Berkeley) 7/24/91 +.\" +.Dd July 24, 1991 +.Dt GPROF 1 +.Os BSD 4.2 +.Sh NAME +.Nm gprof +.Nd display call graph profile data +.Sh SYNOPSIS +.Nm gprof +.Op options +.Op Ar a.out Op Ar gmon.out ... +.Sh DESCRIPTION +.Nm Gprof +produces an execution profile of C, Pascal, or Fortran77 programs. +The effect of called routines is incorporated in the profile of each caller. +The profile data is taken from the call graph profile file +.Pf ( Pa gmon.out +default) which is created by programs +that are compiled with the +.Fl pg +option of +.Xr cc 1 , +.Xr pc 1 , +and +.Xr f77 1 . +The +.Fl pg +option also links in versions of the library routines +that are compiled for profiling. +.Nm Gprof +reads the given object file (the default is +.Pa a.out) +and establishes the relation between it's symbol table +and the call graph profile from +.Pa gmon.out . +If more than one profile file is specified, +the +.Nm gprof +output shows the sum of the profile information in the given profile files. +.Pp +.Nm Gprof +calculates the amount of time spent in each routine. +Next, these times are propagated along the edges of the call graph. +Cycles are discovered, and calls into a cycle are made to share the time +of the cycle. +The first listing shows the functions +sorted according to the time they represent +including the time of their call graph descendents. +Below each function entry is shown its (direct) call graph children, +and how their times are propagated to this function. +A similar display above the function shows how this function's time and the +time of its descendents is propagated to its (direct) call graph parents. +.Pp +Cycles are also shown, with an entry for the cycle as a whole and +a listing of the members of the cycle and their contributions to the +time and call counts of the cycle. +.Pp +Second, a flat profile is given, +similar to that provided by +.Xr prof 1 . +This listing gives the total execution times, the call counts, +the time in milleseconds the call spent in the routine itself, and +the time in milleseconds the call spent in the routine itself including +its descendents. +.Pp +Finally, an index of the function names is provided. +.Pp +The following options are available: +.Bl -tag -width Fl +.It Fl a +Suppresses the printing of statically declared functions. +If this option is given, all relevant information about the static function +(e.g., time samples, calls to other functions, calls from other functions) +belongs to the function loaded just before the static function in the +.Pa a.out +file. +.It Fl b +Suppresses the printing of a description of each field in the profile. +.It Fl c +The static call graph of the program is discovered by a heuristic +that examines the text space of the object file. +Static-only parents or children are shown +with call counts of 0. +.It Fl e Ar name +Suppresses the printing of the graph profile entry for routine +.Ar name +and all its descendants +(unless they have other ancestors that aren't suppressed). +More than one +.Fl e +option may be given. +Only one +.Ar name +may be given with each +.Fl e +option. +.It Fl E Ar name +Suppresses the printing of the graph profile entry for routine +.Ar name +(and its descendants) as +.Fl e , +above, and also excludes the time spent in +.Ar name +(and its descendants) from the total and percentage time computations. +(For example, +.Fl E +.Ar mcount +.Fl E +.Ar mcleanup +is the default.) +.It Fl f Ar name +Prints the graph profile entry of only the specified routine +.Ar name +and its descendants. +More than one +.Fl f +option may be given. +Only one +.Ar name +may be given with each +.Fl f +option. +.It Fl F Ar name +Prints the graph profile entry of only the routine +.Ar name +and its descendants (as +.Fl f , +above) and also uses only the times of the printed routines +in total time and percentage computations. +More than one +.Fl F +option may be given. +Only one +.Ar name +may be given with each +.Fl F +option. +The +.Fl F +option +overrides +the +.Fl E +option. +.It Fl k Ar fromname Ar toname +Will delete any arcs from routine +.Ar fromname +to routine +.Ar toname . +This can be used to break undesired cycles. +More than one +.Fl k +option may be given. +Only one pair of routine names may be given with each +.Fl k +option. +.It Fl s +A profile file +.Pa gmon.sum +is produced that represents +the sum of the profile information in all the specified profile files. +This summary profile file may be given to later +executions of gprof (probably also with a +.Fl s ) +to accumulate profile data across several runs of an +.Pa a.out +file. +.It Fl z +Displays routines that have zero usage (as shown by call counts +and accumulated time). +This is useful with the +.Fl c +option for discovering which routines were never called. +.El +.Sh FILES +.Bl -tag -width gmon.sum -compact +.It Pa a.out +The namelist and text space. +.It Pa gmon.out +Dynamic call graph and profile. +.It Pa gmon.sum +Summarized dynamic call graph and profile. +.El +.Sh SEE ALSO +.Xr monitor 3 , +.Xr profil 2 , +.Xr cc 1 , +.Xr prof 1 +.Rs +.%T "An Execution Profiler for Modular Programs" +.%A S. Graham +.%A P. Kessler +.%A M. McKusick +.%J "Software - Practice and Experience" +.%V 13 +.%P pp. 671-685 +.%D 1983 +.Re +.Rs +.%T "gprof: A Call Graph Execution Profiler" +.%A S. Graham +.%A P. Kessler +.%A M. McKusick +.%J "Proceedings of the SIGPLAN '82 Symposium on Compiler Construction, SIGPLAN Notices" +.%V 17 +.%N 6 +.%P pp. 120-126 +.%D June 1982 +.Re +.Sh HISTORY +The +.Nm gprof +profiler +appeared in +.Bx 4.2 . +.Sh BUGS +The granularity of the sampling is shown, but remains +statistical at best. +We assume that the time for each execution of a function +can be expressed by the total time for the function divided +by the number of times the function is called. +Thus the time propagated along the call graph arcs to the function's +parents is directly proportional to the number of times that +arc is traversed. +.Pp +Parents that are not themselves profiled will have the time of +their profiled children propagated to them, but they will appear +to be spontaneously invoked in the call graph listing, and will +not have their time propagated further. +Similarly, signal catchers, even though profiled, will appear +to be spontaneous (although for more obscure reasons). +Any profiled children of signal catchers should have their times +propagated properly, unless the signal catcher was invoked during +the execution of the profiling routine, in which case all is lost. +.Pp +The profiled program must call +.Xr exit 2 +or return normally for the profiling information to be saved +in the +.Pa gmon.out +file. diff --git a/usr/src/usr.bin/gprof/gprof.c b/usr/src/usr.bin/gprof/gprof.c new file mode 100644 index 0000000000..615f7ab01b --- /dev/null +++ b/usr/src/usr.bin/gprof/gprof.c @@ -0,0 +1,710 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1983 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)gprof.c 5.7 (Berkeley) 4/24/91"; +#endif /* not lint */ + +#include "gprof.h" + +char *whoami = "gprof"; + + /* + * things which get -E excluded by default. + */ +char *defaultEs[] = { "mcount" , "__mcleanup" , 0 }; + +main(argc, argv) + int argc; + char **argv; +{ + char **sp; + nltype **timesortnlp; + + --argc; + argv++; + debug = 0; + bflag = TRUE; + while ( *argv != 0 && **argv == '-' ) { + (*argv)++; + switch ( **argv ) { + case 'a': + aflag = TRUE; + break; + case 'b': + bflag = FALSE; + break; + case 'c': +#if defined(vax) || defined(tahoe) + cflag = TRUE; +#else + fprintf(stderr, "gprof: -c isn't supported on this architecture yet\n"); + exit(1); +#endif + break; + case 'd': + dflag = TRUE; + (*argv)++; + debug |= atoi( *argv ); + debug |= ANYDEBUG; +# ifdef DEBUG + printf("[main] debug = %d\n", debug); +# else not DEBUG + printf("%s: -d ignored\n", whoami); +# endif DEBUG + break; + case 'E': + ++argv; + addlist( Elist , *argv ); + Eflag = TRUE; + addlist( elist , *argv ); + eflag = TRUE; + break; + case 'e': + addlist( elist , *++argv ); + eflag = TRUE; + break; + case 'F': + ++argv; + addlist( Flist , *argv ); + Fflag = TRUE; + addlist( flist , *argv ); + fflag = TRUE; + break; + case 'f': + addlist( flist , *++argv ); + fflag = TRUE; + break; + case 'k': + addlist( kfromlist , *++argv ); + addlist( ktolist , *++argv ); + kflag = TRUE; + break; + case 's': + sflag = TRUE; + break; + case 'z': + zflag = TRUE; + break; + } + argv++; + } + if ( *argv != 0 ) { + a_outname = *argv; + argv++; + } else { + a_outname = A_OUTNAME; + } + if ( *argv != 0 ) { + gmonname = *argv; + argv++; + } else { + gmonname = GMONNAME; + } + /* + * turn off default functions + */ + for ( sp = &defaultEs[0] ; *sp ; sp++ ) { + Eflag = TRUE; + addlist( Elist , *sp ); + eflag = TRUE; + addlist( elist , *sp ); + } + /* + * how many ticks per second? + * if we can't tell, report time in ticks. + */ + hz = hertz(); + if (hz == 0) { + hz = 1; + fprintf(stderr, "time is in ticks, not seconds\n"); + } + /* + * get information about a.out file. + */ + getnfile(); + /* + * get information about mon.out file(s). + */ + do { + getpfile( gmonname ); + if ( *argv != 0 ) { + gmonname = *argv; + } + } while ( *argv++ != 0 ); + /* + * dump out a gmon.sum file if requested + */ + if ( sflag ) { + dumpsum( GMONSUM ); + } + /* + * assign samples to procedures + */ + asgnsamples(); + /* + * assemble the dynamic profile + */ + timesortnlp = doarcs(); + /* + * print the dynamic profile + */ + printgprof( timesortnlp ); + /* + * print the flat profile + */ + printprof(); + /* + * print the index + */ + printindex(); + done(); +} + + /* + * Set up string and symbol tables from a.out. + * and optionally the text space. + * On return symbol table is sorted by value. + */ +getnfile() +{ + FILE *nfile; + int valcmp(); + + nfile = fopen( a_outname ,"r"); + if (nfile == NULL) { + perror( a_outname ); + done(); + } + fread(&xbuf, 1, sizeof(xbuf), nfile); + if (N_BADMAG(xbuf)) { + fprintf(stderr, "%s: %s: bad format\n", whoami , a_outname ); + done(); + } + getstrtab(nfile); + getsymtab(nfile); + gettextspace( nfile ); + qsort(nl, nname, sizeof(nltype), valcmp); + fclose(nfile); +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + register int j; + + for (j = 0; j < nname; j++){ + printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name); + } + } +# endif DEBUG +} + +getstrtab(nfile) + FILE *nfile; +{ + + fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0); + if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) { + fprintf(stderr, "%s: %s: no string table (old format?)\n" , + whoami , a_outname ); + done(); + } + strtab = (char *)calloc(ssiz, 1); + if (strtab == NULL) { + fprintf(stderr, "%s: %s: no room for %d bytes of string table", + whoami , a_outname , ssiz); + done(); + } + if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) { + fprintf(stderr, "%s: %s: error reading string table\n", + whoami , a_outname ); + done(); + } +} + + /* + * Read in symbol table + */ +getsymtab(nfile) + FILE *nfile; +{ + register long i; + int askfor; + struct nlist nbuf; + + /* pass1 - count symbols */ + fseek(nfile, (long)N_SYMOFF(xbuf), 0); + nname = 0; + for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { + fread(&nbuf, sizeof(nbuf), 1, nfile); + if ( ! funcsymbol( &nbuf ) ) { + continue; + } + nname++; + } + if (nname == 0) { + fprintf(stderr, "%s: %s: no symbols\n", whoami , a_outname ); + done(); + } + askfor = nname + 1; + nl = (nltype *) calloc( askfor , sizeof(nltype) ); + if (nl == 0) { + fprintf(stderr, "%s: No room for %d bytes of symbol table\n", + whoami, askfor * sizeof(nltype) ); + done(); + } + + /* pass2 - read symbols */ + fseek(nfile, (long)N_SYMOFF(xbuf), 0); + npe = nl; + nname = 0; + for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) { + fread(&nbuf, sizeof(nbuf), 1, nfile); + if ( ! funcsymbol( &nbuf ) ) { +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + printf( "[getsymtab] rejecting: 0x%x %s\n" , + nbuf.n_type , strtab + nbuf.n_un.n_strx ); + } +# endif DEBUG + continue; + } + npe->value = nbuf.n_value; + npe->name = strtab+nbuf.n_un.n_strx; +# ifdef DEBUG + if ( debug & AOUTDEBUG ) { + printf( "[getsymtab] %d %s 0x%08x\n" , + nname , npe -> name , npe -> value ); + } +# endif DEBUG + npe++; + nname++; + } + npe->value = -1; +} + + /* + * read in the text space of an a.out file + */ +gettextspace( nfile ) + FILE *nfile; +{ + char *malloc(); + + if ( cflag == 0 ) { + return; + } + textspace = (u_char *) malloc( xbuf.a_text ); + if ( textspace == 0 ) { + fprintf( stderr , "%s: ran out room for %d bytes of text space: " , + whoami , xbuf.a_text ); + fprintf( stderr , "can't do -c\n" ); + return; + } + (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); + if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { + fprintf( stderr , "%s: couldn't read text space: " , whoami ); + fprintf( stderr , "can't do -c\n" ); + free( textspace ); + textspace = 0; + return; + } +} + /* + * information from a gmon.out file is in two parts: + * an array of sampling hits within pc ranges, + * and the arcs. + */ +getpfile(filename) + char *filename; +{ + FILE *pfile; + FILE *openpfile(); + struct rawarc arc; + + pfile = openpfile(filename); + readsamples(pfile); + /* + * the rest of the file consists of + * a bunch of tuples. + */ + while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { +# ifdef DEBUG + if ( debug & SAMPLEDEBUG ) { + printf( "[getpfile] frompc 0x%x selfpc 0x%x count %d\n" , + arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); + } +# endif DEBUG + /* + * add this arc + */ + tally( &arc ); + } + fclose(pfile); +} + +FILE * +openpfile(filename) + char *filename; +{ + struct hdr tmp; + FILE *pfile; + + if((pfile = fopen(filename, "r")) == NULL) { + perror(filename); + done(); + } + fread(&tmp, sizeof(struct hdr), 1, pfile); + if ( s_highpc != 0 && ( tmp.lowpc != h.lowpc || + tmp.highpc != h.highpc || tmp.ncnt != h.ncnt ) ) { + fprintf(stderr, "%s: incompatible with first gmon file\n", filename); + done(); + } + h = tmp; + s_lowpc = (unsigned long) h.lowpc; + s_highpc = (unsigned long) h.highpc; + lowpc = (unsigned long)h.lowpc / sizeof(UNIT); + highpc = (unsigned long)h.highpc / sizeof(UNIT); + sampbytes = h.ncnt - sizeof(struct hdr); + nsamples = sampbytes / sizeof (UNIT); +# ifdef DEBUG + if ( debug & SAMPLEDEBUG ) { + printf( "[openpfile] hdr.lowpc 0x%x hdr.highpc 0x%x hdr.ncnt %d\n", + h.lowpc , h.highpc , h.ncnt ); + printf( "[openpfile] s_lowpc 0x%x s_highpc 0x%x\n" , + s_lowpc , s_highpc ); + printf( "[openpfile] lowpc 0x%x highpc 0x%x\n" , + lowpc , highpc ); + printf( "[openpfile] sampbytes %d nsamples %d\n" , + sampbytes , nsamples ); + } +# endif DEBUG + return(pfile); +} + +tally( rawp ) + struct rawarc *rawp; +{ + nltype *parentp; + nltype *childp; + + parentp = nllookup( rawp -> raw_frompc ); + childp = nllookup( rawp -> raw_selfpc ); + if ( kflag + && onlist( kfromlist , parentp -> name ) + && onlist( ktolist , childp -> name ) ) { + return; + } + childp -> ncall += rawp -> raw_count; +# ifdef DEBUG + if ( debug & TALLYDEBUG ) { + printf( "[tally] arc from %s to %s traversed %d times\n" , + parentp -> name , childp -> name , rawp -> raw_count ); + } +# endif DEBUG + addarc( parentp , childp , rawp -> raw_count ); +} + +/* + * dump out the gmon.sum file + */ +dumpsum( sumfile ) + char *sumfile; +{ + register nltype *nlp; + register arctype *arcp; + struct rawarc arc; + FILE *sfile; + + if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) { + perror( sumfile ); + done(); + } + /* + * dump the header; use the last header read in + */ + if ( fwrite( &h , sizeof h , 1 , sfile ) != 1 ) { + perror( sumfile ); + done(); + } + /* + * dump the samples + */ + if (fwrite(samples, sizeof (UNIT), nsamples, sfile) != nsamples) { + perror( sumfile ); + done(); + } + /* + * dump the normalized raw arc information + */ + for ( nlp = nl ; nlp < npe ; nlp++ ) { + for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { + arc.raw_frompc = arcp -> arc_parentp -> value; + arc.raw_selfpc = arcp -> arc_childp -> value; + arc.raw_count = arcp -> arc_count; + if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) { + perror( sumfile ); + done(); + } +# ifdef DEBUG + if ( debug & SAMPLEDEBUG ) { + printf( "[dumpsum] frompc 0x%x selfpc 0x%x count %d\n" , + arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); + } +# endif DEBUG + } + } + fclose( sfile ); +} + +valcmp(p1, p2) + nltype *p1, *p2; +{ + if ( p1 -> value < p2 -> value ) { + return LESSTHAN; + } + if ( p1 -> value > p2 -> value ) { + return GREATERTHAN; + } + return EQUALTO; +} + +readsamples(pfile) + FILE *pfile; +{ + register i; + UNIT sample; + + if (samples == 0) { + samples = (UNIT *) calloc(sampbytes, sizeof (UNIT)); + if (samples == 0) { + fprintf( stderr , "%s: No room for %d sample pc's\n", + whoami , sampbytes / sizeof (UNIT)); + done(); + } + } + for (i = 0; i < nsamples; i++) { + fread(&sample, sizeof (UNIT), 1, pfile); + if (feof(pfile)) + break; + samples[i] += sample; + } + if (i != nsamples) { + fprintf(stderr, + "%s: unexpected EOF after reading %d/%d samples\n", + whoami , --i , nsamples ); + done(); + } +} + +/* + * Assign samples to the procedures to which they belong. + * + * There are three cases as to where pcl and pch can be + * with respect to the routine entry addresses svalue0 and svalue1 + * as shown in the following diagram. overlap computes the + * distance between the arrows, the fraction of the sample + * that is to be credited to the routine which starts at svalue0. + * + * svalue0 svalue1 + * | | + * v v + * + * +-----------------------------------------------+ + * | | + * | ->| |<- ->| |<- ->| |<- | + * | | | | | | + * +---------+ +---------+ +---------+ + * + * ^ ^ ^ ^ ^ ^ + * | | | | | | + * pcl pch pcl pch pcl pch + * + * For the vax we assert that samples will never fall in the first + * two bytes of any routine, since that is the entry mask, + * thus we give call alignentries() to adjust the entry points if + * the entry mask falls in one bucket but the code for the routine + * doesn't start until the next bucket. In conjunction with the + * alignment of routine addresses, this should allow us to have + * only one sample for every four bytes of text space and never + * have any overlap (the two end cases, above). + */ +asgnsamples() +{ + register int j; + UNIT ccnt; + double time; + unsigned long pcl, pch; + register int i; + unsigned long overlap; + unsigned long svalue0, svalue1; + + /* read samples and assign to namelist symbols */ + scale = highpc - lowpc; + scale /= nsamples; + alignentries(); + for (i = 0, j = 1; i < nsamples; i++) { + ccnt = samples[i]; + if (ccnt == 0) + continue; + pcl = lowpc + scale * i; + pch = lowpc + scale * (i + 1); + time = ccnt; +# ifdef DEBUG + if ( debug & SAMPLEDEBUG ) { + printf( "[asgnsamples] pcl 0x%x pch 0x%x ccnt %d\n" , + pcl , pch , ccnt ); + } +# endif DEBUG + totime += time; + for (j = j - 1; j < nname; j++) { + svalue0 = nl[j].svalue; + svalue1 = nl[j+1].svalue; + /* + * if high end of tick is below entry address, + * go for next tick. + */ + if (pch < svalue0) + break; + /* + * if low end of tick into next routine, + * go for next routine. + */ + if (pcl >= svalue1) + continue; + overlap = min(pch, svalue1) - max(pcl, svalue0); + if (overlap > 0) { +# ifdef DEBUG + if (debug & SAMPLEDEBUG) { + printf("[asgnsamples] (0x%x->0x%x-0x%x) %s gets %f ticks %d overlap\n", + nl[j].value/sizeof(UNIT), svalue0, svalue1, + nl[j].name, + overlap * time / scale, overlap); + } +# endif DEBUG + nl[j].time += overlap * time / scale; + } + } + } +# ifdef DEBUG + if (debug & SAMPLEDEBUG) { + printf("[asgnsamples] totime %f\n", totime); + } +# endif DEBUG +} + + +unsigned long +min(a, b) + unsigned long a,b; +{ + if (ab) + return(a); + return(b); +} + + /* + * calculate scaled entry point addresses (to save time in asgnsamples), + * and possibly push the scaled entry points over the entry mask, + * if it turns out that the entry point is in one bucket and the code + * for a routine is in the next bucket. + */ +alignentries() +{ + register struct nl *nlp; + unsigned long bucket_of_entry; + unsigned long bucket_of_code; + + for (nlp = nl; nlp < npe; nlp++) { + nlp -> svalue = nlp -> value / sizeof(UNIT); + bucket_of_entry = (nlp->svalue - lowpc) / scale; + bucket_of_code = (nlp->svalue + UNITS_TO_CODE - lowpc) / scale; + if (bucket_of_entry < bucket_of_code) { +# ifdef DEBUG + if (debug & SAMPLEDEBUG) { + printf("[alignentries] pushing svalue 0x%x to 0x%x\n", + nlp->svalue, nlp->svalue + UNITS_TO_CODE); + } +# endif DEBUG + nlp->svalue += UNITS_TO_CODE; + } + } +} + +bool +funcsymbol( nlistp ) + struct nlist *nlistp; +{ + extern char *strtab; /* string table from a.out */ + extern int aflag; /* if static functions aren't desired */ + char *name; + + /* + * must be a text symbol, + * and static text symbols don't qualify if aflag set. + */ + if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) ) + || ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) { + return FALSE; + } + /* + * can't have any `funny' characters in name, + * where `funny' includes `.', .o file names + * and `$', pascal labels. + */ + for ( name = strtab + nlistp -> n_un.n_strx ; *name ; name += 1 ) { + if ( *name == '.' || *name == '$' ) { + return FALSE; + } + } + return TRUE; +} + +done() +{ + + exit(0); +} diff --git a/usr/src/usr.bin/gprof/gprof.callg b/usr/src/usr.bin/gprof/gprof.callg new file mode 100644 index 0000000000..533c96ca43 --- /dev/null +++ b/usr/src/usr.bin/gprof/gprof.callg @@ -0,0 +1,108 @@ + + + +call graph profile: + The sum of self and descendents is the major sort + for this listing. + + function entries: + +index the index of the function in the call graph + listing, as an aid to locating it (see below). + +%time the percentage of the total time of the program + accounted for by this function and its + descendents. + +self the number of seconds spent in this function + itself. + +descendents + the number of seconds spent in the descendents of + this function on behalf of this function. + +called the number of times this function is called (other + than recursive calls). + +self the number of times this function calls itself + recursively. + +name the name of the function, with an indication of + its membership in a cycle, if any. + +index the index of the function in the call graph + listing, as an aid to locating it. + + + + parent listings: + +self* the number of seconds of this function's self time + which is due to calls from this parent. + +descendents* + the number of seconds of this function's + descendent time which is due to calls from this + parent. + +called** the number of times this function is called by + this parent. This is the numerator of the + fraction which divides up the function's time to + its parents. + +total* the number of times this function was called by + all of its parents. This is the denominator of + the propagation fraction. + +parents the name of this parent, with an indication of the + parent's membership in a cycle, if any. + +index the index of this parent in the call graph + listing, as an aid in locating it. + + + + children listings: + +self* the number of seconds of this child's self time + which is due to being called by this function. + +descendent* + the number of seconds of this child's descendent's + time which is due to being called by this + function. + +called** the number of times this child is called by this + function. This is the numerator of the + propagation fraction for this child. + +total* the number of times this child is called by all + functions. This is the denominator of the + propagation fraction. + +children the name of this child, and an indication of its + membership in a cycle, if any. + +index the index of this child in the call graph listing, + as an aid to locating it. + + + + * these fields are omitted for parents (or + children) in the same cycle as the function. If + the function (or child) is a member of a cycle, + the propagated times and propagation denominator + represent the self time and descendent time of the + cycle as a whole. + + ** static-only parents and children are indicated + by a call count of 0. + + + + cycle listings: + the cycle as a whole is listed with the same + fields as a function entry. Below it are listed + the members of the cycle, and their contributions + to the time and call counts of the cycle. + diff --git a/usr/src/usr.bin/gprof/gprof.flat b/usr/src/usr.bin/gprof/gprof.flat new file mode 100644 index 0000000000..60999a35f2 --- /dev/null +++ b/usr/src/usr.bin/gprof/gprof.flat @@ -0,0 +1,32 @@ + + + +flat profile: + + % the percentage of the total running time of the +time program used by this function. + +cumulative a running sum of the number of seconds accounted + seconds for by this function and those listed above it. + + self the number of seconds accounted for by this +seconds function alone. This is the major sort for this + listing. + +calls the number of times this function was invoked, if + this function is profiled, else blank. + + self the average number of milliseconds spent in this +ms/call function per call, if this function is profiled, + else blank. + + total the average number of milliseconds spent in this +ms/call function and its descendents per call, if this + function is profiled, else blank. + +name the name of the function. This is the minor sort + for this listing. The index shows the location of + the function in the gprof listing. If the index is + in parenthesis it shows where it would appear in + the gprof listing if it were to be printed. + diff --git a/usr/src/usr.bin/gprof/gprof.h b/usr/src/usr.bin/gprof/gprof.h new file mode 100644 index 0000000000..e34d570c39 --- /dev/null +++ b/usr/src/usr.bin/gprof/gprof.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)gprof.h 5.10 (Berkeley) 4/24/91 + */ + +#include +#include +#include +#include +#include "gmon.h" + +#if vax +# include "vax.h" +#endif +#if sun +# include "sun.h" +#endif +#if tahoe +# include "tahoe.h" +#endif +#if hp300 +# include "hp300.h" +#endif +#if i386 +# include "i386.h" +#endif + + + /* + * who am i, for error messages. + */ +char *whoami; + + /* + * booleans + */ +typedef int bool; +#define FALSE 0 +#define TRUE 1 + + /* + * ticks per second + */ +long hz; + +typedef u_short UNIT; /* unit of profiling */ +char *a_outname; +#define A_OUTNAME "a.out" + +char *gmonname; +#define GMONNAME "gmon.out" +#define GMONSUM "gmon.sum" + + /* + * a constructed arc, + * with pointers to the namelist entry of the parent and the child, + * a count of how many times this arc was traversed, + * and pointers to the next parent of this child and + * the next child of this parent. + */ +struct arcstruct { + struct nl *arc_parentp; /* pointer to parent's nl entry */ + struct nl *arc_childp; /* pointer to child's nl entry */ + long arc_count; /* how calls from parent to child */ + double arc_time; /* time inherited along arc */ + double arc_childtime; /* childtime inherited along arc */ + struct arcstruct *arc_parentlist; /* parents-of-this-child list */ + struct arcstruct *arc_childlist; /* children-of-this-parent list */ +}; +typedef struct arcstruct arctype; + + /* + * The symbol table; + * for each external in the specified file we gather + * its address, the number of calls and compute its share of cpu time. + */ +struct nl { + char *name; /* the name */ + unsigned long value; /* the pc entry point */ + unsigned long svalue; /* entry point aligned to histograms */ + double time; /* ticks in this routine */ + double childtime; /* cumulative ticks in children */ + long ncall; /* how many times called */ + long selfcalls; /* how many calls to self */ + double propfraction; /* what % of time propagates */ + double propself; /* how much self time propagates */ + double propchild; /* how much child time propagates */ + bool printflag; /* should this be printed? */ + int index; /* index in the graph list */ + int toporder; /* graph call chain top-sort order */ + int cycleno; /* internal number of cycle on */ + struct nl *cyclehead; /* pointer to head of cycle */ + struct nl *cnext; /* pointer to next member of cycle */ + arctype *parents; /* list of caller arcs */ + arctype *children; /* list of callee arcs */ +}; +typedef struct nl nltype; + +nltype *nl; /* the whole namelist */ +nltype *npe; /* the virtual end of the namelist */ +int nname; /* the number of function names */ + + /* + * flag which marks a nl entry as topologically ``busy'' + * flag which marks a nl entry as topologically ``not_numbered'' + */ +#define DFN_BUSY -1 +#define DFN_NAN 0 + + /* + * namelist entries for cycle headers. + * the number of discovered cycles. + */ +nltype *cyclenl; /* cycle header namelist */ +int ncycle; /* number of cycles discovered */ + + /* + * The header on the gmon.out file. + * gmon.out consists of one of these headers, + * and then an array of ncnt samples + * representing the discretized program counter values. + * this should be a struct phdr, but since everything is done + * as UNITs, this is in UNITs too. + */ +struct hdr { + UNIT *lowpc; + UNIT *highpc; + int ncnt; +}; + +struct hdr h; + +int debug; + + /* + * Each discretized pc sample has + * a count of the number of samples in its range + */ +UNIT *samples; + +unsigned long s_lowpc; /* lowpc from the profile file */ +unsigned long s_highpc; /* highpc from the profile file */ +unsigned lowpc, highpc; /* range profiled, in UNIT's */ +unsigned sampbytes; /* number of bytes of samples */ +int nsamples; /* number of samples */ +double actime; /* accumulated time thus far for putprofline */ +double totime; /* total time for all routines */ +double printtime; /* total of time being printed */ +double scale; /* scale factor converting samples to pc + values: each sample covers scale bytes */ +char *strtab; /* string table in core */ +off_t ssiz; /* size of the string table */ +struct exec xbuf; /* exec header of a.out */ +unsigned char *textspace; /* text space of a.out in core */ + + /* + * option flags, from a to z. + */ +bool aflag; /* suppress static functions */ +bool bflag; /* blurbs, too */ +bool cflag; /* discovered call graph, too */ +bool dflag; /* debugging options */ +bool eflag; /* specific functions excluded */ +bool Eflag; /* functions excluded with time */ +bool fflag; /* specific functions requested */ +bool Fflag; /* functions requested with time */ +bool kflag; /* arcs to be deleted */ +bool sflag; /* sum multiple gmon.out files */ +bool zflag; /* zero time/called functions, too */ + + /* + * structure for various string lists + */ +struct stringlist { + struct stringlist *next; + char *string; +}; +struct stringlist *elist; +struct stringlist *Elist; +struct stringlist *flist; +struct stringlist *Flist; +struct stringlist *kfromlist; +struct stringlist *ktolist; + + /* + * function declarations + */ +/* + addarc(); +*/ +int arccmp(); +arctype *arclookup(); +/* + asgnsamples(); + printblurb(); + cyclelink(); + dfn(); +*/ +bool dfn_busy(); +/* + dfn_findcycle(); +*/ +bool dfn_numbered(); +/* + dfn_post_visit(); + dfn_pre_visit(); + dfn_self_cycle(); +*/ +nltype **doarcs(); +/* + done(); + findcalls(); + flatprofheader(); + flatprofline(); +*/ +bool funcsymbol(); +/* + getnfile(); + getpfile(); + getstrtab(); + getsymtab(); + gettextspace(); + gprofheader(); + gprofline(); + main(); +*/ +unsigned long max(); +int membercmp(); +unsigned long min(); +nltype *nllookup(); +FILE *openpfile(); +long operandlength(); +operandenum operandmode(); +char *operandname(); +/* + printchildren(); + printcycle(); + printgprof(); + printmembers(); + printname(); + printparents(); + printprof(); + readsamples(); +*/ +unsigned long reladdr(); +/* + sortchildren(); + sortmembers(); + sortparents(); + tally(); + timecmp(); + topcmp(); +*/ +int totalcmp(); +/* + valcmp(); +*/ + +#define LESSTHAN -1 +#define EQUALTO 0 +#define GREATERTHAN 1 + +#define DFNDEBUG 1 +#define CYCLEDEBUG 2 +#define ARCDEBUG 4 +#define TALLYDEBUG 8 +#define TIMEDEBUG 16 +#define SAMPLEDEBUG 32 +#define AOUTDEBUG 64 +#define CALLDEBUG 128 +#define LOOKUPDEBUG 256 +#define PROPDEBUG 512 +#define ANYDEBUG 1024 diff --git a/usr/src/usr.bin/gprof/hertz.c b/usr/src/usr.bin/gprof/hertz.c new file mode 100644 index 0000000000..bd367aabbe --- /dev/null +++ b/usr/src/usr.bin/gprof/hertz.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)hertz.c 5.4 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include + + /* + * discover the tick frequency of the machine + * if something goes wrong, we return 0, an impossible hertz. + */ +#define HZ_WRONG 0 + +hertz() +{ + struct itimerval tim; + + tim.it_interval.tv_sec = 0; + tim.it_interval.tv_usec = 1; + tim.it_value.tv_sec = 0; + tim.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &tim, 0); + setitimer(ITIMER_REAL, 0, &tim); + if (tim.it_interval.tv_usec < 2) + return(HZ_WRONG); + return (1000000 / tim.it_interval.tv_usec); +} diff --git a/usr/src/usr.bin/gprof/hp300.c b/usr/src/usr.bin/gprof/hp300.c new file mode 100644 index 0000000000..6a474086a3 --- /dev/null +++ b/usr/src/usr.bin/gprof/hp300.c @@ -0,0 +1,11 @@ +#include "gprof.h" + +/* + * gprof -c isn't currently supported... + */ +findcall( parentp , p_lowpc , p_highpc ) + nltype *parentp; + unsigned long p_lowpc; + unsigned long p_highpc; +{ +} diff --git a/usr/src/usr.bin/gprof/hp300.h b/usr/src/usr.bin/gprof/hp300.h new file mode 100644 index 0000000000..1227d89054 --- /dev/null +++ b/usr/src/usr.bin/gprof/hp300.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)hp300.h 5.1 (Berkeley) 4/18/91 + */ + + /* + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) + */ +#define OFFSET_OF_CODE 0 +#define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) + +enum opermodes { dummy }; +typedef enum opermodes operandenum; diff --git a/usr/src/usr.bin/gprof/i386.c b/usr/src/usr.bin/gprof/i386.c new file mode 100644 index 0000000000..6a474086a3 --- /dev/null +++ b/usr/src/usr.bin/gprof/i386.c @@ -0,0 +1,11 @@ +#include "gprof.h" + +/* + * gprof -c isn't currently supported... + */ +findcall( parentp , p_lowpc , p_highpc ) + nltype *parentp; + unsigned long p_lowpc; + unsigned long p_highpc; +{ +} diff --git a/usr/src/usr.bin/gprof/i386.h b/usr/src/usr.bin/gprof/i386.h new file mode 100644 index 0000000000..bcb9d52c5d --- /dev/null +++ b/usr/src/usr.bin/gprof/i386.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)i386.h 5.1 (Berkeley) 4/18/91 + */ + + /* + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) + */ +#define OFFSET_OF_CODE 0 +#define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) + +enum opermodes { dummy }; +typedef enum opermodes operandenum; diff --git a/usr/src/usr.bin/gprof/lookup.c b/usr/src/usr.bin/gprof/lookup.c new file mode 100644 index 0000000000..7625024c06 --- /dev/null +++ b/usr/src/usr.bin/gprof/lookup.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)lookup.c 5.5 (Berkeley) 2/6/91"; +#endif /* not lint */ + +#include "gprof.h" + + /* + * look up an address in a sorted-by-address namelist + * this deals with misses by mapping them to the next lower + * entry point. + */ +nltype * +nllookup( address ) + unsigned long address; +{ + register long low; + register long middle; + register long high; +# ifdef DEBUG + register int probes; + + probes = 0; +# endif DEBUG + for ( low = 0 , high = nname - 1 ; low != high ; ) { +# ifdef DEBUG + probes += 1; +# endif DEBUG + middle = ( high + low ) >> 1; + if ( nl[ middle ].value <= address && nl[ middle+1 ].value > address ) { +# ifdef DEBUG + if ( debug & LOOKUPDEBUG ) { + printf( "[nllookup] %d (%d) probes\n" , probes , nname-1 ); + } +# endif DEBUG + return &nl[ middle ]; + } + if ( nl[ middle ].value > address ) { + high = middle; + } else { + low = middle + 1; + } + } + fprintf( stderr , "[nllookup] binary search fails???\n" ); + return 0; +} + +arctype * +arclookup( parentp , childp ) + nltype *parentp; + nltype *childp; +{ + arctype *arcp; + + if ( parentp == 0 || childp == 0 ) { + fprintf( stderr, "[arclookup] parentp == 0 || childp == 0\n" ); + return 0; + } +# ifdef DEBUG + if ( debug & LOOKUPDEBUG ) { + printf( "[arclookup] parent %s child %s\n" , + parentp -> name , childp -> name ); + } +# endif DEBUG + for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { +# ifdef DEBUG + if ( debug & LOOKUPDEBUG ) { + printf( "[arclookup]\t arc_parent %s arc_child %s\n" , + arcp -> arc_parentp -> name , + arcp -> arc_childp -> name ); + } +# endif DEBUG + if ( arcp -> arc_childp == childp ) { + return arcp; + } + } + return 0; +} diff --git a/usr/src/usr.bin/gprof/pathnames.h b/usr/src/usr.bin/gprof/pathnames.h new file mode 100644 index 0000000000..9acf7c452c --- /dev/null +++ b/usr/src/usr.bin/gprof/pathnames.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.2 (Berkeley) 6/1/90 + */ + +#define _PATH_FLAT_BLURB "/usr/share/misc/gprof.flat" +#define _PATH_CALLG_BLURB "/usr/share/misc/gprof.callg" + diff --git a/usr/src/usr.bin/gprof/printgprof.c b/usr/src/usr.bin/gprof/printgprof.c new file mode 100644 index 0000000000..241b1d4b71 --- /dev/null +++ b/usr/src/usr.bin/gprof/printgprof.c @@ -0,0 +1,718 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)printgprof.c 5.7 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include "gprof.h" +#include "pathnames.h" + +printprof() +{ + register nltype *np; + nltype **sortednlp; + int index, timecmp(); + + actime = 0.0; + printf( "\f\n" ); + flatprofheader(); + /* + * Sort the symbol table in by time + */ + sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); + if ( sortednlp == (nltype **) 0 ) { + fprintf( stderr , "[printprof] ran out of memory for time sorting\n" ); + } + for ( index = 0 ; index < nname ; index += 1 ) { + sortednlp[ index ] = &nl[ index ]; + } + qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); + for ( index = 0 ; index < nname ; index += 1 ) { + np = sortednlp[ index ]; + flatprofline( np ); + } + actime = 0.0; + cfree( sortednlp ); +} + +timecmp( npp1 , npp2 ) + nltype **npp1, **npp2; +{ + double timediff; + long calldiff; + + timediff = (*npp2) -> time - (*npp1) -> time; + if ( timediff > 0.0 ) + return 1 ; + if ( timediff < 0.0 ) + return -1; + calldiff = (*npp2) -> ncall - (*npp1) -> ncall; + if ( calldiff > 0 ) + return 1; + if ( calldiff < 0 ) + return -1; + return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); +} + + /* + * header for flatprofline + */ +flatprofheader() +{ + + if ( bflag ) { + printblurb( _PATH_FLAT_BLURB ); + } + printf( "\ngranularity: each sample hit covers %d byte(s)" , + (long) scale * sizeof(UNIT) ); + if ( totime > 0.0 ) { + printf( " for %.2f%% of %.2f seconds\n\n" , + 100.0/totime , totime / hz ); + } else { + printf( " no time accumulated\n\n" ); + /* + * this doesn't hurt sinc eall the numerators will be zero. + */ + totime = 1.0; + } + printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , + "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); + printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , + "time" , "seconds " , "seconds" , "calls" , + "ms/call" , "ms/call" , "name" ); +} + +flatprofline( np ) + register nltype *np; +{ + + if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { + return; + } + actime += np -> time; + printf( "%5.1f %10.2f %8.2f" , + 100 * np -> time / totime , actime / hz , np -> time / hz ); + if ( np -> ncall != 0 ) { + printf( " %8d %8.2f %8.2f " , np -> ncall , + 1000 * np -> time / hz / np -> ncall , + 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); + } else { + printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); + } + printname( np ); + printf( "\n" ); +} + +gprofheader() +{ + + if ( bflag ) { + printblurb( _PATH_CALLG_BLURB ); + } + printf( "\ngranularity: each sample hit covers %d byte(s)" , + (long) scale * sizeof(UNIT) ); + if ( printtime > 0.0 ) { + printf( " for %.2f%% of %.2f seconds\n\n" , + 100.0/printtime , printtime / hz ); + } else { + printf( " no time propagated\n\n" ); + /* + * this doesn't hurt, since all the numerators will be 0.0 + */ + printtime = 1.0; + } + printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , + "" , "" , "" , "" , "called" , "total" , "parents"); + printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , + "index" , "%time" , "self" , "descendents" , + "called" , "self" , "name" , "index" ); + printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , + "" , "" , "" , "" , "called" , "total" , "children"); + printf( "\n" ); +} + +gprofline( np ) + register nltype *np; +{ + char kirkbuffer[ BUFSIZ ]; + + sprintf( kirkbuffer , "[%d]" , np -> index ); + printf( "%-6.6s %5.1f %7.2f %11.2f" , + kirkbuffer , + 100 * ( np -> propself + np -> propchild ) / printtime , + np -> propself / hz , + np -> propchild / hz ); + if ( ( np -> ncall + np -> selfcalls ) != 0 ) { + printf( " %7d" , np -> ncall ); + if ( np -> selfcalls != 0 ) { + printf( "+%-7d " , np -> selfcalls ); + } else { + printf( " %7.7s " , "" ); + } + } else { + printf( " %7.7s %7.7s " , "" , "" ); + } + printname( np ); + printf( "\n" ); +} + +printgprof(timesortnlp) + nltype **timesortnlp; +{ + int index; + nltype *parentp; + + /* + * Print out the structured profiling list + */ + gprofheader(); + for ( index = 0 ; index < nname + ncycle ; index ++ ) { + parentp = timesortnlp[ index ]; + if ( zflag == 0 && + parentp -> ncall == 0 && + parentp -> selfcalls == 0 && + parentp -> propself == 0 && + parentp -> propchild == 0 ) { + continue; + } + if ( ! parentp -> printflag ) { + continue; + } + if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { + /* + * cycle header + */ + printcycle( parentp ); + printmembers( parentp ); + } else { + printparents( parentp ); + gprofline( parentp ); + printchildren( parentp ); + } + printf( "\n" ); + printf( "-----------------------------------------------\n" ); + printf( "\n" ); + } + cfree( timesortnlp ); +} + + /* + * sort by decreasing propagated time + * if times are equal, but one is a cycle header, + * say that's first (e.g. less, i.e. -1). + * if one's name doesn't have an underscore and the other does, + * say the one is first. + * all else being equal, sort by names. + */ +int +totalcmp( npp1 , npp2 ) + nltype **npp1; + nltype **npp2; +{ + register nltype *np1 = *npp1; + register nltype *np2 = *npp2; + double diff; + + diff = ( np1 -> propself + np1 -> propchild ) + - ( np2 -> propself + np2 -> propchild ); + if ( diff < 0.0 ) + return 1; + if ( diff > 0.0 ) + return -1; + if ( np1 -> name == 0 && np1 -> cycleno != 0 ) + return -1; + if ( np2 -> name == 0 && np2 -> cycleno != 0 ) + return 1; + if ( np1 -> name == 0 ) + return -1; + if ( np2 -> name == 0 ) + return 1; + if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) + return -1; + if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) + return 1; + if ( np1 -> ncall > np2 -> ncall ) + return -1; + if ( np1 -> ncall < np2 -> ncall ) + return 1; + return strcmp( np1 -> name , np2 -> name ); +} + +printparents( childp ) + nltype *childp; +{ + nltype *parentp; + arctype *arcp; + nltype *cycleheadp; + + if ( childp -> cyclehead != 0 ) { + cycleheadp = childp -> cyclehead; + } else { + cycleheadp = childp; + } + if ( childp -> parents == 0 ) { + printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s \n" , + "" , "" , "" , "" , "" , "" ); + return; + } + sortparents( childp ); + for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { + parentp = arcp -> arc_parentp; + if ( childp == parentp || + ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { + /* + * selfcall or call among siblings + */ + printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , + "" , "" , "" , "" , + arcp -> arc_count , "" ); + printname( parentp ); + printf( "\n" ); + } else { + /* + * regular parent of child + */ + printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , + "" , "" , + arcp -> arc_time / hz , arcp -> arc_childtime / hz , + arcp -> arc_count , cycleheadp -> ncall ); + printname( parentp ); + printf( "\n" ); + } + } +} + +printchildren( parentp ) + nltype *parentp; +{ + nltype *childp; + arctype *arcp; + + sortchildren( parentp ); + arcp = parentp -> children; + for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { + childp = arcp -> arc_childp; + if ( childp == parentp || + ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { + /* + * self call or call to sibling + */ + printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , + "" , "" , "" , "" , arcp -> arc_count , "" ); + printname( childp ); + printf( "\n" ); + } else { + /* + * regular child of parent + */ + printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , + "" , "" , + arcp -> arc_time / hz , arcp -> arc_childtime / hz , + arcp -> arc_count , childp -> cyclehead -> ncall ); + printname( childp ); + printf( "\n" ); + } + } +} + +printname( selfp ) + nltype *selfp; +{ + + if ( selfp -> name != 0 ) { + printf( "%s" , selfp -> name ); +# ifdef DEBUG + if ( debug & DFNDEBUG ) { + printf( "{%d} " , selfp -> toporder ); + } + if ( debug & PROPDEBUG ) { + printf( "%5.2f%% " , selfp -> propfraction ); + } +# endif DEBUG + } + if ( selfp -> cycleno != 0 ) { + printf( " " , selfp -> cycleno ); + } + if ( selfp -> index != 0 ) { + if ( selfp -> printflag ) { + printf( " [%d]" , selfp -> index ); + } else { + printf( " (%d)" , selfp -> index ); + } + } +} + +sortchildren( parentp ) + nltype *parentp; +{ + arctype *arcp; + arctype *detachedp; + arctype sorted; + arctype *prevp; + + /* + * unlink children from parent, + * then insertion sort back on to sorted's children. + * *arcp the arc you have detached and are inserting. + * *detachedp the rest of the arcs to be sorted. + * sorted arc list onto which you insertion sort. + * *prevp arc before the arc you are comparing. + */ + sorted.arc_childlist = 0; + for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); + arcp ; + (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { + /* + * consider *arcp as disconnected + * insert it into sorted + */ + for ( prevp = &sorted ; + prevp -> arc_childlist ; + prevp = prevp -> arc_childlist ) { + if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { + break; + } + } + arcp -> arc_childlist = prevp -> arc_childlist; + prevp -> arc_childlist = arcp; + } + /* + * reattach sorted children to parent + */ + parentp -> children = sorted.arc_childlist; +} + +sortparents( childp ) + nltype *childp; +{ + arctype *arcp; + arctype *detachedp; + arctype sorted; + arctype *prevp; + + /* + * unlink parents from child, + * then insertion sort back on to sorted's parents. + * *arcp the arc you have detached and are inserting. + * *detachedp the rest of the arcs to be sorted. + * sorted arc list onto which you insertion sort. + * *prevp arc before the arc you are comparing. + */ + sorted.arc_parentlist = 0; + for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); + arcp ; + (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { + /* + * consider *arcp as disconnected + * insert it into sorted + */ + for ( prevp = &sorted ; + prevp -> arc_parentlist ; + prevp = prevp -> arc_parentlist ) { + if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { + break; + } + } + arcp -> arc_parentlist = prevp -> arc_parentlist; + prevp -> arc_parentlist = arcp; + } + /* + * reattach sorted arcs to child + */ + childp -> parents = sorted.arc_parentlist; +} + + /* + * print a cycle header + */ +printcycle( cyclep ) + nltype *cyclep; +{ + char kirkbuffer[ BUFSIZ ]; + + sprintf( kirkbuffer , "[%d]" , cyclep -> index ); + printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , + kirkbuffer , + 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , + cyclep -> propself / hz , + cyclep -> propchild / hz , + cyclep -> ncall ); + if ( cyclep -> selfcalls != 0 ) { + printf( "+%-7d" , cyclep -> selfcalls ); + } else { + printf( " %7.7s" , "" ); + } + printf( " \t[%d]\n" , + cyclep -> cycleno , cyclep -> index ); +} + + /* + * print the members of a cycle + */ +printmembers( cyclep ) + nltype *cyclep; +{ + nltype *memberp; + + sortmembers( cyclep ); + for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { + printf( "%6.6s %5.5s %7.2f %11.2f %7d" , + "" , "" , memberp -> propself / hz , memberp -> propchild / hz , + memberp -> ncall ); + if ( memberp -> selfcalls != 0 ) { + printf( "+%-7d" , memberp -> selfcalls ); + } else { + printf( " %7.7s" , "" ); + } + printf( " " ); + printname( memberp ); + printf( "\n" ); + } +} + + /* + * sort members of a cycle + */ +sortmembers( cyclep ) + nltype *cyclep; +{ + nltype *todo; + nltype *doing; + nltype *prev; + + /* + * detach cycle members from cyclehead, + * and insertion sort them back on. + */ + todo = cyclep -> cnext; + cyclep -> cnext = 0; + for ( (doing = todo)&&(todo = doing -> cnext); + doing ; + (doing = todo )&&(todo = doing -> cnext )){ + for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { + if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { + break; + } + } + doing -> cnext = prev -> cnext; + prev -> cnext = doing; + } +} + + /* + * major sort is on propself + propchild, + * next is sort on ncalls + selfcalls. + */ +int +membercmp( this , that ) + nltype *this; + nltype *that; +{ + double thistime = this -> propself + this -> propchild; + double thattime = that -> propself + that -> propchild; + long thiscalls = this -> ncall + this -> selfcalls; + long thatcalls = that -> ncall + that -> selfcalls; + + if ( thistime > thattime ) { + return GREATERTHAN; + } + if ( thistime < thattime ) { + return LESSTHAN; + } + if ( thiscalls > thatcalls ) { + return GREATERTHAN; + } + if ( thiscalls < thatcalls ) { + return LESSTHAN; + } + return EQUALTO; +} + /* + * compare two arcs to/from the same child/parent. + * - if one arc is a self arc, it's least. + * - if one arc is within a cycle, it's less than. + * - if both arcs are within a cycle, compare arc counts. + * - if neither arc is within a cycle, compare with + * arc_time + arc_childtime as major key + * arc count as minor key + */ +int +arccmp( thisp , thatp ) + arctype *thisp; + arctype *thatp; +{ + nltype *thisparentp = thisp -> arc_parentp; + nltype *thischildp = thisp -> arc_childp; + nltype *thatparentp = thatp -> arc_parentp; + nltype *thatchildp = thatp -> arc_childp; + double thistime; + double thattime; + +# ifdef DEBUG + if ( debug & TIMEDEBUG ) { + printf( "[arccmp] " ); + printname( thisparentp ); + printf( " calls " ); + printname ( thischildp ); + printf( " %f + %f %d/%d\n" , + thisp -> arc_time , thisp -> arc_childtime , + thisp -> arc_count , thischildp -> ncall ); + printf( "[arccmp] " ); + printname( thatparentp ); + printf( " calls " ); + printname( thatchildp ); + printf( " %f + %f %d/%d\n" , + thatp -> arc_time , thatp -> arc_childtime , + thatp -> arc_count , thatchildp -> ncall ); + printf( "\n" ); + } +# endif DEBUG + if ( thisparentp == thischildp ) { + /* this is a self call */ + return LESSTHAN; + } + if ( thatparentp == thatchildp ) { + /* that is a self call */ + return GREATERTHAN; + } + if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && + thisparentp -> cycleno == thischildp -> cycleno ) { + /* this is a call within a cycle */ + if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && + thatparentp -> cycleno == thatchildp -> cycleno ) { + /* that is a call within the cycle, too */ + if ( thisp -> arc_count < thatp -> arc_count ) { + return LESSTHAN; + } + if ( thisp -> arc_count > thatp -> arc_count ) { + return GREATERTHAN; + } + return EQUALTO; + } else { + /* that isn't a call within the cycle */ + return LESSTHAN; + } + } else { + /* this isn't a call within a cycle */ + if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && + thatparentp -> cycleno == thatchildp -> cycleno ) { + /* that is a call within a cycle */ + return GREATERTHAN; + } else { + /* neither is a call within a cycle */ + thistime = thisp -> arc_time + thisp -> arc_childtime; + thattime = thatp -> arc_time + thatp -> arc_childtime; + if ( thistime < thattime ) + return LESSTHAN; + if ( thistime > thattime ) + return GREATERTHAN; + if ( thisp -> arc_count < thatp -> arc_count ) + return LESSTHAN; + if ( thisp -> arc_count > thatp -> arc_count ) + return GREATERTHAN; + return EQUALTO; + } + } +} + +printblurb( blurbname ) + char *blurbname; +{ + FILE *blurbfile; + int input; + + blurbfile = fopen( blurbname , "r" ); + if ( blurbfile == NULL ) { + perror( blurbname ); + return; + } + while ( ( input = getc( blurbfile ) ) != EOF ) { + putchar( input ); + } + fclose( blurbfile ); +} + +int +namecmp( npp1 , npp2 ) + nltype **npp1, **npp2; +{ + return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); +} + +printindex() +{ + nltype **namesortnlp; + register nltype *nlp; + int index, nnames, todo, i, j; + char peterbuffer[ BUFSIZ ]; + + /* + * Now, sort regular function name alphbetically + * to create an index. + */ + namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); + if ( namesortnlp == (nltype **) 0 ) { + fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); + } + for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { + if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) + continue; + namesortnlp[nnames++] = &nl[index]; + } + qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); + for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { + namesortnlp[todo++] = &cyclenl[index]; + } + printf( "\f\nIndex by function name\n\n" ); + index = ( todo + 2 ) / 3; + for ( i = 0; i < index ; i++ ) { + for ( j = i; j < todo ; j += index ) { + nlp = namesortnlp[ j ]; + if ( nlp -> printflag ) { + sprintf( peterbuffer , "[%d]" , nlp -> index ); + } else { + sprintf( peterbuffer , "(%d)" , nlp -> index ); + } + if ( j < nnames ) { + printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); + } else { + printf( "%6.6s " , peterbuffer ); + sprintf( peterbuffer , "" , nlp -> cycleno ); + printf( "%-19.19s" , peterbuffer ); + } + } + printf( "\n" ); + } + cfree( namesortnlp ); +} diff --git a/usr/src/usr.bin/gprof/printlist.c b/usr/src/usr.bin/gprof/printlist.c new file mode 100644 index 0000000000..b12e56faa7 --- /dev/null +++ b/usr/src/usr.bin/gprof/printlist.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)printlist.c 5.5 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include "gprof.h" + + /* + * these are the lists of names: + * there is the list head and then the listname + * is a pointer to the list head + * (for ease of passing to stringlist functions). + */ +struct stringlist kfromhead = { 0 , 0 }; +struct stringlist *kfromlist = &kfromhead; +struct stringlist ktohead = { 0 , 0 }; +struct stringlist *ktolist = &ktohead; +struct stringlist fhead = { 0 , 0 }; +struct stringlist *flist = &fhead; +struct stringlist Fhead = { 0 , 0 }; +struct stringlist *Flist = &Fhead; +struct stringlist ehead = { 0 , 0 }; +struct stringlist *elist = &ehead; +struct stringlist Ehead = { 0 , 0 }; +struct stringlist *Elist = &Ehead; + +addlist( listp , funcname ) + struct stringlist *listp; + char *funcname; +{ + struct stringlist *slp; + + slp = (struct stringlist *) malloc( sizeof(struct stringlist)); + if ( slp == (struct stringlist *) 0 ) { + fprintf( stderr, "gprof: ran out room for printlist\n" ); + done(); + } + slp -> next = listp -> next; + slp -> string = funcname; + listp -> next = slp; +} + +bool +onlist( listp , funcname ) + struct stringlist *listp; + char *funcname; +{ + struct stringlist *slp; + + for ( slp = listp -> next ; slp ; slp = slp -> next ) { + if ( ! strcmp( slp -> string , funcname ) ) { + return TRUE; + } + if ( funcname[0] == '_' && ! strcmp( slp -> string , &funcname[1] ) ) { + return TRUE; + } + } + return FALSE; +} diff --git a/usr/src/usr.bin/gprof/tahoe.c b/usr/src/usr.bin/gprof/tahoe.c new file mode 100644 index 0000000000..bfbd39550c --- /dev/null +++ b/usr/src/usr.bin/gprof/tahoe.c @@ -0,0 +1,349 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tahoe.c 1.5 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include "gprof.h" + + /* + * a namelist entry to be the child of indirect callf + */ +nltype indirectchild = { + "(*)" , /* the name */ + (unsigned long) 0 , /* the pc entry point */ + (unsigned long) 0 , /* entry point aligned to histogram */ + (double) 0.0 , /* ticks in this routine */ + (double) 0.0 , /* cumulative ticks in children */ + (long) 0 , /* how many times called */ + (long) 0 , /* how many calls to self */ + (double) 1.0 , /* propagation fraction */ + (double) 0.0 , /* self propagation time */ + (double) 0.0 , /* child propagation time */ + (bool) 0 , /* print flag */ + (int) 0 , /* index in the graph list */ + (int) 0 , /* graph call chain top-sort order */ + (int) 0 , /* internal number of cycle on */ + (struct nl *) &indirectchild , /* pointer to head of cycle */ + (struct nl *) 0 , /* pointer to next member of cycle */ + (arctype *) 0 , /* list of caller arcs */ + (arctype *) 0 /* list of callee arcs */ + }; + +operandenum +operandmode( modep ) + unsigned char *modep; +{ + long usesreg = ((long)*modep) & 0xf; + + switch ( ((long)*modep) >> 4 ) { + case 0: + case 1: + case 2: + case 3: + return literal; + case 4: + return indexed; + case 5: + return reg; + case 6: + return regdef; + case 7: + return autodec; + case 8: + return ( usesreg != 0xe ? autoinc : immediate ); + case 9: + return ( usesreg != PC ? autoincdef : absolute ); + case 10: + return ( usesreg != PC ? bytedisp : byterel ); + case 11: + return ( usesreg != PC ? bytedispdef : bytereldef ); + case 12: + return ( usesreg != PC ? worddisp : wordrel ); + case 13: + return ( usesreg != PC ? worddispdef : wordreldef ); + case 14: + return ( usesreg != PC ? longdisp : longrel ); + case 15: + return ( usesreg != PC ? longdispdef : longreldef ); + } + /* NOTREACHED */ +} + +char * +operandname( mode ) + operandenum mode; +{ + + switch ( mode ) { + case literal: + return "literal"; + case indexed: + return "indexed"; + case reg: + return "register"; + case regdef: + return "register deferred"; + case autodec: + return "autodecrement"; + case autoinc: + return "autoincrement"; + case autoincdef: + return "autoincrement deferred"; + case bytedisp: + return "byte displacement"; + case bytedispdef: + return "byte displacement deferred"; + case byterel: + return "byte relative"; + case bytereldef: + return "byte relative deferred"; + case worddisp: + return "word displacement"; + case worddispdef: + return "word displacement deferred"; + case wordrel: + return "word relative"; + case wordreldef: + return "word relative deferred"; + case immediate: + return "immediate"; + case absolute: + return "absolute"; + case longdisp: + return "long displacement"; + case longdispdef: + return "long displacement deferred"; + case longrel: + return "long relative"; + case longreldef: + return "long relative deferred"; + } + /* NOTREACHED */ +} + +long +operandlength( modep ) + unsigned char *modep; +{ + + switch ( operandmode( modep ) ) { + case literal: + case reg: + case regdef: + case autodec: + case autoinc: + case autoincdef: + return 1; + case bytedisp: + case bytedispdef: + case byterel: + case bytereldef: + return 2; + case worddisp: + case worddispdef: + case wordrel: + case wordreldef: + return 3; + case immediate: + case absolute: + case longdisp: + case longdispdef: + case longrel: + case longreldef: + return 5; + case indexed: + return 1+operandlength( modep + 1 ); + } + /* NOTREACHED */ +} + +unsigned long +reladdr( modep ) + char *modep; +{ + operandenum mode = operandmode( modep ); + char *cp; + short *sp; + long *lp; + int i; + long value = 0; + + cp = modep; + cp += 1; /* skip over the mode */ + switch ( mode ) { + default: + fprintf( stderr , "[reladdr] not relative address\n" ); + return (unsigned long) modep; + case byterel: + return (unsigned long) ( cp + sizeof *cp + *cp ); + case wordrel: + for (i = 0; i < sizeof *sp; i++) + value = (value << 8) + (cp[i] & 0xff); + return (unsigned long) ( cp + sizeof *sp + value ); + case longrel: + for (i = 0; i < sizeof *lp; i++) + value = (value << 8) + (cp[i] & 0xff); + return (unsigned long) ( cp + sizeof *lp + value ); + } +} + +findcall( parentp , p_lowpc , p_highpc ) + nltype *parentp; + unsigned long p_lowpc; + unsigned long p_highpc; +{ + unsigned char *instructp; + long length; + nltype *childp; + operandenum mode; + operandenum firstmode; + unsigned long destpc; + + if ( textspace == 0 ) { + return; + } + if ( p_lowpc < s_lowpc ) { + p_lowpc = s_lowpc; + } + if ( p_highpc > s_highpc ) { + p_highpc = s_highpc; + } +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall] %s: 0x%x to 0x%x\n" , + parentp -> name , p_lowpc , p_highpc ); + } +# endif DEBUG + for ( instructp = textspace + p_lowpc ; + instructp < textspace + p_highpc ; + instructp += length ) { + length = 1; + if ( *instructp == CALLF ) { + /* + * maybe a callf, better check it out. + * skip the count of the number of arguments. + */ +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall]\t0x%x:callf" , instructp - textspace ); + } +# endif DEBUG + firstmode = operandmode( instructp+length ); + switch ( firstmode ) { + case literal: + case immediate: + break; + default: + goto botched; + } + length += operandlength( instructp+length ); + mode = operandmode( instructp + length ); +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "\tfirst operand is %s", operandname( firstmode ) ); + printf( "\tsecond operand is %s\n" , operandname( mode ) ); + } +# endif DEBUG + switch ( mode ) { + case regdef: + case bytedispdef: + case worddispdef: + case longdispdef: + case bytereldef: + case wordreldef: + case longreldef: + /* + * indirect call: call through pointer + * either *d(r) as a parameter or local + * (r) as a return value + * *f as a global pointer + * [are there others that we miss?, + * e.g. arrays of pointers to functions???] + */ + addarc( parentp , &indirectchild , (long) 0 ); + length += operandlength( instructp + length ); + continue; + case byterel: + case wordrel: + case longrel: + /* + * regular pc relative addressing + * check that this is the address of + * a function. + */ + destpc = reladdr( instructp+length ) + - (unsigned long) textspace; + if ( destpc >= s_lowpc && destpc <= s_highpc ) { + childp = nllookup( destpc ); +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall]\tdestpc 0x%x" , destpc ); + printf( " childp->name %s" , childp -> name ); + printf( " childp->value 0x%x\n" , + childp -> value ); + } +# endif DEBUG + if ( childp -> value == destpc ) { + /* + * a hit + */ + addarc( parentp , childp , (long) 0 ); + length += operandlength( instructp + length ); + continue; + } + goto botched; + } + /* + * else: + * it looked like a callf, + * but it wasn't to anywhere. + */ + goto botched; + default: + botched: + /* + * something funny going on. + */ +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall]\tbut it's a botch\n" ); + } +# endif DEBUG + length = 1; + continue; + } + } + } +} diff --git a/usr/src/usr.bin/gprof/tahoe.h b/usr/src/usr.bin/gprof/tahoe.h new file mode 100644 index 0000000000..29e32735f3 --- /dev/null +++ b/usr/src/usr.bin/gprof/tahoe.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 + */ + + /* + * opcode of the `callf' instruction + */ +#define CALLF 0xfe + + /* + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) + */ +#define OFFSET_OF_CODE 2 +#define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) + + /* + * register for pc relative addressing + */ +#define PC 0xf + +enum opermodes { + literal, indexed, reg, regdef, autodec, autoinc, autoincdef, + bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef, + immediate, absolute, byterel, bytereldef, wordrel, wordreldef, + longrel, longreldef +}; +typedef enum opermodes operandenum; diff --git a/usr/src/usr.bin/gprof/vax.c b/usr/src/usr.bin/gprof/vax.c new file mode 100644 index 0000000000..d8d9fa30be --- /dev/null +++ b/usr/src/usr.bin/gprof/vax.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)vax.c 5.6 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include "gprof.h" + + /* + * a namelist entry to be the child of indirect calls + */ +nltype indirectchild = { + "(*)" , /* the name */ + (unsigned long) 0 , /* the pc entry point */ + (unsigned long) 0 , /* entry point aligned to histogram */ + (double) 0.0 , /* ticks in this routine */ + (double) 0.0 , /* cumulative ticks in children */ + (long) 0 , /* how many times called */ + (long) 0 , /* how many calls to self */ + (double) 1.0 , /* propagation fraction */ + (double) 0.0 , /* self propagation time */ + (double) 0.0 , /* child propagation time */ + (bool) 0 , /* print flag */ + (int) 0 , /* index in the graph list */ + (int) 0 , /* graph call chain top-sort order */ + (int) 0 , /* internal number of cycle on */ + (struct nl *) &indirectchild , /* pointer to head of cycle */ + (struct nl *) 0 , /* pointer to next member of cycle */ + (arctype *) 0 , /* list of caller arcs */ + (arctype *) 0 /* list of callee arcs */ + }; + +operandenum +operandmode( modep ) + struct modebyte *modep; +{ + long usesreg = modep -> regfield; + + switch ( modep -> modefield ) { + case 0: + case 1: + case 2: + case 3: + return literal; + case 4: + return indexed; + case 5: + return reg; + case 6: + return regdef; + case 7: + return autodec; + case 8: + return ( usesreg != PC ? autoinc : immediate ); + case 9: + return ( usesreg != PC ? autoincdef : absolute ); + case 10: + return ( usesreg != PC ? bytedisp : byterel ); + case 11: + return ( usesreg != PC ? bytedispdef : bytereldef ); + case 12: + return ( usesreg != PC ? worddisp : wordrel ); + case 13: + return ( usesreg != PC ? worddispdef : wordreldef ); + case 14: + return ( usesreg != PC ? longdisp : longrel ); + case 15: + return ( usesreg != PC ? longdispdef : longreldef ); + } + /* NOTREACHED */ +} + +char * +operandname( mode ) + operandenum mode; +{ + + switch ( mode ) { + case literal: + return "literal"; + case indexed: + return "indexed"; + case reg: + return "register"; + case regdef: + return "register deferred"; + case autodec: + return "autodecrement"; + case autoinc: + return "autoincrement"; + case autoincdef: + return "autoincrement deferred"; + case bytedisp: + return "byte displacement"; + case bytedispdef: + return "byte displacement deferred"; + case byterel: + return "byte relative"; + case bytereldef: + return "byte relative deferred"; + case worddisp: + return "word displacement"; + case worddispdef: + return "word displacement deferred"; + case wordrel: + return "word relative"; + case wordreldef: + return "word relative deferred"; + case immediate: + return "immediate"; + case absolute: + return "absolute"; + case longdisp: + return "long displacement"; + case longdispdef: + return "long displacement deferred"; + case longrel: + return "long relative"; + case longreldef: + return "long relative deferred"; + } + /* NOTREACHED */ +} + +long +operandlength( modep ) + struct modebyte *modep; +{ + + switch ( operandmode( modep ) ) { + case literal: + case reg: + case regdef: + case autodec: + case autoinc: + case autoincdef: + return 1; + case bytedisp: + case bytedispdef: + case byterel: + case bytereldef: + return 2; + case worddisp: + case worddispdef: + case wordrel: + case wordreldef: + return 3; + case immediate: + case absolute: + case longdisp: + case longdispdef: + case longrel: + case longreldef: + return 5; + case indexed: + return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 ); + } + /* NOTREACHED */ +} + +unsigned long +reladdr( modep ) + struct modebyte *modep; +{ + operandenum mode = operandmode( modep ); + char *cp; + short *sp; + long *lp; + + cp = (char *) modep; + cp += 1; /* skip over the mode */ + switch ( mode ) { + default: + fprintf( stderr , "[reladdr] not relative address\n" ); + return (unsigned long) modep; + case byterel: + return (unsigned long) ( cp + sizeof *cp + *cp ); + case wordrel: + sp = (short *) cp; + return (unsigned long) ( cp + sizeof *sp + *sp ); + case longrel: + lp = (long *) cp; + return (unsigned long) ( cp + sizeof *lp + *lp ); + } +} + +findcall( parentp , p_lowpc , p_highpc ) + nltype *parentp; + unsigned long p_lowpc; + unsigned long p_highpc; +{ + unsigned char *instructp; + long length; + nltype *childp; + operandenum mode; + operandenum firstmode; + unsigned long destpc; + + if ( textspace == 0 ) { + return; + } + if ( p_lowpc < s_lowpc ) { + p_lowpc = s_lowpc; + } + if ( p_highpc > s_highpc ) { + p_highpc = s_highpc; + } +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall] %s: 0x%x to 0x%x\n" , + parentp -> name , p_lowpc , p_highpc ); + } +# endif DEBUG + for ( instructp = textspace + p_lowpc ; + instructp < textspace + p_highpc ; + instructp += length ) { + length = 1; + if ( *instructp == CALLS ) { + /* + * maybe a calls, better check it out. + * skip the count of the number of arguments. + */ +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall]\t0x%x:calls" , instructp - textspace ); + } +# endif DEBUG + firstmode = operandmode( (struct modebyte *) (instructp+length) ); + switch ( firstmode ) { + case literal: + case immediate: + break; + default: + goto botched; + } + length += operandlength( (struct modebyte *) (instructp+length) ); + mode = operandmode( (struct modebyte *) ( instructp + length ) ); +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "\tfirst operand is %s", operandname( firstmode ) ); + printf( "\tsecond operand is %s\n" , operandname( mode ) ); + } +# endif DEBUG + switch ( mode ) { + case regdef: + case bytedispdef: + case worddispdef: + case longdispdef: + case bytereldef: + case wordreldef: + case longreldef: + /* + * indirect call: call through pointer + * either *d(r) as a parameter or local + * (r) as a return value + * *f as a global pointer + * [are there others that we miss?, + * e.g. arrays of pointers to functions???] + */ + addarc( parentp , &indirectchild , (long) 0 ); + length += operandlength( + (struct modebyte *) ( instructp + length ) ); + continue; + case byterel: + case wordrel: + case longrel: + /* + * regular pc relative addressing + * check that this is the address of + * a function. + */ + destpc = reladdr( (struct modebyte *) (instructp+length) ) + - (unsigned long) textspace; + if ( destpc >= s_lowpc && destpc <= s_highpc ) { + childp = nllookup( destpc ); +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall]\tdestpc 0x%x" , destpc ); + printf( " childp->name %s" , childp -> name ); + printf( " childp->value 0x%x\n" , + childp -> value ); + } +# endif DEBUG + if ( childp -> value == destpc ) { + /* + * a hit + */ + addarc( parentp , childp , (long) 0 ); + length += operandlength( (struct modebyte *) + ( instructp + length ) ); + continue; + } + goto botched; + } + /* + * else: + * it looked like a calls, + * but it wasn't to anywhere. + */ + goto botched; + default: + botched: + /* + * something funny going on. + */ +# ifdef DEBUG + if ( debug & CALLDEBUG ) { + printf( "[findcall]\tbut it's a botch\n" ); + } +# endif DEBUG + length = 1; + continue; + } + } + } +} diff --git a/usr/src/usr.bin/gprof/vax.h b/usr/src/usr.bin/gprof/vax.h new file mode 100644 index 0000000000..6ededac629 --- /dev/null +++ b/usr/src/usr.bin/gprof/vax.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vax.h 5.4 (Berkeley) 6/1/90 + */ + + /* + * opcode of the `calls' instruction + */ +#define CALLS 0xfb + + /* + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) + */ +#define OFFSET_OF_CODE 2 +#define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) + + /* + * register for pc relative addressing + */ +#define PC 0xf + +enum opermodes { + literal, indexed, reg, regdef, autodec, autoinc, autoincdef, + bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef, + immediate, absolute, byterel, bytereldef, wordrel, wordreldef, + longrel, longreldef +}; +typedef enum opermodes operandenum; + +struct modebyte { + unsigned int regfield:4; + unsigned int modefield:4; +}; + diff --git a/usr/src/usr.bin/indent/Makefile b/usr/src/usr.bin/indent/Makefile new file mode 100644 index 0000000000..863a6c5a34 --- /dev/null +++ b/usr/src/usr.bin/indent/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 5.11 (Berkeley) 5/11/90 + +PROG= indent +SRCS= indent.c io.c lexi.c parse.c pr_comment.c args.c + +.include diff --git a/usr/src/usr.bin/indent/README b/usr/src/usr.bin/indent/README new file mode 100644 index 0000000000..618f1de1fe --- /dev/null +++ b/usr/src/usr.bin/indent/README @@ -0,0 +1,97 @@ +This is the C indenter, it originally came from the University of Illinois +via some distribution tape for PDP-11 Unix. It has subsequently been +hacked upon by James Gosling @ CMU. It isn't very pretty, and really needs +to be completely redone, but it is probably the nicest C pretty printer +around. + +Further additions to provide "Kernel Normal Form" were contributed +by the folks at Sun Microsystems. + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +> From mnetor!yunexus!oz@uunet.UU.NET Wed Mar 9 15:30:55 1988 +> Date: Tue, 8 Mar 88 18:36:25 EST +> From: yunexus!oz@uunet.UU.NET (Ozan Yigit) +> To: bostic@okeeffe.berkeley.edu +> Cc: ccvaxa!willcox@uunet.UU.NET, jag@sun.com, rsalz@uunet.UU.NET +> In-Reply-To: Keith Bostic's message of Tue, 16 Feb 88 16:09:06 PST +> Subject: Re: Indent... + +Thank you for your response about indent. I was wrong in my original +observation (or mis-observation :-). UCB did keep the Illinois +copyright intact. + +The issue still is whether we can distribute indent, and if we can, which +version. David Willcox (the author) states that: + +| Several people have asked me on what basis I claim that indent is in +| the public domain. I knew I would be sorry I made that posting. +| +| Some history. Way back in 1976, the project I worked on at the +| University of Illinois Center for Advanced Computation had a huge +| battle about how to format C code. After about a week of fighting, I +| got disgusted and wrote a program, which I called indent, to reformat C +| code. It had a bunch of different options that would let you format +| the output the way you liked. In particular, all of the different +| formats being championed were supported. +| +| It was my first big C program. It was ugly. It wasn't designed, it +| just sort of grew. But it pretty much worked, and it stopped most of +| the fighting. +| +| As a matter of form, I included a University of Illinois Copyright +| notice. However, my understanding was that, since the work was done +| on an ARPA contract, it was in the public domain. +| +| Time passed. Some years later, indent showed up on one of the early +| emacs distributions. +| +| Later still, someone from UC Berlekey called the UofI and asked if +| indent was in the public domain. They wanted to include it in their +| UNIX distributions, along with the emacs stuff. I was no longer at the +| UofI, but Rob Kolstad, who was, asked me about it. I told him I didn't +| care if they used it, and since then it has been on the BSD distributions. +| +| Somewhere along the way, several other unnamed people have had their +| hands in it. It was converted to understand version 7 C. (The +| original was version 6.) It was converted from its original filter +| interface to its current "blow away the user's file" interface. +| The $HOME/.indent.pro file parsing was added. Some more formatting +| options were added. +| +| The source I have right now has two copyright notices. One is the +| original from the UofI. One is from Berkeley. +| +| I am not a lawyer, and I certainly do not understand copyright law. As +| far as I am concerned, the bulk of this program, everything covered by +| the UofI copyright, is in the public domain, and worth every penny. +| Berkeley's copyright probably should only cover their changes, and I +| don't know their feelings about sending it out. + +In any case, there appears to be noone at UofI to clarify/and change +that copyright, but I am confident (based on the statements of its +author) that the code, as it stands with its copyright, is +distributable, and will not cause any legal problems. + +Hence, the issue reduces to *which* one to distribute through +comp.sources.unix. I would suggest that with the permission of you +folks (given that you have parts copyrighted), we distribute the 4.3 +version of indent, which appears to be the most up-to-date version. I +happen to have just about every known version of indent, including the +very original submission from the author to a unix tape, later the +G-Emacs version, any 4.n version, sun version and the Unipress +version. I still think we should not have to "go-back-in-time" and +re-do all the work you people have done. + +I hope to hear from you as to what you think about this. You may of +course send 4.3 version to the moderator directly, or you can let me +know of your permission, and I will send the sources, or you can let +me know that 4.3 version is off-limits, in which case we would probably +have to revert to an older version. One way or another, I hope to get +a version of indent to comp.sources.unix. + +regards.. oz + +cc: ccvaxa!willcox + sun.com!jar + uunet!rsalz + diff --git a/usr/src/usr.bin/indent/args.c b/usr/src/usr.bin/indent/args.c new file mode 100644 index 0000000000..06064956ec --- /dev/null +++ b/usr/src/usr.bin/indent/args.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)args.c 5.10 (Berkeley) 2/26/91"; +#endif /* not lint */ + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include +#include +#include +#include +#include "indent_globs.h" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ +#define PRO_FONT 4 /* troff font */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +char *option_source = "?"; + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + char *p_name; /* name, eg -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + "T", PRO_SPECIAL, 0, KEY, 0, + "bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation, + "badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop, + "bad", PRO_BOOL, false, ON, &blanklines_after_declarations, + "bap", PRO_BOOL, false, ON, &blanklines_after_procs, + "bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments, + "bc", PRO_BOOL, true, OFF, &ps.leave_comma, + "bl", PRO_BOOL, true, OFF, &btype_2, + "br", PRO_BOOL, true, ON, &btype_2, + "bs", PRO_BOOL, false, ON, &Bill_Shannon, + "cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline, + "cd", PRO_INT, 0, 0, &ps.decl_com_ind, + "ce", PRO_BOOL, true, ON, &cuddle_else, + "ci", PRO_INT, 0, 0, &continuation_indent, + "cli", PRO_SPECIAL, 0, CLI, 0, + "c", PRO_INT, 33, 0, &ps.com_ind, + "di", PRO_INT, 16, 0, &ps.decl_indent, + "dj", PRO_BOOL, false, ON, &ps.ljust_decl, + "d", PRO_INT, 0, 0, &ps.unindent_displace, + "eei", PRO_BOOL, false, ON, &extra_expression_indent, + "ei", PRO_BOOL, true, ON, &ps.else_if, + "fbc", PRO_FONT, 0, 0, (int *) &blkcomf, + "fbx", PRO_FONT, 0, 0, (int *) &boxcomf, + "fb", PRO_FONT, 0, 0, (int *) &bodyf, + "fc1", PRO_BOOL, true, ON, &format_col1_comments, + "fc", PRO_FONT, 0, 0, (int *) &scomf, + "fk", PRO_FONT, 0, 0, (int *) &keywordf, + "fs", PRO_FONT, 0, 0, (int *) &stringf, + "ip", PRO_BOOL, true, ON, &ps.indent_parameters, + "i", PRO_INT, 8, 0, &ps.ind_size, + "lc", PRO_INT, 0, 0, &block_comment_max_col, + "lp", PRO_BOOL, true, ON, &lineup_to_parens, + "l", PRO_INT, 78, 0, &max_col, + "nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation, + "nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop, + "nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations, + "nbap", PRO_BOOL, false, OFF, &blanklines_after_procs, + "nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments, + "nbc", PRO_BOOL, true, ON, &ps.leave_comma, + "nbs", PRO_BOOL, false, OFF, &Bill_Shannon, + "ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline, + "nce", PRO_BOOL, true, OFF, &cuddle_else, + "ndj", PRO_BOOL, false, OFF, &ps.ljust_decl, + "neei", PRO_BOOL, false, OFF, &extra_expression_indent, + "nei", PRO_BOOL, true, OFF, &ps.else_if, + "nfc1", PRO_BOOL, true, OFF, &format_col1_comments, + "nip", PRO_BOOL, true, OFF, &ps.indent_parameters, + "nlp", PRO_BOOL, true, OFF, &lineup_to_parens, + "npcs", PRO_BOOL, false, OFF, &proc_calls_space, + "npro", PRO_SPECIAL, 0, IGN, 0, + "npsl", PRO_BOOL, true, OFF, &procnames_start_line, + "nps", PRO_BOOL, false, OFF, &pointer_as_binop, + "nsc", PRO_BOOL, true, OFF, &star_comment_cont, + "nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines, + "nv", PRO_BOOL, false, OFF, &verbose, + "pcs", PRO_BOOL, false, ON, &proc_calls_space, + "psl", PRO_BOOL, true, ON, &procnames_start_line, + "ps", PRO_BOOL, false, ON, &pointer_as_binop, + "sc", PRO_BOOL, true, ON, &star_comment_cont, + "sob", PRO_BOOL, false, ON, &swallow_optional_blanklines, + "st", PRO_SPECIAL, 0, STDIN, 0, + "troff", PRO_BOOL, false, ON, &troff, + "v", PRO_BOOL, false, ON, &verbose, + /* whew! */ + 0, 0, 0, 0, 0 +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +set_profile() +{ + register FILE *f; + char fname[BUFSIZ]; + static char prof[] = ".indent.pro"; + + sprintf(fname, "%s/%s", getenv("HOME"), prof); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +scan_profile(f) + register FILE *f; +{ + register int i; + register char *p; + char buf[BUFSIZ]; + + while (1) { + for (p = buf; (i = getc(f)) != EOF && (*p = i) > ' '; ++p); + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +char *param_start; + +eqin(s1, s2) + register char *s1; + register char *s2; +{ + while (*s1) { + if (*s1++ != *s2++) + return (false); + } + param_start = s2; + return (true); +} + +/* + * Set the defaults. + */ +set_defaults() +{ + register struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT) + *p->p_obj = p->p_default; +} + +set_option(arg) + register char *arg; +{ + register struct pro *p; + extern double atof(); + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && eqin(p->p_name, arg)) + goto found; + fprintf(stderr, "indent: %s: unknown parameter \"%s\"\n", option_source, arg - 1); + exit(1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == 0) + input = stdin; + if (output == 0) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + { + register char *str = (char *) malloc(strlen(param_start) + 1); + strcpy(str, param_start); + addkey(str, 4); + } + break; + + default: + fprintf(stderr, "\ +indent: set_option: internal error: p_special %d\n", p->p_special); + exit(1); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit(*param_start)) { + need_param: + fprintf(stderr, "indent: %s: ``%s'' requires a parameter\n", + option_source, arg - 1); + exit(1); + } + *p->p_obj = atoi(param_start); + break; + + case PRO_FONT: + parsefont((struct fstate *) p->p_obj, param_start); + break; + + default: + fprintf(stderr, "indent: set_option: internal error: p_type %d\n", + p->p_type); + exit(1); + } +} diff --git a/usr/src/usr.bin/indent/indent.1 b/usr/src/usr.bin/indent/indent.1 new file mode 100644 index 0000000000..fab871807f --- /dev/null +++ b/usr/src/usr.bin/indent/indent.1 @@ -0,0 +1,452 @@ +.\" Copyright (c) 1980, 1990 The Regents of the University of California. +.\" Copyright (c) 1985 Sun Microsystems, Inc. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)indent.1 6.11 (Berkeley) 7/24/91 +.\" +.Dd July 24, 1991 +.Dt INDENT 1 +.Os BSD 4.2 +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm indent +.Op Ar input-file Op Ar output-file +.Op Fl bad | Fl nbad +.Op Fl bap | Fl nbap +.Bk -words +.Op Fl bbb | Fl nbbb +.Ek +.Op Fl \&bc | Fl nbc +.Op Fl \&bl +.Op Fl \&br +.Op Fl c Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Bk -words +.Op Fl fc1 | Fl nfc1 +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl npro +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl troff +.Op Fl v | Fl \&nv +.Sh DESCRIPTION +.Nm Indent +is a +.Ar C +program formatter. It reformats the +.Ar C +program in the +.Ar input-file +according to the switches. The switches which can be +specified are described below. They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input-file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input-file +and a backup copy of +.Ar input-file +is written in the current directory. If +.Ar input-file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Pa file.BAK . +.Pp +If +.Ar output-file +is specified, +.Nm indent +checks to make sure it is different from +.Ar input-file . +.Pp +The options listed below control the formatting style imposed by +.Nm indent . +.Bl -tag -width Op +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. Default: +.Fl nbad . +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. Default: +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. Default: +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. The default is +.Fl \&bc . +.It Fl \&br , \&bl +Specifying +.Fl \&bl +lines up compound statements like this: +.ne 4 +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.ne 3 +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.Pp +.It Fl c n +The column in which comments on code start. The default is 33. +.It Fl cd n +The column in which comments on declarations start. The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. With +this option enabled, comments look like this: +.Bd -literal -offset indent +.ne 3 + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing `else's to cuddle up to the immediately preceding +`}'. The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0 .5 +causes case labels to be indented half a tab stop. The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. The default +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. Specifying +.Fl \&d\&0 +lines up these comments with the code. See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, from a declaration keyword +to the following identifier. The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. If it's enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. In such cases, +.Fl nfc1 +should be +used. The default is +.Fl fc1 . +.It Fl i Ns Ar n +The number of spaces for one indentation level. The default is 4. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. The default is 75. +.It Fl \&lp , nlp +Lines up code surrounded by parenthesis in continuation lines. If a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.ne 2 +.Bd -literal -offset indent +.Li p1 = first_procedure(second_procedure(p2, p3), +.Li \ \ third_procedure(p4,p5)); +.Ed +.Pp +.ne 5 +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +.Li p1\ =\ first_procedure(second_procedure(p2,\ p3), +.Li \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,p5)); +.Ed +.Pp +.ne 5 +Inserting two more newlines we get: +.Bd -literal -offset indent +.Li p1\ =\ first_procedure(second_procedure(p2, +.Li \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +.Li \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4 +.Li \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. The +default is +.Fl psl . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. You can use this to +get rid of blank lines after declarations. Default: +.Fl nsob . +.It Fl \&st +Causes +.Nm indent +to take its input from stdin, and put its output to stdout. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. Names accumulate: +.Fl T +can be specified more than once. You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program won't be formatted as nicely as +it should. This sounds like a painful thing to have to do, but it's really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm indent +can't find all +instances of +.Ic typedef . +.It Fl troff +Causes +.Nm indent +to format the program for processing by +.Xr troff 1 . +It will produce a fancy +listing in much the same spirit as +.Xr vgrind 1 . +If the output file is not specified, the default is standard output, +rather than formatting in place. +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. When in verbose mode, +.Nm indent +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. The default is +.Fl \&nv . +.El +.Pp +You may set up your own `profile' of defaults to +.Nm indent +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. A `.indent.pro' in the current directory takes +precedence over the one in your login directory. If +.Nm indent +is run and a profile file exists, then it is read to set up the program's +defaults. Switches on the command line, though, always override profile +switches. The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +.Nm Indent +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +.Nm Indent +fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. Blank lines break paragraphs. +.Pp +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Pp +.Ss Preprocessor lines +In general, +.Nm indent +leaves preprocessor lines alone. The only +reformatting that it will do is to straighten up trailing comments. It +leaves embedded comments alone. Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm indent +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Pp +.Ss C syntax +.Nm Indent +understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. It attempts to cope with the usual sorts of +incomplete and misformed syntax. In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +.Nm Indent +uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm indent +command appeared in +.Bx 4.2 . +.Sh BUGS +.Nm Indent +has even more switches than +.Xr ls 1 . +.Pp +.ne 5 +A common mistake that often causes grief is typing: +.Pp +.Dl indent *.c +.Pp +to the shell in an attempt to indent all the +.Nm C +programs in a directory. +This is probably a bug, not a feature. diff --git a/usr/src/usr.bin/indent/indent.c b/usr/src/usr.bin/indent/indent.c new file mode 100644 index 0000000000..e77a51ddbe --- /dev/null +++ b/usr/src/usr.bin/indent/indent.c @@ -0,0 +1,1181 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\ + @(#) Copyright (c) 1980 The Regents of the University of California.\n\ + @(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.16 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent_codes.h" +#include + +char *in_name = "Standard Input"; /* will always point to name of input + * file */ +char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +main(argc, argv) + int argc; + char **argv; +{ + + extern int found_err; /* flag set in diag() on error */ + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int flushed_nl; /* used when buffering up comments to remember + * that a newline was passed over */ + int force_nl; /* when true, code must be broken */ + int hd_type; /* used to store type of stmt for if (...), + * for (...), etc */ + register int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expressin of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a ?: + * construct */ + register char *t_ptr; /* used for copying tokens */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + labbuf = (char *) malloc(bufsize); + codebuf = (char *) malloc(bufsize); + tokenbuf = (char *) malloc(bufsize); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + + scase = ps.pcase = false; + squest = 0; + sc_end = 0; + bp_save = 0; + be_save = 0; + + output = 0; + + + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + set_defaults(); + if (i >= argc) + set_profile(); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == 0) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == 0) /* check for open error */ + err(in_name); + continue; + } + else if (output == 0) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + fprintf(stderr, "indent: input and output files must be different\n"); + exit(1); + } + output = fopen(out_name, "w"); + if (output == 0) /* check for create error */ + err(out_name); + continue; + } + fprintf(stderr, "indent: unknown parameter: %s\n", argv[i]); + exit(1); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == 0) { + fprintf(stderr, "indent: usage: indent file [ outfile ] [ options ]\n"); + exit(1); + } + if (output == 0) + if (troff) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (troff) { + if (bodyf.font[0] == 0) + parsefont(&bodyf, "R"); + if (scomf.font[0] == 0) + parsefont(&scomf, "I"); + if (blkcomf.font[0] == 0) + blkcomf = scomf, blkcomf.size += 2; + if (boxcomf.font[0] == 0) + boxcomf = blkcomf; + if (stringf.font[0] == 0) + parsefont(&stringf, "L"); + if (keywordf.font[0] == 0) + parsefont(&keywordf, "B"); + writefdef(&bodyf, 'B'); + writefdef(&scomf, 'C'); + writefdef(&blkcomf, 'L'); + writefdef(&boxcomf, 'X'); + writefdef(&stringf, 'S'); + writefdef(&keywordf, 'K'); + } + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + register char *p = buf_ptr; + register col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = ((col - 1) & ~7) + 9; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + if (troff) { + register char *p = in_name, + *beg = in_name; + + while (*p) + if (*p++ == '/') + beg = p; + fprintf(output, ".Fn \"%s\"\n", beg); + } + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int is_procname; + + type_code = lexi(); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + is_procname = ps.procname[0]; + + /* + * The following code moves everything following an if (), while (), + * else, etc. up to the start of the following stmt to a buffer. This + * allows proper handling of both kinds of brace placement. + */ + + flushed_nl = false; + while (ps.search_brace) { /* if we scanned an if(), while(), + * etc., we might need to copy stuff + * into a buffer we must loop, copying + * stuff into save_com, until we find + * the start of the stmt which follows + * the if, or whatever */ + switch (type_code) { + case newline: + ++line_no; + flushed_nl = true; + case form_feed: + break; /* form feeds and newlines found here will be + * ignored */ + + case lbrace: /* this is a brace that starts the compound + * stmt */ + if (sc_end == 0) { /* ignore buffering if a comment wasnt + * stored up */ + ps.search_brace = false; + goto check_type; + } + if (btype_2) { + save_com[0] = '{'; /* we either want to put the brace + * right after the if */ + goto sw_buffer; /* go to common code to get out of + * this loop */ + } + case comment: /* we have a comment, so we must copy it into + * the buffer */ + if (!flushed_nl || sc_end != 0) { + if (sc_end == 0) { /* if this is the first comment, we + * must set up the buffer */ + save_com[0] = save_com[1] = ' '; + sc_end = &(save_com[2]); + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + + if (sc_end >= &(save_com[sc_size])) { /* check for temp buffer + * overflow */ + diag(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever."); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + } + default: /* it is the start of a normal statment */ + if (flushed_nl) /* if we flushed a newline, make sure it is + * put back */ + force_nl = true; + if (type_code == sp_paren && *token == 'i' + && last_else && ps.else_if + || type_code == sp_nparen && *token == 'e' + && e_code != s_code && e_code[-1] == '}') + force_nl = false; + + if (sc_end == 0) { /* ignore buffering if comment wasnt + * saved up */ + ps.search_brace = false; + goto check_type; + } + if (force_nl) { /* if we should insert a nl here, put it into + * the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the nl is + * read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose && !flushed_nl) /* print error msg if the line + * was not already broken */ + diag(0, "Line broken"); + flushed_nl = false; + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; /* copy token into temp buffer */ + ps.procname[0] = 0; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = 0; + break; + } /* end of switch */ + if (type_code != 0) /* we must make this check, just in case there + * was an unexpected EOF */ + type_code = lexi(); /* read another token */ + /* if (ps.search_brace) ps.procname[0] = 0; */ + if ((is_procname = ps.procname[0]) && flushed_nl + && !procnames_start_line && ps.in_decl + && type_code == ident) + flushed_nl = 0; + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag(1, "Stuff missing from end of file."); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose && !flushed_nl) + diag(0, "Line broken"); + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + *e_code++ = ' '; + for (t_ptr = s_com; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE; + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + ++ps.p_l_follow; /* count parens to make Healy happy */ + if (ps.want_blank && *token != '[' && + (ps.last_token != ident || proc_calls_space + || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) + *e_code++ = ' '; + if (ps.in_decl && !ps.block_init) + if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) { + ps.dumped_decl_indent = 1; + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + e_code += strlen(e_code); + } + else { + while ((e_code - s_code) < dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + *e_code++ = token[0]; + } + else + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + ps.want_blank = false; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + if (ps.sizeof_keyword) + ps.sizeof_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + rparen_count--; + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + } + ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + ps.want_blank = true; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (ps.want_blank) + *e_code++ = ' '; + + if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) { + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } + else { + char *res = token; + + if (ps.in_decl && !ps.block_init) { /* if this is a unary op + * in a declaration, we + * should indent this + * token */ + for (i = 0; token[i]; ++i); /* find length of token */ + while ((e_code - s_code) < (dec_ind - i)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; /* pad it */ + } + } + if (troff && token[0] == '-' && token[1] == '>') + res = "\\(->"; + for (t_ptr = res; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + if (ps.want_blank) + *e_code++ = ' '; + { + char *res = token; + + if (troff) + switch (token[0]) { + case '<': + if (token[1] == '=') + res = "\\(<="; + break; + case '>': + if (token[1] == '=') + res = "\\(>="; + break; + case '!': + if (token[1] == '=') + res = "\\(!="; + break; + case '|': + if (token[1] == '|') + res = "\\(br\\(br"; + else if (token[1] == 0) + res = "\\(br"; + break; + } + for (t_ptr = res; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; /* move the operator */ + } + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * ?: construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the ?: construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_decl) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + for (t_ptr = s_code; *t_ptr; ++t_ptr) + *e_lab++ = *t_ptr; /* turn everything so far into a label */ + e_code = s_code; + *e_lab++ = ':'; + *e_lab++ = ' '; + *e_lab = '\0'; + + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in a error */ + squest = 0; + if (ps.last_token == rparen && rparen_count == 0) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.sizeof_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for a if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after a end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + dump_line(); + ps.want_blank = false; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceeding unbalanced + * parens */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest++] = dec_ind; + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we cant be in the middle of + * a declaration, so dont do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case decl: /* we have a declaration type (int, register, + * etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + ps.in_parameter_declaration = 1; + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + /* + * dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent + * : i); + */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + goto copy_id; + + case ident: /* got an identifier or constant */ + if (ps.in_decl) { /* if we are in a declaration, we must indent + * identifier */ + if (ps.want_blank) + *e_code++ = ' '; + ps.want_blank = false; + if (is_procname == 0 || !procnames_start_line) { + if (!ps.block_init) + if (troff && !ps.dumped_decl_indent) { + sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); + ps.dumped_decl_indent = 1; + e_code += strlen(e_code); + } + else + while ((e_code - s_code) < dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + } + else { + if (dec_ind && s_code != e_code) + dump_line(); + dec_ind = 0; + ps.want_blank = false; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + if (ps.want_blank) + *e_code++ = ' '; + if (troff && ps.its_a_keyword) { + e_code = chfont(&bodyf, &keywordf, e_code); + for (t_ptr = token; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = keywordf.allcaps && islower(*t_ptr) + ? toupper(*t_ptr) : *t_ptr; + } + e_code = chfont(&keywordf, &bodyf, e_code); + } + else + for (t_ptr = token; *t_ptr; ++t_ptr) { + CHECK_SIZE_CODE; + *e_code++ = *t_ptr; + } + ps.want_blank = true; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && is_procname == 0 && !ps.block_init) + while ((e_code - s_code) < (dec_ind - 1)) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + } + + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || in_comment) { + CHECK_SIZE_LAB; + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (troff) + *e_lab++ = BACKSLASH; + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == 0) { /* comment on + * preprocessor line */ + if (sc_end == 0) /* if this is the first comment, we + * must set up the buffer */ + sc_end = &(save_com[0]); + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + bcopy(s_lab + com_start, sc_end, com_end - com_start); + sc_end += com_end - com_start; + if (sc_end >= &save_com[sc_size]) + abort(); + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = 0; + } + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { + if (blanklines_around_conditional_compilation) { + register c; + prefix_blankline_requested++; + while ((c = getc(input)) == '\n'); + ungetc(c, input); + } + if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#else", 5) == 0) + if (ifdef_level <= 0) + diag(1, "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag(1, "Unmatched #endif"); + else { + ifdef_level--; + +#ifdef undef + /* + * This match needs to be more intelligent before the + * message is useful + */ + if (match_state[ifdef_level].tos >= 0 + && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) + diag(0, "Syntactically inconsistant #ifdef alternatives."); +#endif + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a /* this is a biggie */ + if (flushed_nl) { /* we should force a broken line here */ + flushed_nl = false; + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +bakcopy() +{ + int n, + bakchn; + char buff[8 * 1024]; + register char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(bakfile); + while (n = read(fileno(input), buff, sizeof buff)) + if (write(bakchn, buff, n) != n) + err(bakfile); + if (n < 0) + err(in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == 0) + err(bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == 0) { + unlink(bakfile); + err(in_name); + } +} + +err(msg) + char *msg; +{ + extern int errno; + char *strerror(); + + (void)fprintf(stderr, "indent: %s: %s\n", msg, strerror(errno)); + exit(1); +} diff --git a/usr/src/usr.bin/indent/indent_codes.h b/usr/src/usr.bin/indent/indent_codes.h new file mode 100644 index 0000000000..83a2a854a6 --- /dev/null +++ b/usr/src/usr.bin/indent/indent_codes.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_codes.h 5.7 (Berkeley) 6/1/90 + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 diff --git a/usr/src/usr.bin/indent/indent_globs.h b/usr/src/usr.bin/indent/indent_globs.h new file mode 100644 index 0000000000..cdf79f28fa --- /dev/null +++ b/usr/src/usr.bin/indent/indent_globs.h @@ -0,0 +1,310 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_globs.h 5.11 (Berkeley) 2/26/91 + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + +#define tabsize 8 /* the size of a tab */ +#define tabmask 0177770 /* mask used when figuring length of lines + * with tabs */ + + +#define false 0 +#define true 1 + + +FILE *input; /* the fid for the input file */ +FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE \ + if (e_code >= l_code) { \ + register nsize = l_code-s_code+400; \ + codebuf = (char *) realloc(codebuf, nsize); \ + e_code = codebuf + (e_code-s_code) + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM \ + if (e_com >= l_com) { \ + register nsize = l_com-s_com+400; \ + combuf = (char *) realloc(combuf, nsize); \ + e_com = combuf + (e_com-s_com) + 1; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB \ + if (e_lab >= l_lab) { \ + register nsize = l_lab-s_lab+400; \ + labbuf = (char *) realloc(labbuf, nsize); \ + e_lab = labbuf + (e_lab-s_lab) + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN \ + if (e_token >= l_token) { \ + register nsize = l_token-s_token+400; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + e_token = tokenbuf + (e_token-s_token) + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +char *labbuf; /* buffer for label */ +char *s_lab; /* start ... */ +char *e_lab; /* .. and end of stored label */ +char *l_lab; /* limit of label buffer */ + +char *codebuf; /* buffer for code section */ +char *s_code; /* start ... */ +char *e_code; /* .. and end of stored code */ +char *l_code; /* limit of code section */ + +char *combuf; /* buffer for comments */ +char *s_com; /* start ... */ +char *e_com; /* ... and end of stored comments */ +char *l_com; /* limit of comment buffer */ + +#define token s_token +char *tokenbuf; /* the last token scanned */ +char *s_token; +char *e_token; +char *l_token; + +char *in_buffer; /* input buffer */ +char *in_buffer_limit; /* the end of the input buffer */ +char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +char *buf_end; /* ptr to first after last char in in_buffer */ + +char save_com[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +char *sc_end; /* pointer into save_com buffer */ + +char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +char *be_save; /* similarly saved value of buf_end */ + + +int pointer_as_binop; +int blanklines_after_declarations; +int blanklines_before_blockcomments; +int blanklines_after_procs; +int blanklines_around_conditional_compilation; +int swallow_optional_blanklines; +int n_real_blanklines; +int prefix_blankline_requested; +int postfix_blankline_requested; +int break_comma; /* when true and not in parens, break after a + * comma */ +int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +float case_ind; /* indentation level to be used for a "case + * n:" */ +int code_lines; /* count of lines with code */ +int had_eof; /* set to true when input is exhausted */ +int line_no; /* the current line number. */ +int max_col; /* the maximum allowable line length */ +int verbose; /* when true, non-essential error messages are + * printed */ +int cuddle_else; /* true if else should cuddle up to '}' */ +int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +int comment_delimiter_on_blankline; +int troff; /* true iff were generating troff input */ +int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +int inhibit_formatting; /* true if INDENT OFF is in effect */ +int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +int block_comment_max_col; +int extra_expression_indent; /* True if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ + +/* -troff font state information */ + +struct fstate { + char font[4]; + char size; + int allcaps:1; +}; +char *chfont(); + +struct fstate + keywordf, /* keyword font */ + stringf, /* string font */ + boxcomf, /* Box comment font */ + blkcomf, /* Block comment font */ + scomf, /* Same line comment font */ + bodyf; /* major body font */ + + +#define STACKSIZE 150 + +struct parser_state { + int last_token; + struct fstate cfont; /* Current font */ + int p_stack[STACKSIZE]; /* this is the parsers stack */ + int il[STACKSIZE]; /* this stack stores indentation levels */ + float cstk[STACKSIZE];/* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in /* */ + int comment_delta, + n_comment_delta; + int cast_mask; /* indicates which close parens close off + * casts */ + int sizeof_mask; /* indicates which close parens close off + * sizeof''s */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * coment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within stmts */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int its_a_keyword; + int sizeof_keyword; + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +} ps; + +int ifdef_level; +int rparen_count; +struct parser_state state_stack[5]; +struct parser_state match_state[5]; diff --git a/usr/src/usr.bin/indent/io.c b/usr/src/usr.bin/indent/io.c new file mode 100644 index 0000000000..1973a95416 --- /dev/null +++ b/usr/src/usr.bin/indent/io.c @@ -0,0 +1,625 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)io.c 5.15 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "indent_globs.h" + + +int comment_open; +static paren_target; + +dump_line() +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + register int cur_col, + target_col; + static not_first_line; + + if (ps.procname[0]) { + if (troff) { + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + fprintf(output, ".Pr \"%s\"\n", ps.procname); + } + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + register char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + e_lab - s, s); + } + else fprintf(output, "%.*s", e_lab - s_lab, s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + register char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + register i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) + if (troff) { + int all_here = 0; + register char *p; + + if (e_com[-1] == '/' && e_com[-2] == '*') + e_com -= 2, all_here++; + while (e_com > s_com && e_com[-1] == ' ') + e_com--; + *e_com = 0; + p = s_com; + while (*p == ' ') + p++; + if (p[0] == '/' && p[1] == '*') + p += 2, all_here++; + else if (p[0] == '*') + p += p[1] == '/' ? 2 : 1; + while (*p == ' ') + p++; + if (*p == 0) + goto inhibit_newline; + if (comment_open < 2 && ps.box_com) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + if (comment_open == 0) { + if ('a' <= *p && *p <= 'z') + *p = *p + 'A' - 'a'; + if (e_com - p < 50 && all_here == 2) { + register char *follow = p; + fprintf(output, "\n.nr C! \\w\1"); + while (follow < e_com) { + switch (*follow) { + case '\n': + putc(' ', output); + case 1: + break; + case '\\': + putc('\\', output); + default: + putc(*follow, output); + } + follow++; + } + putc(1, output); + } + fprintf(output, "\n./* %dp %d %dp\n", + ps.com_col * 7, + (s_code != e_code || s_lab != e_lab) - ps.box_com, + target_col * 7); + } + comment_open = 1 + ps.box_com; + while (*p) { + if (*p == BACKSLASH) + putc(BACKSLASH, output); + putc(*p++, output); + } + } + else { /* print comment, if any */ + register target = ps.com_col; + register char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') + com_st++, target += 8; /* ? */ + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = ((target - 1) & ~7) + 9, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment cant fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace(e_com[-1])) + e_com--; + cur_col = pad_output(cur_col, target); + if (!ps.box_com) { + if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1)) + if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1) + com_st[1] = '*'; + else + fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); + } + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + cur_col = count_spaces(cur_col, com_st); + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); +inhibit_newline: + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; + return; +} + +compute_code_target() +{ + register target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent * ps.paren_level; + else { + register w; + register t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +compute_label_target() +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : ps.ind_size * (ps.ind_level - label_offset) + 1; +} + + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: fill_buffer + * + * FUNCTION: Reads one block of input into input_buffer + * + * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A + * Willcox of CAC Added check for switch back to partly full input + * buffer from temporary buffer + * + */ +int +fill_buffer() +{ /* this routine reads stuff from the input */ + register char *p; + register int i; + register FILE *f = input; + + if (bp_save != 0) { /* there is a partly filled input buffer left */ + buf_ptr = bp_save; /* dont read anything, just switch buffers */ + buf_end = be_save; + bp_save = be_save = 0; + if (buf_ptr < buf_end) + return; /* only return if there is really something in + * this buffer */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + register size = (in_buffer_limit - in_buffer) * 2 + 10; + register offset = p - in_buffer; + in_buffer = (char *) realloc(in_buffer, size); + if (in_buffer == 0) + err("input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + if ((i = getc(f)) == EOF) { + *p++ = ' '; + *p++ = '\n'; + had_eof = true; + break; + } + *p++ = i; + if (i == '\n') + break; + } + buf_ptr = in_buffer; + buf_end = p; + if (p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } + return; +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column target + * nteger The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +pad_output(current, target) /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + int current; /* the current column value */ + int target; /* position we want it at */ +{ + register int curr; /* internal column pointer */ + register int tcur; + + if (troff) + fprintf(output, "\\h'|%dp'", (target - 1) * 7); + else { + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) { + putc('\t', output); + curr = tcur; + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + } + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces(current, buffer) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ + int current; + char *buffer; +{ + register char *buf; /* used to look thru buffer */ + register int cur; /* current character counter */ + + cur = current; + + for (buf = buffer; *buf != '\0'; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = ((cur - 1) & tabmask) + tabsize + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +int found_err; +/* VARARGS2 */ +diag(level, msg, a, b) + char *msg; +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +writefdef(f, nm) + register struct fstate *f; +{ + fprintf(output, ".ds f%c %s\n.nr s%c %d\n", + nm, f->font, nm, f->size); +} + +char * +chfont(of, nf, s) + register struct fstate *of, + *nf; + char *s; +{ + if (of->font[0] != nf->font[0] + || of->font[1] != nf->font[1]) { + *s++ = '\\'; + *s++ = 'f'; + if (nf->font[1]) { + *s++ = '('; + *s++ = nf->font[0]; + *s++ = nf->font[1]; + } + else + *s++ = nf->font[0]; + } + if (nf->size != of->size) { + *s++ = '\\'; + *s++ = 's'; + if (nf->size < of->size) { + *s++ = '-'; + *s++ = '0' + of->size - nf->size; + } + else { + *s++ = '+'; + *s++ = '0' + nf->size - of->size; + } + } + return s; +} + + +parsefont(f, s0) + register struct fstate *f; + char *s0; +{ + register char *s = s0; + int sizedelta = 0; + bzero(f, sizeof *f); + while (*s) { + if (isdigit(*s)) + f->size = f->size * 10 + *s - '0'; + else if (isupper(*s)) + if (f->font[0]) + f->font[1] = *s; + else + f->font[0] = *s; + else if (*s == 'c') + f->allcaps = 1; + else if (*s == '+') + sizedelta++; + else if (*s == '-') + sizedelta--; + else { + fprintf(stderr, "indent: bad font specification: %s\n", s0); + exit(1); + } + s++; + } + if (f->font[0] == 0) + f->font[0] = 'R'; + if (bodyf.size == 0) + bodyf.size = 11; + if (f->size == 0) + f->size = bodyf.size + sizedelta; + else if (sizedelta > 0) + f->size += bodyf.size; + else + f->size = bodyf.size - f->size; +} diff --git a/usr/src/usr.bin/indent/lexi.c b/usr/src/usr.bin/indent/lexi.c new file mode 100644 index 0000000000..4ddc1fb257 --- /dev/null +++ b/usr/src/usr.bin/indent/lexi.c @@ -0,0 +1,559 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)lexi.c 5.16 (Berkeley) 2/26/91"; +#endif /* not lint */ + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include +#include +#include +#include +#include "indent_globs.h" +#include "indent_codes.h" + +#define alphanum 1 +#define opchar 3 + +struct templ { + char *rwd; + int rwcode; +}; + +struct templ specials[100] = +{ + "switch", 1, + "case", 2, + "break", 0, + "struct", 3, + "union", 3, + "enum", 3, + "default", 2, + "int", 4, + "char", 4, + "float", 4, + "double", 4, + "long", 4, + "short", 4, + "typdef", 4, + "unsigned", 4, + "register", 4, + "static", 4, + "global", 4, + "extern", 4, + "void", 4, + "goto", 0, + "return", 0, + "if", 5, + "while", 5, + "for", 5, + "else", 6, + "do", 6, + "sizeof", 7, + 0, 0 +}; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + + + + +int +lexi() +{ + int unary_delim; /* this is set to 1 if the current token + * + * forces a following operator to be unary */ + static int last_code; /* the last token type returned */ + static int l_struct; /* set to 1 if the last token was 'struct' */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + ps.col_1 = ps.last_nl; /* tell world that this token started in + * column 1 iff the last thing scanned was nl */ + ps.last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + ps.col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr] == alphanum || buf_ptr[0] == '.' && isdigit(buf_ptr[1])) { + /* + * we have a character or number + */ + register char *j; /* used for searching thru list of + * + * reserved words */ + register struct templ *p; + + if (isdigit(*buf_ptr) || buf_ptr[0] == '.' && isdigit(buf_ptr[1])) { + int seendot = 0, + seenexp = 0; + if (*buf_ptr == '0' && + (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) { + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + while (isxdigit(*buf_ptr)) { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + } + } + else + while (1) { + if (*buf_ptr == '.') + if (seendot) + break; + else + seendot++; + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (!isdigit(*buf_ptr) && *buf_ptr != '.') + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + if (*buf_ptr == 'L' || *buf_ptr == 'l') + *e_token++ = *buf_ptr++; + } + else + while (chartype[*buf_ptr] == alphanum) { /* copy it over */ + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token++ = '\0'; + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + ps.its_a_keyword = false; + ps.sizeof_keyword = false; + if (l_struct) { /* if last token was 'struct', then this token + * should be treated as a declaration */ + l_struct = false; + last_code = ident; + ps.last_u_d = true; + return (decl); + } + ps.last_u_d = false; /* Operator after indentifier is binary */ + last_code = ident; /* Remember that this is the code we will + * return */ + + /* + * This loop will check if the token is a keyword. + */ + for (p = specials; (j = p->rwd) != 0; p++) { + register char *p = s_token; /* point at scanned token */ + if (*j++ != *p++ || *j++ != *p++) + continue; /* This test depends on the fact that + * identifiers are always at least 1 character + * long (ie. the first two bytes of the + * identifier are always meaningful) */ + if (p[-1] == 0) + break; /* If its a one-character identifier */ + while (*p++ == *j) + if (*j++ == 0) + goto found_keyword; /* I wish that C had a multi-level + * break... */ + } + if (p->rwd) { /* we have a keyword */ + found_keyword: + ps.its_a_keyword = true; + ps.last_u_d = true; + switch (p->rwcode) { + case 1: /* it is a switch */ + return (swstmt); + case 2: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + if (ps.p_l_follow) + break; /* inside parens: cast */ + l_struct = true; + + /* + * Next time around, we will want to know that we have had a + * 'struct' + */ + case 4: /* one of the declaration keywords */ + if (ps.p_l_follow) { + ps.cast_mask |= 1 << ps.p_l_follow; + break; /* inside parens: cast */ + } + last_code = decl; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 7: + ps.sizeof_keyword = true; + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) { + register char *tp = buf_ptr; + while (tp < buf_end) + if (*tp++ == ')' && (*tp == ';' || *tp == ',')) + goto not_proc; + strncpy(ps.procname, token, sizeof ps.procname - 1); + ps.in_parameter_declaration = 1; + rparen_count = 1; + not_proc:; + } + /* + * The following hack attempts to guess whether or not the current + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_') + && !ps.p_l_follow + && !ps.block_init + && (ps.last_token == rparen || ps.last_token == semicolon || + ps.last_token == decl || + ps.last_token == lbrace || ps.last_token == rbrace)) { + ps.its_a_keyword = true; + ps.last_u_d = true; + last_code = decl; + return decl; + } + if (last_code == decl) /* if this is a declared variable, then + * following sign is unary */ + ps.last_u_d = true; /* will make "int a -1" work */ + last_code = ident; + return (ident); /* the ident is not in the list */ + } /* end of procesing for alpanum character */ + + /* Scan a non-alphanumeric token */ + + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + if (troff) { + e_token[-1] = '`'; + if (qchar == '"') + *e_token++ = '`'; + e_token = chfont(&bodyf, &stringf, e_token); + } + do { /* copy the string */ + while (1) { /* move one character or [/] */ + if (*buf_ptr == '\n') { + printf("%d: Unterminated literal\n", line_no); + goto stop_lit; + } + CHECK_SIZE_TOKEN; /* Only have to do this once in this loop, + * since CHECK_SIZE guarantees that there + * are at least 5 entries left */ + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + if (troff) { + *++e_token = BACKSLASH; + if (*buf_ptr == BACKSLASH) + *++e_token = BACKSLASH; + } + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); + if (troff) { + e_token = chfont(&stringf, &bodyf, e_token - 1); + if (qchar == '"') + *e_token++ = '\''; + } +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = ps.last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (ps.in_or_st) ps.block_init = 1; + */ + /* ? code = ps.block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = ps.block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = ps.last_u_d; + ps.last_nl = true; /* remember this so we can set 'ps.col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (last_code == ident || last_code == rparen) { + code = (ps.last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + if (!pointer_as_binop) { + unary_delim = false; + code = unary_op; + ps.want_blank = false; + } + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (ps.in_or_st) + ps.block_init = 1; +#ifdef undef + if (chartype[*buf_ptr] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = ps.last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (ps.last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (code != newline) { + l_struct = false; + last_code = code; + } + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + ps.last_u_d = unary_delim; + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +/* + * Add the given keyword to the keyword table, using val as the keyword type + */ +addkey(key, val) + char *key; +{ + register struct templ *p = specials; + while (p->rwd) + if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) + return; + else + p++; + if (p >= specials + sizeof specials / sizeof specials[0]) + return; /* For now, table overflows are silently + * ignored */ + p->rwd = key; + p->rwcode = val; + p[1].rwd = 0; + p[1].rwcode = 0; + return; +} diff --git a/usr/src/usr.bin/indent/parse.c b/usr/src/usr.bin/indent/parse.c new file mode 100644 index 0000000000..280485eb1a --- /dev/null +++ b/usr/src/usr.bin/indent/parse.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parse.c 5.12 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include "indent_globs.h" +#include "indent_codes.h" + +parse(tk) + int tk; /* the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + ps.i_l_follow = ps.il[ps.tos]; + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have or */ + if (ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag(1, "Stmt nesting error."); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * + * + * do "dostmt" + * if "ifstmt" + * switch + * decl + * "ifelse" + * for + * while + * "dostmt" while + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +reduce() +{ + + register int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* */ + case_ind = ps.cstk[ps.tos - 1]; + + case decl: /* finish of a declaration */ + case elsehead: + /* < else> */ + case forstmt: + /* */ + case whilestmt: + /* */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* */ + return; + + } /* end of section for on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.p_stack[--ps.tos] = stmt; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/usr/src/usr.bin/indent/pr_comment.c b/usr/src/usr.bin/indent/pr_comment.c new file mode 100644 index 0000000000..349f94fcf8 --- /dev/null +++ b/usr/src/usr.bin/indent/pr_comment.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980 The Regents of the University of California. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 5.12 (Berkeley) 2/26/91"; +#endif /* not lint */ + +#include +#include +#include "indent_globs.h" + +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + + +pr_comment() +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int unix_comment; /* tri-state variable used to decide if it is + * a unix-style comment. 0 means only blanks + * since /*, 1 means regular style comment, 2 + * means unix style comment */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + /* + * int ps.last_nl = 0; /* true iff the last significant thing + * weve seen is a newline + */ + int one_liner = 1; /* true iff this comment is a one-liner */ + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = 0; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + unix_comment = 1; /* set flag to let us figure out if there is a + * unix-style comment ** DISABLED: use 0 to + * reenable this hack! */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*') { + ps.box_com = true; /* a comment with a '-' or '*' immediately + * after the /* is assumed to be a boxed + * comment */ + break_delim = 0; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + register target_col; + break_delim = 0; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col < target_col) + ps.com_col = ((target_col + 7) & ~7) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + buf_ptr[-2] = 0; + ps.n_comment_delta = 1 - count_spaces(1, in_buffer); + buf_ptr[-2] = '/'; + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + *e_com = '\0'; + if (troff) { + now_col = 1; + adj_max_col = 80; + } + else + now_col = count_spaces(ps.com_col, s_com); /* figure what column we + * would be in if we + * printed the comment + * now */ + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + if (*buf_ptr > 040 && *buf_ptr != '*') + ps.last_nl = 0; + CHECK_SIZE_COM; + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = 0; + *e_com++ = ' '; + *e_com++ = '*'; + *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t'); + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + *e_com = '\0'; + dump_line(); + return; + } + one_liner = 0; + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) { + *e_com++ = ' '; + *e_com++ = ' '; + } + *e_com = '\0'; + if (!ps.box_com && e_com - s_com > 3) { + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + dump_line(); + CHECK_SIZE_COM; + *e_com++ = ' '; + *e_com++ = ' '; + } + dump_line(); + now_col = ps.com_col; + } + else { + ps.last_nl = 1; + if (unix_comment != 1) { /* we not are in unix_style + * comment */ + if (unix_comment == 0 && s_code == e_code) { + /* + * if it is a UNIX-style comment, ignore the + * requirement that previous line be blank for + * unindention + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + if (ps.com_col <= 1) + ps.com_col = 2; + } + unix_comment = 2; /* permanently remember that we are in + * this type of comment */ + dump_line(); + ++line_no; + now_col = ps.com_col; + *e_com++ = ' '; + /* + * fix so that the star at the start of the line will line + * up + */ + do /* flush leading white space */ + if (++buf_ptr >= buf_end) + fill_buffer(); + while (*buf_ptr == ' ' || *buf_ptr == '\t'); + break; + } + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + CHECK_SIZE_COM; + *e_com++ = ' '; + ++now_col; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + + if (unix_comment == 0) /* set flag to show we are not in + * unix-style comment */ + unix_comment = 1; + + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + + if (*(e_com - 1) != ' ' && !ps.box_com) { /* insure blank before + * end */ + *e_com++ = ' '; + ++now_col; + } + if (break_delim == 1 && !one_liner && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (break_delim == 2 && e_com > s_com + 3 + /* now_col > adj_max_col - 2 && !ps.box_com */ ) { + *e_com = '\0'; + dump_line(); + now_col = ps.com_col; + } + CHECK_SIZE_COM; + *e_com++ = '*'; + *e_com++ = '/'; + *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else { /* handle isolated '*' */ + *e_com++ = '*'; + ++now_col; + } + break; + default: /* we have a random char */ + if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') + unix_comment = 1; /* we are not in unix-style comment */ + + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + + if (*e_com == '\t') /* keep track of column */ + now_col = ((now_col - 1) & tabmask) + tabsize + 1; + else if (*e_com == '\b') /* this is a backspace */ + --now_col; + else + ++now_col; + + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; + /* remember we saw a blank */ + + ++e_com; + if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (break_delim == 1 && s_com[0] == '/' + && s_com[1] == '*' && s_com[2] == ' ') { + char *t = e_com; + break_delim = 2; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments) + prefix_blankline_requested = 1; + dump_line(); + e_com = t; + s_com[0] = s_com[1] = s_com[2] = ' '; + } + if (last_bl == 0) { /* we have seen no blanks */ + last_bl = e_com; /* fake it */ + *e_com++ = ' '; + } + *e_com = '\0'; /* print what we have */ + *last_bl = '\0'; + while (last_bl > s_com && last_bl[-1] < 040) + *--last_bl = 0; + e_com = last_bl; + dump_line(); + + *e_com++ = ' '; /* add blanks for continuation */ + *e_com++ = ' '; + *e_com++ = ' '; + + t_ptr = last_bl + 1; + last_bl = 0; + if (t_ptr >= e_com) { + while (*t_ptr == ' ' || *t_ptr == '\t') + t_ptr++; + while (*t_ptr != '\0') { /* move unprinted part of + * comment down in buffer */ + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + *e_com = '\0'; + now_col = count_spaces(ps.com_col, s_com); /* recompute current + * position */ + } + break; + } + } +} diff --git a/usr/src/usr.bin/lastcomm/Makefile b/usr/src/usr.bin/lastcomm/Makefile new file mode 100644 index 0000000000..385a0ee57b --- /dev/null +++ b/usr/src/usr.bin/lastcomm/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 5.4 (Berkeley) 5/11/90 + +PROG= lastcomm +DPADD= ${LIBUTIL} +LDADD= -lutil + +.include diff --git a/usr/src/usr.bin/lastcomm/lastcomm.1 b/usr/src/usr.bin/lastcomm/lastcomm.1 new file mode 100644 index 0000000000..eb835d0ef5 --- /dev/null +++ b/usr/src/usr.bin/lastcomm/lastcomm.1 @@ -0,0 +1,124 @@ +.\" Copyright (c) 1980, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lastcomm.1 6.8 (Berkeley) 7/27/91 +.\" +.Dd July 27, 1991 +.Dt LASTCOMM 1 +.Os BSD 3 +.Sh NAME +.Nm lastcomm +.Nd show last commands executed in reverse order +.Sh SYNOPSIS +.Nm lastcomm +.Op Fl f Ar file +.Op Ar command ... +.Op Ar user ... +.Op Ar terminal ... +.Sh DESCRIPTION +.Nm Lastcomm +gives information on previously executed commands. +With no arguments, +.Nm lastcomm +prints information about all the commands recorded +during the current accounting file's lifetime. +.Pp +Option: +.Pp +.Bl -tag -width Fl +.It Fl f Ar file +Read from +.Ar file +rather than the default +accounting file. +.El +.Pp +If called with arguments, only accounting entries with a +matching +.Ar command +name, +.Ar user +name, +or +.Ar terminal +name +are printed. +So, for example: +.Pp +.Dl lastcomm a.out root ttyd0 +.Pp +would produce a listing of all the +executions of commands named +.Pa a.out +by user +.Ar root +on the terminal +.Ar ttyd0 . +.Pp +For each process entry, the following are printed. +.Pp +.Bl -bullet -offset indent -compact +.It +The name of the user who ran the process. +.It +Flags, as accumulated by the accounting facilities in the system. +.It +The command name under which the process was called. +.It +The amount of cpu time used by the process (in seconds). +.It +The time the process exited. +.El +.Pp +The flags are encoded as follows: ``S'' indicates the command was +executed by the super-user, ``F'' indicates the command ran after +a fork, but without a following +.Xr exec , +``C'' indicates the command was run in PDP-11 compatibility mode +(VAX only), +``D'' indicates the command terminated with the generation of a +.Pa core +file, and ``X'' indicates the command was terminated with a signal. +.Sh FILES +.Bl -tag -width /var/account/acct -compact +.It Pa /var/account/acct +Default accounting file. +.El +.Sh SEE ALSO +.Xr last 1 , +.Xr sigvec 2 , +.Xr acct 5 , +.Xr core 5 +.Sh HISTORY +The +.Nm lastcomm +command appeared in +.Bx 3.0 . diff --git a/usr/src/usr.bin/lastcomm/lastcomm.c b/usr/src/usr.bin/lastcomm/lastcomm.c new file mode 100644 index 0000000000..a5b1cc5c35 --- /dev/null +++ b/usr/src/usr.bin/lastcomm/lastcomm.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lastcomm.c 5.11 (Berkeley) 6/1/90"; +#endif /* not lint */ + +/* + * last command + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +struct acct buf[DEV_BSIZE / sizeof (struct acct)]; + +time_t expand(); +char *flagbits(); +char *getdev(); + +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + extern char *optarg; + register struct acct *acp; + register int bn, cc; + struct stat sb; + int ch, fd; + char *acctfile, *ctime(), *strcpy(), *user_from_uid(); + long lseek(); + + acctfile = _PATH_ACCT; + while ((ch = getopt(argc, argv, "f:")) != EOF) + switch((char)ch) { + case 'f': + acctfile = optarg; + break; + case '?': + default: + fputs("lastcomm [ -f file ]\n", stderr); + exit(1); + } + argv += optind; + + fd = open(acctfile, O_RDONLY); + if (fd < 0) { + perror(acctfile); + exit(1); + } + (void)fstat(fd, &sb); + setpassent(1); + for (bn = btodb(sb.st_size); bn >= 0; bn--) { + (void)lseek(fd, (off_t)dbtob(bn), L_SET); + cc = read(fd, buf, DEV_BSIZE); + if (cc < 0) { + perror("read"); + break; + } + acp = buf + (cc / sizeof (buf[0])) - 1; + for (; acp >= buf; acp--) { + register char *cp; + time_t x; + + if (acp->ac_comm[0] == '\0') + (void)strcpy(acp->ac_comm, "?"); + for (cp = &acp->ac_comm[0]; + cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp; + cp++) + if (!isascii(*cp) || iscntrl(*cp)) + *cp = '?'; + if (*argv && !ok(argv, acp)) + continue; + x = expand(acp->ac_utime) + expand(acp->ac_stime); + printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n", + fldsiz(acct, ac_comm), fldsiz(acct, ac_comm), + acp->ac_comm, flagbits(acp->ac_flag), + UT_NAMESIZE, user_from_uid(acp->ac_uid, 0), + UT_LINESIZE, getdev(acp->ac_tty), + x / (double)AHZ, ctime(&acp->ac_btime)); + } + } +} + +time_t +expand (t) + unsigned t; +{ + register time_t nt; + + nt = t & 017777; + t >>= 13; + while (t) { + t--; + nt <<= 3; + } + return (nt); +} + +char * +flagbits(f) + register int f; +{ + static char flags[20]; + char *p, *strcpy(); + +#define BIT(flag, ch) if (f & flag) *p++ = ch; + p = strcpy(flags, "- "); + BIT(ASU, 'S'); + BIT(AFORK, 'F'); + BIT(ACOMPAT, 'C'); + BIT(ACORE, 'D'); + BIT(AXSIG, 'X'); + return (flags); +} + +ok(argv, acp) + register char *argv[]; + register struct acct *acp; +{ + register char *cp; + char *user_from_uid(); + + do { + cp = user_from_uid(acp->ac_uid, 0); + if (!strcmp(cp, *argv)) + return(1); + if ((cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv)) + return(1); + if (!strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm))) + return(1); + } while (*++argv); + return(0); +} + +#include + +#define N_DEVS 43 /* hash value for device names */ +#define NDEVS 500 /* max number of file names in /dev */ + +struct devhash { + dev_t dev_dev; + char dev_name [UT_LINESIZE + 1]; + struct devhash * dev_nxt; +}; +struct devhash *dev_hash[N_DEVS]; +struct devhash *dev_chain; +#define HASH(d) (((int) d) % N_DEVS) + +setupdevs() +{ + register DIR * fd; + register struct devhash * hashtab; + register ndevs = NDEVS; + struct direct * dp; + char *malloc(); + + /*NOSTRICT*/ + hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash)); + if (hashtab == (struct devhash *)0) { + fputs("No mem for dev table\n", stderr); + return; + } + if ((fd = opendir(_PATH_DEV)) == NULL) { + perror(_PATH_DEV); + return; + } + while (dp = readdir(fd)) { + if (dp->d_ino == 0) + continue; + if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console")) + continue; + (void)strncpy(hashtab->dev_name, dp->d_name, UT_LINESIZE); + hashtab->dev_name[UT_LINESIZE] = 0; + hashtab->dev_nxt = dev_chain; + dev_chain = hashtab; + hashtab++; + if (--ndevs <= 0) + break; + } + closedir(fd); +} + +char * +getdev(dev) + dev_t dev; +{ + register struct devhash *hp, *nhp; + struct stat statb; + char name[fldsiz(devhash, dev_name) + 6]; + static dev_t lastdev = (dev_t) -1; + static char *lastname; + static int init = 0; + char *strcpy(), *strcat(); + + if (dev == NODEV) + return ("__"); + if (dev == lastdev) + return (lastname); + if (!init) { + setupdevs(); + init++; + } + for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt) + if (hp->dev_dev == dev) { + lastdev = dev; + return (lastname = hp->dev_name); + } + for (hp = dev_chain; hp; hp = nhp) { + nhp = hp->dev_nxt; + (void)strcpy(name, _PATH_DEV); + strcat(name, hp->dev_name); + if (stat(name, &statb) < 0) /* name truncated usually */ + continue; + if ((statb.st_mode & S_IFMT) != S_IFCHR) + continue; + hp->dev_dev = statb.st_rdev; + hp->dev_nxt = dev_hash[HASH(hp->dev_dev)]; + dev_hash[HASH(hp->dev_dev)] = hp; + if (hp->dev_dev == dev) { + dev_chain = nhp; + lastdev = dev; + return (lastname = hp->dev_name); + } + } + dev_chain = (struct devhash *) 0; + return ("??"); +} diff --git a/usr/src/usr.bin/lastcomm/pathnames.h b/usr/src/usr.bin/lastcomm/pathnames.h new file mode 100644 index 0000000000..fc7f53d8bc --- /dev/null +++ b/usr/src/usr.bin/lastcomm/pathnames.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.3 (Berkeley) 6/1/90 + */ + +#include + +#define _PATH_ACCT "/var/account/acct" diff --git a/usr/src/usr.bin/look/Makefile b/usr/src/usr.bin/look/Makefile new file mode 100644 index 0000000000..8da0d29762 --- /dev/null +++ b/usr/src/usr.bin/look/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 5.2 (Berkeley) 5/11/90 + +PROG= look + +.include diff --git a/usr/src/usr.bin/look/look.1 b/usr/src/usr.bin/look/look.1 new file mode 100644 index 0000000000..1a71a619f6 --- /dev/null +++ b/usr/src/usr.bin/look/look.1 @@ -0,0 +1,96 @@ +.\" Copyright (c) 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)look.1 6.6 (Berkeley) 7/21/91 +.\" +.Dd July 21, 1991 +.Dt LOOK 1 +.Os +.Sh NAME +.Nm look +.Nd display lines beginning with a given string +.Sh SYNOPSIS +.Nm look +.Op Fl df +.Ar string +.Op Ar file +.Sh DESCRIPTION +The +.Nm look +utility displays any lines in +.Ar file +which contain +.Ar string +as a prefix. +As +.Nm look +performs a binary search, the lines in +.Ar file +must be sorted. +.Pp +If +.Ar file +is not specified, the file +.Pa /usr/share/dict/words +is used, only alphanumeric characters are compared and the case of +alphabetic characters is ignored. +.Pp +Options: +.Bl -tag -width Ds +.It Fl d +Dictionary character set and order, i.e. only alphanumeric characters +are compared. +.It Fl f +Ignore the case of alphabetic characters. +.El +.Pp +The +.Nm look +utility exits 0 if one or more lines were found and displayed, +1 if no lines were found, and >1 if an error occurred. +.Sh FILES +.Bl -tag -width /usr/share/dict/words -compact +.It Pa /usr/share/dict/words +the dictionary +.El +.Sh SEE ALSO +.Xr grep 1 , +.Xr sort 1 +.Sh COMPATIBILITY +The original manual page stated that tabs and blank characters participated +in comparisons when the +.Fl d +option was specified. +This was incorrect and the current man page matches the historic +implementation. +.Sh HISTORY +.Nm Look +appeared in Version 7 AT&T Unix. diff --git a/usr/src/usr.bin/look/look.c b/usr/src/usr.bin/look/look.c new file mode 100644 index 0000000000..2db9f7d4d1 --- /dev/null +++ b/usr/src/usr.bin/look/look.c @@ -0,0 +1,340 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * David Hitz of Auspex Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1991 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)look.c 5.1 (Berkeley) 7/21/91"; +#endif /* not lint */ + +/* + * look -- find lines in a sorted list. + * + * The man page said that TABs and SPACEs participate in -d comparisons. + * In fact, they were ignored. This implements historic practice, not + * the manual page. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +/* + * FOLD and DICT convert characters to a normal form for comparison, + * according to the user specified flags. + * + * DICT expects integers because it uses a non-character value to + * indicate a character which should not participate in comparisons. + */ +#define EQUAL 0 +#define GREATER 1 +#define LESS (-1) +#define NO_COMPARE (-2) + +#define FOLD(c) (isascii(c) && isupper(c) ? tolower(c) : (c)) +#define DICT(c) (isascii(c) && isalnum(c) ? (c) : NO_COMPARE) + +int dflag, fflag; + +char *binary_search __P((char *, char *, char *)); +int compare __P((char *, char *, char *)); +void err __P((const char *fmt, ...)); +char *linear_search __P((char *, char *, char *)); +int look __P((char *, char *, char *)); +void print_from __P((char *, char *, char *)); +void usage __P((void)); + +main(argc, argv) + int argc; + char *argv[]; +{ + struct stat sb; + int ch, fd; + char *back, *file, *front, *string; + + file = _PATH_WORDS; + while ((ch = getopt(argc, argv, "df")) != EOF) + switch(ch) { + case 'd': + dflag = 1; + break; + case 'f': + fflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + switch (argc) { + case 2: /* Don't set -df for user. */ + string = *argv++; + file = *argv; + break; + case 1: /* But set -df by default. */ + dflag = fflag = 1; + string = *argv; + break; + default: + usage(); + } + + if ((fd = open(file, O_RDONLY, 0)) < 0 || fstat(fd, &sb) || + (front = mmap(NULL, sb.st_size, PROT_READ, MAP_FILE, fd, + (off_t)0)) == NULL) + err("%s: %s", file, strerror(errno)); + back = front + sb.st_size; + exit(look(string, front, back)); +} + +look(string, front, back) + char *string, *front, *back; +{ + register int ch; + register char *readp, *writep; + + /* Reformat string string to avoid doing it multiple times later. */ + for (readp = writep = string; ch = *readp++;) { + if (fflag) + ch = FOLD(ch); + if (dflag) + ch = DICT(ch); + if (ch != NO_COMPARE) + *(writep++) = ch; + } + *writep = '\0'; + + front = binary_search(string, front, back); + front = linear_search(string, front, back); + + if (front) + print_from(string, front, back); + return (front ? 0 : 1); +} + + +/* + * Binary search for "string" in memory between "front" and "back". + * + * This routine is expected to return a pointer to the start of a line at + * *or before* the first word matching "string". Relaxing the constraint + * this way simplifies the algorithm. + * + * Invariants: + * front points to the beginning of a line at or before the first + * matching string. + * + * back points to the beginning of a line at or after the first + * matching line. + * + * Base of the Invariants. + * front = NULL; + * back = EOF; + * + * Advancing the Invariants: + * + * p = first newline after halfway point from front to back. + * + * If the string at "p" is not greater than the string to match, + * p is the new front. Otherwise it is the new back. + * + * Termination: + * + * The definition of the routine allows it return at any point, + * since front is always at or before the line to print. + * + * In fact, it returns when the chosen "p" equals "back". This + * implies that there exists a string is least half as long as + * (back - front), which in turn implies that a linear search will + * be no more expensive than the cost of simply printing a string or two. + * + * Trying to continue with binary search at this point would be + * more trouble than it's worth. + */ +#define SKIP_PAST_NEWLINE(p, back) \ + while (p < back && *p++ != '\n'); + +char * +binary_search(string, front, back) + register char *string, *front, *back; +{ + register char *p; + + p = front + (back - front) / 2; + SKIP_PAST_NEWLINE(p, back); + + while (p != back) { + if (compare(string, p, back) == GREATER) + front = p; + else + back = p; + p = front + (back - front) / 2; + SKIP_PAST_NEWLINE(p, back); + } + return (front); +} + +/* + * Find the first line that starts with string, linearly searching from front + * to back. + * + * Return NULL for no such line. + * + * This routine assumes: + * + * o front points at the first character in a line. + * o front is before or at the first line to be printed. + */ +char * +linear_search(string, front, back) + char *string, *front, *back; +{ + while (front < back) { + switch (compare(string, front, back)) { + case EQUAL: /* Found it. */ + return (front); + break; + case LESS: /* No such string. */ + return (NULL); + break; + case GREATER: /* Keep going. */ + break; + } + SKIP_PAST_NEWLINE(front, back); + } + return (NULL); +} + +/* + * Print as many lines as match string, starting at front. + */ +void +print_from(string, front, back) + register char *string, *front, *back; +{ + for (; front < back && compare(string, front, back) == EQUAL; ++front) { + for (; front < back && *front != '\n'; ++front) + if (putchar(*front) == EOF) + err("stdout: %s", strerror(errno)); + if (putchar('\n') == EOF) + err("stdout: %s", strerror(errno)); + } +} + +/* + * Return LESS, GREATER, or EQUAL depending on how the string1 compares with + * string2 (s1 ??? s2). + * + * o Matches up to len(s1) are EQUAL. + * o Matches up to len(s2) are GREATER. + * + * Compare understands about the -f and -d flags, and treats comparisons + * appropriately. + * + * The string "s1" is null terminated. The string s2 is '\n' terminated (or + * "back" terminated). + */ +int +compare(s1, s2, back) + register char *s1, *s2, *back; +{ + register int ch; + + for (; *s1 && s2 < back && *s2 != '\n'; ++s1, ++s2) { + ch = *s2; + if (fflag) + ch = FOLD(ch); + if (dflag) + ch = DICT(ch); + + if (ch == NO_COMPARE) { + ++s2; /* Ignore character in comparison. */ + continue; + } + if (*s1 != ch) + return (*s1 < ch ? LESS : GREATER); + } + return (*s1 ? GREATER : EQUAL); +} + +static void +usage() +{ + (void)fprintf(stderr, "usage: look [-df] string [file]\n"); + exit(2); +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "look: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(2); + /* NOTREACHED */ +} diff --git a/usr/src/usr.bin/look/pathnames.h b/usr/src/usr.bin/look/pathnames.h new file mode 100644 index 0000000000..aa27d02910 --- /dev/null +++ b/usr/src/usr.bin/look/pathnames.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.2 (Berkeley) 6/1/90 + */ + +#define _PATH_WORDS "/usr/share/dict/words" diff --git a/usr/src/usr.bin/mt/Makefile b/usr/src/usr.bin/mt/Makefile new file mode 100644 index 0000000000..0bbdddec53 --- /dev/null +++ b/usr/src/usr.bin/mt/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 5.4 (Berkeley) 1/14/91 + +PROG= mt +CFLAGS+=-I/sys + +.include diff --git a/usr/src/usr.bin/mt/mt.1 b/usr/src/usr.bin/mt/mt.1 new file mode 100644 index 0000000000..a933efcffe --- /dev/null +++ b/usr/src/usr.bin/mt/mt.1 @@ -0,0 +1,130 @@ +.\" Copyright (c) 1981, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)mt.1 6.7 (Berkeley) 7/28/91 +.\" +.Dd July 28, 1991 +.Dt MT 1 +.Os BSD 4 +.Sh NAME +.Nm mt +.Nd magnetic tape manipulating program +.Sh SYNOPSIS +.Nm mt +.Op Fl f Ar tapename +.Ar command +.Op Ar count +.Sh DESCRIPTION +.Nm Mt +is used to give commands to a magnetic tape drive. +By default +.Nm mt +performs the requested operation once. Operations +may be performed multiple times by specifying +.Ar count . +Note +that +.Ar tapename +must reference a raw (not block) tape device. +.Pp +The available commands are listed below. Only as many +characters as are required to uniquely identify a command +need be specified. +.Bl -tag -width "eof, weof" +.It Cm eof , weof +Write +.Ar count +end-of-file marks at the current position on the tape. +.It Cm fsf +Forward space +.Ar count +files. +.It Cm fsr +Forward space +.Ar count +records. +.It Cm bsf +Back space +.Ar count +files. +.It Cm bsr +Back space +.Ar count +records. +.It Cm rewind +Rewind the tape +(Count is ignored). +.It Cm offline , rewoffl +Rewind the tape and place the tape unit off-line +(Count is ignored). +.It Cm status +Print status information about the tape unit. +.El +.Pp +If a tape name is not specified, and the environment variable +.Ev TAPE +does not exist; +.Nm mt +uses the device +.Pa /dev/rmt12 . +.Pp +.Nm Mt +returns a 0 exit status when the operation(s) were successful, +1 if the command was unrecognized, and 2 if an operation failed. +.Sh ENVIRONMENT +If the following environment variable exists, it is utilized by +.Nm mt . +.Bl -tag -width Fl +.It Ev TAPE +.Nm Mt +checks the +.Ev TAPE +environment variable if the +argument +.Ar tapename +is not given. +.Sh FILES +.Bl -tag -width /dev/rmt* -compact +.It Pa /dev/rmt* +Raw magnetic tape interface +.El +.Sh SEE ALSO +.\".Xr mtio 4 , +.Xr dd 1 , +.Xr ioctl 2 , +.Xr environ 7 +.Sh HISTORY +The +.Nm mt +command appeared in +.Bx 4.3 . +.\" mt.1: mtio(4) missing diff --git a/usr/src/usr.bin/mt/mt.c b/usr/src/usr.bin/mt/mt.c new file mode 100644 index 0000000000..009ab1e87b --- /dev/null +++ b/usr/src/usr.bin/mt/mt.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mt.c 5.6 (Berkeley) 6/6/91"; +#endif /* not lint */ + +/* + * mt -- + * magnetic tape manipulation program + */ +#include +#include +#include +#include +#include +#include + +#define equal(s1,s2) (strcmp(s1, s2) == 0) + +struct commands { + char *c_name; + int c_code; + int c_ronly; +} com[] = { + { "weof", MTWEOF, 0 }, + { "eof", MTWEOF, 0 }, + { "fsf", MTFSF, 1 }, + { "bsf", MTBSF, 1 }, + { "fsr", MTFSR, 1 }, + { "bsr", MTBSR, 1 }, + { "rewind", MTREW, 1 }, + { "offline", MTOFFL, 1 }, + { "rewoffl", MTOFFL, 1 }, + { "status", MTNOP, 1 }, + { 0 } +}; + +int mtfd; +struct mtop mt_com; +struct mtget mt_status; +char *tape; + +main(argc, argv) + char **argv; +{ + char line[80], *getenv(); + register char *cp; + register struct commands *comp; + + if (argc > 2 && (equal(argv[1], "-t") || equal(argv[1], "-f"))) { + argc -= 2; + tape = argv[2]; + argv += 2; + } else + if ((tape = getenv("TAPE")) == NULL) + tape = DEFTAPE; + if (argc < 2) { + fprintf(stderr, "usage: mt [ -f device ] command [ count ]\n"); + exit(1); + } + cp = argv[1]; + for (comp = com; comp->c_name != NULL; comp++) + if (strncmp(cp, comp->c_name, strlen(cp)) == 0) + break; + if (comp->c_name == NULL) { + fprintf(stderr, "mt: don't grok \"%s\"\n", cp); + exit(1); + } + if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) { + perror(tape); + exit(1); + } + if (comp->c_code != MTNOP) { + mt_com.mt_op = comp->c_code; + mt_com.mt_count = (argc > 2 ? atoi(argv[2]) : 1); + if (mt_com.mt_count < 0) { + fprintf(stderr, "mt: negative repeat count\n"); + exit(1); + } + if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) { + fprintf(stderr, "%s %s %d ", tape, comp->c_name, + mt_com.mt_count); + perror("failed"); + exit(2); + } + } else { + if (ioctl(mtfd, MTIOCGET, (char *)&mt_status) < 0) { + perror("mt"); + exit(2); + } + status(&mt_status); + } +} + +#ifdef vax +#include +#include + +#include +#include +#undef b_repcnt /* argh */ +#include +#endif + +#ifdef sun +#include +#include +#endif + +#ifdef tahoe +#include +#endif + +struct tape_desc { + short t_type; /* type of magtape device */ + char *t_name; /* printing name */ + char *t_dsbits; /* "drive status" register */ + char *t_erbits; /* "error" register */ +} tapes[] = { +#ifdef vax + { MT_ISTS, "ts11", 0, TSXS0_BITS }, + { MT_ISHT, "tm03", HTDS_BITS, HTER_BITS }, + { MT_ISTM, "tm11", 0, TMER_BITS }, + { MT_ISMT, "tu78", MTDS_BITS, 0 }, + { MT_ISUT, "tu45", UTDS_BITS, UTER_BITS }, +#endif +#ifdef sun + { MT_ISCPC, "TapeMaster", TMS_BITS, 0 }, + { MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS }, +#endif +#ifdef tahoe + { MT_ISCY, "cipher", CYS_BITS, CYCW_BITS }, +#endif + { 0 } +}; + +/* + * Interpret the status buffer returned + */ +status(bp) + register struct mtget *bp; +{ + register struct tape_desc *mt; + + for (mt = tapes; mt->t_type; mt++) + if (mt->t_type == bp->mt_type) + break; + if (mt->t_type == 0) { + printf("unknown tape drive type (%d)\n", bp->mt_type); + return; + } + printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid); + printreg("ds", bp->mt_dsreg, mt->t_dsbits); + printreg("\ner", bp->mt_erreg, mt->t_erbits); + putchar('\n'); +} + +/* + * Print a register a la the %b format of the kernel's printf + */ +printreg(s, v, bits) + char *s; + register char *bits; + register unsigned short v; +{ + register int i, any = 0; + register char c; + + if (bits && *bits == 8) + printf("%s=%o", s, v); + else + printf("%s=%x", s, v); + bits++; + if (v && bits) { + putchar('<'); + while (i = *bits++) { + if (v & (1 << (i-1))) { + if (any) + putchar(','); + any = 1; + for (; (c = *bits) > 32; bits++) + putchar(c); + } else + for (; *bits > 32; bits++) + ; + } + putchar('>'); + } +} diff --git a/usr/src/usr.bin/quota/Makefile b/usr/src/usr.bin/quota/Makefile new file mode 100644 index 0000000000..f45caf9636 --- /dev/null +++ b/usr/src/usr.bin/quota/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 5.3 (Berkeley) 5/11/90 + +PROG= quota +BINOWN= root +BINMODE=4555 + +.include diff --git a/usr/src/usr.bin/quota/quota.1 b/usr/src/usr.bin/quota/quota.1 new file mode 100644 index 0000000000..ad7f1c53d3 --- /dev/null +++ b/usr/src/usr.bin/quota/quota.1 @@ -0,0 +1,131 @@ +.\" Copyright (c) 1983, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Robert Elz at The University of Melbourne. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)quota.1 6.8 (Berkeley) 7/27/91 +.\" +.Dd July 27, 1991 +.Dt QUOTA 1 +.Os BSD 4.2 +.Sh NAME +.Nm quota +.Nd display disk usage and limits +.Sh SYNOPSIS +.Nm quota +.Op Fl g +.Op Fl u +.Op Fl v | Fl q +.Nm quota +.Op Fl u +.Op Fl v | Fl q +.Ar user +.Nm quota +.Op Fl g +.Op Fl v | Fl q +.Ar group +.Sh DESCRIPTION +.Nm Quota +displays users' disk usage and limits. +By default only the user quotas are printed. +.Pp +Options: +.Pp +.Bl -tag -width Ds +.It Fl g +Print group quotas for the group +of which the user is a member. +The optional +.Fl u +flag is equivalent to the default. +.It Fl v +.Nm quota +will display quotas on filesystems +where no storage is allocated. +.It Fl q +Print a more terse message, +containing only information +on filesystems where usage is over quota. +.El +.Pp +Specifying both +.Fl g +and +.Fl u +displays both the user quotas and the group quotas (for +the user). +.Pp +Only the super-user may use the +.Fl u +flag and the optional +.Ar user +argument to view the limits of other users. +Non-super-users can use the the +.Fl g +flag and optional +.Ar group +argument to view only the limits of groups of which they are members. +.Pp +The +.Fl q +flag takes precedence over the +.Fl v +flag. +.Pp +.Nm Quota +reports the quotas of all the filesystems listed in +.Pa /etc/fstab . +If +.Nm quota +exits with a non-zero status, one or more filesystems +are over quota. +.Sh FILES +.Bl -tag -width quota.group -compact +.It Pa quota.user +located at the filesystem root with user quotas +.It Pa quota.group +located at the filesystem root with group quotas +.It Pa /etc/fstab +to find filesystem names and locations +.El +.Sh HISTORY +The +.Nm quota +command appeared in +.Bx 4.2 . +.Sh SEE ALSO +.Xr quotactl 2 , +.Xr fstab 5 , +.Xr edquota 8 , +.Xr quotacheck 8 , +.Xr quotaon 8 , +.Xr repquota 8 diff --git a/usr/src/usr.bin/quota/quota.c b/usr/src/usr.bin/quota/quota.c new file mode 100644 index 0000000000..f8587e927a --- /dev/null +++ b/usr/src/usr.bin/quota/quota.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 1980, 1990 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)quota.c 5.12 (Berkeley) 9/27/90"; +#endif /* not lint */ + +/* + * Disk quota reporting program. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *qfname = QUOTAFILENAME; +char *qfextension[] = INITQFNAMES; + +struct quotause { + struct quotause *next; + long flags; + struct dqblk dqblk; + char fsname[MAXPATHLEN + 1]; +} *getprivs(); +#define FOUND 0x01 + +int qflag; +int vflag; + +main(argc, argv) + char *argv[]; +{ + int ngroups, gidset[NGROUPS]; + int i, gflag = 0, uflag = 0; + char ch; + extern char *optarg; + extern int optind, errno; + + if (quotactl("/", 0, 0, (caddr_t)0) < 0 && errno == EOPNOTSUPP) { + fprintf(stderr, "There are no quotas on this system\n"); + exit(0); + } + while ((ch = getopt(argc, argv, "ugvq")) != EOF) { + switch(ch) { + case 'g': + gflag++; + break; + case 'u': + uflag++; + break; + case 'v': + vflag++; + break; + case 'q': + qflag++; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (!uflag && !gflag) + uflag++; + if (argc == 0) { + if (uflag) + showuid(getuid()); + if (gflag) { + ngroups = getgroups(NGROUPS, gidset); + if (ngroups < 0) { + perror("quota: getgroups"); + exit(1); + } + for (i = 1; i < ngroups; i++) + showgid(gidset[i]); + } + exit(0); + } + if (uflag && gflag) + usage(); + if (uflag) { + for (; argc > 0; argc--, argv++) { + if (alldigits(*argv)) + showuid(atoi(*argv)); + else + showusrname(*argv); + } + exit(0); + } + if (gflag) { + for (; argc > 0; argc--, argv++) { + if (alldigits(*argv)) + showgid(atoi(*argv)); + else + showgrpname(*argv); + } + exit(0); + } +} + +usage() +{ + + fprintf(stderr, "%s\n%s\n%s\n", + "Usage: quota [-guqv]", + "\tquota [-qv] -u username ...", + "\tquota [-qv] -g groupname ..."); + exit(1); +} + +/* + * Print out quotas for a specified user identifier. + */ +showuid(uid) + u_long uid; +{ + struct passwd *pwd = getpwuid(uid); + u_long myuid; + char *name; + + if (pwd == NULL) + name = "(no account)"; + else + name = pwd->pw_name; + myuid = getuid(); + if (uid != myuid && myuid != 0) { + printf("quota: %s (uid %d): permission denied\n", name, uid); + return; + } + showquotas(USRQUOTA, uid, name); +} + +/* + * Print out quotas for a specifed user name. + */ +showusrname(name) + char *name; +{ + struct passwd *pwd = getpwnam(name); + u_long myuid; + + if (pwd == NULL) { + fprintf(stderr, "quota: %s: unknown user\n", name); + return; + } + myuid = getuid(); + if (pwd->pw_uid != myuid && myuid != 0) { + fprintf(stderr, "quota: %s (uid %d): permission denied\n", + name, pwd->pw_uid); + return; + } + showquotas(USRQUOTA, pwd->pw_uid, name); +} + +/* + * Print out quotas for a specified group identifier. + */ +showgid(gid) + u_long gid; +{ + struct group *grp = getgrgid(gid); + int ngroups, gidset[NGROUPS]; + register int i; + char *name; + + if (grp == NULL) + name = "(no entry)"; + else + name = grp->gr_name; + ngroups = getgroups(NGROUPS, gidset); + if (ngroups < 0) { + perror("quota: getgroups"); + return; + } + for (i = 1; i < ngroups; i++) + if (gid == gidset[i]) + break; + if (i >= ngroups && getuid() != 0) { + fprintf(stderr, "quota: %s (gid %d): permission denied\n", + name, gid); + return; + } + showquotas(GRPQUOTA, gid, name); +} + +/* + * Print out quotas for a specifed group name. + */ +showgrpname(name) + char *name; +{ + struct group *grp = getgrnam(name); + int ngroups, gidset[NGROUPS]; + register int i; + + if (grp == NULL) { + fprintf(stderr, "quota: %s: unknown group\n", name); + return; + } + ngroups = getgroups(NGROUPS, gidset); + if (ngroups < 0) { + perror("quota: getgroups"); + return; + } + for (i = 1; i < ngroups; i++) + if (grp->gr_gid == gidset[i]) + break; + if (i >= ngroups && getuid() != 0) { + fprintf(stderr, "quota: %s (gid %d): permission denied\n", + name, grp->gr_gid); + return; + } + showquotas(GRPQUOTA, grp->gr_gid, name); +} + +showquotas(type, id, name) + int type; + u_long id; + char *name; +{ + register struct quotause *qup; + struct quotause *quplist, *getprivs(); + char *msgi, *msgb, *timeprt(); + int myuid, fd, lines = 0; + static int first; + static time_t now; + + if (now == 0) + time(&now); + quplist = getprivs(id, type); + for (qup = quplist; qup; qup = qup->next) { + if (!vflag && + qup->dqblk.dqb_isoftlimit == 0 && + qup->dqblk.dqb_ihardlimit == 0 && + qup->dqblk.dqb_bsoftlimit == 0 && + qup->dqblk.dqb_bhardlimit == 0) + continue; + msgi = (char *)0; + if (qup->dqblk.dqb_ihardlimit && + qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit) + msgi = "File limit reached on"; + else if (qup->dqblk.dqb_isoftlimit && + qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit) + if (qup->dqblk.dqb_itime > now) + msgi = "In file grace period on"; + else + msgi = "Over file quota on"; + msgb = (char *)0; + if (qup->dqblk.dqb_bhardlimit && + qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit) + msgb = "Block limit reached on"; + else if (qup->dqblk.dqb_bsoftlimit && + qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit) + if (qup->dqblk.dqb_btime > now) + msgb = "In block grace period on"; + else + msgb = "Over block quota on"; + if (qflag) { + if ((msgi != (char *)0 || msgb != (char *)0) && + lines++ == 0) + heading(type, id, name, ""); + if (msgi != (char *)0) + printf("\t%s %s\n", msgi, qup->fsname); + if (msgb != (char *)0) + printf("\t%s %s\n", msgb, qup->fsname); + continue; + } + if (vflag || + qup->dqblk.dqb_curblocks || + qup->dqblk.dqb_curinodes) { + if (lines++ == 0) + heading(type, id, name, ""); + printf("%15s%8d%c%7d%8d%8s" + , qup->fsname + , dbtob(qup->dqblk.dqb_curblocks) / 1024 + , (msgb == (char *)0) ? ' ' : '*' + , dbtob(qup->dqblk.dqb_bsoftlimit) / 1024 + , dbtob(qup->dqblk.dqb_bhardlimit) / 1024 + , (msgb == (char *)0) ? "" + : timeprt(qup->dqblk.dqb_btime)); + printf("%8d%c%7d%8d%8s\n" + , qup->dqblk.dqb_curinodes + , (msgi == (char *)0) ? ' ' : '*' + , qup->dqblk.dqb_isoftlimit + , qup->dqblk.dqb_ihardlimit + , (msgi == (char *)0) ? "" + : timeprt(qup->dqblk.dqb_itime) + ); + continue; + } + } + if (!qflag && lines == 0) + heading(type, id, name, "none"); +} + +heading(type, id, name, tag) + int type; + u_long id; + char *name, *tag; +{ + + printf("Disk quotas for %s %s (%cid %d): %s\n", qfextension[type], + name, *qfextension[type], id, tag); + if (!qflag && tag[0] == '\0') { + printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n" + , "Filesystem" + , "blocks" + , "quota" + , "limit" + , "grace" + , "files" + , "quota" + , "limit" + , "grace" + ); + } +} + +/* + * Calculate the grace period and return a printable string for it. + */ +char * +timeprt(seconds) + time_t seconds; +{ + time_t hours, minutes; + static char buf[20]; + static time_t now; + + if (now == 0) + time(&now); + if (now > seconds) + return ("none"); + seconds -= now; + minutes = (seconds + 30) / 60; + hours = (minutes + 30) / 60; + if (hours >= 36) { + sprintf(buf, "%ddays", (hours + 12) / 24); + return (buf); + } + if (minutes >= 60) { + sprintf(buf, "%2d:%d", minutes / 60, minutes % 60); + return (buf); + } + sprintf(buf, "%2d", minutes); + return (buf); +} + +/* + * Collect the requested quota information. + */ +struct quotause * +getprivs(id, quotatype) + register long id; + int quotatype; +{ + register struct fstab *fs; + register struct quotause *qup, *quptail; + struct quotause *quphead; + char *qfpathname; + int qcmd, fd; + + setfsent(); + quphead = (struct quotause *)0; + qcmd = QCMD(Q_GETQUOTA, quotatype); + while (fs = getfsent()) { + if (strcmp(fs->fs_vfstype, "ufs")) + continue; + if (!hasquota(fs, quotatype, &qfpathname)) + continue; + if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) { + fprintf(stderr, "quota: out of memory\n"); + exit(2); + } + if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { + if ((fd = open(qfpathname, O_RDONLY)) < 0) { + perror(qfpathname); + free(qup); + continue; + } + lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET); + switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { + case 0: /* EOF */ + /* + * Convert implicit 0 quota (EOF) + * into an explicit one (zero'ed dqblk) + */ + bzero((caddr_t)&qup->dqblk, + sizeof(struct dqblk)); + break; + + case sizeof(struct dqblk): /* OK */ + break; + + default: /* ERROR */ + fprintf(stderr, "quota: read error"); + perror(qfpathname); + close(fd); + free(qup); + continue; + } + close(fd); + } + strcpy(qup->fsname, fs->fs_file); + if (quphead == NULL) + quphead = qup; + else + quptail->next = qup; + quptail = qup; + qup->next = 0; + } + endfsent(); + return (quphead); +} + +/* + * Check to see if a particular quota is to be enabled. + */ +hasquota(fs, type, qfnamep) + register struct fstab *fs; + int type; + char **qfnamep; +{ + register char *opt; + char *cp, *index(), *strtok(); + static char initname, usrname[100], grpname[100]; + static char buf[BUFSIZ]; + + if (!initname) { + sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); + sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); + initname = 1; + } + strcpy(buf, fs->fs_mntops); + for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { + if (cp = index(opt, '=')) + *cp++ = '\0'; + if (type == USRQUOTA && strcmp(opt, usrname) == 0) + break; + if (type == GRPQUOTA && strcmp(opt, grpname) == 0) + break; + } + if (!opt) + return (0); + if (cp) { + *qfnamep = cp; + return (1); + } + (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); + *qfnamep = buf; + return (1); +} + +alldigits(s) + register char *s; +{ + register c; + + c = *s++; + do { + if (!isdigit(c)) + return (0); + } while (c = *s++); + return (1); +} diff --git a/usr/src/usr.bin/sccs/Makefile b/usr/src/usr.bin/sccs/Makefile new file mode 100644 index 0000000000..be42d485d1 --- /dev/null +++ b/usr/src/usr.bin/sccs/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 5.3 (Berkeley) 5/11/90 + +PROG= sccs + +.include diff --git a/usr/src/usr.bin/sccs/pathnames.h b/usr/src/usr.bin/sccs/pathnames.h new file mode 100644 index 0000000000..5510033619 --- /dev/null +++ b/usr/src/usr.bin/sccs/pathnames.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.6 (Berkeley) 3/4/91 + */ + +#include + +#define _PATH_SCCSADMIN "/usr/local/bin/admin" +#define _PATH_SCCSBDIFF "/usr/local/bin/bdiff" +#define _PATH_SCCSCOMB "/usr/local/bin/comb" +#define _PATH_SCCSDELTA "/usr/local/bin/delta" +#define _PATH_SCCSDIFF "/usr/local/bin/sccsdiff" +#define _PATH_SCCSGET "/usr/local/bin/get" +#define _PATH_SCCSHELP "/usr/local/bin/help" +#define _PATH_SCCSPRS "/usr/local/bin/prs" +#define _PATH_SCCSPRT "/usr/local/bin/prt" +#define _PATH_SCCSRMDEL "/usr/local/bin/rmdel" +#define _PATH_SCCSVAL "/usr/local/bin/val" +#define _PATH_SCCSWHAT "/usr/local/bin/what" +#undef _PATH_TMP +#define _PATH_TMP "/tmp/sccsXXXXX" diff --git a/usr/src/usr.bin/sccs/sccs.1 b/usr/src/usr.bin/sccs/sccs.1 new file mode 100644 index 0000000000..d38f3ce2df --- /dev/null +++ b/usr/src/usr.bin/sccs/sccs.1 @@ -0,0 +1,398 @@ +.\" Copyright (c) 1983, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)sccs.1 2.10 (Berkeley) 7/24/91 +.\" +.Dd July 24, 1991 +.Dt SCCS 1 +.Os BSD 4.2 +.Sh NAME +.Nm sccs +.Nd front end for the +.Li SCCS +subsystem +.Sh SYNOPSIS +.Nm sccs +.Op Fl r +.Op Fl d Ar path +.Op Fl p Ar path +.Ar command +.Op flags +.Op Ar +.Sh DESCRIPTION +.Nm Sccs +is a front end to the +.Li SCCS +programs +that +helps them mesh more cleanly +with +the rest of UNIX. +It +also includes the capability to run +.Dq set user id +to another user +to +provide additional protection. +.Pp +Basically, +.Nm sccs +runs the command with the specified +.Ar flags +and +.Ar args . +Each argument is normally modified to be prepended with +.Dq Li SCCS/s. . +.Pp +Flags to be interpreted by the +.Nm sccs +program must be before the +.Ar command +argument. +Flags to be passed to the actual +.Li SCCS +program must come after the +.Ar command +argument. +These flags are specific to the command and +are discussed in the documentation for that command. +.Pp +Besides the usual +.Li SCCS +commands, +several +.Dq pseudo-commands +can be issued. +These are: +.Bl -tag -width deledit +.It Cm edit +Equivalent +to +.Dq Li get \-e . +.It Cm delget +Perform a delta on the named files and +then get new versions. +The new versions will have id keywords expanded, and +will not be editable. +The +.Fl m , +.Fl p , +.Fl r , +.Fl s , +and +.Fl y +flags will be passed to +.Nm delta , +and the +.Fl b, +.Fl c , +.Fl e , +.Fl i , +.Fl k , +.Fl l , +.Fl s , +.\" anybody who has a bad xterm which is almost anyone +and +.Fl x +flags will be passed to get. +.It Cm deledit +Equivalent +to +.Nm delget +except that the +.Nm get +phase includes the +.Fl e +flag. +This +option is useful for making a +.Em checkpoint +of your current editing phase. The same flags will be passed to delta +as described above, and +all the flags listed for +.om get +above except +.Fl e +and +.Fl k +are +passed to +.Nm edit . +.It Cm create +Creates +an +.Li SCCS +file , +taking +the initial contents from the file of the same name. +Any +flags to +.Nm admin +are accepted. If the creation is successful, +the files are renamed with a comma on the front. +These should be removed when you are convinced that the +.Li SCCS +files +have been created successfully. +.It Cm fix +Must +be followed by a +.Fl r +flag. +This command essentially removes the named delta, but +leaves you with a copy of the delta +with the changes that were in it. It +is useful for fixing small compiler bugs, etc. +Since it doesn't leave audit trails, it should be used carefully. +.It Cm clean +This routine removes everything from the current directory +that can be recreated from SCCS files. +It will not remove any files being edited. +If the +.Fl b +flag is given, branches are ignored in the determination of +whether they are being edited; this +is dangerous if you are keeping the branches in the +same directory. +.It Cm unedit +This +is the opposite of an +.Nm edit +or +a +.Dq Li get \-e . +It should be used with extreme caution, since +any changes you made since the get will be irretrievably lost. +.It Cm info +Gives a listing of all files being edited. +If the +.Fl b +flag +is given, branches (i.e., +.Li SID Ns \&\'s +with two or fewer components) +are ignored. If the +.Fl u +flag is given (with an optional argument) then +only files being edited by you (or the named user) are listed. +.It Cm check +Like +.Nm info +except that nothing is printed if nothing is being edited, and +a non-zero exit status is returned if anything is being edited. +The intent is to have this included in an +.Em install +entry in a makefile to insure that everything is included into the +.Li SCCS +file before a version is installed. +.It Cm tell +Gives a newline-separated list of the files being edited +on the standard output. Takes the +.Fl b +and +.Fl u +flags like +.Nm info +and +.Nm check . +.It Cm diffs +Gives a +.Nm diff +listing between the current version of the +program(s) you have out for editing and the versions in +.Li SCCS +format. +The +.Fl r , +.Fl c , +.Fl i , +.Fl x , +and +.Fl t +flags are passed to +.if n \{\ +. br +.\} +.Nm get ; +the +.Fl l , +.Fl s , +.Fl e , +.Fl f , +.Fl h , +and +.Fl b +options are passed to +.if n \{\ +. br +.\} +.Nm diff . +The +.Fl C +flag is passed to +.Nm diff +as +.Fl c . +.It Cm print +This command prints out verbose information +about the named files. +.Pp +.It Fl r +Runs +.Nm sccs +as the real user rather than as whatever effective user +.Nm sccs +is +.Dq Li set user id +to. +.It Fl d +Specifies a root directory for the +.Li SCCS +files. +The default is the current directory. +If environment variable +.Ev PROJECT +is set, +it will be used to determine the +.Fl d +flag. +.It Fl p +Defines the pathname of the directory in which the +.Li SCCS +files will be found; +.Dq Li SCCS +is the default. +The +.Fl p +flag +differs from the +.Fl d +flag +in that the +.Fl d +argument is prepended to the entire pathname and the +.Fl p +argument is inserted before the final component of the pathname. +For example, +.Dq Li sccs \-d/x \-py get a/b +will convert to +.Dq Li get /x/a/y/s.b . +The intent here is to create aliases such as +.Dq Li alias syssccs sccs -d/usr/src +which +will be used as +.Dq Li syssccs get cmd/who.c . +.Pp +Certain +commands (such as +.Nm admin ) +cannot be run +.Dq Li set user id +by all users, since this would allow anyone to change the authorizations. +These commands are always run as the real user. +.Sh EXAMPLES +To get a file for editing, +edit it, +and produce a new delta: +.Pp +.Dl sccs get \-e file.c +.Dl ex file.c +.Dl sccs delta file.c +.Pp +To get a file from another directory: +.Pp +.Dl sccs \-p/usr/src/sccs/s. get cc.c +.Pp +or +.Pp +.Dl sccs get /usr/src/sccs/s.cc.c +.Pp +To make a delta of a large number of files +in the current directory: +.Pp +.Dl sccs delta *.c +.Pp +To get a list of files being edited that are not on branches: +.Pp +.Dl sccs info \-b +.Pp +To delta everything being edited by you: +.Pp +.Dl sccs delta \`sccs tell \-u\` +.Pp +In a makefile, to get source files +from an +.Li SCCS +file if it does not already exist: +.Pp +.Dl SRCS = +.Dl $(SRCS): +.Dl \&\tsccs get $(REL) $@ +.Sh ENVIRONMENT +.Bl -tag -width Ar +.It Ev PROJECT +The PROJECT environment variable is checked by the +.Fl d +flag. If +it begins with a slash, it is taken directly; otherwise, +the home directory of a user of that name is +examined for a subdirectory +.Dq Li src +or +.Dq Li source . +If such a directory is found, it is used. +.El +.Sh SEE ALSO +.Xr what 1 +.Xr admin SCCS , +.Xr chghist SCCS , +.Xr comb SCCS , +.Xr delta SCCS , +.Xr get SCCS , +.Xr help SCCS , +.Xr prt SCCS , +.Xr rmdel SCCS , +.Xr sccsdiff SCCS , +.Rs +.%A Eric Allman +.%T "An Introduction to the Source Code Control System" +.Re +.Sh HISTORY +The +.Nm sccs +command +appeared in +.Bx 4.3 . +.Sh BUGS +It should be able to take directory arguments on pseudo-commands +like the +.Li SCCS +commands do. diff --git a/usr/src/usr.bin/sccs/sccs.c b/usr/src/usr.bin/sccs/sccs.c new file mode 100644 index 0000000000..d244092c04 --- /dev/null +++ b/usr/src/usr.bin/sccs/sccs.c @@ -0,0 +1,1623 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)sccs.c 5.11 (Berkeley) 3/4/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +/* +** SCCS.C -- human-oriented front end to the SCCS system. +** +** Without trying to add any functionality to speak of, this +** program tries to make SCCS a little more accessible to human +** types. The main thing it does is automatically put the +** string "SCCS/s." on the front of names. Also, it has a +** couple of things that are designed to shorten frequent +** combinations, e.g., "delget" which expands to a "delta" +** and a "get". +** +** This program can also function as a setuid front end. +** To do this, you should copy the source, renaming it to +** whatever you want, e.g., "syssccs". Change any defaults +** in the program (e.g., syssccs might default -d to +** "/usr/src/sys"). Then recompile and put the result +** as setuid to whomever you want. In this mode, sccs +** knows to not run setuid for certain programs in order +** to preserve security, and so forth. +** +** Usage: +** sccs [flags] command [args] +** +** Flags: +** -d represents a directory to search +** out of. It should be a full pathname +** for general usage. E.g., if is +** "/usr/src/sys", then a reference to the +** file "dev/bio.c" becomes a reference to +** "/usr/src/sys/dev/bio.c". +** -p prepends to the final component +** of the pathname. By default, this is +** "SCCS". For example, in the -d example +** above, the path then gets modified to +** "/usr/src/sys/dev/SCCS/s.bio.c". In +** more common usage (without the -d flag), +** "prog.c" would get modified to +** "SCCS/s.prog.c". In both cases, the +** "s." gets automatically prepended. +** -r run as the real user. +** +** Commands: +** admin, +** get, +** delta, +** rmdel, +** cdc, +** etc. Straight out of SCCS; only difference +** is that pathnames get modified as +** described above. +** enter Front end doing "sccs admin -i " +** create Macro for "enter" followed by "get". +** edit Macro for "get -e". +** unedit Removes a file being edited, knowing +** about p-files, etc. +** delget Macro for "delta" followed by "get". +** deledit Macro for "delta" followed by "get -e". +** branch Macro for "get -b -e", followed by "delta +** -s -n", followd by "get -e -t -g". +** diffs "diff" the specified version of files +** and the checked-out version. +** print Macro for "prs -e" followed by "get -p -m". +** tell List what files are being edited. +** info Print information about files being edited. +** clean Remove all files that can be +** regenerated from SCCS files. +** check Like info, but return exit status, for +** use in makefiles. +** fix Remove a top delta & reedit, but save +** the previous changes in that delta. +** +** Compilation Flags: +** UIDUSER -- determine who the user is by looking at the +** uid rather than the login name -- for machines +** where SCCS gets the user in this way. +** SCCSDIR -- if defined, forces the -d flag to take on +** this value. This is so that the setuid +** aspects of this program cannot be abused. +** This flag also disables the -p flag. +** SCCSPATH -- the default for the -p flag. +** MYNAME -- the title this program should print when it +** gives error messages. +** +** Compilation Instructions: +** cc -O -n -s sccs.c +** The flags listed above can be -D defined to simplify +** recompilation for variant versions. +** +** Author: +** Eric Allman, UCB/INGRES +** Copyright 1980 Regents of the University of California +*/ + + +/******************* Configuration Information ********************/ + +# ifndef SCCSPATH +# define SCCSPATH "SCCS" /* pathname in which to find s-files */ +# endif NOT SCCSPATH + +# ifndef MYNAME +# define MYNAME "sccs" /* name used for printing errors */ +# endif NOT MYNAME + +/**************** End of Configuration Information ****************/ + +typedef char bool; +# define TRUE 1 +# define FALSE 0 + +# define bitset(bit, word) ((bool) ((bit) & (word))) + +struct sccsprog +{ + char *sccsname; /* name of SCCS routine */ + short sccsoper; /* opcode, see below */ + short sccsflags; /* flags, see below */ + char *sccspath; /* pathname of binary implementing */ +}; + +/* values for sccsoper */ +# define PROG 0 /* call a program */ +# define CMACRO 1 /* command substitution macro */ +# define FIX 2 /* fix a delta */ +# define CLEAN 3 /* clean out recreatable files */ +# define UNEDIT 4 /* unedit a file */ +# define SHELL 5 /* call a shell file (like PROG) */ +# define DIFFS 6 /* diff between sccs & file out */ +# define DODIFF 7 /* internal call to diff program */ +# define ENTER 8 /* enter new files */ + +/* bits for sccsflags */ +# define NO_SDOT 0001 /* no s. on front of args */ +# define REALUSER 0002 /* protected (e.g., admin) */ + +/* modes for the "clean", "info", "check" ops */ +# define CLEANC 0 /* clean command */ +# define INFOC 1 /* info command */ +# define CHECKC 2 /* check command */ +# define TELLC 3 /* give list of files being edited */ + +/* +** Description of commands known to this program. +** First argument puts the command into a class. Second arg is +** info regarding treatment of this command. Third arg is a +** list of flags this command accepts from macros, etc. Fourth +** arg is the pathname of the implementing program, or the +** macro definition, or the arg to a sub-algorithm. +*/ + +struct sccsprog SccsProg[] = { + "admin", PROG, REALUSER, _PATH_SCCSADMIN, + "cdc", PROG, 0, _PATH_SCCSRMDEL, + "comb", PROG, 0, _PATH_SCCSCOMB, + "delta", PROG, 0, _PATH_SCCSDELTA, + "get", PROG, 0, _PATH_SCCSGET, + "help", PROG, NO_SDOT, _PATH_SCCSHELP, + "prs", PROG, 0, _PATH_SCCSPRS, + "prt", PROG, 0, _PATH_SCCSPRT, + "rmdel", PROG, REALUSER, _PATH_SCCSRMDEL, + "val", PROG, 0, _PATH_SCCSVAL, + "what", PROG, NO_SDOT, _PATH_SCCSWHAT, + "sccsdiff", SHELL, REALUSER, _PATH_SCCSDIFF, + "edit", CMACRO, NO_SDOT, "get -e", + "delget", CMACRO, NO_SDOT, "delta:mysrp/get:ixbeskcl -t", + "deledit", CMACRO, NO_SDOT, + "delta:mysrp -n/get:ixbskcl -e -t -g", + "fix", FIX, NO_SDOT, NULL, + "clean", CLEAN, REALUSER|NO_SDOT, + (char *) CLEANC, + "info", CLEAN, REALUSER|NO_SDOT, + (char *) INFOC, + "check", CLEAN, REALUSER|NO_SDOT, + (char *) CHECKC, + "tell", CLEAN, REALUSER|NO_SDOT, + (char *) TELLC, + "unedit", UNEDIT, NO_SDOT, NULL, + "diffs", DIFFS, NO_SDOT|REALUSER, + NULL, + "-diff", DODIFF, NO_SDOT|REALUSER, + _PATH_SCCSBDIFF, + "print", CMACRO, 0, "prs -e/get -p -m -s", + "branch", CMACRO, NO_SDOT, + "get:ixrc -e -b/delta: -s -n -ybranch-place-holder/get:pl -e -t -g", + "enter", ENTER, NO_SDOT, NULL, + "create", CMACRO, NO_SDOT, "enter/get:ixbeskcl -t", + NULL, -1, 0, NULL +}; + +/* one line from a p-file */ +struct pfile +{ + char *p_osid; /* old SID */ + char *p_nsid; /* new SID */ + char *p_user; /* user who did edit */ + char *p_date; /* date of get */ + char *p_time; /* time of get */ + char *p_aux; /* extra info at end */ +}; + +char *SccsPath = SCCSPATH; /* pathname of SCCS files */ +# ifdef SCCSDIR +char *SccsDir = SCCSDIR; /* directory to begin search from */ +# else +char *SccsDir = ""; +# endif +char MyName[] = MYNAME; /* name used in messages */ +int OutFile = -1; /* override output file for commands */ +bool RealUser; /* if set, running as real user */ +# ifdef DEBUG +bool Debug; /* turn on tracing */ +# endif +# ifndef V6 +extern char *getenv(); +# endif V6 + +extern char *sys_siglist[]; + +char *gstrcat(), *strcat(); +char *gstrncat(), *strncat(); +char *gstrcpy(), *strcpy(); +#define FBUFSIZ BUFSIZ +#define PFILELG 120 + +main(argc, argv) + int argc; + char **argv; +{ + register char *p; + extern struct sccsprog *lookup(); + register int i; +# ifndef V6 +# ifndef SCCSDIR + register struct passwd *pw; + extern struct passwd *getpwnam(); + char buf[FBUFSIZ]; + + /* pull "SccsDir" out of the environment (possibly) */ + p = getenv("PROJECTDIR"); + if (p != NULL && p[0] != '\0') + { + if (p[0] == '/') + SccsDir = p; + else + { + pw = getpwnam(p); + if (pw == NULL) + { + usrerr("user %s does not exist", p); + exit(EX_USAGE); + } + gstrcpy(buf, pw->pw_dir, sizeof(buf)); + gstrcat(buf, "/src", sizeof(buf)); + if (access(buf, 0) < 0) + { + gstrcpy(buf, pw->pw_dir, sizeof(buf)); + gstrcat(buf, "/source", sizeof(buf)); + if (access(buf, 0) < 0) + { + usrerr("project %s has no source!", p); + exit(EX_USAGE); + } + } + SccsDir = buf; + } + } +# endif SCCSDIR +# endif V6 + + /* + ** Detect and decode flags intended for this program. + */ + + if (argc < 2) + { + fprintf(stderr, "Usage: %s [flags] command [flags]\n", MyName); + exit(EX_USAGE); + } + argv[argc] = NULL; + + if (lookup(argv[0]) == NULL) + { + while ((p = *++argv) != NULL) + { + if (*p != '-') + break; + switch (*++p) + { + case 'r': /* run as real user */ + setuid(getuid()); + RealUser++; + break; + +# ifndef SCCSDIR + case 'p': /* path of sccs files */ + SccsPath = ++p; + if (SccsPath[0] == '\0' && argv[1] != NULL) + SccsPath = *++argv; + break; + + case 'd': /* directory to search from */ + SccsDir = ++p; + if (SccsDir[0] == '\0' && argv[1] != NULL) + SccsDir = *++argv; + break; +# endif + +# ifdef DEBUG + case 'T': /* trace */ + Debug++; + break; +# endif + + default: + usrerr("unknown option -%s", p); + break; + } + } + if (SccsPath[0] == '\0') + SccsPath = "."; + } + + i = command(argv, FALSE, ""); + exit(i); +} + +/* +** COMMAND -- look up and perform a command +** +** This routine is the guts of this program. Given an +** argument vector, it looks up the "command" (argv[0]) +** in the configuration table and does the necessary stuff. +** +** Parameters: +** argv -- an argument vector to process. +** forkflag -- if set, fork before executing the command. +** editflag -- if set, only include flags listed in the +** sccsklets field of the command descriptor. +** arg0 -- a space-seperated list of arguments to insert +** before argv. +** +** Returns: +** zero -- command executed ok. +** else -- error status. +** +** Side Effects: +** none. +*/ + +command(argv, forkflag, arg0) + char **argv; + bool forkflag; + char *arg0; +{ + register struct sccsprog *cmd; + register char *p; + char buf[FBUFSIZ]; + extern struct sccsprog *lookup(); + char *nav[1000]; + char **np; + register char **ap; + register int i; + register char *q; + extern bool unedit(); + int rval = 0; + extern char *index(); + extern char *makefile(); + char *editchs; + extern char *tail(); + +# ifdef DEBUG + if (Debug) + { + printf("command:\n\t\"%s\"\n", arg0); + for (np = argv; *np != NULL; np++) + printf("\t\"%s\"\n", *np); + } +# endif + + /* + ** Copy arguments. + ** Copy from arg0 & if necessary at most one arg + ** from argv[0]. + */ + + np = ap = &nav[1]; + editchs = NULL; + for (p = arg0, q = buf; *p != '\0' && *p != '/'; ) + { + *np++ = q; + while (*p == ' ') + p++; + while (*p != ' ' && *p != '\0' && *p != '/' && *p != ':') + *q++ = *p++; + *q++ = '\0'; + if (*p == ':') + { + editchs = q; + while (*++p != '\0' && *p != '/' && *p != ' ') + *q++ = *p; + *q++ = '\0'; + } + } + *np = NULL; + if (*ap == NULL) + *np++ = *argv++; + + /* + ** Look up command. + ** At this point, *ap is the command name. + */ + + cmd = lookup(*ap); + if (cmd == NULL) + { + usrerr("Unknown command \"%s\"", *ap); + return (EX_USAGE); + } + + /* + ** Copy remaining arguments doing editing as appropriate. + */ + + for (; *argv != NULL; argv++) + { + p = *argv; + if (*p == '-') + { + if (p[1] == '\0' || editchs == NULL || index(editchs, p[1]) != NULL) + *np++ = p; + } + else + { + if (!bitset(NO_SDOT, cmd->sccsflags)) + p = makefile(p); + if (p != NULL) + *np++ = p; + } + } + *np = NULL; + + /* + ** Interpret operation associated with this command. + */ + + switch (cmd->sccsoper) + { + case SHELL: /* call a shell file */ + *ap = cmd->sccspath; + *--ap = "sh"; + rval = callprog(_PATH_BSHELL, cmd->sccsflags, ap, forkflag); + break; + + case PROG: /* call an sccs prog */ + rval = callprog(cmd->sccspath, cmd->sccsflags, ap, forkflag); + break; + + case CMACRO: /* command macro */ + /* step through & execute each part of the macro */ + for (p = cmd->sccspath; *p != '\0'; p++) + { + q = p; + while (*p != '\0' && *p != '/') + p++; + rval = command(&ap[1], *p != '\0', q); + if (rval != 0) + break; + } + break; + + case FIX: /* fix a delta */ + if (ap[1]==0 || strncmp(ap[1], "-r", 2)!=0) + { + usrerr("-r flag needed for fix command"); + rval = EX_USAGE; + break; + } + + /* get the version with all changes */ + rval = command(&ap[1], TRUE, "get -k"); + + /* now remove that version from the s-file */ + if (rval == 0) + rval = command(&ap[1], TRUE, "rmdel:r"); + + /* and edit the old version (but don't clobber new vers) */ + if (rval == 0) + rval = command(&ap[2], FALSE, "get -e -g"); + break; + + case CLEAN: + rval = clean((int) cmd->sccspath, ap); + break; + + case UNEDIT: + for (argv = np = &ap[1]; *argv != NULL; argv++) + { + if (unedit(*argv)) + *np++ = *argv; + } + *np = NULL; + + /* get all the files that we unedited successfully */ + if (np > &ap[1]) + rval = command(&ap[1], FALSE, "get"); + break; + + case DIFFS: /* diff between s-file & edit file */ + /* find the end of the flag arguments */ + for (np = &ap[1]; *np != NULL && **np == '-'; np++) + continue; + argv = np; + + /* for each file, do the diff */ + p = argv[1]; + while (*np != NULL) + { + /* messy, but we need a null terminated argv */ + *argv = *np++; + argv[1] = NULL; + i = dodiff(ap, tail(*argv)); + if (rval == 0) + rval = i; + argv[1] = p; + } + break; + + case DODIFF: /* internal diff call */ + setuid(getuid()); + for (np = ap; *np != NULL; np++) + { + if ((*np)[0] == '-' && (*np)[1] == 'C') + (*np)[1] = 'c'; + } + + /* insert "-" argument */ + np[1] = NULL; + np[0] = np[-1]; + np[-1] = "-"; + + /* execute the diff program of choice */ +# ifndef V6 + execvp("diff", ap); +# endif + execv(cmd->sccspath, argv); + syserr("cannot exec %s", cmd->sccspath); + exit(EX_OSERR); + + case ENTER: /* enter new sccs files */ + /* skip over flag arguments */ + for (np = &ap[1]; *np != NULL && **np == '-'; np++) + continue; + argv = np; + + /* do an admin for each file */ + p = argv[1]; + while (*np != NULL) + { + printf("\n%s:\n", *np); + strcpy(buf, "-i"); + gstrcat(buf, *np, sizeof(buf)); + ap[0] = buf; + argv[0] = tail(*np); + argv[1] = NULL; + rval = command(ap, TRUE, "admin"); + argv[1] = p; + if (rval == 0) + { + strcpy(buf, ","); + gstrcat(buf, tail(*np), sizeof(buf)); + if (link(*np, buf) >= 0) + unlink(*np); + } + np++; + } + break; + + default: + syserr("oper %d", cmd->sccsoper); + exit(EX_SOFTWARE); + } +# ifdef DEBUG + if (Debug) + printf("command: rval=%d\n", rval); +# endif + return (rval); +} + +/* +** LOOKUP -- look up an SCCS command name. +** +** Parameters: +** name -- the name of the command to look up. +** +** Returns: +** ptr to command descriptor for this command. +** NULL if no such entry. +** +** Side Effects: +** none. +*/ + +struct sccsprog * +lookup(name) + char *name; +{ + register struct sccsprog *cmd; + + for (cmd = SccsProg; cmd->sccsname != NULL; cmd++) + { + if (strcmp(cmd->sccsname, name) == 0) + return (cmd); + } + return (NULL); +} + +/* +** CALLPROG -- call a program +** +** Used to call the SCCS programs. +** +** Parameters: +** progpath -- pathname of the program to call. +** flags -- status flags from the command descriptors. +** argv -- an argument vector to pass to the program. +** forkflag -- if true, fork before calling, else just +** exec. +** +** Returns: +** The exit status of the program. +** Nothing if forkflag == FALSE. +** +** Side Effects: +** Can exit if forkflag == FALSE. +*/ + +callprog(progpath, flags, argv, forkflag) + char *progpath; + short flags; + char **argv; + bool forkflag; +{ + register int i; + register int wpid; + auto int st; + register int sigcode; + register int coredumped; + register char *sigmsg; + auto char sigmsgbuf[10+1]; /* "Signal 127" + terminating '\0' */ + +# ifdef DEBUG + if (Debug) + { + printf("callprog:\n"); + for (i = 0; argv[i] != NULL; i++) + printf("\t\"%s\"\n", argv[i]); + } +# endif + + if (*argv == NULL) + return (-1); + + /* + ** Fork if appropriate. + */ + + if (forkflag) + { +# ifdef DEBUG + if (Debug) + printf("Forking\n"); +# endif + i = fork(); + if (i < 0) + { + syserr("cannot fork"); + exit(EX_OSERR); + } + else if (i > 0) + { + while ((wpid = wait(&st)) != -1 && wpid != i) + ; + if ((sigcode = st & 0377) == 0) + st = (st >> 8) & 0377; + else + { + coredumped = sigcode & 0200; + sigcode &= 0177; + if (sigcode != SIGINT && sigcode != SIGPIPE) + { + if (sigcode < NSIG) + sigmsg = sys_siglist[sigcode]; + else + { + sprintf(sigmsgbuf, "Signal %d", + sigcode); + sigmsg = sigmsgbuf; + } + fprintf(stderr, "sccs: %s: %s%s", argv[0], + sigmsg, + coredumped ? " - core dumped": ""); + } + st = EX_SOFTWARE; + } + if (OutFile >= 0) + { + close(OutFile); + OutFile = -1; + } + return (st); + } + } + else if (OutFile >= 0) + { + syserr("callprog: setting stdout w/o forking"); + exit(EX_SOFTWARE); + } + + /* set protection as appropriate */ + if (bitset(REALUSER, flags)) + setuid(getuid()); + + /* change standard input & output if needed */ + if (OutFile >= 0) + { + close(1); + dup(OutFile); + close(OutFile); + } + + /* call real SCCS program */ + execv(progpath, argv); + syserr("cannot execute %s", progpath); + exit(EX_UNAVAILABLE); + /*NOTREACHED*/ +} + +/* +** MAKEFILE -- make filename of SCCS file +** +** If the name passed is already the name of an SCCS file, +** just return it. Otherwise, munge the name into the name +** of the actual SCCS file. +** +** There are cases when it is not clear what you want to +** do. For example, if SccsPath is an absolute pathname +** and the name given is also an absolute pathname, we go +** for SccsPath (& only use the last component of the name +** passed) -- this is important for security reasons (if +** sccs is being used as a setuid front end), but not +** particularly intuitive. +** +** Parameters: +** name -- the file name to be munged. +** +** Returns: +** The pathname of the sccs file. +** NULL on error. +** +** Side Effects: +** none. +*/ + +char * +makefile(name) + char *name; +{ + register char *p; + char buf[3*FBUFSIZ]; + extern char *malloc(); + extern char *rindex(); + extern bool safepath(); + extern bool isdir(); + register char *q; + + p = rindex(name, '/'); + if (p == NULL) + p = name; + else + p++; + + /* + ** Check to see that the path is "safe", i.e., that we + ** are not letting some nasty person use the setuid part + ** of this program to look at or munge some presumably + ** hidden files. + */ + + if (SccsDir[0] == '/' && !safepath(name)) + return (NULL); + + /* + ** Create the base pathname. + */ + + /* first the directory part */ + if (SccsDir[0] != '\0' && name[0] != '/' && strncmp(name, "./", 2) != 0) + { + gstrcpy(buf, SccsDir, sizeof(buf)); + gstrcat(buf, "/", sizeof(buf)); + } + else + gstrcpy(buf, "", sizeof(buf)); + + /* then the head of the pathname */ + gstrncat(buf, name, p - name, sizeof(buf)); + q = &buf[strlen(buf)]; + + /* now copy the final part of the name, in case useful */ + gstrcpy(q, p, sizeof(buf)); + + /* so is it useful? */ + if (strncmp(p, "s.", 2) != 0 && !isdir(buf)) + { + /* sorry, no; copy the SCCS pathname & the "s." */ + gstrcpy(q, SccsPath, sizeof(buf)); + gstrcat(buf, "/s.", sizeof(buf)); + + /* and now the end of the name */ + gstrcat(buf, p, sizeof(buf)); + } + + /* if i haven't changed it, why did I do all this? */ + if (strcmp(buf, name) == 0) + p = name; + else + { + /* but if I have, squirrel it away */ + p = malloc(strlen(buf) + 1); + if (p == NULL) + { + perror("Sccs: no mem"); + exit(EX_OSERR); + } + strcpy(p, buf); + } + + return (p); +} + +/* +** ISDIR -- return true if the argument is a directory. +** +** Parameters: +** name -- the pathname of the file to check. +** +** Returns: +** TRUE if 'name' is a directory, FALSE otherwise. +** +** Side Effects: +** none. +*/ + +bool +isdir(name) + char *name; +{ + struct stat stbuf; + + return (stat(name, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR); +} + +/* +** SAFEPATH -- determine whether a pathname is "safe" +** +** "Safe" pathnames only allow you to get deeper into the +** directory structure, i.e., full pathnames and ".." are +** not allowed. +** +** Parameters: +** p -- the name to check. +** +** Returns: +** TRUE -- if the path is safe. +** FALSE -- if the path is not safe. +** +** Side Effects: +** Prints a message if the path is not safe. +*/ + +bool +safepath(p) + register char *p; +{ + extern char *index(); + + if (*p != '/') + { + while (strncmp(p, "../", 3) != 0 && strcmp(p, "..") != 0) + { + p = index(p, '/'); + if (p == NULL) + return (TRUE); + p++; + } + } + + printf("You may not use full pathnames or \"..\"\n"); + return (FALSE); +} + +/* +** CLEAN -- clean out recreatable files +** +** Any file for which an "s." file exists but no "p." file +** exists in the current directory is purged. +** +** Parameters: +** mode -- tells whether this came from a "clean", "info", or +** "check" command. +** argv -- the rest of the argument vector. +** +** Returns: +** none. +** +** Side Effects: +** Removes files in the current directory. +** Prints information regarding files being edited. +** Exits if a "check" command. +*/ + +clean(mode, argv) + int mode; + char **argv; +{ + struct direct *dir; + char buf[FBUFSIZ]; + char *bufend; + register DIR *dirp; + register char *basefile; + bool gotedit; + bool gotpfent; + FILE *pfp; + bool nobranch = FALSE; + extern struct pfile *getpfent(); + register struct pfile *pf; + register char **ap; + extern char *username(); + char *usernm = NULL; + char *subdir = NULL; + char *cmdname; + + /* + ** Process the argv + */ + + cmdname = *argv; + for (ap = argv; *++ap != NULL; ) + { + if (**ap == '-') + { + /* we have a flag */ + switch ((*ap)[1]) + { + case 'b': + nobranch = TRUE; + break; + + case 'u': + if ((*ap)[2] != '\0') + usernm = &(*ap)[2]; + else if (ap[1] != NULL && ap[1][0] != '-') + usernm = *++ap; + else + usernm = username(); + break; + } + } + else + { + if (subdir != NULL) + usrerr("too many args"); + else + subdir = *ap; + } + } + + /* + ** Find and open the SCCS directory. + */ + + gstrcpy(buf, SccsDir, sizeof(buf)); + if (buf[0] != '\0') + gstrcat(buf, "/", sizeof(buf)); + if (subdir != NULL) + { + gstrcat(buf, subdir, sizeof(buf)); + gstrcat(buf, "/", sizeof(buf)); + } + gstrcat(buf, SccsPath, sizeof(buf)); + bufend = &buf[strlen(buf)]; + + dirp = opendir(buf); + if (dirp == NULL) + { + usrerr("cannot open %s", buf); + return (EX_NOINPUT); + } + + /* + ** Scan the SCCS directory looking for s. files. + ** gotedit tells whether we have tried to clean any + ** files that are being edited. + */ + + gotedit = FALSE; + while (dir = readdir(dirp)) { + if (strncmp(dir->d_name, "s.", 2) != 0) + continue; + + /* got an s. file -- see if the p. file exists */ + gstrcpy(bufend, "/p.", sizeof(buf)); + basefile = bufend + 3; + gstrcpy(basefile, &dir->d_name[2], sizeof(buf)); + + /* + ** open and scan the p-file. + ** 'gotpfent' tells if we have found a valid p-file + ** entry. + */ + + pfp = fopen(buf, "r"); + gotpfent = FALSE; + if (pfp != NULL) + { + /* the file exists -- report it's contents */ + while ((pf = getpfent(pfp)) != NULL) + { + if (nobranch && isbranch(pf->p_nsid)) + continue; + if (usernm != NULL && strcmp(usernm, pf->p_user) != 0 && mode != CLEANC) + continue; + gotedit = TRUE; + gotpfent = TRUE; + if (mode == TELLC) + { + printf("%s\n", basefile); + break; + } + printf("%12s: being edited: ", basefile); + putpfent(pf, stdout); + } + fclose(pfp); + } + + /* the s. file exists and no p. file exists -- unlink the g-file */ + if (mode == CLEANC && !gotpfent) + { + char unlinkbuf[FBUFSIZ]; + gstrcpy(unlinkbuf, &dir->d_name[2], sizeof(unlinkbuf)); + unlink(unlinkbuf); + } + } + + /* cleanup & report results */ + closedir(dirp); + if (!gotedit && mode == INFOC) + { + printf("Nothing being edited"); + if (nobranch) + printf(" (on trunk)"); + if (usernm == NULL) + printf("\n"); + else + printf(" by %s\n", usernm); + } + if (mode == CHECKC) + exit(gotedit); + return (EX_OK); +} + +/* +** ISBRANCH -- is the SID a branch? +** +** Parameters: +** sid -- the sid to check. +** +** Returns: +** TRUE if the sid represents a branch. +** FALSE otherwise. +** +** Side Effects: +** none. +*/ + +isbranch(sid) + char *sid; +{ + register char *p; + int dots; + + dots = 0; + for (p = sid; *p != '\0'; p++) + { + if (*p == '.') + dots++; + if (dots > 1) + return (TRUE); + } + return (FALSE); +} + +/* +** UNEDIT -- unedit a file +** +** Checks to see that the current user is actually editting +** the file and arranges that s/he is not editting it. +** +** Parameters: +** fn -- the name of the file to be unedited. +** +** Returns: +** TRUE -- if the file was successfully unedited. +** FALSE -- if the file was not unedited for some +** reason. +** +** Side Effects: +** fn is removed +** entries are removed from pfile. +*/ + +bool +unedit(fn) + char *fn; +{ + register FILE *pfp; + char *cp, *pfn; + static char tfn[] = _PATH_TMP; + FILE *tfp; + register char *q; + bool delete = FALSE; + bool others = FALSE; + char *myname; + extern char *username(); + struct pfile *pent; + extern struct pfile *getpfent(); + char buf[PFILELG]; + extern char *makefile(), *rindex(), *tail(); + + /* make "s." filename & find the trailing component */ + pfn = makefile(fn); + if (pfn == NULL) + return (FALSE); + q = rindex(pfn, '/'); + if (q == NULL) + q = &pfn[-1]; + if (q[1] != 's' || q[2] != '.') + { + usrerr("bad file name \"%s\"", fn); + return (FALSE); + } + + /* turn "s." into "p." & try to open it */ + *++q = 'p'; + + pfp = fopen(pfn, "r"); + if (pfp == NULL) + { + printf("%12s: not being edited\n", fn); + return (FALSE); + } + + /* create temp file for editing p-file */ + mktemp(tfn); + tfp = fopen(tfn, "w"); + if (tfp == NULL) + { + usrerr("cannot create \"%s\"", tfn); + exit(EX_OSERR); + } + + /* figure out who I am */ + myname = username(); + + /* + ** Copy p-file to temp file, doing deletions as needed. + */ + + while ((pent = getpfent(pfp)) != NULL) + { + if (strcmp(pent->p_user, myname) == 0) + { + /* a match */ + delete++; + } + else + { + /* output it again */ + putpfent(pent, tfp); + others++; + } + } + + /* + * Before changing anything, make sure we can remove + * the file in question (assuming it exists). + */ + if (delete) { + extern int errno; + + cp = tail(fn); + errno = 0; + if (access(cp, 0) < 0 && errno != ENOENT) + goto bad; + if (errno == 0) + /* + * This is wrong, but the rest of the program + * has built in assumptions about "." as well, + * so why make unedit a special case? + */ + if (access(".", 2) < 0) { + bad: + printf("%12s: can't remove\n", cp); + fclose(tfp); + fclose(pfp); + unlink(tfn); + return (FALSE); + } + } + /* do final cleanup */ + if (others) + { + /* copy it back (perhaps it should be linked?) */ + if (freopen(tfn, "r", tfp) == NULL) + { + syserr("cannot reopen \"%s\"", tfn); + exit(EX_OSERR); + } + if (freopen(pfn, "w", pfp) == NULL) + { + usrerr("cannot create \"%s\"", pfn); + return (FALSE); + } + while (fgets(buf, sizeof buf, tfp) != NULL) + fputs(buf, pfp); + } + else + { + /* it's empty -- remove it */ + unlink(pfn); + } + fclose(tfp); + fclose(pfp); + unlink(tfn); + + /* actually remove the g-file */ + if (delete) + { + /* + * Since we've checked above, we can + * use the return from unlink to + * determine if the file existed or not. + */ + if (unlink(cp) >= 0) + printf("%12s: removed\n", cp); + return (TRUE); + } + else + { + printf("%12s: not being edited by you\n", fn); + return (FALSE); + } +} + +/* +** DODIFF -- diff an s-file against a g-file +** +** Parameters: +** getv -- argv for the 'get' command. +** gfile -- name of the g-file to diff against. +** +** Returns: +** Result of get. +** +** Side Effects: +** none. +*/ + +dodiff(getv, gfile) + char **getv; + char *gfile; +{ + int pipev[2]; + int rval; + register int i; + register int pid; + auto int st; + extern int errno; + sig_t osig; + + printf("\n------- %s -------\n", gfile); + fflush(stdout); + + /* create context for diff to run in */ + if (pipe(pipev) < 0) + { + syserr("dodiff: pipe failed"); + exit(EX_OSERR); + } + if ((pid = fork()) < 0) + { + syserr("dodiff: fork failed"); + exit(EX_OSERR); + } + else if (pid > 0) + { + /* in parent; run get */ + OutFile = pipev[1]; + close(pipev[0]); + rval = command(&getv[1], TRUE, "get:rcixt -s -k -p"); + osig = signal(SIGINT, SIG_IGN); + while (((i = wait(&st)) >= 0 && i != pid) || errno == EINTR) + errno = 0; + signal(SIGINT, osig); + /* ignore result of diff */ + } + else + { + /* in child, run diff */ + if (close(pipev[1]) < 0 || close(0) < 0 || + dup(pipev[0]) != 0 || close(pipev[0]) < 0) + { + syserr("dodiff: magic failed"); + exit(EX_OSERR); + } + command(&getv[1], FALSE, "-diff:elsfhbC"); + } + return (rval); +} + +/* +** TAIL -- return tail of filename. +** +** Parameters: +** fn -- the filename. +** +** Returns: +** a pointer to the tail of the filename; e.g., given +** "cmd/ls.c", "ls.c" is returned. +** +** Side Effects: +** none. +*/ + +char * +tail(fn) + register char *fn; +{ + register char *p; + + for (p = fn; *p != 0; p++) + if (*p == '/' && p[1] != '\0' && p[1] != '/') + fn = &p[1]; + return (fn); +} + +/* +** GETPFENT -- get an entry from the p-file +** +** Parameters: +** pfp -- p-file file pointer +** +** Returns: +** pointer to p-file struct for next entry +** NULL on EOF or error +** +** Side Effects: +** Each call wipes out results of previous call. +*/ + +struct pfile * +getpfent(pfp) + FILE *pfp; +{ + static struct pfile ent; + static char buf[PFILELG]; + register char *p; + extern char *nextfield(); + + if (fgets(buf, sizeof buf, pfp) == NULL) + return (NULL); + + ent.p_osid = p = buf; + ent.p_nsid = p = nextfield(p); + ent.p_user = p = nextfield(p); + ent.p_date = p = nextfield(p); + ent.p_time = p = nextfield(p); + ent.p_aux = p = nextfield(p); + + return (&ent); +} + + +char * +nextfield(p) + register char *p; +{ + if (p == NULL || *p == '\0') + return (NULL); + while (*p != ' ' && *p != '\n' && *p != '\0') + p++; + if (*p == '\n' || *p == '\0') + { + *p = '\0'; + return (NULL); + } + *p++ = '\0'; + return (p); +} + /* +** PUTPFENT -- output a p-file entry to a file +** +** Parameters: +** pf -- the p-file entry +** f -- the file to put it on. +** +** Returns: +** none. +** +** Side Effects: +** pf is written onto file f. +*/ + +putpfent(pf, f) + register struct pfile *pf; + register FILE *f; +{ + fprintf(f, "%s %s %s %s %s", pf->p_osid, pf->p_nsid, + pf->p_user, pf->p_date, pf->p_time); + if (pf->p_aux != NULL) + fprintf(f, " %s", pf->p_aux); + else + fprintf(f, "\n"); +} + +/* +** USRERR -- issue user-level error +** +** Parameters: +** f -- format string. +** p1-p3 -- parameters to a printf. +** +** Returns: +** -1 +** +** Side Effects: +** none. +*/ + +/*VARARGS1*/ +usrerr(f, p1, p2, p3) + char *f; +{ + fprintf(stderr, "\n%s: ", MyName); + fprintf(stderr, f, p1, p2, p3); + fprintf(stderr, "\n"); + + return (-1); +} + +/* +** SYSERR -- print system-generated error. +** +** Parameters: +** f -- format string to a printf. +** p1, p2, p3 -- parameters to f. +** +** Returns: +** never. +** +** Side Effects: +** none. +*/ + +/*VARARGS1*/ +syserr(f, p1, p2, p3) + char *f; +{ + extern int errno; + + fprintf(stderr, "\n%s SYSERR: ", MyName); + fprintf(stderr, f, p1, p2, p3); + fprintf(stderr, "\n"); + if (errno == 0) + exit(EX_SOFTWARE); + else + { + perror(NULL); + exit(EX_OSERR); + } +} + /* +** USERNAME -- return name of the current user +** +** Parameters: +** none +** +** Returns: +** name of current user +** +** Side Effects: +** none +*/ + +char * +username() +{ +# ifdef UIDUSER + extern struct passwd *getpwuid(); + register struct passwd *pw; + + pw = getpwuid(getuid()); + if (pw == NULL) + { + syserr("who are you? (uid=%d)", getuid()); + exit(EX_OSERR); + } + return (pw->pw_name); +# else + extern char *getlogin(); + register char *p; + + p = getenv("USER"); + if (p == NULL || p[0] == '\0') + p = getlogin(); + return (p); +# endif UIDUSER +} + +/* +** Guarded string manipulation routines; the last argument +** is the length of the buffer into which the strcpy or strcat +** is to be done. +*/ +char *gstrcat(to, from, length) + char *to, *from; + int length; +{ + if (strlen(from) + strlen(to) >= length) { + gstrbotch(to, from); + } + return(strcat(to, from)); +} + +char *gstrncat(to, from, n, length) + char *to, *from; + int n; + int length; +{ + if (n + strlen(to) >= length) { + gstrbotch(to, from); + } + return(strncat(to, from, n)); +} + +char *gstrcpy(to, from, length) + char *to, *from; + int length; +{ + if (strlen(from) >= length) { + gstrbotch(from, (char *)0); + } + return(strcpy(to, from)); +} +gstrbotch(str1, str2) + char *str1, *str2; +{ + usrerr("Filename(s) too long: %s %s", str1, str2); +} diff --git a/usr/src/usr.bin/tcopy/Makefile b/usr/src/usr.bin/tcopy/Makefile new file mode 100644 index 0000000000..81417d1e63 --- /dev/null +++ b/usr/src/usr.bin/tcopy/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 5.3 (Berkeley) 5/11/90 + +PROG= tcopy + +.include diff --git a/usr/src/usr.bin/tcopy/pathnames.h b/usr/src/usr.bin/tcopy/pathnames.h new file mode 100644 index 0000000000..78fd252f13 --- /dev/null +++ b/usr/src/usr.bin/tcopy/pathnames.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.2 (Berkeley) 6/1/90 + */ + +#define _PATH_DEFTAPE "/dev/rmt0" diff --git a/usr/src/usr.bin/tcopy/tcopy.1 b/usr/src/usr.bin/tcopy/tcopy.1 new file mode 100644 index 0000000000..a9448c4ee3 --- /dev/null +++ b/usr/src/usr.bin/tcopy/tcopy.1 @@ -0,0 +1,83 @@ +.\" Copyright (c) 1985, 1990, 1991 Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)tcopy.1 6.4 (Berkeley) 4/22/91 +.\" +.Dd April 22, 1991 +.Dt TCOPY 1 +.Os BSD 4.3 +.Sh NAME +.Nm tcopy +.Nd copy and/or verify mag tapes +.Sh SYNOPSIS +.Nm tcopy +.Op Fl cv +.Op Fl s Ar maxblk +.Oo Ar src Op Ar dest +.Oc +.Sh DESCRIPTION +.Nm Tcopy +is designed to copy magnetic tapes. The only assumption made +about the tape is that there are two tape marks at the end. +.Nm Tcopy +with only a source tape +.Pf ( Ar rmt0 +by default) specified will print +information about the sizes of records and tape files. If a destination +is specified a copy will be made of the source tape. The blocking on the +destination tape will be identical to that used on the source tape. Copying +a tape will yield the same output as if just printing the sizes. +.Pp +Options: +.Bl -tag -width s_maxblk +.It Fl c +Copy +.Ar src +to +.Ar dest +and then verify that the two tapes are identical. +.It Fl s Ar maxblk +Specify a maximum block size, +.Ar maxblk . +.It Fl v +Given the two tapes, +.ar src +and +.Ar dest +verify that they are identical. +.El +.Sh SEE ALSO +.Xr mtio 4 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/usr/src/usr.bin/tcopy/tcopy.c b/usr/src/usr.bin/tcopy/tcopy.c new file mode 100644 index 0000000000..f6fa5c169a --- /dev/null +++ b/usr/src/usr.bin/tcopy/tcopy.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 1985, 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1985, 1987 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tcopy.c 5.15 (Berkeley) 11/5/90"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +#define MAXREC (64 * 1024) +#define NOCOUNT (-2) + +int filen, guesslen, maxblk = MAXREC; +long lastrec, record, size, tsize; + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind, errno; + register int lastnread, nread, nw, inp, outp; + enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; + sig_t oldsig; + int ch, needeof; + char *buff, *inf, *getspace(); + void intr(); + + guesslen = 1; + while ((ch = getopt(argc, argv, "cs:v")) != EOF) + switch((char)ch) { + case 'c': + op = COPYVERIFY; + break; + case 's': + maxblk = atoi(optarg); + if (maxblk <= 0) { + fprintf(stderr, "tcopy: illegal block size\n"); + usage(); + } + guesslen = 0; + break; + case 'v': + op = VERIFY; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + switch(argc) { + case 0: + if (op != READ) + usage(); + inf = _PATH_DEFTAPE; + break; + case 1: + if (op != READ) + usage(); + inf = argv[0]; + break; + case 2: + if (op == READ) + op = COPY; + inf = argv[0]; + if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : O_RDWR, + 0666)) < 0) { + perror(argv[1]); + exit(3); + } + break; + default: + usage(); + } + + if ((inp = open(inf, O_RDONLY, 0)) < 0) { + perror(inf); + exit(1); + } + + buff = getspace(maxblk); + + if (op == VERIFY) { + verify(inp, outp, buff); + exit(0); + } + + if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) + (void) signal(SIGINT, intr); + + needeof = 0; + for (lastnread = NOCOUNT;;) { + if ((nread = read(inp, buff, maxblk)) == -1) { + while (errno == EINVAL && (maxblk -= 1024)) { + nread = read(inp, buff, maxblk); + if (nread >= 0) + goto r1; + } + fprintf(stderr, "read error, file %d, record %ld: ", + filen, record); + perror(""); + exit(1); + } else if (nread != lastnread) { + if (lastnread != 0 && lastnread != NOCOUNT) { + if (lastrec == 0 && nread == 0) + printf("%ld records\n", record); + else if (record - lastrec > 1) + printf("records %ld to %ld\n", + lastrec, record); + else + printf("record %ld\n", lastrec); + } + if (nread != 0) + printf("file %d: block size %d: ", + filen, nread); + (void) fflush(stdout); + lastrec = record; + } +r1: guesslen = 0; + if (nread > 0) { + if (op == COPY || op == COPYVERIFY) { + if (needeof) { + writeop(outp, MTWEOF); + needeof = 0; + } + nw = write(outp, buff, nread); + if (nw != nread) { + fprintf(stderr, + "write error, file %d, record %ld: ", + filen, record); + if (nw == -1) + perror(""); + else + fprintf(stderr, + "write (%d) != read (%d)\n", + nw, nread); + fprintf(stderr, "copy aborted\n"); + exit(5); + } + } + size += nread; + record++; + } else { + if (lastnread <= 0 && lastnread != NOCOUNT) { + printf("eot\n"); + break; + } + printf("file %d: eof after %ld records: %ld bytes\n", + filen, record, size); + needeof = 1; + filen++; + tsize += size; + size = record = lastrec = 0; + lastnread = 0; + } + lastnread = nread; + } + printf("total length: %ld bytes\n", tsize); + (void)signal(SIGINT, oldsig); + if (op == COPY || op == COPYVERIFY) { + writeop(outp, MTWEOF); + writeop(outp, MTWEOF); + if (op == COPYVERIFY) { + writeop(outp, MTREW); + writeop(inp, MTREW); + verify(inp, outp, buff); + } + } + exit(0); +} + +verify(inp, outp, outb) + register int inp, outp; + register char *outb; +{ + extern int errno; + register int eot, inmaxblk, inn, outmaxblk, outn; + register char *inb; + char *getspace(); + + inb = getspace(maxblk); + inmaxblk = outmaxblk = maxblk; + for (eot = 0;; guesslen = 0) { + if ((inn = read(inp, inb, inmaxblk)) == -1) { + if (guesslen) + while (errno == EINVAL && (inmaxblk -= 1024)) { + inn = read(inp, inb, inmaxblk); + if (inn >= 0) + goto r1; + } + perror("tcopy: read error"); + break; + } +r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { + if (guesslen) + while (errno == EINVAL && (outmaxblk -= 1024)) { + outn = read(outp, outb, outmaxblk); + if (outn >= 0) + goto r2; + } + perror("tcopy: read error"); + break; + } +r2: if (inn != outn) { + printf("tcopy: tapes have different block sizes; %d != %d.\n", inn, outn); + break; + } + if (!inn) { + if (eot++) { + printf("tcopy: tapes are identical.\n"); + return; + } + } else { + if (bcmp(inb, outb, inn)) { + printf("tcopy: tapes have different data.\n"); + break; + } + eot = 0; + } + } + exit(1); +} + +void +intr() +{ + if (record) + if (record - lastrec > 1) + printf("records %ld to %ld\n", lastrec, record); + else + printf("record %ld\n", lastrec); + printf("interrupt at file %d: record %ld\n", filen, record); + printf("total length: %ld bytes\n", tsize + size); + exit(1); +} + +char * +getspace(blk) + int blk; +{ + char *bp, *malloc(); + + if ((bp = malloc((u_int)blk)) == NULL) { + fprintf(stderr, "tcopy: no memory\n"); + exit(11); + } + return(bp); +} + +writeop(fd, type) + int fd, type; +{ + struct mtop op; + + op.mt_op = type; + op.mt_count = (daddr_t)1; + if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) { + perror("tcopy: tape op"); + exit(6); + } +} + +usage() +{ + fprintf(stderr, "usage: tcopy [-cv] [-s maxblk] src [dest]\n"); + exit(1); +} diff --git a/usr/src/usr.bin/tset/Makefile b/usr/src/usr.bin/tset/Makefile new file mode 100644 index 0000000000..206aed74e1 --- /dev/null +++ b/usr/src/usr.bin/tset/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 5.14 (Berkeley) 12/22/91 + +PROG= tset +SRCS= map.c misc.c set.c term.c tset.c wrterm.c + +DPADD= ${LIBTERMCAP} +LDADD= -ltermcap +LINKS= ${BINDIR}/tset ${BINDIR}/reset +MLINKS= tset.1 reset.1 + +.include diff --git a/usr/src/usr.bin/tset/extern.h b/usr/src/usr.bin/tset/extern.h new file mode 100644 index 0000000000..e7d1a05d7b --- /dev/null +++ b/usr/src/usr.bin/tset/extern.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 5.2 (Berkeley) 12/24/91 + */ + +/* This should be in instead. */ +extern char PC; +extern short ospeed; +int tgetent __P((char *, char *)); +int tgetflag __P((char *)); +int tgetnum __P((char *)); +char *tgetstr __P((char *, char **)); +char *tgoto __P((char *, int, int)); +int tputs __P((char *, int, void (*) __P((int)))); + +extern struct termios mode, oldmode; +extern int columns, isreset, lines; +extern int erasechar, intrchar, killchar; + +void add_mapping __P((char *, char *)); +void cat __P((char *)); +void err __P((const char *, ...)); +char *get_termcap_entry __P((char *, char **)); +char *mapped __P((char *)); +void outc __P((int)); +void reset_mode __P((void)); +void set_control_chars __P((void)); +void set_conversions __P((int)); +void set_init __P((void)); +void wrtermcap __P((char *)); diff --git a/usr/src/usr.bin/tset/map.c b/usr/src/usr.bin/tset/map.c new file mode 100644 index 0000000000..d71fefbaa0 --- /dev/null +++ b/usr/src/usr.bin/tset/map.c @@ -0,0 +1,263 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)map.c 5.2 (Berkeley) 12/24/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include "extern.h" + +int baudrate __P((char *)); + +/* Baud rate conditionals for mapping. */ +#define GT 0x01 +#define EQ 0x02 +#define LT 0x04 +#define NOT 0x08 +#define GE (GT | EQ) +#define LE (LT | EQ) + +typedef struct map { + struct map *next; /* Linked list of maps. */ + char *porttype; /* Port type, or "" for any. */ + char *type; /* Terminal type to select. */ + int conditional; /* Baud rate conditionals bitmask. */ + int speed; /* Baud rate to compare against. */ +} MAP; + +MAP *cur, *maplist; + +/* + * Syntax for -m: + * [port-type][test baudrate]:terminal-type + * The baud rate tests are: >, <, @, =, ! + */ +void +add_mapping(port, arg) + char *port, *arg; +{ + MAP *mapp; + char *copy, *p, *termp; + + copy = strdup(arg); + mapp = malloc((u_int)sizeof(MAP)); + if (copy == NULL || mapp == NULL) + err("%s", strerror(errno)); + mapp->next = NULL; + if (maplist == NULL) + cur = maplist = mapp; + else { + cur->next = mapp; + cur = mapp; + } + + mapp->porttype = arg; + mapp->conditional = 0; + + arg = strpbrk(arg, "><@=!:"); + + if (arg == NULL) { /* [?]term */ + mapp->type = mapp->porttype; + mapp->porttype = NULL; + goto done; + } + + if (arg == mapp->porttype) /* [><@=! baud]:term */ + termp = mapp->porttype = NULL; + else + termp = arg; + + for (;; ++arg) /* Optional conditionals. */ + switch(*arg) { + case '<': + if (mapp->conditional & GT) + goto badmopt; + mapp->conditional |= LT; + break; + case '>': + if (mapp->conditional & LT) + goto badmopt; + mapp->conditional |= GT; + break; + case '@': + case '=': /* Not documented. */ + mapp->conditional |= EQ; + break; + case '!': + mapp->conditional |= NOT; + break; + default: + goto next; + } + +next: if (*arg == ':') { + if (mapp->conditional) + goto badmopt; + ++arg; + } else { /* Optional baudrate. */ + arg = index(p = arg, ':'); + if (arg == NULL) + goto badmopt; + *arg++ = '\0'; + mapp->speed = baudrate(p); + } + + if (*arg == NULL) /* Non-optional type. */ + goto badmopt; + + mapp->type = arg; + + /* Terminate porttype, if specified. */ + if (termp != NULL) + *termp = '\0'; + + /* If a NOT conditional, reverse the test. */ + if (mapp->conditional & NOT) + mapp->conditional = ~mapp->conditional & (EQ | GT | LT); + + /* If user specified a port with an option flag, set it. */ +done: if (port) { + if (mapp->porttype) +badmopt: err("illegal -m option format: %s", copy); + mapp->porttype = port; + } + +#ifdef MAPDEBUG + (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); + (void)printf("type: %s\n", mapp->type); + (void)printf("conditional: "); + p = ""; + if (mapp->conditional & GT) { + (void)printf("GT"); + p = "/"; + } + if (mapp->conditional & EQ) { + (void)printf("%sEQ", p); + p = "/"; + } + if (mapp->conditional & LT) + (void)printf("%sLT", p); + (void)printf("\nspeed: %d\n", mapp->speed); +#endif +} + +/* + * Return the type of terminal to use for a port of type 'type', as specified + * by the first applicable mapping in 'map'. If no mappings apply, return + * 'type'. + */ +char * +mapped(type) + char *type; +{ + MAP *mapp; + int match; + + for (mapp = maplist; mapp; mapp = mapp->next) + if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) { + switch (mapp->conditional) { + case 0: /* No test specified. */ + match = 1; + break; + case EQ: + match = (ospeed == mapp->speed); + break; + case GE: + match = (ospeed >= mapp->speed); + break; + case GT: + match = (ospeed > mapp->speed); + break; + case LE: + match = (ospeed <= mapp->speed); + break; + case LT: + match = (ospeed < mapp->speed); + break; + } + if (match) + return (mapp->type); + } + /* No match found; return given type. */ + return (type); +} + +typedef struct speeds { + char *string; + int speed; +} SPEEDS; + +SPEEDS speeds[] = { + "0", B0, + "50", B50, + "75", B75, + "110", B110, + "134", B134, + "134.5", B134, + "150", B150, + "200", B200, + "300", B300, + "600", B600, + "1200", B1200, + "1800", B1800, + "2400", B2400, + "4800", B4800, + "9600", B9600, + "19200", B19200, + "38400", B38400, + "exta", B19200, + "extb", B38400, + NULL +}; + +int +baudrate(rate) + char *rate; +{ + SPEEDS *sp; + + /* The baudrate number can be preceded by a 'B', which is ignored. */ + if (*rate == 'B') + ++rate; + + for (sp = speeds; sp->string; ++sp) + if (!strcasecmp(rate, sp->string)) + return (sp->speed); + err("unknown baud rate %s", rate); + /* NOTREACHED */ +} diff --git a/usr/src/usr.bin/tset/misc.c b/usr/src/usr.bin/tset/misc.c new file mode 100644 index 0000000000..69f68abeca --- /dev/null +++ b/usr/src/usr.bin/tset/misc.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)misc.c 5.1 (Berkeley) 12/22/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include "extern.h" + +void +cat(file) + char *file; +{ + register int fd, nr, nw; + char buf[1024]; + + if ((fd = open(file, O_RDONLY, 0)) < 0) + err("%s: %s", file, strerror(errno)); + + while ((nr = read(fd, buf, sizeof(buf))) > 0) + if ((nw = write(STDERR_FILENO, buf, nr)) == -1) + err("write to stderr: %s", strerror(errno)); + if (nr != 0) + err("%s: %s", file, strerror(errno)); + (void)close(fd); +} + +void +outc(c) + int c; +{ + (void)putc(c, stderr); +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "tset: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(1); + /* NOTREACHED */ +} diff --git a/usr/src/usr.bin/tset/set.c b/usr/src/usr.bin/tset/set.c new file mode 100644 index 0000000000..b6a1851282 --- /dev/null +++ b/usr/src/usr.bin/tset/set.c @@ -0,0 +1,320 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)set.c 5.2 (Berkeley) 12/24/91"; +#endif /* not lint */ + +#include +#include +#include +#include "extern.h" + +#define CHK(val, dft) (val <= 0 ? dft : val) + +int set_tabs __P((void)); + +/* + * Reset the terminal mode bits to a sensible state. Very useful after + * a child program dies in raw mode. + */ +void +reset_mode() +{ + tcgetattr(STDERR_FILENO, &mode); + +#if defined(VDISCARD) && defined(CDISCARD) + mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); +#endif + mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); + mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); +#if defined(VFLUSH) && defined(CFLUSH) + mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); +#endif + mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); + mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); +#if defined(VLNEXT) && defined(CLNEXT) + mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); +#endif + mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); +#if defined(VREPRINT) && defined(CRPRNT) + mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); +#endif + mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); + mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); + mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); +#if defined(VWERASE) && defined(CWERASE) + mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); +#endif + + mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR +#ifdef IUCLC + | IUCLC +#endif +#ifdef IXANY + | IXANY +#endif + | IXOFF); + + mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON +#ifdef IMAXBEL + | IMAXBEL +#endif + ); + + mode.c_oflag &= ~(0 +#ifdef OLCUC + | OLCUC +#endif +#ifdef OCRNL + | OCRNL +#endif +#ifdef ONOCR + | ONOCR +#endif +#ifdef ONLRET + | ONLRET +#endif +#ifdef OFILL + | OFILL +#endif +#ifdef OFDEL + | OFDEL +#endif +#ifdef NLDLY + | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY +#endif + ); + + mode.c_oflag |= (OPOST +#ifdef ONLCR + | ONLCR +#endif + ); + + mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); + mode.c_cflag |= (CS8 | CREAD); + mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP +#ifdef ECHOPTR + | ECHOPRT +#endif +#ifdef XCASE + | XCASE +#endif + ); + + mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK +#ifdef ECHOCTL + | ECHOCTL +#endif +#ifdef ECHOKE + | ECHOKE +#endif + ); + + tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); +} + +/* + * Determine the erase, interrupt, and kill characters from the termcap + * entry and command line and update their values in 'mode'. + */ +void +set_control_chars() +{ + char *bp, *p, bs_char, buf[1024]; + + bp = buf; + p = tgetstr("kb", &bp); + if (p == NULL || p[1] != '\0') + p = tgetstr("bc", &bp); + if (p != NULL && p[1] == '\0') + bs_char = p[0]; + else if (tgetflag("bs")) + bs_char = CTRL('h'); + else + bs_char = 0; + + if (erasechar == 0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) { + if (tgetflag("bs") || bs_char != 0) + erasechar = -1; + } + if (erasechar < 0) + erasechar = (bs_char != 0) ? bs_char : CTRL('h'); + + if (mode.c_cc[VERASE] == 0 || erasechar != 0) + mode.c_cc[VERASE] = erasechar ? erasechar : CERASE; + + if (mode.c_cc[VINTR] == 0 || intrchar != 0) + mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; + + if (mode.c_cc[VKILL] == 0 || killchar != 0) + mode.c_cc[VKILL] = killchar ? killchar : CKILL; +} + +/* + * Set up various conversions in 'mode', including parity, tabs, returns, + * echo, and case, according to the termcap entry. If the program we're + * running was named with a leading upper-case character, map external + * uppercase to internal lowercase. + */ +void +set_conversions(usingupper) + int usingupper; +{ + if (tgetflag("UC") || usingupper) { +#ifdef IUCLC + mode.c_iflag |= IUCLC; + mode.c_oflag |= OLCUC; +#endif + } else if (tgetflag("LC")) { +#ifdef IUCLC + mode.c_iflag &= ~IUCLC; + mode.c_oflag &= ~OLCUC; +#endif + } + mode.c_iflag &= ~(PARMRK | INPCK); + mode.c_lflag |= ICANON; + if (tgetflag("EP")) { + mode.c_cflag |= PARENB; + mode.c_cflag &= ~PARODD; + } + if (tgetflag("OP")) { + mode.c_cflag |= PARENB; + mode.c_cflag |= PARODD; + } + +#ifdef ONLCR + mode.c_oflag |= ONLCR; +#endif + mode.c_iflag |= ICRNL; + mode.c_lflag |= ECHO; + mode.c_oflag |= OXTABS; + if (tgetflag("NL")) { /* Newline, not linefeed. */ +#ifdef ONLCR + mode.c_oflag &= ~ONLCR; +#endif + mode.c_iflag &= ~ICRNL; + } + if (tgetflag("HD")) /* Half duplex. */ + mode.c_lflag &= ~ECHO; + if (tgetflag("pt")) /* Print tabs. */ + mode.c_oflag &= ~OXTABS; + mode.c_lflag |= (ECHOE | ECHOK); +} + +/* Output startup string. */ +void +set_init() +{ + char *bp, buf[1024]; + int settle; + + bp = buf; + if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ + PC = buf[0]; + +#ifdef TAB3 + if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { + oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); + tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); + } +#endif + settle = set_tabs(); + + if (isreset) { + if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { + tputs(buf, 0, outc); + settle = 1; + } + if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { + cat(buf); + settle = 1; + } + } + + if (settle) { + (void)putc('\r', stderr); + (void)fflush(stderr); + (void)sleep(1); /* Settle the terminal. */ + } +} + +/* + * Set the hardware tabs on the terminal, using the ct (clear all tabs), + * st (set one tab) and ch (horizontal cursor addressing) capabilities. + * This is done before if and is, so they can patch in case we blow this. + * Return nonzero if we set any tab stops, zero if not. + */ +int +set_tabs() +{ + int c; + char *capsp, *clear_tabs; + char *set_column, *set_pos, *set_tab, *tg_out; + char caps[1024]; + + capsp = caps; + set_tab = tgetstr("st", &capsp); + + if (set_tab && (clear_tabs = tgetstr("ct", &capsp))) { + (void)putc('\r', stderr); /* Force to left margin. */ + tputs(clear_tabs, 0, outc); + } + + set_column = tgetstr("ch", &capsp); + set_pos = set_column ? NULL : tgetstr("cm", &capsp); + + if (set_tab) { + for (c = 8; c < columns; c += 8) { + /* + * Get to the right column. "OOPS" is returned by + * tgoto() if it can't do the job. (*snarl*) + */ + tg_out = "OOPS"; + if (set_column) + tg_out = tgoto(set_column, 0, c); + if (*tg_out == 'O' && set_pos) + tg_out = tgoto(set_pos, c, lines - 1); + if (*tg_out != 'O') + tputs(tg_out, 1, outc); + else + (void)fprintf(stderr, "%s", " "); + /* Set the tab. */ + tputs(set_tab, 0, outc); + } + putc('\r', stderr); + return (1); + } + return (0); +} diff --git a/usr/src/usr.bin/tset/term.c b/usr/src/usr.bin/tset/term.c new file mode 100644 index 0000000000..403eb2d795 --- /dev/null +++ b/usr/src/usr.bin/tset/term.c @@ -0,0 +1,138 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)term.c 5.1 (Berkeley) 12/22/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include "extern.h" + +char tbuf[1024]; /* Termcap entry. */ + +char *askuser __P((char *)); +char *ttys __P((char *)); + +/* + * Figure out what kind of terminal we're dealing with, and then read in + * its termcap entry. + */ +char * +get_termcap_entry(userarg, tcapbufp) + char *userarg, **tcapbufp; +{ + struct ttyent *t; + int rval; + char *base, *ttype, *ttypath; + + if (userarg) { + ttype = userarg; + goto found; + } + + /* Try the environment. */ + if (ttype = getenv("TERM")) + goto map; + + /* Try ttyname(3); check for dialup or other mapping. */ + if (ttypath = ttyname(STDERR_FILENO)) { + if (base = rindex(ttypath, '/')) + ++base; + else + base = ttypath; + if ((t = getttynam(base))) { + ttype = t->ty_type; + goto map; + } + } + + /* If still undefined, use "unknown". */ + ttype = "unknown"; + +map: ttype = mapped(ttype); + + /* + * Remove TERMCAP from the environment so we get a real entry from + * /etc/termcap. This prevents us from being fooled by out of date + * stuff in the environment. + */ +found: unsetenv("TERMCAP"); + + /* + * ttype now contains a pointer to the type of the terminal. + * If the first character is '?', ask the user. + */ + if (ttype[0] == '?') + ttype = askuser(ttype + 1); + + /* Find the termcap entry. If it doesn't exist, ask the user. */ + while ((rval = tgetent(tbuf, ttype)) == 0) { + (void)fprintf(stderr, + "tset: terminal type %s is unknown\n", ttype); + ttype = askuser(NULL); + } + if (rval == -1) + err("termcap: %s", strerror(errno ? errno : ENOENT)); + *tcapbufp = tbuf; + return (ttype); +} + +/* Prompt the user for a terminal type. */ +char * +askuser(dflt) + char *dflt; +{ + static char answer[256]; + char *p; + + for (;;) { + if (dflt) + (void)fprintf(stderr, "Terminal type? [%s] ", dflt); + else + (void)fprintf(stderr, "Terminal type? "); + (void)fflush(stderr); + + if (fgets(answer, sizeof(answer), stdin) == NULL) + continue; + + if (p = index(answer, '\n')) + *p = '\0'; + return (answer[0] ? answer : dflt); + } +} diff --git a/usr/src/usr.bin/tset/tset.1 b/usr/src/usr.bin/tset/tset.1 new file mode 100644 index 0000000000..a292b1dc05 --- /dev/null +++ b/usr/src/usr.bin/tset/tset.1 @@ -0,0 +1,370 @@ +.\" Copyright (c) 1985, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)tset.1 6.10 (Berkeley) 12/24/91 +.\" +.Dd December 24, 1991 +.Dt TSET 1 +.Os BSD 4 +.Sh NAME +.Nm tset +.Nd terminal initialization +.Sh SYNOPSIS +.Nm tset +.Op Fl IQrs +.Op Fl +.Op Fl e Ar ch +.Op Fl i Ar ch +.Op Fl k Ar ch +.Op Fl m Ar mapping +.Op Ar terminal +.br +.Nm reset +.Op Fl IQrs +.Op Fl +.Op Fl e Ar ch +.Op Fl i Ar ch +.Op Fl k Ar ch +.Op Fl m Ar mapping +.Op Ar terminal +.Sh DESCRIPTION +.Nm Tset +initializes terminals. +.Nm Tset +first determines the type of terminal that you are using. +This determination is done as follows, using the first terminal type found. +.sp +.Bl -bullet -compact -offset indent +.It +The +.Ar terminal +argument specified on the command line. +.It +The value of the +.Ev TERM +environmental variable. +.It +The terminal type associated with the standard error output device in the +.Pa /etc/ttys +file. +.It +The default terminal type, ``unknown''. +.El +.Pp +If the terminal type was not specified on the command-line, the +.Fl m +option mappings are then applied (see below for more information). +Then, if the terminal type begins with a question mark (``?''), the user is +prompted for confirmation of the terminal type. +An empty response confirms the type, or, another type can be entered to +specify a new type. +Once the terminal type has been determined, the termcap entry for the terminal +is retrieved. +If no termcap entry is found for the type, the user is prompted for another +terminal type. +.Pp +Once the termcap entry is retrieved, the window size, backspace, interrupt +and line kill characters (among many other things) are set and the terminal +and tab initialization strings are sent to the standard error output. +Finally, if the erase, interrupt and line kill characters have changed, +or are not set to their default values, their values are displayed to the +standard error output. +.Pp +When invoked as +.Nm reset , +.Nm tset +sets cooked and echo modes, turns off cbreak and raw modes, turns on +newline translation and resets any unset special characters to their +default values before doing the terminal initialization described above. +This is useful after a program dies leaving a terminal in a abnormal state. +Note, you may have to type +.Dq Li reset +(the line-feed character is normally control-J) to get the terminal +to work, as carriage-return may no longer work in the abnormal state. +Also, the terminal will often not echo the command. +.Pp +The options are as follows: +.Bl -tag -width flag +.It Fl +The terminal type is displayed to the standard output, and the terminal is +not initialized in any way. +.It Fl e +Set the erase character to +.Ar ch . +.It Fl I +Do not send the terminal or tab initialization strings to the terminal. +.It Fl i +Set the interrupt character to +.Ar ch . +.It Fl k +Set the line kill character to +.Ar ch . +.It Fl m +Specify a mapping from a port type to a terminal. +See below for more information. +.It Fl r +Print the terminal type to the standard error output. +.It Fl s +Print the sequence of shell commands to initialize the environment variables +.Ev TERM +and +.Ev TERMCAP +to the standard output. +.It Fl Q +Don't display any values for the erase, interrupt and line kill characters. +.El +.Pp +The arguments for the +.Fl e , +.Fl i +and +.Fl k +options may either be entered as actual characters or by using the +.Dq hat +notation, i.e. control-h may be specified as +.Dq Li ^H +or +.Dq Li ^h . +.Sh SETTING THE ENVIRONMENT +It is often desirable to set the terminal type and information about the +terminal's capabilities in the shell's environment. +This is done with the +.Fl s +option; when this option is specified, the commands to enter the information +into the shell's environment are output to the standard output. +If the +.Ev SHELL +environmental variable ends in ``csh'', the output commands are for the +.Xr csh 1 , +otherwise, they are for +.Xr sh 1 . +Note, the output commands for the +.Nm csh +set and unset the shell variable +.Dq noglob . +The following line in the +.Pa .login +or +.Pa .profile +files will initialize the environment correctly: +.Bd -literal -offset indent +eval \`tset -s options ... \` +.Ed +.Sh TERMINAL TYPE MAPPING +When the terminal is not hardwired into the system (or the current system +information is incorrect) the terminal type derived from the +.Pa /etc/ttys +file or the +.Ev TERM +environmental variable is often something generic like +.Dq network , +.Dq dialup , +or +.Dq unknown . +When +.Nm tset +is used in a startup script +.Pf ( Pa .profile +for +.Xr sh 1 +users or +.Pa .login +for +.Xr csh 1 +users) it is often desirable to provide information about the type of +terminal used on such ports. +The purpose of the +.Fl m +option is to +.Dq map +from some set of conditions to a terminal type, that is, to +tell +.Nm tset +``If I'm on this port at a particular speed, guess that I'm on that +kind of terminal''. +.Pp +The argument to the +.Fl m +option consists of an optional port type, an optional operator, an optional +baud rate specification, an optional colon (``:'') character and a terminal +type. +The port type is a string (delimited by either the operator or the colon +character). +The operator may be any combination of: +.Dq Li \&> , +.Dq Li \&< , +.Dq Li \&@ , +and +.Dq Li \&! ; +.Dq Li \&> +means greater than, +.Dq Li \&< +means less than, +.Dq Li \&@ +means equal to +and +.Dq Li \&! +inverts the sense of the test. +The baud rate is specified as a number and is compared with the speed +of the standard error output (which should be the control terminal). +The terminal type is a string. +.Pp +If the terminal type is not specified on the command line, the +.Fl m +mappings are applied to the terminal type. +If the port type and baud rate match the mapping, the terminal type specified +in the mapping replaces the current type. +If more than one mapping is specified, the first applicable mapping is used. +.Pp +For example, consider the following: +.Dq Li dialup>9600:vt100 . +The port type is +.Dq Li dialup , +the operator is +.Dq Li > , +the baud rate specification is +.Dq Li 9600 , +and the terminal type is +.Dq Li vt100 . +The result of this mapping is to specify that if the terminal type is +.Dq Li dialup , +and the baud rate is greater than 9600 baud, a terminal type of +.Dq Li vt100 +will be used. +.Pp +If no port type is specified, the terminal type will match any port type, +for example, +.Dq Li -m dialup:vt100 -m :?xterm +will cause any dialup port, regardless of baud rate, to match the terminal +type +.Dq Li vt100 , +and any non-dialup port type to match the terminal type +.Dq Li ?xterm . +Note, because of the leading question mark, the user will be +queried on a default port as to whether they are actually using an +.Ar xterm +terminal. +.Pp +No whitespace characters are permitted in the +.Fl m +option argument. +Also, to avoid problems with metacharacters, it is suggested that the entire +.Fl m +option argument be placed within single quote characters, and that +.Nm csh +users insert a backslash character (``\e'') before any exclamation +marks (``!''). +.Sh ENVIRONMENT +The +.Nm tset +command utilizes the +.Ev SHELL +and +.Ev TERM +environment variables. +.Sh FILES +.Bl -tag -width /usr/share/misc/termcap -compact +.It Pa /etc/ttys +system port name to terminal type mapping database +.It Pa /usr/share/misc/termcap +terminal capability database +.El +.Sh SEE ALSO +.Xr csh 1 , +.Xr sh 1 , +.Xr stty 1 , +.Xr tty 4 , +.Xr termcap 5 , +.Xr ttys 5 , +.Xr environ 7 +.Sh HISTORY +The +.Nm tset +command appeared in +.Bx 3.0 . +.Sh COMPATIBILITY +The +.Fl A , +.Fl E , +.Fl h , +.Fl S , +.Fl u +and +.Fl v +options have been deleted from the +.Nm tset +utility. +None of them were documented in 4.3BSD and all are of limited utility at +best. +The +.Fl a , +.Fl d +and +.Fl p +options are similarly not documented or useful, but were retained as they +appear to be in widespread use. +It is strongly recommended that any usage of these three options be +changed to use the +.Fl m +option instead. +The +.Fl n +option remains, but has no effect. +It is still permissible to specify the +.Fl e , +.Fl i +and +.Fl k +options without arguments, although it is strongly recommended that such +usage be fixed to explicitly specify the character. +.Pp +Executing +.Nm tset +as +.Nm reset +no longer implies the +.Fl Q +option. +Also, the interaction between the +.Fl +option and the +.Ar terminal +argument in some historic implementations of +.Nm tset +has been removed. +.Pp +Finally, the +.Nm tset +implementation has been completely redone (as part of the addition to the +system of a +.St -p1003.1-88 +compliant terminal interface) and will no longer compile on systems with +older terminal interfaces. diff --git a/usr/src/usr.bin/tset/tset.c b/usr/src/usr.bin/tset/tset.c new file mode 100644 index 0000000000..d55fb31d3d --- /dev/null +++ b/usr/src/usr.bin/tset/tset.c @@ -0,0 +1,304 @@ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tset.c 5.19 (Berkeley) 12/24/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "extern.h" + +void obsolete __P((char *[])); +void report __P((char *, int, u_int)); +void usage __P((void)); + +struct termios mode, oldmode; + +int dosetenv; /* output TERMCAP strings */ +int erasechar; /* new erase character */ +int intrchar; /* new interrupt character */ +int isreset; /* invoked as reset */ +int killchar; /* new kill character */ +int noinit; /* don't output initialization string */ +int noset; /* only report term type */ +int quiet; /* don't display ctrl key settings */ +int showterm; /* display term on stderr */ + +int lines, columns; /* window size */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef TIOCGWINSZ + struct winsize win; +#endif + int ch, csh, usingupper; + char savech, *p, *t, *tcapbuf, *ttype; + + if (tcgetattr(STDERR_FILENO, &mode) < 0) + err("standard error: %s", strerror(errno)); + + oldmode = mode; + ospeed = cfgetospeed(&mode); + + if (p = strrchr(*argv, '/')) + ++p; + else + p = *argv; + usingupper = isupper(*p); + if (!strcasecmp(p, "reset")) { + isreset = 1; + reset_mode(); + } + + obsolete(argv); + while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:Qrs")) != EOF) { + switch (ch) { + case '-': /* OBSOLETE: display term only */ + noset = 1; + break; + case 'a': /* OBSOLETE: map identifier to type */ + add_mapping("arpanet", optarg); + break; + case 'd': /* OBSOLETE: map identifier to type */ + add_mapping("dialup", optarg); + break; + case 'e': /* erase character */ + erasechar = optarg[0] == '^' && optarg[1] != '\0' ? + optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : + optarg[0]; + break; + case 'I': /* no initialization */ + noinit = 1; + break; + case 'i': /* interrupt character */ + intrchar = optarg[0] == '^' && optarg[1] != '\0' ? + optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : + optarg[0]; + break; + case 'k': /* kill character */ + killchar = optarg[0] == '^' && optarg[1] != '\0' ? + optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : + optarg[0]; + break; + case 'm': /* map identifier to type */ + add_mapping(NULL, optarg); + break; + case 'n': /* OBSOLETE: set new tty driver */ + break; + case 'p': /* OBSOLETE: map identifier to type */ + add_mapping("plugboard", optarg); + break; + case 'Q': /* be quiet */ + quiet = 1; + break; + case 'r': /* display term on stderr */ + showterm = 1; + break; + case 's': /* print commands to set environment */ + dosetenv = 1; + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc > 1) + usage(); + + ttype = get_termcap_entry(*argv, &tcapbuf); + + if (!noset) { + columns = tgetnum("co"); + lines = tgetnum("li"); + +#ifdef TIOCGWINSZ + /* Set window size */ + (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); + if (win.ws_row == 0 && win.ws_col == 0 && + lines > 0 && columns > 0) { + win.ws_row = lines; + win.ws_col = columns; + (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); + } +#endif + set_control_chars(); + set_conversions(usingupper); + + if (!noinit) + set_init(); + + /* Set the modes if they've changed. */ + if (memcmp(&mode, &oldmode, sizeof(mode))) + tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); + } + + /* + * The termcap file generally has a two-character name first in each + * entry followed by more descriptive names. If we ended up with the + * first one, we switch to the second one for setting or reporting + * information. + */ + p = strpbrk(tcapbuf, "|:"); + if (p && *p != ':' && !strncmp(ttype, tcapbuf, p - tcapbuf)) { + t = ++p; + if (p = strpbrk(p, "|:")) { + savech = *p; + *p = '\0'; + if ((ttype = strdup(t)) == NULL) + err("%s", strerror(errno)); + *p = savech; + } + } + + if (noset) + (void)printf("%s\n", ttype); + else { + if (showterm) + (void)fprintf(stderr, "Terminal type is %s.\n", ttype); + /* + * If erase, kill and interrupt characters could have been + * modified and not -Q, display the changes. + */ + if (!quiet) { + report("Erase", VERASE, CERASE); + report("Kill", VKILL, CKILL); + report("Interrupt", VINTR, CINTR); + } + } + + if (!dosetenv) + exit(0); + + /* + * Figure out what shell we're using. A hack, we look for a $SHELL + * ending in "csh". + */ + csh = (p = getenv("SHELL")) && !strcmp(p + strlen(p) - 3, "csh"); + if (csh) + (void)printf("set noglob;\nsetenv TERM %s;\nsetenv TERMCAP '", + ttype); + else + (void)printf("TERM=%s;\nTERMCAP='", ttype); + wrtermcap(tcapbuf); + if (csh) + (void)printf("';\nunset noglob;\n"); + else + (void)printf("';\nexport TERMCAP TERM;\n"); + exit(0); +} + +/* + * Tell the user if a control key has been changed from the default value. + */ +void +report(name, which, def) + char *name; + int which; + u_int def; +{ + u_int old, new; + char *bp, buf[1024]; + + new = mode.c_cc[which]; + old = oldmode.c_cc[which]; + + if (old == new && old == def) + return; + + (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to"); + + bp = buf; + if (tgetstr("kb", &bp) && new == buf[0] && buf[1] == '\0') + (void)fprintf(stderr, "backspace.\n"); + else if (new == 0177) + (void)fprintf(stderr, "delete.\n"); + else if (new < 040) { + new ^= 0100; + (void)fprintf(stderr, "control-%c (^%c).\n", new, new); + } else + (void)fprintf(stderr, "%c.\n", new); +} + +/* + * Convert the obsolete argument form into something that getopt can handle. + * This means that -e, -i and -k get default arguments supplied for them. + */ +void +obsolete(argv) + char *argv[]; +{ + for (; *argv; ++argv) { + if (argv[0][0] != '-' || argv[1] && argv[1][0] != '-' || + argv[0][1] != 'e' && argv[0][1] != 'i' && + argv[0][1] != 'k' || argv[0][2] != '\0') + continue; + switch(argv[0][1]) { + case 'e': + argv[0] = "-e^H"; + break; + case 'i': + argv[0] = "-i^C"; + break; + case 'k': + argv[0] = "-k^U"; + break; + } + } +} + +void +usage() +{ + (void)fprintf(stderr, +"usage: tset [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n"); + exit(1); +} diff --git a/usr/src/usr.bin/tset/wrterm.c b/usr/src/usr.bin/tset/wrterm.c new file mode 100644 index 0000000000..b31d3c1395 --- /dev/null +++ b/usr/src/usr.bin/tset/wrterm.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wrterm.c 5.2 (Berkeley) 12/24/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "extern.h" + +/* + * Output termcap entry to stdout, quoting characters that would give the + * shell problems and omitting empty fields. + */ +void +wrtermcap(bp) + char *bp; +{ + register int ch; + register char *p; + char *t, *sep; + + /* Find the end of the terminal names. */ + if ((t = index(bp, ':')) == NULL) + err("termcap names not colon terminated"); + *t++ = '\0'; + + /* Output terminal names that don't have whitespace. */ + sep = ""; + while ((p = strsep(&bp, "|")) != NULL) + if (*p != '\0' && strpbrk(p, " \t") == NULL) { + (void)printf("%s%s", sep, p); + sep = "|"; + } + (void)putchar(':'); + + /* + * Output fields, transforming any dangerous characters. Skip + * empty fields or fields containing only whitespace. + */ + while ((p = strsep(&t, ":")) != NULL) { + while ((ch = *p) != '\0' && isspace(ch)) + ++p; + if (ch == '\0') + continue; + while ((ch = *p++) != '\0') + switch(ch) { + case '\033': + (void)printf("\\E"); + case ' ': /* No spaces. */ + (void)printf("\\040"); + break; + case '!': /* No csh history chars. */ + (void)printf("\\041"); + break; + case ',': /* No csh history chars. */ + (void)printf("\\054"); + break; + case '"': /* No quotes. */ + (void)printf("\\042"); + break; + case '\'': /* No quotes. */ + (void)printf("\\047"); + break; + case '`': /* No quotes. */ + (void)printf("\\140"); + break; + case '\\': /* Anything following is OK. */ + case '^': + (void)putchar(ch); + if ((ch = *p++) == '\0') + break; + /* FALLTHROUGH */ + default: + (void)putchar(ch); + } + (void)putchar(':'); + } +} diff --git a/usr/src/usr.bin/vgrind/Makefile b/usr/src/usr.bin/vgrind/Makefile new file mode 100644 index 0000000000..fa7dde8bf2 --- /dev/null +++ b/usr/src/usr.bin/vgrind/Makefile @@ -0,0 +1,17 @@ +# @(#)Makefile 5.8 (Berkeley) 6/5/90 + +PROG= vfontedpr +SRCS= regexp.c vfontedpr.c vgrindefs.c +MAN1= vgrind.0 +MAN5= vgrindefs.0 +BINDIR= /usr/libexec + +beforeinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/vgrind.sh ${DESTDIR}/usr/bin/vgrind + install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/vgrindefs.src \ + ${DESTDIR}/usr/share/misc/vgrindefs + install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/tmac.vgrind \ + ${DESTDIR}/usr/share/tmac + +.include diff --git a/usr/src/usr.bin/vgrind/pathnames.h b/usr/src/usr.bin/vgrind/pathnames.h new file mode 100644 index 0000000000..c039cec2f0 --- /dev/null +++ b/usr/src/usr.bin/vgrind/pathnames.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.2 (Berkeley) 6/1/90 + */ + +#define _PATH_VGRINDEFS "/usr/share/misc/vgrindefs" diff --git a/usr/src/usr.bin/vgrind/regexp.c b/usr/src/usr.bin/vgrind/regexp.c new file mode 100644 index 0000000000..878a429e4b --- /dev/null +++ b/usr/src/usr.bin/vgrind/regexp.c @@ -0,0 +1,582 @@ +/* + * Copyright (c) 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)regexp.c 5.3 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include + +typedef int boolean; +#define TRUE 1 +#define FALSE 0 +#define NIL 0 + +boolean l_onecase; /* true if upper and lower equivalent */ + +#define makelower(c) (isupper((c)) ? tolower((c)) : (c)) + +/* STRNCMP - like strncmp except that we convert the + * first string to lower case before comparing + * if l_onecase is set. + */ + +STRNCMP(s1, s2, len) + register char *s1,*s2; + register int len; +{ + if (l_onecase) { + do + if (*s2 - makelower(*s1)) + return (*s2 - makelower(*s1)); + else { + s2++; + s1++; + } + while (--len); + } else { + do + if (*s2 - *s1) + return (*s2 - *s1); + else { + s2++; + s1++; + } + while (--len); + } + return(0); +} + +/* The following routine converts an irregular expression to + * internal format. + * + * Either meta symbols (\a \d or \p) or character strings or + * operations ( alternation or perenthesizing ) can be + * specified. Each starts with a descriptor byte. The descriptor + * byte has STR set for strings, META set for meta symbols + * and OPER set for operations. + * The descriptor byte can also have the OPT bit set if the object + * defined is optional. Also ALT can be set to indicate an alternation. + * + * For metasymbols the byte following the descriptor byte identities + * the meta symbol (containing an ascii 'a', 'd', 'p', '|', or '('). For + * strings the byte after the descriptor is a character count for + * the string: + * + * meta symbols := descriptor + * symbol + * + * strings := descriptor + * character count + * the string + * + * operatins := descriptor + * symbol + * character count + */ + +/* + * handy macros for accessing parts of match blocks + */ +#define MSYM(A) (*(A+1)) /* symbol in a meta symbol block */ +#define MNEXT(A) (A+2) /* character following a metasymbol block */ + +#define OSYM(A) (*(A+1)) /* symbol in an operation block */ +#define OCNT(A) (*(A+2)) /* character count */ +#define ONEXT(A) (A+3) /* next character after the operation */ +#define OPTR(A) (A+*(A+2)) /* place pointed to by the operator */ + +#define SCNT(A) (*(A+1)) /* byte count of a string */ +#define SSTR(A) (A+2) /* address of the string */ +#define SNEXT(A) (A+2+*(A+1)) /* character following the string */ + +/* + * bit flags in the descriptor + */ +#define OPT 1 +#define STR 2 +#define META 4 +#define ALT 8 +#define OPER 16 + +char *ure; /* pointer current position in unconverted exp */ +char *ccre; /* pointer to current position in converted exp*/ +char *malloc(); + +char * +convexp(re) + char *re; /* unconverted irregular expression */ +{ + register char *cre; /* pointer to converted regular expression */ + + /* allocate room for the converted expression */ + if (re == NIL) + return (NIL); + if (*re == '\0') + return (NIL); + cre = malloc (4 * strlen(re) + 3); + ccre = cre; + ure = re; + + /* start the conversion with a \a */ + *cre = META | OPT; + MSYM(cre) = 'a'; + ccre = MNEXT(cre); + + /* start the conversion (its recursive) */ + expconv (); + *ccre = 0; + return (cre); +} + +expconv() +{ + register char *cs; /* pointer to current symbol in converted exp */ + register char c; /* character being processed */ + register char *acs; /* pinter to last alternate */ + register int temp; + + /* let the conversion begin */ + acs = NIL; + cs = NIL; + while (*ure != NIL) { + switch (c = *ure++) { + + case '\\': + switch (c = *ure++) { + + /* escaped characters are just characters */ + default: + if (cs == NIL || (*cs & STR) == 0) { + cs = ccre; + *cs = STR; + SCNT(cs) = 1; + ccre += 2; + } else + SCNT(cs)++; + *ccre++ = c; + break; + + /* normal(?) metacharacters */ + case 'a': + case 'd': + case 'e': + case 'p': + if (acs != NIL && acs != cs) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NIL; + } + cs = ccre; + *cs = META; + MSYM(cs) = c; + ccre = MNEXT(cs); + break; + } + break; + + /* just put the symbol in */ + case '^': + case '$': + if (acs != NIL && acs != cs) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NIL; + } + cs = ccre; + *cs = META; + MSYM(cs) = c; + ccre = MNEXT(cs); + break; + + /* mark the last match sequence as optional */ + case '?': + if (cs) + *cs = *cs | OPT; + break; + + /* recurse and define a subexpression */ + case '(': + if (acs != NIL && acs != cs) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NIL; + } + cs = ccre; + *cs = OPER; + OSYM(cs) = '('; + ccre = ONEXT(cs); + expconv (); + OCNT(cs) = ccre - cs; /* offset to next symbol */ + break; + + /* return from a recursion */ + case ')': + if (acs != NIL) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NIL; + } + cs = ccre; + *cs = META; + MSYM(cs) = c; + ccre = MNEXT(cs); + return; + + /* mark the last match sequence as having an alternate */ + /* the third byte will contain an offset to jump over the */ + /* alternate match in case the first did not fail */ + case '|': + if (acs != NIL && acs != cs) + OCNT(ccre) = ccre - acs; /* make a back pointer */ + else + OCNT(ccre) = 0; + *cs |= ALT; + cs = ccre; + *cs = OPER; + OSYM(cs) = '|'; + ccre = ONEXT(cs); + acs = cs; /* remember that the pointer is to be filles */ + break; + + /* if its not a metasymbol just build a scharacter string */ + default: + if (cs == NIL || (*cs & STR) == 0) { + cs = ccre; + *cs = STR; + SCNT(cs) = 1; + ccre = SSTR(cs); + } else + SCNT(cs)++; + *ccre++ = c; + break; + } + } + if (acs != NIL) { + do { + temp = OCNT(acs); + OCNT(acs) = ccre - acs; + acs -= temp; + } while (temp != 0); + acs = NIL; + } + return; +} +/* end of convertre */ + + +/* + * The following routine recognises an irregular expresion + * with the following special characters: + * + * \? - means last match was optional + * \a - matches any number of characters + * \d - matches any number of spaces and tabs + * \p - matches any number of alphanumeric + * characters. The + * characters matched will be copied into + * the area pointed to by 'name'. + * \| - alternation + * \( \) - grouping used mostly for alternation and + * optionality + * + * The irregular expression must be translated to internal form + * prior to calling this routine + * + * The value returned is the pointer to the first non \a + * character matched. + */ + +boolean _escaped; /* true if we are currently _escaped */ +char *_start; /* start of string */ + +char * +expmatch (s, re, mstring) + register char *s; /* string to check for a match in */ + register char *re; /* a converted irregular expression */ + register char *mstring; /* where to put whatever matches a \p */ +{ + register char *cs; /* the current symbol */ + register char *ptr,*s1; /* temporary pointer */ + boolean matched; /* a temporary boolean */ + + /* initial conditions */ + if (re == NIL) + return (NIL); + cs = re; + matched = FALSE; + + /* loop till expression string is exhausted (or at least pretty tired) */ + while (*cs) { + switch (*cs & (OPER | STR | META)) { + + /* try to match a string */ + case STR: + matched = !STRNCMP (s, SSTR(cs), SCNT(cs)); + if (matched) { + + /* hoorah it matches */ + s += SCNT(cs); + cs = SNEXT(cs); + } else if (*cs & ALT) { + + /* alternation, skip to next expression */ + cs = SNEXT(cs); + } else if (*cs & OPT) { + + /* the match is optional */ + cs = SNEXT(cs); + matched = 1; /* indicate a successful match */ + } else { + + /* no match, error return */ + return (NIL); + } + break; + + /* an operator, do something fancy */ + case OPER: + switch (OSYM(cs)) { + + /* this is an alternation */ + case '|': + if (matched) + + /* last thing in the alternation was a match, skip ahead */ + cs = OPTR(cs); + else + + /* no match, keep trying */ + cs = ONEXT(cs); + break; + + /* this is a grouping, recurse */ + case '(': + ptr = expmatch (s, ONEXT(cs), mstring); + if (ptr != NIL) { + + /* the subexpression matched */ + matched = 1; + s = ptr; + } else if (*cs & ALT) { + + /* alternation, skip to next expression */ + matched = 0; + } else if (*cs & OPT) { + + /* the match is optional */ + matched = 1; /* indicate a successful match */ + } else { + + /* no match, error return */ + return (NIL); + } + cs = OPTR(cs); + break; + } + break; + + /* try to match a metasymbol */ + case META: + switch (MSYM(cs)) { + + /* try to match anything and remember what was matched */ + case 'p': + /* + * This is really the same as trying the match the + * remaining parts of the expression to any subset + * of the string. + */ + s1 = s; + do { + ptr = expmatch (s1, MNEXT(cs), mstring); + if (ptr != NIL && s1 != s) { + + /* we have a match, remember the match */ + strncpy (mstring, s, s1 - s); + mstring[s1 - s] = '\0'; + return (ptr); + } else if (ptr != NIL && (*cs & OPT)) { + + /* it was aoptional so no match is ok */ + return (ptr); + } else if (ptr != NIL) { + + /* not optional and we still matched */ + return (NIL); + } + if (!isalnum(*s1) && *s1 != '_') + return (NIL); + if (*s1 == '\\') + _escaped = _escaped ? FALSE : TRUE; + else + _escaped = FALSE; + } while (*s1++); + return (NIL); + + /* try to match anything */ + case 'a': + /* + * This is really the same as trying the match the + * remaining parts of the expression to any subset + * of the string. + */ + s1 = s; + do { + ptr = expmatch (s1, MNEXT(cs), mstring); + if (ptr != NIL && s1 != s) { + + /* we have a match */ + return (ptr); + } else if (ptr != NIL && (*cs & OPT)) { + + /* it was aoptional so no match is ok */ + return (ptr); + } else if (ptr != NIL) { + + /* not optional and we still matched */ + return (NIL); + } + if (*s1 == '\\') + _escaped = _escaped ? FALSE : TRUE; + else + _escaped = FALSE; + } while (*s1++); + return (NIL); + + /* fail if we are currently _escaped */ + case 'e': + if (_escaped) + return(NIL); + cs = MNEXT(cs); + break; + + /* match any number of tabs and spaces */ + case 'd': + ptr = s; + while (*s == ' ' || *s == '\t') + s++; + if (s != ptr || s == _start) { + + /* match, be happy */ + matched = 1; + cs = MNEXT(cs); + } else if (*s == '\n' || *s == '\0') { + + /* match, be happy */ + matched = 1; + cs = MNEXT(cs); + } else if (*cs & ALT) { + + /* try the next part */ + matched = 0; + cs = MNEXT(cs); + } else if (*cs & OPT) { + + /* doesn't matter */ + matched = 1; + cs = MNEXT(cs); + } else + + /* no match, error return */ + return (NIL); + break; + + /* check for end of line */ + case '$': + if (*s == '\0' || *s == '\n') { + + /* match, be happy */ + s++; + matched = 1; + cs = MNEXT(cs); + } else if (*cs & ALT) { + + /* try the next part */ + matched = 0; + cs = MNEXT(cs); + } else if (*cs & OPT) { + + /* doesn't matter */ + matched = 1; + cs = MNEXT(cs); + } else + + /* no match, error return */ + return (NIL); + break; + + /* check for start of line */ + case '^': + if (s == _start) { + + /* match, be happy */ + matched = 1; + cs = MNEXT(cs); + } else if (*cs & ALT) { + + /* try the next part */ + matched = 0; + cs = MNEXT(cs); + } else if (*cs & OPT) { + + /* doesn't matter */ + matched = 1; + cs = MNEXT(cs); + } else + + /* no match, error return */ + return (NIL); + break; + + /* end of a subexpression, return success */ + case ')': + return (s); + } + break; + } + } + return (s); +} diff --git a/usr/src/usr.bin/vgrind/retest/Makefile b/usr/src/usr.bin/vgrind/retest/Makefile new file mode 100644 index 0000000000..9423b9d2e2 --- /dev/null +++ b/usr/src/usr.bin/vgrind/retest/Makefile @@ -0,0 +1,10 @@ +# @(#)Makefile 5.1 (Berkeley) 6/5/90 + +PROG= retest +SRCS= regexp.c retest.c +.PATH: ${.CURDIR}/.. +NOMAN= noman + +install: + +.include diff --git a/usr/src/usr.bin/vgrind/retest/retest.c b/usr/src/usr.bin/vgrind/retest/retest.c new file mode 100644 index 0000000000..b2554ed1b7 --- /dev/null +++ b/usr/src/usr.bin/vgrind/retest/retest.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)retest.c 5.3 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include + +int l_onecase = 0; +char * _start; +char * _escaped; +char * convexp(); +char * expmatch(); +main() +{ + char reg[132]; + char *ireg; + char str[132]; + char *match; + char matstr[132]; + char c; + + while (1) { + printf ("\nexpr: "); + scanf ("%s", reg); + ireg = convexp(reg); + match = ireg; + while(*match) { + switch (*match) { + + case '\\': + case '(': + case ')': + case '|': + printf ("%c", *match); + break; + + default: + if (isalnum(*match)) + printf("%c", *match); + else + printf ("<%03o>", *match); + break; + } + match++; + } + printf("\n"); + getchar(); + while(1) { + printf ("string: "); + match = str; + while ((c = getchar()) != '\n') + *match++ = c; + *match = 0; + if (str[0] == '#') + break; + matstr[0] = 0; + _start = str; + _escaped = 0; + match = expmatch (str, ireg, matstr); + if (match == 0) + printf ("FAILED\n"); + else + printf ("match\nmatstr = %s\n", matstr); + } + + } +} diff --git a/usr/src/usr.bin/vgrind/tmac.vgrind b/usr/src/usr.bin/vgrind/tmac.vgrind new file mode 100644 index 0000000000..d9d8af2a51 --- /dev/null +++ b/usr/src/usr.bin/vgrind/tmac.vgrind @@ -0,0 +1,68 @@ +'ss 23 +'ds _ \d\(mi\u +'ps 9p +'vs 10p +'ds - \(mi +'ds / \\h'\\w' 'u-\\w'/'u'/ +'ds /* \\h'\\w' 'u-\\w'/'u'/* +'bd B 3 +'bd S B 3 +'nr cm 0 +'nf +'de vH +'ev 2 +'if t 'if !\nv 'tl '\-\-''\-\-' +'ft 1 +'sp .35i +'tl '\s14\f3\\*(=F\fP\s0'\\*(=H'\f3\s14\\*(=F\fP\s0' +'sp .25i +'ft 1 +\f2\s12\h'\\n(.lu-\w'\\*(=f'u'\\*(=f\fP\s0\h'|0u' +.sp .05i +'ev +'ds =G \\*(=F +.. +'de vF +'ev 2 +'sp .35i +'ie o 'tl '\f2\\*(=M''Page % of \\*(=G\fP' +'el 'tl '\f2Page % of \\*(=G''\\*(=M\fP' +'bp +'ev +'ft 1 +'if \\n(cm=1 'ft 2 +.. +'de () +'pn 1 +.. +'de +C +'nr cm 1 +'ft 2 +'ds +K +'ds -K +.. +'de -C +'nr cm 0 +'ft 1 +'ds +K \f3 +'ds -K \fP +.. +'+C +'-C +'am +C +'ne 3 +.. +'de FN +\f2\s14\h'\\n(.lu-\w'\\$1'u'\\$1\fP\s0\h'|0u'\c +.if \\nx .tm \\$1 \\*(=F \\n% +'ds =f \&...\\$1 +.. +'de FC +.if \\nx .tm \\$1 \\*(=F \\n% +'ds =f \&...\\$1 +.. +'de -F +'rm =f +.. +'ft 1 +'lg 0 diff --git a/usr/src/usr.bin/vgrind/vfontedpr.c b/usr/src/usr.bin/vgrind/vfontedpr.c new file mode 100644 index 0000000000..c0256e1f01 --- /dev/null +++ b/usr/src/usr.bin/vgrind/vfontedpr.c @@ -0,0 +1,703 @@ +/* + * Copyright (c) 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)vfontedpr.c 5.5 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "pathnames.h" + +#define boolean int +#define TRUE 1 +#define FALSE 0 +#define NIL 0 +#define STANDARD 0 +#define ALTERNATE 1 + +/* + * Vfontedpr. + * + * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy) + * + */ + +#define STRLEN 10 /* length of strings introducing things */ +#define PNAMELEN 40 /* length of a function/procedure name */ +#define PSMAX 20 /* size of procedure name stacking */ + +/* regular expression routines */ + +char *expmatch(); /* match a string to an expression */ +char *STRNCMP(); /* a different kindof strncmp */ +char *convexp(); /* convert expression to internal form */ +char *tgetstr(); + +boolean isproc(); + + +char *ctime(); + +/* + * The state variables + */ + +boolean incomm; /* in a comment of the primary type */ +boolean instr; /* in a string constant */ +boolean inchr; /* in a string constant */ +boolean nokeyw = FALSE; /* no keywords being flagged */ +boolean index = FALSE; /* form an index */ +boolean filter = FALSE; /* act as a filter (like eqn) */ +boolean pass = FALSE; /* when acting as a filter, pass indicates + * whether we are currently processing + * input. + */ +boolean prccont; /* continue last procedure */ +int comtype; /* type of comment */ +int margin; +int psptr; /* the stack index of the current procedure */ +char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */ +int plstack[PSMAX]; /* the procedure nesting level stack */ +int blklevel; /* current nesting level */ +char *defsfile = _PATH_VGRINDEFS; /* name of language definitions file */ +char pname[BUFSIZ+1]; + +/* + * The language specific globals + */ + +char *language = "c"; /* the language indicator */ +char *l_keywds[BUFSIZ/2]; /* keyword table address */ +char *l_prcbeg; /* regular expr for procedure begin */ +char *l_combeg; /* string introducing a comment */ +char *l_comend; /* string ending a comment */ +char *l_acmbeg; /* string introducing a comment */ +char *l_acmend; /* string ending a comment */ +char *l_blkbeg; /* string begining of a block */ +char *l_blkend; /* string ending a block */ +char *l_strbeg; /* delimiter for string constant */ +char *l_strend; /* delimiter for string constant */ +char *l_chrbeg; /* delimiter for character constant */ +char *l_chrend; /* delimiter for character constant */ +char l_escape; /* character used to escape characters */ +boolean l_toplex; /* procedures only defined at top lex level */ + +/* + * global variables also used by expmatch + */ +boolean _escaped; /* if last character was an escape */ +char *_start; /* start of the current string */ +boolean l_onecase; /* upper and lower case are equivalent */ + +#define ps(x) printf("%s", x) + +main(argc, argv) + int argc; + char *argv[]; +{ + int lineno; + char *fname = ""; + char *ptr; + struct stat stbuf; + char buf[BUFSIZ]; + char strings[2 * BUFSIZ]; + char defs[2 * BUFSIZ]; + int needbp = 0; + + argc--, argv++; + do { + char *cp; + int i; + + if (argc > 0) { + if (!strcmp(argv[0], "-h")) { + if (argc == 1) { + printf("'ds =H\n"); + argc = 0; + goto rest; + } + printf("'ds =H %s\n", argv[1]); + argc--, argv++; + argc--, argv++; + if (argc > 0) + continue; + goto rest; + } + + /* act as a filter like eqn */ + if (!strcmp(argv[0], "-f")) { + filter++; + argv[0] = argv[argc-1]; + argv[argc-1] = "-"; + continue; + } + + /* take input from the standard place */ + if (!strcmp(argv[0], "-")) { + argc = 0; + goto rest; + } + + /* build an index */ + if (!strcmp(argv[0], "-x")) { + index++; + argv[0] = "-n"; + } + + /* indicate no keywords */ + if (!strcmp(argv[0], "-n")) { + nokeyw++; + argc--, argv++; + continue; + } + + /* specify the font size */ + if (!strncmp(argv[0], "-s", 2)) { + i = 0; + cp = argv[0] + 2; + while (*cp) + i = i * 10 + (*cp++ - '0'); + printf("'ps %d\n'vs %d\n", i, i+1); + argc--, argv++; + continue; + } + + /* specify the language */ + if (!strncmp(argv[0], "-l", 2)) { + language = argv[0]+2; + argc--, argv++; + continue; + } + + /* specify the language description file */ + if (!strncmp(argv[0], "-d", 2)) { + defsfile = argv[1]; + argc--, argv++; + argc--, argv++; + continue; + } + + /* open the file for input */ + if (freopen(argv[0], "r", stdin) == NULL) { + perror(argv[0]); + exit(1); + } + if (index) + printf("'ta 4i 4.25i 5.5iR\n'in .5i\n"); + fname = argv[0]; + argc--, argv++; + } + rest: + + /* + * get the language definition from the defs file + */ + i = tgetent (defs, language, defsfile); + if (i == 0) { + fprintf (stderr, "no entry for language %s\n", language); + exit (0); + } else if (i < 0) { + fprintf (stderr, "cannot find vgrindefs file %s\n", defsfile); + exit (0); + } + cp = strings; + if (tgetstr ("kw", &cp) == NIL) + nokeyw = TRUE; + else { + char **cpp; + + cpp = l_keywds; + cp = strings; + while (*cp) { + while (*cp == ' ' || *cp =='\t') + *cp++ = NULL; + if (*cp) + *cpp++ = cp; + while (*cp != ' ' && *cp != '\t' && *cp) + cp++; + } + *cpp = NIL; + } + cp = buf; + l_prcbeg = convexp (tgetstr ("pb", &cp)); + cp = buf; + l_combeg = convexp (tgetstr ("cb", &cp)); + cp = buf; + l_comend = convexp (tgetstr ("ce", &cp)); + cp = buf; + l_acmbeg = convexp (tgetstr ("ab", &cp)); + cp = buf; + l_acmend = convexp (tgetstr ("ae", &cp)); + cp = buf; + l_strbeg = convexp (tgetstr ("sb", &cp)); + cp = buf; + l_strend = convexp (tgetstr ("se", &cp)); + cp = buf; + l_blkbeg = convexp (tgetstr ("bb", &cp)); + cp = buf; + l_blkend = convexp (tgetstr ("be", &cp)); + cp = buf; + l_chrbeg = convexp (tgetstr ("lb", &cp)); + cp = buf; + l_chrend = convexp (tgetstr ("le", &cp)); + l_escape = '\\'; + l_onecase = tgetflag ("oc"); + l_toplex = tgetflag ("tl"); + + /* initialize the program */ + + incomm = FALSE; + instr = FALSE; + inchr = FALSE; + _escaped = FALSE; + blklevel = 0; + for (psptr=0; psptr= 0)) { + ps("'FC "); + ps(pstack[psptr]); + ps("\n"); + } +#ifdef DEBUG + printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr); +#endif + margin = 0; + } + needbp = 1; + } while (argc > 0); + exit(0); +} + +#define isidchr(c) (isalnum(c) || (c) == '_') + +putScp(os) + char *os; +{ + register char *s = os; /* pointer to unmatched string */ + char dummy[BUFSIZ]; /* dummy to be used by expmatch */ + char *comptr; /* end of a comment delimiter */ + char *acmptr; /* end of a comment delimiter */ + char *strptr; /* end of a string delimiter */ + char *chrptr; /* end of a character const delimiter */ + char *blksptr; /* end of a lexical block start */ + char *blkeptr; /* end of a lexical block end */ + + _start = os; /* remember the start for expmatch */ + _escaped = FALSE; + if (nokeyw || incomm || instr) + goto skip; + if (isproc(s)) { + ps("'FN "); + ps(pname); + ps("\n"); + if (psptr < PSMAX) { + ++psptr; + strncpy (pstack[psptr], pname, PNAMELEN); + pstack[psptr][PNAMELEN] = NULL; + plstack[psptr] = blklevel; + } + } +skip: + do { + /* check for string, comment, blockstart, etc */ + if (!incomm && !instr && !inchr) { + + blkeptr = expmatch (s, l_blkend, dummy); + blksptr = expmatch (s, l_blkbeg, dummy); + comptr = expmatch (s, l_combeg, dummy); + acmptr = expmatch (s, l_acmbeg, dummy); + strptr = expmatch (s, l_strbeg, dummy); + chrptr = expmatch (s, l_chrbeg, dummy); + + /* start of a comment? */ + if (comptr != NIL) + if ((comptr < strptr || strptr == NIL) + && (comptr < acmptr || acmptr == NIL) + && (comptr < chrptr || chrptr == NIL) + && (comptr < blksptr || blksptr == NIL) + && (comptr < blkeptr || blkeptr == NIL)) { + putKcp (s, comptr-1, FALSE); + s = comptr; + incomm = TRUE; + comtype = STANDARD; + if (s != os) + ps ("\\c"); + ps ("\\c\n'+C\n"); + continue; + } + + /* start of a comment? */ + if (acmptr != NIL) + if ((acmptr < strptr || strptr == NIL) + && (acmptr < chrptr || chrptr == NIL) + && (acmptr < blksptr || blksptr == NIL) + && (acmptr < blkeptr || blkeptr == NIL)) { + putKcp (s, acmptr-1, FALSE); + s = acmptr; + incomm = TRUE; + comtype = ALTERNATE; + if (s != os) + ps ("\\c"); + ps ("\\c\n'+C\n"); + continue; + } + + /* start of a string? */ + if (strptr != NIL) + if ((strptr < chrptr || chrptr == NIL) + && (strptr < blksptr || blksptr == NIL) + && (strptr < blkeptr || blkeptr == NIL)) { + putKcp (s, strptr-1, FALSE); + s = strptr; + instr = TRUE; + continue; + } + + /* start of a character string? */ + if (chrptr != NIL) + if ((chrptr < blksptr || blksptr == NIL) + && (chrptr < blkeptr || blkeptr == NIL)) { + putKcp (s, chrptr-1, FALSE); + s = chrptr; + inchr = TRUE; + continue; + } + + /* end of a lexical block */ + if (blkeptr != NIL) { + if (blkeptr < blksptr || blksptr == NIL) { + putKcp (s, blkeptr - 1, FALSE); + s = blkeptr; + blklevel--; + if (psptr >= 0 && plstack[psptr] >= blklevel) { + + /* end of current procedure */ + if (s != os) + ps ("\\c"); + ps ("\\c\n'-F\n"); + blklevel = plstack[psptr]; + + /* see if we should print the last proc name */ + if (--psptr >= 0) + prccont = TRUE; + else + psptr = -1; + } + continue; + } + } + + /* start of a lexical block */ + if (blksptr != NIL) { + putKcp (s, blksptr - 1, FALSE); + s = blksptr; + blklevel++; + continue; + } + + /* check for end of comment */ + } else if (incomm) { + comptr = expmatch (s, l_comend, dummy); + acmptr = expmatch (s, l_acmend, dummy); + if (((comtype == STANDARD) && (comptr != NIL)) || + ((comtype == ALTERNATE) && (acmptr != NIL))) { + if (comtype == STANDARD) { + putKcp (s, comptr-1, TRUE); + s = comptr; + } else { + putKcp (s, acmptr-1, TRUE); + s = acmptr; + } + incomm = FALSE; + ps("\\c\n'-C\n"); + continue; + } else { + putKcp (s, s + strlen(s) -1, TRUE); + s = s + strlen(s); + continue; + } + + /* check for end of string */ + } else if (instr) { + if ((strptr = expmatch (s, l_strend, dummy)) != NIL) { + putKcp (s, strptr-1, TRUE); + s = strptr; + instr = FALSE; + continue; + } else { + putKcp (s, s+strlen(s)-1, TRUE); + s = s + strlen(s); + continue; + } + + /* check for end of character string */ + } else if (inchr) { + if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) { + putKcp (s, chrptr-1, TRUE); + s = chrptr; + inchr = FALSE; + continue; + } else { + putKcp (s, s+strlen(s)-1, TRUE); + s = s + strlen(s); + continue; + } + } + + /* print out the line */ + putKcp (s, s + strlen(s) -1, FALSE); + s = s + strlen(s); + } while (*s); +} + +putKcp (start, end, force) + char *start; /* start of string to write */ + char *end; /* end of string to write */ + boolean force; /* true if we should force nokeyw */ +{ + int i; + int xfld = 0; + + while (start <= end) { + if (index) { + if (*start == ' ' || *start == '\t') { + if (xfld == 0) + printf(""); + printf("\t"); + xfld = 1; + while (*start == ' ' || *start == '\t') + start++; + continue; + } + } + + /* take care of nice tab stops */ + if (*start == '\t') { + while (*start == '\t') + start++; + i = tabs(_start, start) - margin / 8; + printf("\\h'|%dn'", i * 10 + 1 - margin % 8); + continue; + } + + if (!nokeyw && !force) + if ((*start == '#' || isidchr(*start)) + && (start == _start || !isidchr(start[-1]))) { + i = iskw(start); + if (i > 0) { + ps("\\*(+K"); + do + putcp(*start++); + while (--i > 0); + ps("\\*(-K"); + continue; + } + } + + putcp (*start++); + } +} + + +tabs(s, os) + char *s, *os; +{ + + return (width(s, os) / 8); +} + +width(s, os) + register char *s, *os; +{ + register int i = 0; + + while (s < os) { + if (*s == '\t') { + i = (i + 8) &~ 7; + s++; + continue; + } + if (*s < ' ') + i += 2; + else + i++; + s++; + } + return (i); +} + +putcp(c) + register int c; +{ + + switch(c) { + + case 0: + break; + + case '\f': + break; + + case '{': + ps("\\*(+K{\\*(-K"); + break; + + case '}': + ps("\\*(+K}\\*(-K"); + break; + + case '\\': + ps("\\e"); + break; + + case '_': + ps("\\*_"); + break; + + case '-': + ps("\\*-"); + break; + + case '`': + ps("\\`"); + break; + + case '\'': + ps("\\'"); + break; + + case '.': + ps("\\&."); + break; + + case '*': + ps("\\fI*\\fP"); + break; + + case '/': + ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP"); + break; + + default: + if (c < 040) + putchar('^'), c |= '@'; + case '\t': + case '\n': + putchar(c); + } +} + +/* + * look for a process beginning on this line + */ +boolean +isproc(s) + char *s; +{ + pname[0] = NULL; + if (!l_toplex || blklevel == 0) + if (expmatch (s, l_prcbeg, pname) != NIL) { + return (TRUE); + } + return (FALSE); +} + + +/* iskw - check to see if the next word is a keyword + */ + +iskw(s) + register char *s; +{ + register char **ss = l_keywds; + register int i = 1; + register char *cp = s; + + while (++cp, isidchr(*cp)) + i++; + while (cp = *ss++) + if (!STRNCMP(s,cp,i) && !isidchr(cp[i])) + return (i); + return (0); +} diff --git a/usr/src/usr.bin/vgrind/vgrind.1 b/usr/src/usr.bin/vgrind/vgrind.1 new file mode 100644 index 0000000000..4e4a796b26 --- /dev/null +++ b/usr/src/usr.bin/vgrind/vgrind.1 @@ -0,0 +1,225 @@ +.\" Copyright (c) 1980 ,1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)vgrind.1 6.4 (Berkeley) 4/23/91 +.\" +.Dd April 23, 1991 +.Dt VGRIND 1 +.Os BSD 4 +.Sh NAME +.Nm vgrind +.Nd grind nice listings of programs +.Sh SYNOPSIS +.Nm vgrind +.Op Fl +.Op Fl W +.Op Fl d Ar file +.Op Fl f +.Op Fl h Ar header +.Op Fl l Ar language +.Op Fl n +.Op Fl sn +.Op Fl t +.Op Fl x +.Ar name Ar ... +.Sh DESCRIPTION +.Nm Vgrind +formats the program sources which are arguments +in a nice style using +.Xr troff 1 +Comments are placed in italics, keywords in bold face, +and the name of the current function is listed down the margin of each +page as it is encountered. +.Pp +.Nm Vgrind +runs in two basic modes, filter mode (see the +.Fl f +option) or regular mode. In filter mode +.Nm vgrind +acts as a filter in a manner similar to +.Xr tbl 1 . +The standard input is passed directly to the standard output except +for lines bracketed by the +.Em troff-like +macros: +.Bl -tag -width Ds +.It \&.vS +starts processing +.It \&.vE +ends processing +.El +.Pp +These lines are formatted as described above. The output from this +filter can be passed to +.Xr troff +for output. There need be no particular ordering with +.Xr eqn 1 +or +.Xr tbl 1 . +.Pp +In regular mode +.Nm vgrind +accepts input files, processes them, and passes them to +.Xr troff 1 +for output. +.Pp +In both modes +.Nm vgrind +passes any lines beginning with a decimal point without conversion. +.Pp +The options are: +.Bl -tag -width Ar +.It Fl +forces input to be taken from standard input (default if +.Fl f +is specified ) +.It Fl W +forces output to the (wide) Versatec printer rather than the (narrow) +Varian +.It Fl d Ar file +specifies an alternate language definitions +file (default is +.Pa /usr/share/misc/vgrindefs ) +.It Fl f +forces filter mode +.It Fl h Ar header +specifies a particular header to put on every output page (default is +the file name) +.It Fl l +specifies the language to use. Currently known are +.Tn PASCAL +.Pq Fl l Ns Ar p , +.Tn MODEL +.Pq Fl l Ns Ar m , +C +.Pf ( Fl l Ns Ar c +or the default), +.Tn CSH +.Pq Fl l Ns Ar csh , +.Tn SHELL +.Pq Fl l Ns Ar sh , +.Tn RATFOR +.Pq Fl l Ns Ar r , +.Tn MODULA2 +.Pq Fl l Ns Ar mod2 , +.Tn YACC +.Pq Fl l Ns Ar yacc , +.Tn LISP +.Pq Fl l Ns Ar isp , +and +.Tn ICON +.Pq Fl l Ns Ar I . +.It Fl n +forces no keyword bolding +.It Fl s +specifies a point size to use on output (exactly the same as the argument +of a .ps) +.It Fl t +similar to the same option in +.Xr troff +causing formatted text to go to the standard output +.It Fl x +outputs the index file in a ``pretty'' format. +The index file itself is produced whenever +.Nm vgrind +is run with a file called +.Pa index +in the current directory. +The index of function +definitions can then be run off by giving +.Nm vgrind +the +.Fl x +option and the file +.Pa index +as argument. +.El +.Sh FILES +.Bl -tag -width /usr/share/misc/vgrindefsxx -compact +.It Pa index +file where source for index is created +.It Pa /usr/share/tmac/tmac.vgrind +macro package +.It Pa /usr/libexec/vfontedpr +preprocessor +.It Pa /usr/share/misc/vgrindefs +language descriptions +.El +.Sh SEE ALSO +.Xr vlp 1 , +.Xr vtroff 1 , +.Xr vgrindefs 5 +.Sh BUGS +Vfontedpr assumes that a certain programming style is followed: +.Pp +For +.Tn C +\- function names can be preceded on a line only by spaces, tabs, or an +asterisk. The parenthesized arguments must also be on the same line. +.Pp +For +.Tn PASCAL +\- function names need to appear on the same line as the keywords +.Em function +or +.Em procedure . +.Pp +For +.Tn MODEL +\- function names need to appear on the same line as the keywords +.Em is beginproc . +.Pp +If these conventions are not followed, the indexing and marginal function +name comment mechanisms will fail. +.Pp +More generally, arbitrary formatting styles for programs mostly look bad. +The use of spaces to align source code fails miserably; if you plan to +.Nm vgrind +your program you should use tabs. This is somewhat inevitable since the +font used by +.Nm vgrind +is variable width. +.Pp +The mechanism of +.Xr ctags 1 +in recognizing functions should be used here. +.Pp +Filter mode does not work in documents using the +.Fl me +or +.Fl ms +macros. +(So what use is it anyway?) +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/usr/src/usr.bin/vgrind/vgrind.sh b/usr/src/usr.bin/vgrind/vgrind.sh new file mode 100644 index 0000000000..d7fa30ba4d --- /dev/null +++ b/usr/src/usr.bin/vgrind/vgrind.sh @@ -0,0 +1,143 @@ +#!/bin/csh -f +# +# Copyright (c) 1980 The Regents of the University of California. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)vgrind.sh 5.7 (Berkeley) 4/16/91 +# + +set voptions= +set options= +set files= +set f='' +set head="" +set vf=/usr/libexec/vfontedpr +set tm=/usr/share/tmac +top: +if ($#argv > 0) then + switch ($1:q) + + case -f: + set f='filter' + set options = "$options $1:q" + shift + goto top + + case -t: + set voptions = "$voptions -t" + shift + goto top + + case -o*: + set voptions="$voptions $1:q" + shift + goto top + + case -W: + set voptions = "$voptions -W" + shift + goto top + + case -d: + if ($#argv < 2) then + echo "vgrind: $1:q option must have argument" + goto done + else + set options = ($options $1:q $2) + shift + shift + goto top + endif + + case -h: + if ($#argv < 2) then + echo "vgrind: $1:q option must have argument" + goto done + else + set head="$2" + shift + shift + goto top + endif + + case -*: + set options = "$options $1:q" + shift + goto top + + default: + set files = "$files $1:q" + shift + goto top + endsw +endif +if (-r index) then + echo > nindex + foreach i ($files) + # make up a sed delete command for filenames + # being careful about slashes. + echo "? $i ?d" | sed -e "s:/:\\/:g" -e "s:?:/:g" >> nindex + end + sed -f nindex index >xindex + if ($f == 'filter') then + if ("$head" != "") then + $vf $options -h "$head" $files | cat $tm/tmac.vgrind - + else + $vf $options $files | cat $tm/tmac.vgrind - + endif + else + if ("$head" != "") then + $vf $options -h "$head" $files | \ + sh -c "vtroff -rx1 $voptions -i -mvgrind 2>> xindex" + else + $vf $options $files | \ + sh -c "vtroff -rx1 $voptions -i -mvgrind 2>> xindex" + endif + endif + sort -df +0 -2 xindex >index + rm nindex xindex +else + if ($f == 'filter') then + if ("$head" != "") then + $vf $options -h "$head" $files | cat $tm/tmac.vgrind - + else + $vf $options $files | cat $tm/tmac.vgrind - + endif + else + if ("$head" != "") then + $vf $options -h "$head" $files | vtroff -i $voptions -mvgrind + else + $vf $options $files | vtroff -i $voptions -mvgrind + endif + endif +endif + +done: diff --git a/usr/src/usr.bin/vgrind/vgrindefs.5 b/usr/src/usr.bin/vgrind/vgrindefs.5 new file mode 100644 index 0000000000..55e353d23d --- /dev/null +++ b/usr/src/usr.bin/vgrind/vgrindefs.5 @@ -0,0 +1,158 @@ +.\" Copyright (c) 1989, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)vgrindefs.5 6.7 (Berkeley) 7/31/91 +.\" +.Dd July 31, 1991 +.Dt VGRINDEFS 5 +.Os BSD 4.2 +.Sh NAME +.Nm vgrindefs +.Nd language definition data base for +.Xr vgrind 1 +.Sh SYNOPSIS +.Nm vgrindefs +.Sh DESCRIPTION +The +.Nm vgrindefs +file +contains all language definitions for +.Xr vgrind 1 . +The data base is +very similar to +.Xr termcap 5 . +.Sh FIELDS +The following table names and describes each field. +.Pp +.Bl -column Namexxx Tpexxx +.Sy Name Type Description +.It "pb str regular expression for start of a procedure" +.It "bb str regular expression for start of a lexical block" +.It "be str regular expression for the end of a lexical block" +.It "cb str regular expression for the start of a comment" +.It "ce str regular expression for the end of a comment" +.It "sb str regular expression for the start of a string" +.It "se str regular expression for the end of a string" +.It "lb str regular expression for the start of a character constant" +.It "le str regular expression for the end of a character constant" +.It "tl bool present means procedures are only defined at the top lexical level" +.It "oc bool present means upper and lower case are equivalent" +.It "kw str a list of keywords separated by spaces" +.El +.Pp +.Sh EXAMPLES +The following entry, which describes the C language, is +typical of a language entry. +.Bd -literal +C|c:\ +:pb=^\ed?*?\ed?\ep\ed?\e(\ea?\e):bb={:be=}:cb=/*:ce=*/:sb=":se=\ee":\e +:lb=':le=\ee':tl:\e +:kw=asm auto break case char continue default do double else enum\e +extern float for fortran goto if int long register return short\e +sizeof static struct switch typedef union unsigned while #define\e +#else #endif #if #ifdef #ifndef #include #undef # define else endif\e +if ifdef ifndef include undef: +.Ed +.Pp +Note that the first field is just the language name (and any variants +of it). Thus the C language could be specified to +.Xr vgrind 1 +as "c" or "C". +.Pp +Entries may continue onto multiple lines by giving a \e as the last +character of a line. +Capabilities in +.Nm vgrindefs +are of two types: +Boolean capabilities which indicate that the language has +some particular feature +and string +capabilities which give a regular expression or +keyword list. +.Sh REGULAR EXPRESSIONS +.Nm Vgrindefs +uses regular expression which are very similar to those of +.Xr ex 1 +and +.Xr lex 1 . +The characters `^', `$', `:' and `\e' +are reserved characters and must be +"quoted" with a preceding +.Ql \e +if they +are to be included as normal characters. +The metasymbols and their meanings are: +.Bl -tag -width indent +.It $ +the end of a line +.It \&^ +the beginning of a line +.It \ed +a delimiter (space, tab, newline, start of line) +.It \ea +matches any string of symbols (like .* in lex) +.It \ep +matches any alphanumeric name. In a procedure definition (pb) the string +that matches this symbol is used as the procedure name. +.It () +grouping +.It \&| +alternation +.It ? +last item is optional +.It \ee +preceding any string means that the string will not match an +input string if the input string is preceded by an escape character (\e). +This is typically used for languages (like C) which can include the +string delimiter in a string by escaping it. +.El +.Pp +Unlike other regular expressions in the system, these match words +and not characters. Hence something like "(tramp|steamer)flies?" +would match "tramp", "steamer", "trampflies", or "steamerflies". +.Sh KEYWORD LIST +The keyword list is just a list of keywords in the language separated +by spaces. If the "oc" boolean is specified, indicating that upper +and lower case are equivalent, then all the keywords should be +specified in lower case. +.Sh FILES +.Bl -tag -width /usr/share/misc/vgrindefs -compact +.It Pa /usr/share/misc/vgrindefs +File containing terminal descriptions. +.El +.Sh SEE ALSO +.Xr vgrind 1 , +.Xr troff 1 +.Sh HISTORY +The +.Nm +file format appeared in +.Bx 4.2 . diff --git a/usr/src/usr.bin/vgrind/vgrindefs.c b/usr/src/usr.bin/vgrind/vgrindefs.c new file mode 100644 index 0000000000..18b0715ed5 --- /dev/null +++ b/usr/src/usr.bin/vgrind/vgrindefs.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 1980 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)vgrindefs.c 5.3 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#define BUFSIZ 1024 +#define MAXHOP 32 /* max number of tc= indirections */ + +#include +/* + * grindcap - routines for dealing with the language definitions data base + * (code stolen almost totally from termcap) + * + * BUG: Should use a "last" pointer in tbuf, so that searching + * for capabilities alphabetically would not be a n**2/2 + * process when large numbers of capabilities are given. + * Note: If we add a last pointer now we will screw up the + * tc capability. We really should compile termcap. + * + * Essentially all the work here is scanning and decoding escapes + * in string capabilities. We don't use stdio because the editor + * doesn't, and because living w/o it is not hard. + */ + +static char *tbuf; +static char *filename; +static int hopcount; /* detect infinite loops in termcap, init 0 */ +char *tskip(); +char *tgetstr(); +char *tdecode(); +char *getenv(); + +/* + * Get an entry for terminal name in buffer bp, + * from the termcap file. Parse is very rudimentary; + * we just notice escaped newlines. + */ +tgetent(bp, name, file) + char *bp, *name, *file; +{ + register char *cp; + register int c; + register int i = 0, cnt = 0; + char ibuf[BUFSIZ]; + char *cp2; + int tf; + + tbuf = bp; + tf = 0; + filename = file; + tf = open(filename, 0); + if (tf < 0) + return (-1); + for (;;) { + cp = bp; + for (;;) { + if (i == cnt) { + cnt = read(tf, ibuf, BUFSIZ); + if (cnt <= 0) { + close(tf); + return (0); + } + i = 0; + } + c = ibuf[i++]; + if (c == '\n') { + if (cp > bp && cp[-1] == '\\'){ + cp--; + continue; + } + break; + } + if (cp >= bp+BUFSIZ) { + write(2,"Vgrind entry too long\n", 23); + break; + } else + *cp++ = c; + } + *cp = 0; + + /* + * The real work for the match. + */ + if (tnamatch(name)) { + close(tf); + return(tnchktc()); + } + } +} + +/* + * tnchktc: check the last entry, see if it's tc=xxx. If so, + * recursively find xxx and append that entry (minus the names) + * to take the place of the tc=xxx entry. This allows termcap + * entries to say "like an HP2621 but doesn't turn on the labels". + * Note that this works because of the left to right scan. + */ +tnchktc() +{ + register char *p, *q; + char tcname[16]; /* name of similar terminal */ + char tcbuf[BUFSIZ]; + char *holdtbuf = tbuf; + int l; + + p = tbuf + strlen(tbuf) - 2; /* before the last colon */ + while (*--p != ':') + if (p MAXHOP) { + write(2, "Infinite tc= loop\n", 18); + return (0); + } + if (tgetent(tcbuf, tcname, filename) != 1) + return(0); + for (q=tcbuf; *q != ':'; q++) + ; + l = p - holdtbuf + strlen(q); + if (l > BUFSIZ) { + write(2, "Vgrind entry too long\n", 23); + q[BUFSIZ - (p-tbuf)] = 0; + } + strcpy(p, q+1); + tbuf = holdtbuf; + return(1); +} + +/* + * Tnamatch deals with name matching. The first field of the termcap + * entry is a sequence of names separated by |'s, so we compare + * against each such name. The normal : terminator after the last + * name (before the first field) stops us. + */ +tnamatch(np) + char *np; +{ + register char *Np, *Bp; + + Bp = tbuf; + if (*Bp == '#') + return(0); + for (;;) { + for (Np = np; *Np && *Bp == *Np; Bp++, Np++) + continue; + if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) + return (1); + while (*Bp && *Bp != ':' && *Bp != '|') + Bp++; + if (*Bp == 0 || *Bp == ':') + return (0); + Bp++; + } +} + +/* + * Skip to the next field. Notice that this is very dumb, not + * knowing about \: escapes or any such. If necessary, :'s can be put + * into the termcap file in octal. + */ +static char * +tskip(bp) + register char *bp; +{ + + while (*bp && *bp != ':') + bp++; + if (*bp == ':') + bp++; + return (bp); +} + +/* + * Return the (numeric) option id. + * Numeric options look like + * li#80 + * i.e. the option string is separated from the numeric value by + * a # character. If the option is not found we return -1. + * Note that we handle octal numbers beginning with 0. + */ +tgetnum(id) + char *id; +{ + register int i, base; + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (*bp == 0) + return (-1); + if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) + continue; + if (*bp == '@') + return(-1); + if (*bp != '#') + continue; + bp++; + base = 10; + if (*bp == '0') + base = 8; + i = 0; + while (isdigit(*bp)) + i *= base, i += *bp++ - '0'; + return (i); + } +} + +/* + * Handle a flag option. + * Flag options are given "naked", i.e. followed by a : or the end + * of the buffer. Return 1 if we find the option, or 0 if it is + * not given. + */ +tgetflag(id) + char *id; +{ + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (!*bp) + return (0); + if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { + if (!*bp || *bp == ':') + return (1); + else if (*bp == '@') + return(0); + } + } +} + +/* + * Get a string valued option. + * These are given as + * cl=^Z + * Much decoding is done on the strings, and the strings are + * placed in area, which is a ref parameter which is updated. + * No checking on area overflow. + */ +char * +tgetstr(id, area) + char *id, **area; +{ + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (!*bp) + return (0); + if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) + continue; + if (*bp == '@') + return(0); + if (*bp != '=') + continue; + bp++; + return (tdecode(bp, area)); + } +} + +/* + * Tdecode does the grung work to decode the + * string capability escapes. + */ +static char * +tdecode(str, area) + register char *str; + char **area; +{ + register char *cp; + register int c; + int i; + + cp = *area; + while (c = *str++) { + if (c == ':' && *(cp-1) != '\\') + break; + *cp++ = c; + } + *cp++ = 0; + str = *area; + *area = cp; + return (str); +} diff --git a/usr/src/usr.bin/vgrind/vgrindefs.src b/usr/src/usr.bin/vgrind/vgrindefs.src new file mode 100644 index 0000000000..67de24d1fc --- /dev/null +++ b/usr/src/usr.bin/vgrind/vgrindefs.src @@ -0,0 +1,146 @@ +# Copyright (c) 1987 The Regents of the University of California. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)vgrindefs.src 1.15 (Berkeley) 4/16/91 +# + +C|c:\ + :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:cb=/*:ce=*/:sb=":se=\e":lb=':\ + :le=\e':tl:\ + :kw=asm auto break case char continue default do double else enum\ + extern float for fortran goto if int long register return short\ + sizeof static struct switch typedef union unsigned void while #define\ + #else #endif #if #ifdef #ifndef #include #undef # define else endif\ + if ifdef ifndef include undef: +model|mod|m:\ + :pb=^\d(space\d\p\drep)|(\p\dis|inline|public\dbeginproc):\ + :bb=\dbeginproc|space|case\d:be=\dendproc|end\d|;:\ + :cb=\$:ce=\$|$:sb=":se=":lb=':le=\a|$:\ + :kw=abs and array beginproc boolean by case cdnl char copied dispose\ + div do dynamic else elsif end endproc entry external FALSE false\ + fi file for formal fortran global if iff ift\ + in integer include inline is lbnd\ + max min mod new NIL nil noresult not notin od of or procedure public\ + read readln readonly record recursive rem rep repeat res\ + result return set\ + space string subscript such then TRUE true type ubnd union until\ + varies while width: +pascal|pasc|p:\ + :pb=(^\d?procedure|function|program\d\p\d|\(|;|\:)|(=\d?record\d):\ + :bb=\dcase|begin\d:be=\dend|forward\d|;:\ + :cb={:ce=}:\ + :ab=\(*:ae=*\):\ + :sb=':se=':\ + :kw=and array assert begin case const div do downto else end file for\ + forward function goto if in label mod nil not of or packed procedure\ + program record repeat set then to type until var while with oct hex\ + external: +ISP|isp|i:\ + :cb=!:ce=!|$:oc:\ + :kw=and begin decode define end eql eqv geq gtr if leave leq lss mod\ + neq next not or otherwise repeat restart resume sr0 sr1 srd srr sl0 sl1\ + sld slr tst xor: +SH|sh:\ + :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\ + :le=\e':tl:\ + :kw=break case cd continue do done \ + elif else esac eval exec exit export \ + fi for if in then while until \ + read readonly set shift test trap umask wait: +CSH|csh:\ + :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\ + :le=\e':tl:\ + :kw=alias alloc break breaksw case cd chdir continue default\ + echo else end endif endsw exec exit foreach \ + glob goto history if logout nice nohup onintr repeat set\ + setenv shift source switch then time \ + while umask unalias unset wait while @ env \ + argv child home ignoreeof noclobber noglob \ + nomatch path prompt shell status verbose : +ldl|LDL:\ + :pb=^\p\::bb=\::be=;:cb=/*:ce=*/:sb=":se=\e":\ + :kw=constant functions grammar reswords tokens add1 addste\ + car cdr check colno cond cons copy defun divide empty enter\ + eq equal findattr firstchild ge getattr getfield gt hash label\ + lambda lastchild le leftsibling lookone lookup lt minus name ne\ + newnode nextcom nil null parent plus precnl prevcom prog progn\ + quote reglob return rightsibling self set setattr setfield setq\ + stjoin sub1 t times tnull tokno ttype: +Icon|icon|I:\ + :pb=^\d?procedure\d\p\d?\(\a?\):\ + :bb=(^\d?procedure\d\p\d?\(\a?\))|{:be=}|(^\d?end\d?$):\ + :cb=#:ce=$:\ + :sb=":se=\e":lb=':le=\e':tl:\ + :kw=break by case create default do dynamic else end every external\ + fail global if initial local next not of procedure record\ + repeat return static suspend then to until using while\ + &ascii &clock &cset &date &dateline &errout &fail &host &input\ + &lcase &level &main &null &output &pos &random &source &subject\ + &time &trace &ucase &version: +ratfor|rat|r:\ + :pb=(subroutine|function)\d\p\d?\(\a?\):\ + :bb=(subroutine|function)\d\p\d?\(\a?\):be=^\d?end:\ + :cb=#:ce=$:\ + :sb=":se=\e":lb=':le=\e':oc:\ + :kw=DRETURN DRIVER arith break case character default define do\ + else elsedef enddef filedes for function goto if ifdef ifelse\ + ifnotdef include incr integer linepointer next opeq pointer\ + real repeat return select string subroutine substr until: +modula2|mod2|m2:\ + :pb=(^\d?(procedure|function|module)\d\p\d|\(|;|\:):\ + :bb=\d(begin|case|for|if|loop|record|repeat|while|with)\d:\ + :be=\dend|;:\ + :cb={:ce=}:\ + :ab=\(*:ae=*\):\ + :sb=":se=":\ + :oc:\ + :kw=and array begin by case const\ + definition div do else elsif end exit export\ + for from if implementation import in\ + loop mod module not of or pointer procedure qualified\ + record repeat return set then to type\ + until var while with: +yacc|Yacc|y:\ + :cb=/*:ce=*/:sb=":se=\e":lb=':le=\e':tl:\ + :kw=%{ %} %% %union %token %type\ + #else #endif #if #ifdef #ifndef #include #undef # define else endif\ + if ifdef ifndef include undef: +C++|c++:\ + :pb=^\d?*?\d?\p\d?\(\a?\)(\d|{):bb={:be=}:cb=/*:ce=*/:ab=//:\ + :ae=$:sb=":se=\e":lb=':\ + :le=\e':tl:\ + :kw=asm auto break case char continue default do double else enum\ + extern float for fortran goto if int long register return short\ + sizeof static struct switch typedef union unsigned while void #define\ + #else #endif #if #ifdef #ifndef #include #undef # define endif\ + ifdef ifndef include undef defined\ + class const delete friend inline new operator overload private\ + protected public virtual: diff --git a/usr/src/usr.bin/vmstat/Makefile b/usr/src/usr.bin/vmstat/Makefile new file mode 100644 index 0000000000..a344ce37b6 --- /dev/null +++ b/usr/src/usr.bin/vmstat/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 5.7 (Berkeley) 4/24/91 + +PROG= vmstat +CFLAGS+=-I/sys +MAN8= vmstat.0 +BINGRP= kmem +BINMODE=2555 +DPADD= names.c ${LIBUTIL} +LDADD= -lutil + +.include diff --git a/usr/src/usr.bin/vmstat/names.c b/usr/src/usr.bin/vmstat/names.c new file mode 100644 index 0000000000..6f04979e81 --- /dev/null +++ b/usr/src/usr.bin/vmstat/names.c @@ -0,0 +1,221 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)names.c 5.2 (Berkeley) 6/4/91 + */ + +#if !defined(hp300) && !defined(tahoe) && !defined(vax) && !defined(__386BSD__) +char *defdrives[] = { 0 }; + +void read_names() +{ +} +#endif + +#ifdef __386BSD__ +/* + * 386BSD support added by Rodney W. Grimes, rgrimes@agora.rain.com 3/24/93 + */ +#include + +char *defdrives[] = { "fd0", "fd1", "wd0", "wd1", + "as0", "as1", "sd0", "sd1", 0 }; + +void +read_names() +{ + register char *p; + register u_long isa_bio; + static char buf[BUFSIZ]; + struct isa_device dev; + struct isa_driver drv; + char name[10]; + int i = 0; + int dummydk = 0; + int fdunit = 0; + int wdunit = 0; + int ahaunit = 0; + + isa_bio = nl[X_ISA_BIO].n_value; + if (isa_bio == 0) { + (void) fprintf(stderr, + "vmstat: disk init info not in namelist\n"); + exit(1); + } + + p = buf; + for (;; isa_bio += sizeof dev) { + (void)kvm_read((void *)isa_bio, &dev, sizeof dev); + if (dev.id_driver == 0) + break; + if (dev.id_alive == 0) + continue; + (void)kvm_read(dev.id_driver, &drv, sizeof drv); + (void)kvm_read(drv.name, name, sizeof name); + + /* + * 386bsd is kinda brain dead about dk_units, or at least + * I can't figure out how to get the real unit mappings + */ + if (strcmp(name, "fd") == 0) dummydk = fdunit++; + if (strcmp(name, "wd") == 0) dummydk = wdunit++; + if (strcmp(name, "aha") == 0) dummydk = ahaunit++; + + dr_name[i] = p; + p += sprintf(p, "%s%d", name, dummydk) + 1; + i++; + } +} +#endif /* __386BSD__ */ + +#ifdef hp300 +#include + +char *defdrives[] = { "sd0", "sd1", "sd2", "rd0", "rd1", "rd2", 0 }; + +void +read_names() +{ + register char *p; + register u_long hp; + static char buf[BUFSIZ]; + struct hp_device hdev; + struct driver hdrv; + char name[10]; + + hp = nl[X_HPDINIT].n_value; + if (hp == 0) { + (void) fprintf(stderr, + "vmstat: disk init info not in namelist\n"); + exit(1); + } + p = buf; + for (;; hp += sizeof hdev) { + (void)kvm_read((void *)hp, &hdev, sizeof hdev); + if (hdev.hp_driver == 0) + break; + if (hdev.hp_dk < 0 || hdev.hp_alive == 0 || + hdev.hp_cdriver == 0) + continue; + (void)kvm_read(hdev.hp_driver, &hdrv, sizeof hdrv); + (void)kvm_read(hdrv.d_name, name, sizeof name); + dr_name[hdev.hp_dk] = p; + p += sprintf(p, "%s%d", name, hdev.hp_unit) + 1; + } +} +#endif /* hp300 */ + +#ifdef tahoe +#include + +char *defdrives[] = { "dk0", "dk1", "dk2", 0 }; + +void +read_names() +{ + register char *p; + struct vba_device udev, *up; + struct vba_driver udrv; + char name[10]; + static char buf[BUFSIZ]; + + up = (struct vba_device *) nl[X_VBDINIT].n_value; + if (up == 0) { + (void) fprintf(stderr, + "vmstat: disk init info not in namelist\n"); + exit(1); + } + p = buf; + for (;; up += sizeof udev) { + (void)kvm_read(up, &udev, sizeof udev); + if (udev.ui_driver == 0) + break; + if (udev.ui_dk < 0 || udev.ui_alive == 0) + continue; + (void)kvm_read(udev.ui_driver, &udrv, sizeof udrv); + (void)kvm_read(udrv.ud_dname, name, sizeof name); + dr_name[udev.ui_dk] = p; + p += sprintf(p, "%s%d", name, udev.ui_unit); + } +} +#endif /* tahoe */ + +#ifdef vax +#include +#include + +char *defdrives[] = { "hp0", "hp1", "hp2", 0 }; + +void +read_names() +{ + register char *p; + unsigned long mp, up; + struct mba_device mdev; + struct mba_driver mdrv; + struct uba_device udev; + struct uba_driver udrv; + char name[10]; + static char buf[BUFSIZ]; + + mp = nl[X_MBDINIT].n_value; + up = nl[X_UBDINIT].n_value; + if (mp == 0 && up == 0) { + (void) fprintf(stderr, + "vmstat: disk init info not in namelist\n"); + exit(1); + } + p = buf; + if (mp) for (;; mp += sizeof mdev) { + (void)kvm_read(mp, &mdev, sizeof mdev); + if (mdev.mi_driver == 0) + break; + if (mdev.mi_dk < 0 || mdev.mi_alive == 0) + continue; + (void)kvm_read(mdev.mi_driver, &mdrv, sizeof mdrv); + (void)kvm_read(mdrv.md_dname, name, sizeof name); + dr_name[mdev.mi_dk] = p; + p += sprintf(p, "%s%d", name, mdev.mi_unit); + } + if (up) for (;; up += sizeof udev) { + (void)kvm_read(up, &udev, sizeof udev); + if (udev.ui_driver == 0) + break; + if (udev.ui_dk < 0 || udev.ui_alive == 0) + continue; + (void)kvm_read(udev.ui_driver, &udrv, sizeof udrv); + (void)kvm_read(udrv.ud_dname, name, sizeof name); + dr_name[udev.ui_dk] = p; + p += sprintf(p, "%s%d", name, udev.ui_unit); + } +} +#endif /* vax */ diff --git a/usr/src/usr.bin/vmstat/vmstat.8 b/usr/src/usr.bin/vmstat/vmstat.8 new file mode 100644 index 0000000000..f2e15a7d96 --- /dev/null +++ b/usr/src/usr.bin/vmstat/vmstat.8 @@ -0,0 +1,206 @@ +.\" Copyright (c) 1986 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)vmstat.8 6.8 (Berkeley) 6/20/91 +.\" +.TH VMSTAT 1 "June 20, 1991" +.UC 4 +.SH NAME +vmstat \- report virtual memory statistics +.SH SYNOPSIS +.nf +.ft B +vmstat [ \-fimst ] [ \-c count ] [ \-M core ] [ \-N system ] +.ti +5 +[ \-w wait ] [ disks ] +.ft R +.fi +.SH DESCRIPTION +.I Vmstat +reports certain kernel statistics kept about process, virtual memory, +disk, trap and cpu activity. +.PP +The options are as follows: +.TP +\-c +Repeat the display +.I count +times. +The first display is for the time since a reboot and each subsequent report +is for the time period since the last display. +If no +.I wait +interval is specified, the default is 1 second. +.TP +\-f +Report on the number +.IR fork (2) +and +.IR vfork (2) +system calls since system startup, and the number of pages of virtual memory +involved in each. +.TP +\-i +Report on the number of interrupts taken by each device since system +startup. +.TP +\-M +Extract values associated with the name list from the specified core +instead of the default ``/dev/kmem''. +.TP +\-N +Extract the name list from the specified system instead of the default +``/vmunix''. +.TP +\-m +Report on the usage of kernel dynamic memory listed first by size of +allocation and then by type of usage. +.TP +\-s +Display the contents of the +.I sum +structure, giving the total number of several kinds of paging related +events which have occurred since system startup. +.TP +\-t +Report on the number of page in and page reclaims since system startup, +and the amount of time required by each. +.TP +\-w +Pause +.I wait +seconds between each display. +If no repeat +.I count +is specified, the default is infinity. +.PP +By default, +.I vmstat +displays the following information: +.PP +.TP +procs +Information about the numbers of processes in various states. +.sp +.RS +.nf +r in run queue +b blocked for resources (i/o, paging, etc.) +w runnable or short sleeper (< 20 secs) but swapped +.fi +.RE +.TP +memory +Information about the usage of virtual and real memory. +Virtual pages (reported in units of 1024 bytes) are considered active if +they belong to processes which are running or have run in the last 20 +seconds. +.sp +.RS +.nf +avm active virtual pages +fre size of the free list +.fi +.RE +.TP +page +Information about page faults and paging activity. +These are averaged each five seconds, and given in units per second. +.sp +.RS +.nf +re page reclaims (simulating reference bits) +at pages attached (found in free list) +pi pages paged in +po pages paged out +fr pages freed per second +de anticipated short term memory shortfall +sr pages scanned by clock algorithm, per-second +.fi +.RE +.TP +disks +Disk operations per second (this field is system dependent). +Typically paging will be split across the available drives. +The header of the field is the first character of the disk name and +the unit number. +If more than four disk drives are configured in the system, +.I vmstat +displays only the first four drives. +To force +.I vmstat +to display specific drives, their names may be supplied on the command line. +.TP +faults +Trap/interrupt rate averages per second over last 5 seconds. +.sp +.RS +.nf +in device interrupts per interval (including clock interrupts) +sy system calls per interval +cs cpu context switch rate (switches/interval) +.fi +.RE +.TP +cpu +Breakdown of percentage usage of CPU time. +.sp +.RS +.nf +us user time for normal and low priority processes +sy system time +id cpu idle +.fi +.RE +.SH EXAMPLES +The command ``vmstat -i 5'' will print what the system is doing every five +seconds; this is a good choice of printing interval since this is how often +some of the statistics are sampled in the system. +Others vary every second and running the output for a while will make it +apparent which are recomputed every second. +.SH FILES +.ta \w'/dev/kmem 'u +/vmunix default kernel namelist +.br +/dev/kmem default memory file +.SH SEE ALSO +.IR fstat (1), +.IR netstat (1), +.IR nfsstat (1), +.IR ps (1), +.IR systat (1), +.IR iostat (8), +.IR pstat (8) +.sp +The sections starting with ``Interpreting system activity'' in +.IR "Installing and Operating 4.3BSD" . +.SH BUGS +The \-c and \-w options are only available with the default output. diff --git a/usr/src/usr.bin/vmstat/vmstat.c b/usr/src/usr.bin/vmstat/vmstat.c new file mode 100644 index 0000000000..9c6bce5c83 --- /dev/null +++ b/usr/src/usr.bin/vmstat/vmstat.c @@ -0,0 +1,868 @@ +/* + * Copyright (c) 1980, 1986, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980, 1986, 1991 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)vmstat.c 5.31 (Berkeley) 7/2/91"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NEWVM /* XXX till old has been updated or purged */ +struct nlist nl[] = { +#define X_CPTIME 0 + { "_cp_time" }, +#define X_TOTAL 1 + { "_total" }, +#define X_SUM 2 + { "_cnt" }, /* XXX for now that's where it is */ +#define X_BOOTTIME 3 + { "_boottime" }, +#define X_DKXFER 4 + { "_dk_xfer" }, +#define X_HZ 5 + { "_hz" }, +#define X_PHZ 6 + { "_phz" }, +#define X_NCHSTATS 7 + { "_nchstats" }, +#define X_INTRNAMES 8 + { "_intrnames" }, +#define X_EINTRNAMES 9 + { "_eintrnames" }, +#define X_INTRCNT 10 + { "_intrcnt" }, +#define X_EINTRCNT 11 + { "_eintrcnt" }, +#define X_DK_NDRIVE 12 + { "_dk_ndrive" }, +#define X_KMEMSTAT 13 + { "_kmemstats" }, +#define X_KMEMBUCKETS 14 + { "_bucket" }, +#define X_VMSTAT 15 + { "_vm_stat" }, +#ifdef notdef +#define X_DEFICIT 15 + { "_deficit" }, +#define X_FORKSTAT 16 + { "_forkstat" }, +#define X_REC 17 + { "_rectime" }, +#define X_PGIN 18 + { "_pgintime" }, +#define X_XSTATS 19 + { "_xstats" }, +#define X_END 19 +#else +#define X_END 15 +#endif +#ifdef hp300 +#define X_HPDINIT (X_END+1) + { "_hp_dinit" }, +#endif +#ifdef tahoe +#define X_VBDINIT (X_END+1) + { "_vbdinit" }, +#define X_CKEYSTATS (X_END+2) + { "_ckeystats" }, +#define X_DKEYSTATS (X_END+3) + { "_dkeystats" }, +#endif +#ifdef vax +#define X_MBDINIT (X_END+1) + { "_mbdinit" }, +#define X_UBDINIT (X_END+2) + { "_ubdinit" }, +#endif +#ifdef __386BSD__ +#define X_FREE (X_END+1) + { "_vm_page_free_count" }, +#define X_ACTIVE (X_END+2) + { "_vm_page_active_count" }, +#define X_INACTIVE (X_END+3) + { "_vm_page_inactive_count" }, +#define X_WIRED (X_END+4) + { "_vm_page_wire_count" }, +#define X_PAGESIZE (X_END+5) + { "_page_size" }, +#define X_ISA_BIO (X_END+6) + { "_isa_devtab_bio" }, +#endif /* __386BSD__ */ + { "" }, +}; + +struct _disk { + long time[CPUSTATES]; + long *xfer; +} cur, last; + +struct vm_statistics vm_stat, ostat; +struct vmmeter sum, osum; +char *vmunix = _PATH_UNIX; +char **dr_name; +int *dr_select, dk_ndrive, ndrives; +#ifdef __386BSD__ + /* to make up for statistics that don't get updated */ +int size, free_count, active_count, inactive, wired; +#endif + +int winlines = 20; + +#define FORKSTAT 0x01 +#define INTRSTAT 0x02 +#define MEMSTAT 0x04 +#define SUMSTAT 0x08 +#define TIMESTAT 0x10 +#define VMSTAT 0x20 + +#include "names.c" /* disk names -- machine dependent */ + +void cpustats(), dkstats(), dointr(), domem(), dosum(); +void dovmstat(), kread(), usage(); +#ifdef notdef +void dotimes(), doforkst(); +#endif + +main(argc, argv) + register int argc; + register char **argv; +{ + extern int optind; + extern char *optarg; + register int c, todo; + u_int interval; + int reps; + char *kmem; + + kmem = NULL; + interval = reps = todo = 0; + while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { + switch (c) { + case 'c': + reps = atoi(optarg); + break; +#ifndef notdef + case 'f': + todo |= FORKSTAT; + break; +#endif + case 'i': + todo |= INTRSTAT; + break; + case 'M': + kmem = optarg; + break; + case 'm': + todo |= MEMSTAT; + break; + case 'N': + vmunix = optarg; + break; + case 's': + todo |= SUMSTAT; + break; +#ifndef notdef + case 't': + todo |= TIMESTAT; + break; +#endif + case 'w': + interval = atoi(optarg); + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (todo == 0) + todo = VMSTAT; + + if (kvm_openfiles(vmunix, kmem, NULL) < 0) { + (void)fprintf(stderr, + "vmstat: kvm_openfiles: %s\n", kvm_geterr()); + exit(1); + } + + if ((c = kvm_nlist(nl)) != 0) { + if (c > 0) { + (void)fprintf(stderr, + "vmstat: undefined symbols in %s:", vmunix); + for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) + if (nl[c].n_type == 0) + fprintf(stderr, " %s", nl[c].n_name); + (void)fputc('\n', stderr); + } else + (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", + kvm_geterr()); + exit(1); + } + + if (todo & VMSTAT) { + char **getdrivedata(); + struct winsize winsize; + + argv = getdrivedata(argv); + winsize.ws_row = 0; + (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); + if (winsize.ws_row > 0) + winlines = winsize.ws_row; + + } + +#define BACKWARD_COMPATIBILITY +#ifdef BACKWARD_COMPATIBILITY + if (*argv) { + interval = atoi(*argv); + if (*++argv) + reps = atoi(*argv); + } +#endif + + if (interval) { + if (!reps) + reps = -1; + } else if (reps) + interval = 1; + +#ifdef notdef + if (todo & FORKSTAT) + doforkst(); +#endif + if (todo & MEMSTAT) + domem(); + if (todo & SUMSTAT) + dosum(); +#ifdef notdef + if (todo & TIMESTAT) + dotimes(); +#endif + if (todo & INTRSTAT) + dointr(); + if (todo & VMSTAT) + dovmstat(interval, reps); + exit(0); +} + +char ** +getdrivedata(argv) + char **argv; +{ + register int i; + register char **cp; + char buf[30]; + + kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); + if (dk_ndrive <= 0) { + (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); + exit(1); + } + dr_select = calloc((size_t)dk_ndrive, sizeof(int)); + dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); + for (i = 0; i < dk_ndrive; i++) + dr_name[i] = NULL; + cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); + last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); + read_names(); + for (i = 0; i < dk_ndrive; i++) + if (dr_name[i] == NULL) { + (void)sprintf(buf, "??%d", i); + dr_name[i] = strdup(buf); + } + + /* + * Choose drives to be displayed. Priority goes to (in order) drives + * supplied as arguments, default drives. If everything isn't filled + * in and there are drives not taken care of, display the first few + * that fit. + */ +#define BACKWARD_COMPATIBILITY + for (ndrives = 0; *argv; ++argv) { +#ifdef BACKWARD_COMPATIBILITY + if (isdigit(**argv)) + break; +#endif + for (i = 0; i < dk_ndrive; i++) { + if (strcmp(dr_name[i], *argv)) + continue; + dr_select[i] = 1; + ++ndrives; + break; + } + } + for (i = 0; i < dk_ndrive && ndrives < 4; i++) { + if (dr_select[i]) + continue; + for (cp = defdrives; *cp; cp++) + if (strcmp(dr_name[i], *cp) == 0) { + dr_select[i] = 1; + ++ndrives; + break; + } + } + for (i = 0; i < dk_ndrive && ndrives < 4; i++) { + if (dr_select[i]) + continue; + dr_select[i] = 1; + ++ndrives; + } + return(argv); +} + +#ifdef __386BSD__ +/* + * Make up for the fact that under 0.1, VM doesn't update all of the + * fields in the statistics structures. + */ + +void +fill_in_vm_stat(vm_stat) + struct vm_statistics *vm_stat; +{ + kread(X_FREE, &vm_stat->free_count, sizeof(vm_stat->free_count)); + kread(X_ACTIVE, &vm_stat->active_count, sizeof(vm_stat->active_count)); + kread(X_INACTIVE, &vm_stat->inactive_count, + sizeof(vm_stat->inactive_count)); + kread(X_WIRED, &vm_stat->wire_count, sizeof(vm_stat->wire_count)); + kread(X_PAGESIZE, &vm_stat->pagesize, sizeof(vm_stat->pagesize)); +} +#endif + +long +getuptime() +{ + static time_t now, boottime; + time_t uptime; + + if (boottime == 0) + kread(X_BOOTTIME, &boottime, sizeof(boottime)); + (void)time(&now); + uptime = now - boottime; + if (uptime <= 0 || uptime > 60*60*24*365*10) { + (void)fprintf(stderr, + "vmstat: time makes no sense; namelist must be wrong.\n"); + exit(1); + } + return(uptime); +} + +int hz, hdrcnt; + +void +dovmstat(interval, reps) + u_int interval; + int reps; +{ + struct vmtotal total; + time_t uptime, halfuptime; + void needhdr(); +#ifndef notdef + int deficit; +#endif + + uptime = getuptime(); + halfuptime = uptime / 2; + (void)signal(SIGCONT, needhdr); + + if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) + kread(X_PHZ, &hz, sizeof(hz)); + if (!hz) + kread(X_HZ, &hz, sizeof(hz)); + + for (hdrcnt = 1;;) { + if (!--hdrcnt) + printhdr(); + kread(X_CPTIME, cur.time, sizeof(cur.time)); + kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive); + kread(X_SUM, &sum, sizeof(sum)); + kread(X_TOTAL, &total, sizeof(total)); + kread(X_VMSTAT, &vm_stat, sizeof(vm_stat)); +#ifdef __386BSD__ + fill_in_vm_stat (&vm_stat); +#endif +#ifdef notdef + kread(X_DEFICIT, &deficit, sizeof(deficit)); +#endif + (void)printf("%2d %1d %1d ", + total.t_rq, total.t_dw + total.t_pw, total.t_sw); +#define pgtok(a) ((a)*NBPG >> 10) +#define rate(x) (((x) + halfuptime) / uptime) /* round */ + (void)printf("%5ld %5ld ", +#ifdef __386BSD__ + pgtok(vm_stat.active_count), pgtok(vm_stat.free_count)); +#else + pgtok(total.t_avm), pgtok(total.t_free)); +#endif +#ifdef NEWVM + (void)printf("%4lu ", rate(vm_stat.faults - ostat.faults)); + (void)printf("%3lu ", + rate(vm_stat.reactivations - ostat.reactivations)); + (void)printf("%3lu ", rate(vm_stat.pageins - ostat.pageins)); + (void)printf("%3lu %3lu ", + rate(vm_stat.pageouts - ostat.pageouts), 0); +#else + (void)printf("%3lu %2lu ", + rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - + (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), + rate(sum.v_xsfrec + sum.v_xifrec - + osum.v_xsfrec - osum.v_xifrec)); + (void)printf("%3lu ", + rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); + (void)printf("%3lu %3lu ", + rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), + rate(pgtok(sum.v_dfree - osum.v_dfree))); + (void)printf("%3d ", pgtok(deficit)); +#endif + (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); + dkstats(); + (void)printf("%4lu %4lu %3lu ", + rate(sum.v_intr - osum.v_intr), + rate(sum.v_syscall - osum.v_syscall), + rate(sum.v_swtch - osum.v_swtch)); + cpustats(); + (void)printf("\n"); + (void)fflush(stdout); + if (reps >= 0 && --reps <= 0) + break; + osum = sum; + ostat = vm_stat; + uptime = interval; + /* + * We round upward to avoid losing low-frequency events + * (i.e., >= 1 per interval but < 1 per second). + */ + halfuptime = (uptime + 1) / 2; + (void)sleep(interval); + } +} + +printhdr() +{ + register int i; + + (void)printf(" procs memory page%*s", 20, ""); + if (ndrives > 1) + (void)printf("disks %*s faults cpu\n", + ndrives * 3 - 6, ""); + else + (void)printf("%*s faults cpu\n", ndrives * 3, ""); +#ifndef NEWVM + (void)printf(" r b w avm fre re at pi po fr de sr "); +#else + (void)printf(" r b w avm fre flt re pi po fr sr "); +#endif + for (i = 0; i < dk_ndrive; i++) + if (dr_select[i]) + (void)printf("%c%c ", dr_name[i][0], + dr_name[i][strlen(dr_name[i]) - 1]); + (void)printf(" in sy cs us sy id\n"); + hdrcnt = winlines - 2; +} + +/* + * Force a header to be prepended to the next output. + */ +void +needhdr() +{ + + hdrcnt = 1; +} + +#ifdef notdef +void +dotimes() +{ + u_int pgintime, rectime; + + kread(X_REC, &rectime, sizeof(rectime)); + kread(X_PGIN, &pgintime, sizeof(pgintime)); + kread(X_SUM, &sum, sizeof(sum)); + (void)printf("%u reclaims, %u total time (usec)\n", + sum.v_pgrec, rectime); + (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); + (void)printf("\n"); + (void)printf("%u page ins, %u total time (msec)\n", + sum.v_pgin, pgintime / 10); + (void)printf("average: %8.1f msec / page in\n", + pgintime / (sum.v_pgin * 10.0)); +} +#endif + +pct(top, bot) + long top, bot; +{ + if (bot == 0) + return(0); + return((top * 100) / bot); +} + +#define PCT(top, bot) pct((long)(top), (long)(bot)) + +#if defined(tahoe) +#include +#endif + +void +dosum() +{ + struct nchstats nchstats; +#ifndef NEWVM + struct xstats xstats; +#endif + long nchtotal; +#if defined(tahoe) + struct keystats keystats; +#endif + + kread(X_SUM, &sum, sizeof(sum)); +#ifdef NEWVM + kread(X_VMSTAT, &vm_stat, sizeof(vm_stat)); +#ifdef __386BSD__ + fill_in_vm_stat(&vm_stat); +#endif +#else + (void)printf("%9u swap ins\n", sum.v_swpin); + (void)printf("%9u swap outs\n", sum.v_swpout); + (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); + (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); + (void)printf("%9u total address trans. faults taken\n", sum.v_faults); + (void)printf("%9u page ins\n", sum.v_pgin); + (void)printf("%9u page outs\n", sum.v_pgout); + (void)printf("%9u pages paged in\n", sum.v_pgpgin); + (void)printf("%9u pages paged out\n", sum.v_pgpgout); + (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); + (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, + PCT(sum.v_fastpgrec, sum.v_pgrec)); + (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); + (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); + (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); + (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); + (void)printf("%9u executable fill pages created\n", + sum.v_nexfod / CLSIZE); + (void)printf("%9u executable fill page faults\n", + sum.v_exfod / CLSIZE); + (void)printf("%9u swap text pages found in free list\n", + sum.v_xsfrec); + (void)printf("%9u inode text pages found in free list\n", + sum.v_xifrec); + (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); + (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); + (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); + (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); + (void)printf("%9u pages freed by the clock daemon\n", + sum.v_dfree / CLSIZE); +#endif + (void)printf("%9u cpu context switches\n", sum.v_swtch); + (void)printf("%9u device interrupts\n", sum.v_intr); + (void)printf("%9u software interrupts\n", sum.v_soft); +#ifdef vax + (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); +#endif + (void)printf("%9u traps\n", sum.v_trap); + (void)printf("%9u system calls\n", sum.v_syscall); +#ifdef NEWVM + (void)printf("%9u bytes per page\n", vm_stat.pagesize); + (void)printf("%9u pages free\n", vm_stat.free_count); + (void)printf("%9u pages active\n", vm_stat.active_count); + (void)printf("%9u pages inactive\n", vm_stat.inactive_count); + (void)printf("%9u pages wired down\n", vm_stat.wire_count); + (void)printf("%9u zero-fill pages\n", vm_stat.zero_fill_count); + (void)printf("%9u pages reactivated\n", vm_stat.reactivations); + (void)printf("%9u pageins\n", vm_stat.pageins); + (void)printf("%9u pageouts\n", vm_stat.pageouts); + (void)printf("%9u VM faults\n", vm_stat.faults); + (void)printf("%9u copy-on-write faults\n", vm_stat.cow_faults); + (void)printf("%9u VM object cache lookups\n", vm_stat.lookups); + (void)printf("%9u VM object hits\n", vm_stat.hits); +#endif + + kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); + nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + + nchstats.ncs_badhits + nchstats.ncs_falsehits + + nchstats.ncs_miss + nchstats.ncs_long; + (void)printf("%9ld total name lookups\n", nchtotal); + (void)printf( + "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", + "", PCT(nchstats.ncs_goodhits, nchtotal), + PCT(nchstats.ncs_neghits, nchtotal), + PCT(nchstats.ncs_pass2, nchtotal)); + (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", + PCT(nchstats.ncs_badhits, nchtotal), + PCT(nchstats.ncs_falsehits, nchtotal), + PCT(nchstats.ncs_long, nchtotal)); +#ifndef NEWVM + kread(X_XSTATS, &xstats, sizeof(xstats)); + (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", + xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); + (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", + xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); + (void)printf("%9lu total calls to xfree", xstats.free); + (void)printf(" (sticky %lu cached %lu swapped %lu)\n", + xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); +#endif +#if defined(tahoe) + kread(X_CKEYSTATS, &keystats, sizeof(keystats)); + (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", + keystats.ks_allocs, "code cache keys allocated", + PCT(keystats.ks_allocfree, keystats.ks_allocs), + PCT(keystats.ks_norefs, keystats.ks_allocs), + PCT(keystats.ks_taken, keystats.ks_allocs), + PCT(keystats.ks_shared, keystats.ks_allocs)); + kread(X_DKEYSTATS, &keystats, sizeof(keystats)); + (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", + keystats.ks_allocs, "data cache keys allocated", + PCT(keystats.ks_allocfree, keystats.ks_allocs), + PCT(keystats.ks_norefs, keystats.ks_allocs), + PCT(keystats.ks_taken, keystats.ks_allocs), + PCT(keystats.ks_shared, keystats.ks_allocs)); +#endif +} + +#ifdef notdef +void +doforkst() +{ + struct forkstat fks; + + kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); + (void)printf("%d forks, %d pages, average %.2f\n", + fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); + (void)printf("%d vforks, %d pages, average %.2f\n", + fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); +} +#endif + +void +dkstats() +{ + register int dn, state; + double etime; + long tmp; + + for (dn = 0; dn < dk_ndrive; ++dn) { + tmp = cur.xfer[dn]; + cur.xfer[dn] -= last.xfer[dn]; + last.xfer[dn] = tmp; + } + etime = 0; + for (state = 0; state < CPUSTATES; ++state) { + tmp = cur.time[state]; + cur.time[state] -= last.time[state]; + last.time[state] = tmp; + etime += cur.time[state]; + } + if (etime == 0) + etime = 1; + etime /= hz; + for (dn = 0; dn < dk_ndrive; ++dn) { + if (!dr_select[dn]) + continue; + (void)printf("%2.0f ", cur.xfer[dn] / etime); + } +} + +void +cpustats() +{ + register int state; + double pct, total; + + total = 0; + for (state = 0; state < CPUSTATES; ++state) + total += cur.time[state]; + if (total) + pct = 100 / total; + else + pct = 0; + (void)printf("%2.0f ", /* user + nice */ + (cur.time[0] + cur.time[1]) * pct); + (void)printf("%2.0f ", cur.time[2] * pct); /* system */ + (void)printf("%2.0f", cur.time[3] * pct); /* idle */ +} + +void +dointr() +{ + register long *intrcnt, inttotal, uptime; + register int nintr, inamlen; + register char *intrname; + + uptime = getuptime(); + nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; + inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; + intrcnt = malloc((size_t)nintr); + intrname = malloc((size_t)inamlen); + if (intrcnt == NULL || intrname == NULL) { + (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); + exit(1); + } + kread(X_INTRCNT, intrcnt, (size_t)nintr); + kread(X_INTRNAMES, intrname, (size_t)inamlen); + (void)printf("interrupt total rate\n"); + inttotal = 0; + nintr /= sizeof(long); + while (--nintr >= 0) { + if (*intrcnt) + (void)printf("%-12s %8ld %8ld\n", intrname, + *intrcnt, *intrcnt / uptime); + intrname += strlen(intrname) + 1; + inttotal += *intrcnt++; + } + (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); +} + +/* + * These names are defined in . + */ +char *kmemnames[] = INITKMEMNAMES; + +void +domem() +{ + register struct kmembuckets *kp; + register struct kmemstats *ks; + register int i; + int size; + long totuse = 0, totfree = 0, totreq = 0; + struct kmemstats kmemstats[M_LAST]; + struct kmembuckets buckets[MINBUCKET + 16]; + + kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); + (void)printf("Memory statistics by bucket size\n"); + (void)printf( + " Size In Use Free Requests HighWater Couldfree\n"); + for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { + if (kp->kb_calls == 0) + continue; + size = 1 << i; + (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, + kp->kb_total - kp->kb_totalfree, + kp->kb_totalfree, kp->kb_calls, + kp->kb_highwat, kp->kb_couldfree); + totfree += size * kp->kb_totalfree; + } + + kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); + (void)printf("\nMemory statistics by type\n"); + (void)printf( +" Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); + for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { + if (ks->ks_calls == 0) + continue; + (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n", + kmemnames[i] ? kmemnames[i] : "undefined", + ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, + (ks->ks_maxused + 1023) / 1024, + (ks->ks_limit + 1023) / 1024, ks->ks_calls, + ks->ks_limblocks, ks->ks_mapblocks); + totuse += ks->ks_memuse; + totreq += ks->ks_calls; + } + (void)printf("\nMemory Totals: In Use Free Requests\n"); + (void)printf(" %7ldK %6ldK %8ld\n", + (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); +} + +/* + * kread reads something from the kernel, given its nlist index. + */ +void +kread(nlx, addr, size) + int nlx; + void *addr; + size_t size; +{ + char *sym; + + if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { + sym = nl[nlx].n_name; + if (*sym == '_') + ++sym; + (void)fprintf(stderr, + "vmstat: %s: symbol %s not defined\n", vmunix, sym); + exit(1); + } + if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { + sym = nl[nlx].n_name; + if (*sym == '_') + ++sym; + (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); + exit(1); + } +} + +void +usage() +{ + (void)fprintf(stderr, +#ifndef NEWVM + "usage: vmstat [-fimst] [-c count] [-M core] \ +[-N system] [-w wait] [disks]\n"); +#else + "usage: vmstat [-ims] [-c count] [-M core] \ +[-N system] [-w wait] [disks]\n"); +#endif + exit(1); +} diff --git a/usr/src/usr.bin/window/:tt b/usr/src/usr.bin/window/:tt new file mode 100644 index 0000000000..7ec4352d88 --- /dev/null +++ b/usr/src/usr.bin/window/:tt @@ -0,0 +1,11 @@ +./"init"16t"end"n2p ++/"move"16t"insline"16t"delline"16t"delchar"n4p ++/"write"16t"putc"16tn2p ++/"clreol"16t"clreos"16t"clear"n3p ++/"scroll_down"16t"scroll_up"16t"setscroll"n3p ++/"setinsert"16t"setmodes"n2p ++/"modes"8t"nmodes"8t"insert"8t"ninsert"n4b ++/"row"16t"col"16t"scrtop"16t"sclbot"n4D ++/"nrow"16t"ncol"16t"hasins"8t"avlmods"8t"wrap"8t"retain"n2D4b ++/"frame" +*./16b diff --git a/usr/src/usr.bin/window/:tty b/usr/src/usr.bin/window/:tty new file mode 100644 index 0000000000..2eb61efb4d --- /dev/null +++ b/usr/src/usr.bin/window/:tty @@ -0,0 +1,6 @@ +./"sgttyb:"8t"ispeed"8t"ospeed"8t"erase"8t"kill"8t"flags"n8tbbC8tC8tx ++/"tchars:"8t"intrc"8t"quitc"8t"startc"8t"stopc"8t"eofc"8t"brkc" ++/8tC8tC8tC8tC8tC8tC ++/"ltchars:suspc"8t"dsuspc"8t"rprntc"8t"flushc"8t"werasc"8t"lnextc" ++/8tC8tC8tC8tC8tC8tC2+ ++/"lmode"16t"ldisc"16t"fflags"nXDX diff --git a/usr/src/usr.bin/window/:var b/usr/src/usr.bin/window/:var new file mode 100644 index 0000000000..ff3de6b81b --- /dev/null +++ b/usr/src/usr.bin/window/:var @@ -0,0 +1,2 @@ +./"left"16t"right"16t"v_type"8t"v_val"npp4+b3+x +*(.+8)/"name: "S diff --git a/usr/src/usr.bin/window/:ww b/usr/src/usr.bin/window/:ww new file mode 100644 index 0000000000..0e99f0af75 --- /dev/null +++ b/usr/src/usr.bin/window/:ww @@ -0,0 +1,19 @@ +./"state"8t"oflags"nbb++ ++/"forw"16t"back"16t"index"8t"order"nppbb++ ++/"w.nr"16t"w.nc"nDD ++/"w.t"16t"w.b"16t"w.l"16t"w.r"nDDDD ++/"b.nr"16t"b.nc"nDD ++/"b.t"16t"b.b"16t"b.l"16t"b.r"nDDDD ++/"i.nr"16t"i.nc"nDD ++/"i.t"16t"i.b"16t"i.l"16t"i.r"nDDDD ++/"cur.r"16t"cur.c"nDD ++/"win"16t"buf"16t"fmap"16t"nvis"npppp ++/"wstate"8t"modes"8t"insert"8t"mapnl"8t"noupd"n5b ++/"unctrl"8t"nointr"8t"hascurs"8t"hasframe"n4b ++/"ispty"8t"stopped"8t"pty"16t"socket"16t"pid"nbb+3D ++/"ttyname"n11C+ ++/"ob"16t"obe"16t"obp"16t"obq"n4p ++/"center"8t"id"8t"label"nbb++p ++/"alt.nr"16t"alt.nc"nDD ++/"alt.t"16t"alt.b"16t"alt.l"16t"alt.r"nDDDD ++/t diff --git a/usr/src/usr.bin/window/Makefile b/usr/src/usr.bin/window/Makefile new file mode 100644 index 0000000000..d4cef4c150 --- /dev/null +++ b/usr/src/usr.bin/window/Makefile @@ -0,0 +1,21 @@ +# @(#)Makefile 5.7 (Berkeley) 5/11/90 + +PROG= window +CFLAGS+=-R +SRCS= char.c cmd.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c \ + context.c error.c lcmd.c lcmd1.c lcmd2.c main.c mloop.c parser1.c \ + parser2.c parser3.c parser4.c parser5.c scanner.c startup.c string.c \ + ttf100.c ttgeneric.c tth19.c tth29.c ttinit.c ttoutput.c tttermcap.c \ + tttvi925.c ttwyse60.c ttwyse75.c ttzapple.c ttzentec.c var.c win.c \ + wwadd.c wwalloc.c wwbox.c wwchild.c wwclose.c wwclreol.c wwclreos.c \ + wwcursor.c wwdata.c wwdelchar.c wwdelete.c wwdelline.c wwdump.c \ + wwend.c wwenviron.c wwerror.c wwflush.c wwframe.c wwgets.c wwinit.c \ + wwinschar.c wwinsline.c wwiomux.c wwlabel.c wwmisc.c wwmove.c \ + wwopen.c wwprintf.c wwpty.c wwputc.c wwputs.c wwredraw.c \ + wwredrawwin.c wwrint.c wwscroll.c wwsize.c wwspawn.c wwsuspend.c \ + wwtty.c wwunframe.c wwupdate.c wwwrite.c xx.c xxflush.c compress.c +MAN= window.0 +DPADD= ${LIBTERMCAP} +LDADD= -ltermcap + +.include diff --git a/usr/src/usr.bin/window/README b/usr/src/usr.bin/window/README new file mode 100644 index 0000000000..787c8adb50 --- /dev/null +++ b/usr/src/usr.bin/window/README @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)README 3.13 (Berkeley) 6/6/90 + */ + +Compilation notes: + + There is only one compiler option: + + BYTE_ORDER (used only in ww.h) + It should already be defined in machine/endian.h. + The code knows about BIG_ENDIAN, LITTLE_ENDIAN, and PDP_ENDIAN. + It only cares about byte order in words, so PDP_ENDIAN + is the same as LITTLE_ENDIAN. + + Ok, there's another one, STR_DEBUG. It turns on consistency checks + in the string allocator. It's been left on since performace doesn't + seem to suffer. There's an abort() somewhere when an inconsistency + is found. It hasn't happened in years. + + The file local.h contains locally tunable constants. + + The makefile used to be updated with mkmf; it has been changed +at various times to use cpp -M and, currently, mkdep. The only library +it needs is termcap. + + Window, as is, only runs on 4.3 machines. + + On 4.2 machines, at least these modifications must be done: + + delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ, + struct winsize + add to ww.h + typedef int fd_set; + #define FD_ZERO(s) (*(s) = 0) + #define FD_SET(b, s) (*(s) |= 1 << (b)) + #define FD_ISSET(b, s) (*(s) & 1 << (b)) + add to ww.h + #define sigmask(s) (1 << (s) - 1) + + +A few notes about the internals: + + The window package. Windows are opened by calling wwopen(). +Wwwrite() is the primitive for writing to windows. Wwputc(), wwputs(), +and wwprintf() are also supported. Some of the outputs to windows are +delayed. Wwupdate() updates the terminal to match the internal screen +buffer. Wwspawn() spawns a child process on the other end of a window, +with its environment tailored to the window. Visible windows are +doubly linked in the order of their overlap. Wwadd() inserts a window +into the list at a given place. Wwdelete() deletes it. Windows not in +the list are not visible, though wwwrite() still works. Window was +written before the days of X and Sunview, so some of the terminology +is not standard. + + Most functions return -1 on error. Wwopen() returns the null +pointer. An error number is saved in wwerrno. Wwerror() returns an +error string based on wwerrno suitable for printing. + + The terminal drivers perform all output to the physical terminal, +including special functions like character and line insertion and +deletion. The window package keeps a list of known terminals. At +initialization time, the terminal type is matched against the list to +find the right terminal driver to use. The last driver, the generic +driver, matches all terminals and uses the termcap database. The +interface between the window package the terminal driver is the `tt' +structure. It contains pointers to functions to perform special +functions and terminal output, as well as flags about the +characteristics of the terminal. Most of these ideas are borrowed +from the Maryland window package, which in turn is based on Goslin's +Emacs. + + The IO system is semi-synchronous. Terminal input is signal +driven, and everything else is done synchronously with a single +select(). It is roughly event-driven, though not in a clean way. + + Normally, in both conversation mode and command mode, window +sleeps in a select() in wwiomux() waiting for data from the +pseudo-terminals. At the same time, terminal input causes SIGIO which +is caught by wwrint(). The select() returns when at least one of the +pseudo-terminals becomes ready for reading. + + Wwrint() is the interrupt handler for tty input. It reads input +into a linear buffer accessed through four pointers: + + +-------+--------------+----------------+ + | empty | data | empty | + +-------+--------------+----------------+ + ^ ^ ^ ^ + | | | | + wwib wwibp wwibq wwibe + +Wwrint() appends characters at the end and increments wwibq (*wwibq++ += c), and characters are taken off the buffer at wwibp using the +wwgetc() and wwpeekc() macros. As is the convention in C, wwibq +and wwibe point to one position beyond the end. In addition, +wwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is +used by wwiomux() to interrupt the select() which would otherwise +resume after the interrupt. (Actually, I hear this is not true, +but the longjmp feature is used to avoid a race condition as well. +Anyway, it means I didn't have to depend on a feature in a +daily-changing kernel, but that's another story.) The macro +wwinterrupt() returns true if the input buffer is non-empty. +Wwupdate(), wwwrite(), and wwiomux() check this condition and will +return at the first convenient opportunity when it becomes true. +In the case of wwwrite(), the flag ww_nointr in the window structure +overrides this. This feature allows the user to interrupt lengthy +outputs safely. The structure of the input buffer is designed to +avoid race conditions without blocking interrupts. + + Actually, wwsetjmp and wwinterrupt() are part of a software +interrupt scheme used by the two interrupt catchers wwrint() and +wwchild(). Asserting the interrupt lets the synchronous parts of +the program know that there's an interesting asynchronous condition +(i.e., got a keyboard character, or a child process died) that they +might want to process before anything else. The synchronous routines +can check for this condition with wwinterrupt() or by arranging +that a longjmp() be done. + + Wwiomux() copies pseudo-terminal output into their corresponding +windows. Without anything to do, it blocks in a select(), waiting for +read ready on pseudo-terminals. Reads are done into per-window buffers +in the window structures. When there is at least one buffer non-empty, +wwiomux() finds the top most of these windows and writes it using +wwwrite(). Then the process is repeated. A non-blocking select() is +done after a wwwrite() to pick up any output that may have come in +during the write, which may take a long time. Specifically, we use +this to stop output or flush buffer when a pseudo-terminal tells us to +(we use pty packet mode). The select() blocks only when all of the +windows' buffers are empty. A wwupdate() is done prior to this, which +is the only time the screen is guaranteed to be completely up to date. +Wwiomux() loops until wwinterrupt() becomes true. + + The top level routine for all this is mloop(). In conversation +mode, it simply calls wwiomux(), which only returns when input is +available. The input buffer is then written to the pseudo-terminal of +the current window. If the escape character is found in the input, +command mode is entered. Otherwise, the process is repeated. In +command mode, control is transferred to docmd() which returns only when +conversation mode is reentered. Docmd() and other command processing +routines typically wait for input in a loop: + + while (wwpeekc() < 0) + wwiomux(); + +When the loop terminates, wwgetc() is used to read the input buffer. + + Output to the physical terminal is handled by the lowest level +routines of the window package, in the files ttoutput.c and tt.h. The +standard IO package is not used, to get better control over buffering +and to use non-blocking reads in wwrint(). The buffer size is set to +approximately one second of output time, based on the baudrate. + + The result of all this complexity is faster response time, +especially in output stopping and flushing. Wwwrite() checks +wwinterrupt() after every line. It also calls wwupdate() for each line +it writes. The output buffer is limited to one second of output time. +Thus, there is usually only a delay of one to two lines plus one second +after a ^C or ^S. Also, commands that produce lengthy output can be +aborted without actually showing all of it on the terminal. (Try the +'?' command followed by escape immediately.) diff --git a/usr/src/usr.bin/window/alias.h b/usr/src/usr.bin/window/alias.h new file mode 100644 index 0000000000..0adeb7bb9e --- /dev/null +++ b/usr/src/usr.bin/window/alias.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)alias.h 3.8 (Berkeley) 6/6/90 + */ + +#define alias var +#define a_name r_name +#define a_buf r_val.v_str +#define a_flags r_val.v_type + + /* a_flags bits, must not interfere with v_type values */ +#define A_INUSE 0x010 /* already inuse */ + +#define alias_set(n, s) var_setstr1(&alias_head, n, s) +#define alias_walk(f, a) var_walk1(alias_head, f, a) +#define alias_unset(n) var_unset1(&alias_head, n) +#define alias_lookup(n) (*var_lookup1(&alias_head, n)) + +struct var *alias_head; diff --git a/usr/src/usr.bin/window/char.c b/usr/src/usr.bin/window/char.c new file mode 100644 index 0000000000..df6e9914e9 --- /dev/null +++ b/usr/src/usr.bin/window/char.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)char.c 3.7 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "char.h" + +char _cmap[] = { + _C|_U, _C|_U, _C|_U, _C|_U, /* ^@ - ^C */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^D - ^G */ + _C, _C|_P, _C, _C|_U, /* ^H - ^K */ + _C|_U, _C, _C|_U, _C|_U, /* ^L - ^O */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^P - ^S */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^T - ^W */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^U - ^[ */ + _C|_U, _C|_U, _C|_U, _C|_U, /* ^\ - ^_ */ + + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _P|_U, + _P|_U, _P|_U, _P|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U, + _C|_U, _C|_U, _C|_U, _C|_U +}; + +char *_unctrl[] = { + "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", + "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O", + "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", + "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", + " ", "!", "\"", "#", "$", "%", "&", "'", + "(", ")", "*", "+", ",", "-", ".", "/", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", ":", ";", "<", "=", ">", "?", + "@", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "[", "\\", "]", "^", "_", + "`", "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "{", "|", "}", "~", "^?", + "\\200","\\201","\\202","\\203","\\204","\\205","\\206","\\207", + "\\210","\\211","\\212","\\213","\\214","\\215","\\216","\\217", + "\\220","\\221","\\222","\\223","\\224","\\225","\\226","\\227", + "\\230","\\231","\\232","\\233","\\234","\\235","\\236","\\237", + "\\240","\\241","\\242","\\243","\\244","\\245","\\246","\\247", + "\\250","\\251","\\252","\\253","\\254","\\255","\\256","\\257", + "\\260","\\261","\\262","\\263","\\264","\\265","\\266","\\267", + "\\270","\\271","\\272","\\273","\\274","\\275","\\276","\\277", + "\\300","\\301","\\302","\\303","\\304","\\305","\\306","\\307", + "\\310","\\311","\\312","\\313","\\314","\\315","\\316","\\317", + "\\320","\\321","\\322","\\323","\\324","\\325","\\326","\\327", + "\\330","\\331","\\332","\\333","\\334","\\335","\\336","\\337", + "\\340","\\341","\\342","\\343","\\344","\\345","\\346","\\347", + "\\350","\\351","\\352","\\353","\\354","\\355","\\356","\\357", + "\\360","\\361","\\362","\\363","\\364","\\365","\\366","\\367", + "\\370","\\371","\\372","\\373","\\374","\\375","\\376","\\377" +}; diff --git a/usr/src/usr.bin/window/char.h b/usr/src/usr.bin/window/char.h new file mode 100644 index 0000000000..255a71a6ff --- /dev/null +++ b/usr/src/usr.bin/window/char.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)char.h 3.9 (Berkeley) 6/6/90 + */ + +/* + * Macros and things to deal with control characters. + * + * Unctrl() is just like the standard function, except we don't want + * to include curses. + * Isctrl() returns true for all characters less than space and + * greater than or equal to delete. + * Isprt() is tab and all characters not isctrl(). It's used + * by wwwrite(). + * Isunctrl() includes all characters that should be expanded + * using unctrl() by wwwrite() if ww_unctrl is set. + */ + +extern char *_unctrl[]; +extern char _cmap[]; +#define ctrl(c) (c & 0x1f) +#define unctrl(c) (_unctrl[(unsigned char) (c)]) +#define _C 0x01 +#define _P 0x02 +#define _U 0x04 +#define isctrl(c) (_cmap[(unsigned char) (c)] & _C) +#define isprt(c) (_cmap[(unsigned char) (c)] & _P) +#define isunctrl(c) (_cmap[(unsigned char) (c)] & _U) diff --git a/usr/src/usr.bin/window/cmd.c b/usr/src/usr.bin/window/cmd.c new file mode 100644 index 0000000000..63630e6c13 --- /dev/null +++ b/usr/src/usr.bin/window/cmd.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd.c 3.40 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "char.h" + +docmd() +{ + register char c; + register struct ww *w; + char out = 0; + + while (!out && !quit) { + if ((c = wwgetc()) < 0) { + if (terse) + wwsetcursor(0, 0); + else { + wwputs("Command: ", cmdwin); + wwcurtowin(cmdwin); + } + do + wwiomux(); + while ((c = wwgetc()) < 0); + } + if (!terse) + wwputc('\n', cmdwin); + switch (c) { + default: + if (c != escapec) + break; + case 'h': case 'j': case 'k': case 'l': + case ctrl('y'): + case ctrl('e'): + case ctrl('u'): + case ctrl('d'): + case ctrl('b'): + case ctrl('f'): + case ctrl('s'): + case ctrl('q'): + case ctrl('['): + if (selwin == 0) { + error("No window."); + continue; + } + } + switch (c) { + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if ((w = window[c - '1']) == 0) { + error("%c: No such window.", c); + break; + } + setselwin(w); + if (checkproc(selwin) >= 0) + out = 1; + break; + case '%': + if ((w = getwin()) != 0) + setselwin(w); + break; + case ctrl('^'): + if (lastselwin != 0) { + setselwin(lastselwin); + if (checkproc(selwin) >= 0) + out = 1; + } else + error("No previous window."); + break; + case 'c': + if ((w = getwin()) != 0) + closewin(w); + break; + case 'w': + c_window(); + break; + case 'm': + if ((w = getwin()) != 0) + c_move(w); + break; + case 'M': + if ((w = getwin()) != 0) + movewin(w, w->ww_alt.t, w->ww_alt.l); + break; + case 's': + if ((w = getwin()) != 0) + c_size(w); + break; + case 'S': + if ((w = getwin()) != 0) + sizewin(w, w->ww_alt.nr, w->ww_alt.nc); + break; + case ':': + c_colon(); + break; + case 'h': + (void) wwwrite(selwin, "\b", 1); + break; + case 'j': + (void) wwwrite(selwin, "\n", 1); + break; + case 'k': + (void) wwwrite(selwin, "\033A", 2); + break; + case 'l': + (void) wwwrite(selwin, "\033C", 2); + break; + case ctrl('e'): + wwscroll(selwin, 1); + break; + case ctrl('y'): + wwscroll(selwin, -1); + break; + case ctrl('d'): + wwscroll(selwin, selwin->ww_w.nr / 2); + break; + case ctrl('u'): + wwscroll(selwin, - selwin->ww_w.nr / 2); + break; + case ctrl('f'): + wwscroll(selwin, selwin->ww_w.nr); + break; + case ctrl('b'): + wwscroll(selwin, - selwin->ww_w.nr); + break; + case ctrl('s'): + stopwin(selwin); + break; + case ctrl('q'): + startwin(selwin); + break; + case ctrl('l'): + wwredraw(); + break; + case '?': + c_help(); + break; + case ctrl('['): + if (checkproc(selwin) >= 0) + out = 1; + break; + case ctrl('z'): + wwsuspend(); + break; + case 'q': + c_quit(); + break; + /* debugging stuff */ + case '&': + if (debug) { + c_debug(); + break; + } + default: + if (c == escapec) { + if (checkproc(selwin) >= 0) { + (void) write(selwin->ww_pty, + &escapec, 1); + out = 1; + } + } else { + if (!terse) + wwbell(); + error("Type ? for help."); + } + } + } + if (!quit) + setcmd(0); +} + +struct ww * +getwin() +{ + register int c; + struct ww *w = 0; + + if (!terse) + wwputs("Which window? ", cmdwin); + wwcurtowin(cmdwin); + while ((c = wwgetc()) < 0) + wwiomux(); + if (debug && c == 'c') + w = cmdwin; + else if (debug && c == 'f') + w = framewin; + else if (debug && c == 'b') + w = boxwin; + else if (c >= '1' && c < NWINDOW + '1') + w = window[c - '1']; + else if (c == '+') + w = selwin; + else if (c == '-') + w = lastselwin; + if (w == 0) + wwbell(); + if (!terse) + wwputc('\n', cmdwin); + return w; +} + +checkproc(w) +struct ww *w; +{ + if (w->ww_state != WWS_HASPROC) { + error("No process in window."); + return -1; + } + return 0; +} + +setcmd(new) +char new; +{ + if (new && !incmd) { + if (!terse) + wwadd(cmdwin, &wwhead); + if (selwin != 0) + wwcursor(selwin, 1); + wwcurwin = 0; + } else if (!new && incmd) { + if (!terse) { + wwdelete(cmdwin); + reframe(); + } + if (selwin != 0) + wwcursor(selwin, 0); + wwcurwin = selwin; + } + incmd = new; +} + +setterse(new) +char new; +{ + if (incmd) + if (new && !terse) { + wwdelete(cmdwin); + reframe(); + } else if (!new && terse) + wwadd(cmdwin, &wwhead); + terse = new; +} + +/* + * Set the current window. + */ +setselwin(w) +struct ww *w; +{ + if (selwin == w) + return; + if (selwin != 0) + lastselwin = selwin; + if ((selwin = w) != 0) + front(selwin, 1); +} diff --git a/usr/src/usr.bin/window/cmd1.c b/usr/src/usr.bin/window/cmd1.c new file mode 100644 index 0000000000..8be41db3be --- /dev/null +++ b/usr/src/usr.bin/window/cmd1.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd1.c 3.36 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "char.h" + +c_window() +{ + int col, row, xcol, xrow; + int id; + + if ((id = findid()) < 0) + return; + if (!terse) + wwputs("New window (upper left corner): ", cmdwin); + col = 0; + row = 1; + wwadd(boxwin, framewin->ww_back); + for (;;) { + wwbox(boxwin, row - 1, col - 1, 3, 3); + wwsetcursor(row, col); + while (wwpeekc() < 0) + wwiomux(); + switch (getpos(&row, &col, row > 1, 0, + wwnrow - 1, wwncol - 1)) { + case 3: + wwunbox(boxwin); + wwdelete(boxwin); + return; + case 2: + wwunbox(boxwin); + break; + case 1: + wwunbox(boxwin); + case 0: + continue; + } + break; + } + if (!terse) + wwputs("\nNew window (lower right corner): ", cmdwin); + xcol = col; + xrow = row; + for (;;) { + wwbox(boxwin, row - 1, col - 1, + xrow - row + 3, xcol - col + 3); + wwsetcursor(xrow, xcol); + while (wwpeekc() < 0) + wwiomux(); + switch (getpos(&xrow, &xcol, row, col, wwnrow - 1, wwncol - 1)) + { + case 3: + wwunbox(boxwin); + wwdelete(boxwin); + return; + case 2: + wwunbox(boxwin); + break; + case 1: + wwunbox(boxwin); + case 0: + continue; + } + break; + } + wwdelete(boxwin); + if (!terse) + wwputc('\n', cmdwin); + wwcurtowin(cmdwin); + (void) openwin(id, row, col, xrow-row+1, xcol-col+1, default_nline, + (char *) 0, 1, 1, default_shellfile, default_shell); +} + +getpos(row, col, minrow, mincol, maxrow, maxcol) +register int *row, *col; +int minrow, mincol; +int maxrow, maxcol; +{ + static int scount; + int count; + char c; + int oldrow = *row, oldcol = *col; + + while ((c = wwgetc()) >= 0) { + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + scount = scount * 10 + c - '0'; + continue; + } + count = scount ? scount : 1; + scount = 0; + switch (c) { + case 'h': + if ((*col -= count) < mincol) + *col = mincol; + break; + case 'H': + *col = mincol; + break; + case 'l': + if ((*col += count) > maxcol) + *col = maxcol; + break; + case 'L': + *col = maxcol; + break; + case 'j': + if ((*row += count) > maxrow) + *row = maxrow; + break; + case 'J': + *row = maxrow; + break; + case 'k': + if ((*row -= count) < minrow) + *row = minrow; + break; + case 'K': + *row = minrow; + break; + case ctrl('['): + if (!terse) + wwputs("\nCancelled. ", cmdwin); + return 3; + case '\r': + return 2; + default: + if (!terse) + wwputs("\nType [hjklHJKL] to move, return to enter position, escape to cancel.", cmdwin); + wwbell(); + } + } + return oldrow != *row || oldcol != *col; +} diff --git a/usr/src/usr.bin/window/cmd2.c b/usr/src/usr.bin/window/cmd2.c new file mode 100644 index 0000000000..7ee9a7d098 --- /dev/null +++ b/usr/src/usr.bin/window/cmd2.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd2.c 3.40 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" + +char *help_shortcmd[] = { + "# Select window # and return to conversation mode", + "%# Select window # but stay in command mode", + "escape Return to conversation mode without changing window", + "^^ Return to conversation mode and change to previous window", + "c# Close window #", + "w Open a new window", + "m# Move window #", + "M# Move window # to its previous position", + "s# Change the size of window #", + "S# Change window # to its previous size", + "^Y Scroll up one line", + "^E Scroll down one line", + "^U Scroll up half a window", + "^D Scroll down half a window", + "^B Scroll up a full window", + "^F Scroll down a full window", + "h Move cursor left", + "j Move cursor down", + "k Move cursor up", + "l Move cursor right", + "^S Stop output in current window", + "^Q Restart output in current window", + "^L Redraw screen", + "^Z Suspend", + "q Quit", + ": Enter a long command", + 0 +}; +char *help_longcmd[] = { + ":alias name string ... Make `name' an alias for `string ...'", + ":alias Show all aliases", + ":close # ... Close windows", + ":close all Close all windows", + ":cursor modes Set the cursor modes", + ":echo # string ... Print `string ...' in window #", + ":escape c Set escape character to `c'", + ":foreground # flag Make # a foreground window, if `flag' is true", + ":label # string Set label of window # to `string'", + ":list List all open windows", + ":default_nline lines Set default window buffer size to `lines'", + ":default_shell string ...", + " Set default shell to `string ...'", + ":default_smooth flag Set default smooth scroll flag", + ":select # Select window #", + ":smooth # flag Set window # to smooth scroll mode", + ":source filename Execute commands in `filename'", + ":terse flag Set terse mode", + ":unalias name Undefine `name' as an alias", + ":unset variable Deallocate `variable'", + ":variable List all variables", + ":window [row col nrow ncol nline label pty frame mapnl keepopen smooth shell]", + " Open a window at `row', `col' of size `nrow', `ncol',", + " with `nline' lines in the buffer, and `label'", + ":write # string ... Write `string ...' to window # as input", + 0 +}; + +c_help() +{ + register struct ww *w; + + if ((w = openiwin(wwnrow - 3, "Help")) == 0) { + error("Can't open help window: %s.", wwerror()); + return; + } + wwprintf(w, "The escape character is %c.\n", escapec); + wwprintf(w, "(# represents one of the digits from 1 to 9.)\n\n"); + if (help_print(w, "Short commands", help_shortcmd) >= 0) + (void) help_print(w, "Long commands", help_longcmd); + closeiwin(w); +} + +help_print(w, name, list) +register struct ww *w; +char *name; +register char **list; +{ + wwprintf(w, "%s:\n\n", name); + while (*list) + switch (more(w, 0)) { + case 0: + wwputs(*list++, w); + wwputc('\n', w); + break; + case 1: + wwprintf(w, "%s: (continued)\n\n", name); + break; + case 2: + return -1; + } + return more(w, 1) == 2 ? -1 : 0; +} + +c_quit() +{ + char oldterse = terse; + + setterse(0); + wwputs("Really quit [yn]? ", cmdwin); + wwcurtowin(cmdwin); + while (wwpeekc() < 0) + wwiomux(); + if (wwgetc() == 'y') { + wwputs("Yes", cmdwin); + quit++; + } else + wwputc('\n', cmdwin); + setterse(!quit && oldterse); +} diff --git a/usr/src/usr.bin/window/cmd3.c b/usr/src/usr.bin/window/cmd3.c new file mode 100644 index 0000000000..3429718af5 --- /dev/null +++ b/usr/src/usr.bin/window/cmd3.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd3.c 3.18 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "string.h" + +setescape(esc) +register char *esc; +{ + if (*esc == '^') { + if (esc[1] != 0) + escapec = esc[1] & 0x1f; + else + escapec = '^'; + } else + escapec = *esc; +} + +setlabel(w, label) +register struct ww *w; +char *label; +{ + if (w->ww_label != 0) + str_free(w->ww_label); + if ((w->ww_label = str_cpy(label)) == 0) + return -1; + return 0; +} diff --git a/usr/src/usr.bin/window/cmd4.c b/usr/src/usr.bin/window/cmd4.c new file mode 100644 index 0000000000..e168506293 --- /dev/null +++ b/usr/src/usr.bin/window/cmd4.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd4.c 3.18 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" + +c_colon() +{ + char oldterse = terse; + char buf[512]; + + setterse(0); + wwputc(':', cmdwin); + wwgets(buf, wwncol - 3, cmdwin); + wwputc('\n', cmdwin); + wwcurtowin(cmdwin); + setterse(oldterse); + if (dolongcmd(buf, (struct value *)0, 0) < 0) + error("Out of memory."); +} diff --git a/usr/src/usr.bin/window/cmd5.c b/usr/src/usr.bin/window/cmd5.c new file mode 100644 index 0000000000..d0625bcfc3 --- /dev/null +++ b/usr/src/usr.bin/window/cmd5.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd5.c 3.18 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" + +/* + * Window movement. + */ + +c_move(w) +register struct ww *w; +{ + int col, row; + int mincol, minrow; + int maxcol, maxrow; + int curcol, currow; + + if (!terse) + wwputs("New window position: ", cmdwin); + col = w->ww_w.l; + row = w->ww_w.t; + wwadd(boxwin, framewin->ww_back); + for (;;) { + wwbox(boxwin, row - 1, col - 1, w->ww_w.nr + 2, w->ww_w.nc + 2); + getminmax(row, w->ww_w.nr, 1, wwnrow, + &currow, &minrow, &maxrow); + getminmax(col, w->ww_w.nc, 0, wwncol, + &curcol, &mincol, &maxcol); + wwsetcursor(currow, curcol); + while (wwpeekc() < 0) + wwiomux(); + switch (getpos(&row, &col, minrow, mincol, maxrow, maxcol)) { + case 3: + wwunbox(boxwin); + wwdelete(boxwin); + return; + case 2: + wwunbox(boxwin); + break; + case 1: + wwunbox(boxwin); + case 0: + continue; + } + break; + } + wwdelete(boxwin); + if (!terse) + wwputc('\n', cmdwin); + wwcurtowin(cmdwin); + movewin(w, row, col); +} + +movewin(w, row, col) +register struct ww *w; +{ + struct ww *back = w->ww_back; + + w->ww_alt.t = w->ww_w.t; + w->ww_alt.l = w->ww_w.l; + wwdelete(w); + wwmove(w, row, col); + wwadd(w, back); + reframe(); +} + +/* + * Weird stufff, don't ask. + */ +getminmax(x, n, a, b, curx, minx, maxx) +register x, n, a, b; +int *curx, *minx, *maxx; +{ + if (x < 0) + *curx = x + n - 1; + else + *curx = x; + + if (x <= a) + *minx = 1 - n; + else if (x <= b - n) + *minx = a; + else + *minx = b - n; + + if (x >= b - n) + *maxx = b - 1; + else if (x >= a) + *maxx = b - n; + else + *maxx = a; +} diff --git a/usr/src/usr.bin/window/cmd6.c b/usr/src/usr.bin/window/cmd6.c new file mode 100644 index 0000000000..db34782a4b --- /dev/null +++ b/usr/src/usr.bin/window/cmd6.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd6.c 3.17 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "string.h" +#include "char.h" + +/* + * Debugging commands. + */ + +c_debug() +{ + register struct ww *w; + + if (!terse) + wwputs("[m(smap) n(ns) o(os) s(string) v(nvis) w(win)]? ", cmdwin); + wwcurtowin(cmdwin); + while (wwpeekc() < 0) + wwiomux(); + if (!terse) + wwputc('\n', cmdwin); + switch (wwgetc()) { + case 'm': + wwdumpsmap(); + break; + case 'n': + wwdumpns(); + break; + case 'o': + wwdumpos(); + break; + case 's': + debug_str(); + break; + case 'v': + if ((w = getwin()) != 0) + wwdumpnvis(w); + break; + case 'w': + if ((w = getwin()) != 0) + wwdumpwin(w); + break; + default: + wwbell(); + } +} + +#ifdef STR_DEBUG +debug_str() +{ + register struct ww *w; + struct string *s; + + if ((w = openiwin(wwnrow - 3, "Allocated Strings")) == 0) { + error("Can't open string window: %s.", wwerror()); + return; + } + for (s = str_head.s_forw; s != &str_head; s = s->s_forw) { + if (more(w, 0) == 2) + goto out; + wwprintf(w, "(0x%x)\t\"%s\"\n", s->s_data, s->s_data); + } + waitnl(w); +out: + closeiwin(w); +} +#else +debug_str() +{ + error("No string debugging."); +} +#endif diff --git a/usr/src/usr.bin/window/cmd7.c b/usr/src/usr.bin/window/cmd7.c new file mode 100644 index 0000000000..7ffdbea5c2 --- /dev/null +++ b/usr/src/usr.bin/window/cmd7.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmd7.c 3.7 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" + +/* + * Window size. + */ + +c_size(w) +register struct ww *w; +{ + int col, row; + + if (!terse) + wwputs("New window size (lower right corner): ", cmdwin); + col = MIN(w->ww_w.r, wwncol) - 1; + row = MIN(w->ww_w.b, wwnrow) - 1; + wwadd(boxwin, framewin->ww_back); + for (;;) { + wwbox(boxwin, w->ww_w.t - 1, w->ww_w.l - 1, + row - w->ww_w.t + 3, col - w->ww_w.l + 3); + wwsetcursor(row, col); + while (wwpeekc() < 0) + wwiomux(); + switch (getpos(&row, &col, w->ww_w.t, w->ww_w.l, + wwnrow - 1, wwncol - 1)) { + case 3: + wwunbox(boxwin); + wwdelete(boxwin); + return; + case 2: + wwunbox(boxwin); + break; + case 1: + wwunbox(boxwin); + case 0: + continue; + } + break; + } + wwdelete(boxwin); + if (!terse) + wwputc('\n', cmdwin); + wwcurtowin(cmdwin); + sizewin(w, row - w->ww_w.t + 1, col - w->ww_w.l + 1); +} diff --git a/usr/src/usr.bin/window/compress.c b/usr/src/usr.bin/window/compress.c new file mode 100644 index 0000000000..ec831ae2c7 --- /dev/null +++ b/usr/src/usr.bin/window/compress.c @@ -0,0 +1,889 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)compress.c 3.6 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + + /* special */ +#include +int cc_trace = 0; +FILE *cc_trace_fp; + + /* tunable parameters */ + +int cc_reverse = 1; +int cc_sort = 0; +int cc_chop = 0; + +int cc_token_max = 8; /* <= TOKEN_MAX */ +int cc_token_min = 2; /* > tt.tt_put_token_cost */ +int cc_npass0 = 1; +int cc_npass1 = 1; + +int cc_bufsize = 1024 * 3; /* XXX, or 80 * 24 * 2 */ + +int cc_ntoken = 8192; + +#define cc_weight XXX +#ifndef cc_weight +int cc_weight = 0; +#endif + +#define TOKEN_MAX 16 + +struct cc { + char string[TOKEN_MAX]; + char length; + char flag; +#ifndef cc_weight + short weight; +#endif + long time; /* time last seen */ + short bcount; /* count in this buffer */ + short ccount; /* count in compression */ + short places; /* places in the buffer */ + short code; /* token code */ + struct cc *qforw, *qback; + struct cc *hforw, **hback; +}; + +short cc_thresholds[TOKEN_MAX + 1]; +#define thresh(length) (cc_thresholds[length]) +#define threshp(code, count, length) \ + ((code) >= 0 || (short) (count) >= cc_thresholds[length]) + +#ifndef cc_weight +short cc_wthresholds[TOKEN_MAX + 1]; +#define wthresh(length) (cc_wthresholds[length]) +#define wthreshp(weight, length) ((short) (weight) >= cc_wthresholds[length]) +#else +#define wthreshp(weight, length) (0) +#endif + +#ifndef cc_weight +short cc_wlimits[TOKEN_MAX + 1]; +#define wlimit(length) (cc_wlimits[length]) +#endif + +#define put_token_score(length) ((length) - tt.tt_put_token_cost) + +int cc_score_adjustments[TOKEN_MAX + 1][8]; /* XXX, 8 > max of cc_thresholds */ +#define score_adjust(score, p) \ + do { \ + int length = (p)->length; \ + int ccount = (p)->ccount; \ + if (threshp((p)->code, ccount, length) || \ + wthreshp((p)->weight, length)) /* XXX */ \ + (score) -= length - tt.tt_put_token_cost; \ + else \ + (score) += cc_score_adjustments[length][ccount]; \ + } while (0) + +int cc_initial_scores[TOKEN_MAX + 1][8]; /* XXX, 8 > max of cc_thresholds */ + +struct cc cc_q0a, cc_q0b, cc_q1a, cc_q1b; + +#define qinsert(p1, p2) \ + do { \ + register struct cc *forw = (p1)->qforw; \ + register struct cc *back = (p1)->qback; \ + back->qforw = forw; \ + forw->qback = back; \ + forw = (p2)->qforw; \ + (p1)->qforw = forw; \ + forw->qback = (p1); \ + (p2)->qforw = (p1); \ + (p1)->qback = (p2); \ + } while (0) + +#define qinsertq(q, p) \ + ((q)->qforw == (q) ? 0 : \ + ((q)->qback->qforw = (p)->qforw, \ + (p)->qforw->qback = (q)->qback, \ + (q)->qforw->qback = (p), \ + (p)->qforw = (q)->qforw, \ + (q)->qforw = (q), \ + (q)->qback = (q))) + +#define H (14) +#define HSIZE (1 << H) +#define hash(h, c) ((((h) >> H - 8 | (h) << 8) ^ (c)) & HSIZE - 1) + +char *cc_buffer; +struct cc **cc_output; /* the output array */ +short *cc_places[TOKEN_MAX + 1]; +short *cc_hashcodes; /* for computing hashcodes */ +struct cc **cc_htab; /* the hash table */ +struct cc **cc_tokens; /* holds all the active tokens */ +struct cc_undo { + struct cc **pos; + struct cc *val; +} *cc_undo; + +long cc_time, cc_time0; + +char *cc_tt_ob, *cc_tt_obe; + +ccinit() +{ + register i, j; + register struct cc *p; + + if (tt.tt_token_max > cc_token_max) + tt.tt_token_max = cc_token_max; + if (tt.tt_token_min < cc_token_min) + tt.tt_token_min = cc_token_min; + if (tt.tt_token_min > tt.tt_token_max) { + tt.tt_ntoken = 0; + return 0; + } + if (tt.tt_ntoken > cc_ntoken / 2) /* not likely */ + tt.tt_ntoken = cc_ntoken / 2; +#define C(x) (sizeof (x) / sizeof *(x)) + for (i = 0; i < C(cc_thresholds); i++) { + int h = i - tt.tt_put_token_cost; + if (h > 0) + cc_thresholds[i] = + (tt.tt_set_token_cost + 1 + h - 1) / h + 1; + else + cc_thresholds[i] = 0; + } + for (i = 0; i < C(cc_score_adjustments); i++) { + int t = cc_thresholds[i]; + for (j = 0; j < C(*cc_score_adjustments); j++) { + if (j >= t) + cc_score_adjustments[i][j] = + - (i - tt.tt_put_token_cost); + else if (j < t - 1) + cc_score_adjustments[i][j] = 0; + else + /* + * cost now is + * length * (ccount + 1) a + * cost before was + * set-token-cost + length + + * ccount * put-token-cost b + * the score adjustment is (b - a) + */ + cc_score_adjustments[i][j] = + tt.tt_set_token_cost + i + + j * tt.tt_put_token_cost - + i * (j + 1); + if (j >= t) + cc_initial_scores[i][j] = 0; + else + /* + * - (set-token-cost + + * (length - put-token-cost) - + * (length - put-token-cost) * ccount) + */ + cc_initial_scores[i][j] = + - (tt.tt_set_token_cost + + (i - tt.tt_put_token_cost) - + (i - tt.tt_put_token_cost) * j); + } + } +#ifndef cc_weight + for (i = 1; i < C(cc_wthresholds); i++) { + cc_wthresholds[i] = + ((tt.tt_set_token_cost + tt.tt_put_token_cost) / i + + i / 5 + 1) * + cc_weight + 1; + cc_wlimits[i] = cc_wthresholds[i] + cc_weight; + } +#endif +#undef C + if ((cc_output = (struct cc **) + malloc((unsigned) cc_bufsize * sizeof *cc_output)) == 0) + goto nomem; + if ((cc_hashcodes = (short *) + malloc((unsigned) cc_bufsize * sizeof *cc_hashcodes)) == 0) + goto nomem; + if ((cc_htab = (struct cc **) malloc(HSIZE * sizeof *cc_htab)) == 0) + goto nomem; + if ((cc_tokens = (struct cc **) + malloc((unsigned) + (cc_ntoken + tt.tt_token_max - tt.tt_token_min + 1) * + sizeof *cc_tokens)) == 0) + goto nomem; + if ((cc_undo = (struct cc_undo *) + malloc((unsigned) cc_bufsize * sizeof *cc_undo)) == 0) + goto nomem; + for (i = tt.tt_token_min; i <= tt.tt_token_max; i++) + if ((cc_places[i] = (short *) + malloc((unsigned) cc_bufsize * sizeof **cc_places)) == 0) + goto nomem; + cc_q0a.qforw = cc_q0a.qback = &cc_q0a; + cc_q0b.qforw = cc_q0b.qback = &cc_q0b; + cc_q1a.qforw = cc_q1a.qback = &cc_q1a; + cc_q1b.qforw = cc_q1b.qback = &cc_q1b; + if ((p = (struct cc *) malloc((unsigned) cc_ntoken * sizeof *p)) == 0) + goto nomem; + for (i = 0; i < tt.tt_ntoken; i++) { + p->code = i; + p->time = -1; + p->qback = cc_q0a.qback; + p->qforw = &cc_q0a; + p->qback->qforw = p; + cc_q0a.qback = p; + p++; + } + for (; i < cc_ntoken; i++) { + p->code = -1; + p->time = -1; + p->qback = cc_q1a.qback; + p->qforw = &cc_q1a; + p->qback->qforw = p; + cc_q1a.qback = p; + p++; + } + cc_tt_ob = tt_ob; + cc_tt_obe = tt_obe; + if ((cc_buffer = malloc((unsigned) cc_bufsize)) == 0) + goto nomem; + return 0; +nomem: + wwerrno = WWE_NOMEM; + return -1; +} + +ccstart() +{ + register struct cc *p; + int ccflush(); + + (*tt.tt_flush)(); + tt_obp = tt_ob = cc_buffer; + tt_obe = tt_ob + cc_bufsize; + tt.tt_flush = ccflush; + bzero((char *) cc_htab, HSIZE * sizeof *cc_htab); + for (p = cc_q0a.qforw; p != &cc_q0a; p = p->qforw) + p->hback = 0; + for (p = cc_q1a.qforw; p != &cc_q1a; p = p->qforw) + p->hback = 0; + if (cc_trace) + cc_trace_fp = fopen("window-trace", "a"); +} + +ccend() +{ + int ttflush(); + + (*tt.tt_flush)(); + tt_obp = tt_ob = cc_tt_ob; + tt_obe = cc_tt_obe; + tt.tt_flush = ttflush; + if (cc_trace_fp != NULL) { + (void) fclose(cc_trace_fp); + cc_trace_fp = NULL; + } +} + +ccflush() +{ + int bufsize = tt_obp - tt_ob; + int n; + int ttflush(); + + if (tt_ob != cc_buffer) + abort(); + if (cc_trace_fp != NULL) { + (void) fwrite(tt_ob, 1, bufsize, cc_trace_fp); + putc(-1, cc_trace_fp); + } + if (bufsize < tt.tt_token_min) { + ttflush(); + return; + } + tt_obp = tt_ob = cc_tt_ob; + tt_obe = cc_tt_obe; + tt.tt_flush = ttflush; + cc_time0 = cc_time; + cc_time += bufsize; + n = cc_sweep_phase(cc_buffer, bufsize, cc_tokens); + cc_compress_phase(cc_output, bufsize, cc_tokens, n); + cc_output_phase(cc_buffer, cc_output, bufsize); + ttflush(); + tt_obp = tt_ob = cc_buffer; + tt_obe = cc_buffer + cc_bufsize; + tt.tt_flush = ccflush; +} + +cc_sweep_phase(buffer, bufsize, tokens) + char *buffer; + struct cc **tokens; +{ + register struct cc **pp = tokens; + register i, n; +#ifdef STATS + int nn, ii; +#endif + +#ifdef STATS + if (verbose >= 0) + time_begin(); + if (verbose > 0) + printf("Sweep:"); +#endif + cc_sweep0(buffer, bufsize, tt.tt_token_min - 1); +#ifdef STATS + ntoken_stat = 0; + nn = 0; + ii = 0; +#endif + for (i = tt.tt_token_min; i <= tt.tt_token_max; i++) { +#ifdef STATS + if (verbose > 0) { + if (ii > 7) { + printf("\n "); + ii = 0; + } + ii++; + printf(" (%d", i); + (void) fflush(stdout); + } +#endif + n = cc_sweep(buffer, bufsize, pp, i); + pp += n; +#ifdef STATS + if (verbose > 0) { + if (--n > 0) { + printf(" %d", n); + nn += n; + } + putchar(')'); + } +#endif + } + qinsertq(&cc_q1b, &cc_q1a); +#ifdef STATS + if (verbose > 0) + printf("\n %d tokens, %d candidates\n", + ntoken_stat, nn); + if (verbose >= 0) + time_end(); +#endif + return pp - tokens; +} + +cc_sweep0(buffer, n, length) + char *buffer; +{ + register char *p; + register short *hc; + register i; + register short c; + register short pc = tt.tt_padc; + + /* n and length are at least 1 */ + p = buffer++; + hc = cc_hashcodes; + i = n; + do { + if ((*hc++ = *p++) == pc) + hc[-1] = -1; + } while (--i); + while (--length) { + p = buffer++; + hc = cc_hashcodes; + for (i = n--; --i;) { + if ((c = *p++) == pc || *hc < 0) + c = -1; + else + c = hash(*hc, c); + *hc++ = c; + } + } +} + +cc_sweep(buffer, bufsize, tokens, length) + char *buffer; + struct cc **tokens; + register length; +{ + register struct cc *p; + register char *cp; + register i; + short *hc; + short *places = cc_places[length]; + struct cc **pp = tokens; + short threshold = thresh(length); +#ifndef cc_weight + short wthreshold = wthresh(length); + short limit = wlimit(length); +#endif + int time; + short pc = tt.tt_padc; + + i = length - 1; + bufsize -= i; + cp = buffer + i; + hc = cc_hashcodes; + time = cc_time0; + for (i = 0; i < bufsize; i++, time++) { + struct cc **h; + + { + register short *hc1 = hc; + register short c = *cp++; + register short hh; + if ((hh = *hc1) < 0 || c == pc) { + *hc1++ = -1; + hc = hc1; + continue; + } + h = cc_htab + (*hc1++ = hash(hh, c)); + hc = hc1; + } + for (p = *h; p != 0; p = p->hforw) + if (p->length == (char) length) { + register char *p1 = p->string; + register char *p2 = cp - length; + register n = length; + do + if (*p1++ != *p2++) + goto fail; + while (--n); + break; + fail:; + } + if (p == 0) { + p = cc_q1a.qback; + if (p == &cc_q1a || + p->time >= cc_time0 && p->length == (char) length) + continue; + if (p->hback != 0) + if ((*p->hback = p->hforw) != 0) + p->hforw->hback = p->hback; + { + register char *p1 = p->string; + register char *p2 = cp - length; + register n = length; + do + *p1++ = *p2++; + while (--n); + } + p->length = length; +#ifndef cc_weight + p->weight = cc_weight; +#endif + p->time = time; + p->bcount = 1; + p->ccount = 0; + p->flag = 0; + if ((p->hforw = *h) != 0) + p->hforw->hback = &p->hforw; + *h = p; + p->hback = h; + qinsert(p, &cc_q1a); + places[i] = -1; + p->places = i; +#ifdef STATS + ntoken_stat++; +#endif + } else if (p->time < cc_time0) { +#ifndef cc_weight + if ((p->weight += p->time - time) < 0) + p->weight = cc_weight; + else if ((p->weight += cc_weight) > limit) + p->weight = limit; +#endif + p->time = time; + p->bcount = 1; + p->ccount = 0; + if (p->code >= 0) { + p->flag = 1; + *pp++ = p; + } else +#ifndef cc_weight + if (p->weight >= wthreshold) { + p->flag = 1; + *pp++ = p; + qinsert(p, &cc_q1b); + } else +#endif + { + p->flag = 0; + qinsert(p, &cc_q1a); + } + places[i] = -1; + p->places = i; +#ifdef STATS + ntoken_stat++; +#endif + } else if (p->time + length > time) { + /* + * overlapping token, don't count as two and + * don't update time, but do adjust weight to offset + * the difference + */ +#ifndef cc_weight + if (cc_weight != 0) { /* XXX */ + p->weight += time - p->time; + if (!p->flag && p->weight >= wthreshold) { + p->flag = 1; + *pp++ = p; + qinsert(p, &cc_q1b); + } + } +#endif + places[i] = p->places; + p->places = i; + } else { +#ifndef cc_weight + if ((p->weight += p->time - time) < 0) + p->weight = cc_weight; + else if ((p->weight += cc_weight) > limit) + p->weight = limit; +#endif + p->time = time; + p->bcount++; + if (!p->flag && + /* code must be < 0 if flag false here */ + (p->bcount >= threshold +#ifndef cc_weight + || p->weight >= wthreshold +#endif + )) { + p->flag = 1; + *pp++ = p; + qinsert(p, &cc_q1b); + } + places[i] = p->places; + p->places = i; + } + } + if ((i = pp - tokens) > 0) { + *pp = 0; + if (cc_reverse) + cc_sweep_reverse(tokens, places); + if (cc_sort && i > 1) { + int cc_token_compare(); + qsort((char *) tokens, i, sizeof *tokens, + cc_token_compare); + } + if (cc_chop) { + if ((i = i * cc_chop / 100) == 0) + i = 1; + tokens[i] = 0; + } + i++; + } + return i; +} + +cc_sweep_reverse(pp, places) + register struct cc **pp; + register short *places; +{ + register struct cc *p; + register short front, back, t; + + while ((p = *pp++) != 0) { + back = -1; + t = p->places; + /* the list is never empty */ + do { + front = places[t]; + places[t] = back; + back = t; + } while ((t = front) >= 0); + p->places = back; + } +} + +cc_compress_phase(output, bufsize, tokens, ntoken) + struct cc **output; + struct cc **tokens; +{ + register i; + + bzero((char *) output, bufsize * sizeof *output); + for (i = 0; i < cc_npass0; i++) + cc_compress_phase1(output, tokens, ntoken, 0); + for (i = 0; i < cc_npass1; i++) + cc_compress_phase1(output, tokens, ntoken, 1); + cc_compress_cleanup(output, bufsize); +} + +cc_compress_phase1(output, tokens, ntoken, flag) + register struct cc **output; + struct cc **tokens; +{ + register struct cc **pp; +#ifdef STATS + register int i = 0; + int nt = 0, cc = 0, nc = 0; +#endif + +#ifdef STATS + if (verbose >= 0) + time_begin(); + if (verbose > 0) + printf("Compress:"); +#endif + pp = tokens; + while (pp < tokens + ntoken) { +#ifdef STATS + if (verbose > 0) { + ntoken_stat = 0; + ccount_stat = 0; + ncover_stat = 0; + if (i > 2) { + printf("\n "); + i = 0; + } + i++; + printf(" (%d", (*pp)->length); + (void) fflush(stdout); + } +#endif + pp += cc_compress(output, pp, flag); +#ifdef STATS + if (verbose > 0) { + printf(" %dt %du %dc)", ntoken_stat, ccount_stat, + ncover_stat); + nt += ntoken_stat; + cc += ccount_stat; + nc += ncover_stat; + } +#endif + } +#ifdef STATS + if (verbose > 0) + printf("\n total: (%dt %du %dc)\n", nt, cc, nc); + if (verbose >= 0) + time_end(); +#endif +} + +cc_compress_cleanup(output, bufsize) + register struct cc **output; +{ + register struct cc **end; + + /* the previous output phase may have been interrupted */ + qinsertq(&cc_q0b, &cc_q0a); + for (end = output + bufsize; output < end;) { + register struct cc *p; + register length; + if ((p = *output) == 0) { + output++; + continue; + } + length = p->length; + if (!p->flag) { + } else if (p->code >= 0) { + qinsert(p, &cc_q0b); + p->flag = 0; + } else if (p->ccount == 0) { + *output = 0; + } else if (p->ccount >= thresh(length) +#ifndef cc_weight + || wthreshp(p->weight, length) +#endif + ) { + p->flag = 0; + } else { + p->ccount = 0; + *output = 0; + } + output += length; + } +} + +cc_compress(output, tokens, flag) + struct cc **output; + struct cc **tokens; + char flag; +{ + struct cc **pp = tokens; + register struct cc *p = *pp++; + int length = p->length; + int threshold = thresh(length); +#ifndef cc_weight + short wthreshold = wthresh(length); +#endif + short *places = cc_places[length]; + int *initial_scores = cc_initial_scores[length]; + int initial_score0 = put_token_score(length); + + do { + int score; + register struct cc_undo *undop; + int ccount; +#ifdef STATS + int ncover; +#endif + int i; + + ccount = p->ccount; + if ((short) ccount >= p->bcount) + continue; + if (p->code >= 0 || ccount >= threshold) + score = 0; +#ifndef cc_weight + else if (p->weight >= wthreshold) + /* allow one fewer match than normal */ + /* XXX, should adjust for ccount */ + score = - tt.tt_set_token_cost; +#endif + else + score = initial_scores[ccount]; + undop = cc_undo; +#ifdef STATS + ncover = 0; +#endif + for (i = p->places; i >= 0; i = places[i]) { + register struct cc **jp; + register struct cc *x; + register struct cc **ip = output + i; + register score0 = initial_score0; + struct cc **iip = ip + length; + struct cc_undo *undop1 = undop; + + if ((x = *(jp = ip)) != 0) + goto z; + while (--jp >= output) + if ((x = *jp) != 0) { + if (jp + x->length > ip) + goto z; + break; + } + jp = ip + 1; + while (jp < iip) { + if ((x = *jp) == 0) { + jp++; + continue; + } + z: + if (x == p) + goto undo; +#ifdef STATS + ncover++; +#endif + undop->pos = jp; + undop->val = x; + undop++; + *jp = 0; + x->ccount--; + score_adjust(score0, x); + if (score0 < 0 && flag) + goto undo; + jp += x->length; + } + undop->pos = ip; + undop->val = 0; + undop++; + *ip = p; + ccount++; + score += score0; + continue; + undo: + while (--undop >= undop1) + if (*undop->pos = x = undop->val) + x->ccount++; + undop++; + } + if (score > 0) { +#ifdef STATS + ccount_stat += ccount - p->ccount; + ntoken_stat++; + ncover_stat += ncover; +#endif + p->ccount = ccount; + } else { + register struct cc_undo *u = cc_undo; + while (--undop >= u) { + register struct cc *x; + if (*undop->pos = x = undop->val) + x->ccount++; + } + } + } while ((p = *pp++) != 0); + return pp - tokens; +} + +cc_output_phase(buffer, output, bufsize) + register char *buffer; + register struct cc **output; + register bufsize; +{ + register i; + register struct cc *p, *p1; + + for (i = 0; i < bufsize;) { + if ((p = output[i]) == 0) { + ttputc(buffer[i]); + i++; + } else if (p->code >= 0) { + if (--p->ccount == 0) + qinsert(p, &cc_q0a); + (*tt.tt_put_token)(p->code, p->string, p->length); + wwntokuse++; + wwntoksave += put_token_score(p->length); + i += p->length; + } else if ((p1 = cc_q0a.qback) != &cc_q0a) { + p->code = p1->code; + p1->code = -1; + qinsert(p1, &cc_q1a); + if (--p->ccount == 0) + qinsert(p, &cc_q0a); + else + qinsert(p, &cc_q0b); + (*tt.tt_set_token)(p->code, p->string, p->length); + wwntokdef++; + wwntoksave -= tt.tt_set_token_cost; + i += p->length; + } else { + p->ccount--; + ttwrite(p->string, p->length); + wwntokbad++; + i += p->length; + } + } + wwntokc += bufsize; +} + +cc_token_compare(p1, p2) + struct cc **p1, **p2; +{ + return (*p2)->bcount - (*p1)->bcount; +} diff --git a/usr/src/usr.bin/window/context.c b/usr/src/usr.bin/window/context.c new file mode 100644 index 0000000000..a1f7ea7546 --- /dev/null +++ b/usr/src/usr.bin/window/context.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)context.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "value.h" +#include "string.h" +#include "context.h" + +/* + * Context push/pop for nested command files. + */ + +char *malloc(); + +cx_alloc() +{ + register struct context *xp; + + if (cx.x_type != 0) { + xp = (struct context *) + malloc((unsigned) sizeof (struct context)); + if (xp == 0) + return -1; + *xp = cx; + cx.x_link = xp; + cx.x_type = 0; + } + cx.x_erred = 0; + cx.x_synerred = 0; + cx.x_abort = 0; + return 0; +} + +cx_free() +{ + struct context *xp; + + if ((xp = cx.x_link) != 0) { + cx = *xp; + free((char *)xp); + } else + cx.x_type = 0; +} + +cx_beginfile(filename) +char *filename; +{ + if (cx_alloc() < 0) + return -1; + cx.x_type = X_FILE; + if ((cx.x_filename = str_cpy(filename)) == 0) + goto bad; + cx.x_fp = fopen(filename, "r"); + if (cx.x_fp == 0) + goto bad; + cx.x_bol = 1; + cx.x_lineno = 0; + cx.x_errwin = 0; + cx.x_noerr = 0; + return 0; +bad: + if (cx.x_filename != 0) + str_free(cx.x_filename); + cx_free(); + return -1; +} + +cx_beginbuf(buf, arg, narg) +char *buf; +struct value *arg; +int narg; +{ + if (cx_alloc() < 0) + return -1; + cx.x_type = X_BUF; + cx.x_bufp = cx.x_buf = buf; + cx.x_arg = arg; + cx.x_narg = narg; + return 0; +} + +cx_end() +{ + switch (cx.x_type) { + case X_BUF: + break; + case X_FILE: + (void) fclose(cx.x_fp); + str_free(cx.x_filename); + break; + } + cx_free(); +} diff --git a/usr/src/usr.bin/window/context.h b/usr/src/usr.bin/window/context.h new file mode 100644 index 0000000000..7b7cce01b1 --- /dev/null +++ b/usr/src/usr.bin/window/context.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)context.h 3.11 (Berkeley) 6/6/90 + */ + +#include + +struct context { + struct context *x_link; /* nested contexts */ + char x_type; /* tag for union */ + union { + struct { /* input is a file */ + char *X_filename; /* input file name */ + FILE *X_fp; /* input stream */ + short X_lineno; /* current line number */ + char X_bol; /* at beginning of line */ + char X_noerr; /* don't report errors */ + struct ww *X_errwin; /* error window */ + } x_f; + struct { /* input is a buffer */ + char *X_buf; /* input buffer */ + char *X_bufp; /* current position in buf */ + struct value *X_arg; /* argument for alias */ + int X_narg; /* number of arguments */ + } x_b; + } x_un; + /* holding place for current token */ + int x_token; /* the token */ + struct value x_val; /* values associated with token */ + /* parser error flags */ + unsigned x_erred :1; /* had an error */ + unsigned x_synerred :1; /* had syntax error */ + unsigned x_abort :1; /* fatal error */ +}; +#define x_buf x_un.x_b.X_buf +#define x_bufp x_un.x_b.X_bufp +#define x_arg x_un.x_b.X_arg +#define x_narg x_un.x_b.X_narg +#define x_filename x_un.x_f.X_filename +#define x_fp x_un.x_f.X_fp +#define x_lineno x_un.x_f.X_lineno +#define x_bol x_un.x_f.X_bol +#define x_errwin x_un.x_f.X_errwin +#define x_noerr x_un.x_f.X_noerr + + /* x_type values, 0 is reserved */ +#define X_FILE 1 /* input is a file */ +#define X_BUF 2 /* input is a buffer */ + +struct context cx; /* the current context */ diff --git a/usr/src/usr.bin/window/defs.h b/usr/src/usr.bin/window/defs.h new file mode 100644 index 0000000000..4cb99e6d1d --- /dev/null +++ b/usr/src/usr.bin/window/defs.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 3.21 (Berkeley) 6/6/90 + */ + +#include "ww.h" +#include + +#define NWINDOW 9 + +struct timeval starttime; + +struct ww *window[NWINDOW]; /* the windows */ +struct ww *selwin; /* the selected window */ +struct ww *lastselwin; /* the last selected window */ +struct ww *cmdwin; /* the command window */ +struct ww *framewin; /* the window for framing */ +struct ww *boxwin; /* the window for the box */ +struct ww *fgwin; /* the last foreground window */ + +#define isfg(w) ((w)->ww_order <= fgwin->ww_order) + +char *default_shell[128]; /* default shell argv */ +char *default_shellfile; /* default shell program */ +int default_nline; /* default buffer size for new windows */ +int default_smooth; /* default "smooth" parameter */ +char escapec; /* the escape character */ + + /* flags */ +char quit; /* quit command issued */ +char terse; /* terse mode */ +char debug; /* debug mode */ +char incmd; /* in command mode */ + +struct ww *getwin(); +struct ww *openwin(); +struct ww *vtowin(); +struct ww *openiwin(); diff --git a/usr/src/usr.bin/window/error.c b/usr/src/usr.bin/window/error.c new file mode 100644 index 0000000000..422cc525bc --- /dev/null +++ b/usr/src/usr.bin/window/error.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)error.c 3.16 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "value.h" +#include "context.h" +#include "char.h" + +#define ERRLINES 10 /* number of lines for errwin */ + +/*VARARGS1*/ +error(fmt, a, b, c, d, e, f, g, h) +char *fmt; +{ + register struct context *x; + register struct ww *w; + + for (x = &cx; x != 0 && x->x_type != X_FILE; x = x->x_link) + ; + if (x == 0) { + if (terse) + wwbell(); + else { + wwprintf(cmdwin, fmt, a, b, c, d, e, f, g, h); + wwputs(" ", cmdwin); + } + return; + } + if (x->x_noerr) + return; + if ((w = x->x_errwin) == 0) { + char buf[512]; + + (void) sprintf(buf, "Errors from %s", x->x_filename); + if ((w = x->x_errwin = openiwin(ERRLINES, buf)) == 0) { + wwputs("Can't open error window. ", cmdwin); + x->x_noerr = 1; + return; + } + } + if (more(w, 0) == 2) { + x->x_noerr = 1; + return; + } + wwprintf(w, "line %d: ", x->x_lineno); + wwprintf(w, fmt, a, b, c, d, e, f, g, h); + wwputc('\n', w); +} + +err_end() +{ + if (cx.x_type == X_FILE && cx.x_errwin != 0) { + if (!cx.x_noerr) + waitnl(cx.x_errwin); + closeiwin(cx.x_errwin); + cx.x_errwin = 0; + } +} diff --git a/usr/src/usr.bin/window/lcmd.c b/usr/src/usr.bin/window/lcmd.c new file mode 100644 index 0000000000..2af6b8cb26 --- /dev/null +++ b/usr/src/usr.bin/window/lcmd.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)lcmd.c 3.34 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "value.h" +#include "lcmd.h" + +int l_alias(); +int l_close(); +int l_cursormodes(); +int l_debug(); +int l_def_nline(); +int l_def_shell(); +int l_def_smooth(); +int l_echo(); +int l_escape(); +int l_foreground(); +int l_iostat(); +int l_label(); +int l_list(); +int l_select(); +int l_smooth(); +int l_source(); +int l_terse(); +int l_time(); +int l_unalias(); +int l_unset(); +int l_variable(); +int l_window(); +int l_write(); + +extern struct lcmd_arg arg_alias[]; +extern struct lcmd_arg arg_cursormodes[]; +extern struct lcmd_arg arg_debug[]; +extern struct lcmd_arg arg_echo[]; +extern struct lcmd_arg arg_escape[]; +extern struct lcmd_arg arg_foreground[]; +extern struct lcmd_arg arg_label[]; +extern struct lcmd_arg arg_def_nline[]; +extern struct lcmd_arg arg_def_shell[]; +extern struct lcmd_arg arg_def_smooth[]; +extern struct lcmd_arg arg_close[]; +extern struct lcmd_arg arg_select[]; +extern struct lcmd_arg arg_smooth[]; +extern struct lcmd_arg arg_source[]; +extern struct lcmd_arg arg_terse[]; +extern struct lcmd_arg arg_time[]; +extern struct lcmd_arg arg_unalias[]; +extern struct lcmd_arg arg_unset[]; +extern struct lcmd_arg arg_window[]; +extern struct lcmd_arg arg_write[]; +struct lcmd_arg arg_null[1] = { { 0 } }; + +struct lcmd_tab lcmd_tab[] = { + "alias", 1, l_alias, arg_alias, + "close", 2, l_close, arg_close, + "cursormodes", 2, l_cursormodes, arg_cursormodes, + "debug", 1, l_debug, arg_debug, + "default_nlines", 9, l_def_nline, arg_def_nline, + "default_shell", 10, l_def_shell, arg_def_shell, + "default_smooth", 10, l_def_smooth, arg_def_smooth, + "echo", 2, l_echo, arg_echo, + "escape", 2, l_escape, arg_escape, + "foreground", 1, l_foreground, arg_foreground, + "iostat", 1, l_iostat, arg_null, + "label", 2, l_label, arg_label, + "list", 2, l_list, arg_null, + "nlines", 1, l_def_nline, arg_def_nline, + "select", 2, l_select, arg_select, + "shell", 2, l_def_shell, arg_def_shell, + "smooth", 2, l_smooth, arg_smooth, + "source", 2, l_source, arg_source, + "terse", 2, l_terse, arg_terse, + "time", 2, l_time, arg_time, + "unalias", 3, l_unalias, arg_unalias, + "unset", 3, l_unset, arg_unset, + "variable", 1, l_variable, arg_null, + "window", 2, l_window, arg_window, + "write", 2, l_write, arg_write, + 0 +}; + +struct lcmd_tab * +lcmd_lookup(name) +char *name; +{ + register struct lcmd_tab *p; + + for (p = lcmd_tab; p->lc_name != 0; p++) + if (str_match(name, p->lc_name, p->lc_minlen)) + return p; + return 0; +} + +dosource(filename) +char *filename; +{ + if (cx_beginfile(filename) < 0) + return -1; + p_start(); + err_end(); + cx_end(); + return 0; +} + +dolongcmd(buffer, arg, narg) +char *buffer; +struct value *arg; +int narg; +{ + if (cx_beginbuf(buffer, arg, narg) < 0) + return -1; + p_start(); + err_end(); + cx_end(); + return 0; +} diff --git a/usr/src/usr.bin/window/lcmd.h b/usr/src/usr.bin/window/lcmd.h new file mode 100644 index 0000000000..c20748624b --- /dev/null +++ b/usr/src/usr.bin/window/lcmd.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lcmd.h 3.9 (Berkeley) 6/6/90 + */ + +#define LCMD_NARG 20 /* maximum number of arguments */ + +struct lcmd_tab { + char *lc_name; + int lc_minlen; + int (*lc_func)(); + struct lcmd_arg *lc_arg; +}; + +struct lcmd_arg { + char *arg_name; + int arg_minlen; + int arg_flags; +}; + + /* arg_flags bits */ +#define ARG_TYPE 0x0f /* type of arg */ +#define ARG_ANY 0x00 /* any type */ +#define ARG_NUM 0x01 /* must be a number */ +#define ARG_STR 0x02 /* must be a string */ +#define ARG_LIST 0x10 /* this arg can be a list */ + +struct lcmd_tab *lcmd_lookup(); diff --git a/usr/src/usr.bin/window/lcmd1.c b/usr/src/usr.bin/window/lcmd1.c new file mode 100644 index 0000000000..f493cff876 --- /dev/null +++ b/usr/src/usr.bin/window/lcmd1.c @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)lcmd1.c 3.36 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "string.h" +#include "value.h" +#include "lcmd.h" +#include "var.h" + +struct lcmd_arg arg_window[] = { + { "row", 1, ARG_NUM }, + { "column", 1, ARG_NUM }, + { "nrows", 2, ARG_NUM }, + { "ncols", 2, ARG_NUM }, + { "nlines", 2, ARG_NUM }, + { "label", 1, ARG_STR }, + { "pty", 1, ARG_ANY }, + { "frame", 1, ARG_ANY }, + { "mapnl", 1, ARG_ANY }, + { "keepopen", 1, ARG_ANY }, + { "smooth", 1, ARG_ANY }, + { "shell", 1, ARG_STR|ARG_LIST }, + 0 +}; + +l_window(v, a) +struct value *v; +register struct value *a; +{ + struct ww *w; + int col, row, ncol, nrow, id, nline; + char *label; + char haspty, hasframe, mapnl, keepopen, smooth; + char *shf, **sh; + char *argv[sizeof default_shell / sizeof *default_shell]; + register char **pp; + + if ((id = findid()) < 0) + return; + row = a->v_type == V_ERR ? 1 : a->v_num; + a++; + col = a->v_type == V_ERR ? 0 : a->v_num; + a++; + nrow = a->v_type == V_ERR ? wwnrow - row : a->v_num; + a++; + ncol = a->v_type == V_ERR ? wwncol - col : a->v_num; + a++; + nline = a->v_type == V_ERR ? default_nline : a->v_num; + a++; + label = a->v_type == V_ERR ? 0 : a->v_str; + if ((haspty = vtobool(++a, 1, -1)) < 0) + return; + if ((hasframe = vtobool(++a, 1, -1)) < 0) + return; + if ((mapnl = vtobool(++a, !haspty, -1)) < 0) + return; + if ((keepopen = vtobool(++a, 0, -1)) < 0) + return; + if ((smooth = vtobool(++a, default_smooth, -1)) < 0) + return; + if ((++a)->v_type != V_ERR) { + for (pp = argv; a->v_type != V_ERR && + pp < &argv[sizeof argv/sizeof *argv-1]; pp++, a++) + *pp = a->v_str; + *pp = 0; + shf = *(sh = argv); + if (*sh = rindex(shf, '/')) + (*sh)++; + else + *sh = shf; + } else { + sh = default_shell; + shf = default_shellfile; + } + if ((w = openwin(id, row, col, nrow, ncol, nline, label, haspty, + hasframe, shf, sh)) == 0) + return; + w->ww_mapnl = mapnl; + w->ww_keepopen = keepopen; + w->ww_noupdate = !smooth; + v->v_type = V_NUM; + v->v_num = id + 1; +} + +struct lcmd_arg arg_def_nline[] = { + { "nlines", 1, ARG_NUM }, + 0 +}; + +l_def_nline(v, a) +register struct value *v, *a; +{ + v->v_num = default_nline; + v->v_type = V_NUM; + if (a->v_type != V_ERR) + default_nline = a->v_num; +} + +struct lcmd_arg arg_smooth[] = { + { "window", 1, ARG_NUM }, + { "flag", 1, ARG_ANY }, + 0 +}; + +l_smooth(v, a) +register struct value *v, *a; +{ + struct ww *w; + + v->v_type = V_NUM; + v->v_num = 0; + if ((w = vtowin(a++, selwin)) == 0) + return; + v->v_num = !w->ww_noupdate; + w->ww_noupdate = !vtobool(a, v->v_num, v->v_num); +} + +struct lcmd_arg arg_def_smooth[] = { + { "flag", 1, ARG_ANY }, + 0 +}; + +l_def_smooth(v, a) +register struct value *v, *a; +{ + v->v_type = V_NUM; + v->v_num = default_smooth; + default_smooth = vtobool(a, v->v_num, v->v_num); +} + +struct lcmd_arg arg_select[] = { + { "window", 1, ARG_NUM }, + 0 +}; + +l_select(v, a) +register struct value *v, *a; +{ + struct ww *w; + + v->v_type = V_NUM; + v->v_num = selwin ? selwin->ww_id + 1 : -1; + if (a->v_type == V_ERR) + return; + if ((w = vtowin(a, (struct ww *)0)) == 0) + return; + setselwin(w); +} + +struct lcmd_arg arg_debug[] = { + { "flag", 1, ARG_ANY }, + 0 +}; + +l_debug(v, a) +register struct value *v, *a; +{ + v->v_type = V_NUM; + v->v_num = debug; + debug = vtobool(a, debug, debug); +} + +struct lcmd_arg arg_escape[] = { + { "escapec", 1, ARG_STR }, + 0 +}; + +l_escape(v, a) +register struct value *v, *a; +{ + char buf[2]; + + buf[0] = escapec; + buf[1] = 0; + if ((v->v_str = str_cpy(buf)) == 0) { + error("Out of memory."); + return; + } + v->v_type = V_STR; + if (a->v_type != V_ERR) + setescape(a->v_str); +} + +struct lcmd_arg arg_label[] = { + { "window", 1, ARG_NUM }, + { "label", 1, ARG_STR }, + 0 +}; + +/*ARGSUSED*/ +l_label(v, a) +struct value *v; +register struct value *a; +{ + struct ww *w; + + if ((w = vtowin(a, selwin)) == 0) + return; + if ((++a)->v_type != V_ERR && setlabel(w, a->v_str) < 0) + error("Out of memory."); + reframe(); +} + +struct lcmd_arg arg_foreground[] = { + { "window", 1, ARG_NUM }, + { "flag", 1, ARG_ANY }, + 0 +}; + +l_foreground(v, a) +register struct value *v, *a; +{ + struct ww *w; + char flag; + + if ((w = vtowin(a, selwin)) == 0) + return; + v->v_type = V_NUM; + v->v_num = isfg(w); + flag = vtobool(++a, v->v_num, v->v_num); + if (flag == v->v_num) + return; + deletewin(w); + addwin(w, flag); + reframe(); +} + +struct lcmd_arg arg_terse[] = { + { "flag", 1, ARG_ANY }, + 0 +}; + +l_terse(v, a) +register struct value *v, *a; +{ + v->v_type = V_NUM; + v->v_num = terse; + setterse(vtobool(a, terse, terse)); +} + +struct lcmd_arg arg_source[] = { + { "filename", 1, ARG_STR }, + 0 +}; + +l_source(v, a) +register struct value *v, *a; +{ + v->v_type = V_NUM; + if (a->v_type != V_ERR && dosource(a->v_str) < 0) { + error("Can't open %s.", a->v_str); + v->v_num = -1; + } else + v->v_num = 0; +} + +struct lcmd_arg arg_write[] = { + { "window", 1, ARG_NUM }, + { "", 0, ARG_ANY|ARG_LIST }, + 0 +}; + +/*ARGSUSED*/ +l_write(v, a) +struct value *v; +register struct value *a; +{ + char buf[20]; + struct ww *w; + + if ((w = vtowin(a++, selwin)) == 0) + return; + while (a->v_type != V_ERR) { + if (a->v_type == V_NUM) { + (void) sprintf(buf, "%d", a->v_num); + (void) write(w->ww_pty, buf, strlen(buf)); + } else + (void) write(w->ww_pty, a->v_str, strlen(a->v_str)); + if ((++a)->v_type != V_ERR) + (void) write(w->ww_pty, " ", 1); + } +} + +struct lcmd_arg arg_close[] = { + { "window", 1, ARG_ANY|ARG_LIST }, + 0 +}; + +/*ARGSUSED*/ +l_close(v, a) +struct value *v; +register struct value *a; +{ + struct ww *w; + + if (a->v_type == V_STR && str_match(a->v_str, "all", 3)) + closewin((struct ww *)0); + else + for (; a->v_type != V_ERR; a++) + if ((w = vtowin(a, (struct ww *)0)) != 0) + closewin(w); +} + +struct lcmd_arg arg_cursormodes[] = { + { "modes", 1, ARG_NUM }, + 0 +}; + +l_cursormodes(v, a) +register struct value *v, *a; +{ + + v->v_type = V_NUM; + v->v_num = wwcursormodes; + if (a->v_type != V_ERR) + wwsetcursormodes(a->v_num); +} + +struct lcmd_arg arg_unset[] = { + { "variable", 1, ARG_ANY }, + 0 +}; + +l_unset(v, a) +register struct value *v, *a; +{ + v->v_type = V_NUM; + switch (a->v_type) { + case V_ERR: + v->v_num = -1; + return; + case V_NUM: + if ((a->v_str = str_itoa(a->v_num)) == 0) { + error("Out of memory."); + v->v_num = -1; + return; + } + a->v_type = V_STR; + break; + } + v->v_num = var_unset(a->v_str); +} + +struct ww * +vtowin(v, w) +register struct value *v; +struct ww *w; +{ + switch (v->v_type) { + case V_ERR: + if (w != 0) + return w; + error("No window specified."); + return 0; + case V_STR: + error("%s: No such window.", v->v_str); + return 0; + } + if (v->v_num < 1 || v->v_num > NWINDOW + || (w = window[v->v_num - 1]) == 0) { + error("%d: No such window.", v->v_num); + return 0; + } + return w; +} + +vtobool(v, def, err) +register struct value *v; +char def, err; +{ + switch (v->v_type) { + case V_NUM: + return v->v_num != 0; + case V_STR: + if (str_match(v->v_str, "true", 1) + || str_match(v->v_str, "on", 2) + || str_match(v->v_str, "yes", 1)) + return 1; + else if (str_match(v->v_str, "false", 1) + || str_match(v->v_str, "off", 2) + || str_match(v->v_str, "no", 1)) + return 0; + else { + error("%s: Illegal boolean value.", v->v_str); + return err; + } + /*NOTREACHED*/ + case V_ERR: + return def; + } + /*NOTREACHED*/ +} diff --git a/usr/src/usr.bin/window/lcmd2.c b/usr/src/usr.bin/window/lcmd2.c new file mode 100644 index 0000000000..4dd77a1290 --- /dev/null +++ b/usr/src/usr.bin/window/lcmd2.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)lcmd2.c 3.23 (Berkeley) 6/17/90"; +#endif /* not lint */ + +#include "defs.h" +#include "string.h" +#include "value.h" +#include "var.h" +#include "lcmd.h" +#include +#include "alias.h" + +/*ARGSUSED*/ +l_iostat(v, a) +struct value *v, *a; +{ + register struct ww *w; + + if ((w = openiwin(16, "IO Statistics")) == 0) { + error("Can't open statistics window: %s.", wwerror()); + return; + } + wwprintf(w, "ttflush\twrite\terror\tzero\tchar\n"); + wwprintf(w, "%d\t%d\t%d\t%d\t%d\n", + wwnflush, wwnwr, wwnwre, wwnwrz, wwnwrc); + wwprintf(w, "token\tuse\tbad\tsaving\ttotal\tbaud\n"); + wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d/%d (%.1f/%.1f)\n", + wwntokdef, wwntokuse, wwntokbad, wwntoksave, wwntokc, + wwntokc - wwntoksave ? + (int) ((float) wwbaud * wwntokc / + (wwntokc - wwntoksave)) : + wwbaud, + wwnwrc ? (int) ((float) wwbaud * (wwnwrc + wwntoksave) / + wwnwrc) : + wwbaud, + wwntokc - wwntoksave ? + (float) wwntokc / (wwntokc - wwntoksave) : 1.0, + wwnwrc ? (float) (wwnwrc + wwntoksave) / wwnwrc : 1.0); + wwprintf(w, "wwwrite\tattempt\tchar\n"); + wwprintf(w, "%d\t%d\t%d\n", + wwnwwr, wwnwwra, wwnwwrc); + wwprintf(w, "wwupdat\tline\tmiss\tscan\tclreol\tclreos\tmiss\tline\n"); + wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + wwnupdate, wwnupdline, wwnupdmiss, wwnupdscan, wwnupdclreol, + wwnupdclreos, wwnupdclreosmiss, wwnupdclreosline); + wwprintf(w, "select\terror\tzero\n"); + wwprintf(w, "%d\t%d\t%d\n", + wwnselect, wwnselecte, wwnselectz); + wwprintf(w, "read\terror\tzero\tchar\n"); + wwprintf(w, "%d\t%d\t%d\t%d\n", + wwnread, wwnreade, wwnreadz, wwnreadc); + wwprintf(w, "ptyread\terror\tzero\tcontrol\tdata\tchar\n"); + wwprintf(w, "%d\t%d\t%d\t%d\t%d\t%d\n", + wwnwread, wwnwreade, wwnwreadz, + wwnwreadp, wwnwreadd, wwnwreadc); + waitnl(w); + closeiwin(w); +} + +struct lcmd_arg arg_time[] = { + { "who", 1, ARG_STR }, + 0 +}; + +/*ARGSUSED*/ +l_time(v, a) +struct value *v; +register struct value *a; +{ + register struct ww *w; + struct rusage rusage; + struct timeval timeval; + char *strtime(); + + if ((w = openiwin(8, "Timing and Resource Usage")) == 0) { + error("Can't open time window: %s.", wwerror()); + return; + } + + (void) gettimeofday(&timeval, (struct timezone *)0); + timeval.tv_sec -= starttime.tv_sec; + if ((timeval.tv_usec -= starttime.tv_usec) < 0) { + timeval.tv_sec--; + timeval.tv_usec += 1000000; + } + (void) getrusage(a->v_type == V_STR + && str_match(a->v_str, "children", 1) + ? RUSAGE_CHILDREN : RUSAGE_SELF, &rusage); + + wwprintf(w, "%-15s %-15s %-15s\n", + "time", "utime", "stime"); + wwprintf(w, "%-15s ", strtime(&timeval)); + wwprintf(w, "%-15s ", strtime(&rusage.ru_utime)); + wwprintf(w, "%-15s\n", strtime(&rusage.ru_stime)); + wwprintf(w, "%-15s %-15s %-15s %-15s\n", + "maxrss", "ixrss", "idrss", "isrss"); + wwprintf(w, "%-15ld %-15ld %-15ld %-15ld\n", + rusage.ru_maxrss, rusage.ru_ixrss, + rusage.ru_idrss, rusage.ru_isrss); + wwprintf(w, "%-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n", + "minflt", "majflt", "nswap", "inblk", "oublk", + "msgsnd", "msgrcv", "nsigs", "nvcsw", "nivcsw"); + wwprintf(w, "%-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld %-7ld\n", + rusage.ru_minflt, rusage.ru_majflt, rusage.ru_nswap, + rusage.ru_inblock, rusage.ru_oublock, + rusage.ru_msgsnd, rusage.ru_msgrcv, rusage.ru_nsignals, + rusage.ru_nvcsw, rusage.ru_nivcsw); + + waitnl(w); + closeiwin(w); +} + +char * +strtime(t) +register struct timeval *t; +{ + char fill = 0; + static char buf[20]; + register char *p = buf; + + if (t->tv_sec > 60*60) { + (void) sprintf(p, "%ld:", t->tv_sec / (60*60)); + while (*p++) + ; + p--; + t->tv_sec %= 60*60; + fill++; + } + if (t->tv_sec > 60) { + (void) sprintf(p, fill ? "%02ld:" : "%ld:", t->tv_sec / 60); + while (*p++) + ; + p--; + t->tv_sec %= 60; + fill++; + } + (void) sprintf(p, fill ? "%02ld.%02d" : "%ld.%02ld", + t->tv_sec, t->tv_usec / 10000); + return buf; +} + +/*ARGSUSED*/ +l_list(v, a) +struct value *v, *a; +{ + register struct ww *w, *wp; + register i; + int n; + + for (n = 0, i = 0; i < NWINDOW; i++) + if (window[i] != 0) + n++; + if (n == 0) { + error("No windows."); + return; + } + if ((w = openiwin(n + 2, "Windows")) == 0) { + error("Can't open listing window: %s.", wwerror()); + return; + } + for (i = 0; i < NWINDOW; i++) { + if ((wp = window[i]) == 0) + continue; + wwprintf(w, "%c %c %-13s %-.*s\n", + wp == selwin ? '+' : (wp == lastselwin ? '-' : ' '), + i + '1', + wp->ww_state == WWS_HASPROC ? "" : "(No process)", + wwncol - 20, + wp->ww_label ? wp->ww_label : "(No label)"); + } + waitnl(w); + closeiwin(w); +} + +/*ARGSUSED*/ +l_variable(v, a) +struct value *v, *a; +{ + register struct ww *w; + int printvar(); + + if ((w = openiwin(wwnrow - 3, "Variables")) == 0) { + error("Can't open variable window: %s.", wwerror()); + return; + } + if (var_walk(printvar, (int)w) >= 0) + waitnl(w); + closeiwin(w); +} + +printvar(w, r) +register struct ww *w; +register struct var *r; +{ + if (more(w, 0) == 2) + return -1; + wwprintf(w, "%16s ", r->r_name); + switch (r->r_val.v_type) { + case V_STR: + wwprintf(w, "%s\n", r->r_val.v_str); + break; + case V_NUM: + wwprintf(w, "%d\n", r->r_val.v_num); + break; + case V_ERR: + wwprintf(w, "ERROR\n"); + break; + } + return 0; +} + +struct lcmd_arg arg_def_shell[] = { + { "", 0, ARG_ANY|ARG_LIST }, + 0 +}; + +l_def_shell(v, a) + struct value *v, *a; +{ + register char **pp; + register struct value *vp; + + if (a->v_type == V_ERR) { + if ((v->v_str = str_cpy(default_shellfile)) != 0) + v->v_type = V_STR; + return; + } + if (v->v_str = default_shellfile) { + v->v_type = V_STR; + for (pp = default_shell + 1; *pp; pp++) { + str_free(*pp); + *pp = 0; + } + } + for (pp = default_shell, vp = a; + vp->v_type != V_ERR && + pp < &default_shell[sizeof default_shell/sizeof *default_shell-1]; + pp++, vp++) + if ((*pp = vp->v_type == V_STR ? + str_cpy(vp->v_str) : str_itoa(vp->v_num)) == 0) { + /* just leave default_shell[] the way it is */ + p_memerror(); + break; + } + if (default_shellfile = *default_shell) + if (*default_shell = rindex(default_shellfile, '/')) + (*default_shell)++; + else + *default_shell = default_shellfile; +} + +struct lcmd_arg arg_alias[] = { + { "", 0, ARG_STR }, + { "", 0, ARG_STR|ARG_LIST }, + 0 +}; + +l_alias(v, a) + struct value *v, *a; +{ + if (a->v_type == V_ERR) { + register struct ww *w; + int printalias(); + + if ((w = openiwin(wwnrow - 3, "Aliases")) == 0) { + error("Can't open alias window: %s.", wwerror()); + return; + } + if (alias_walk(printalias, (int)w) >= 0) + waitnl(w); + closeiwin(w); + } else { + register struct alias *ap = 0; + + if (ap = alias_lookup(a->v_str)) { + if ((v->v_str = str_cpy(ap->a_buf)) == 0) { + p_memerror(); + return; + } + v->v_type = V_STR; + } + if (a[1].v_type == V_STR) { + register struct value *vp; + register char *p, *q; + char *str; + register n; + + for (n = 0, vp = a + 1; vp->v_type != V_ERR; vp++, n++) + for (p = vp->v_str; *p; p++, n++) + ; + if ((str = str_alloc(n)) == 0) { + p_memerror(); + return; + } + for (q = str, vp = a + 1; vp->v_type != V_ERR; + vp++, q[-1] = ' ') + for (p = vp->v_str; *q++ = *p++;) + ; + q[-1] = 0; + if ((ap = alias_set(a[0].v_str, (char *)0)) == 0) { + p_memerror(); + str_free(str); + return; + } + ap->a_buf = str; + } + } +} + +printalias(w, a) +register struct ww *w; +register struct alias *a; +{ + if (more(w, 0) == 2) + return -1; + wwprintf(w, "%16s %s\n", a->a_name, a->a_buf); + return 0; +} + +struct lcmd_arg arg_unalias[] = { + { "alias", 1, ARG_STR }, + 0 +}; + +l_unalias(v, a) +struct value *v, *a; +{ + if (a->v_type == ARG_STR) + v->v_num = alias_unset(a->v_str); + v->v_type = V_NUM; +} + +struct lcmd_arg arg_echo[] = { + { "window", 1, ARG_NUM }, + { "", 0, ARG_ANY|ARG_LIST }, + 0 +}; + +/*ARGSUSED*/ +l_echo(v, a) +struct value *v; +register struct value *a; +{ + char buf[20]; + struct ww *w; + + if ((w = vtowin(a++, selwin)) == 0) + return; + while (a->v_type != V_ERR) { + if (a->v_type == V_NUM) { + (void) sprintf(buf, "%d", a->v_num); + (void) wwwrite(w, buf, strlen(buf)); + } else + (void) wwwrite(w, a->v_str, strlen(a->v_str)); + if ((++a)->v_type != V_ERR) + (void) wwwrite(w, " ", 1); + } + (void) wwwrite(w, "\r\n", 2); +} diff --git a/usr/src/usr.bin/window/local.h b/usr/src/usr.bin/window/local.h new file mode 100644 index 0000000000..ef828cca73 --- /dev/null +++ b/usr/src/usr.bin/window/local.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)local.h 3.11 (Berkeley) 6/6/90 + */ + +/* + * Things of local interest. + */ + +#define RUNCOM ".windowrc" +#define ESCAPEC ctrl('p') +#define NLINE 48 /* default text buffer size */ diff --git a/usr/src/usr.bin/window/main.c b/usr/src/usr.bin/window/main.c new file mode 100644 index 0000000000..2dc0714903 --- /dev/null +++ b/usr/src/usr.bin/window/main.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 3.42 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "defs.h" +#include +#include +#include "string.h" +#include "char.h" +#include "local.h" + +#define next(a) (*++*(a) ? *(a) : (*++(a) ? *(a) : (char *)usage())) + +/*ARGSUSED*/ +main(argc, argv) +char **argv; +{ + register char *p; + char fflag = 0; + char dflag = 0; + char xflag = 0; + char *cmd = 0; + char tflag = 0; + + escapec = ESCAPEC; + if (p = rindex(*argv, '/')) + p++; + else + p = *argv; + debug = strcmp(p, "a.out") == 0; + while (*++argv) { + if (**argv == '-') { + switch (*++*argv) { + case 'f': + fflag++; + break; + case 'c': + if (cmd != 0) { + (void) fprintf(stderr, + "Only one -c allowed.\n"); + (void) usage(); + } + cmd = next(argv); + break; + case 'e': + setescape(next(argv)); + break; + case 't': + tflag++; + break; + case 'd': + dflag++; + break; + case 'D': + debug = !debug; + break; + case 'x': + xflag++; + break; + default: + (void) usage(); + } + } else + (void) usage(); + } + if ((p = getenv("SHELL")) == 0) + p = _PATH_BSHELL; + if ((default_shellfile = str_cpy(p)) == 0) { + (void) fprintf(stderr, "Out of memory.\n"); + exit(1); + } + if (p = rindex(default_shellfile, '/')) + p++; + else + p = default_shellfile; + default_shell[0] = p; + default_shell[1] = 0; + default_nline = NLINE; + default_smooth = 1; + (void) gettimeofday(&starttime, (struct timezone *)0); + if (wwinit() < 0) { + (void) fprintf(stderr, "%s.\n", wwerror()); + exit(1); + } + +#ifdef OLD_TTY + if (debug) + wwnewtty.ww_tchars.t_quitc = wwoldtty.ww_tchars.t_quitc; + if (xflag) { + wwnewtty.ww_tchars.t_stopc = wwoldtty.ww_tchars.t_stopc; + wwnewtty.ww_tchars.t_startc = wwoldtty.ww_tchars.t_startc; + } +#else + if (debug) { + wwnewtty.ww_termios.c_cc[VQUIT] = + wwoldtty.ww_termios.c_cc[VQUIT]; + wwnewtty.ww_termios.c_lflag |= ISIG; + } + if (xflag) { + wwnewtty.ww_termios.c_cc[VSTOP] = + wwoldtty.ww_termios.c_cc[VSTOP]; + wwnewtty.ww_termios.c_cc[VSTART] = + wwoldtty.ww_termios.c_cc[VSTART]; + wwnewtty.ww_termios.c_iflag |= IXON; + } +#endif + if (debug || xflag) + (void) wwsettty(0, &wwnewtty); + + if ((cmdwin = wwopen(wwbaud > 2400 ? WWO_REVERSE : 0, 1, wwncol, + 0, 0, 0)) == 0) { + wwflush(); + (void) fprintf(stderr, "%s.\r\n", wwerror()); + goto bad; + } + cmdwin->ww_mapnl = 1; + cmdwin->ww_nointr = 1; + cmdwin->ww_noupdate = 1; + cmdwin->ww_unctrl = 1; + if ((framewin = wwopen(WWO_GLASS|WWO_FRAME, wwnrow, wwncol, 0, 0, 0)) + == 0) { + wwflush(); + (void) fprintf(stderr, "%s.\r\n", wwerror()); + goto bad; + } + wwadd(framewin, &wwhead); + if ((boxwin = wwopen(WWO_GLASS, wwnrow, wwncol, 0, 0, 0)) == 0) { + wwflush(); + (void) fprintf(stderr, "%s.\r\n", wwerror()); + goto bad; + } + fgwin = framewin; + + wwupdate(); + wwflush(); + setvars(); + + setterse(tflag); + setcmd(1); + if (cmd != 0) + (void) dolongcmd(cmd, (struct value *)0, 0); + if (!fflag) + if (dflag || doconfig() < 0) + dodefault(); + if (selwin != 0) + setcmd(0); + + mloop(); + +bad: + wwend(); + return 0; +} + +usage() +{ + (void) fprintf(stderr, "Usage: window [-e escape-char] [-c command] [-t] [-f] [-d]\n"); + exit(1); + return 0; /* for lint */ +} diff --git a/usr/src/usr.bin/window/mloop.c b/usr/src/usr.bin/window/mloop.c new file mode 100644 index 0000000000..c0fd47987b --- /dev/null +++ b/usr/src/usr.bin/window/mloop.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)mloop.c 3.17 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" + +mloop() +{ + while (!quit) { + if (incmd) { + docmd(); + } else if (wwcurwin->ww_state != WWS_HASPROC) { + if (!wwcurwin->ww_keepopen) + closewin(wwcurwin); + setcmd(1); + if (wwpeekc() == escapec) + (void) wwgetc(); + error("Process died."); + } else { + register struct ww *w = wwcurwin; + register char *p; + register n; + + if (wwibp >= wwibq) + wwiomux(); + for (p = wwibp; p < wwibq && *p != escapec; + p++) + ; + if ((n = p - wwibp) > 0) { + if (!w->ww_ispty && w->ww_stopped) + startwin(w); + (void) write(w->ww_pty, wwibp, n); + wwibp = p; + } + if (wwpeekc() == escapec) { + (void) wwgetc(); + setcmd(1); + } + } + } +} diff --git a/usr/src/usr.bin/window/parser.h b/usr/src/usr.bin/window/parser.h new file mode 100644 index 0000000000..3fb5379d01 --- /dev/null +++ b/usr/src/usr.bin/window/parser.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)parser.h 3.9 (Berkeley) 6/6/90 + */ + +#include "value.h" +#include "context.h" +#include "token.h" +#include "string.h" + +#define p_erred() (cx.x_erred) +#define p_synerred() (cx.x_synerred) +#define p_clearerr() (cx.x_erred = cx.x_synerred = 0) +#define p_abort() (cx.x_abort) diff --git a/usr/src/usr.bin/window/parser1.c b/usr/src/usr.bin/window/parser1.c new file mode 100644 index 0000000000..4a18ecc131 --- /dev/null +++ b/usr/src/usr.bin/window/parser1.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parser1.c 3.22 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "parser.h" + +p_start() +{ + char flag = 1; + + (void) s_gettok(); + for (;;) { + p_statementlist(flag); + if (token == T_EOF || p_abort()) + break; + flag = 0; + p_synerror(); + while (token != T_EOL && token != T_EOF) { + if (token == T_STR) + str_free(token_str); + (void) s_gettok(); + } + if (token == T_EOL) + (void) s_gettok(); + p_clearerr(); + } +} + +p_statementlist(flag) +char flag; +{ + for (; p_statement(flag) >= 0; p_clearerr()) + ; +} + +p_statement(flag) +char flag; +{ + switch (token) { + case T_EOL: + (void) s_gettok(); + return 0; + case T_IF: + return p_if(flag); + default: + return p_expression(flag); + } +} + +p_if(flag) +char flag; +{ + struct value t; + char true = 0; + +top: + (void) s_gettok(); + + if (p_expr(&t, flag) < 0) { + p_synerror(); + return -1; + } + switch (t.v_type) { + case V_NUM: + true = !true && t.v_num != 0; + break; + case V_STR: + p_error("if: Numeric value required."); + str_free(t.v_str); + case V_ERR: + flag = 0; + break; + } + + if (token != T_THEN) { + p_synerror(); + return -1; + } + + (void) s_gettok(); + p_statementlist(flag && true); + if (p_erred()) + return -1; + + if (token == T_ELSIF) + goto top; + + if (token == T_ELSE) { + (void) s_gettok(); + p_statementlist(flag && !true); + if (p_erred()) + return -1; + } + + if (token == T_ENDIF) { + (void) s_gettok(); + return 0; + } + + p_synerror(); + return -1; +} + +p_expression(flag) +char flag; +{ + struct value t; + char *cmd; + int p_function(), p_assign(); + + switch (token) { + case T_NUM: + t.v_type = V_NUM; + t.v_num = token_num; + (void) s_gettok(); + break; + case T_STR: + t.v_type = V_STR; + t.v_str = token_str; + (void) s_gettok(); + break; + default: + if (p_expr(&t, flag) < 0) + return -1; + if (token == T_EOF) { + val_free(t); + return 0; + } + } + if (token != T_ASSIGN && p_convstr(&t) < 0) + return -1; + cmd = t.v_type == V_STR ? t.v_str : 0; + if ((*(token == T_ASSIGN ? p_assign : p_function))(cmd, &t, flag) < 0) { + if (cmd) + str_free(cmd); + return -1; + } + if (cmd) + str_free(cmd); + val_free(t); + if (token == T_EOL) + (void) s_gettok(); + else if (token != T_EOF) { + p_synerror(); + return -1; + } + return 0; +} + +p_convstr(v) +register struct value *v; +{ + if (v->v_type != V_NUM) + return 0; + if ((v->v_str = str_itoa(v->v_num)) == 0) { + p_memerror(); + v->v_type = V_ERR; + return -1; + } + v->v_type = V_STR; + return 0; +} + +p_synerror() +{ + if (!cx.x_synerred) { + cx.x_synerred = cx.x_erred = 1; + error("Syntax error."); + } +} + +/*VARARGS1*/ +p_error(msg, a, b, c) +char *msg; +{ + if (!cx.x_erred) { + cx.x_erred = 1; + error(msg, a, b, c); + } +} + +p_memerror() +{ + cx.x_erred = cx.x_abort = 1; + error("Out of memory."); +} diff --git a/usr/src/usr.bin/window/parser2.c b/usr/src/usr.bin/window/parser2.c new file mode 100644 index 0000000000..6f7ff41986 --- /dev/null +++ b/usr/src/usr.bin/window/parser2.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parser2.c 3.14 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "parser.h" +#include "var.h" +#include "lcmd.h" +#include "alias.h" + +/* + * name == 0 means we don't have a function name but + * want to parse the arguments anyway. flag == 0 in this case. + */ +p_function(name, v, flag) +char *name; +register struct value *v; +{ + struct value t; + register struct lcmd_tab *c = 0; + register struct alias *a = 0; + register struct lcmd_arg *ap; /* this arg */ + struct lcmd_arg *lp = 0; /* list arg */ + register i; + struct value av[LCMD_NARG + 1]; + register struct value *vp; + + if (name != 0) + if (c = lcmd_lookup(name)) + name = c->lc_name; + else if (a = alias_lookup(name)) + name = a->a_name; + else { + p_error("%s: No such command or alias.", name); + flag = 0; + } + + for (vp = av; vp < &av[LCMD_NARG + 1]; vp++) + vp->v_type = V_ERR; + + if (token == T_LP) + (void) s_gettok(); + i = 0; + for (;;) { + ap = 0; + vp = 0; + if (token == T_COMMA) /* null argument */ + t.v_type = V_ERR; + else { + if (p_expr0(&t, flag) < 0) + break; + if (t.v_type == V_ERR) + flag = 0; + } + if (token != T_ASSIGN) { + if (i >= LCMD_NARG || + c != 0 && (ap = lp) == 0 && + (ap = c->lc_arg + i)->arg_name == 0) { + p_error("%s: Too many arguments.", name); + flag = 0; + } else + vp = &av[i++]; + } else { + char *tmp; + if (p_convstr(&t) < 0) + goto abort; + tmp = t.v_type == V_STR ? t.v_str : 0; + (void) s_gettok(); + if (p_expr(&t, flag) < 0) { + if (tmp) + str_free(tmp); + p_synerror(); + goto abort; + } + if (t.v_type == V_ERR) + flag = 0; + if (tmp) { + if (c == 0) { + /* an aliase */ + p_error("%s: Bad alias syntax.", name); + flag = 0; + } else { + for (ap = c->lc_arg, vp = av; + ap != 0 && ap->arg_name != 0 && + (*ap->arg_name == '\0' || + !str_match(tmp, ap->arg_name, + ap->arg_minlen)); + ap++, vp++) + ; + if (ap == 0 || ap->arg_name == 0) { + p_error("%s: Unknown argument \"%s\".", + name, tmp); + flag = 0; + ap = 0; + vp = 0; + } + } + str_free(tmp); + } + } + if (ap != 0) { + if (ap->arg_flags & ARG_LIST) { + i = vp - av + 1; + lp = ap; + } + if (vp->v_type != V_ERR) { + if (*ap->arg_name) + p_error("%s: Argument %d (%s) duplicated.", + name, vp - av + 1, + ap->arg_name); + else + p_error("%s: Argument %d duplicated.", + name, vp - av + 1); + flag = 0; + vp = 0; + } else if (t.v_type == V_ERR) { + /* do nothing */ + } else if ((ap->arg_flags&ARG_TYPE) == ARG_NUM && + t.v_type != V_NUM || + (ap->arg_flags&ARG_TYPE) == ARG_STR && + t.v_type != V_STR) { + if (*ap->arg_name) + p_error("%s: Argument %d (%s) type mismatch.", + name, vp - av + 1, + ap->arg_name); + else + p_error("%s: Argument %d type mismatch.", + name, vp - av + 1); + flag = 0; + vp = 0; + } + } + if (vp != 0) + *vp = t; + else + val_free(t); + if (token == T_COMMA) + (void) s_gettok(); + } + + if (p_erred()) + flag = 0; + if (token == T_RP) + (void) s_gettok(); + else if (token != T_EOL && token != T_EOF) + flag = 0; /* look for legal follow set */ + v->v_type = V_ERR; + if (flag) + if (c != 0) + (*c->lc_func)(v, av); + else + if (a->a_flags & A_INUSE) + p_error("%s: Recursive alias.", a->a_name); + else { + a->a_flags |= A_INUSE; + if (dolongcmd(a->a_buf, av, i) < 0) + p_memerror(); + a->a_flags &= ~A_INUSE; + } + if (p_abort()) { + val_free(*v); + v->v_type = V_ERR; + goto abort; + } + for (vp = av; vp < &av[LCMD_NARG]; vp++) + val_free(*vp); + return 0; +abort: + for (vp = av; vp < &av[LCMD_NARG]; vp++) + val_free(*vp); + return -1; +} + +p_assign(name, v, flag) +char *name; +struct value *v; +char flag; +{ + (void) s_gettok(); + + if (p_expr(v, flag) < 0) { + p_synerror(); + return -1; + } + switch (v->v_type) { + case V_STR: + case V_NUM: + if (flag && var_set(name, v) == 0) { + p_memerror(); + val_free(*v); + return -1; + } + break; + } + return 0; +} diff --git a/usr/src/usr.bin/window/parser3.c b/usr/src/usr.bin/window/parser3.c new file mode 100644 index 0000000000..36c943b9f4 --- /dev/null +++ b/usr/src/usr.bin/window/parser3.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parser3.c 3.9 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "parser.h" + +/* + * = + * ? : + * || + * && + * | + * ^ + * & + * == != + * <= >= + * << >> + * + - + * * / % + * unary - + ~ ! + */ +p_expr(v, flag) +register struct value *v; +char flag; +{ + struct value t; + int ret; + + if (p_expr0(&t, flag) < 0) + return -1; + + if (token != T_ASSIGN) { + *v = t; + return 0; + } + switch (t.v_type) { + case V_NUM: + p_error("%d: Not a variable.", t.v_num); + case V_ERR: + t.v_str = 0; + break; + } + ret = p_assign(t.v_str, v, flag); + if (t.v_str != 0) + str_free(t.v_str); + return ret; +} + +/* + * ? : + */ +p_expr0(v, flag) +register struct value *v; +char flag; +{ + struct value t; + char true; + + if (p_expr1(v, flag) < 0) + return -1; + if (token != T_QUEST) + return 0; + switch (v->v_type) { + case V_NUM: + true = v->v_num != 0; + break; + case V_STR: + p_error("?: Numeric left operand required."); + str_free(v->v_str); + v->v_type = V_ERR; + case V_ERR: + flag = 0; + break; + } + (void) s_gettok(); + v->v_type = V_ERR; + if ((flag && true ? p_expr1(v, 1) : p_expr1(&t, 0)) < 0) + return -1; + if (token != T_COLON) { + val_free(*v); + p_synerror(); + return -1; + } + (void) s_gettok(); + return flag && !true ? p_expr1(v, 1) : p_expr1(&t, 0); +} + +/* + * || + */ +p_expr1(v, flag) +register struct value *v; +char flag; +{ + char true = 0; + + if (p_expr2(v, flag) < 0) + return -1; + if (token != T_OROR) + return 0; + for (;;) { + switch (v->v_type) { + case V_NUM: + v->v_num = true = true || v->v_num != 0; + break; + case V_STR: + p_error("||: Numeric operands required."); + str_free(v->v_str); + v->v_type = V_ERR; + case V_ERR: + flag = 0; + break; + } + if (token != T_OROR) + return 0; + (void) s_gettok(); + if (p_expr2(v, flag && !true) < 0) + return -1; + } +} + +/* + * && + */ +p_expr2(v, flag) +register struct value *v; +char flag; +{ + char true = 1; + + if (p_expr3_10(3, v, flag) < 0) + return -1; + if (token != T_ANDAND) + return 0; + for (;;) { + switch (v->v_type) { + case V_NUM: + v->v_num = true = true && v->v_num != 0; + break; + case V_STR: + p_error("&&: Numeric operands required."); + str_free(v->v_str); + v->v_type = V_ERR; + case V_ERR: + flag = 0; + break; + } + if (token != T_ANDAND) + return 0; + (void) s_gettok(); + if (p_expr3_10(3, v, flag && true) < 0) + return -1; + } + /*NOTREACHED*/ +} diff --git a/usr/src/usr.bin/window/parser4.c b/usr/src/usr.bin/window/parser4.c new file mode 100644 index 0000000000..00e402a4a5 --- /dev/null +++ b/usr/src/usr.bin/window/parser4.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parser4.c 3.8 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "parser.h" + +/* + * | 3 + * ^ 4 + * & 5 + * == != 6 + * < <= > >= 7 + * << >> 8 + * + - 9 + * * / % 10 + */ +p_expr3_10(level, v, flag) +register struct value *v; +char flag; +{ + struct value l, r; + int op; + char *opname; + + if ((level == 10 ? p_expr11(v, flag) + : p_expr3_10(level + 1, v, flag)) < 0) + return -1; + for (;;) { + switch (level) { + case 3: + if (token != T_OR) + return 0; + opname = "|"; + break; + case 4: + if (token != T_XOR) + return 0; + opname = "^"; + break; + case 5: + if (token != T_AND) + return 0; + opname = "&"; + break; + case 6: + if (token == T_EQ) + opname = "=="; + else if (token == T_NE) + opname = "!="; + else + return 0; + break; + case 7: + switch (token) { + case T_LT: + opname = "<"; + break; + case T_LE: + opname = "<="; + break; + case T_GT: + opname = ">"; + break; + case T_GE: + opname = ">="; + break; + default: + return 0; + } + break; + case 8: + if (token == T_LS) + opname = "<<"; + else if (token == T_RS) + opname = ">>"; + else + return 0; + break; + case 9: + if (token == T_PLUS) + opname = "+"; + else if (token == T_MINUS) + opname = "-"; + else + return 0; + break; + case 10: + switch (token) { + case T_MUL: + opname = "*"; + break; + case T_DIV: + opname = "/"; + break; + case T_MOD: + opname = "%"; + break; + default: + return 0; + } + break; + } + l = *v; + if (l.v_type == V_ERR) + flag = 0; + + op = token; + (void) s_gettok(); + if ((level == 10 ? p_expr11(&r, flag) + : p_expr3_10(level + 1, &r, flag)) < 0) { + p_synerror(); + val_free(l); + return -1; + } + + if (r.v_type == V_ERR) + flag = 0; + else switch (op) { + case T_EQ: + case T_NE: + case T_LT: + case T_LE: + case T_GT: + case T_GE: + case T_PLUS: + if (l.v_type == V_STR) { + if (r.v_type == V_NUM) + if (p_convstr(&r) < 0) + flag = 0; + } else + if (r.v_type == V_STR) + if (p_convstr(&l) < 0) + flag = 0; + break; + case T_LS: + case T_RS: + if (r.v_type == V_STR) { + char *p = r.v_str; + r.v_type = V_NUM; + r.v_num = strlen(p); + str_free(p); + } + break; + case T_OR: + case T_XOR: + case T_AND: + case T_MINUS: + case T_MUL: + case T_DIV: + case T_MOD: + default: + if (l.v_type == V_STR || r.v_type == V_STR) { + p_error("%s: Numeric operands required.", + opname); + flag = 0; + } + } + if (!flag) { + val_free(l); + val_free(r); + v->v_type = V_ERR; + if (p_abort()) + return -1; + continue; + } + + v->v_type = V_NUM; + switch (op) { + case T_EQ: + case T_NE: + case T_LT: + case T_LE: + case T_GT: + case T_GE: + if (l.v_type == V_STR) { + int tmp = strcmp(l.v_str, r.v_str); + str_free(l.v_str); + str_free(r.v_str); + l.v_type = V_NUM; + l.v_num = tmp; + r.v_type = V_NUM; + r.v_num = 0; + } + break; + } + switch (op) { + case T_OR: + v->v_num = l.v_num | r.v_num; + break; + case T_XOR: + v->v_num = l.v_num ^ r.v_num; + break; + case T_AND: + v->v_num = l.v_num & r.v_num; + break; + case T_EQ: + v->v_num = l.v_num == r.v_num; + break; + case T_NE: + v->v_num = l.v_num != r.v_num; + break; + case T_LT: + v->v_num = l.v_num < r.v_num; + break; + case T_LE: + v->v_num = l.v_num <= r.v_num; + break; + case T_GT: + v->v_num = l.v_num > r.v_num; + break; + case T_GE: + v->v_num = l.v_num >= r.v_num; + break; + case T_LS: + if (l.v_type == V_STR) { + int i; + if ((i = strlen(l.v_str)) > r.v_num) + i = r.v_num; + v->v_str = str_ncpy(l.v_str, i); + v->v_type = V_STR; + } else + v->v_num = l.v_num << r.v_num; + break; + case T_RS: + if (l.v_type == V_STR) { + int i; + if ((i = strlen(l.v_str)) > r.v_num) + i -= r.v_num; + else + i = 0; + v->v_str = str_cpy(l.v_str + i); + v->v_type = V_STR; + } else + v->v_num = l.v_num >> r.v_num; + break; + case T_PLUS: + if (l.v_type == V_STR) { + v->v_str = str_cat(l.v_str, r.v_str); + v->v_type = V_STR; + } else + v->v_num = l.v_num + r.v_num; + break; + case T_MINUS: + v->v_num = l.v_num - r.v_num; + break; + case T_MUL: + v->v_num = l.v_num * r.v_num; + break; + case T_DIV: + v->v_num = l.v_num / r.v_num; + break; + case T_MOD: + v->v_num = l.v_num % r.v_num; + break; + } + val_free(l); + val_free(r); + } + /*NOTREACHED*/ +} diff --git a/usr/src/usr.bin/window/parser5.c b/usr/src/usr.bin/window/parser5.c new file mode 100644 index 0000000000..eb02b0d75a --- /dev/null +++ b/usr/src/usr.bin/window/parser5.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parser5.c 3.13 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "parser.h" +#include "var.h" + +/* + * unary $ $? + - ! ~ + */ +p_expr11(v, flag) +register struct value *v; +char flag; +{ + int op; + char *opname; + + switch (token) { + case T_DOLLAR: + opname = "$"; + break; + case T_DQ: + opname = "$?"; + break; + case T_PLUS: + opname = "unary +"; + break; + case T_MINUS: + opname = "unary -"; + break; + case T_NOT: + opname = "!"; + break; + case T_COMP: + opname = "~"; + break; + default: + return p_expr12(v, flag); + } + op = token; + (void) s_gettok(); + if (p_expr11(v, flag) < 0) + return -1; + switch (v->v_type) { + case V_NUM: + break; + case V_STR: + switch (op) { + case T_MINUS: + case T_NOT: + case T_COMP: + p_error("%s: Numeric operand required.", opname); + str_free(v->v_str); + v->v_type = V_ERR; + return 0; + } + break; + case V_ERR: + return 0; + } + switch (op) { + case T_DOLLAR: + case T_DQ: + if (v->v_type == V_NUM) { + int tmp = cx.x_type == X_BUF && cx.x_arg != 0 && + v->v_num > 0 && v->v_num <= cx.x_narg; + if (op == T_DQ) + v->v_num = tmp; + else if (tmp) + *v = cx.x_arg[v->v_num - 1]; + else { + p_error("%d: No such argument.", v->v_num); + v->v_type = V_ERR; + } + } else { + char *name = v->v_str; + struct var *r = var_lookup(name); + if (op == T_DQ) { + v->v_type = V_NUM; + v->v_num = r != 0; + } else if (r != 0) + *v = r->r_val; + else { + p_error("%s: Undefined variable.", name); + v->v_type = V_ERR; + } + str_free(name); + } + if (v->v_type == V_STR && (v->v_str = str_cpy(v->v_str)) == 0) { + p_memerror(); + return -1; + } + break; + case T_MINUS: + v->v_num = - v->v_num; + break; + case T_NOT: + v->v_num = ! v->v_num; + break; + case T_COMP: + v->v_num = ~ v->v_num; + break; + } + return 0; +} + +/* + * string, number, ( expr ) + * Plus function calls. + * + * Always return v_type == V_ERR when flag == 0. + */ +p_expr12(v, flag) +register struct value *v; +char flag; +{ + v->v_type = V_ERR; + switch (token) { + case T_NUM: + if (flag) { + v->v_type = V_NUM; + v->v_num = token_num; + } + (void) s_gettok(); + break; + case T_STR: + if (flag) { + v->v_type = V_STR; + v->v_str = token_str; + } else + str_free(token_str); + (void) s_gettok(); + break; + case T_LP: + (void) s_gettok(); + if (p_expr(v, flag) < 0) { + p_synerror(); + return -1; + } + if (token != T_RP) { + p_synerror(); + val_free(*v); + return -1; + } + (void) s_gettok(); + break; + default: + return -1; + } + while (token == T_LP) { + char *cmd; + + if (p_convstr(v) < 0) + return -1; + cmd = v->v_type == V_STR ? v->v_str : 0; + if (p_function(cmd, v, flag) < 0) { + if (cmd) + str_free(cmd); + return -1; + } + if (cmd) + str_free(cmd); + } + return 0; +} diff --git a/usr/src/usr.bin/window/scanner.c b/usr/src/usr.bin/window/scanner.c new file mode 100644 index 0000000000..1e7f009b02 --- /dev/null +++ b/usr/src/usr.bin/window/scanner.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)scanner.c 3.14 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "value.h" +#include "token.h" +#include "context.h" +#include "string.h" + +s_getc() +{ + register c; + + switch (cx.x_type) { + case X_FILE: + c = getc(cx.x_fp); + if (cx.x_bol && c != EOF) { + cx.x_bol = 0; + cx.x_lineno++; + } + if (c == '\n') + cx.x_bol = 1; + return c; + case X_BUF: + if (*cx.x_bufp != 0) + return *cx.x_bufp++ & 0xff; + else + return EOF; + } + /*NOTREACHED*/ +} + +s_ungetc(c) +{ + if (c == EOF) + return EOF; + switch (cx.x_type) { + case X_FILE: + cx.x_bol = 0; + return ungetc(c, cx.x_fp); + case X_BUF: + if (cx.x_bufp > cx.x_buf) + return *--cx.x_bufp = c; + else + return EOF; + } + /*NOTREACHED*/ +} + +s_gettok() +{ + char buf[100]; + register char *p = buf; + register c; + register state = 0; + +loop: + c = s_getc(); + switch (state) { + case 0: + switch (c) { + case ' ': + case '\t': + break; + case '\n': + case ';': + cx.x_token = T_EOL; + state = -1; + break; + case '#': + state = 1; + break; + case EOF: + cx.x_token = T_EOF; + state = -1; + break; + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '_': case '.': + *p++ = c; + state = 2; + break; + case '"': + state = 3; + break; + case '\'': + state = 4; + break; + case '\\': + switch (c = s_gettok1()) { + case -1: + break; + case -2: + state = 0; + break; + default: + *p++ = c; + state = 2; + } + break; + case '0': + cx.x_val.v_num = 0; + state = 10; + break; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + cx.x_val.v_num = c - '0'; + state = 11; + break; + case '>': + state = 20; + break; + case '<': + state = 21; + break; + case '=': + state = 22; + break; + case '!': + state = 23; + break; + case '&': + state = 24; + break; + case '|': + state = 25; + break; + case '$': + state = 26; + break; + case '~': + cx.x_token = T_COMP; + state = -1; + break; + case '+': + cx.x_token = T_PLUS; + state = -1; + break; + case '-': + cx.x_token = T_MINUS; + state = -1; + break; + case '*': + cx.x_token = T_MUL; + state = -1; + break; + case '/': + cx.x_token = T_DIV; + state = -1; + break; + case '%': + cx.x_token = T_MOD; + state = -1; + break; + case '^': + cx.x_token = T_XOR; + state = -1; + break; + case '(': + cx.x_token = T_LP; + state = -1; + break; + case ')': + cx.x_token = T_RP; + state = -1; + break; + case ',': + cx.x_token = T_COMMA; + state = -1; + break; + case '?': + cx.x_token = T_QUEST; + state = -1; + break; + case ':': + cx.x_token = T_COLON; + state = -1; + break; + case '[': + cx.x_token = T_LB; + state = -1; + break; + case ']': + cx.x_token = T_RB; + state = -1; + break; + default: + cx.x_val.v_num = c; + cx.x_token = T_CHAR; + state = -1; + break; + } + break; + case 1: /* got # */ + if (c == '\n' || c == EOF) { + (void) s_ungetc(c); + state = 0; + } + break; + case 2: /* unquoted string */ + switch (c) { + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '_': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (p < buf + sizeof buf - 1) + *p++ = c; + break; + case '"': + state = 3; + break; + case '\'': + state = 4; + break; + case '\\': + switch (c = s_gettok1()) { + case -2: + (void) s_ungetc(' '); + case -1: + break; + default: + if (p < buf + sizeof buf - 1) + *p++ = c; + } + break; + default: + (void) s_ungetc(c); + case EOF: + *p = 0; + cx.x_token = T_STR; + switch (*buf) { + case 'i': + if (buf[1] == 'f' && buf[2] == 0) + cx.x_token = T_IF; + break; + case 't': + if (buf[1] == 'h' && buf[2] == 'e' + && buf[3] == 'n' && buf[4] == 0) + cx.x_token = T_THEN; + break; + case 'e': + if (buf[1] == 'n' && buf[2] == 'd' + && buf[3] == 'i' && buf[4] == 'f' + && buf[5] == 0) + cx.x_token = T_ENDIF; + else if (buf[1] == 'l' && buf[2] == 's') + if (buf[3] == 'i' && buf[4] == 'f' + && buf[5] == 0) + cx.x_token = T_ELSIF; + else if (buf[3] == 'e' && buf[4] == 0) + cx.x_token = T_ELSE; + break; + } + if (cx.x_token == T_STR + && (cx.x_val.v_str = str_cpy(buf)) == 0) { + p_memerror(); + cx.x_token = T_EOF; + } + state = -1; + break; + } + break; + case 3: /* " quoted string */ + switch (c) { + case '\n': + (void) s_ungetc(c); + case EOF: + case '"': + state = 2; + break; + case '\\': + switch (c = s_gettok1()) { + case -1: + case -2: /* newlines are invisible */ + break; + default: + if (p < buf + sizeof buf - 1) + *p++ = c; + } + break; + default: + if (p < buf + sizeof buf - 1) + *p++ = c; + break; + } + break; + case 4: /* ' quoted string */ + switch (c) { + case '\n': + (void) s_ungetc(c); + case EOF: + case '\'': + state = 2; + break; + case '\\': + switch (c = s_gettok1()) { + case -1: + case -2: /* newlines are invisible */ + break; + default: + if (p < buf + sizeof buf - 1) + *p++ = c; + } + break; + default: + if (p < buf + sizeof buf - 1) + *p++ = c; + break; + } + break; + case 10: /* got 0 */ + switch (c) { + case 'x': + case 'X': + cx.x_val.v_num = 0; + state = 12; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + cx.x_val.v_num = c - '0'; + state = 13; + break; + case '8': case '9': + cx.x_val.v_num = c - '0'; + state = 11; + break; + default: + (void) s_ungetc(c); + state = -1; + cx.x_token = T_NUM; + } + break; + case 11: /* decimal number */ + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + cx.x_val.v_num = cx.x_val.v_num * 10 + c - '0'; + break; + default: + (void) s_ungetc(c); + state = -1; + cx.x_token = T_NUM; + } + break; + case 12: /* hex number */ + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + cx.x_val.v_num = cx.x_val.v_num * 16 + c - '0'; + break; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'a' + 10; + break; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'A' + 10; + break; + default: + (void) s_ungetc(c); + state = -1; + cx.x_token = T_NUM; + } + break; + case 13: /* octal number */ + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + cx.x_val.v_num = cx.x_val.v_num * 8 + c - '0'; + break; + default: + (void) s_ungetc(c); + state = -1; + cx.x_token = T_NUM; + } + break; + case 20: /* got > */ + switch (c) { + case '=': + cx.x_token = T_GE; + state = -1; + break; + case '>': + cx.x_token = T_RS; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_GT; + state = -1; + } + break; + case 21: /* got < */ + switch (c) { + case '=': + cx.x_token = T_LE; + state = -1; + break; + case '<': + cx.x_token = T_LS; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_LT; + state = -1; + } + break; + case 22: /* got = */ + switch (c) { + case '=': + cx.x_token = T_EQ; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_ASSIGN; + state = -1; + } + break; + case 23: /* got ! */ + switch (c) { + case '=': + cx.x_token = T_NE; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_NOT; + state = -1; + } + break; + case 24: /* got & */ + switch (c) { + case '&': + cx.x_token = T_ANDAND; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_AND; + state = -1; + } + break; + case 25: /* got | */ + switch (c) { + case '|': + cx.x_token = T_OROR; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_OR; + state = -1; + } + break; + case 26: /* got $ */ + switch (c) { + case '?': + cx.x_token = T_DQ; + state = -1; + break; + default: + (void) s_ungetc(c); + cx.x_token = T_DOLLAR; + state = -1; + } + break; + default: + abort(); + } + if (state >= 0) + goto loop; + return cx.x_token; +} + +s_gettok1() +{ + register c; + register n; + + c = s_getc(); /* got \ */ + switch (c) { + case EOF: + return -1; + case '\n': + return -2; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + default: + return c; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + break; + } + n = c - '0'; + c = s_getc(); /* got \[0-7] */ + if (c < '0' || c > '7') { + (void) s_ungetc(c); + return n; + } + n = n * 8 + c - '0'; + c = s_getc(); /* got \[0-7][0-7] */ + if (c < '0' || c > '7') { + (void) s_ungetc(c); + return n; + } + return n * 8 + c - '0'; +} diff --git a/usr/src/usr.bin/window/startup.c b/usr/src/usr.bin/window/startup.c new file mode 100644 index 0000000000..39821076ec --- /dev/null +++ b/usr/src/usr.bin/window/startup.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)startup.c 3.25 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "defs.h" +#include "value.h" +#include "var.h" +#include "char.h" +#include "local.h" + +doconfig() +{ + char buf[100]; + char *home; + static char runcom[] = RUNCOM; + + if ((home = getenv("HOME")) == 0) + home = "."; + (void) sprintf(buf, "%.*s/%s", + (sizeof buf - sizeof runcom) / sizeof (char) - 1, + home, runcom); + return dosource(buf); +} + +/* + * The default is two windows of equal size. + */ +dodefault() +{ + struct ww *w; + register r = wwnrow / 2 - 1; + + if (openwin(1, r + 2, 0, wwnrow - r - 2, wwncol, default_nline, + (char *) 0, 1, 1, default_shellfile, default_shell) == 0) + return; + if ((w = openwin(0, 1, 0, r, wwncol, default_nline, + (char *) 0, 1, 1, default_shellfile, default_shell)) == 0) + return; + wwprintf(w, "Escape character is %s.\r\n", unctrl(escapec)); +} + +setvars() +{ + /* try to use a random ordering to balance the tree */ + (void) var_setnum("nrow", wwnrow); + (void) var_setnum("ncol", wwncol); + (void) var_setnum("baud", wwbaud); + (void) var_setnum("m_rev", WWM_REV); + (void) var_setnum("m_blk", WWM_BLK); + (void) var_setnum("m_ul", WWM_UL); + (void) var_setnum("m_grp", WWM_GRP); + (void) var_setnum("m_dim", WWM_DIM); + (void) var_setnum("m_usr", WWM_USR); + (void) var_setstr("term", wwterm); + (void) var_setnum("modes", wwavailmodes); +} diff --git a/usr/src/usr.bin/window/string.c b/usr/src/usr.bin/window/string.c new file mode 100644 index 0000000000..9392dbaf44 --- /dev/null +++ b/usr/src/usr.bin/window/string.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)string.c 3.13 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "string.h" + +char *malloc(); + +char * +str_cpy(s) +register char *s; +{ + char *str; + register char *p; + + str = p = str_alloc(strlen(s) + 1); + if (p == 0) + return 0; + while (*p++ = *s++) + ; + return str; +} + +char * +str_ncpy(s, n) +register char *s; +register n; +{ + int l = strlen(s); + char *str; + register char *p; + + if (n > l) + n = l; + str = p = str_alloc(n + 1); + if (p == 0) + return 0; + while (--n >= 0) + *p++ = *s++; + *p = 0; + return str; +} + +char * +str_itoa(i) +int i; +{ + char buf[30]; + + (void) sprintf(buf, "%d", i); + return str_cpy(buf); +} + +char * +str_cat(s1, s2) +char *s1, *s2; +{ + char *str; + register char *p, *q; + + str = p = str_alloc(strlen(s1) + strlen(s2) + 1); + if (p == 0) + return 0; + for (q = s1; *p++ = *q++;) + ; + for (q = s2, p--; *p++ = *q++;) + ; + return str; +} + +/* + * match s against p. + * s can be a prefix of p with at least min characters. + */ +str_match(s, p, min) +register char *s, *p; +register min; +{ + for (; *s && *p && *s == *p; s++, p++, min--) + ; + return *s == *p || *s == 0 && min <= 0; +} + +#ifdef STR_DEBUG +char * +str_alloc(l) +int l; +{ + register struct string *s; + + s = (struct string *) malloc((unsigned)l + str_offset); + if (s == 0) + return 0; + if (str_head.s_forw == 0) + str_head.s_forw = str_head.s_back = &str_head; + s->s_forw = str_head.s_forw; + s->s_back = &str_head; + str_head.s_forw = s; + s->s_forw->s_back = s; + return s->s_data; +} + +str_free(str) +char *str; +{ + register struct string *s; + + for (s = str_head.s_forw; s != &str_head && s->s_data != str; + s = s->s_forw) + ; + if (s == &str_head) + abort(); + s->s_back->s_forw = s->s_forw; + s->s_forw->s_back = s->s_back; + free((char *)s); +} +#endif diff --git a/usr/src/usr.bin/window/string.h b/usr/src/usr.bin/window/string.h new file mode 100644 index 0000000000..8d060e1e4f --- /dev/null +++ b/usr/src/usr.bin/window/string.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)string.h 3.9 (Berkeley) 6/6/90 + */ + +#define STR_DEBUG + +char *str_cpy(); +char *str_ncpy(); +char *str_cat(); +char *str_itoa(); + +#define str_cmp(a, b) strcmp(a, b) + +#ifdef STR_DEBUG +struct string { + struct string *s_forw; + struct string *s_back; + char s_data[1]; +}; + +struct string str_head; + +#define str_offset ((unsigned)str_head.s_data - (unsigned)&str_head) +#define str_stos(s) ((struct string *)((unsigned)(s) - str_offset)) + +char *str_alloc(); +int str_free(); +#else +#define str_free(s) free(s) +#define str_alloc(s) malloc(s) +#endif diff --git a/usr/src/usr.bin/window/token.h b/usr/src/usr.bin/window/token.h new file mode 100644 index 0000000000..162ea34239 --- /dev/null +++ b/usr/src/usr.bin/window/token.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)token.h 3.9 (Berkeley) 6/6/90 + */ + +#define token (cx.x_token) +#define token_num (cx.x_val.v_num) +#define token_str (cx.x_val.v_str) + +#define T_EOL 1 +#define T_EOF 2 +#define T_COMP 3 +#define T_PLUS 4 +#define T_MINUS 5 +#define T_MUL 6 +#define T_DIV 7 +#define T_LP 8 +#define T_RP 9 +#define T_LB 10 +#define T_RB 11 +#define T_DOLLAR 12 +#define T_COMMA 13 +#define T_QUEST 14 +#define T_COLON 15 +#define T_CHAR 16 +#define T_STR 17 +#define T_NUM 18 +#define T_MOD 19 +#define T_XOR 20 +#define T_DQ 21 /* $? */ +#define T_GE 22 +#define T_RS 23 +#define T_GT 24 +#define T_LE 25 +#define T_LS 26 +#define T_LT 27 +#define T_EQ 28 +#define T_ASSIGN 29 +#define T_NE 30 +#define T_NOT 31 +#define T_ANDAND 32 +#define T_AND 33 +#define T_OROR 34 +#define T_OR 35 + +#define T_IF 40 +#define T_THEN 41 +#define T_ELSIF 42 +#define T_ELSE 43 +#define T_ENDIF 44 diff --git a/usr/src/usr.bin/window/tt.h b/usr/src/usr.bin/window/tt.h new file mode 100644 index 0000000000..8408bf55c2 --- /dev/null +++ b/usr/src/usr.bin/window/tt.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tt.h 3.27 (Berkeley) 6/6/90 + */ + +/* + * Interface structure for the terminal drivers. + */ +struct tt { + /* startup and cleanup */ + int (*tt_start)(); + int (*tt_end)(); + + /* terminal functions */ + int (*tt_move)(); + int (*tt_insline)(); + int (*tt_delline)(); + int (*tt_inschar)(); + int (*tt_insspace)(); + int (*tt_delchar)(); + int (*tt_write)(); /* write a whole block */ + int (*tt_putc)(); /* write one character */ + int (*tt_clreol)(); + int (*tt_clreos)(); + int (*tt_clear)(); + int (*tt_scroll_down)(); + int (*tt_scroll_up)(); + int (*tt_setscroll)(); /* set scrolling region */ + int (*tt_setmodes)(); /* set display modes */ + int (*tt_set_token)(); /* define a token */ + int (*tt_put_token)(); /* refer to a defined token */ + + /* internal variables */ + char tt_modes; /* the current display modes */ + char tt_nmodes; /* the new modes for next write */ + char tt_insert; /* currently in insert mode */ + int tt_row; /* cursor row */ + int tt_col; /* cursor column */ + int tt_scroll_top; /* top of scrolling region */ + int tt_scroll_bot; /* bottom of scrolling region */ + + /* terminal info */ + int tt_nrow; /* number of display rows */ + int tt_ncol; /* number of display columns */ + char tt_availmodes; /* the display modes supported */ + char tt_wrap; /* has auto wrap around */ + char tt_retain; /* can retain below (db flag) */ + short tt_padc; /* the pad character */ + int tt_ntoken; /* number of compression tokens */ + int tt_token_min; /* minimun token size */ + int tt_token_max; /* maximum token size */ + int tt_set_token_cost; /* cost in addition to string */ + int tt_put_token_cost; /* constant cost */ + + /* the frame characters */ + short *tt_frame; + + /* the output routine */ + int (*tt_flush)(); +}; +struct tt tt; + +/* + * tt_padc is used by the compression routine. + * It is a short to allow the driver to indicate that there is no padding. + */ +#define TT_PADC_NONE 0x100 + +/* + * List of terminal drivers. + */ +struct tt_tab { + char *tt_name; + int tt_len; + int (*tt_func)(); +}; +extern struct tt_tab tt_tab[]; + +/* + * Clean interface to termcap routines. + * Too may t's. + */ +char tt_strings[1024]; /* string buffer */ +char *tt_strp; /* pointer for it */ + +struct tt_str { + char *ts_str; + int ts_n; +}; + +struct tt_str *tttgetstr(); +struct tt_str *ttxgetstr(); /* tgetstr() and expand delays */ + +int tttputc(); +#define tttputs(s, n) tputs((s)->ts_str, (n), tttputc) +#define ttxputs(s) ttwrite((s)->ts_str, (s)->ts_n) + +/* + * Buffered output without stdio. + * These variables have different meanings from the ww_ob* variables. + * But I'm too lazy to think up different names. + */ +char *tt_ob; +char *tt_obp; +char *tt_obe; +#define ttputc(c) (tt_obp < tt_obe ? (*tt_obp++ = (c)) \ + : ((*tt.tt_flush)(), *tt_obp++ = (c))) + +/* + * Convenience macros for the drivers + * They require char.h + */ +#define ttctrl(c) ttputc(ctrl(c)) +#define ttesc(c) (ttctrl('['), ttputc(c)) diff --git a/usr/src/usr.bin/window/ttf100.c b/usr/src/usr.bin/window/ttf100.c new file mode 100644 index 0000000000..dea06b5b7d --- /dev/null +++ b/usr/src/usr.bin/window/ttf100.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttf100.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +/* + * Freedom 100 + */ + +#define G (WWM_GRP << WWC_MSHIFT) +short f100_frame[16] = { + ' ', 'J'|G, 'K'|G, 'A'|G, + 'J'|G, 'J'|G, 'B'|G, 'M'|G, + 'K'|G, 'D'|G, 'K'|G, 'O'|G, + 'C'|G, 'L'|G, 'N'|G, 'I'|G +}; +extern struct tt_str *gen_AE, *gen_AS; + +tt_f100() +{ + static struct tt_str ae = { "\033%", 2 }; + static struct tt_str as = { "\033$", 2 }; + + if (tt_generic() < 0) + return -1; + tt.tt_frame = f100_frame; + tt.tt_availmodes |= WWM_GRP; + gen_AS = &as; + gen_AE = &ae; + return 0; +} diff --git a/usr/src/usr.bin/window/ttgeneric.c b/usr/src/usr.bin/window/ttgeneric.c new file mode 100644 index 0000000000..c912d16dea --- /dev/null +++ b/usr/src/usr.bin/window/ttgeneric.c @@ -0,0 +1,549 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttgeneric.c 3.46 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +char PC, *BC, *UP; +short ospeed; + + /* normal frame */ +short gen_frame[16] = { + ' ', '|', '-', '+', + '|', '|', '+', '+', + '-', '+', '-', '+', + '+', '+', '+', '+' +}; + + /* ANSI graphics frame */ +#define G (WWM_GRP << WWC_MSHIFT) +short ansi_frame[16] = { + ' ', 'x'|G, 'Q'|G, 'm'|G, + 'x'|G, 'x'|G, 'l'|G, 't'|G, + 'q'|G, 'j'|G, 'q'|G, 'v'|G, + 'k'|G, 'u'|G, 'w'|G, 'n'|G +}; +struct tt_str ansi_AS = { + "\033(0", 3 +}; + +struct tt_str *gen_PC; +struct tt_str *gen_CM; +struct tt_str *gen_IM; +struct tt_str *gen_IC; +struct tt_str *gen_ICn; +struct tt_str *gen_IP; +struct tt_str *gen_EI; +struct tt_str *gen_DC; +struct tt_str *gen_DCn; +struct tt_str *gen_AL; +struct tt_str *gen_ALn; +struct tt_str *gen_DL; +struct tt_str *gen_DLn; +struct tt_str *gen_CE; +struct tt_str *gen_CD; +struct tt_str *gen_CL; +struct tt_str *gen_VS; +struct tt_str *gen_VE; +struct tt_str *gen_TI; +struct tt_str *gen_TE; +struct tt_str *gen_SO; +struct tt_str *gen_SE; +struct tt_str *gen_US; +struct tt_str *gen_UE; +struct tt_str *gen_LE; +struct tt_str *gen_ND; +struct tt_str *gen_UP; +struct tt_str *gen_DO; +struct tt_str *gen_BC; +struct tt_str *gen_NL; +struct tt_str *gen_CR; +struct tt_str *gen_HO; +struct tt_str *gen_AS; +struct tt_str *gen_AE; +struct tt_str *gen_XS; +struct tt_str *gen_XE; +struct tt_str *gen_SF; +struct tt_str *gen_SFn; +struct tt_str *gen_SR; +struct tt_str *gen_SRn; +struct tt_str *gen_CS; +char gen_MI; +char gen_MS; +char gen_AM; +char gen_OS; +char gen_BS; +char gen_DA; +char gen_DB; +char gen_NS; +char gen_XN; +int gen_CO; +int gen_LI; +int gen_UG; +int gen_SG; + +gen_setinsert(new) +char new; +{ + if (new) { + if (gen_IM) + ttxputs(gen_IM); + } else + if (gen_EI) + ttxputs(gen_EI); + tt.tt_insert = new; +} + +gen_setmodes(new) +register new; +{ + register diff; + + diff = new ^ tt.tt_modes; + if (diff & WWM_REV) { + if (new & WWM_REV) { + if (gen_SO) + ttxputs(gen_SO); + } else + if (gen_SE) + ttxputs(gen_SE); + } + if (diff & WWM_UL) { + if (new & WWM_UL) { + if (gen_US) + ttxputs(gen_US); + } else + if (gen_UE) + ttxputs(gen_UE); + } + if (diff & WWM_GRP) { + if (new & WWM_GRP) { + if (gen_AS) + ttxputs(gen_AS); + } else + if (gen_AE) + ttxputs(gen_AE); + } + if (diff & WWM_USR) { + if (new & WWM_USR) { + if (gen_XS) + ttxputs(gen_XS); + } else + if (gen_XE) + ttxputs(gen_XE); + } + tt.tt_modes = new; +} + +gen_insline(n) +{ + if (tt.tt_modes) /* for concept 100 */ + gen_setmodes(0); + if (gen_ALn) + ttpgoto(gen_ALn, 0, n, gen_LI - tt.tt_row); + else + while (--n >= 0) + tttputs(gen_AL, gen_LI - tt.tt_row); +} + +gen_delline(n) +{ + if (tt.tt_modes) /* for concept 100 */ + gen_setmodes(0); + if (gen_DLn) + ttpgoto(gen_DLn, 0, n, gen_LI - tt.tt_row); + else + while (--n >= 0) + tttputs(gen_DL, gen_LI - tt.tt_row); +} + +gen_putc(c) +register char c; +{ + if (tt.tt_insert) + gen_setinsert(0); + if (tt.tt_nmodes != tt.tt_modes) + gen_setmodes(tt.tt_nmodes); + ttputc(c); + if (++tt.tt_col == gen_CO) + if (gen_XN) + tt.tt_col = tt.tt_row = -10; + else if (gen_AM) + tt.tt_col = 0, tt.tt_row++; + else + tt.tt_col--; +} + +gen_write(p, n) + register char *p; + register n; +{ + if (tt.tt_insert) + gen_setinsert(0); + if (tt.tt_nmodes != tt.tt_modes) + gen_setmodes(tt.tt_nmodes); + ttwrite(p, n); + tt.tt_col += n; + if (tt.tt_col == gen_CO) + if (gen_XN) + tt.tt_col = tt.tt_row = -10; + else if (gen_AM) + tt.tt_col = 0, tt.tt_row++; + else + tt.tt_col--; +} + +gen_move(row, col) +register int row, col; +{ + if (tt.tt_row == row && tt.tt_col == col) + return; + if (!gen_MI && tt.tt_insert) + gen_setinsert(0); + if (!gen_MS && tt.tt_modes) + gen_setmodes(0); + if (row < tt.tt_scroll_top || row > tt.tt_scroll_bot) + gen_setscroll(0, tt.tt_nrow - 1); + if (tt.tt_row == row) { + if (col == 0) { + ttxputs(gen_CR); + goto out; + } + if (tt.tt_col == col - 1) { + if (gen_ND) { + ttxputs(gen_ND); + goto out; + } + } else if (tt.tt_col == col + 1) { + if (gen_LE) { + ttxputs(gen_LE); + goto out; + } + } + } + if (tt.tt_col == col) { + if (tt.tt_row == row + 1) { + if (gen_UP) { + ttxputs(gen_UP); + goto out; + } + } else if (tt.tt_row == row - 1) { + ttxputs(gen_DO); + goto out; + } + } + if (gen_HO && col == 0 && row == 0) { + ttxputs(gen_HO); + goto out; + } + tttgoto(gen_CM, col, row); +out: + tt.tt_col = col; + tt.tt_row = row; +} + +gen_start() +{ + if (gen_VS) + ttxputs(gen_VS); + if (gen_TI) + ttxputs(gen_TI); + ttxputs(gen_CL); + tt.tt_col = tt.tt_row = 0; + tt.tt_insert = 0; + tt.tt_nmodes = tt.tt_modes = 0; +} + +gen_end() +{ + if (tt.tt_insert) + gen_setinsert(0); + if (gen_TE) + ttxputs(gen_TE); + if (gen_VE) + ttxputs(gen_VE); +} + +gen_clreol() +{ + if (tt.tt_modes) /* for concept 100 */ + gen_setmodes(0); + tttputs(gen_CE, gen_CO - tt.tt_col); +} + +gen_clreos() +{ + if (tt.tt_modes) /* for concept 100 */ + gen_setmodes(0); + tttputs(gen_CD, gen_LI - tt.tt_row); +} + +gen_clear() +{ + if (tt.tt_modes) /* for concept 100 */ + gen_setmodes(0); + ttxputs(gen_CL); +} + +gen_inschar(c) +register char c; +{ + if (!tt.tt_insert) + gen_setinsert(1); + if (tt.tt_nmodes != tt.tt_modes) + gen_setmodes(tt.tt_nmodes); + if (gen_IC) + tttputs(gen_IC, gen_CO - tt.tt_col); + ttputc(c); + if (gen_IP) + tttputs(gen_IP, gen_CO - tt.tt_col); + if (++tt.tt_col == gen_CO) + if (gen_XN) + tt.tt_col = tt.tt_row = -10; + else if (gen_AM) + tt.tt_col = 0, tt.tt_row++; + else + tt.tt_col--; +} + +gen_insspace(n) +{ + if (gen_ICn) + ttpgoto(gen_ICn, 0, n, gen_CO - tt.tt_col); + else + while (--n >= 0) + tttputs(gen_IC, gen_CO - tt.tt_col); +} + +gen_delchar(n) +{ + if (gen_DCn) + ttpgoto(gen_DCn, 0, n, gen_CO - tt.tt_col); + else + while (--n >= 0) + tttputs(gen_DC, gen_CO - tt.tt_col); +} + +gen_scroll_down(n) +{ + gen_move(tt.tt_scroll_bot, 0); + if (gen_SFn) + ttpgoto(gen_SFn, 0, n, n); + else + while (--n >= 0) + ttxputs(gen_SF); +} + +gen_scroll_up(n) +{ + gen_move(tt.tt_scroll_top, 0); + if (gen_SRn) + ttpgoto(gen_SRn, 0, n, n); + else + while (--n >= 0) + ttxputs(gen_SR); +} + +gen_setscroll(top, bot) +{ + tttgoto(gen_CS, bot, top); + tt.tt_scroll_top = top; + tt.tt_scroll_bot = bot; + tt.tt_row = tt.tt_col = -10; +} + +tt_generic() +{ + gen_PC = tttgetstr("pc"); + PC = gen_PC ? *gen_PC->ts_str : 0; + ospeed = wwospeed; + + gen_CM = ttxgetstr("cm"); /* may not work */ + gen_IM = ttxgetstr("im"); + gen_IC = tttgetstr("ic"); + gen_ICn = tttgetstr("IC"); + gen_IP = tttgetstr("ip"); + gen_EI = ttxgetstr("ei"); + gen_DC = tttgetstr("dc"); + gen_DCn = tttgetstr("DC"); + gen_AL = tttgetstr("al"); + gen_ALn = tttgetstr("AL"); + gen_DL = tttgetstr("dl"); + gen_DLn = tttgetstr("DL"); + gen_CE = tttgetstr("ce"); + gen_CD = tttgetstr("cd"); + gen_CL = ttxgetstr("cl"); + gen_VS = ttxgetstr("vs"); + gen_VE = ttxgetstr("ve"); + gen_TI = ttxgetstr("ti"); + gen_TE = ttxgetstr("te"); + gen_SO = ttxgetstr("so"); + gen_SE = ttxgetstr("se"); + gen_US = ttxgetstr("us"); + gen_UE = ttxgetstr("ue"); + gen_LE = ttxgetstr("le"); + gen_ND = ttxgetstr("nd"); + gen_UP = ttxgetstr("up"); + gen_DO = ttxgetstr("do"); + gen_BC = ttxgetstr("bc"); + gen_NL = ttxgetstr("nl"); + gen_CR = ttxgetstr("cr"); + gen_HO = ttxgetstr("ho"); + gen_AS = ttxgetstr("as"); + gen_AE = ttxgetstr("ae"); + gen_XS = ttxgetstr("XS"); + gen_XE = ttxgetstr("XE"); + gen_SF = ttxgetstr("sf"); + gen_SFn = ttxgetstr("SF"); + gen_SR = ttxgetstr("sr"); + gen_SRn = ttxgetstr("SR"); + gen_CS = ttxgetstr("cs"); + gen_MI = tgetflag("mi"); + gen_MS = tgetflag("ms"); + gen_AM = tgetflag("am"); + gen_OS = tgetflag("os"); + gen_BS = tgetflag("bs"); + gen_DA = tgetflag("da"); + gen_DB = tgetflag("db"); + gen_NS = tgetflag("ns"); + gen_XN = tgetflag("xn"); + gen_CO = tgetnum("co"); + gen_LI = tgetnum("li"); + gen_UG = tgetnum("ug"); + gen_SG = tgetnum("sg"); + if (gen_CL == 0 || gen_OS || gen_CM == 0) + return -1; + + /* + * Deal with obsolete termcap fields. + */ + if (gen_LE == 0) + if (gen_BC) + gen_LE = gen_BC; + else if (gen_BS) { + static struct tt_str bc = { "\b", 1 }; + gen_BC = &bc; + } + if (gen_NL == 0) { + static struct tt_str nl = { "\n", 1 }; + gen_NL = &nl; + } + if (gen_DO == 0) + gen_DO = gen_NL; + if (gen_CR == 0) { + static struct tt_str cr = { "\r", 1 }; + gen_CR = &cr; + } + /* + * Most terminal will scroll with "nl", but very few specify "sf". + * We shouldn't use "do" here. + */ + if (gen_SF == 0 && !gen_NS) + gen_SF = gen_NL; + BC = gen_LE ? gen_LE->ts_str : 0; + UP = gen_UP ? gen_UP->ts_str : 0; + /* + * Fix up display attributes that we can't handle, or don't + * really exist. + */ + if (gen_SG > 0) + gen_SO = 0; + if (gen_UG > 0 || gen_US && gen_SO && ttstrcmp(gen_US, gen_SO) == 0) + gen_US = 0; + + if (gen_IM && gen_IM->ts_n == 0) { + free((char *) gen_IM); + gen_IM = 0; + } + if (gen_EI && gen_EI->ts_n == 0) { + free((char *) gen_EI); + gen_EI = 0; + } + if (gen_IC && gen_IC->ts_n == 0) { + free((char *) gen_IC); + gen_IC = 0; + } + if (gen_IM) + tt.tt_inschar = gen_inschar; + else if (gen_IC) + tt.tt_insspace = gen_insspace; + if (gen_DC) + tt.tt_delchar = gen_delchar; + if (gen_AL) + tt.tt_insline = gen_insline; + if (gen_DL) + tt.tt_delline = gen_delline; + if (gen_CE) + tt.tt_clreol = gen_clreol; + if (gen_CD) + tt.tt_clreos = gen_clreos; + if (gen_SF) + tt.tt_scroll_down = gen_scroll_down; + /* + * Don't allow scroll_up if da or db but not cs. + * See comment in wwscroll.c. + */ + if (gen_SR && (gen_CS || !gen_DA && !gen_DB)) + tt.tt_scroll_up = gen_scroll_up; + if (gen_CS) + tt.tt_setscroll = gen_setscroll; + if (gen_SO) + tt.tt_availmodes |= WWM_REV; + if (gen_US) + tt.tt_availmodes |= WWM_UL; + if (gen_AS) + tt.tt_availmodes |= WWM_GRP; + if (gen_XS) + tt.tt_availmodes |= WWM_USR; + tt.tt_wrap = gen_AM; + tt.tt_retain = gen_DB; + tt.tt_ncol = gen_CO; + tt.tt_nrow = gen_LI; + tt.tt_start = gen_start; + tt.tt_end = gen_end; + tt.tt_write = gen_write; + tt.tt_putc = gen_putc; + tt.tt_move = gen_move; + tt.tt_clear = gen_clear; + tt.tt_setmodes = gen_setmodes; + tt.tt_frame = gen_AS && ttstrcmp(gen_AS, &ansi_AS) == 0 ? + ansi_frame : gen_frame; + return 0; +} diff --git a/usr/src/usr.bin/window/tth19.c b/usr/src/usr.bin/window/tth19.c new file mode 100644 index 0000000000..0aec0381db --- /dev/null +++ b/usr/src/usr.bin/window/tth19.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tth19.c 3.25 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include "char.h" + +/* +kb|h19|heath|h19-b|h19b|heathkit|heath-19|z19|zenith: + cr=^M:nl=^J:bl=^G:al=1*\EL:am:le=^H:bs:cd=\EJ:ce=\EK: + cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:dl=1*\EM:do=\EB: + ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:ms: + ta=^I:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4: + kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH: + kn#8:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW: + l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER: + es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1: +*/ + +#define NCOL 80 +#define NROW 24 + +#define G (WWM_GRP << WWC_MSHIFT) +short h19_frame[16] = { + ' ', '`'|G, 'a'|G, 'e'|G, + '`'|G, '`'|G, 'f'|G, 'v'|G, + 'a'|G, 'd'|G, 'a'|G, 'u'|G, + 'c'|G, 't'|G, 's'|G, 'b'|G +}; + +extern struct tt_str *gen_VS; +extern struct tt_str *gen_VE; + +int h19_msp10c; + +#define PAD(ms10) { \ + register i; \ + for (i = ((ms10) + 5) / h19_msp10c; --i >= 0;) \ + ttputc('\0'); \ +} +#define ICPAD() PAD((NCOL - tt.tt_col) * 1) /* 0.1 ms per char */ +#define ILPAD() PAD((NROW - tt.tt_row) * 10) /* 1 ms per char */ + +#define H19_SETINSERT(m) ttesc((tt.tt_insert = (m)) ? '@' : 'O') + +h19_setmodes(new) +register new; +{ + register diff; + + diff = new ^ tt.tt_modes; + if (diff & WWM_REV) + ttesc(new & WWM_REV ? 'p' : 'q'); + if (diff & WWM_GRP) + ttesc(new & WWM_REV ? 'F' : 'G'); + tt.tt_modes = new; +} + +h19_insline(n) +{ + while (--n >= 0) { + ttesc('L'); + ILPAD(); + } +} + +h19_delline(n) +{ + while (--n >= 0) { + ttesc('M'); + ILPAD(); + } +} + +h19_putc(c) +register char c; +{ + if (tt.tt_nmodes != tt.tt_modes) + (*tt.tt_setmodes)(tt.tt_nmodes); + if (tt.tt_insert) + H19_SETINSERT(0); + ttputc(c); + if (++tt.tt_col == NCOL) + tt.tt_col = NCOL - 1; +} + +h19_write(p, n) +register char *p; +register n; +{ + if (tt.tt_nmodes != tt.tt_modes) + (*tt.tt_setmodes)(tt.tt_nmodes); + if (tt.tt_insert) + H19_SETINSERT(0); + ttwrite(p, n); + tt.tt_col += n; + if (tt.tt_col == NCOL) + tt.tt_col = NCOL - 1; +} + +h19_move(row, col) +register char row, col; +{ + if (tt.tt_row == row) { + if (tt.tt_col == col) + return; + if (col == 0) { + ttctrl('m'); + goto out; + } + if (tt.tt_col == col - 1) { + ttesc('C'); + goto out; + } + if (tt.tt_col == col + 1) { + ttctrl('h'); + goto out; + } + } + if (tt.tt_col == col) { + if (tt.tt_row == row + 1) { + ttesc('A'); + goto out; + } + if (tt.tt_row == row - 1) { + ttctrl('j'); + goto out; + } + } + if (col == 0 && row == 0) { + ttesc('H'); + goto out; + } + ttesc('Y'); + ttputc(' ' + row); + ttputc(' ' + col); +out: + tt.tt_col = col; + tt.tt_row = row; +} + +h19_start() +{ + if (gen_VS) + ttxputs(gen_VS); + ttesc('w'); + ttesc('E'); + tt.tt_col = tt.tt_row = 0; + tt.tt_insert = 0; + tt.tt_nmodes = tt.tt_modes = 0; +} + +h19_end() +{ + if (tt.tt_insert) + H19_SETINSERT(0); + if (gen_VE) + ttxputs(gen_VE); + ttesc('v'); +} + +h19_clreol() +{ + ttesc('K'); +} + +h19_clreos() +{ + ttesc('J'); +} + +h19_clear() +{ + ttesc('E'); +} + +h19_inschar(c) +register char c; +{ + if (tt.tt_nmodes != tt.tt_modes) + (*tt.tt_setmodes)(tt.tt_nmodes); + if (!tt.tt_insert) + H19_SETINSERT(1); + ttputc(c); + if (tt.tt_insert) + ICPAD(); + if (++tt.tt_col == NCOL) + tt.tt_col = NCOL - 1; +} + +h19_delchar(n) +{ + while (--n >= 0) + ttesc('N'); +} + +h19_scroll_down(n) +{ + h19_move(NROW - 1, 0); + while (--n >= 0) + ttctrl('j'); +} + +h19_scroll_up(n) +{ + h19_move(0, 0); + while (--n >= 0) + ttesc('I'); +} + +tt_h19() +{ + float cpms = (float) wwbaud / 10000; /* char per ms */ + + h19_msp10c = 10 / cpms; /* ms per 10 char */ + gen_VS = ttxgetstr("vs"); + gen_VE = ttxgetstr("ve"); + + tt.tt_start = h19_start; + tt.tt_end = h19_end; + + tt.tt_insline = h19_insline; + tt.tt_delline = h19_delline; + tt.tt_inschar = h19_inschar; + tt.tt_delchar = h19_delchar; + tt.tt_clreol = h19_clreol; + tt.tt_clreos = h19_clreos; + tt.tt_clear = h19_clear; + tt.tt_move = h19_move; + tt.tt_write = h19_write; + tt.tt_putc = h19_putc; + tt.tt_scroll_down = h19_scroll_down; + tt.tt_scroll_up = h19_scroll_up; + tt.tt_setmodes = h19_setmodes; + + tt.tt_ncol = NCOL; + tt.tt_nrow = NROW; + tt.tt_availmodes = WWM_REV|WWM_GRP; + tt.tt_frame = h19_frame; + return 0; +} diff --git a/usr/src/usr.bin/window/tth29.c b/usr/src/usr.bin/window/tth29.c new file mode 100644 index 0000000000..1d8c06ee66 --- /dev/null +++ b/usr/src/usr.bin/window/tth29.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tth29.c 3.10 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include "char.h" + +/* + * H29 Driver + * + * WWM_USR mode is alternate character set. + * +kC|h29|heath-29|z29|zenith-29:\ + :am:bc=\ED:bt=\E-:cr=^M:do=^J:nl=^J:bl=^G:\ + :al=\EL:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:\ + :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\ + :ms:ta=^I:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\ + :kb=^H:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#1:k0=\E~:l0=HOME:\ + :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:k9=\E01:\ + :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1:us=\Es8:ue=\Es0: + * + */ + +h29_setmodes(new) +register new; +{ + register modes = '0'; + + if (new & WWM_REV) + modes += 0x01; + if (new & WWM_BLK) + modes += 0x02; + if (new & WWM_DIM) + modes += 0x04; + if (new & WWM_UL) + modes += 0x08; + if (new & WWM_USR) + modes += 0x10; + ttesc('s'); + ttputc(modes); + if (new & WWM_GRP) { + if ((tt.tt_modes & WWM_GRP) == 0) + ttesc('F'); + } else + if (tt.tt_modes & WWM_GRP) + ttesc('G'); + tt.tt_modes = new; +} + +tt_h29() +{ + if (tt_h19() < 0) + return -1; + tt.tt_setmodes = h29_setmodes; + tt.tt_availmodes |= WWM_BLK|WWM_UL|WWM_DIM|WWM_USR; + return 0; +} diff --git a/usr/src/usr.bin/window/ttinit.c b/usr/src/usr.bin/window/ttinit.c new file mode 100644 index 0000000000..0c6e8f1f90 --- /dev/null +++ b/usr/src/usr.bin/window/ttinit.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttinit.c 3.27 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +int tt_h19(); +int tt_h29(); +int tt_f100(); +int tt_tvi925(); +int tt_wyse75(); +int tt_wyse60(); +int tt_zapple(); +int tt_zentec(); +int tt_generic(); +struct tt_tab tt_tab[] = { + { "h19", 3, tt_h19 }, + { "h29", 3, tt_h29 }, + { "f100", 4, tt_f100 }, + { "tvi925", 6, tt_tvi925 }, + { "wyse75", 6, tt_wyse75 }, + { "wyse60", 6, tt_wyse60 }, + { "w60", 3, tt_wyse60 }, + { "zapple", 6, tt_zapple }, + { "zentec", 6, tt_zentec }, + { "generic", 0, tt_generic }, + 0 +}; + +ttinit() +{ + int i; + register struct tt_tab *tp; + register char *p, *q; + register char *t; + int ttflush(); + + tt_strp = tt_strings; + + /* + * Set output buffer size to about 1 second of output time. + */ + i = MIN(wwbaud/10, 512); + if ((tt_ob = malloc((unsigned) i)) == 0) { + wwerrno = WWE_NOMEM; + return -1; + } + tt_obp = tt_ob; + tt_obe = tt_ob + i; + + /* + * Use the standard name of the terminal (i.e. the second + * name in termcap). + */ + for (p = wwtermcap; *p && *p != '|' && *p != ':'; p++) + ; + if (*p == '|') + p++; + for (q = p; *q && *q != '|' && *q != ':'; q++) + ; + if (q != p && (t = malloc((unsigned) (q - p + 1))) != 0) { + wwterm = t; + while (p < q) + *t++ = *p++; + *t = 0; + } + for (tp = tt_tab; tp->tt_name != 0; tp++) + if (strncmp(tp->tt_name, wwterm, tp->tt_len) == 0) + break; + if (tp->tt_name == 0) { + wwerrno = WWE_BADTERM; + return -1; + } + if ((*tp->tt_func)() < 0) { + wwerrno = WWE_CANTDO; + return -1; + } + if (wwgetttysize(0, &tt.tt_nrow, &tt.tt_ncol) < 0) + return -1; + tt.tt_scroll_top = 0; + tt.tt_scroll_bot = tt.tt_nrow - 1; + tt.tt_flush = ttflush; + return 0; +} diff --git a/usr/src/usr.bin/window/ttoutput.c b/usr/src/usr.bin/window/ttoutput.c new file mode 100644 index 0000000000..05c1af8f94 --- /dev/null +++ b/usr/src/usr.bin/window/ttoutput.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttoutput.c 3.9 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include + +/* + * Buffered output package. + * We need this because stdio fails on non-blocking writes. + */ + +ttflush() +{ + register char *p; + register n; + extern errno; + + wwnflush++; + for (p = tt_ob; p < tt_obp;) { + wwnwr++; + n = write(1, p, tt_obp - p); + if (n < 0) { + wwnwre++; + if (errno != EWOULDBLOCK) { + /* can't deal with this */ + p = tt_obp; + } + } else if (n == 0) { + /* what to do? */ + wwnwrz++; + } else { + wwnwrc += n; + p += n; + } + } + tt_obp = tt_ob; +} + +ttputs(s) +register char *s; +{ + while (*s) + ttputc(*s++); +} + +ttwrite(s, n) + register char *s; + register n; +{ + switch (n) { + case 0: + break; + case 1: + ttputc(*s); + break; + case 2: + if (tt_obe - tt_obp < 2) + (*tt.tt_flush)(); + *tt_obp++ = *s++; + *tt_obp++ = *s; + break; + case 3: + if (tt_obe - tt_obp < 3) + (*tt.tt_flush)(); + *tt_obp++ = *s++; + *tt_obp++ = *s++; + *tt_obp++ = *s; + break; + case 4: + if (tt_obe - tt_obp < 4) + (*tt.tt_flush)(); + *tt_obp++ = *s++; + *tt_obp++ = *s++; + *tt_obp++ = *s++; + *tt_obp++ = *s; + break; + case 5: + if (tt_obe - tt_obp < 5) + (*tt.tt_flush)(); + *tt_obp++ = *s++; + *tt_obp++ = *s++; + *tt_obp++ = *s++; + *tt_obp++ = *s++; + *tt_obp++ = *s; + break; + default: + while (n > 0) { + register m; + + while ((m = tt_obe - tt_obp) == 0) + (*tt.tt_flush)(); + if ((m = tt_obe - tt_obp) > n) + m = n; + bcopy(s, tt_obp, m); + tt_obp += m; + s += m; + n -= m; + } + } +} diff --git a/usr/src/usr.bin/window/tttermcap.c b/usr/src/usr.bin/window/tttermcap.c new file mode 100644 index 0000000000..ff21cc542a --- /dev/null +++ b/usr/src/usr.bin/window/tttermcap.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tttermcap.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "tt.h" + +char *tgetstr(); +char *tgoto(); +char *malloc(); + +tttputc(c) +{ + ttputc(c); +} + +ttxputc(c) +{ + *tt_strp++ = c; +} + +struct tt_str * +tttgetstr(str) + char *str; +{ + register struct tt_str *s; + + if ((str = tgetstr(str, &tt_strp)) == 0) + return 0; + if ((s = (struct tt_str *) malloc(sizeof *s)) == 0) + return 0; + s->ts_str = str; + s->ts_n = tt_strp - s->ts_str - 1; + return s; +} + +struct tt_str * +ttxgetstr(str) + char *str; +{ + register struct tt_str *s; + char buf[100]; + char *bufp = buf; + + if (tgetstr(str, &bufp) == 0) + return 0; + if ((s = (struct tt_str *) malloc(sizeof *s)) == 0) + return 0; + s->ts_str = tt_strp; + tputs(buf, 1, ttxputc); + s->ts_n = tt_strp - s->ts_str; + *tt_strp++ = 0; + return s; +} + +tttgoto(s, col, row) + struct tt_str *s; +{ + register char *p = s->ts_str; + + ttputs(tgoto(p, col, row)); + for (p += s->ts_n; *--p == 0;) + ttputc(0); +} + +ttpgoto(s, col, row, n) + struct tt_str *s; +{ + + tputs(tgoto(s->ts_str, col, row), n, tttputc); +} + +ttstrcmp(a, b) + register struct tt_str *a, *b; +{ + int n, r; + + if (r = bcmp(a->ts_str, b->ts_str, + (n = a->ts_n - b->ts_n) < 0 ? a->ts_n : b->ts_n)) + return r; + return n; +} diff --git a/usr/src/usr.bin/window/tttvi925.c b/usr/src/usr.bin/window/tttvi925.c new file mode 100644 index 0000000000..82eaf1921b --- /dev/null +++ b/usr/src/usr.bin/window/tttvi925.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * David Barto at Celerity Computer Corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tttvi925.c 3.6 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +/* + * Televideo 925 as emulated by Microterm. + */ + +#define G (WWM_GRP << WWC_MSHIFT) +short tvi925_frame[16] = { + ' ', '~'|G, '|'|G, 'c'|G, + '~'|G, '~'|G, '`'|G, 'e'|G, + '|'|G, 'a'|G, '|'|G, 'g'|G, + 'b'|G, 'f'|G, 'h'|G, 'd'|G +}; + +tt_tvi925() +{ + + if (tt_generic() < 0) + return -1; + tt.tt_availmodes |= WWM_GRP; + tt.tt_frame = tvi925_frame; + return 0; +} diff --git a/usr/src/usr.bin/window/ttwyse60.c b/usr/src/usr.bin/window/ttwyse60.c new file mode 100644 index 0000000000..388d2ebce0 --- /dev/null +++ b/usr/src/usr.bin/window/ttwyse60.c @@ -0,0 +1,76 @@ +/* + * Copyright 1987 by David C. Elliott, MIPS Computer Systems. + * + * Unlimited redistribution allowed as long as this notice + * is kept intact. + */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * David C. Elliott, of MIPS Computer Systems. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttwyse60.c 3.4 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +#define G (WWM_GRP << WWC_MSHIFT) +short wyse60_frame[16] = { + ' ', '6'|G, ':'|G, '1'|G, + '6'|G, '6'|G, '2'|G, '4'|G, + ':'|G, '5'|G, ':'|G, '='|G, + '3'|G, '9'|G, '0'|G, '0'|G +}; + +extern struct tt_str *gen_AS; +extern struct tt_str *gen_AE; + +tt_wyse60() +{ + static struct tt_str ae = { "\033H\003", 3 }; + static struct tt_str as = { "\033H\002", 3 }; + + if (tt_generic() < 0) + return -1; + tt.tt_availmodes |= WWM_GRP; + tt.tt_frame = wyse60_frame; + if (gen_AS == 0) + gen_AS = &as; + if (gen_AE == 0) + gen_AE = &ae; + return 0; +} diff --git a/usr/src/usr.bin/window/ttwyse75.c b/usr/src/usr.bin/window/ttwyse75.c new file mode 100644 index 0000000000..aa94e6afe2 --- /dev/null +++ b/usr/src/usr.bin/window/ttwyse75.c @@ -0,0 +1,76 @@ +/* + * Copyright 1987 by David C. Elliott, MIPS Computer Systems. + * + * Unlimited redistribution allowed as long as this notice + * is kept intact. + */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * David C. Elliott, of MIPS Computer Systems. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttwyse75.c 3.4 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +#define G (WWM_GRP << WWC_MSHIFT) +short wyse75_frame[16] = { + ' ', 'x'|G, 'q'|G, 'm'|G, + 'x'|G, 'x'|G, 'l'|G, 't'|G, + 'q'|G, 'j'|G, 'q'|G, 'v'|G, + 'k'|G, 'u'|G, 'w'|G, 'v'|G +}; + +extern struct tt_str *gen_AS; +extern struct tt_str *gen_AE; + +tt_wyse75() +{ + static struct tt_str ae = { "\033(B", 3 }; + static struct tt_str as = { "\033(0", 3 }; + + if (tt_generic() < 0) + return -1; + tt.tt_availmodes |= WWM_GRP; + tt.tt_frame = wyse75_frame; + if (gen_AS == 0) + gen_AS = &as; + if (gen_AE == 0) + gen_AE = &ae; + return 0; +} diff --git a/usr/src/usr.bin/window/ttzapple.c b/usr/src/usr.bin/window/ttzapple.c new file mode 100644 index 0000000000..41b41a565d --- /dev/null +++ b/usr/src/usr.bin/window/ttzapple.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttzapple.c 3.11 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include "char.h" + +/* +zz|zapple|perfect apple:\ + :am:pt:co#80:li#24:le=^H:nd=^F:up=^K:do=^J:\ + :ho=\E0:ll=\E1:cm=\E=%+ %+ :ch=\E<%+ :cv=\E>%+ :\ + :cl=\E4:ce=\E2:cd=\E3:rp=\E@%.%+ :\ + :so=\E+:se=\E-:\ + :dc=\Ec:DC=\EC%+ :ic=\Ei:IC=\EI%+ :\ + :al=\Ea:AL=\EA%+ :dl=\Ed:DL=\ED%+ :\ + :sf=\Ef:SF=\EF%+ :sr=\Er:SR=\ER%+ :cs=\E?%+ %+ :\ + :is=\E-\ET : +*/ + +#define NCOL 80 +#define NROW 24 +#define TOKEN_MAX 32 + +extern short gen_frame[]; + +zz_setmodes(new) +{ + if (new & WWM_REV) { + if ((tt.tt_modes & WWM_REV) == 0) + ttesc('+'); + } else + if (tt.tt_modes & WWM_REV) + ttesc('-'); + tt.tt_modes = new; +} + +zz_insline(n) +{ + if (n == 1) + ttesc('a'); + else { + ttesc('A'); + ttputc(n + ' '); + } +} + +zz_delline(n) +{ + if (n == 1) + ttesc('d'); + else { + ttesc('D'); + ttputc(n + ' '); + } +} + +zz_putc(c) + char c; +{ + if (tt.tt_nmodes != tt.tt_modes) + zz_setmodes(tt.tt_nmodes); + ttputc(c); + if (++tt.tt_col == NCOL) + tt.tt_col = 0, tt.tt_row++; +} + +zz_write(p, n) + register char *p; + register n; +{ + if (tt.tt_nmodes != tt.tt_modes) + zz_setmodes(tt.tt_nmodes); + ttwrite(p, n); + tt.tt_col += n; + if (tt.tt_col == NCOL) + tt.tt_col = 0, tt.tt_row++; +} + +zz_move(row, col) + register row, col; +{ + register x; + + if (tt.tt_row == row) { +same_row: + if ((x = col - tt.tt_col) == 0) + return; + if (col == 0) { + ttctrl('m'); + goto out; + } + switch (x) { + case 2: + ttctrl('f'); + case 1: + ttctrl('f'); + goto out; + case -2: + ttctrl('h'); + case -1: + ttctrl('h'); + goto out; + } + if ((col & 7) == 0 && x > 0 && x <= 16) { + ttctrl('i'); + if (x > 8) + ttctrl('i'); + goto out; + } + ttesc('<'); + ttputc(col + ' '); + goto out; + } + if (tt.tt_col == col) { + switch (row - tt.tt_row) { + case 2: + ttctrl('j'); + case 1: + ttctrl('j'); + goto out; + case -2: + ttctrl('k'); + case -1: + ttctrl('k'); + goto out; + } + if (col == 0) { + if (row == 0) + goto home; + if (row == NROW - 1) + goto ll; + } + ttesc('>'); + ttputc(row + ' '); + goto out; + } + if (col == 0) { + if (row == 0) { +home: + ttesc('0'); + goto out; + } + if (row == tt.tt_row + 1) { + /* + * Do newline first to match the sequence + * for scroll down and return + */ + ttctrl('j'); + ttctrl('m'); + goto out; + } + if (row == NROW - 1) { +ll: + ttesc('1'); + goto out; + } + } + /* favor local motion for better compression */ + if (row == tt.tt_row + 1) { + ttctrl('j'); + goto same_row; + } + if (row == tt.tt_row - 1) { + ttctrl('k'); + goto same_row; + } + ttesc('='); + ttputc(' ' + row); + ttputc(' ' + col); +out: + tt.tt_col = col; + tt.tt_row = row; +} + +zz_start() +{ + zz_setmodes(0); + zz_setscroll(0, NROW - 1); + zz_clear(); + ttesc('T'); + ttputc(TOKEN_MAX + ' '); +} + +zz_end() +{ + ttesc('T'); + ttputc(' '); +} + +zz_clreol() +{ + ttesc('2'); +} + +zz_clreos() +{ + ttesc('3'); +} + +zz_clear() +{ + ttesc('4'); + tt.tt_col = tt.tt_row = 0; +} + +zz_insspace(n) +{ + if (n == 1) + ttesc('i'); + else { + ttesc('I'); + ttputc(n + ' '); + } +} + +zz_delchar(n) +{ + if (n == 1) + ttesc('c'); + else { + ttesc('C'); + ttputc(n + ' '); + } +} + +zz_scroll_down(n) +{ + if (n == 1) + if (tt.tt_row == NROW - 1) + ttctrl('j'); + else + ttesc('f'); + else { + ttesc('F'); + ttputc(n + ' '); + } +} + +zz_scroll_up(n) +{ + if (n == 1) + ttesc('r'); + else { + ttesc('R'); + ttputc(n + ' '); + } +} + +zz_setscroll(top, bot) +{ + ttesc('?'); + ttputc(top + ' '); + ttputc(bot + ' '); + tt.tt_scroll_top = top; + tt.tt_scroll_bot = bot; +} + +int zz_debug = 0; + +zz_set_token(t, s, n) + char *s; +{ + if (tt.tt_nmodes != tt.tt_modes) + zz_setmodes(tt.tt_nmodes); + if (zz_debug) { + char buf[100]; + zz_setmodes(WWM_REV); + (void) sprintf(buf, "%02x=", t); + ttputs(buf); + tt.tt_col += 3; + } + ttputc(0x80); + ttputc(t + 1); + s[n - 1] |= 0x80; + ttwrite(s, n); + s[n - 1] &= ~0x80; +} + +/*ARGSUSED*/ +zz_put_token(t, s, n) + char *s; +{ + if (tt.tt_nmodes != tt.tt_modes) + zz_setmodes(tt.tt_nmodes); + if (zz_debug) { + char buf[100]; + zz_setmodes(WWM_REV); + (void) sprintf(buf, "%02x>", t); + ttputs(buf); + tt.tt_col += 3; + } + ttputc(t + 0x81); +} + +tt_zapple() +{ + tt.tt_insspace = zz_insspace; + tt.tt_delchar = zz_delchar; + tt.tt_insline = zz_insline; + tt.tt_delline = zz_delline; + tt.tt_clreol = zz_clreol; + tt.tt_clreos = zz_clreos; + tt.tt_scroll_down = zz_scroll_down; + tt.tt_scroll_up = zz_scroll_up; + tt.tt_setscroll = zz_setscroll; + tt.tt_availmodes = WWM_REV; + tt.tt_wrap = 1; + tt.tt_retain = 0; + tt.tt_ncol = NCOL; + tt.tt_nrow = NROW; + tt.tt_start = zz_start; + tt.tt_end = zz_end; + tt.tt_write = zz_write; + tt.tt_putc = zz_putc; + tt.tt_move = zz_move; + tt.tt_clear = zz_clear; + tt.tt_setmodes = zz_setmodes; + tt.tt_frame = gen_frame; + tt.tt_padc = TT_PADC_NONE; + tt.tt_ntoken = 127; + tt.tt_set_token = zz_set_token; + tt.tt_put_token = zz_put_token; + tt.tt_token_min = 1; + tt.tt_token_max = TOKEN_MAX; + tt.tt_set_token_cost = 2; + tt.tt_put_token_cost = 1; + return 0; +} diff --git a/usr/src/usr.bin/window/ttzentec.c b/usr/src/usr.bin/window/ttzentec.c new file mode 100644 index 0000000000..3a9fc9b30c --- /dev/null +++ b/usr/src/usr.bin/window/ttzentec.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ttzentec.c 3.5 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +/* + * Zentec 1021 + * + * We let the termcap entry specify how to enter and exit graphics mode, + * since it varies with what the terminal is emulating. + */ + +#define G (WWM_GRP << WWC_MSHIFT) +short zentec_frame[16] = { + ' ', 'x'|G, 'q'|G, 'm'|G, + 'x'|G, 'x'|G, 'l'|G, 't'|G, + 'q'|G, 'j'|G, 'q'|G, 'v'|G, + 'k'|G, 'u'|G, 'w'|G, 'n'|G +}; + +tt_zentec() +{ + if (tt_generic() < 0) + return -1; + if (tt.tt_availmodes | WWM_GRP) + tt.tt_frame = zentec_frame; + return 0; +} diff --git a/usr/src/usr.bin/window/value.h b/usr/src/usr.bin/window/value.h new file mode 100644 index 0000000000..46293c5022 --- /dev/null +++ b/usr/src/usr.bin/window/value.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)value.h 3.9 (Berkeley) 6/6/90 + */ + +struct value { + char v_type; + union { + int V_num; + char *V_str; + } v_un; +}; +#define v_num v_un.V_num +#define v_str v_un.V_str + +#define V_NUM 1 +#define V_STR 2 +#define V_ERR 3 + +#define val_free(v) ((v).v_type == V_STR ? str_free((v).v_str) : 0) diff --git a/usr/src/usr.bin/window/var.c b/usr/src/usr.bin/window/var.c new file mode 100644 index 0000000000..c9085b3473 --- /dev/null +++ b/usr/src/usr.bin/window/var.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)var.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "value.h" +#include "var.h" +#include "string.h" + +char *malloc(); + +struct var * +var_set1(head, name, v) +struct var **head; +char *name; +struct value *v; +{ + register struct var **p; + register struct var *r; + struct value val; + + /* do this first, easier to recover */ + val = *v; + if (val.v_type == V_STR && val.v_str != 0 && + (val.v_str = str_cpy(val.v_str)) == 0) + return 0; + if (*(p = var_lookup1(head, name)) == 0) { + r = (struct var *) malloc(sizeof (struct var)); + if (r == 0) { + val_free(val); + return 0; + } + if ((r->r_name = str_cpy(name)) == 0) { + val_free(val); + free((char *) r); + return 0; + } + r->r_left = r->r_right = 0; + *p = r; + } else { + r = *p; + val_free(r->r_val); + } + r->r_val = val; + return r; +} + +struct var * +var_setstr1(head, name, str) +struct var **head; +char *name; +char *str; +{ + struct value v; + + v.v_type = V_STR; + v.v_str = str; + return var_set1(head, name, &v); +} + +struct var * +var_setnum1(head, name, num) +struct var **head; +char *name; +int num; +{ + struct value v; + + v.v_type = V_NUM; + v.v_num = num; + return var_set1(head, name, &v); +} + +var_unset1(head, name) +struct var **head; +char *name; +{ + register struct var **p; + register struct var *r; + + if (*(p = var_lookup1(head, name)) == 0) + return -1; + r = *p; + *p = r->r_left; + while (*p != 0) + p = &(*p)->r_right; + *p = r->r_right; + val_free(r->r_val); + str_free(r->r_name); + free((char *) r); + return 0; +} + +struct var ** +var_lookup1(p, name) +register struct var **p; +register char *name; +{ + register cmp; + + while (*p != 0) { + if ((cmp = strcmp(name, (*p)->r_name)) < 0) + p = &(*p)->r_left; + else if (cmp > 0) + p = &(*p)->r_right; + else + break; + } + return p; +} + +var_walk1(r, func, a) +register struct var *r; +int (*func)(); +{ + if (r == 0) + return 0; + if (var_walk1(r->r_left, func, a) < 0 || (*func)(a, r) < 0 + || var_walk1(r->r_right, func, a) < 0) + return -1; + return 0; +} diff --git a/usr/src/usr.bin/window/var.h b/usr/src/usr.bin/window/var.h new file mode 100644 index 0000000000..54bc241e97 --- /dev/null +++ b/usr/src/usr.bin/window/var.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)var.h 3.11 (Berkeley) 6/6/90 + */ + +struct var { + struct var *r_left; + struct var *r_right; + char *r_name; + struct value r_val; +}; + +struct var *var_set1(); +struct var *var_setstr1(); +struct var *var_setnum1(); +struct var **var_lookup1(); + +#define var_set(n, v) var_set1(&var_head, n, v) +#define var_setstr(n, s) var_setstr1(&var_head, n, s) +#define var_setnum(n, i) var_setnum1(&var_head, n, i) +#define var_unset(n) var_unset1(&var_head, n) +#define var_lookup(n) (*var_lookup1(&var_head, n)) +#define var_walk(f, a) var_walk1(var_head, f, a) + +struct var *var_head; /* secret, shhh */ diff --git a/usr/src/usr.bin/window/win.c b/usr/src/usr.bin/window/win.c new file mode 100644 index 0000000000..ce8601e051 --- /dev/null +++ b/usr/src/usr.bin/window/win.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)win.c 3.25 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "defs.h" +#include "char.h" + +/* + * Higher level routines for dealing with windows. + * + * There are two types of windows: user window, and information window. + * User windows are the ones with a pty and shell. Information windows + * are for displaying error messages, and other information. + * + * The windows are doubly linked in overlapping order and divided into + * two groups: foreground and normal. Information + * windows are always foreground. User windows can be either. + * Addwin() adds a window to the list at the top of one of the two groups. + * Deletewin() deletes a window. Front() moves a window to the front + * of its group. Wwopen(), wwadd(), and wwdelete() should never be called + * directly. + */ + +/* + * Open a user window. + */ +struct ww * +openwin(id, row, col, nrow, ncol, nline, label, haspty, hasframe, shf, sh) +char *label; +char haspty, hasframe; +char *shf, **sh; +{ + register struct ww *w; + + if (id < 0 && (id = findid()) < 0) + return 0; + if (row + nrow <= 0 || row > wwnrow - 1 + || col + ncol <= 0 || col > wwncol - 1) { + error("Illegal window position."); + return 0; + } + w = wwopen(haspty ? WWO_PTY : WWO_SOCKET, nrow, ncol, row, col, nline); + if (w == 0) { + error("Can't open window: %s.", wwerror()); + return 0; + } + w->ww_id = id; + window[id] = w; + w->ww_hasframe = hasframe; + w->ww_alt = w->ww_w; + if (label != 0 && setlabel(w, label) < 0) + error("No memory for label."); + wwcursor(w, 1); + /* + * We have to do this little maneuver to make sure + * addwin() puts w at the top, so we don't waste an + * insert and delete operation. + */ + setselwin((struct ww *)0); + addwin(w, 0); + setselwin(w); + if (wwspawn(w, shf, sh) < 0) { + error("Can't execute %s: %s.", shf, wwerror()); + closewin(w); + return 0; + } + return w; +} + +findid() +{ + register i; + + for (i = 0; i < NWINDOW && window[i] != 0; i++) + ; + if (i >= NWINDOW) { + error("Too many windows."); + return -1; + } + return i; +} + +struct ww * +findselwin() +{ + register struct ww *w, *s = 0; + register i; + + for (i = 0; i < NWINDOW; i++) + if ((w = window[i]) != 0 && w != selwin && + (s == 0 || + !isfg(w) && (w->ww_order < s->ww_order || isfg(s)))) + s = w; + return s; +} + +/* + * Close a user window. Close all if w == 0. + */ +closewin(w) +register struct ww *w; +{ + char didit = 0; + register i; + + if (w != 0) { + closewin1(w); + didit++; + } else + for (i = 0; i < NWINDOW; i++) { + if ((w = window[i]) == 0) + continue; + closewin1(w); + didit++; + } + if (didit) { + if (selwin == 0) + if (lastselwin != 0) { + setselwin(lastselwin); + lastselwin = 0; + } else if (w = findselwin()) + setselwin(w); + if (lastselwin == 0 && selwin) + if (w = findselwin()) + lastselwin = w; + reframe(); + } +} + +/* + * Open an information (display) window. + */ +struct ww * +openiwin(nrow, label) +char *label; +{ + register struct ww *w; + + if ((w = wwopen(0, nrow, wwncol, 2, 0, 0)) == 0) + return 0; + w->ww_mapnl = 1; + w->ww_hasframe = 1; + w->ww_nointr = 1; + w->ww_noupdate = 1; + w->ww_unctrl = 1; + w->ww_id = -1; + w->ww_center = 1; + (void) setlabel(w, label); + addwin(w, 1); + reframe(); + return w; +} + +/* + * Close an information window. + */ +closeiwin(w) +struct ww *w; +{ + closewin1(w); + reframe(); +} + +closewin1(w) +register struct ww *w; +{ + if (w == selwin) + selwin = 0; + if (w == lastselwin) + lastselwin = 0; + if (w->ww_id >= 0 && w->ww_id < NWINDOW) + window[w->ww_id] = 0; + if (w->ww_label) + str_free(w->ww_label); + deletewin(w); + wwclose(w); +} + +/* + * Move the window to the top of its group. + * Don't do it if already fully visible. + * Wwvisible() doesn't work for tinted windows. + * But anything to make it faster. + * Always reframe() if doreframe is true. + */ +front(w, doreframe) +register struct ww *w; +char doreframe; +{ + if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) { + deletewin(w); + addwin(w, isfg(w)); + doreframe = 1; + } + if (doreframe) + reframe(); +} + +/* + * Add a window at the top of normal windows or foreground windows. + * For normal windows, we put it behind the current window. + */ +addwin(w, fg) +register struct ww *w; +char fg; +{ + if (fg) { + wwadd(w, framewin); + if (fgwin == framewin) + fgwin = w; + } else + wwadd(w, selwin != 0 && selwin != w && !isfg(selwin) + ? selwin : fgwin); +} + +/* + * Delete a window. + */ +deletewin(w) +register struct ww *w; +{ + if (fgwin == w) + fgwin = w->ww_back; + wwdelete(w); +} + +reframe() +{ + register struct ww *w; + + wwunframe(framewin); + for (w = wwhead.ww_back; w != &wwhead; w = w->ww_back) + if (w->ww_hasframe) { + wwframe(w, framewin); + labelwin(w); + } +} + +labelwin(w) +register struct ww *w; +{ + int mode = w == selwin ? WWM_REV : 0; + + if (!w->ww_hasframe) + return; + if (w->ww_id >= 0) { + char buf[2]; + + buf[0] = w->ww_id + '1'; + buf[1] = 0; + wwlabel(w, framewin, 1, buf, mode); + } + if (w->ww_label) { + int col; + + if (w->ww_center) { + col = (w->ww_w.nc - strlen(w->ww_label)) / 2; + col = MAX(3, col); + } else + col = 3; + wwlabel(w, framewin, col, w->ww_label, mode); + } +} + +stopwin(w) + register struct ww *w; +{ + if (w->ww_pty >= 0 && w->ww_ispty && wwstoptty(w->ww_pty) < 0) + error("Can't stop output: %s.", wwerror()); + else + w->ww_stopped = 1; +} + +startwin(w) + register struct ww *w; +{ + if (w->ww_pty >= 0 && w->ww_ispty && wwstarttty(w->ww_pty) < 0) + error("Can't start output: %s.", wwerror()); + else + w->ww_stopped = 0; +} + +sizewin(w, nrow, ncol) +register struct ww *w; +{ + struct ww *back = w->ww_back; + + w->ww_alt.nr = w->ww_w.nr; + w->ww_alt.nc = w->ww_w.nc; + wwdelete(w); + if (wwsize(w, nrow, ncol) < 0) + error("Can't resize window: %s.", wwerror()); + wwadd(w, back); + reframe(); +} + +waitnl(w) +struct ww *w; +{ + (void) waitnl1(w, "[Type any key to continue]"); +} + +more(w, always) +register struct ww *w; +char always; +{ + int c; + char uc = w->ww_unctrl; + + if (!always && w->ww_cur.r < w->ww_w.b - 2) + return 0; + c = waitnl1(w, "[Type escape to abort, any other key to continue]"); + w->ww_unctrl = 0; + wwputs("\033E", w); + w->ww_unctrl = uc; + return c == ctrl('[') ? 2 : 1; +} + +waitnl1(w, prompt) +register struct ww *w; +char *prompt; +{ + char uc = w->ww_unctrl; + + w->ww_unctrl = 0; + front(w, 0); + wwprintf(w, "\033Y%c%c\033sA%s\033rA ", + w->ww_w.nr - 1 + ' ', ' ', prompt); /* print on last line */ + wwcurtowin(w); + while (wwpeekc() < 0) + wwiomux(); + w->ww_unctrl = uc; + return wwgetc(); +} diff --git a/usr/src/usr.bin/window/window.1 b/usr/src/usr.bin/window/window.1 new file mode 100644 index 0000000000..2e2c795f43 --- /dev/null +++ b/usr/src/usr.bin/window/window.1 @@ -0,0 +1,940 @@ +.\" Copyright (c) 1985, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Edward Wang at The University of California, Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)window.1 6.15 (Berkeley) 7/26/91 +.\" +.Dd July 26, 1991 +.Dt WINDOW 1 +.Os BSD 4.3 +.Sh NAME +.Nm window +.Nd window environment +.Sh SYNOPSIS +.Nm window +.Op Fl t +.Op Fl f +.Op Fl d +.Op Fl e Ar escape-char +.Op Fl c Ar command +.Sh DESCRIPTION +.Nm Window +implements a window environment on +.Tn ASCII +terminals. +.Pp +A window is a rectangular portion of the physical terminal +screen associated with a set of processes. Its size and +position can be changed by the user at any time. Processes +communicate with their window in the same way they normally +interact with a terminal\-through their standard input, output, +and diagnostic file descriptors. The window program handles the +details of redirecting input an output to and from the +windows. At any one time, only one window can receive +input from the keyboard, but all windows can simultaneously send output +to the display. +.Pp +When +.Nm window +starts up, the commands (see long commands below) +contained in the file +.Pa .windowrc +in the user's home directory are +executed. If it does not exist, two equal sized windows spanning +the terminal screen are created by default. +.Pp +The command line options are +.Bl -tag -width Fl +.It Fl t +Turn on terse mode (see +.Ic terse +command below). +.It Fl f +Fast. Don't perform any startup action. +.It Fl d +Ignore +.Pa .windowrc +and create the two default +windows instead. +.It Fl e Ar escape-char +Set the escape character to +.Ar escape-char . +.Ar Escape-char +can be a single character, or in the form +.Ic ^X +where +.Ar X +is any character, meaning +.No control\- Ns Ar X . +.It Fl c Ar command +Execute the string +.Ar command +as a long command (see below) +before doing anything else. +.El +.Pp +Windows can overlap and are framed as necessary. Each window +is named by one of the digits ``1'' to ``9''. This one-character +identifier, as well as a user definable label string, are displayed +with the window on the top edge of its frame. A window can be +designated to be in the +.Ar foreground , +in which case it will always be +on top of all normal, non-foreground windows, and can be covered +only by other foreground windows. A window need not be completely +within the edges of the terminal screen. Thus a large window +(possibly larger than the screen) may be positioned to show only +a portion of its full size. +.Pp +Each window has a cursor and a set of control functions. Most intelligent +terminal operations such as line and +character deletion and insertion are supported. Display modes +such as underlining and reverse video are available if they are +supported by the terminal. In addition, +similar to terminals with multiple pages of memory, +each window has a text buffer which can have more lines than the window +itself. +.Ss Process Environment +With each newly created window, a shell program is spawned with its +process environment tailored to that window. Its standard input, +output, and diagnostic file descriptors are bound to one end of either +a pseudo-terminal +.Xr (pty 4 ) +or a +.Ux +domain socket +.Xr (socketpair 4 ) . +If a pseudo-terminal is used, then its special +characters and modes (see +.Xr stty 1 ) +are copied from the physical +terminal. A +.Xr termcap 5 +entry tailored to this window is created +and passed as environment +.Xr (environ 5 ) +variable +.Ev TERMCAP . +The termcap entry contains the window's size and +characteristics as well as information from the physical terminal, +such as the existence of underline, reverse video, and other display +modes, and the codes produced by the terminal's function keys, +if any. In addition, the window size attributes of the pseudo-terminal +are set to reflect the size of this window, and updated whenever +it is changed by the user. In particular, the editor +.Xr vi 1 +uses +this information to redraw its display. +.Ss Operation +During normal execution, +.Nm window +can be in one of two states: +conversation mode and command mode. In conversation mode, the +terminal's real cursor is placed at the cursor position of a particular +window--called the current window--and input from the keyboard is sent +to the process in that window. The current window is always +on top of all other windows, except those in foreground. In addition, +it is set apart by highlighting its identifier and label in reverse video. +.Pp +Typing +.Nm window Ns 's +escape character (normally +.Ic ^P ) +in conversation +mode switches it into command mode. In command mode, the top line of +the terminal screen becomes the command prompt window, and +.Nm window +interprets input from the keyboard as commands to manipulate windows. +.Pp +There are two types of commands: short commands are usually one or two +key strokes; long commands are strings either typed by the user in the +command window (see the +.Dq Ic \&: +command below), or read from a file (see +.Ic source +below). +.Ss Short Commands +Below, +.Ar \&# +represents one of the digits ``1'' to ``9'' +corresponding to the windows 1 to 9. +.Ic ^X +means +.No control\- Ns Ar X , +where +.Ar X +is any character. In particular, +.Ic ^^ +is +.Li control\-^. +.Ar Escape +is the escape key, or +.Ic ^\&[ . +.Bl -tag -width Ds +.It Ar # +Select window +.Ar # +as the current window +and return to conversation mode. +.It Ic \&% Ns Ar # +Select window +.Ar # +but stay in command mode. +.It Ic ^^ +Select the previous window and return to conversation +mode. This is useful for toggling between two windows. +.It Ic escape +Return to conversation mode. +.It Ic ^P +Return to conversation mode and write +.Ic ^P +to the +current window. Thus, typing two +.Ic ^P Ns 's +in conversation +mode sends one to the current window. If the +.Nm window +escape is changed to some other character, that +character takes the place of +.Ic ^P +here. +.It Ic ? +List a short summary of commands. +.It Ic ^L +Refresh the screen. +.It Ic q +Exit +.Nm window . +Confirmation is requested. +.It Ic ^Z +Suspend +.Nm window . +.It Ic w +Create a new window. The user is prompted for the positions +of the upper left and lower right corners of the window. +The cursor is placed on the screen and the keys ``h'', ``j'', +``k'', and ``l'' +move the cursor left, down, up, and right, respectively. +The keys ``H'', ``J'', ``K'', and ``L'' move the cursor to the respective +limits of the screen. Typing a number before the movement keys +repeats the movement that number of times. Return enters the cursor position +as the upper left corner of the window. The lower right corner +is entered in the same manner. During this process, +the placement of the new window is indicated by a rectangular +box drawn on the screen, corresponding to where the new window +will be framed. Typing escape at any point +cancels this command. +.Pp +This window becomes the current window, +and is given the first available ID. The default buffer size +is used (see +.Ar default_nline +command below). +.Pp +Only fully visible windows can be created this way. +.It Ic c Ns Ar # +Close window +.Ar # . +The process in the window is sent +the hangup signal (see +.Xr kill 1 ) . +.Xr Csh 1 +should +handle this signal correctly and cause no problems. +.It Ic m Ns Ar # +Move window +.Ar # +to another location. A box in the shape +of the window is drawn on +the screen to indicate the new position of the window, and the same keys as +those for the +.Ic w +command are used to position the box. The +window can be moved partially off-screen. +.It Ic M Ns Ar # +Move window +.Ar # +to its previous position. +.It Ic s Ns Ar # +Change the size of window +.Ar # . +The user is prompted +to enter the new lower right corner of the window. A box +is drawn to indicate the new window size. The same +keys used in +.Ic w +and +.Ic m +are used to enter the position. +.It Ic S Ns Ar # +Change window +.Ar # +to its previous size. +.It Ic ^Y +Scroll the current window up by one line. +.It Ic ^E +Scroll the current window down by one line. +.It Ic ^U +Scroll the current window up by half the window size. +.It Ic ^D +Scroll the current window down by half the window size. +.It Ic ^B +Scroll the current window up by the full window size. +.It Ic ^F +Scroll the current window down by the full window size. +.It Ic h +Move the cursor of the current window left by one column. +.It Ic j +Move the cursor of the current window down by one line. +.It Ic k +Move the cursor of the current window up by one line. +.It Ic l +Move the cursor of the current window right by one column. +.It Ic ^S +Stop output in the current window. +.It Ic ^Q +Start output in the current window. +.It Ic : +Enter a line to be executed as long commands. +Normal line +editing characters (erase character, erase word, erase line) +are supported. +.El +.Ss Long Commands +Long commands are a sequence of statements +parsed much like a programming language, with a syntax +similar to that of C. Numeric and string expressions and variables +are supported, as well as conditional statements. +.Pp +There are two data types: string and number. A string is a sequence +of letters or digits beginning with a letter. ``_'' and ``.'' are +considered letters. Alternately, non-alphanumeric characters can +be included in strings by quoting them in ``"'' or escaping them +with ``\\''. In addition, the ``\\'' sequences of C are supported, +both inside and outside quotes (e.g., ``\\n'' is a new line, +``\\r'' a carriage return). For example, these are legal strings: +abcde01234, "&#$^*&#", ab"$#"cd, ab\\$\\#cd, "/usr/ucb/window". +.Pp +A number is an integer value in one of three forms: +a decimal number, an octal number preceded by ``0'', +or a hexadecimal number preceded by ``0x'' or ``0X''. The natural +machine integer size is used (i.e., the signed integer type +of the C compiler). As in C, a non-zero number represents +a boolean true. +.Pp +The character ``#'' begins a comment which terminates at the +end of the line. +.Pp +A statement is either a conditional or an expression. Expression +statements are terminated with a new line or ``;''. To continue +an expression on the next line, terminate the first line with ``\\''. +.Ss Conditional Statement +.Nm Window +has a single control structure: +the fully bracketed if statement in the form +.Pp +.Bd -literal -offset indent -compact +if then +\t +\t... +elsif then +\t +\t... +else +\t +\t... +endif +.Ed +.Pp +The +.Ic else +and +.Ic elsif +parts are optional, and the latter can +be repeated any number of times. + +must be numeric. +.Ss Expressions +Expressions in +.Nm window +are similar to those in the +C language, with most C operators supported on numeric +operands. In addition, some are overloaded to operate on strings. +.Pp +When an expression is used as a statement, its value is discarded +after evaluation. Therefore, only expressions with side +effects (assignments and function calls) are useful as statements. +.Pp +Single valued (no arrays) variables are supported, of both +numeric and string values. Some variables are predefined. They +are listed below. +.Pp +The operators in order of increasing precedence: +.Bl -tag -width Fl +.It Xo +.Aq Va expr1 +.Ic = +.Aq Va expr2 +.Xc +Assignment. The variable of name +.Aq Va expr1 , +which must be string valued, +is assigned the result of +.Aq Va expr2 . +Returns the value of +.Aq Va expr2 . +.It Xo +.Aq Va expr1 +.Ic ? +.Aq Va expr2 +.Ic : +.Aq Va expr3 +.Xc +Returns the value of +.Aq Va expr2 +if +.Aq Va expr1 +evaluates true +(non-zero numeric value); returns the value of +.Aq Va expr3 +otherwise. Only +one of +.Aq Va expr2 +and +.Aq Va expr3 +is evaluated. +.Aq Va Expr1 +must +be numeric. +.It Xo +.Aq Va expr1 +.Ic \&|\&| +.Aq Va expr2 +.Xc +Logical or. Numeric values only. Short circuit evaluation is supported +(i.e., if +.Aq Va expr1 +evaluates true, then +.Aq Va expr2 +is not evaluated). +.It Xo +.Aq Va expr1 +.Ic \&&\&& +.Aq Va expr2 +.Xc +Logical and with short circuit evaluation. Numeric values only. +.It Xo +.Aq Va expr1 +.Ic \&| +.Aq Va expr2 +.Xc +Bitwise or. Numeric values only. +.It Xo +.Aq Va expr1 +.Ic ^ +.Aq Va expr2 +.Xc +Bitwise exclusive or. Numeric values only. +.It Xo +.Aq Va expr1 +.Ic \&& +.Aq Va expr2 +.Xc +Bitwise and. Numeric values only. +.It Xo +.Aq Va expr1 +.Ic == +.Aq Va expr2 , +.Aq Va expr1 +.Ic != +.Aq expr2 +.Xc +Comparison (equal and not equal, respectively). The boolean +result (either 1 or 0) of the comparison is returned. The +operands can be numeric or string valued. One string operand +forces the other to be converted to a string in necessary. +.It Xo +.Aq Va expr1 +.Ic < +.Aq Va expr2 , +.Aq Va expr1 +.Ic > +.Aq Va expr2 , +.Aq Va expr1 +.Ic <= +.Aq Va expr2 , +.Xc +Less than, greater than, less than or equal to, +greater than or equal to. Both numeric and string values, with +automatic conversion as above. +.It Xo +.Aq Va expr1 +.Ic << +.Aq Va expr2 , +.Aq Va expr1 +.Ic >> +.Aq Va expr2 +.Xc +If both operands are numbers, +.Aq Va expr1 +is bit +shifted left (or right) by +.Aq Va expr2 +bits. If +.Aq Va expr1 +is +a string, then its first (or last) +.Aq Va expr2 +characters are +returns (if +.Aq Va expr2 +is also a string, then its length is used +in place of its value). +.It Xo +.Aq Va expr1 +.Ic + +.Aq Va expr2 , +.Aq Va expr1 +.Ic - +.Aq Va expr2 +.Xc +Addition and subtraction on numbers. For ``+'', if one +argument is a string, then the other is converted to a string, +and the result is the concatenation of the two strings. +.It Xo +.Aq Va expr1 +.Ic \&* +.Aq Va expr2 , +.Aq Va expr1 +.Ic \&/ +.Aq Va expr2 , +.Aq Va expr1 +.Ic \&% +.Aq Va expr2 +.Xc +Multiplication, division, modulo. Numbers only. +.It Xo +.Ic \- Ns Aq Va expr , +.Ic ~ Ns Aq Va expr , +.Ic \&! Ns Aq Va expr , +.Ic \&$ Ns Aq Va expr , +.Ic \&$? Ns Aq Va expr +.Xc +The first three are unary minus, bitwise complement and logical complement +on numbers only. The operator, ``$'', takes +.Aq Va expr +and returns +the value of the variable of that name. If +.Aq Va expr +is numeric +with value +.Ar n +and it appears within an alias macro (see below), +then it refers to the nth argument of the alias invocation. ``$?'' +tests for the existence of the variable +.Aq Va expr , +and returns 1 +if it exists or 0 otherwise. +.It Xo +.Ao Va expr Ac Ns Pq Aq Ar arglist +.Xc +Function call. +.Aq Va Expr +must be a string that is the unique +prefix of the name of a builtin +.Nm window +function +or the full name of a user defined alias macro. In the case of a builtin +function, +.Aq Ar arglist +can be in one of two forms: +.Bd -literal -offset indent +, , ... +argname1 = , argname2 = , ... +.Ed +.Pp +The two forms can in fact be intermixed, but the result is +unpredictable. Most arguments can be omitted; default values will +be supplied for them. The +.Ar argnames +can be unique prefixes +of the the argument names. The commas separating +arguments are used only to disambiguate, and can usually be omitted. +.Pp +Only the first argument form is valid for user defined aliases. Aliases +are defined using the +.Ic alias +builtin function (see below). Arguments +are accessed via a variant of the variable mechanism (see ``$'' operator +above). +.Pp +Most functions return value, but some are used for side effect +only and so must be used as statements. When a function or an alias is used +as a statement, the parenthesis surrounding +the argument list may be omitted. Aliases return no value. +.El +.Ss Builtin Functions +The arguments are listed by name in their natural +order. Optional arguments are in square brackets +.Sq Op . +Arguments +that have no names are in angle brackets +.Sq <> . +An argument meant to be a boolean flag (often named +.Ar flag ) +can be one of +.Ar on , +.Ar off , +.Ar yes , +.Ar no , +.Ar true , +or +.Ar false , +with +obvious meanings, or it can be a numeric expression, +in which case a non-zero value is true. +.Bl -tag -width Fl +.It Xo +.Ic alias Ns Po Bq Aq Ar string , +.Bq Aq Ar string\-list Pc +.Xc +If no argument is given, all currently defined alias macros are +listed. Otherwise, +.Aq Ar string +is defined as an alias, +with expansion +.Aq Ar string\-list > . +The previous definition of +.Aq Ar string , +if any, is returned. Default for +.Aq Ar string\-list +is no change. +.It Ic close Ns Pq Aq Ar window\-list +Close the windows specified in +.Aq Ar window\-list . +If +.Aq Ar window\-list +is the word +.Ar all , +than all windows are closed. No value is returned. +.It Ic cursormodes Ns Pq Bq Ar modes +Set the window cursor to +.Ar modes . +.Ar Modes +is the bitwise +or of the mode bits defined as the variables +.Ar m_ul +(underline), +.Ar m_rev +(reverse video), +.Ar m_blk +(blinking), +and +.Ar m_grp +(graphics, terminal dependent). Return +value is the previous modes. Default is no change. +For example, +.Li cursor($m_rev$m_blk) +sets the window cursors to blinking +reverse video. +.It Ic default_nline Ns Pq Bq Ar nline +Set the default buffer size to +.Ar nline . +Initially, it is +48 lines. Returns the old default buffer size. Default is +no change. Using a very large buffer can slow the program down +considerably. +.It Ic default_shell Ns Pq Bq Aq Ar string\-list +Set the default window shell program to +.Aq Ar string\-list . +Returns +the first string in the old shell setting. Default is no change. Initially, +the default shell is taken from the environment variable +.Ev SHELL . +.It Ic default_smooth Ns Pq Bq Ar flag +Set the default value of the +.Ar smooth +argument +to the command +.Nm window +(see below). The argument +is a boolean flag (one of +.Ar on , +.Ar off , +.Ar yes , +.Ar no , +.Ar true , +.Ar false , +or a number, +as described above). Default is no change. +The old value (as a number) is returned. +The initial value is 1 (true). +.It Xo +.Ic echo Ns ( Op Ar window , +.Bq Aq Ar string\-list ) +.Xc +Write the list of strings, +.Aq Ar string-list , +to +.Nm window , +separated +by spaces and terminated with a new line. The strings are only +displayed in the window, the processes in the window are not +involved (see +.Ic write +below). No value is returned. Default +is the current window. +.It Ic escape Ns Pq Bq Ar escapec +Set the escape character to +.Ar escape-char . +Returns the old +escape character as a one-character string. Default is no +change. +.Ar Escapec +can be a string of a single character, or +in the form +.Fl ^X , +meaning +.No control\- Ns Ar X . +.It Xo +.Ic foreground Ns ( Bq Ar window , +.Bq Ar flag ) +.Xc +Move +.Nm window +in or out of foreground. +.Ar Flag +is a boolean value. The old foreground flag +is returned. Default for +.Nm window +is the current window, +default for +.Ar flag +is no change. +.It Xo +.Ic label Ns ( Bq Ar window , +.Bq Ar label ) +.Xc +Set the label of +.Nm window +to +.Ar label . +Returns the old +label as a string. Default for +.Nm window +is the current +window, default for +.Ar label +is no change. To turn +off a label, set it to an empty string (""). +.It Ic list Ns Pq +No arguments. List the identifiers and labels of all windows. No +value is returned. +.It Ic select Ns Pq Bq Ar window +Make +.Nm window +the current window. The previous current window +is returned. Default is no change. +.It Ic source Ns Pq Ar filename +Read and execute the long commands in +.Ar filename . +Returns \-1 if the file cannot be read, 0 otherwise. +.It Ic terse Ns Pq Bq flag +Set terse mode to +.Ar flag . +In terse mode, the command window +stays hidden even in command mode, and errors are reported by +sounding the terminal's bell. +.Ar Flag +can take on the same +values as in +.Ar foreground +above. Returns the old terse flag. +Default is no change. +.It Ic unalias Ns Pq Ar alias +Undefine +.Ar alias . +Returns -1 if +.Ar alias +does not exist, +0 otherwise. +.It Ic unset Ns Pq Ar variable +Undefine +.Ar variable . +Returns -1 if +.Ar variable +does not exist, +0 otherwise. +.It Ic variables Ns Pq +No arguments. List all variables. No value is returned. +.It Xo +.Ic window Ns ( Bq Ar row , +.Bq Ar column , +.Bq Ar nrow , +.Bq Ar ncol , +.Bq Ar nline , +.Bq Ar label , +.Bq Ar pty , +.Bq Ar frame , +.Bq Ar mapnl , +.Bq Ar keepopen , +.Bq Ar smooth , +.Bq Ar shell ) . +.Xc +Open a window with upper left corner at +.Ar row , +.Ar column +and size +.Ar nrow , +.Ar ncol . +If +.Ar nline +is specified, +then that many lines are allocated for the text buffer. Otherwise, +the default buffer size is used. Default values for +.Ar row , +.Ar column , +.Ar nrow , +and +.Ar ncol +are, respectively, +the upper, left-most, lower, or right-most extremes of the +screen. +.Ar Label +is the label string. +.Ar Frame , +.Ar pty , +and +.Ar mapnl +are flag values +interpreted in the same way as the argument to +.Ar foreground +(see above); +they mean, respectively, put a frame around this window (default true), +allocate pseudo-terminal for this window rather than socketpair (default +true), and map new line characters in this window to carriage return +and line feed (default true if socketpair is used, false otherwise). +Normally, a window is automatically closed when its process +exits. Setting +.Ar keepopen +to true (default false) prevents this +action. When +.Ar smooth +is true, the screen is updated more frequently +(for this window) to produce a more terminal-like behavior. +The default value of +.Ar smooth +is set by the +.Ar default_smooth +command (see above). +.Ar Shell +is a list of strings that will be used as the shell +program to place in the window (default is the program specified +by +.Ar default_shell , +see above). The created window's identifier +is returned as a number. +.It Xo +.Ic write Ns ( Bq Ar window , +.Bq Aq Ar string\-list ) +.Xc +Send the list of strings, +.Aq Ar string-list , +to +.Nm window , +separated +by spaces but not terminated with a new line. The strings are actually +given to the window as input. No value is returned. Default +is the current window. +.El +.Ss Predefined Variables +These variables are for information only. Redefining them does +not affect the internal operation of +.Nm window . +.Bl -tag -width modes +.It Ar baud +The baud rate as a number between 50 and 38400. +.It Ar modes +The display modes (reverse video, underline, blinking, graphics) +supported by the physical terminal. The value of +.Ar modes +is the bitwise or of some of the one bit values, +.Ar m_blk , +.Ar m_grp , +.Ar m_rev , +and +.Ar m_ul +(see below). +These values are useful +in setting the window cursors' modes (see +.Ar cursormodes +above). +.It Ar m_blk +The blinking mode bit. +.It Ar m_grp +The graphics mode bit (not very useful). +.It Ar m_rev +The reverse video mode bit. +.It Ar m_ul +The underline mode bit. +.It Ar ncol +The number of columns on the physical screen. +.It Ar nrow +The number of rows on the physical screen. +.It Ar term +The terminal type. The standard name, found in the second name +field of the terminal's +.Ev TERMCAP +entry, is used. +.Sh ENVIRONMENT +.Nm Window +utilizes these environment variables: +.Ev HOME , +.Ev SHELL , +.Ev TERM , +.Ev TERMCAP , +.Ev WINDOW_ID . +.Sh FILES +.Bl -tag -width /dev/[pt]ty[pq]? -compact +.It Pa ~/.windowrc +startup command file. +.It Pa /dev/[pt]ty[pq]? +pseudo-terminal devices. +.El +.Sh HISTORY +The +.Nm window +command appeared in +.Bx 4.3 . +.Sh DIAGNOSTICS +Should be self explanatory. diff --git a/usr/src/usr.bin/window/windowrc b/usr/src/usr.bin/window/windowrc new file mode 100644 index 0000000000..47d3b1c26a --- /dev/null +++ b/usr/src/usr.bin/window/windowrc @@ -0,0 +1,85 @@ +# Copyright (c) 1983 The Regents of the University of California. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)windowrc 3.9 (Berkeley) 4/18/91 +# + +# Configuration file example for window manager +# To be installed in ~/.windowrc +# +# Create two unequal sized windows of full screen width, +# and set up some useful aliases. +# + +# +# Optional settings +# +# terse on # set terse mode +# escape "^A" # set escape character +# nline 100 # set default buffer size + # initially, this is 48 + +# +# Make two windows +# The bottom one is MIN(24, total lines * 3 / 4) lines +# The top one is the rest of the screen. +# +three_fourth = $nrow - ((_ = $nrow * 3 / 4) > 24 ? 24 : $_) +unset _ +window row = 0, nrow = $three_fourth - 1, label = "Top" +window row = $three_fourth, label = "Local" + +# +# Useful aliases +# +# +# Standard window +# +alias std "window r = $three_fourth, l = $?1 ? $1 : ''" +# +# Sysline, add your own options +# +alias sysline "_ = select();" \ + "foreground window(r = 0, nr = 1, nc = $ncol + 1, nl = 0," \ + "l = sysline, pty = no, frame = no, sh = sysline \\-w), 1;" \ + "select $_; unset _" +# +# Rlogin +# +alias rlogin "window r = $three_fourth, l = $1, pty = no, mapnl = no," \ + "sh = sh \\-c 'echo $TERMCAP | rsh ' + $1 + ' \\'cat > .TERMCAP\\' ;" \ + "exec rlogin ' + $1" +alias rl rlogin \$1 +# +# Two equal windows +# +alias two "window r = 1, nr = $nrow / 2 - 1, l = top;" \ + "window r = $nrow / 2 + 1, l = bottom" diff --git a/usr/src/usr.bin/window/ww.h b/usr/src/usr.bin/window/ww.h new file mode 100644 index 0000000000..9acbc8e3b3 --- /dev/null +++ b/usr/src/usr.bin/window/ww.h @@ -0,0 +1,310 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ww.h 3.63 (Berkeley) 3/2/91 + */ + +#ifdef OLD_TTY +#include +#else +#include +#endif +#include +#include + +#define NWW 30 /* maximum number of windows */ + + /* a rectangle */ +struct ww_dim { + int nr; /* number of rows */ + int nc; /* number of columns */ + int t, b; /* top, bottom */ + int l, r; /* left, right */ +}; + + /* a coordinate */ +struct ww_pos { + int r; /* row */ + int c; /* column */ +}; + + /* the window structure */ +struct ww { + /* general flags and states */ + char ww_state; /* state of window */ + char ww_oflags; /* wwopen flags */ + + /* information for overlap */ + struct ww *ww_forw; /* doubly linked list, for overlapping info */ + struct ww *ww_back; + char ww_index; /* the window index, for wwindex[] */ + char ww_order; /* the overlapping order */ + + /* sizes and positions */ + struct ww_dim ww_w; /* window size and pos */ + struct ww_dim ww_b; /* buffer size and pos */ + struct ww_dim ww_i; /* the part inside the screen */ + struct ww_pos ww_cur; /* the cursor position, relative to ww_w */ + + /* arrays */ + char **ww_win; /* the window */ + union ww_char **ww_buf; /* the buffer */ + char **ww_fmap; /* map for frame and box windows */ + short *ww_nvis; /* how many ww_buf chars are visible per row */ + + /* information for wwwrite() and company */ + char ww_wstate; /* state for outputting characters */ + char ww_modes; /* current display modes */ + char ww_insert; /* insert mode */ + char ww_mapnl; /* map \n to \r\n */ + char ww_noupdate; /* don't do updates in wwwrite() */ + char ww_unctrl; /* expand control characters */ + char ww_nointr; /* wwwrite() not interruptable */ + char ww_hascursor; /* has fake cursor */ + + /* things for the window process and io */ + char ww_ispty; /* ww_pty is really a pty, not socket pair */ + char ww_stopped; /* output stopped */ + int ww_pty; /* file descriptor of pty or socket pair */ + int ww_socket; /* other end of socket pair */ + int ww_pid; /* pid of process, if WWS_HASPROC true */ + char ww_ttyname[11]; /* "/dev/ttyp?" */ + char *ww_ob; /* output buffer */ + char *ww_obe; /* end of ww_ob */ + char *ww_obp; /* current read position in ww_ob */ + char *ww_obq; /* current write position in ww_ob */ + + /* things for the user, they really don't belong here */ + char ww_id; /* the user window id */ + char ww_center; /* center the label */ + char ww_hasframe; /* frame it */ + char ww_keepopen; /* keep it open after the process dies */ + char *ww_label; /* the user supplied label */ + struct ww_dim ww_alt; /* alternate position and size */ +}; + + /* state of a tty */ +struct ww_tty { +#ifdef OLD_TTY + struct sgttyb ww_sgttyb; + struct tchars ww_tchars; + struct ltchars ww_ltchars; + int ww_lmode; + int ww_ldisc; +#else + struct termios ww_termios; +#endif + int ww_fflags; +}; + +union ww_char { + short c_w; /* as a word */ + struct { +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + char C_c; /* the character part */ + char C_m; /* the mode part */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + char C_m; /* the mode part */ + char C_c; /* the character part */ +#endif + } c_un; +}; +#define c_c c_un.C_c +#define c_m c_un.C_m + + /* for display update */ +struct ww_update { + int best_gain; + int best_col; + int gain; +}; + + /* parts of ww_char */ +#define WWC_CMASK 0x00ff +#define WWC_MMASK 0xff00 +#define WWC_MSHIFT 8 + + /* c_m bits */ +#define WWM_REV 0x01 /* reverse video */ +#define WWM_BLK 0x02 /* blinking */ +#define WWM_UL 0x04 /* underlined */ +#define WWM_GRP 0x08 /* graphics */ +#define WWM_DIM 0x10 /* half intensity */ +#define WWM_USR 0x20 /* user specified mode */ +#define WWM_GLS 0x40 /* window only, glass, i.e., transparent */ + + /* ww_state values */ +#define WWS_INITIAL 0 /* just opened */ +#define WWS_HASPROC 1 /* has process on pty */ +#define WWS_DEAD 3 /* child died */ + + /* flags for ww_fmap */ +#define WWF_U 0x01 +#define WWF_R 0x02 +#define WWF_D 0x04 +#define WWF_L 0x08 +#define WWF_MASK (WWF_U|WWF_R|WWF_D|WWF_L) +#define WWF_LABEL 0x40 +#define WWF_TOP 0x80 + + /* flags to wwopen() */ +#define WWO_PTY 0x01 /* want pty */ +#define WWO_SOCKET 0x02 /* want socket pair */ +#define WWO_REVERSE 0x04 /* make it all reverse video */ +#define WWO_GLASS 0x08 /* make it all glass */ +#define WWO_FRAME 0x10 /* this is a frame window */ + + /* special ww_index value */ +#define WWX_NOBODY NWW + + /* error codes */ +#define WWE_NOERR 0 +#define WWE_SYS 1 /* system error */ +#define WWE_NOMEM 2 /* out of memory */ +#define WWE_TOOMANY 3 /* too many windows */ +#define WWE_NOPTY 4 /* no more ptys */ +#define WWE_SIZE 5 /* bad window size */ +#define WWE_BADTERM 6 /* bad terminal type */ +#define WWE_CANTDO 7 /* dumb terminal */ + + /* wwtouched[] bits, there used to be more than one */ +#define WWU_TOUCHED 0x01 /* touched */ + + /* the window structures */ +struct ww wwhead; +struct ww *wwindex[NWW + 1]; /* last location is for wwnobody */ +struct ww wwnobody; + + /* tty things */ +struct ww_tty wwoldtty; /* the old (saved) terminal settings */ +struct ww_tty wwnewtty; /* the new (current) terminal settings */ +struct ww_tty wwwintty; /* the terminal settings for windows */ +char *wwterm; /* the terminal name */ +char wwtermcap[1024]; /* place for the termcap */ + + /* generally useful variables */ +int wwnrow, wwncol; /* the screen size */ +char wwavailmodes; /* actually supported modes */ +char wwcursormodes; /* the modes for the fake cursor */ +char wwwrap; /* terminal has auto wrap around */ +int wwdtablesize; /* result of getdtablesize() call */ +char **wwsmap; /* the screen map */ +union ww_char **wwos; /* the old (current) screen */ +union ww_char **wwns; /* the new (desired) screen */ +char *wwtouched; /* wwns changed flags */ +struct ww_update *wwupd; /* for display update */ +int wwospeed; /* output baud rate, copied from wwoldtty */ +int wwbaud; /* wwospeed converted into actual number */ +int wwcursorrow, wwcursorcol; /* where we want the cursor to be */ +int wwerrno; /* error number */ + + /* statistics */ +int wwnflush, wwnwr, wwnwre, wwnwrz, wwnwrc; +int wwnwwr, wwnwwra, wwnwwrc; +int wwntokdef, wwntokuse, wwntokbad, wwntoksave, wwntokc; +int wwnupdate, wwnupdline, wwnupdmiss; +int wwnupdscan, wwnupdclreol, wwnupdclreos, wwnupdclreosmiss, wwnupdclreosline; +int wwnread, wwnreade, wwnreadz, wwnreadc; +int wwnwread, wwnwreade, wwnwreadz, wwnwreadd, wwnwreadc, wwnwreadp; +int wwnselect, wwnselecte, wwnselectz; + + /* quicky macros */ +#define wwsetcursor(r,c) (wwcursorrow = (r), wwcursorcol = (c)) +#define wwcurtowin(w) wwsetcursor((w)->ww_cur.r, (w)->ww_cur.c) +#define wwunbox(w) wwunframe(w) +#define wwclreol(w,r,c) wwclreol1((w), (r), (c), 0) +#define wwredrawwin(w) wwredrawwin1((w), (w)->ww_i.t, (w)->ww_i.b, 0) +#define wwupdate() wwupdate1(0, wwnrow); + + /* things for handling input */ +void wwrint(); /* interrupt handler */ +struct ww *wwcurwin; /* window to copy input into */ +char *wwib; /* input (keyboard) buffer */ +char *wwibe; /* wwib + sizeof buffer */ +char *wwibp; /* current read position in buffer */ +char *wwibq; /* current write position in buffer */ +#define wwgetc() (wwibp < wwibq ? *wwibp++ & 0x7f : -1) +#define wwpeekc() (wwibp < wwibq ? *wwibp & 0x7f : -1) +#define wwungetc(c) (wwibp > wwib ? *--wwibp = (c) : -1) + + /* things for short circuiting wwiomux() */ +char wwintr; /* interrupting */ +char wwsetjmp; /* want a longjmp() from wwrint() and wwchild() */ +jmp_buf wwjmpbuf; /* jmpbuf for above */ +#define wwinterrupt() wwintr +#define wwsetintr() do { wwintr = 1; if (wwsetjmp) longjmp(wwjmpbuf, 1); } \ + while (0) +#define wwclrintr() (wwintr = 0) + + /* the window virtual terminal */ +#define WWT_TERM "window-v2" +#define WWT_TERMCAP "WW|window-v2|window program version 2:\ + :am:bs:da:db:ms:pt:cr=^M:nl=^J:bl=^G:ta=^I:\ + :cm=\\EY%+ %+ :le=^H:nd=\\EC:up=\\EA:do=\\EB:ho=\\EH:\ + :cd=\\EJ:ce=\\EK:cl=\\EE:me=\\Er^?:" +#define WWT_REV "se=\\ErA:so=\\EsA:mr=\\EsA:" +#define WWT_BLK "BE=\\ErB:BS=\\EsB:mb=\\EsB:" +#define WWT_UL "ue=\\ErD:us=\\EsD:" +#define WWT_GRP "ae=\\ErH:as=\\EsH:" +#define WWT_DIM "HE=\\ErP:HS=\\EsP:mh=\\EsP:" +#define WWT_USR "XE=\\Er`:XS=\\Es`:" +#define WWT_ALDL "al=\\EL:dl=\\EM:" +#define WWT_IMEI "im=\\E@:ei=\\EO:ic=:mi:" /* XXX, ic for emacs bug */ +#define WWT_IC "ic=\\EP:" +#define WWT_DC "dc=\\EN:" +char wwwintermcap[1024]; /* terminal-specific but window-independent + part of the window termcap */ + + /* our functions */ +struct ww *wwopen(); +void wwchild(); +void wwsuspend(); +char **wwalloc(); +char *wwerror(); + + /* c library functions */ +char *malloc(); +char *calloc(); +char *getenv(); +char *tgetstr(); +char *rindex(); +char *strcpy(); +char *strcat(); + +#undef MIN +#undef MAX +#define MIN(x, y) ((x) > (y) ? (y) : (x)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) diff --git a/usr/src/usr.bin/window/wwadd.c b/usr/src/usr.bin/window/wwadd.c new file mode 100644 index 0000000000..d1a4b38bca --- /dev/null +++ b/usr/src/usr.bin/window/wwadd.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwadd.c 3.14 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +/* + * Stick w1 behind w2. + */ +wwadd(w1, w2) +register struct ww *w1; +struct ww *w2; +{ + register i; + register struct ww *w; + + w1->ww_order = w2->ww_order + 1; + w1->ww_back = w2; + w1->ww_forw = w2->ww_forw; + w2->ww_forw->ww_back = w1; + w2->ww_forw = w1; + + for (w = w1->ww_forw; w != &wwhead; w = w->ww_forw) + w->ww_order++; + for (i = w1->ww_i.t; i < w1->ww_i.b; i++) { + register j; + register char *smap = wwsmap[i]; + register char *win = w1->ww_win[i]; + union ww_char *ns = wwns[i]; + union ww_char *buf = w1->ww_buf[i]; + int nvis = 0; + int nchanged = 0; + + for (j = w1->ww_i.l; j < w1->ww_i.r; j++) { + w = wwindex[smap[j]]; + if (w1->ww_order > w->ww_order) + continue; + if (win[j] & WWM_GLS) + continue; + if (w != &wwnobody && w->ww_win[i][j] == 0) + w->ww_nvis[i]--; + smap[j] = w1->ww_index; + if (win[j] == 0) + nvis++; + ns[j].c_w = buf[j].c_w ^ win[j] << WWC_MSHIFT; + nchanged++; + } + if (nchanged > 0) + wwtouched[i] |= WWU_TOUCHED; + w1->ww_nvis[i] = nvis; + } +} diff --git a/usr/src/usr.bin/window/wwalloc.c b/usr/src/usr.bin/window/wwalloc.c new file mode 100644 index 0000000000..cf2519d43f --- /dev/null +++ b/usr/src/usr.bin/window/wwalloc.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwalloc.c 3.11 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +char ** +wwalloc(row, col, nrow, ncol, size) +{ + register char *p, **pp; + register int i; + + /* fast, call malloc only once */ + pp = (char **) + malloc((unsigned) sizeof (char **) * nrow + size * nrow * ncol); + if (pp == 0) { + wwerrno = WWE_NOMEM; + return 0; + } + p = (char *)&pp[nrow]; + col *= size; + size /= sizeof (char); /* paranoid */ + size *= ncol; + for (i = 0; i < nrow; i++) { + pp[i] = p - col; + p += size; + } + return pp - row; +} + +wwfree(p, row) +register char **p; +{ + free((char *)(p + row)); +} diff --git a/usr/src/usr.bin/window/wwbox.c b/usr/src/usr.bin/window/wwbox.c new file mode 100644 index 0000000000..cf2884cc29 --- /dev/null +++ b/usr/src/usr.bin/window/wwbox.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwbox.c 3.8 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwbox(w, r, c, nr, nc) +register struct ww *w; +register r, c; +int nr, nc; +{ + register r1, c1; + register i; + + r1 = r + nr - 1; + c1 = c + nc - 1; + wwframec(w, r, c, WWF_D|WWF_R); + for (i = c + 1; i < c1; i++) + wwframec(w, r, i, WWF_L|WWF_R); + wwframec(w, r, i, WWF_L|WWF_D); + for (i = r + 1; i < r1; i++) + wwframec(w, i, c1, WWF_U|WWF_D); + wwframec(w, i, c1, WWF_U|WWF_L); + for (i = c1 - 1; i > c; i--) + wwframec(w, r1, i, WWF_R|WWF_L); + wwframec(w, r1, i, WWF_R|WWF_U); + for (i = r1 - 1; i > r; i--) + wwframec(w, i, c, WWF_D|WWF_U); +} diff --git a/usr/src/usr.bin/window/wwchild.c b/usr/src/usr.bin/window/wwchild.c new file mode 100644 index 0000000000..909e78efd2 --- /dev/null +++ b/usr/src/usr.bin/window/wwchild.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwchild.c 3.15 (Berkeley) 3/2/91"; +#endif /* not lint */ + +#include "ww.h" +#include +#include + +void +wwchild() +{ + extern errno; + int olderrno; + register struct ww **wp; + union wait w; + int pid; + char collected = 0; + + olderrno = errno; + while ((pid = + wait3((int *)&w, WNOHANG|WUNTRACED, (struct rusage *)0)) > 0) { + for (wp = wwindex; wp < &wwindex[NWW]; wp++) { + if (*wp && (*wp)->ww_state == WWS_HASPROC + && (*wp)->ww_pid == pid) { + (*wp)->ww_state = WWS_DEAD; + collected = 1; + break; + } + } + } + errno = olderrno; + /* jump out of wwiomux when somebody dies */ + if (collected) + wwsetintr(); +} diff --git a/usr/src/usr.bin/window/wwclose.c b/usr/src/usr.bin/window/wwclose.c new file mode 100644 index 0000000000..8d11ed4d0f --- /dev/null +++ b/usr/src/usr.bin/window/wwclose.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwclose.c 3.18 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwclose(w) +register struct ww *w; +{ + wwindex[w->ww_index] = 0; + if (w->ww_pty >= 0) + (void) close(w->ww_pty); + if (w->ww_socket >= 0) + (void) close(w->ww_socket); + wwfree((char **)w->ww_win, w->ww_w.t); + wwfree((char **)w->ww_buf, w->ww_b.t); + if (w->ww_fmap != 0) + wwfree((char **)w->ww_fmap, w->ww_w.t); + free((char *)(w->ww_nvis + w->ww_w.t)); + if (w->ww_ob != 0) + free(w->ww_ob); + free((char *)w); +} diff --git a/usr/src/usr.bin/window/wwclreol.c b/usr/src/usr.bin/window/wwclreol.c new file mode 100644 index 0000000000..971822bd3a --- /dev/null +++ b/usr/src/usr.bin/window/wwclreol.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwclreol.c 3.20 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +/* + * Clear w to the end of line. + * If cleared is true, then the screen line has already been cleared. + */ +wwclreol1(w, row, col, cleared) +register struct ww *w; +int row, col; +char cleared; +{ + register i; + + /* + * Clear the buffer right off + */ + { + register union ww_char *buf; + + buf = &w->ww_buf[row][col]; + for (i = w->ww_b.r - col; --i >= 0;) + buf++->c_w = ' '; + } + + /* + * If can't see it, just return. + */ + if (row < w->ww_i.t || row >= w->ww_i.b + || w->ww_i.r <= 0 || w->ww_i.r <= col) + return; + + if (col < w->ww_i.l) + col = w->ww_i.l; + + /* + * Now fix wwns. + */ + { + register union ww_char *s; + register char *smap, *win; + + i = col; + smap = &wwsmap[row][i]; + s = &wwns[row][i]; + win = &w->ww_win[row][i]; + for (i = w->ww_i.r - i; --i >= 0;) + if (*smap++ == w->ww_index) + s++->c_w = ' ' | *win++ << WWC_MSHIFT; + else + s++, win++; + } + if (!cleared) + wwtouched[row] |= WWU_TOUCHED; +} diff --git a/usr/src/usr.bin/window/wwclreos.c b/usr/src/usr.bin/window/wwclreos.c new file mode 100644 index 0000000000..7b16ea6579 --- /dev/null +++ b/usr/src/usr.bin/window/wwclreos.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwclreos.c 3.11 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwclreos(w, row, col) +register struct ww *w; +{ + register i; + + wwclreol(w, row, col); + for (i = row + 1; i < w->ww_b.b; i++) + wwclreol(w, i, w->ww_b.l); + /* XXX */ + if (!w->ww_noupdate) + wwupdate1(w->ww_i.t, w->ww_i.b); +} diff --git a/usr/src/usr.bin/window/wwcursor.c b/usr/src/usr.bin/window/wwcursor.c new file mode 100644 index 0000000000..f933a1b5f1 --- /dev/null +++ b/usr/src/usr.bin/window/wwcursor.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwcursor.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwcursor(w, on) +register struct ww *w; +{ + register char *win; + + if (on) { + if (w->ww_hascursor) + return; + w->ww_hascursor = 1; + } else { + if (!w->ww_hascursor) + return; + w->ww_hascursor = 0; + } + if (wwcursormodes != 0) { + win = &w->ww_win[w->ww_cur.r][w->ww_cur.c]; + *win ^= wwcursormodes; + if (w->ww_cur.r < w->ww_i.t || w->ww_cur.r >= w->ww_i.b + || w->ww_cur.c < w->ww_i.l || w->ww_cur.c >= w->ww_i.r) + return; + if (wwsmap[w->ww_cur.r][w->ww_cur.c] == w->ww_index) { + if (*win == 0) + w->ww_nvis[w->ww_cur.r]++; + else if (*win == wwcursormodes) + w->ww_nvis[w->ww_cur.r]--; + wwns[w->ww_cur.r][w->ww_cur.c].c_m ^= wwcursormodes; + wwtouched[w->ww_cur.r] |= WWU_TOUCHED; + } + } +} + +wwsetcursormodes(new) +register new; +{ + register i; + register struct ww *w; + register old = wwcursormodes; + + new &= wwavailmodes; + if (new == wwcursormodes) + return; + for (i = 0; i < NWW; i++) + if (wwindex[i] != 0 && (w = wwindex[i])->ww_hascursor) { + wwcursor(w, 0); + wwcursormodes = new; + wwcursor(w, 1); + wwcursormodes = old; + } + wwcursormodes = new; +} diff --git a/usr/src/usr.bin/window/wwdata.c b/usr/src/usr.bin/window/wwdata.c new file mode 100644 index 0000000000..9ffa20c84e --- /dev/null +++ b/usr/src/usr.bin/window/wwdata.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwdata.c 3.19 (Berkeley) 8/12/90"; +#endif /* not lint */ diff --git a/usr/src/usr.bin/window/wwdelchar.c b/usr/src/usr.bin/window/wwdelchar.c new file mode 100644 index 0000000000..0be6f3f0c5 --- /dev/null +++ b/usr/src/usr.bin/window/wwdelchar.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwdelchar.c 3.16 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwdelchar(w, row, col) +register struct ww *w; +{ + register i; + int nvis; + + /* + * First, shift the line. + */ + { + register union ww_char *p, *q; + + p = &w->ww_buf[row][col]; + q = p + 1; + for (i = w->ww_b.r - col; --i > 0;) + *p++ = *q++; + p->c_w = ' '; + } + + /* + * If can't see it, just return. + */ + if (row < w->ww_i.t || row >= w->ww_i.b + || w->ww_i.r <= 0 || w->ww_i.r <= col) + return; + + if (col < w->ww_i.l) + col = w->ww_i.l; + + /* + * Now find out how much is actually changed, and fix wwns. + */ + { + register union ww_char *buf; + register char *win; + register union ww_char *ns; + register char *smap; + char touched; + + nvis = 0; + smap = &wwsmap[row][col]; + for (i = col; i < w->ww_i.r && *smap++ != w->ww_index; i++) + ; + if (i >= w->ww_i.r) + return; + col = i; + buf = w->ww_buf[row]; + win = w->ww_win[row]; + ns = wwns[row]; + smap = &wwsmap[row][i]; + touched = wwtouched[row]; + for (; i < w->ww_i.r; i++) { + if (*smap++ != w->ww_index) + continue; + touched |= WWU_TOUCHED; + if (win[i]) + ns[i].c_w = + buf[i].c_w ^ win[i] << WWC_MSHIFT; + else { + nvis++; + ns[i] = buf[i]; + } + } + wwtouched[row] = touched; + } + + /* + * Can/Should we use delete character? + */ + if (tt.tt_delchar != 0 && nvis > (wwncol - col) / 2) { + register union ww_char *p, *q; + + xxdelchar(row, col); + p = &wwos[row][col]; + q = p + 1; + for (i = wwncol - col; --i > 0;) + *p++ = *q++; + p->c_w = ' '; + } +} diff --git a/usr/src/usr.bin/window/wwdelete.c b/usr/src/usr.bin/window/wwdelete.c new file mode 100644 index 0000000000..01b7544989 --- /dev/null +++ b/usr/src/usr.bin/window/wwdelete.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwdelete.c 3.19 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +/* + * Pull w free from the cover list. + */ +wwdelete(w) +register struct ww *w; +{ + register i; + + for (i = w->ww_i.t; i < w->ww_i.b; i++) { + register j; + register char *smap = wwsmap[i]; + register union ww_char *ns = wwns[i]; + register int nchanged = 0; + + for (j = w->ww_i.l; j < w->ww_i.r; j++) + if (smap[j] == w->ww_index) { + smap[j] = WWX_NOBODY; + ns[j].c_w = ' '; + nchanged++; + } + if (nchanged > 0) + wwtouched[i] |= WWU_TOUCHED; + } + + { + register struct ww *wp; + + for (wp = w->ww_forw; wp != &wwhead; wp = wp->ww_forw) + wp->ww_order--; + } + + if (w->ww_forw != &wwhead) + wwdelete1(w->ww_forw, + w->ww_i.t, w->ww_i.b, w->ww_i.l, w->ww_i.r); + + w->ww_back->ww_forw = w->ww_forw; + w->ww_forw->ww_back = w->ww_back; + w->ww_forw = w->ww_back = 0; +} + +wwdelete1(w, t, b, l, r) +register struct ww *w; +{ + int i; + int tt, bb, ll, rr; + char hasglass; + +again: + hasglass = 0; + tt = MAX(t, w->ww_i.t); + bb = MIN(b, w->ww_i.b); + ll = MAX(l, w->ww_i.l); + rr = MIN(r, w->ww_i.r); + if (tt >= bb || ll >= rr) { + if ((w = w->ww_forw) == &wwhead) + return; + goto again; + } + for (i = tt; i < bb; i++) { + register j; + register char *smap = wwsmap[i]; + register union ww_char *ns = wwns[i]; + register char *win = w->ww_win[i]; + register union ww_char *buf = w->ww_buf[i]; + int nvis = w->ww_nvis[i]; + int nchanged = 0; + + for (j = ll; j < rr; j++) { + if (smap[j] != WWX_NOBODY) + continue; + if (win[j] & WWM_GLS) { + hasglass = 1; + continue; + } + smap[j] = w->ww_index; + ns[j].c_w = buf[j].c_w ^ win[j] << WWC_MSHIFT; + nchanged++; + if (win[j] == 0) + nvis++; + } + if (nchanged > 0) + wwtouched[i] |= WWU_TOUCHED; + w->ww_nvis[i] = nvis; + } + if ((w = w->ww_forw) == &wwhead) + return; + if (hasglass) + goto again; + if (tt > t) + wwdelete1(w, t, tt, l, r); + if (bb < b) + wwdelete1(w, bb, b, l, r); + if (ll > l) + wwdelete1(w, tt, bb, l, ll); + if (rr < r) + wwdelete1(w, tt, bb, rr, r); +} diff --git a/usr/src/usr.bin/window/wwdelline.c b/usr/src/usr.bin/window/wwdelline.c new file mode 100644 index 0000000000..26d03bdce5 --- /dev/null +++ b/usr/src/usr.bin/window/wwdelline.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwdelline.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwdelline(w, row) +register struct ww *w; +int row; +{ + register i; + register union ww_char **cpp, **cqq; + register union ww_char *cp; + int row1, row2; + char deleted; + int visible; + + /* + * Scroll first. + */ + if ((row1 = row) < w->ww_i.t) { + row1 = w->ww_i.t; + } + if ((row2 = w->ww_b.b) > w->ww_i.b) { + row2 = w->ww_i.b; + visible = 0; + } else + visible = 1; + deleted = wwscroll1(w, row1, row2, 1, visible); + + /* + * Fix the buffer. + * But leave clearing the last line for wwclreol(). + */ + cpp = &w->ww_buf[row]; + cqq = cpp + 1; + cp = *cpp; + for (i = w->ww_b.b - row; --i > 0;) + *cpp++ = *cqq++; + *cpp = cp; + + /* + * Now clear the last line. + */ + if (visible) + wwclreol1(w, w->ww_b.b - 1, w->ww_b.l, deleted); + else { + cp += w->ww_b.l; + for (i = w->ww_b.nc; --i >= 0;) + cp++->c_w = ' '; + } +} diff --git a/usr/src/usr.bin/window/wwdump.c b/usr/src/usr.bin/window/wwdump.c new file mode 100644 index 0000000000..1dbecb7b64 --- /dev/null +++ b/usr/src/usr.bin/window/wwdump.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwdump.c 3.15 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +static char cmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +wwdumpwin(w) +register struct ww *w; +{ + register i, j; + + tt.tt_nmodes = 0; + (*tt.tt_clear)(); + for (i = w->ww_i.t; i < w->ww_i.b; i++) { + (*tt.tt_move)(i, w->ww_i.l); + for (j = w->ww_i.l; j < w->ww_i.r; j++) + (*tt.tt_putc)(w->ww_win[i][j] & WWM_GLS ? 'G' : ' '); + } +} + +wwdumpnvis(w) +register struct ww *w; +{ + register i; + char buf[20]; + + tt.tt_nmodes = 0; + (*tt.tt_clear)(); + for (i = w->ww_i.t; i < w->ww_i.b; i++) { + (*tt.tt_move)(i, w->ww_i.l); + (void) sprintf(buf, "%d", w->ww_nvis[i]); + (*tt.tt_write)(buf, strlen(buf)); + } +} + +wwdumpsmap() +{ + register i, j; + + tt.tt_nmodes = 0; + (*tt.tt_clear)(); + for (i = 0; i < wwnrow; i++) { + (*tt.tt_move)(i, 0); + for (j = 0; j < wwncol; j++) + (*tt.tt_putc)(cmap[wwsmap[i][j]]); + } +} + +wwdumpns() +{ + register i, j; + + (*tt.tt_clear)(); + for (i = 0; i < wwnrow; i++) { + (*tt.tt_move)(i, 0); + for (j = 0; j < wwncol; j++) { + tt.tt_nmodes = wwns[i][j].c_m & tt.tt_availmodes; + (*tt.tt_putc)(wwns[i][j].c_c); + } + } +} + +wwdumpos() +{ + register i, j; + + (*tt.tt_clear)(); + for (i = 0; i < wwnrow; i++) { + (*tt.tt_move)(i, 0); + for (j = 0; j < wwncol; j++) { + tt.tt_nmodes = wwos[i][j].c_m & tt.tt_availmodes; + (*tt.tt_putc)(wwns[i][j].c_c); + } + } +} diff --git a/usr/src/usr.bin/window/wwend.c b/usr/src/usr.bin/window/wwend.c new file mode 100644 index 0000000000..08690187f7 --- /dev/null +++ b/usr/src/usr.bin/window/wwend.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwend.c 3.16 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwend() +{ + xxend(); + (void) wwsettty(0, &wwoldtty); +} diff --git a/usr/src/usr.bin/window/wwenviron.c b/usr/src/usr.bin/window/wwenviron.c new file mode 100644 index 0000000000..23cd568ffd --- /dev/null +++ b/usr/src/usr.bin/window/wwenviron.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwenviron.c 3.27 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#if !defined(OLD_TTY) && !defined(TIOCSCTTY) && !defined(TIOCNOTTY) +#include +#endif +#include + +/* + * Set up the environment of this process to run in window 'wp'. + */ +wwenviron(wp) +register struct ww *wp; +{ + register i; +#ifndef TIOCSCTTY + int pgrp = getpid(); +#endif + char buf[1024]; + +#ifndef TIOCSCTTY + if ((i = open("/dev/tty", 0)) < 0) + goto bad; + if (ioctl(i, TIOCNOTTY, (char *)0) < 0) + goto bad; + (void) close(i); +#endif + if ((i = wp->ww_socket) < 0) { + if ((i = open(wp->ww_ttyname, 2)) < 0) + goto bad; + if (wwsettty(i, &wwwintty) < 0) + goto bad; + if (wwsetttysize(i, wp->ww_w.nr, wp->ww_w.nc) < 0) + goto bad; + } + (void) dup2(i, 0); + (void) dup2(i, 1); + (void) dup2(i, 2); + for (i = wwdtablesize - 1; i > 2; i--) + (void) close(i); +#ifdef TIOCSCTTY + (void) setsid(); + (void) ioctl(0, TIOCSCTTY, 0); +#else + (void) ioctl(0, TIOCSPGRP, (char *)&pgrp); + (void) setpgrp(pgrp, pgrp); +#endif + /* SIGPIPE is the only one we ignore */ + (void) signal(SIGPIPE, SIG_DFL); + (void) sigsetmask(0); + /* + * Two conditions that make destructive setenv ok: + * 1. setenv() copies the string, + * 2. we've already called tgetent which copies the termcap entry. + */ + (void) sprintf(buf, "%sco#%d:li#%d:%s", + WWT_TERMCAP, wp->ww_w.nc, wp->ww_w.nr, wwwintermcap); + (void) setenv("TERMCAP", buf, 1); + (void) sprintf(buf, "%d", wp->ww_id + 1); + (void) setenv("WINDOW_ID", buf, 1); + return 0; +bad: + wwerrno = WWE_SYS; + return -1; +} diff --git a/usr/src/usr.bin/window/wwerror.c b/usr/src/usr.bin/window/wwerror.c new file mode 100644 index 0000000000..91d4173fa4 --- /dev/null +++ b/usr/src/usr.bin/window/wwerror.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwerror.c 3.8 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +char * +wwerror() +{ + extern int errno; + char *strerror(); + + switch (wwerrno) { + case WWE_NOERR: + return "No error"; + case WWE_SYS: + return strerror(errno); + case WWE_NOMEM: + return "Out of memory"; + case WWE_TOOMANY: + return "Too many windows"; + case WWE_NOPTY: + return "Out of pseudo-terminals"; + case WWE_SIZE: + return "Bad window size"; + case WWE_BADTERM: + return "Unknown terminal type"; + case WWE_CANTDO: + return "Can't run window on this terminal"; + default: + return "Unknown error"; + } +} diff --git a/usr/src/usr.bin/window/wwflush.c b/usr/src/usr.bin/window/wwflush.c new file mode 100644 index 0000000000..08389de66b --- /dev/null +++ b/usr/src/usr.bin/window/wwflush.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwflush.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwflush() +{ + register row, col; + + if ((row = wwcursorrow) < 0) + row = 0; + else if (row >= wwnrow) + row = wwnrow - 1; + if ((col = wwcursorcol) < 0) + col = 0; + else if (col >= wwncol) + col = wwncol - 1; + xxmove(row, col); + xxflush(1); +} diff --git a/usr/src/usr.bin/window/wwframe.c b/usr/src/usr.bin/window/wwframe.c new file mode 100644 index 0000000000..65bdec69cd --- /dev/null +++ b/usr/src/usr.bin/window/wwframe.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwframe.c 3.20 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +#define frameok(w, r, c) (w1 = wwindex[wwsmap[r][c]], \ + w1->ww_fmap || w1->ww_order > (w)->ww_order) + +wwframe(w, wframe) +register struct ww *w; +struct ww *wframe; +{ + register r, c; + char a1, a2, a3; + char b1, b2, b3; + register char *smap; + register code; + register struct ww *w1; + + if (w->ww_w.t > 0) { + r = w->ww_w.t - 1; + c = w->ww_i.l - 1; + smap = &wwsmap[r + 1][c + 1]; + a1 = 0; + a2 = 0; + b1 = 0; + b2 = c < 0 || frameok(w, r, c); + + for (; c < w->ww_i.r; c++) { + if (c + 1 >= wwncol) { + a3 = 1; + b3 = 1; + } else { + a3 = w->ww_index == *smap++; + b3 = frameok(w, r, c + 1); + } + if (b2) { + code = 0; + if ((a1 || a2) && b1) + code |= WWF_L; + if ((a2 || a3) && b3) + code |= WWF_R; + if (code) + wwframec(wframe, r, c, code|WWF_TOP); + } + a1 = a2; + a2 = a3; + b1 = b2; + b2 = b3; + } + if ((a1 || a2) && b1 && b2) + wwframec(wframe, r, c, WWF_L|WWF_TOP); + } + + if (w->ww_w.b < wwnrow) { + r = w->ww_w.b; + c = w->ww_i.l - 1; + smap = &wwsmap[r - 1][c + 1]; + a1 = 0; + a2 = 0; + b1 = 0; + b2 = c < 0 || frameok(w, r, c); + + for (; c < w->ww_i.r; c++) { + if (c + 1 >= wwncol) { + a3 = 1; + b3 = 1; + } else { + a3 = w->ww_index == *smap++; + b3 = frameok(w, r, c + 1); + } + if (b2) { + code = 0; + if ((a1 || a2) && b1) + code |= WWF_L; + if ((a2 || a3) && b3) + code |= WWF_R; + if (code) + wwframec(wframe, r, c, code); + } + a1 = a2; + a2 = a3; + b1 = b2; + b2 = b3; + } + if ((a1 || a2) && b1 && b2) + wwframec(wframe, r, c, WWF_L); + } + + if (w->ww_w.l > 0) { + r = w->ww_i.t - 1; + c = w->ww_w.l - 1; + a1 = 0; + a2 = 0; + b1 = 0; + b2 = r < 0 || frameok(w, r, c); + + for (; r < w->ww_i.b; r++) { + if (r + 1 >= wwnrow) { + a3 = 1; + b3 = 1; + } else { + a3 = w->ww_index == wwsmap[r + 1][c + 1]; + b3 = frameok(w, r + 1, c); + } + if (b2) { + code = 0; + if ((a1 || a2) && b1) + code |= WWF_U; + if ((a2 || a3) && b3) + code |= WWF_D; + if (code) + wwframec(wframe, r, c, code); + } + a1 = a2; + a2 = a3; + b1 = b2; + b2 = b3; + } + if ((a1 || a2) && b1 && b2) + wwframec(wframe, r, c, WWF_U); + } + + if (w->ww_w.r < wwncol) { + r = w->ww_i.t - 1; + c = w->ww_w.r; + a1 = 0; + a2 = 0; + b1 = 0; + b2 = r < 0 || frameok(w, r, c); + + for (; r < w->ww_i.b; r++) { + if (r + 1 >= wwnrow) { + a3 = 1; + b3 = 1; + } else { + a3 = w->ww_index == wwsmap[r + 1][c - 1]; + b3 = frameok(w, r + 1, c); + } + if (b2) { + code = 0; + if ((a1 || a2) && b1) + code |= WWF_U; + if ((a2 || a3) && b3) + code |= WWF_D; + if (code) + wwframec(wframe, r, c, code); + } + a1 = a2; + a2 = a3; + b1 = b2; + b2 = b3; + } + if ((a1 || a2) && b1 && b2) + wwframec(wframe, r, c, WWF_U); + } +} + +wwframec(f, r, c, code) +register struct ww *f; +register r, c; +char code; +{ + char oldcode; + register char *smap; + + if (r < f->ww_i.t || r >= f->ww_i.b || c < f->ww_i.l || c >= f->ww_i.r) + return; + + smap = &wwsmap[r][c]; + + { + register struct ww *w; + + w = wwindex[*smap]; + if (w->ww_order > f->ww_order) { + if (w != &wwnobody && w->ww_win[r][c] == 0) + w->ww_nvis[r]--; + *smap = f->ww_index; + } + } + + if (f->ww_fmap != 0) { + register char *fmap; + + fmap = &f->ww_fmap[r][c]; + oldcode = *fmap; + *fmap |= code; + if (code & WWF_TOP) + *fmap &= ~WWF_LABEL; + code = *fmap; + } else + oldcode = 0; + { + register char *win = &f->ww_win[r][c]; + + if (*win == WWM_GLS && *smap == f->ww_index) + f->ww_nvis[r]++; + *win &= ~WWM_GLS; + } + if (oldcode != code && (code & WWF_LABEL) == 0) { + register short frame; + + frame = tt.tt_frame[code & WWF_MASK]; + f->ww_buf[r][c].c_w = frame; + if (wwsmap[r][c] == f->ww_index) { + wwtouched[r] |= WWU_TOUCHED; + wwns[r][c].c_w = frame; + } + } +} diff --git a/usr/src/usr.bin/window/wwgets.c b/usr/src/usr.bin/window/wwgets.c new file mode 100644 index 0000000000..111e52dba3 --- /dev/null +++ b/usr/src/usr.bin/window/wwgets.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwgets.c 3.17 (Berkeley) 3/2/91"; +#endif /* not lint */ + +#include "ww.h" +#include "char.h" + +wwgets(buf, n, w) +char *buf; +int n; +register struct ww *w; +{ + register char *p = buf; + register char c; + char uc = w->ww_unctrl; + static void rub(); + + w->ww_unctrl = 0; + for (;;) { + wwcurtowin(w); + while ((c = wwgetc()) < 0) + wwiomux(); +#ifdef OLD_TTY + if (c == wwoldtty.ww_sgttyb.sg_erase) +#else + if (c == wwoldtty.ww_termios.c_cc[VERASE]) +#endif + { + if (p > buf) + rub(*--p, w); + } else +#ifdef OLD_TTY + if (c == wwoldtty.ww_sgttyb.sg_kill) +#else + if (c == wwoldtty.ww_termios.c_cc[VKILL]) +#endif + { + while (p > buf) + rub(*--p, w); + } else +#ifdef OLD_TTY + if (c == wwoldtty.ww_ltchars.t_werasc) +#else + if (c == wwoldtty.ww_termios.c_cc[VWERASE]) +#endif + { + while (--p >= buf && (*p == ' ' || *p == '\t')) + rub(*p, w); + while (p >= buf && *p != ' ' && *p != '\t') + rub(*p--, w); + p++; + } else if (c == '\r' || c == '\n') { + break; + } else { + if (p >= buf + n - 1) + wwputc(ctrl('g'), w); + else + wwputs(unctrl(*p++ = c), w); + } + } + *p = 0; + w->ww_unctrl = uc; +} + +static void +rub(c, w) +struct ww *w; +{ + register i; + + for (i = strlen(unctrl(c)); --i >= 0;) + (void) wwwrite(w, "\b \b", 3); +} diff --git a/usr/src/usr.bin/window/wwinit.c b/usr/src/usr.bin/window/wwinit.c new file mode 100644 index 0000000000..7ed318b050 --- /dev/null +++ b/usr/src/usr.bin/window/wwinit.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwinit.c 3.40 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include +#include +#include "char.h" + +wwinit() +{ + register i, j; + char *kp; + int s; + + wwdtablesize = getdtablesize(); + wwhead.ww_forw = &wwhead; + wwhead.ww_back = &wwhead; + + s = sigblock(sigmask(SIGIO)); + if (signal(SIGIO, wwrint) == BADSIG || + signal(SIGCHLD, wwchild) == BADSIG || + signal(SIGPIPE, SIG_IGN) == BADSIG) { + wwerrno = WWE_SYS; + return -1; + } + + if (wwgettty(0, &wwoldtty) < 0) + return -1; + wwwintty = wwoldtty; +#ifdef OLD_TTY + wwwintty.ww_sgttyb.sg_flags &= ~XTABS; + wwnewtty.ww_sgttyb = wwoldtty.ww_sgttyb; + wwnewtty.ww_sgttyb.sg_erase = -1; + wwnewtty.ww_sgttyb.sg_kill = -1; + wwnewtty.ww_sgttyb.sg_flags |= CBREAK; + wwnewtty.ww_sgttyb.sg_flags &= ~(ECHO|CRMOD); + wwnewtty.ww_tchars.t_intrc = -1; + wwnewtty.ww_tchars.t_quitc = -1; + wwnewtty.ww_tchars.t_startc = -1; + wwnewtty.ww_tchars.t_stopc = -1; + wwnewtty.ww_tchars.t_eofc = -1; + wwnewtty.ww_tchars.t_brkc = -1; + wwnewtty.ww_ltchars.t_suspc = -1; + wwnewtty.ww_ltchars.t_dsuspc = -1; + wwnewtty.ww_ltchars.t_rprntc = -1; + wwnewtty.ww_ltchars.t_flushc = -1; + wwnewtty.ww_ltchars.t_werasc = -1; + wwnewtty.ww_ltchars.t_lnextc = -1; + wwnewtty.ww_lmode = wwoldtty.ww_lmode | LLITOUT; + wwnewtty.ww_ldisc = wwoldtty.ww_ldisc; +#else +#ifndef OXTABS +#define OXTABS XTABS +#endif +#ifndef _POSIX_VDISABLE +#define _POSIX_VDISABLE -1 +#endif + wwwintty.ww_termios.c_oflag &= ~OXTABS; + wwnewtty.ww_termios = wwoldtty.ww_termios; + wwnewtty.ww_termios.c_iflag &= + ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IMAXBEL); + wwnewtty.ww_termios.c_iflag |= INPCK; + wwnewtty.ww_termios.c_oflag = 0; + wwnewtty.ww_termios.c_cflag &= ~(CSIZE | PARENB); + wwnewtty.ww_termios.c_cflag |= CS8; + wwnewtty.ww_termios.c_lflag = 0; + for (i = 0; i < NCCS; i++) + wwnewtty.ww_termios.c_cc[i] = _POSIX_VDISABLE; +#endif + wwnewtty.ww_fflags = wwoldtty.ww_fflags | FASYNC; + if (wwsettty(0, &wwnewtty) < 0) + goto bad; + + if ((wwterm = getenv("TERM")) == 0) { + wwerrno = WWE_BADTERM; + goto bad; + } + if (tgetent(wwtermcap, wwterm) != 1) { + wwerrno = WWE_BADTERM; + goto bad; + } +#ifdef OLD_TTY + wwospeed = wwoldtty.ww_sgttyb.sg_ospeed; +#else + wwospeed = cfgetospeed(&wwoldtty.ww_termios); +#endif + switch (wwospeed) { + default: + case B0: + wwbaud = 0; + break; + case B50: + wwbaud = 50; + break; + case B75: + wwbaud = 75; + break; + case B110: + wwbaud = 110; + break; + case B134: + wwbaud = 134; + break; + case B150: + wwbaud = 150; + break; + case B200: + wwbaud = 200; + break; + case B300: + wwbaud = 300; + break; + case B600: + wwbaud = 600; + break; + case B1200: + wwbaud = 1200; + break; + case B1800: + wwbaud = 1800; + break; + case B2400: + wwbaud = 2400; + break; + case B4800: + wwbaud = 4800; + break; + case B9600: + wwbaud = 9600; + break; +#ifdef B19200 + case B19200: +#else + case EXTA: +#endif + wwbaud = 19200; + break; +#ifdef B38400 + case B38400: +#else + case EXTB: +#endif + wwbaud = 38400; + break; + } + + if (xxinit() < 0) + goto bad; + wwnrow = tt.tt_nrow; + wwncol = tt.tt_ncol; + wwavailmodes = tt.tt_availmodes; + wwwrap = tt.tt_wrap; + + if (wwavailmodes & WWM_REV) + wwcursormodes = WWM_REV | wwavailmodes & WWM_BLK; + else if (wwavailmodes & WWM_UL) + wwcursormodes = WWM_UL; + + if ((wwib = malloc((unsigned) 512)) == 0) + goto bad; + wwibe = wwib + 512; + wwibq = wwibp = wwib; + + if ((wwsmap = wwalloc(0, 0, wwnrow, wwncol, sizeof (char))) == 0) + goto bad; + for (i = 0; i < wwnrow; i++) + for (j = 0; j < wwncol; j++) + wwsmap[i][j] = WWX_NOBODY; + + wwos = (union ww_char **) + wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); + if (wwos == 0) + goto bad; + for (i = 0; i < wwnrow; i++) + for (j = 0; j < wwncol; j++) + wwos[i][j].c_w = ' '; + wwns = (union ww_char **) + wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char)); + if (wwns == 0) + goto bad; + for (i = 0; i < wwnrow; i++) + for (j = 0; j < wwncol; j++) + wwns[i][j].c_w = ' '; + + wwtouched = malloc((unsigned) wwnrow); + if (wwtouched == 0) { + wwerrno = WWE_NOMEM; + goto bad; + } + for (i = 0; i < wwnrow; i++) + wwtouched[i] = 0; + + wwupd = (struct ww_update *) malloc((unsigned) wwnrow * sizeof *wwupd); + if (wwupd == 0) { + wwerrno = WWE_NOMEM; + goto bad; + } + + wwindex[WWX_NOBODY] = &wwnobody; + wwnobody.ww_order = NWW; + + kp = wwwintermcap; + if (wwavailmodes & WWM_REV) + wwaddcap1(WWT_REV, &kp); + if (wwavailmodes & WWM_BLK) + wwaddcap1(WWT_BLK, &kp); + if (wwavailmodes & WWM_UL) + wwaddcap1(WWT_UL, &kp); + if (wwavailmodes & WWM_GRP) + wwaddcap1(WWT_GRP, &kp); + if (wwavailmodes & WWM_DIM) + wwaddcap1(WWT_DIM, &kp); + if (wwavailmodes & WWM_USR) + wwaddcap1(WWT_USR, &kp); + if (tt.tt_insline && tt.tt_delline || tt.tt_setscroll) + wwaddcap1(WWT_ALDL, &kp); + if (tt.tt_inschar) + wwaddcap1(WWT_IMEI, &kp); + if (tt.tt_insspace) + wwaddcap1(WWT_IC, &kp); + if (tt.tt_delchar) + wwaddcap1(WWT_DC, &kp); + wwaddcap("kb", &kp); + wwaddcap("ku", &kp); + wwaddcap("kd", &kp); + wwaddcap("kl", &kp); + wwaddcap("kr", &kp); + wwaddcap("kh", &kp); + if ((j = tgetnum("kn")) >= 0) { + char cap[32]; + + (void) sprintf(kp, "kn#%d:", j); + for (; *kp; kp++) + ; + for (i = 1; i <= j; i++) { + (void) sprintf(cap, "k%d", i); + wwaddcap(cap, &kp); + cap[0] = 'l'; + wwaddcap(cap, &kp); + } + } + /* + * It's ok to do this here even if setenv() is destructive + * since tt_init() has already made its own copy of it and + * wwterm now points to the copy. + */ + (void) setenv("TERM", WWT_TERM, 1); + + (void) sigsetmask(s); + /* catch typeahead before ASYNC was set */ + (void) kill(getpid(), SIGIO); + xxstart(); + return 0; +bad: + /* + * Don't bother to free storage. We're supposed + * to exit when wwinit fails anyway. + */ + (void) wwsettty(0, &wwoldtty); + (void) signal(SIGIO, SIG_DFL); + (void) sigsetmask(s); + return -1; +} + +wwaddcap(cap, kp) + register char *cap; + register char **kp; +{ + char tbuf[512]; + char *tp = tbuf; + register char *str, *p; + + if ((str = tgetstr(cap, &tp)) != 0) { + while (*(*kp)++ = *cap++) + ; + (*kp)[-1] = '='; + while (*str) { + for (p = unctrl(*str++); *(*kp)++ = *p++;) + ; + (*kp)--; + } + *(*kp)++ = ':'; + **kp = 0; + } +} + +wwaddcap1(cap, kp) + register char *cap; + register char **kp; +{ + while (*(*kp)++ = *cap++) + ; + (*kp)--; +} diff --git a/usr/src/usr.bin/window/wwinschar.c b/usr/src/usr.bin/window/wwinschar.c new file mode 100644 index 0000000000..8b32fc9189 --- /dev/null +++ b/usr/src/usr.bin/window/wwinschar.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwinschar.c 3.20 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwinschar(w, row, col, c, m) +register struct ww *w; +char c, m; +{ + register i; + int nvis; + short x = c | m << WWC_MSHIFT; + + /* + * First, shift the line. + */ + { + register union ww_char *p, *q; + + p = &w->ww_buf[row][w->ww_b.r]; + q = p - 1; + for (i = w->ww_b.r - col; --i > 0;) + *--p = *--q; + q->c_w = x; + } + + /* + * If can't see it, just return. + */ + if (row < w->ww_i.t || row >= w->ww_i.b + || w->ww_i.r <= 0 || w->ww_i.r <= col) + return; + + if (col < w->ww_i.l) + col = w->ww_i.l; + + /* + * Now find out how much is actually changed, and fix wwns. + */ + { + register union ww_char *buf; + register char *win; + register union ww_char *ns; + register char *smap; + char touched; + + nvis = 0; + smap = &wwsmap[row][col]; + for (i = col; i < w->ww_i.r && *smap++ != w->ww_index; i++) + ; + if (i >= w->ww_i.r) + return; + col = i; + buf = w->ww_buf[row]; + win = w->ww_win[row]; + ns = wwns[row]; + smap = &wwsmap[row][i]; + touched = wwtouched[row]; + for (; i < w->ww_i.r; i++) { + if (*smap++ != w->ww_index) + continue; + touched |= WWU_TOUCHED; + if (win[i]) + ns[i].c_w = + buf[i].c_w ^ win[i] << WWC_MSHIFT; + else { + nvis++; + ns[i] = buf[i]; + } + } + wwtouched[row] = touched; + } + + /* + * Can/Should we use delete character? + */ + if ((tt.tt_inschar || tt.tt_insspace) && nvis > (wwncol - col) / 2) { + register union ww_char *p, *q; + + if (tt.tt_inschar) + xxinschar(row, col, c, m); + else { + xxinsspace(row, col); + x = ' '; + } + p = &wwos[row][wwncol]; + q = p - 1; + for (i = wwncol - col; --i > 0;) + *--p = *--q; + q->c_w = x; + } +} diff --git a/usr/src/usr.bin/window/wwinsline.c b/usr/src/usr.bin/window/wwinsline.c new file mode 100644 index 0000000000..c7c543e31e --- /dev/null +++ b/usr/src/usr.bin/window/wwinsline.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwinsline.c 3.12 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwinsline(w, row) +register struct ww *w; +int row; +{ + register i; + register union ww_char **cpp, **cqq; + register union ww_char *cp; + int row1, row2; + char deleted; + int visible; + + /* + * Scroll first. + */ + if ((row1 = row) < w->ww_i.t) { + row1 = w->ww_i.t; + visible = 0; + } else + visible = 1; + if ((row2 = w->ww_b.b) > w->ww_i.b) { + row2 = w->ww_i.b; + } + deleted = wwscroll1(w, row1, row2, -1, visible); + + /* + * Fix the buffer. + * But leave clearing the last line for wwclreol(). + */ + cpp = &w->ww_buf[w->ww_b.b]; + cqq = cpp - 1; + cp = *cqq; + for (i = w->ww_b.b - row; --i > 0;) + *--cpp = *--cqq; + *cqq = cp; + + /* + * Now clear the last line. + */ + if (visible) + wwclreol1(w, row, w->ww_b.l, deleted); + else { + cp += w->ww_b.l; + for (i = w->ww_b.nc; --i >= 0;) + cp++->c_w = ' '; + } +} diff --git a/usr/src/usr.bin/window/wwiomux.c b/usr/src/usr.bin/window/wwiomux.c new file mode 100644 index 0000000000..1ea8f9ca75 --- /dev/null +++ b/usr/src/usr.bin/window/wwiomux.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwiomux.c 3.26 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include +#include +#if !defined(OLD_TTY) && !defined(TIOCPKT_DATA) +#include +#endif +#include + +/* + * Multiple window output handler. + * The idea is to copy window outputs to the terminal, via the + * display package. We try to give wwcurwin highest priority. + * The only return conditions are when there is keyboard input + * and when a child process dies, which are serviced by signal + * catchers (wwrint() and wwchild()). + * When there's nothing to do, we sleep in a select(). + * This can be done better with interrupt driven io. But that's + * not supported on ptys, yet. + * The history of this routine is interesting. + */ +wwiomux() +{ + register struct ww *w; + fd_set imask; + register n; + register char *p; + char c; + struct timeval tv; + char noblock = 0; + + for (;;) { + if (wwinterrupt()) { + wwclrintr(); + return; + } + + FD_ZERO(&imask); + for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { + if (w->ww_pty < 0) + continue; + if (w->ww_obq < w->ww_obe) + FD_SET(w->ww_pty, &imask); + if (w->ww_obq > w->ww_obp && !w->ww_stopped) + noblock = 1; + } + + if (!noblock) { + if (wwcurwin != 0) + wwcurtowin(wwcurwin); + wwupdate(); + wwflush(); + (void) setjmp(wwjmpbuf); + wwsetjmp = 1; + if (wwinterrupt()) { + wwsetjmp = 0; + wwclrintr(); + return; + } + /* + * Defensive code. If somebody else (for example, + * wall) clears the ASYNC flag on us, we will block + * forever. So we need a finite timeout and set + * the flag again. Anything more clever will probably + * need even more system calls. (This is a bug + * in the kernel.) + * I don't like this one bit. + */ + (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags); + tv.tv_sec = 30; + tv.tv_usec = 0; + } else { + tv.tv_sec = 0; + tv.tv_usec = 10000; + } + wwnselect++; + n = select(wwdtablesize, &imask, (fd_set *)0, (fd_set *)0, &tv); + wwsetjmp = 0; + noblock = 0; + + if (n < 0) + wwnselecte++; + else if (n == 0) + wwnselectz++; + else + for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { + if (w->ww_pty < 0 || + !FD_ISSET(w->ww_pty, &imask)) + continue; + wwnwread++; + p = w->ww_obq; + if (w->ww_ispty) { + if (p == w->ww_ob) { + w->ww_obp++; + w->ww_obq++; + } else + p--; + c = *p; + } + n = read(w->ww_pty, p, w->ww_obe - p); + if (n < 0) { + wwnwreade++; + (void) close(w->ww_pty); + w->ww_pty = -1; + } else if (n == 0) { + wwnwreadz++; + (void) close(w->ww_pty); + w->ww_pty = -1; + } else if (!w->ww_ispty) { + wwnwreadd++; + wwnwreadc += n; + w->ww_obq += n; + } else if (*p == TIOCPKT_DATA) { + n--; + wwnwreadd++; + wwnwreadc += n; + w->ww_obq += n; + } else { + wwnwreadp++; + if (*p & TIOCPKT_STOP) + w->ww_stopped = 1; + if (*p & TIOCPKT_START) + w->ww_stopped = 0; + if (*p & TIOCPKT_FLUSHWRITE) { + w->ww_stopped = 0; + w->ww_obq = w->ww_obp = + w->ww_ob; + } + } + if (w->ww_ispty) + *p = c; + } + /* + * Try the current window first, if there is output + * then process it and go back to the top to try again. + * This can lead to starvation of the other windows, + * but presumably that what we want. + * Update will eventually happen when output from wwcurwin + * dies down. + */ + if ((w = wwcurwin) != 0 && w->ww_pty >= 0 && + w->ww_obq > w->ww_obp && !w->ww_stopped) { + n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp); + if ((w->ww_obp += n) == w->ww_obq) + w->ww_obq = w->ww_obp = w->ww_ob; + noblock = 1; + continue; + } + for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) + if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp && + !w->ww_stopped) { + n = wwwrite(w, w->ww_obp, + w->ww_obq - w->ww_obp); + if ((w->ww_obp += n) == w->ww_obq) + w->ww_obq = w->ww_obp = w->ww_ob; + if (wwinterrupt()) + break; + } + } +} diff --git a/usr/src/usr.bin/window/wwlabel.c b/usr/src/usr.bin/window/wwlabel.c new file mode 100644 index 0000000000..bdff90d7aa --- /dev/null +++ b/usr/src/usr.bin/window/wwlabel.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwlabel.c 3.17 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "char.h" + +/* + * Label window w on f, + * at 1 line above w and 'where' columns from it's left edge. + * Gross, but it works. + */ +wwlabel(w, f, where, l, mode) +struct ww *w; +struct ww *f; +char *l; +{ + int row; + register j; + int jj; + register char *win; + register union ww_char *buf; + register union ww_char *ns; + register char *fmap; + register char *smap; + char touched; + char *p; + + if (f->ww_fmap == 0) + return; + + row = w->ww_w.t - 1; + if (row < f->ww_i.t || row >= f->ww_i.b) + return; + win = f->ww_win[row]; + buf = f->ww_buf[row]; + fmap = f->ww_fmap[row]; + ns = wwns[row]; + smap = wwsmap[row]; + touched = wwtouched[row]; + mode <<= WWC_MSHIFT; + + jj = MIN(w->ww_i.r, f->ww_i.r); + j = w->ww_i.l + where; + while (j < jj && *l) + for (p = unctrl(*l++); j < jj && *p; j++, p++) { + /* can't label if not already framed */ + if (win[j] & WWM_GLS) + continue; + if (smap[j] != f->ww_index) + buf[j].c_w = mode | *p; + else { + ns[j].c_w = (buf[j].c_w = mode | *p) + ^ win[j] << WWC_MSHIFT; + touched |= WWU_TOUCHED; + } + fmap[j] |= WWF_LABEL; + } + wwtouched[row] = touched; +} diff --git a/usr/src/usr.bin/window/wwmisc.c b/usr/src/usr.bin/window/wwmisc.c new file mode 100644 index 0000000000..c25ae877f8 --- /dev/null +++ b/usr/src/usr.bin/window/wwmisc.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwmisc.c 3.14 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include "char.h" + +/* + * Sufficient but not necessary test for total visibility. + */ +wwvisible(w) +register struct ww *w; +{ + register i; + register nvis = 0; + + for (i = w->ww_i.t; i < w->ww_i.b; i++) + nvis += w->ww_nvis[i]; + if (w->ww_hascursor + && w->ww_cur.r >= w->ww_i.t && w->ww_cur.r < w->ww_i.b + && w->ww_cur.c >= w->ww_i.l && w->ww_cur.c < w->ww_i.r + && wwsmap[w->ww_cur.r][w->ww_cur.c] == w->ww_index) + nvis++; + return nvis == w->ww_i.nr * w->ww_i.nc; +} + +wwbell() +{ + ttputc(ctrl('g')); +} diff --git a/usr/src/usr.bin/window/wwmove.c b/usr/src/usr.bin/window/wwmove.c new file mode 100644 index 0000000000..db98a2c5f0 --- /dev/null +++ b/usr/src/usr.bin/window/wwmove.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwmove.c 3.11 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +/* + * Move a window. Should be unattached. + */ +wwmove(w, row, col) +register struct ww *w; +{ + register dr, dc; + register i; + + dr = row - w->ww_w.t; + dc = col - w->ww_w.l; + + w->ww_w.t += dr; + w->ww_w.b += dr; + w->ww_w.l += dc; + w->ww_w.r += dc; + + w->ww_b.t += dr; + w->ww_b.b += dr; + w->ww_b.l += dc; + w->ww_b.r += dc; + + w->ww_i.t = MAX(w->ww_w.t, 0); + w->ww_i.b = MIN(w->ww_w.b, wwnrow); + w->ww_i.nr = w->ww_i.b - w->ww_i.t; + w->ww_i.l = MAX(w->ww_w.l, 0); + w->ww_i.r = MIN(w->ww_w.r, wwncol); + w->ww_i.nc = w->ww_i.r - w->ww_i.l; + + w->ww_cur.r += dr; + w->ww_cur.c += dc; + + w->ww_win -= dr; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + w->ww_win[i] -= dc; + if (w->ww_fmap != 0) { + w->ww_fmap -= dr; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + w->ww_fmap[i] -= dc; + } + w->ww_nvis -= dr; + for (i = w->ww_i.t; i < w->ww_i.b; i++) { + register j = w->ww_i.l; + register char *win = &w->ww_win[i][j]; + register char *smap = &wwsmap[i][j]; + int nvis = 0; + + for (; j < w->ww_i.r; j++, win++, smap++) + if (*win == 0 && *smap == w->ww_index) + nvis++; + w->ww_nvis[i] = nvis; + } + w->ww_buf -= dr; + for (i = w->ww_b.t; i < w->ww_b.b; i++) + w->ww_buf[i] -= dc; +} diff --git a/usr/src/usr.bin/window/wwopen.c b/usr/src/usr.bin/window/wwopen.c new file mode 100644 index 0000000000..52c6683d63 --- /dev/null +++ b/usr/src/usr.bin/window/wwopen.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwopen.c 3.29 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include +#include + +struct ww * +wwopen(flags, nrow, ncol, row, col, nline) +{ + register struct ww *w; + register i, j; + char m; + short nvis; + + w = (struct ww *)calloc(sizeof (struct ww), 1); + if (w == 0) { + wwerrno = WWE_NOMEM; + goto bad; + } + w->ww_pty = -1; + w->ww_socket = -1; + + for (i = 0; i < NWW && wwindex[i] != 0; i++) + ; + if (i >= NWW) { + wwerrno = WWE_TOOMANY; + goto bad; + } + w->ww_index = i; + + if (nline < nrow) + nline = nrow; + + w->ww_w.t = row; + w->ww_w.b = row + nrow; + w->ww_w.l = col; + w->ww_w.r = col + ncol; + w->ww_w.nr = nrow; + w->ww_w.nc = ncol; + + w->ww_b.t = row; + w->ww_b.b = row + nline; + w->ww_b.l = col; + w->ww_b.r = col + ncol; + w->ww_b.nr = nline; + w->ww_b.nc = ncol; + + w->ww_i.t = MAX(w->ww_w.t, 0); + w->ww_i.b = MIN(w->ww_w.b, wwnrow); + w->ww_i.l = MAX(w->ww_w.l, 0); + w->ww_i.r = MIN(w->ww_w.r, wwncol); + w->ww_i.nr = w->ww_i.b - w->ww_i.t; + w->ww_i.nc = w->ww_i.r - w->ww_i.l; + + w->ww_cur.r = w->ww_w.t; + w->ww_cur.c = w->ww_w.l; + + if (flags & WWO_PTY) { + if (wwgetpty(w) < 0) + goto bad; + w->ww_ispty = 1; + } else if (flags & WWO_SOCKET) { + int d[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, d) < 0) { + wwerrno = WWE_SYS; + goto bad; + } + w->ww_pty = d[0]; + w->ww_socket = d[1]; + } + if (flags & (WWO_PTY|WWO_SOCKET)) { + if ((w->ww_ob = malloc(512)) == 0) { + wwerrno = WWE_NOMEM; + goto bad; + } + w->ww_obe = w->ww_ob + 512; + w->ww_obp = w->ww_obq = w->ww_ob; + } + + w->ww_win = wwalloc(w->ww_w.t, w->ww_w.l, + w->ww_w.nr, w->ww_w.nc, sizeof (char)); + if (w->ww_win == 0) + goto bad; + m = 0; + if (flags & WWO_GLASS) + m |= WWM_GLS; + if (flags & WWO_REVERSE) + if (wwavailmodes & WWM_REV) + m |= WWM_REV; + else + flags &= ~WWO_REVERSE; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + for (j = w->ww_w.l; j < w->ww_w.r; j++) + w->ww_win[i][j] = m; + + if (flags & WWO_FRAME) { + w->ww_fmap = wwalloc(w->ww_w.t, w->ww_w.l, + w->ww_w.nr, w->ww_w.nc, sizeof (char)); + if (w->ww_fmap == 0) + goto bad; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + for (j = w->ww_w.l; j < w->ww_w.r; j++) + w->ww_fmap[i][j] = 0; + } + + w->ww_buf = (union ww_char **) + wwalloc(w->ww_b.t, w->ww_b.l, + w->ww_b.nr, w->ww_b.nc, sizeof (union ww_char)); + if (w->ww_buf == 0) + goto bad; + for (i = w->ww_b.t; i < w->ww_b.b; i++) + for (j = w->ww_b.l; j < w->ww_b.r; j++) + w->ww_buf[i][j].c_w = ' '; + + w->ww_nvis = (short *)malloc((unsigned) w->ww_w.nr * sizeof (short)); + if (w->ww_nvis == 0) { + wwerrno = WWE_NOMEM; + goto bad; + } + w->ww_nvis -= w->ww_w.t; + nvis = m ? 0 : w->ww_w.nc; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + w->ww_nvis[i] = nvis; + + w->ww_state = WWS_INITIAL; + w->ww_oflags = flags; + return wwindex[w->ww_index] = w; +bad: + if (w != 0) { + if (w->ww_win != 0) + wwfree(w->ww_win, w->ww_w.t); + if (w->ww_fmap != 0) + wwfree(w->ww_fmap, w->ww_w.t); + if (w->ww_buf != 0) + wwfree((char **)w->ww_buf, w->ww_b.t); + if (w->ww_nvis != 0) + free((char *)(w->ww_nvis + w->ww_w.t)); + if (w->ww_ob != 0) + free(w->ww_ob); + if (w->ww_pty >= 0) + (void) close(w->ww_pty); + if (w->ww_socket >= 0) + (void) close(w->ww_socket); + free((char *)w); + } + return 0; +} diff --git a/usr/src/usr.bin/window/wwprintf.c b/usr/src/usr.bin/window/wwprintf.c new file mode 100644 index 0000000000..8e99dd16b4 --- /dev/null +++ b/usr/src/usr.bin/window/wwprintf.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwprintf.c 3.11 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include + +/*VARARGS2*/ +wwprintf(w, fmt, va_alist) +struct ww *w; +char *fmt; +va_dcl +{ + char buf[1024]; + va_list ap; + + va_start(ap); + /* buffer can overflow */ + (void) wwwrite(w, buf, vsprintf(buf, fmt, ap)); + va_end(ap); +} diff --git a/usr/src/usr.bin/window/wwpty.c b/usr/src/usr.bin/window/wwpty.c new file mode 100644 index 0000000000..22b7e9f813 --- /dev/null +++ b/usr/src/usr.bin/window/wwpty.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwpty.c 3.19 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#if !defined(OLD_TTY) && !defined(TIOCPKT) +#include +#endif + +wwgetpty(w) +register struct ww *w; +{ + register char c, *p; + int tty; + int on = 1; +#define PTY "/dev/XtyXX" +#define _PT 5 +#define _PQRS 8 +#define _0_9 9 + + (void) strcpy(w->ww_ttyname, PTY); + for (c = 'p'; c <= 'u'; c++) { + w->ww_ttyname[_PT] = 'p'; + w->ww_ttyname[_PQRS] = c; + w->ww_ttyname[_0_9] = '0'; + if (access(w->ww_ttyname, 0) < 0) + break; + for (p = "0123456789abcdef"; *p; p++) { + w->ww_ttyname[_PT] = 'p'; + w->ww_ttyname[_0_9] = *p; + if ((w->ww_pty = open(w->ww_ttyname, 2)) < 0) + continue; + w->ww_ttyname[_PT] = 't'; + if ((tty = open(w->ww_ttyname, 2)) < 0) { + (void) close(w->ww_pty); + continue; + } + (void) close(tty); + if (ioctl(w->ww_pty, TIOCPKT, (char *)&on) < 0) { + (void) close(w->ww_pty); + continue; + } + return 0; + } + } + w->ww_pty = -1; + wwerrno = WWE_NOPTY; + return -1; +} diff --git a/usr/src/usr.bin/window/wwputc.c b/usr/src/usr.bin/window/wwputc.c new file mode 100644 index 0000000000..1bc9f7e05f --- /dev/null +++ b/usr/src/usr.bin/window/wwputc.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwputc.c 3.8 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwputc(c, w) +char c; +struct ww *w; +{ + (void) wwwrite(w, &c, sizeof c); +} diff --git a/usr/src/usr.bin/window/wwputs.c b/usr/src/usr.bin/window/wwputs.c new file mode 100644 index 0000000000..bc48a3edcb --- /dev/null +++ b/usr/src/usr.bin/window/wwputs.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwputs.c 3.8 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwputs(s, w) +register char *s; +struct ww *w; +{ + register char *p = s; + + while (*p++) + ; + (void) wwwrite(w, s, p - s - 1); +} diff --git a/usr/src/usr.bin/window/wwredraw.c b/usr/src/usr.bin/window/wwredraw.c new file mode 100644 index 0000000000..8f3867d87e --- /dev/null +++ b/usr/src/usr.bin/window/wwredraw.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwredraw.c 3.13 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwredraw() +{ + register i, j; + register union ww_char *os; + + xxclear(); + for (i = 0; i < wwnrow; i++) { + wwtouched[i] = WWU_TOUCHED; + os = wwos[i]; + for (j = wwncol; --j >= 0;) + (os++)->c_w = ' '; + } +} diff --git a/usr/src/usr.bin/window/wwredrawwin.c b/usr/src/usr.bin/window/wwredrawwin.c new file mode 100644 index 0000000000..f40d4021ed --- /dev/null +++ b/usr/src/usr.bin/window/wwredrawwin.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwredrawwin.c 3.16 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwredrawwin1(w, row1, row2, offset) +register struct ww *w; +int row1, row2, offset; +{ + int row; + register col; + register char *smap; + register union ww_char *buf; + register char *win; + register union ww_char *ns; + int x; + int nchanged; + + for (row = row1; row < row2; row++) { + col = w->ww_i.l; + ns = wwns[row]; + smap = &wwsmap[row][col]; + buf = w->ww_buf[row + offset]; + win = w->ww_win[row]; + nchanged = 0; + for (; col < w->ww_i.r; col++) + if (*smap++ == w->ww_index && + ns[col].c_w != + (x = buf[col].c_w ^ win[col] << WWC_MSHIFT)) { + nchanged++; + ns[col].c_w = x; + } + if (nchanged > 0) + wwtouched[row] |= WWU_TOUCHED; + } +} diff --git a/usr/src/usr.bin/window/wwrint.c b/usr/src/usr.bin/window/wwrint.c new file mode 100644 index 0000000000..23b9865da9 --- /dev/null +++ b/usr/src/usr.bin/window/wwrint.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwrint.c 3.12 (Berkeley) 7/1/91"; +#endif /* not lint */ + +#include "ww.h" +#include + +/* + * Tty input interrupt handler. + * (1) Read input into buffer (wwib*). + * (2) Set the interrupt flag if anything is read. + * Currently, the last is used to get out of the blocking + * select() in wwiomux(). + * To avoid race conditions, we only modify wwibq in here, except + * when the buffer is empty; and everywhere else, we only change wwibp. + * It should be completely safe. + */ +void +wwrint() +{ + register n; + + if (wwibp == wwibq) + wwibp = wwibq = wwib; + wwnread++; + (void) fcntl(0, F_SETFL, O_NONBLOCK|wwnewtty.ww_fflags); + n = read(0, wwibq, wwibe - wwibq); + (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags); + if (n > 0) { + wwibq += n; + wwnreadc += n; + wwsetintr(); + } else if (n == 0) + wwnreadz++; + else + wwnreade++; +} diff --git a/usr/src/usr.bin/window/wwscroll.c b/usr/src/usr.bin/window/wwscroll.c new file mode 100644 index 0000000000..904ccafd54 --- /dev/null +++ b/usr/src/usr.bin/window/wwscroll.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwscroll.c 3.24 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwscroll(w, n) +register struct ww *w; +int n; +{ + register dir; + register top; + + if (n == 0) + return; + dir = n < 0 ? -1 : 1; + top = w->ww_b.t - n; + if (top > w->ww_w.t) + top = w->ww_w.t; + else if (top + w->ww_b.nr < w->ww_w.b) + top = w->ww_w.b - w->ww_b.nr; + n = abs(top - w->ww_b.t); + if (n < w->ww_i.nr) { + while (--n >= 0) { + (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0); + w->ww_buf += dir; + w->ww_b.t -= dir; + w->ww_b.b -= dir; + } + } else { + w->ww_buf -= top - w->ww_b.t; + w->ww_b.t = top; + w->ww_b.b = top + w->ww_b.nr; + wwredrawwin(w); + } +} + +/* + * Scroll one line, between 'row1' and 'row2', in direction 'dir'. + * Don't adjust ww_scroll. + * And don't redraw 'leaveit' lines. + */ +wwscroll1(w, row1, row2, dir, leaveit) +register struct ww *w; +int row1, row2, dir; +int leaveit; +{ + register i; + int row1x, row2x; + int nvis; + int nvismax; + int scrolled = 0; + + /* + * See how many lines on the screen are affected. + * And calculate row1x, row2x, and left at the same time. + */ + for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++) + ; + if (i >= row2) /* can't do any fancy stuff */ + goto out; + row1x = i; + for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--) + ; + if (i <= row1x) + goto out; /* just one line is easy */ + row2x = i + 1; + + /* + * See how much of this window is visible. + */ + nvismax = wwncol * (row2x - row1x); + nvis = 0; + for (i = row1x; i < row2x; i++) + nvis += w->ww_nvis[i]; + + /* + * If it's a good idea to scroll and the terminal can, then do it. + */ + if (nvis < nvismax / 2) + goto no_scroll; /* not worth it */ + if ((dir > 0 ? tt.tt_scroll_down == 0 : tt.tt_scroll_up == 0) || + (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) && + tt.tt_setscroll == 0) + if (tt.tt_delline == 0 || tt.tt_insline == 0) + goto no_scroll; + xxscroll(dir, row1x, row2x); + scrolled = 1; + /* + * Fix up the old screen. + */ + { + register union ww_char *tmp; + register union ww_char **cpp, **cqq; + + if (dir > 0) { + cpp = &wwos[row1x]; + cqq = cpp + 1; + tmp = *cpp; + for (i = row2x - row1x; --i > 0;) + *cpp++ = *cqq++; + *cpp = tmp; + } else { + cpp = &wwos[row2x]; + cqq = cpp - 1; + tmp = *cqq; + for (i = row2x - row1x; --i > 0;) + *--cpp = *--cqq; + *cqq = tmp; + } + for (i = wwncol; --i >= 0;) + tmp++->c_w = ' '; + } + +no_scroll: + /* + * Fix the new screen. + */ + if (nvis == nvismax) { + /* + * Can shift whole lines. + */ + if (dir > 0) { + { + register union ww_char *tmp; + register union ww_char **cpp, **cqq; + + cpp = &wwns[row1x]; + cqq = cpp + 1; + tmp = *cpp; + for (i = row2x - row1x; --i > 0;) + *cpp++ = *cqq++; + *cpp = tmp; + } + if (scrolled) { + register char *p, *q; + + p = &wwtouched[row1x]; + q = p + 1; + for (i = row2x - row1x; --i > 0;) + *p++ = *q++; + *p |= WWU_TOUCHED; + } else { + register char *p; + + p = &wwtouched[row1x]; + for (i = row2x - row1x; --i >= 0;) + *p++ |= WWU_TOUCHED; + } + wwredrawwin1(w, row1, row1x, dir); + wwredrawwin1(w, row2x - 1, row2 - leaveit, dir); + } else { + { + register union ww_char *tmp; + register union ww_char **cpp, **cqq; + + cpp = &wwns[row2x]; + cqq = cpp - 1; + tmp = *cqq; + for (i = row2x - row1x; --i > 0;) + *--cpp = *--cqq; + *cqq = tmp; + } + if (scrolled) { + register char *p, *q; + + p = &wwtouched[row2x]; + q = p - 1; + for (i = row2x - row1x; --i > 0;) + *--p = *--q; + *q |= WWU_TOUCHED; + } else { + register char *p; + + p = &wwtouched[row1x]; + for (i = row2x - row1x; --i >= 0;) + *p++ |= WWU_TOUCHED; + } + wwredrawwin1(w, row1 + leaveit, row1x + 1, dir); + wwredrawwin1(w, row2x, row2, dir); + } + } else { + if (scrolled) { + register char *p; + + p = &wwtouched[row1x]; + for (i = row2x - row1x; --i >= 0;) + *p++ |= WWU_TOUCHED; + } +out: + if (dir > 0) + wwredrawwin1(w, row1, row2 - leaveit, dir); + else + wwredrawwin1(w, row1 + leaveit, row2, dir); + } + return scrolled; +} diff --git a/usr/src/usr.bin/window/wwsize.c b/usr/src/usr.bin/window/wwsize.c new file mode 100644 index 0000000000..f16cebcddd --- /dev/null +++ b/usr/src/usr.bin/window/wwsize.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwsize.c 3.10 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" + +/* + * Resize a window. Should be unattached. + */ +wwsize(w, nrow, ncol) +register struct ww *w; +{ + register i, j; + int nline; + union ww_char **buf = 0; + char **win = 0; + short *nvis = 0; + char **fmap = 0; + char m; + + /* + * First allocate new buffers. + */ + win = wwalloc(w->ww_w.t, w->ww_w.l, nrow, ncol, sizeof (char)); + if (win == 0) + goto bad; + if (w->ww_fmap != 0) { + fmap = wwalloc(w->ww_w.t, w->ww_w.l, nrow, ncol, sizeof (char)); + if (fmap == 0) + goto bad; + } + if (nrow > w->ww_b.nr || ncol > w->ww_b.nc) { + nline = MAX(w->ww_b.nr, nrow); + buf = (union ww_char **) wwalloc(w->ww_b.t, w->ww_b.l, + nline, ncol, sizeof (union ww_char)); + if (buf == 0) + goto bad; + } + nvis = (short *)malloc((unsigned) nrow * sizeof (short)); + if (nvis == 0) { + wwerrno = WWE_NOMEM; + goto bad; + } + nvis -= w->ww_w.t; + /* + * Copy text buffer. + */ + if (buf != 0) { + int b, r; + + b = w->ww_b.t + nline; + r = w->ww_b.l + ncol; + if (ncol < w->ww_b.nc) + for (i = w->ww_b.t; i < w->ww_b.b; i++) + for (j = w->ww_b.l; j < r; j++) + buf[i][j] = w->ww_buf[i][j]; + else + for (i = w->ww_b.t; i < w->ww_b.b; i++) { + for (j = w->ww_b.l; j < w->ww_b.r; j++) + buf[i][j] = w->ww_buf[i][j]; + for (; j < r; j++) + buf[i][j].c_w = ' '; + } + for (; i < b; i++) + for (j = w->ww_b.l; j < r; j++) + buf[i][j].c_w = ' '; + } + /* + * Now free the old stuff. + */ + wwfree((char **)w->ww_win, w->ww_w.t); + w->ww_win = win; + if (buf != 0) { + wwfree((char **)w->ww_buf, w->ww_b.t); + w->ww_buf = buf; + } + if (w->ww_fmap != 0) { + wwfree((char **)w->ww_fmap, w->ww_w.t); + w->ww_fmap = fmap; + } + free((char *)(w->ww_nvis + w->ww_w.t)); + w->ww_nvis = nvis; + /* + * Set new sizes. + */ + /* window */ + w->ww_w.b = w->ww_w.t + nrow; + w->ww_w.r = w->ww_w.l + ncol; + w->ww_w.nr = nrow; + w->ww_w.nc = ncol; + /* text buffer */ + if (buf != 0) { + w->ww_b.b = w->ww_b.t + nline; + w->ww_b.r = w->ww_b.l + ncol; + w->ww_b.nr = nline; + w->ww_b.nc = ncol; + } + /* scroll */ + if ((i = w->ww_b.b - w->ww_w.b) < 0 || + (i = w->ww_cur.r - w->ww_w.b + 1) > 0) { + w->ww_buf += i; + w->ww_b.t -= i; + w->ww_b.b -= i; + w->ww_cur.r -= i; + } + /* interior */ + w->ww_i.b = MIN(w->ww_w.b, wwnrow); + w->ww_i.r = MIN(w->ww_w.r, wwncol); + w->ww_i.nr = w->ww_i.b - w->ww_i.t; + w->ww_i.nc = w->ww_i.r - w->ww_i.l; + /* + * Initialize new buffers. + */ + /* window */ + m = 0; + if (w->ww_oflags & WWO_GLASS) + m |= WWM_GLS; + if (w->ww_oflags & WWO_REVERSE) + m |= WWM_REV; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + for (j = w->ww_w.l; j < w->ww_w.r; j++) + w->ww_win[i][j] = m; + /* frame map */ + if (fmap != 0) + for (i = w->ww_w.t; i < w->ww_w.b; i++) + for (j = w->ww_w.l; j < w->ww_w.r; j++) + w->ww_fmap[i][j] = 0; + /* visibility */ + j = m ? 0 : w->ww_w.nc; + for (i = w->ww_w.t; i < w->ww_w.b; i++) + w->ww_nvis[i] = j; + /* + * Put cursor back. + */ + if (w->ww_hascursor) { + w->ww_hascursor = 0; + wwcursor(w, 1); + } + /* + * Fool with pty. + */ + if (w->ww_ispty && w->ww_pty >= 0) + (void) wwsetttysize(w->ww_pty, nrow, ncol); + return 0; +bad: + if (win != 0) + wwfree(win, w->ww_w.t); + if (fmap != 0) + wwfree(fmap, w->ww_w.t); + if (buf != 0) + wwfree((char **)buf, w->ww_b.t); + if (nvis != 0) + free((char *)(nvis + w->ww_w.t)); + return -1; +} diff --git a/usr/src/usr.bin/window/wwspawn.c b/usr/src/usr.bin/window/wwspawn.c new file mode 100644 index 0000000000..65b604661f --- /dev/null +++ b/usr/src/usr.bin/window/wwspawn.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwspawn.c 3.15 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include + +/* + * There is a dead lock with vfork and closing of pseudo-ports. + * So we have to be sneaky about error reporting. + */ +wwspawn(wp, file, argv) +register struct ww *wp; +char *file; +char **argv; +{ + int pid; + int ret; + char erred = 0; + int s; + + s = sigblock(sigmask(SIGCHLD)); + switch (pid = vfork()) { + case -1: + wwerrno = WWE_SYS; + ret = -1; + break; + case 0: + if (wwenviron(wp) >= 0) + execvp(file, argv); + erred = 1; + _exit(1); + default: + if (erred) { + wwerrno = WWE_SYS; + ret = -1; + } else { + wp->ww_pid = pid; + wp->ww_state = WWS_HASPROC; + ret = pid; + } + } + (void) sigsetmask(s); + if (wp->ww_socket >= 0) { + (void) close(wp->ww_socket); + wp->ww_socket = -1; + } + return ret; +} diff --git a/usr/src/usr.bin/window/wwsuspend.c b/usr/src/usr.bin/window/wwsuspend.c new file mode 100644 index 0000000000..f45e4d5f62 --- /dev/null +++ b/usr/src/usr.bin/window/wwsuspend.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwsuspend.c 3.15 (Berkeley) 8/12/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include + +void +wwsuspend() +{ + sig_t oldsig; + + oldsig = signal(SIGTSTP, SIG_IGN); + wwend(); + (void) signal(SIGTSTP, SIG_DFL); + (void) kill(0, SIGTSTP); + (void) signal(SIGTSTP, SIG_IGN); + (void) wwsettty(0, &wwnewtty); + xxstart(); + wwredraw(); /* XXX, clears the screen twice */ + (void) signal(SIGTSTP, oldsig); +} diff --git a/usr/src/usr.bin/window/wwtty.c b/usr/src/usr.bin/window/wwtty.c new file mode 100644 index 0000000000..c6c4097983 --- /dev/null +++ b/usr/src/usr.bin/window/wwtty.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwtty.c 3.18 (Berkeley) 2/2/91"; +#endif /* not lint */ + +#include "ww.h" +#include +#include +#if !defined(OLD_TTY) && !defined(TIOCGWINSZ) +#include +#endif + +wwgettty(d, t) +register struct ww_tty *t; +{ +#ifdef OLD_TTY + if (ioctl(d, TIOCGETP, (char *)&t->ww_sgttyb) < 0) + goto bad; + if (ioctl(d, TIOCGETC, (char *)&t->ww_tchars) < 0) + goto bad; + if (ioctl(d, TIOCGLTC, (char *)&t->ww_ltchars) < 0) + goto bad; + if (ioctl(d, TIOCLGET, (char *)&t->ww_lmode) < 0) + goto bad; + if (ioctl(d, TIOCGETD, (char *)&t->ww_ldisc) < 0) + goto bad; +#else + if (tcgetattr(d, &t->ww_termios) < 0) + goto bad; +#endif + if ((t->ww_fflags = fcntl(d, F_GETFL, 0)) < 0) + goto bad; + return 0; +bad: + wwerrno = WWE_SYS; + return -1; +} + +/* + * Set the modes of tty 'd' to 't' + * 'o' is the current modes. We set the line discipline only if + * it changes, to avoid unnecessary flushing of typeahead. + */ +wwsettty(d, t) +register struct ww_tty *t; +{ +#ifdef OLD_TTY + int i; + + /* XXX, for buggy tty drivers that don't wait for output to drain */ + while (ioctl(d, TIOCOUTQ, &i) >= 0 && i > 0) + usleep(100000); + if (ioctl(d, TIOCSETN, (char *)&t->ww_sgttyb) < 0) + goto bad; + if (ioctl(d, TIOCSETC, (char *)&t->ww_tchars) < 0) + goto bad; + if (ioctl(d, TIOCSLTC, (char *)&t->ww_ltchars) < 0) + goto bad; + if (ioctl(d, TIOCLSET, (char *)&t->ww_lmode) < 0) + goto bad; + if (ioctl(d, TIOCGETD, (char *)&i) < 0) + goto bad; + if (t->ww_ldisc != i && + ioctl(d, TIOCSETD, (char *)&t->ww_ldisc) < 0) + goto bad; +#else +#ifdef sun + /* XXX, for buggy tty drivers that don't wait for output to drain */ + (void) tcdrain(d); +#endif + if (tcsetattr(d, TCSADRAIN, &t->ww_termios) < 0) + goto bad; +#endif + if (fcntl(d, F_SETFL, t->ww_fflags) < 0) + goto bad; + return 0; +bad: + wwerrno = WWE_SYS; + return -1; +} + +/* + * The ttysize and stop-start routines must also work + * on the control side of pseudoterminals. + */ + +wwgetttysize(d, r, c) + int *r, *c; +{ + struct winsize winsize; + + if (ioctl(d, TIOCGWINSZ, (char *)&winsize) < 0) { + wwerrno = WWE_SYS; + return -1; + } + if (winsize.ws_row != 0) + *r = winsize.ws_row; + if (winsize.ws_col != 0) + *c = winsize.ws_col; + return 0; +} + +wwsetttysize(d, r, c) +{ + struct winsize winsize; + + winsize.ws_row = r; + winsize.ws_col = c; + winsize.ws_xpixel = winsize.ws_ypixel = 0; + if (ioctl(d, TIOCSWINSZ, (char *)&winsize) < 0) { + wwerrno = WWE_SYS; + return -1; + } + return 0; +} + +wwstoptty(d) +{ +#if !defined(OLD_TTY) && defined(TCOOFF) + /* not guaranteed to work on the pty side */ + if (tcflow(d, TCOOFF) < 0) +#else + if (ioctl(d, TIOCSTOP, (char *)0) < 0) +#endif + { + wwerrno = WWE_SYS; + return -1; + } + return 0; +} + +wwstarttty(d) +{ +#if !defined(OLD_TTY) && defined(TCOON) + /* not guaranteed to work on the pty side */ + if (tcflow(d, TCOON) < 0) +#else + if (ioctl(d, TIOCSTART, (char *)0) < 0) +#endif + { + wwerrno = WWE_SYS; + return -1; + } + return 0; +} diff --git a/usr/src/usr.bin/window/wwunframe.c b/usr/src/usr.bin/window/wwunframe.c new file mode 100644 index 0000000000..8b68a66e50 --- /dev/null +++ b/usr/src/usr.bin/window/wwunframe.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwunframe.c 3.20 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" + +wwunframe(w) +register struct ww *w; +{ + int i; + + for (i = w->ww_i.t; i < w->ww_i.b; i++) { + register j; + register char *win = w->ww_win[i]; + register char *fmap = w->ww_fmap ? w->ww_fmap[i] : 0; + register char *smap = wwsmap[i]; + register union ww_char *ns = wwns[i]; + int nchanged = 0; + + for (j = w->ww_i.l; j < w->ww_i.r; j++) { + if (win[j] & WWM_GLS) + continue; + win[j] |= WWM_GLS; + if (fmap != 0) + fmap[j] = 0; + if (smap[j] == w->ww_index) { + smap[j] = WWX_NOBODY; + ns[j].c_w = ' '; + nchanged++; + } + } + if (nchanged > 0) + wwtouched[i] |= WWU_TOUCHED; + w->ww_nvis[i] = 0; + } + + if (w->ww_forw != &wwhead) + wwdelete1(w->ww_forw, + w->ww_i.t, w->ww_i.b, w->ww_i.l, w->ww_i.r); +} diff --git a/usr/src/usr.bin/window/wwupdate.c b/usr/src/usr.bin/window/wwupdate.c new file mode 100644 index 0000000000..8908932401 --- /dev/null +++ b/usr/src/usr.bin/window/wwupdate.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwupdate.c 3.29 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" + +wwupdate1(top, bot) +{ + int i; + register j; + char *touched; + struct ww_update *upd; + char check_clreos = 0; + int scan_top, scan_bot; + + wwnupdate++; + { + register char *t1 = wwtouched + top, *t2 = wwtouched + bot; + register n; + + while (!*t1++) + if (t1 == t2) + return; + while (!*--t2) + ; + scan_top = top = t1 - wwtouched - 1; + scan_bot = bot = t2 - wwtouched + 1; + if (scan_bot - scan_top > 1 && + (tt.tt_clreos != 0 || tt.tt_clear != 0)) { + int st = tt.tt_clreos != 0 ? scan_top : 0; + + /* + * t1 is one past the first touched row, + * t2 is on the last touched row. + */ + for (t1--, n = 1; t1 < t2;) + if (*t1++) + n++; + /* + * If we can't clreos then we try for clearing + * the whole screen. + */ + if (check_clreos = n * 10 > (wwnrow - st) * 9) { + scan_top = st; + scan_bot = wwnrow; + } + } + } + if (tt.tt_clreol == 0 && !check_clreos) + goto simple; + for (i = scan_top, touched = &wwtouched[i], upd = &wwupd[i]; + i < scan_bot; + i++, touched++, upd++) { + register gain = 0; + register best_gain = 0; + register best_col; + register union ww_char *ns, *os; + + if (wwinterrupt()) + return; + if (!check_clreos && !*touched) + continue; + wwnupdscan++; + j = wwncol; + ns = &wwns[i][j]; + os = &wwos[i][j]; + while (--j >= 0) { + /* + * The cost of clearing is: + * ncol - nblank + X + * The cost of straight update is, more or less: + * ncol - nsame + * We clear if nblank - nsame > X + * X is the clreol overhead. + * So we make gain = nblank - nsame. + */ + if ((--ns)->c_w == (--os)->c_w) + gain--; + else + best_gain--; + if (ns->c_w == ' ') + gain++; + if (gain > best_gain) { + best_col = j; + best_gain = gain; + } + } + upd->best_gain = best_gain; + upd->best_col = best_col; + upd->gain = gain; + } + if (check_clreos) { + register struct ww_update *u; + register gain = 0; + register best_gain = 0; + int best_row; + register simple_gain = 0; + char didit = 0; + + /* + * gain is the advantage of clearing all the lines. + * best_gain is the advantage of clearing to eos + * at best_row and u->best_col. + * simple_gain is the advantage of using only clreol. + * We use g > best_gain because u->best_col can be + * undefined when u->best_gain is 0 so we can't use it. + */ + for (j = scan_bot - 1, u = wwupd + j; j >= top; j--, u--) { + register g = gain + u->best_gain; + + if (g > best_gain) { + best_gain = g; + best_row = j; + } + gain += u->gain; + if (tt.tt_clreol != 0 && u->best_gain > 4) + simple_gain += u->best_gain - 4; + } + if (tt.tt_clreos == 0) { + if (gain > simple_gain && gain > 4) { + xxclear(); + i = top = scan_top; + bot = scan_bot; + j = 0; + didit = 1; + } + } else + if (best_gain > simple_gain && best_gain > 4) { + i = best_row; + xxclreos(i, j = wwupd[i].best_col); + bot = scan_bot; + didit = 1; + } + if (didit) { + wwnupdclreos++; + wwnupdclreosline += wwnrow - i; + u = wwupd + i; + while (i < scan_bot) { + register union ww_char *os = &wwos[i][j]; + + for (j = wwncol - j; --j >= 0;) + os++->c_w = ' '; + wwtouched[i++] |= WWU_TOUCHED; + u++->best_gain = 0; + j = 0; + } + } else + wwnupdclreosmiss++; + } +simple: + for (i = top, touched = &wwtouched[i], upd = &wwupd[i]; i < bot; + i++, touched++, upd++) { + register union ww_char *os, *ns; + char didit; + + if (!*touched) + continue; + *touched = 0; + wwnupdline++; + didit = 0; + if (tt.tt_clreol != 0 && upd->best_gain > 4) { + wwnupdclreol++; + xxclreol(i, j = upd->best_col); + for (os = &wwos[i][j], j = wwncol - j; --j >= 0;) + os++->c_w = ' '; + didit = 1; + } + ns = wwns[i]; + os = wwos[i]; + for (j = 0; j < wwncol;) { + register char *p, *q; + char m; + int c; + register n; + char buf[512]; /* > wwncol */ + union ww_char lastc; + + for (; j++ < wwncol && ns++->c_w == os++->c_w;) + ; + if (j > wwncol) + break; + p = buf; + m = ns[-1].c_m; + c = j - 1; + os[-1] = ns[-1]; + *p++ = ns[-1].c_c; + n = 5; + q = p; + while (j < wwncol && ns->c_m == m) { + *p++ = ns->c_c; + if (ns->c_w == os->c_w) { + if (--n <= 0) + break; + os++; + ns++; + } else { + n = 5; + q = p; + lastc = *os; + *os++ = *ns++; + } + j++; + } + n = q - buf; + if (!wwwrap || i != wwnrow - 1 || c + n != wwncol) + xxwrite(i, c, buf, n, m); + else if (tt.tt_inschar || tt.tt_insspace) { + if (n > 1) { + q[-2] = q[-1]; + n--; + } else + c--; + xxwrite(i, c, buf, n, m); + c += n - 1; + if (tt.tt_inschar) + xxinschar(i, c, ns[-2].c_c, + ns[-2].c_m); + else { + xxinsspace(i, c); + xxwrite(i, c, &ns[-2].c_c, 1, + ns[-2].c_m); + } + } else { + if (--n) + xxwrite(i, c, buf, n, m); + os[-1] = lastc; + *touched = WWU_TOUCHED; + } + didit = 1; + } + if (!didit) + wwnupdmiss++; + } +} diff --git a/usr/src/usr.bin/window/wwwrite.c b/usr/src/usr.bin/window/wwwrite.c new file mode 100644 index 0000000000..39269a05b7 --- /dev/null +++ b/usr/src/usr.bin/window/wwwrite.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)wwwrite.c 3.33 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "tt.h" +#include "char.h" + +#define UPDATE() \ + if (!w->ww_noupdate && w->ww_cur.r >= 0 && w->ww_cur.r < wwnrow && \ + wwtouched[w->ww_cur.r]) \ + wwupdate1(w->ww_cur.r, w->ww_cur.r + 1) + +/* + * To support control character expansion, we save the old + * p and q values in r and s, and point p at the beginning + * of the expanded string, and q at some safe place beyond it + * (p + 10). At strategic points in the loops, we check + * for (r && !*p) and restore the saved values back into + * p and q. Essentially, we implement a stack of depth 2, + * to avoid recursion, which might be a better idea. + */ +wwwrite(w, p, n) +register struct ww *w; +register char *p; +int n; +{ + char hascursor; + char *savep = p; + char *q = p + n; + char *r = 0; + char *s; + +#ifdef lint + s = 0; /* define it before possible use */ +#endif + if (hascursor = w->ww_hascursor) + wwcursor(w, 0); + while (p < q && !w->ww_stopped && (!wwinterrupt() || w->ww_nointr)) { + if (r && !*p) { + p = r; + q = s; + r = 0; + continue; + } + if (w->ww_wstate == 0 && + (isprt(*p) || w->ww_unctrl && isunctrl(*p))) { + register i; + register union ww_char *bp; + int col, col1; + + if (w->ww_insert) { /* this is very slow */ + if (*p == '\t') { + p++; + w->ww_cur.c += 8 - + (w->ww_cur.c - w->ww_w.l & 7); + goto chklf; + } + if (!isprt(*p)) { + r = p + 1; + s = q; + p = unctrl(*p); + q = p + 10; + } + wwinschar(w, w->ww_cur.r, w->ww_cur.c, + *p++, w->ww_modes); + goto right; + } + + bp = &w->ww_buf[w->ww_cur.r][w->ww_cur.c]; + i = w->ww_cur.c; + while (i < w->ww_w.r && p < q) + if (!*p && r) { + p = r; + q = s; + r = 0; + } else if (*p == '\t') { + register tmp = 8 - (i - w->ww_w.l & 7); + p++; + i += tmp; + bp += tmp; + } else if (isprt(*p)) { + bp++->c_w = *p++ + | w->ww_modes << WWC_MSHIFT; + i++; + } else if (w->ww_unctrl && isunctrl(*p)) { + r = p + 1; + s = q; + p = unctrl(*p); + q = p + 10; + } else + break; + col = MAX(w->ww_cur.c, w->ww_i.l); + col1 = MIN(i, w->ww_i.r); + w->ww_cur.c = i; + if (w->ww_cur.r >= w->ww_i.t + && w->ww_cur.r < w->ww_i.b) { + register union ww_char *ns = wwns[w->ww_cur.r]; + register char *smap = &wwsmap[w->ww_cur.r][col]; + register char *win = w->ww_win[w->ww_cur.r]; + int nchanged = 0; + + bp = w->ww_buf[w->ww_cur.r]; + for (i = col; i < col1; i++) + if (*smap++ == w->ww_index) { + nchanged++; + ns[i].c_w = bp[i].c_w + ^ win[i] << WWC_MSHIFT; + } + if (nchanged > 0) + wwtouched[w->ww_cur.r] |= WWU_TOUCHED; + } + chklf: + if (w->ww_cur.c >= w->ww_w.r) + goto crlf; + } else switch (w->ww_wstate) { + case 0: + switch (*p++) { + case '\n': + if (w->ww_mapnl) + crlf: + w->ww_cur.c = w->ww_w.l; + lf: + UPDATE(); + if (++w->ww_cur.r >= w->ww_w.b) { + w->ww_cur.r = w->ww_w.b - 1; + if (w->ww_w.b < w->ww_b.b) { + (void) wwscroll1(w, w->ww_i.t, + w->ww_i.b, 1, 0); + w->ww_buf++; + w->ww_b.t--; + w->ww_b.b--; + } else + wwdelline(w, w->ww_b.t); + } + break; + case '\b': + if (--w->ww_cur.c < w->ww_w.l) { + w->ww_cur.c = w->ww_w.r - 1; + goto up; + } + break; + case '\r': + w->ww_cur.c = w->ww_w.l; + break; + case ctrl('g'): + ttputc(ctrl('g')); + break; + case ctrl('['): + w->ww_wstate = 1; + break; + } + break; + case 1: + w->ww_wstate = 0; + switch (*p++) { + case '@': + w->ww_insert = 1; + break; + case 'A': + up: + UPDATE(); + if (--w->ww_cur.r < w->ww_w.t) { + w->ww_cur.r = w->ww_w.t; + if (w->ww_w.t > w->ww_b.t) { + (void) wwscroll1(w, w->ww_i.t, + w->ww_i.b, -1, 0); + w->ww_buf--; + w->ww_b.t++; + w->ww_b.b++; + } else + wwinsline(w, w->ww_b.t); + } + break; + case 'B': + goto lf; + case 'C': + right: + w->ww_cur.c++; + goto chklf; + case 'E': + w->ww_buf -= w->ww_w.t - w->ww_b.t; + w->ww_b.t = w->ww_w.t; + w->ww_b.b = w->ww_b.t + w->ww_b.nr; + w->ww_cur.r = w->ww_w.t; + w->ww_cur.c = w->ww_w.l; + wwclreos(w, w->ww_w.t, w->ww_w.l); + break; + case 'H': + UPDATE(); + w->ww_cur.r = w->ww_w.t; + w->ww_cur.c = w->ww_w.l; + break; + case 'J': + wwclreos(w, w->ww_cur.r, w->ww_cur.c); + break; + case 'K': + wwclreol(w, w->ww_cur.r, w->ww_cur.c); + break; + case 'L': + UPDATE(); + wwinsline(w, w->ww_cur.r); + break; + case 'M': + wwdelline(w, w->ww_cur.r); + break; + case 'N': + wwdelchar(w, w->ww_cur.r, w->ww_cur.c); + break; + case 'O': + w->ww_insert = 0; + break; + case 'P': + wwinschar(w, w->ww_cur.r, w->ww_cur.c, ' ', 0); + break; + case 'X': + wwupdate(); + break; + case 'Y': + UPDATE(); + w->ww_wstate = 2; + break; + case 'Z': + wwupdate(); + xxflush(0); + break; + case 's': + w->ww_wstate = 4; + break; + case 'r': + w->ww_wstate = 5; + break; + } + break; + case 2: + w->ww_cur.r = w->ww_w.t + + (unsigned)(*p++ - ' ') % w->ww_w.nr; + w->ww_wstate = 3; + break; + case 3: + w->ww_cur.c = w->ww_w.l + + (unsigned)(*p++ - ' ') % w->ww_w.nc; + w->ww_wstate = 0; + break; + case 4: + w->ww_modes |= *p++ & wwavailmodes; + w->ww_wstate = 0; + break; + case 5: + w->ww_modes &= ~*p++; + w->ww_wstate = 0; + break; + } + } + if (hascursor) + wwcursor(w, 1); + wwnwwr++; + wwnwwra += n; + n = p - savep; + wwnwwrc += n; + return n; +} diff --git a/usr/src/usr.bin/window/xx.c b/usr/src/usr.bin/window/xx.c new file mode 100644 index 0000000000..1f7ade55e3 --- /dev/null +++ b/usr/src/usr.bin/window/xx.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)xx.c 3.6 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "xx.h" +#include "tt.h" + +xxinit() +{ + if (ttinit() < 0) + return -1; + xxbufsize = tt.tt_nrow * tt.tt_ncol * 2; + /* ccinit may choose to change xxbufsize */ + if (tt.tt_ntoken > 0 && ccinit() < 0) + return -1; + xxbuf = malloc((unsigned) xxbufsize * sizeof *xxbuf); + if (xxbuf == 0) { + wwerrno = WWE_NOMEM; + return -1; + } + xxbufp = xxbuf; + xxbufe = xxbuf + xxbufsize; + return 0; +} + +xxstart() +{ + (*tt.tt_start)(); + if (tt.tt_ntoken > 0) + ccstart(); + xxreset(); /* might be a restart */ +} + +xxend() +{ + if (tt.tt_scroll_top != 0 || tt.tt_scroll_bot != tt.tt_nrow - 1) + /* tt.tt_setscroll is known to be defined */ + (*tt.tt_setscroll)(0, tt.tt_nrow - 1); + if (tt.tt_modes) + (*tt.tt_setmodes)(0); + if (tt.tt_scroll_down) + (*tt.tt_scroll_down)(1); + (*tt.tt_move)(tt.tt_nrow - 1, 0); + if (tt.tt_ntoken > 0) + ccend(); + (*tt.tt_end)(); + (*tt.tt_flush)(); +} + +struct xx * +xxalloc() +{ + register struct xx *xp; + + if (xxbufp > xxbufe) + abort(); + if ((xp = xx_freelist) == 0) + /* XXX can't deal with failure */ + xp = (struct xx *) malloc((unsigned) sizeof *xp); + else + xx_freelist = xp->link; + if (xx_head == 0) + xx_head = xp; + else + xx_tail->link = xp; + xx_tail = xp; + xp->link = 0; + return xp; +} + +xxfree(xp) + register struct xx *xp; +{ + xp->link = xx_freelist; + xx_freelist = xp; +} + +xxmove(row, col) +{ + register struct xx *xp = xx_tail; + + if (xp == 0 || xp->cmd != xc_move) { + xp = xxalloc(); + xp->cmd = xc_move; + } + xp->arg0 = row; + xp->arg1 = col; +} + +xxscroll(dir, top, bot) +{ + register struct xx *xp = xx_tail; + + if (xp != 0 && xp->cmd == xc_scroll && + xp->arg1 == top && xp->arg2 == bot && + (xp->arg0 < 0 && dir < 0 || xp->arg0 > 0 && dir > 0)) { + xp->arg0 += dir; + return; + } + xp = xxalloc(); + xp->cmd = xc_scroll; + xp->arg0 = dir; + xp->arg1 = top; + xp->arg2 = bot; +} + +xxinschar(row, col, c, m) +{ + register struct xx *xp; + + xp = xxalloc(); + xp->cmd = xc_inschar; + xp->arg0 = row; + xp->arg1 = col; + xp->arg2 = c; + xp->arg3 = m; +} + +xxinsspace(row, col) +{ + register struct xx *xp = xx_tail; + + if (xp != 0 && xp->cmd == xc_insspace && xp->arg0 == row && + col >= xp->arg1 && col <= xp->arg1 + xp->arg2) { + xp->arg2++; + return; + } + xp = xxalloc(); + xp->cmd = xc_insspace; + xp->arg0 = row; + xp->arg1 = col; + xp->arg2 = 1; +} + +xxdelchar(row, col) +{ + register struct xx *xp = xx_tail; + + if (xp != 0 && xp->cmd == xc_delchar && + xp->arg0 == row && xp->arg1 == col) { + xp->arg2++; + return; + } + xp = xxalloc(); + xp->cmd = xc_delchar; + xp->arg0 = row; + xp->arg1 = col; + xp->arg2 = 1; +} + +xxclear() +{ + register struct xx *xp; + + xxreset(); + xp = xxalloc(); + xp->cmd = xc_clear; +} + +xxclreos(row, col) +{ + register struct xx *xp = xxalloc(); + + xp->cmd = xc_clreos; + xp->arg0 = row; + xp->arg1 = col; +} + +xxclreol(row, col) +{ + register struct xx *xp = xxalloc(); + + xp->cmd = xc_clreol; + xp->arg0 = row; + xp->arg1 = col; +} + +xxwrite(row, col, p, n, m) + char *p; +{ + register struct xx *xp; + + if (xxbufp + n + 1 > xxbufe) + xxflush(0); + xp = xxalloc(); + xp->cmd = xc_write; + xp->arg0 = row; + xp->arg1 = col; + xp->arg2 = n; + xp->arg3 = m; + xp->buf = xxbufp; + bcopy(p, xxbufp, n); + xxbufp += n; + *xxbufp++ = char_sep; +} + +xxreset() +{ + register struct xx *xp, *xq; + + for (xp = xx_head; xp != 0; xp = xq) { + xq = xp->link; + xxfree(xp); + } + xx_tail = xx_head = 0; + xxbufp = xxbuf; +} diff --git a/usr/src/usr.bin/window/xx.h b/usr/src/usr.bin/window/xx.h new file mode 100644 index 0000000000..13c0a632b3 --- /dev/null +++ b/usr/src/usr.bin/window/xx.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)xx.h 3.5 (Berkeley) 6/6/90 + */ + +struct xx { + enum { xc_move, xc_scroll, xc_inschar, xc_insspace, xc_delchar, + xc_clear, xc_clreos, xc_clreol, xc_write } cmd; + int arg0; + int arg1; + int arg2; + int arg3; + char *buf; + struct xx *link; +}; + +struct xx *xxalloc(); + +struct xx *xx_head, *xx_tail; +struct xx *xx_freelist; + +char *xxbuf, *xxbufp, *xxbufe; +int xxbufsize; + +#define char_sep '\0' diff --git a/usr/src/usr.bin/window/xxflush.c b/usr/src/usr.bin/window/xxflush.c new file mode 100644 index 0000000000..85fcedab2d --- /dev/null +++ b/usr/src/usr.bin/window/xxflush.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Edward Wang at The University of California, Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)xxflush.c 3.6 (Berkeley) 6/6/90"; +#endif /* not lint */ + +#include "ww.h" +#include "xx.h" +#include "tt.h" + +xxflush(intr) + register intr; +{ + register struct xx *xp, *xq; + + for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) { + switch (xp->cmd) { + case xc_move: + if (xp->link == 0) + (*tt.tt_move)(xp->arg0, xp->arg1); + break; + case xc_scroll: + xxflush_scroll(xp); + break; + case xc_inschar: + (*tt.tt_move)(xp->arg0, xp->arg1); + tt.tt_nmodes = xp->arg3; + (*tt.tt_inschar)(xp->arg2); + break; + case xc_insspace: + (*tt.tt_move)(xp->arg0, xp->arg1); + (*tt.tt_insspace)(xp->arg2); + break; + case xc_delchar: + (*tt.tt_move)(xp->arg0, xp->arg1); + (*tt.tt_delchar)(xp->arg2); + break; + case xc_clear: + (*tt.tt_clear)(); + break; + case xc_clreos: + (*tt.tt_move)(xp->arg0, xp->arg1); + (*tt.tt_clreos)(); + break; + case xc_clreol: + (*tt.tt_move)(xp->arg0, xp->arg1); + (*tt.tt_clreol)(); + break; + case xc_write: + (*tt.tt_move)(xp->arg0, xp->arg1); + tt.tt_nmodes = xp->arg3; + (*tt.tt_write)(xp->buf, xp->arg2); + break; + } + xq = xp->link; + xxfree(xp); + } + if ((xx_head = xp) == 0) { + xx_tail = 0; + xxbufp = xxbuf; + } + (*tt.tt_flush)(); +} + +xxflush_scroll(xp) + register struct xx *xp; +{ + register struct xx *xq; + + top: + if (xp->arg0 == 0) + return; + /* + * We handle retain (da and db) by putting the burden on scrolling up, + * which is the less common operation. It must ensure that + * text is not pushed below the screen, so scrolling down doesn't + * have to worry about it. + * + * Try scrolling region (or scrolling the whole screen) first. + * Can we assume "sr" doesn't push text below the screen + * so we don't have to worry about retain below? + * What about scrolling down with a newline? It probably does + * push text above (with da). Scrolling up would then have + * to take care of that. + * It's easy to be fool proof, but that slows things down. + * The current solution is to disallow tt_scroll_up if da or db is true + * but cs (scrolling region) is not. Again, we sacrifice scrolling + * up in favor of scrolling down. The idea is having scrolling regions + * probably means we can scroll (even the whole screen) with impunity. + * This lets us work efficiently on simple terminals (use newline + * on the bottom to scroll), on any terminal without retain, and + * on vt100 style scrolling regions (I think). + */ + if (xp->arg0 > 0) { + if ((xq = xp->link) != 0 && xq->cmd == xc_scroll && + xp->arg2 == xq->arg2 && xq->arg0 < 0) { + if (xp->arg1 < xq->arg1) { + if (xp->arg2 - xp->arg0 <= xq->arg1) { + xq->arg0 = xp->arg0; + xq->arg1 = xp->arg1; + xq->arg2 = xp->arg2; + return; + } + xp->arg2 = xq->arg1 + xp->arg0; + xq->arg0 += xp->arg0; + xq->arg1 = xp->arg2; + if (xq->arg0 > 0) + xq->arg1 -= xq->arg0; + goto top; + } else { + if (xp->arg1 - xq->arg0 >= xp->arg2) + return; + xq->arg2 = xp->arg1 - xq->arg0; + xp->arg0 += xq->arg0; + xp->arg1 = xq->arg2; + if (xp->arg0 < 0) + xp->arg1 += xp->arg0; + goto top; + } + } + if (xp->arg0 > xp->arg2 - xp->arg1) + xp->arg0 = xp->arg2 - xp->arg1; + if (tt.tt_scroll_down) { + if (tt.tt_scroll_top != xp->arg1 || + tt.tt_scroll_bot != xp->arg2 - 1) { + if (tt.tt_setscroll == 0) + goto down; + (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); + } + tt.tt_scroll_down(xp->arg0); + } else { + down: + (*tt.tt_move)(xp->arg1, 0); + (*tt.tt_delline)(xp->arg0); + if (xp->arg2 < tt.tt_nrow) { + (*tt.tt_move)(xp->arg2 - xp->arg0, 0); + (*tt.tt_insline)(xp->arg0); + } + } + } else { + xp->arg0 = - xp->arg0; + if (xp->arg0 > xp->arg2 - xp->arg1) + xp->arg0 = xp->arg2 - xp->arg1; + if (tt.tt_scroll_up) { + if (tt.tt_scroll_top != xp->arg1 || + tt.tt_scroll_bot != xp->arg2 - 1) { + if (tt.tt_setscroll == 0) + goto up; + (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1); + } + tt.tt_scroll_up(xp->arg0); + } else { + up: + if (tt.tt_retain || xp->arg2 != tt.tt_nrow) { + (*tt.tt_move)(xp->arg2 - xp->arg0, 0); + (*tt.tt_delline)(xp->arg0); + } + (*tt.tt_move)(xp->arg1, 0); + (*tt.tt_insline)(xp->arg0); + } + } +} -- 2.20.1