From e07eb1a5502721a12346d17bd3f3e7d8630d92d1 Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Mon, 23 Mar 2026 20:46:08 +0100 Subject: [PATCH 1/8] Fix vision: remove NO_MACRO_CPATH The non-macro q_path() function wrappers in vision.c pass the first two arguments in the wrong order to the _q*_path() functions, swapping rows and columns. This causes the Bresenham line-of-sight code to use column values as row indices into viz_clear_rows[ROWNO], producing out-of-bounds access and infinite loops. NO_MACRO_CPATH selects these broken function wrappers. It was only defined for Amiga (in config1.h), so the bug never triggered on other platforms. Remove the define to use the correct macro versions. --- include/config1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config1.h b/include/config1.h index 3a8632564..402e0e73c 100644 --- a/include/config1.h +++ b/include/config1.h @@ -95,7 +95,7 @@ #undef UNIX #define DLB #define HACKDIR "NetHack:" -#define NO_MACRO_CPATH + #endif /* From 1ca15d99ff125c52c4bcb4f63d1f2e5ee817c0de Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Mon, 23 Mar 2026 20:46:31 +0100 Subject: [PATCH 2/8] Fix clipping: move cliparound after vision_recalc cliparound() was called before rhack(), triggering a map redraw with stale vision data followed by a second correct redraw. Move it after vision_recalc() so the map is redrawn once with correct data. --- src/allmain.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/allmain.c b/src/allmain.c index 2db536e5e..4dd27680c 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -13,6 +13,7 @@ staticfn void moveloop_preamble(boolean); staticfn void u_calc_moveamt(int); + staticfn void maybe_do_tutorial(void); #ifdef POSITIONBAR staticfn void do_positionbar(void); @@ -511,11 +512,6 @@ moveloop_core(void) return; } -#ifdef CLIPPING - /* just before rhack */ - cliparound(u.ux, u.uy); -#endif - u.umoved = FALSE; if (gm.multi > 0) { @@ -546,6 +542,11 @@ moveloop_core(void) if (gv.vision_full_recalc) vision_recalc(0); /* vision! */ +#ifdef CLIPPING + /* after rhack() and vision_recalc() so that the map is redrawn + once with correct vision data, not twice (overshoot+correct) */ + cliparound(u.ux, u.uy); +#endif /* when running in non-tport mode, this gets done through domove() */ if ((!svc.context.run || flags.runmode == RUN_TPORT) && (gm.multi && (!svc.context.travel ? !(gm.multi % 7) From 7b89255ea8a7ec89b4989b64d3c12a017f2d9018 Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Mon, 23 Mar 2026 20:46:56 +0100 Subject: [PATCH 3/8] Move Amiga port files from outdated/ to sys/amiga/ Move the active Amiga source files back into their proper locations. Legacy native build files (Makefile.ami, Build.ami, etc.) remain in outdated/ as they are not used by the cross-compilation build. --- {outdated/include => include}/amiconf.h | 0 {outdated/sys => sys}/amiga/amidos.c | 0 {outdated/sys => sys}/amiga/amidos.p | 0 {outdated/sys => sys}/amiga/amifont.uu | 0 {outdated/sys => sys}/amiga/amifont8.uu | 0 {outdated/sys => sys}/amiga/amigst.c | 0 {outdated/sys => sys}/amiga/amii.hlp | 0 {outdated/sys => sys}/amiga/amimenu.c | 0 {outdated/sys => sys}/amiga/amirip.c | 0 {outdated/sys => sys}/amiga/amistack.c | 0 {outdated/sys => sys}/amiga/amitty.c | 0 {outdated/sys => sys}/amiga/amiwind.c | 0 {outdated/sys => sys}/amiga/amiwind.p | 0 {outdated/sys => sys}/amiga/clipwin.c | 0 {outdated/sys => sys}/amiga/colorwin.c | 0 {outdated/sys => sys}/amiga/grave16.xpm | 0 {outdated/sys => sys}/amiga/txt2iff.c | 0 {outdated/sys => sys}/amiga/winamenu.c | 0 {outdated/sys => sys}/amiga/winami.c | 0 {outdated/sys => sys}/amiga/winami.p | 0 {outdated/sys => sys}/amiga/winchar.c | 0 {outdated/sys => sys}/amiga/windefs.h | 0 {outdated/sys => sys}/amiga/winext.h | 0 {outdated/sys => sys}/amiga/winfuncs.c | 0 {outdated/sys => sys}/amiga/winkey.c | 0 {outdated/sys => sys}/amiga/winproto.h | 0 {outdated/sys => sys}/amiga/winreq.c | 0 {outdated/sys => sys}/amiga/winstr.c | 0 {outdated/sys => sys}/amiga/xpm2iff.c | 0 29 files changed, 0 insertions(+), 0 deletions(-) rename {outdated/include => include}/amiconf.h (100%) rename {outdated/sys => sys}/amiga/amidos.c (100%) rename {outdated/sys => sys}/amiga/amidos.p (100%) rename {outdated/sys => sys}/amiga/amifont.uu (100%) rename {outdated/sys => sys}/amiga/amifont8.uu (100%) rename {outdated/sys => sys}/amiga/amigst.c (100%) rename {outdated/sys => sys}/amiga/amii.hlp (100%) rename {outdated/sys => sys}/amiga/amimenu.c (100%) rename {outdated/sys => sys}/amiga/amirip.c (100%) rename {outdated/sys => sys}/amiga/amistack.c (100%) rename {outdated/sys => sys}/amiga/amitty.c (100%) rename {outdated/sys => sys}/amiga/amiwind.c (100%) rename {outdated/sys => sys}/amiga/amiwind.p (100%) rename {outdated/sys => sys}/amiga/clipwin.c (100%) rename {outdated/sys => sys}/amiga/colorwin.c (100%) rename {outdated/sys => sys}/amiga/grave16.xpm (100%) rename {outdated/sys => sys}/amiga/txt2iff.c (100%) rename {outdated/sys => sys}/amiga/winamenu.c (100%) rename {outdated/sys => sys}/amiga/winami.c (100%) rename {outdated/sys => sys}/amiga/winami.p (100%) rename {outdated/sys => sys}/amiga/winchar.c (100%) rename {outdated/sys => sys}/amiga/windefs.h (100%) rename {outdated/sys => sys}/amiga/winext.h (100%) rename {outdated/sys => sys}/amiga/winfuncs.c (100%) rename {outdated/sys => sys}/amiga/winkey.c (100%) rename {outdated/sys => sys}/amiga/winproto.h (100%) rename {outdated/sys => sys}/amiga/winreq.c (100%) rename {outdated/sys => sys}/amiga/winstr.c (100%) rename {outdated/sys => sys}/amiga/xpm2iff.c (100%) diff --git a/outdated/include/amiconf.h b/include/amiconf.h similarity index 100% rename from outdated/include/amiconf.h rename to include/amiconf.h diff --git a/outdated/sys/amiga/amidos.c b/sys/amiga/amidos.c similarity index 100% rename from outdated/sys/amiga/amidos.c rename to sys/amiga/amidos.c diff --git a/outdated/sys/amiga/amidos.p b/sys/amiga/amidos.p similarity index 100% rename from outdated/sys/amiga/amidos.p rename to sys/amiga/amidos.p diff --git a/outdated/sys/amiga/amifont.uu b/sys/amiga/amifont.uu similarity index 100% rename from outdated/sys/amiga/amifont.uu rename to sys/amiga/amifont.uu diff --git a/outdated/sys/amiga/amifont8.uu b/sys/amiga/amifont8.uu similarity index 100% rename from outdated/sys/amiga/amifont8.uu rename to sys/amiga/amifont8.uu diff --git a/outdated/sys/amiga/amigst.c b/sys/amiga/amigst.c similarity index 100% rename from outdated/sys/amiga/amigst.c rename to sys/amiga/amigst.c diff --git a/outdated/sys/amiga/amii.hlp b/sys/amiga/amii.hlp similarity index 100% rename from outdated/sys/amiga/amii.hlp rename to sys/amiga/amii.hlp diff --git a/outdated/sys/amiga/amimenu.c b/sys/amiga/amimenu.c similarity index 100% rename from outdated/sys/amiga/amimenu.c rename to sys/amiga/amimenu.c diff --git a/outdated/sys/amiga/amirip.c b/sys/amiga/amirip.c similarity index 100% rename from outdated/sys/amiga/amirip.c rename to sys/amiga/amirip.c diff --git a/outdated/sys/amiga/amistack.c b/sys/amiga/amistack.c similarity index 100% rename from outdated/sys/amiga/amistack.c rename to sys/amiga/amistack.c diff --git a/outdated/sys/amiga/amitty.c b/sys/amiga/amitty.c similarity index 100% rename from outdated/sys/amiga/amitty.c rename to sys/amiga/amitty.c diff --git a/outdated/sys/amiga/amiwind.c b/sys/amiga/amiwind.c similarity index 100% rename from outdated/sys/amiga/amiwind.c rename to sys/amiga/amiwind.c diff --git a/outdated/sys/amiga/amiwind.p b/sys/amiga/amiwind.p similarity index 100% rename from outdated/sys/amiga/amiwind.p rename to sys/amiga/amiwind.p diff --git a/outdated/sys/amiga/clipwin.c b/sys/amiga/clipwin.c similarity index 100% rename from outdated/sys/amiga/clipwin.c rename to sys/amiga/clipwin.c diff --git a/outdated/sys/amiga/colorwin.c b/sys/amiga/colorwin.c similarity index 100% rename from outdated/sys/amiga/colorwin.c rename to sys/amiga/colorwin.c diff --git a/outdated/sys/amiga/grave16.xpm b/sys/amiga/grave16.xpm similarity index 100% rename from outdated/sys/amiga/grave16.xpm rename to sys/amiga/grave16.xpm diff --git a/outdated/sys/amiga/txt2iff.c b/sys/amiga/txt2iff.c similarity index 100% rename from outdated/sys/amiga/txt2iff.c rename to sys/amiga/txt2iff.c diff --git a/outdated/sys/amiga/winamenu.c b/sys/amiga/winamenu.c similarity index 100% rename from outdated/sys/amiga/winamenu.c rename to sys/amiga/winamenu.c diff --git a/outdated/sys/amiga/winami.c b/sys/amiga/winami.c similarity index 100% rename from outdated/sys/amiga/winami.c rename to sys/amiga/winami.c diff --git a/outdated/sys/amiga/winami.p b/sys/amiga/winami.p similarity index 100% rename from outdated/sys/amiga/winami.p rename to sys/amiga/winami.p diff --git a/outdated/sys/amiga/winchar.c b/sys/amiga/winchar.c similarity index 100% rename from outdated/sys/amiga/winchar.c rename to sys/amiga/winchar.c diff --git a/outdated/sys/amiga/windefs.h b/sys/amiga/windefs.h similarity index 100% rename from outdated/sys/amiga/windefs.h rename to sys/amiga/windefs.h diff --git a/outdated/sys/amiga/winext.h b/sys/amiga/winext.h similarity index 100% rename from outdated/sys/amiga/winext.h rename to sys/amiga/winext.h diff --git a/outdated/sys/amiga/winfuncs.c b/sys/amiga/winfuncs.c similarity index 100% rename from outdated/sys/amiga/winfuncs.c rename to sys/amiga/winfuncs.c diff --git a/outdated/sys/amiga/winkey.c b/sys/amiga/winkey.c similarity index 100% rename from outdated/sys/amiga/winkey.c rename to sys/amiga/winkey.c diff --git a/outdated/sys/amiga/winproto.h b/sys/amiga/winproto.h similarity index 100% rename from outdated/sys/amiga/winproto.h rename to sys/amiga/winproto.h diff --git a/outdated/sys/amiga/winreq.c b/sys/amiga/winreq.c similarity index 100% rename from outdated/sys/amiga/winreq.c rename to sys/amiga/winreq.c diff --git a/outdated/sys/amiga/winstr.c b/sys/amiga/winstr.c similarity index 100% rename from outdated/sys/amiga/winstr.c rename to sys/amiga/winstr.c diff --git a/outdated/sys/amiga/xpm2iff.c b/sys/amiga/xpm2iff.c similarity index 100% rename from outdated/sys/amiga/xpm2iff.c rename to sys/amiga/xpm2iff.c From 2d597cb9fa99e90517b4b024157f4ae280704b0b Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Mon, 23 Mar 2026 20:48:06 +0100 Subject: [PATCH 4/8] Revive Amiga port for NetHack 3.7 Update the Amiga Intuition window port (AMII/AMIV) for the 3.7 window_procs API. Key changes: - Update all window function signatures for 3.7 - Add assembly trampolines for AmigaOS register-based callbacks - Convert all K&R function definitions to C99 - Add cross-compilation build system (cross-pre1/pre2/post.370) using bebbo's m68k-amigaos-gcc with -noixemul -std=gnu17 -m68000 - Clipping fixes: viewport centering, simplified ScrollRaster, duplicate Ctrl-R suppression, glyph buffer invalidation - Add menucolor support in menu rendering - Move native txt2iff.c and xpm2iff.c to outdated/ - Add nethack.cnf and README.amiga --- include/amiconf.h | 8 +- include/winami.h | 1 + include/winprocs.h | 5 +- {sys => outdated/sys}/amiga/txt2iff.c | 0 {sys => outdated/sys}/amiga/xpm2iff.c | 0 src/rip.c | 3 +- sys/amiga/README.amiga | 106 ++++++ sys/amiga/amidos.c | 94 +++-- sys/amiga/amirip.c | 33 +- sys/amiga/amistack.c | 12 +- sys/amiga/amitty.c | 9 +- sys/amiga/amiwind.c | 147 ++++--- sys/amiga/nethack.cnf | 44 +++ sys/amiga/winamenu.c | 149 ++++---- sys/amiga/winami.c | 135 +++---- sys/amiga/winami.p | 8 +- sys/amiga/winchar.c | 371 +++++++----------- sys/amiga/windefs.h | 3 +- sys/amiga/winfuncs.c | 527 ++++++++++++++------------ sys/amiga/winkey.c | 13 +- sys/amiga/winproto.h | 27 +- sys/amiga/winreq.c | 91 ++--- sys/amiga/winstr.c | 48 +-- sys/share/pcmain.c | 5 + sys/unix/hints/include/cross-post.370 | 70 ++++ sys/unix/hints/include/cross-pre1.370 | 10 + sys/unix/hints/include/cross-pre2.370 | 90 +++++ 27 files changed, 1101 insertions(+), 908 deletions(-) rename {sys => outdated/sys}/amiga/txt2iff.c (100%) rename {sys => outdated/sys}/amiga/xpm2iff.c (100%) create mode 100644 sys/amiga/README.amiga create mode 100644 sys/amiga/nethack.cnf diff --git a/include/amiconf.h b/include/amiconf.h index d09801509..b607fd228 100644 --- a/include/amiconf.h +++ b/include/amiconf.h @@ -48,13 +48,9 @@ typedef long off_t; #define PATHLEN 130 /* data librarian defs */ -#ifndef NOCWD_ASSUMPTIONS -#define DLBFILE "NetHack:nhdat" /* main library */ -#define DLBFILE2 "NetHack:nhsdat" /* sound library */ -#else #define DLBFILE "nhdat" /* main library */ -#define DLBFILE2 "nhsdat" /* sound library */ -#endif +/* nhsdat sound library not used in 3.7 */ +#undef DLBFILE2 #ifndef CROSS_TO_AMIGA #define FILENAME_CMP stricmp /* case insensitive */ diff --git a/include/winami.h b/include/winami.h index b9fbfb65c..1cfd85078 100644 --- a/include/winami.h +++ b/include/winami.h @@ -22,6 +22,7 @@ typedef struct amii_mi { char gselector; /* Group selector */ char canselect; /* Can user select this entry. */ char attr; /* Attribute for the line. */ + int color; /* Color for the line (from menucolors). */ char *str; /* The text of the item. */ } amii_menu_item; diff --git a/include/winprocs.h b/include/winprocs.h index c77288891..688d76138 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -13,8 +13,11 @@ enum wp_ids { wp_tty = 1, wp_X11, wp_Qt, wp_mswin, wp_curses, wp_chainin, wp_chainout, wp_safestartup, wp_shim, wp_hup, wp_guistubs, wp_ttystubs, +#if defined(AMIGA) + wp_amii, wp_amiv, +#endif #ifdef OUTDATED_STUFF - wp_mac, wp_Gem, wp_Gnome, wp_amii, wp_amiv, + wp_mac, wp_Gem, wp_Gnome, #endif wp_trace // XXX do we need this? should chainin/out get an id? TBD }; diff --git a/sys/amiga/txt2iff.c b/outdated/sys/amiga/txt2iff.c similarity index 100% rename from sys/amiga/txt2iff.c rename to outdated/sys/amiga/txt2iff.c diff --git a/sys/amiga/xpm2iff.c b/outdated/sys/amiga/xpm2iff.c similarity index 100% rename from sys/amiga/xpm2iff.c rename to outdated/sys/amiga/xpm2iff.c diff --git a/src/rip.c b/src/rip.c index d482eb0a2..c9c64dfae 100644 --- a/src/rip.c +++ b/src/rip.c @@ -9,7 +9,8 @@ necessarily have to be used by a binary with multiple window-ports */ #if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) \ - || defined(DUMPLOG) || defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS) + || defined(DUMPLOG) || defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS) \ + || defined(AMII_GRAPHICS) #define TEXT_TOMBSTONE #endif #if defined(mac) || defined(__BEOS__) diff --git a/sys/amiga/README.amiga b/sys/amiga/README.amiga new file mode 100644 index 000000000..165501014 --- /dev/null +++ b/sys/amiga/README.amiga @@ -0,0 +1,106 @@ + NetHack 3.7 for Amiga + ==================== + +Requirements +------------ + - AmigaOS 3.0 or later (Kickstart 39+) + - 6 MB free RAM minimum (8 MB recommended) + - Hard drive with ~5 MB free space + +Recommended: RTG graphics card (Picasso96/CyberGraphX) for best +tile rendering. Native AGA/OCS/ECS chipsets are supported. + + +Installation +------------ +Extract NH370AMI.ZIP to a directory and assign it: + + assign NetHack: + +The directory should contain: + nethack - game binary + nhdat - data library + symbols - symbol set definitions + sysconf - system configuration + nethack.cnf - game options + hack.font - font descriptor + hack/8 - font bitmap (8pt) + tiles/tiles16.iff - 16-color tiles (OCS/ECS) + tiles/tiles32.iff - 32-color tiles (AGA/RTG) + tomb.iff - tombstone image + record - high score file + +To play: + cd NetHack: + nethack + + +Display Modes +------------- +Two display modes are available, selected in nethack.cnf: + + Text mode (AMII): + OPTIONS=symset:AmigaFont + + Tile mode (AMIV): + OPTIONS=windowtype:amiv + +Tile mode auto-selects tiles32.iff (32 colors, 5 bitplanes) when the +screen supports 32+ colors, otherwise tiles16.iff (16 colors, 4 planes). + + +Configuration +------------- +Edit nethack.cnf for game options. Key settings: + + OPTIONS=windowtype:amiv - tile graphics (default) + OPTIONS=symset:AmigaFont - text mode with line-drawing chars + OPTIONS=menucolors - colored inventory items + OPTIONS=time,lit_corridor - show turn count, lit corridors + OPTIONS=boulder:0 - display boulders as '0' + +Menu color examples (add after OPTIONS=menucolors): + MENUCOLOR=" blessed "=green + MENUCOLOR=" cursed "=red + MENUCOLOR=" uncursed "=cyan + + +Building from Source +-------------------- +Cross-compilation from Linux using bebbo's m68k-amigaos-gcc toolchain +(https://franke.ms/git/bebbo/amiga-gcc): + + # Install toolchain to /opt/amiga + # Clone NetHack 3.7 source + cd NetHack + make fetch-lua + sys/unix/setup.sh sys/unix/hints/linux.370 + make CROSS_TO_AMIGA=1 all + make CROSS_TO_AMIGA=1 package + +The distribution ZIP is created at targets/amiga/NH370AMI.ZIP. + +Toolchain requirements: + - m68k-amigaos-gcc (bebbo's amigaos-cross-toolchain in /opt/amiga) + - -noixemul (libnix) for linking + - -m68000 for maximum compatibility (or -m68020/040/060) + + +Known Issues +------------ + - Native Amiga compilation (SAS/C, DICE) is not supported; + cross-compilation with GCC is required + + +Credits +------- +Olaf Seibert first ported NetHack 2.3 and 3.0 to the Amiga. +Richard Addison, Andrew Church, Jochen Erwied, Mark Gooderum, +Ken Lorber, Greg Olson, Mike Passaretti, and Gregg Wonderly +polished and extended the 3.0 and 3.1 ports. Andrew Church, +Ken Lorber, and Gregg Wonderly are responsible for the 3.2 port. +Janne Salmijärvi resurrected the Amiga port for 3.3 and +Teemu Suikki joined before 3.4.0. + +Updated for NetHack 3.7, cross compile fixes and 32 color tile support by Ingo +Paschke in 2026. diff --git a/sys/amiga/amidos.c b/sys/amiga/amidos.c index 6ec41b5de..3d465ddd2 100644 --- a/sys/amiga/amidos.c +++ b/sys/amiga/amidos.c @@ -9,6 +9,7 @@ #include "hack.h" #include "winami.h" +#include "windefs.h" /* Defined in config.h, let's undefine it here (static function below) */ #undef strcmpi @@ -18,11 +19,17 @@ #include #undef COUNT + #if defined(__SASC_60) || defined(__GNUC__) #include #include #endif +/* POSIX stubs needed by libnix (-noixemul) */ +#ifdef __noixemul__ +int getpid(void) { return (int)FindTask(NULL); } +#endif + #ifdef AZTEC_50 #include #undef strcmpi @@ -34,11 +41,12 @@ #include "NH:sys/amiga/winami.p" #include "NH:sys/amiga/amidos.p" #else -#include "winami.p" +#include "amiwind.p" #include "winami.p" #include "amidos.p" #endif + extern char Initialized; extern struct window_procs amii_procs; struct ami_sysflags sysflags = {0}; @@ -54,13 +62,14 @@ char PATH[PATHLEN] = "NetHack:"; static boolean record_exists(void); void -flushout() +flushout(void) { (void) fflush(stdout); } #ifndef getuid -getuid() +int +getuid(void) { return 1; } @@ -68,26 +77,19 @@ getuid() #ifndef getlogin char * -getlogin() +getlogin(void) { return ((char *) NULL); } #endif -#ifndef AZTEC_50 -int -abs(x) -int x; -{ - return x < 0 ? -x : x; -} -#endif +/* abs() provided by libnix/stdlib */ #ifdef SHELL int -dosh() +dosh(void) { - int i; + int i = 0; char buf[BUFSZ]; extern struct ExecBase *SysBase; @@ -121,8 +123,7 @@ dosh() */ /* TODO: update this for FFS */ long -freediskspace(path) -char *path; +freediskspace(char *path) { #ifdef UNTESTED /* these changes from Patric Mueller for AROS to @@ -131,9 +132,9 @@ char *path; */ unsigned long long freeBytes = 0; #else - register long freeBytes = 0; + long freeBytes = 0; #endif - register struct InfoData *infoData; /* Remember... longword aligned */ + struct InfoData *infoData; /* Remember... longword aligned */ char fileName[32]; /* @@ -145,7 +146,7 @@ char *path; * so must be on the current device, so "" is enough... */ { - register char *colon; + char *colon; strncpy(fileName, path, sizeof(fileName) - 1); fileName[31] = 0; @@ -191,12 +192,11 @@ char *path; } long -filesize(file) -char *file; +filesize(char *file) { - register BPTR fileLock; - register struct FileInfoBlock *fileInfoBlock; - register long size = 0; + BPTR fileLock; + struct FileInfoBlock *fileInfoBlock; + long size = 0; fileInfoBlock = (struct FileInfoBlock *) alloc(sizeof(struct FileInfoBlock)); @@ -212,8 +212,8 @@ char *file; #if 0 void -eraseall(path, files) -const char *path, *files; +void +eraseall(const char *path, const char *files) { BPTR dirLock, dirLock2; struct FileInfoBlock *fibp; @@ -248,12 +248,11 @@ const char *path, *files; #if 0 /* Unused */ #define COPYSIZE 4096 -char *CopyFile(from, to) -const char *from, *to; +char *CopyFile(const char *from, const char *to) { - register BPTR fromFile, toFile; - register char *buffer; - register long size; + BPTR fromFile, toFile; + char *buffer; + long size; char *error = NULL; buffer = (char *) alloc(COPYSIZE); @@ -282,7 +281,8 @@ const char *from, *to; #ifdef MFLOPPY /* this should be replaced */ -saveDiskPrompt(start) +int +saveDiskPrompt(int start) { char buf[BUFSIZ], *bp; BPTR fileLock; @@ -338,7 +338,7 @@ saveDiskPrompt(start) /* Return 1 if the record file was found */ static boolean -record_exists() +record_exists(void) { FILE *file; @@ -355,7 +355,7 @@ record_exists() * For Amiga: do nothing, but called from restore.c */ void -gameDiskPrompt() +gameDiskPrompt(void) { } #endif @@ -365,8 +365,7 @@ gameDiskPrompt() * be room for the /. */ void -append_slash(name) -char *name; +append_slash(char *name) { char *ptr; @@ -381,8 +380,7 @@ char *name; } void -getreturn(str) -const char *str; +getreturn(const char *str) { int ch; @@ -396,12 +394,11 @@ const char *str; #define PATHSEP ';' FILE * -fopenp(name, mode) -register const char *name, *mode; +fopenp(const char *name, const char *mode) { - register char *bp, *pp, lastch; - register FILE *fp; - register BPTR theLock; + char *bp, *pp, lastch = 0; + FILE *fp; + BPTR theLock; char buf[BUFSIZ]; /* Try the default directory first. Then look along PATH. @@ -452,7 +449,8 @@ register const char *name, *mode; static BPTR OrgDirLock = NO_LOCK; -chdir(dir) char *dir; +int +chdir(char *dir) { extern char orgdir[]; @@ -489,7 +487,7 @@ chdir(dir) char *dir; */ #undef exit void -nethack_exit(code) +nethack_exit(int code) { #ifdef CHDIR extern char orgdir[]; @@ -506,10 +504,10 @@ nethack_exit(code) exit(code); } -void regularize(s) /* normalize file name - we don't like :'s or /'s */ -register char *s; +void +regularize(char *s) /* normalize file name - we don't like :'s or /'s */ { - register char *lp; + char *lp; while ((lp = strchr(s, ':')) || (lp = strchr(s, '/'))) *lp = '_'; diff --git a/sys/amiga/amirip.c b/sys/amiga/amirip.c index b14689f80..5f4aa52af 100644 --- a/sys/amiga/amirip.c +++ b/sys/amiga/amirip.c @@ -43,15 +43,15 @@ static struct RastPort *rp; #include #endif -static char *load_list[] = { "tomb.iff", 0 }; static BitMapHeader tomb_bmhd; -static struct BitMap *tbmp[1] = { 0 }; +static struct BitMap *tombimg = NULL; -static int cols[2] = { 154, 319 }; /* X location of center of columns */ +static const int cols_base[2] = { 154, 319 }; /* X location of center of columns */ +static int cols[2]; /* cols_base[] + xoff, computed per call */ static int cno = 0; /* current column */ #define TEXT_TOP (65 + yoff) -static xoff, yoff; /* image centering */ +static int xoff, yoff; /* image centering */ /* terrible kludge */ /* this is why prototypes should have ONLY types in them! */ @@ -100,19 +100,16 @@ int wh; /* was local in outrip, but needed for SCALE macro */ int cmap_white, cmap_black; void -amii_outrip(tmpwin, how, when) -winid tmpwin; -int how; -time_t when; +amii_outrip(winid tmpwin, int how, time_t when) { int just_return = 0; int done, rtxth; + struct IntuiMessage *imsg; int i; - register char *dpx; + char *dpx; char buf[200]; int line, tw, ww; - char *errstr = NULL; long year; if (!WINVERS_AMIV || HackScreen->RastPort.BitMap->Depth < 4) @@ -141,9 +138,7 @@ time_t when; SetFont(rp, HackFont); #endif - tomb_bmhd = ReadImageFiles(load_list, tbmp, &errstr); - if (errstr) - goto cleanup; + tomb_bmhd = ReadImageFile("tomb.iff", &tombimg); if (tomb_bmhd.w > ww || tomb_bmhd.h > wh) goto cleanup; @@ -151,12 +146,12 @@ time_t when; xoff = GENOFF(ww, tomb_bmhd.w); yoff = GENOFF(wh, tomb_bmhd.h); for (i = 0; i < SIZE(cols); i++) - cols[i] += xoff; + cols[i] = cols_base[i] + xoff; cmap_white = search_cmap(0, 0, 0); cmap_black = search_cmap(15, 15, 15); - BltBitMap(*tbmp, 0, 0, rp->BitMap, xoff, yoff, tomb_bmhd.w, tomb_bmhd.h, + BltBitMap(tombimg, 0, 0, rp->BitMap, xoff, yoff, tomb_bmhd.w, tomb_bmhd.h, 0xc0, 0xff, NULL); /* Put together death description */ @@ -199,7 +194,7 @@ time_t when; /* Put death type on stone */ for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) { - register int i, i0; + int i, i0; char tmpchar; if ((i0 = strlen(dpx)) > STONE_LINE_LEN) { @@ -280,8 +275,7 @@ cleanup: } LoadRGB4(&HackScreen->ViewPort, sysflags.amii_curmap, amii_numcolors); - if (tbmp[0]) - FreeImageFiles(load_list, tbmp); + FreeImageFile(&tombimg); if (just_return) return; /* fall back to the straight-ASCII version */ @@ -289,8 +283,7 @@ cleanup: } static void -tomb_text(p) -char *p; +tomb_text(char *p) { char buf[STONE_LINE_LEN * 2]; int l; diff --git a/sys/amiga/amistack.c b/sys/amiga/amistack.c index 33769697f..e0ea10a7b 100644 --- a/sys/amiga/amistack.c +++ b/sys/amiga/amistack.c @@ -1,5 +1,5 @@ /* NetHack 3.6 amistack.c $NHDT-Date: 1432512795 2015/05/25 00:13:15 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */ -/* Copyright (c) Janne Salmijärvi, Tampere, Finland, 2000 */ +/* Copyright (c) Janne Salmij�rvi, Tampere, Finland, 2000 */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -12,10 +12,16 @@ #ifdef __SASC_60 #include +#endif /* - * At the moment 90*1024 would suffice, but just to be on the safe side ... + * Increase stack size to allow deep recursions. + * NetHack 3.7 with Lua needs significantly more stack than 3.6. */ -long __stack = 128 * 1024; +#ifdef __SASC_60 +long __stack = 256 * 1024; +#else +/* For GCC with -noixemul (libnix), __stack is also recognized */ +unsigned long __stack = 256 * 1024; #endif diff --git a/sys/amiga/amitty.c b/sys/amiga/amitty.c index e3ff882ef..22036c8f5 100644 --- a/sys/amiga/amitty.c +++ b/sys/amiga/amitty.c @@ -23,12 +23,12 @@ void tty_change_color(void); char *tty_get_color_string(void); -#ifdef TTY_GRAPHICS - int amibbs = 0; /* BBS mode */ char bbs_id[80] = ""; /* BBS uid equivalent */ long afh_in, afh_out; /* BBS mode Amiga filehandles */ +#ifdef TTY_GRAPHICS + void settty(const char *s) { @@ -58,9 +58,10 @@ setftty() } char kill_char = 'X' - '@'; char erase_char = '\b'; -tgetch() +int +tgetch(void) { - char x; + unsigned char x; Read(afh_in, &x, 1); return (x == '\r') ? '\n' : x; } diff --git a/sys/amiga/amiwind.c b/sys/amiga/amiwind.c index 6a64667eb..e06630675 100644 --- a/sys/amiga/amiwind.c +++ b/sys/amiga/amiwind.c @@ -23,18 +23,20 @@ static struct Message *GetFMsg(struct MsgPort *); #endif static int BufferGetchar(void); -static void ProcessMessage(register struct IntuiMessage *message); +static void ProcessMessage(struct IntuiMessage *message); #define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch)) -#ifndef CROSS_TO_AMIGA -struct Library *ConsoleDevice; -#else -struct Device * -# ifdef __CONSTLIBBASEDECL__ - __CONSTLIBBASEDECL__ -# endif /* __CONSTLIBBASEDECL__ */ - ConsoleDevice; -#endif + +struct Device *ConsoleDevice = NULL; + +/* Library bases - opened by amii_init_nhwindows, closed by amii_cleanup. + DOSBase is provided by newlib's startup code. + The rest must be defined here. */ +struct IntuitionBase *IntuitionBase = NULL; +struct GfxBase *GfxBase = NULL; +struct Library *GadToolsBase = NULL; +struct Library *LayersBase = NULL; +struct Library *AslBase = NULL; #ifndef CROSS_TO_AMIGA #include "NH:sys/amiga/amimenu.c" @@ -44,7 +46,6 @@ struct Device * /* Now our own variables */ -struct IntuitionBase *IntuitionBase; struct Screen *HackScreen; struct Window *pr_WindowPtr; struct MsgPort *HackPort; @@ -55,7 +56,6 @@ char Initialized = 0; WEVENT lastevent; #ifdef HACKFONT -struct GfxBase *GfxBase; struct Library *DiskfontBase; #endif @@ -100,11 +100,10 @@ static enum { NoAction, CloseOver } delayed_key_action = NoAction; */ struct Window * -OpenShWindow(nw) -struct NewWindow *nw; +OpenShWindow(struct NewWindow *nw) { - register struct Window *win; - register ULONG idcmpflags; + struct Window *win; + ULONG idcmpflags; if (!HackPort) /* Sanity check */ return (struct Window *) 0; @@ -126,12 +125,10 @@ struct NewWindow *nw; * Close a window that shared the HackPort IDCMP port. */ -void CloseShWindow(struct Window *); void -CloseShWindow(win) -struct Window *win; +CloseShWindow(struct Window *win) { - register struct IntuiMessage *msg; + struct IntuiMessage *msg; if (!HackPort) panic("HackPort NULL in CloseShWindow"); @@ -152,9 +149,9 @@ struct Window *win; } static int -BufferGetchar() +BufferGetchar(void) { - register int c; + int c; if (KbdBuffered > 0) { c = KbdBuffer[0]; @@ -180,8 +177,7 @@ BufferGetchar() */ int -ConvertKey(message) -register struct IntuiMessage *message; +ConvertKey(struct IntuiMessage *message) { static struct InputEvent theEvent; static char numpad[] = "bjnh.lyku"; @@ -190,8 +186,8 @@ register struct IntuiMessage *message; unsigned char buffer[10]; struct Window *w = message->IDCMPWindow; - register int length; - register ULONG qualifier; + int length; + ULONG qualifier; char numeric_pad, shift, control, alt; if (amii_wins[WIN_MAP]) @@ -355,10 +351,7 @@ register struct IntuiMessage *message; return (-1); } } - printf("Unrecognized key: %d ", (int) buffer[0]); - for (i = 1; i < length; ++i) - printf("%d ", (int) buffer[i]); - printf("\n"); + /* unrecognized key — silently ignore */ } return (-1); } @@ -373,8 +366,7 @@ register struct IntuiMessage *message; */ static void -ProcessMessage(message) -register struct IntuiMessage *message; +ProcessMessage(struct IntuiMessage *message) { int c; int cnt; @@ -385,15 +377,7 @@ register struct IntuiMessage *message; switch (message->Class) { case ACTIVEWINDOW: - if (alwaysinvent && WIN_INVEN != WIN_ERR - && w == amii_wins[WIN_INVEN]->win) { - cnt = DoMenuScroll(WIN_INVEN, 0, PICK_NONE, &mip); - } else if (scrollmsg && WIN_MESSAGE != WIN_ERR - && w == amii_wins[WIN_MESSAGE]->win) { - cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip); - } else { - skip_mouse = 1; - } + skip_mouse = 1; break; case MOUSEBUTTONS: { @@ -429,12 +413,8 @@ register struct IntuiMessage *message; } } break; - case REFRESHWINDOW: { - if (scrollmsg && amii_wins[WIN_MESSAGE] - && w == amii_wins[WIN_MESSAGE]->win) { - cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip); - } - } break; + case REFRESHWINDOW: + break; case CLOSEWINDOW: if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) { @@ -458,11 +438,6 @@ register struct IntuiMessage *message; break; case GADGETDOWN: - if (WIN_MESSAGE != WIN_ERR && w == amii_wins[WIN_MESSAGE]->win) { - cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip); - } else if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) { - cnt = DoMenuScroll(WIN_INVEN, 0, PICK_NONE, &mip); - } break; case NEWSIZE: @@ -481,7 +456,17 @@ register struct IntuiMessage *message; ReDisplayData(WIN_INVEN); } else if (WINVERS_AMIV && (WIN_OVER != WIN_ERR && w == amii_wins[WIN_OVER]->win)) { - BufferQueueChar('R' - 64); + { + int i, have_redraw = 0; + for (i = 0; i < KbdBuffered; i++) { + if (KbdBuffer[i] == 'R' - 64) { + have_redraw = 1; + break; + } + } + if (!have_redraw) + BufferQueueChar('R' - 64); + } } else if (WIN_MAP != WIN_ERR && w == amii_wins[WIN_MAP]->win) { #ifdef CLIPPING CO = (w->Width - w->BorderLeft - w->BorderRight) / mxsize; @@ -494,7 +479,17 @@ register struct IntuiMessage *message; clipping = FALSE; clipx = clipy = 0; } - BufferQueueChar('R' - 64); + { + int i, have_redraw = 0; + for (i = 0; i < KbdBuffered; i++) { + if (KbdBuffer[i] == 'R' - 64) { + have_redraw = 1; + break; + } + } + if (!have_redraw) + BufferQueueChar('R' - 64); + } #endif } break; @@ -506,8 +501,9 @@ register struct IntuiMessage *message; amii_destroy_nhwindow(WIN_OVER); WIN_OVER = WIN_ERR; delayed_key_action = NoAction; + break; case NoAction: - ; /* null */ + break; } } @@ -522,13 +518,13 @@ register struct IntuiMessage *message; #if defined(TTY_GRAPHICS) && !defined(AMII_GRAPHICS) int -kbhit() +kbhit(void) { return 0; } #else int -kbhit() +kbhit(void) { int c; #ifdef TTY_GRAPHICS @@ -547,9 +543,9 @@ kbhit() #ifdef AMII_GRAPHICS int -amikbhit() +amikbhit(void) { - register struct IntuiMessage *message; + struct IntuiMessage *message; while (KbdBuffered < KBDBUFFER / 2) { #ifdef AMIFLUSH message = (struct IntuiMessage *) GetFMsg(HackPort); @@ -572,7 +568,7 @@ amikbhit() */ int -WindowGetchar() +WindowGetchar(void) { while ((lastevent.type = WEUNK), amikbhit() <= 0) { WaitPort(HackPort); @@ -581,7 +577,7 @@ WindowGetchar() } WETYPE -WindowGetevent() +WindowGetevent(void) { lastevent.type = WEUNK; while (amikbhit() == 0) { @@ -601,9 +597,9 @@ WindowGetevent() */ void -amii_cleanup() +amii_cleanup(void) { - register struct IntuiMessage *msg; + struct IntuiMessage *msg; /* Close things up */ if (HackPort) { @@ -713,8 +709,7 @@ amii_cleanup() #ifndef SHAREDLIB void -Abort(rc) -long rc; +Abort(long rc) { int fault = 1; #ifdef CHDIR @@ -765,7 +760,7 @@ long rc; } void -CleanUp() +CleanUp(void) { amii_cleanup(); } @@ -776,8 +771,7 @@ CleanUp() #ifdef AMIFLUSH /* This routine adapted from AmigaMail IV-37 by Michael Sinz */ static struct Message * -GetFMsg(port) -struct MsgPort *port; +GetFMsg(struct MsgPort *port) { struct IntuiMessage *msg, *succ, *succ1; @@ -803,8 +797,7 @@ struct MsgPort *port; #endif struct NewWindow * -DupNewWindow(win) -struct NewWindow *win; +DupNewWindow(struct NewWindow *win) { struct NewWindow *nwin; struct Gadget *ngd, *gd, *pgd = NULL; @@ -845,11 +838,10 @@ struct NewWindow *win; } void -FreeNewWindow(win) -struct NewWindow *win; +FreeNewWindow(struct NewWindow *win) { - register struct Gadget *gd, *pgd; - register struct StringInfo *sip; + struct Gadget *gd, *pgd; + struct StringInfo *sip; for (gd = win->FirstGadget; gd; gd = pgd) { pgd = gd->NextGadget; @@ -868,7 +860,7 @@ struct NewWindow *win; } void -bell() +bell(void) { if (flags.silent) return; @@ -876,15 +868,14 @@ bell() } void -amii_delay_output() +amii_delay_output(void) { /* delay 50 ms */ Delay(2L); } void -amii_number_pad(state) -int state; +amii_number_pad(int state) { } #endif /* AMII_GRAPHICS */ diff --git a/sys/amiga/nethack.cnf b/sys/amiga/nethack.cnf new file mode 100644 index 000000000..dad37d4d5 --- /dev/null +++ b/sys/amiga/nethack.cnf @@ -0,0 +1,44 @@ +# NetHack 3.7 Amiga Configuration +# +# For a full list of options, see the opthelp file or press '?' +# then 'o' during gameplay. + +# *** DISPLAY MODE *** +# +# Tile mode (graphical tiles, recommended): +OPTIONS=windowtype:amiv +# +# Text mode (uses hack.font line-drawing characters): +#OPTIONS=windowtype:amii +#OPTIONS=symset:AmigaFont + +# *** GENERAL OPTIONS *** +OPTIONS=time,showexp,lit_corridor +OPTIONS=boulder:0 +OPTIONS=autopickup,pickup_types:$"=/!?+ +OPTIONS=catname:Kaori + +# *** MENU COLORS *** +# Colour-code inventory items by BUC status and value. +OPTIONS=menucolors +MENUCOLOR=" blessed "=green +MENUCOLOR=" holy "=green +MENUCOLOR=" uncursed "=cyan +MENUCOLOR=" cursed "=red +MENUCOLOR=" unholy "=red +MENUCOLOR=" cursed .* (being worn)"=red&underline +MENUCOLOR=" cursed .* (wielded)"=red&underline +MENUCOLOR="loadstone"=red&underline +MENUCOLOR="gold piece"=brown +MENUCOLOR="worthless"=brown +MENUCOLOR="wand of wishing"=magenta +MENUCOLOR="magic lamp"=magenta +MENUCOLOR="magic marker"=magenta +MENUCOLOR="bag of holding"=magenta +MENUCOLOR="amulet of life saving"=magenta +MENUCOLOR="cloak of magic resistance"=magenta +MENUCOLOR="silver dragon scale"=cyan +MENUCOLOR="gray dragon scale"=cyan +MENUCOLOR="speed boots"=magenta +MENUCOLOR="luckstone"=green +MENUCOLOR="unicorn horn"=green diff --git a/sys/amiga/winamenu.c b/sys/amiga/winamenu.c index 013e3c792..d391bdec4 100644 --- a/sys/amiga/winamenu.c +++ b/sys/amiga/winamenu.c @@ -15,14 +15,12 @@ /* Start building the text for a menu */ void -amii_start_menu(window, mbehavior) -register winid window; -unsigned long mbehavior UNUSED; - +amii_start_menu(winid window, unsigned long mbehavior UNUSED) { - register int i; - register struct amii_WinDesc *cw; - register amii_menu_item *mip; + int i; + struct amii_WinDesc *cw; + amii_menu_item *mip; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) @@ -64,17 +62,12 @@ unsigned long mbehavior UNUSED; /* Add a string to a menu */ void -amii_add_menu(window, glyph, id, ch, gch, attr, str, itemflags) -register winid window; -register int glyph; -register const anything *id; -register char ch; -register char gch; -register int attr; -register const char *str; -register unsigned int itemflags; +amii_add_menu(winid window, const glyph_info *glyphinfo, const anything *id, + char ch, char gch, int attr, int clr, + const char *str, unsigned int itemflags) { - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + boolean preselected = ((itemflags & MENU_ITEMFLAGS_SELECTED) != 0); amii_menu_item *mip; char buf[4 + BUFSZ]; @@ -90,7 +83,8 @@ register unsigned int itemflags; mip->identifier = *id; mip->selected = preselected; mip->attr = attr; - mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : glyph; + mip->color = clr; + mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : (glyphinfo ? glyphinfo->glyph : NO_GLYPH); mip->selector = 0; mip->gselector = gch; mip->count = -1; @@ -131,11 +125,10 @@ register unsigned int itemflags; /* Done building a menu. */ void -amii_end_menu(window, morestr) -register winid window; -register const char *morestr; +amii_end_menu(winid window, const char *morestr) { - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) @@ -151,8 +144,8 @@ register const char *morestr; mip = cw->menu.last; #endif any.a_void = 0; - amii_add_menu(window, NO_GLYPH, &any, 0, 0, ATR_NONE, morestr, - MENU_ITEMFLAGS_NONE); + amii_add_menu(window, (const glyph_info *) 0, &any, 0, 0, ATR_NONE, + NO_COLOR, morestr, MENU_ITEMFLAGS_NONE); #ifdef PROMPTFIRST /* Do some shuffling. Last first, push others one forward \ */ mip->next = NULL; @@ -178,13 +171,11 @@ register const char *morestr; /* Select something from the menu. */ int -amii_select_menu(window, how, mip) -register winid window; -register int how; -register menu_item **mip; +amii_select_menu(winid window, int how, menu_item **mip) { int cnt; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) @@ -199,7 +190,7 @@ register menu_item **mip; } amii_menu_item * -find_menu_item(register struct amii_WinDesc *cw, int idx) +find_menu_item(struct amii_WinDesc *cw, int idx) { amii_menu_item *mip; for (mip = cw->menu.items; idx > 0 && mip; mip = mip->next) @@ -209,11 +200,11 @@ find_menu_item(register struct amii_WinDesc *cw, int idx) } int -make_menu_items(register struct amii_WinDesc *cw, register menu_item **rmip) +make_menu_items(struct amii_WinDesc *cw, menu_item **rmip) { - register int idx = 0; - register amii_menu_item *mip; - register menu_item *mmip; + int idx = 0; + amii_menu_item *mip; + menu_item *mmip; for (mip = cw->menu.items; mip; mip = mip->next) { if (mip->selected) @@ -236,19 +227,17 @@ make_menu_items(register struct amii_WinDesc *cw, register menu_item **rmip) } int -DoMenuScroll(win, blocking, how, retmip) -int win, blocking, how; -menu_item **retmip; +DoMenuScroll(int win, int blocking, int how, menu_item **retmip) { amii_menu_item *amip; - register struct Window *w; - register struct NewWindow *nw; + struct Window *w; + struct NewWindow *nw; struct PropInfo *pip; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; struct IntuiMessage *imsg; struct Gadget *gd; - register int wheight, xsize, ysize, aredone = 0; - register int txwd, txh; + int wheight, xsize, ysize, aredone = 0; + int txwd, txh; long mics, secs, class, code; long oldmics = 0, oldsecs = 0; int aidx, oidx, topidx, hidden; @@ -819,7 +808,7 @@ menu_item **retmip; ++topidx; else break; - } else if (code = CTRL('U') + } else if (code == CTRL('U') || code == MENU_PREVIOUS_PAGE) { if (topidx > 0) --topidx; @@ -1007,11 +996,13 @@ menu_item **retmip; oldmics = mics; } else { amip = find_menu_item(cw, oidx); - amip->selected = 0; - amip->count = -1; - reset_counting = TRUE; - if (amip->canselect && amip->selector) - amip->str[SOFF + 2] = '-'; + if (amip) { + amip->selected = 0; + amip->count = -1; + reset_counting = TRUE; + if (amip->canselect && amip->selector) + amip->str[SOFF + 2] = '-'; + } } if (counting && amip->selected && amip->canselect && amip->selector) { @@ -1092,13 +1083,12 @@ menu_item **retmip; } void -ReDisplayData(win) -winid win; +ReDisplayData(winid win) { int totalvis; - register struct amii_WinDesc *cw; - register struct Window *w; - register struct Gadget *gd; + struct amii_WinDesc *cw; + struct Window *w; + struct Gadget *gd; unsigned long hidden, aidx, wheight; struct PropInfo *pip; @@ -1123,15 +1113,13 @@ winid win; } long -FindLine(win, line) -winid win; -int line; +FindLine(winid win, int line) { int txwd; - register char *t; - register struct amii_WinDesc *cw; - register struct Window *w; - register int i, disprow, len; + char *t; + struct amii_WinDesc *cw; + struct Window *w; + int i, disprow, len; int col = -1; if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) { @@ -1186,15 +1174,14 @@ int line; } long -CountLines(win) -winid win; +CountLines(winid win) { int txwd; amii_menu_item *mip; - register char *t; - register struct amii_WinDesc *cw; - register struct Window *w; - register int i, disprow, len; + char *t; + struct amii_WinDesc *cw; + struct Window *w; + int i, disprow, len; int col = -1; if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) { @@ -1250,17 +1237,15 @@ winid win; } void -DisplayData(win, start) -winid win; -int start; +DisplayData(winid win, int start) { int txwd; amii_menu_item *mip; - register char *t; - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; - register int i, disprow, len, wheight; + char *t; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; + int i, disprow, len, wheight; int whichcolor = -1; int col; @@ -1363,6 +1348,13 @@ int start; whichcolor = 2; } + /* Apply menucolor if set for this item */ + if (mip && mip->color != NO_COLOR && !(mip->selected)) { + extern const int foreg[]; + SetAPen(rp, foreg[mip->color]); + whichcolor = 0; /* force re-evaluation next item */ + } + /* Next line out, wrap if too long */ t = cw->data[i] + SOFF; @@ -1427,14 +1419,11 @@ int start; } void -SetPropInfo(win, gad, vis, total, top) -register struct Window *win; -register struct Gadget *gad; -register long vis, total, top; +SetPropInfo(struct Window *win, struct Gadget *gad, long vis, long total, long top) { long mflags; - register long hidden; - register int body, pot; + long hidden; + int body, pot; hidden = max(total - vis, 0); diff --git a/sys/amiga/winami.c b/sys/amiga/winami.c index 4b7866346..7770a3547 100644 --- a/sys/amiga/winami.c +++ b/sys/amiga/winami.c @@ -39,7 +39,8 @@ long amii_scrnmode; * the intuition interface for the amiga... */ struct window_procs amii_procs = { - "amii", WC_COLOR | WC_HILITE_PET | WC_INVERSE, + WPID(amii), + WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ amii_init_nhwindows, @@ -48,7 +49,7 @@ struct window_procs amii_procs = { amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow, amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed, amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu, - amii_select_menu, genl_message_menu, amii_update_inventory, + amii_select_menu, genl_message_menu, amii_mark_synch, amii_wait_synch, #ifdef CLIPPING amii_cliparound, @@ -67,13 +68,16 @@ struct window_procs amii_procs = { genl_status_init, genl_status_finish, genl_status_enablefield, genl_status_update, genl_can_suspend_yes, + amii_update_inventory, + amii_ctrl_nhwindow, }; /* The view window layout uses the same function names so we can use * a shared library to allow the executable to be smaller. */ struct window_procs amiv_procs = { - "amitile", WC_COLOR | WC_HILITE_PET | WC_INVERSE, + WPID(amiv), + WC_COLOR | WC_HILITE_PET | WC_INVERSE, 0L, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */ amii_init_nhwindows, @@ -82,7 +86,7 @@ struct window_procs amiv_procs = { amii_create_nhwindow, amii_clear_nhwindow, amii_display_nhwindow, amii_destroy_nhwindow, amii_curs, amii_putstr, genl_putmixed, amii_display_file, amii_start_menu, amii_add_menu, amii_end_menu, - amii_select_menu, genl_message_menu, amii_update_inventory, + amii_select_menu, genl_message_menu, amii_mark_synch, amii_wait_synch, #ifdef CLIPPING amii_cliparound, @@ -101,6 +105,8 @@ struct window_procs amiv_procs = { genl_status_init, genl_status_finish, genl_status_enablefield, genl_status_update, genl_can_suspend_yes, + amii_update_inventory, + amii_ctrl_nhwindow, }; unsigned short amii_initmap[AMII_MAXCOLORS]; @@ -428,7 +434,7 @@ struct NewScreen NewHackScreen = { 0, 0, WIDTH, SCREENHEIGHT, 3, 0, * init_sound_disp_gamewindows(). */ void -amii_askname() +amii_askname(void) { char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */ *plnametmp = 0; @@ -454,12 +460,12 @@ amii_askname() #if 0 /* New function at the bottom */ void -amii_player_selection() +amii_player_selection(void) { - register struct Window *cwin; - register struct IntuiMessage *imsg; - register int aredone = 0; - register struct Gadget *gd; + struct Window *cwin; + struct IntuiMessage *imsg; + int aredone = 0; + struct Gadget *gd; static int once = 0; long class, code; @@ -499,7 +505,7 @@ amii_player_selection() #ifdef INTUI_NEW_LOOK Type_NewWindowStructure1.Extension = wintags; Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; - fillhook.h_Entry = (ULONG(*)())LayerFillHook; + fillhook.h_Entry = (void *) &LayerFillHook; fillhook.h_Data = (void *)-2; fillhook.h_SubEntry = 0; #endif @@ -595,8 +601,7 @@ amii_player_selection() #include "NH:sys/amiga/randwin.c" void -RandomWindow( name ) - char *name; +RandomWindow(char *name) { struct MsgPort *tport; struct timerequest *trq; @@ -672,7 +677,7 @@ allocerr: #ifdef INTUI_NEW_LOOK Rnd_NewWindowStructure1.Extension = wintags; Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; - fillhook.h_Entry = (ULONG(*)())LayerFillHook; + fillhook.h_Entry = (void *) &LayerFillHook; fillhook.h_Data = (void *)-2; fillhook.h_SubEntry = 0; #endif @@ -762,10 +767,11 @@ amii_get_ext_cmd(void) #endif int colx; int bottom = 0; + struct Window *w; char obufp[100]; - register char *bufp = obufp; - register int c; + char *bufp = obufp; + int c; int com_index, oindex; int did_comp = 0; /* did successful completion? */ int sel = -1; @@ -787,7 +793,8 @@ amii_get_ext_cmd(void) id.a_char = *extcmdlist[i].ef_txt; sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt, extcmdlist[i].ef_desc); - amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0, + amii_add_menu(win, (const glyph_info *) 0, &id, + extcmdlist[i].ef_txt[0], 0, 0, NO_COLOR, buf, MENU_ITEMFLAGS_NONE); } @@ -848,8 +855,9 @@ amii_get_ext_cmd(void) id.a_char = extcmdlist[i].ef_txt[0]; sprintf(buf, "%-10s - %s ", extcmdlist[i].ef_txt, extcmdlist[i].ef_desc); - amii_add_menu(win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, - 0, buf, MENU_ITEMFLAGS_NONE); + amii_add_menu(win, (const glyph_info *) 0, &id, + extcmdlist[i].ef_txt[0], 0, 0, NO_COLOR, + buf, MENU_ITEMFLAGS_NONE); } amii_end_menu(win, (char *) 0); @@ -941,10 +949,7 @@ amii_get_ext_cmd(void) } static int -put_ext_cmd(obufp, colx, cw, bottom) -char * obufp; -int colx, bottom; -struct amii_WinDesc *cw; +put_ext_cmd(char *obufp, int colx, struct amii_WinDesc *cw, int bottom) { struct Window *w = cw->win; char *t; @@ -989,10 +994,9 @@ struct amii_WinDesc *cw; /* Ask a question and get a response */ char -amii_yn_function(query, resp, def) -const char * query, *resp; -char def; +amii_yn_function(const char *query, const char *resp, char def) { + /* * Generic yes/no function. 'def' is the default (returned by space or * return; 'esc' returns 'q', or 'n', or the default, depending on @@ -1004,11 +1008,11 @@ char def; * are allowed); if it includes an , anything beyond that won't * be shown in the prompt to the user but will be acceptable as input. */ - register char q; + char q; char rtmp[40]; boolean digit_ok, allow_num; char prompt[BUFSZ]; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; if (cw = amii_wins[WIN_MESSAGE]) cw->disprows = 0; @@ -1138,16 +1142,15 @@ char def; } void -amii_display_file(fn, complain) -const char * fn; -boolean complain; +amii_display_file(const char *fn, boolean complain) { - register struct amii_WinDesc *cw; - register int win; - register dlb *fp; - register char *t; + struct amii_WinDesc *cw; + int win; + dlb *fp; + char *t; char buf[200]; + if (fn == NULL) panic("NULL file name in display_file()"); @@ -1194,12 +1197,11 @@ boolean complain; * are rendered in the up position by default. */ void -SetBorder(gd) -register struct Gadget * gd; +SetBorder(struct Gadget *gd) { - register struct Border *bp; - register short *sp; - register int i, inc = -1, dec = -1; + struct Border *bp; + short *sp; + int i, inc = -1, dec = -1; int borders = 6; int hipen = sysflags.amii_dripens[SHINEPEN], shadowpen = sysflags.amii_dripens[SHADOWPEN]; @@ -1337,7 +1339,7 @@ register struct Gadget * gd; /* Following function copied from wintty.c; Modified slightly to fit amiga needs */ void -amii_player_selection() +amii_player_selection(void) { int i, k, n; char pick4u = 'n', thisch, lastch = 0; @@ -1346,6 +1348,7 @@ amii_player_selection() anything any; menu_item *selected = 0; + rigid_role_checks(); /* Should we randomly pick for the player? */ @@ -1424,8 +1427,8 @@ amii_player_selection() } else Strcpy(rolenamebuf, roles[i].name.m); } - add_menu(win, NO_GLYPH, &any, thisch, 0, ATR_NONE, - an(rolenamebuf), MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, thisch, 0, ATR_NONE, + NO_COLOR, an(rolenamebuf), MENU_ITEMFLAGS_NONE); lastch = thisch; } } @@ -1433,11 +1436,11 @@ amii_player_selection() flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrole(FALSE) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick a role for your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); @@ -1498,19 +1501,19 @@ amii_player_selection() if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) { any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, races[i].noun[0], 0, - ATR_NONE, races[i].noun, + add_menu(win, &nul_glyphinfo, &any, races[i].noun[0], 0, + ATR_NONE, NO_COLOR, races[i].noun, MENU_ITEMFLAGS_NONE); } any.a_int = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrace(flags.initrole) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the race of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); @@ -1571,18 +1574,19 @@ amii_player_selection() if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) { any.a_int = i + 1; - add_menu(win, NO_GLYPH, &any, genders[i].adj[0], 0, - ATR_NONE, genders[i].adj, MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, genders[i].adj[0], 0, + ATR_NONE, NO_COLOR, genders[i].adj, + MENU_ITEMFLAGS_NONE); } any.a_int = pick_gend(flags.initrole, flags.initrace, flags.initalign, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randgend(flags.initrole, flags.initrace) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the gender of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); @@ -1642,18 +1646,19 @@ amii_player_selection() if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) { any.a_int = i + 1; - add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], 0, - ATR_NONE, aligns[i].adj, MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, aligns[i].adj[0], 0, + ATR_NONE, NO_COLOR, aligns[i].adj, + MENU_ITEMFLAGS_NONE); } any.a_int = pick_align(flags.initrole, flags.initrace, flags.initgend, PICK_RANDOM) + 1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randalign(flags.initrole, flags.initrace) + 1; - add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, '*', 0, ATR_NONE, + NO_COLOR, "Random", MENU_ITEMFLAGS_NONE); any.a_int = i + 1; /* must be non-zero */ - add_menu(win, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit", - MENU_ITEMFLAGS_NONE); + add_menu(win, &nul_glyphinfo, &any, 'q', 0, ATR_NONE, + NO_COLOR, "Quit", MENU_ITEMFLAGS_NONE); Sprintf(pbuf, "Pick the alignment of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); diff --git a/sys/amiga/winami.p b/sys/amiga/winami.p index 2e26cfb10..dfb588177 100644 --- a/sys/amiga/winami.p +++ b/sys/amiga/winami.p @@ -5,10 +5,10 @@ void amii_raw_print(const char *); void amii_raw_print_bold(const char *); void amii_start_menu(winid , unsigned long ); -void amii_add_menu(winid , char , int , const char *, unsigned int); +void amii_add_menu(winid, const glyph_info *, const anything *, char, char, int, int, const char *, unsigned int); void amii_end_menu(winid , char , const char * , const char *); char amii_select_menu(winid ); -void amii_update_inventory (void); +void amii_update_inventory(int); void amii_mark_synch (void); void amii_wait_synch (void); void amii_setclipped (void); @@ -27,7 +27,7 @@ void amii_putstr(winid , int , const char *); void amii_putsym(winid , int , int , CHAR_P ); void amii_clear_nhwindow(winid ); void amii_exit_nhwindows(const char *); -int amii_nh_poskey(int * , int * , int *); +int amii_nh_poskey(coordxy *, coordxy *, int *); int amii_nhgetch (void); void amii_get_nh_event (void); void amii_remember_topl (void); @@ -35,7 +35,7 @@ int amii_doprev_message (void); void amii_display_nhwindow(winid , boolean ); void amii_display_file(const char * , boolean ); void amii_curs(winid , int , int ); -void amii_print_glyph(winid , coordxy , coordxy , int, int ); +void amii_print_glyph(winid, coordxy, coordxy, const glyph_info *, const glyph_info *); void DoMenuScroll(int , int ); void DisplayData(int , int , int ); void SetPropInfo(struct Window * , struct Gadget * , long , long , long ); diff --git a/sys/amiga/winchar.c b/sys/amiga/winchar.c index e4e56b8a2..75c35c87b 100644 --- a/sys/amiga/winchar.c +++ b/sys/amiga/winchar.c @@ -41,7 +41,8 @@ int main(int, char **); struct BitMap *MyAllocBitMap(int, int, int, long); void MyFreeBitMap(struct BitMap *); -void FreeImageFiles(char **, struct BitMap **); +BitMapHeader ReadImageFile(const char *, struct BitMap **); +void FreeImageFile(struct BitMap **); void amiv_flush_glyph_buffer(struct Window *); void amiv_lprint_glyph(winid, int, int); void amii_lprint_glyph(winid, int, int); @@ -91,17 +92,9 @@ extern int maxmontile, maxobjtile, maxothtile; /* from tile.c */ struct PDAT pictdata; -#define NUMTILEIMAGES 3 -char *tileimages[] = { -#define TBLMONTILE 0 - "NetHack:tiles/monsters.iff", -#define TBLOBJTILE 1 - "NetHack:tiles/objects.iff", -#define TBLOTHTILE 2 - "NetHack:tiles/other.iff", 0, -}; - -struct BitMap *ifftimg[NUMTILEIMAGES], *tile; +/* Single tile image file, set at runtime by amii_init_nhwindows */ +char *tilefile; +struct BitMap *tileimg, *tile; #ifdef TESTING short pens[NUMDRIPENS] = { 8, 3, 15, 0, 15, 7, 7, 8, 0 }; @@ -146,7 +139,7 @@ main(int argc, char **argv) x = x % IMGCOLUMNS; dx = i % (IMGCOLUMNS * 2); dy = i / (IMGCOLUMNS * 2); - BltBitMapRastPort(ifftimg[tbl], x * pictdata.xsize, + BltBitMapRastPort(tileimg, x * pictdata.xsize, y * pictdata.ysize, w->RPort, w->BorderLeft + 1 + dx * pictdata.xsize, w->BorderTop + 1 + dy * pictdata.ysize, @@ -176,175 +169,112 @@ main(int argc, char **argv) CloseScreen(scr); } - FreeImageFiles(tileimages, ifftimg); + FreeTileImageFiles(); return (0); } #endif +/* + * Read a single BMAP IFF file into a BitMap. + * Returns the BitMapHeader; *bmp receives the bitmap. + * Caller frees via FreeImageFile(). + */ BitMapHeader -ReadTileImageFiles() +ReadImageFile(const char *filename, struct BitMap **bmp) { - char *errstr = NULL; - BitMapHeader ret = ReadImageFiles(tileimages, ifftimg, &errstr); - if (errstr) { - panic(errstr); - } - return ret; -} - -BitMapHeader -ReadImageFiles(char **filenames, struct BitMap **iffimg, char **errstrp) -{ - BitMapHeader *bmhd = NULL, bmhds; - unsigned char *cmap; - extern int errno; - register int i, j; + BitMapHeader *bmhd, bmhds; + int j, np; struct IFFHandle *iff; struct StoredProperty *prop; IFFParseBase = OpenLibrary("iffparse.library", 0L); - if (!IFFParseBase) { - *errstrp = "No iffparse.library"; - return bmhds; + if (!IFFParseBase) + panic("No iffparse.library"); + + iff = AllocIFF(); + if (!iff) + panic("can't start IFF processing"); + + iff->iff_Stream = Open(filename, MODE_OLDFILE); + if (iff->iff_Stream == 0) + panic("Can't open %s", filename); + + InitIFFasDOS(iff); + OpenIFF(iff, IFFF_READ); + PropChunk(iff, ID_BMAP, ID_BMHD); + PropChunk(iff, ID_BMAP, ID_CMAP); + PropChunk(iff, ID_BMAP, ID_PDAT); + StopChunk(iff, ID_BMAP, ID_PLNE); + if ((j = ParseIFF(iff, IFFPARSE_SCAN)) != 0) + panic("ParseIFF failed on %s, code %d", + filename, j); + + prop = FindProp(iff, ID_BMAP, ID_BMHD); + if (!prop) + panic("No BMHD chunk in %s", filename); + bmhd = (BitMapHeader *) prop->sp_Data; + np = bmhd->nPlanes; + + /* Load CMAP into palette arrays if present */ + prop = FindProp(iff, ID_BMAP, ID_CMAP); + if (prop) { + unsigned char *cmap = prop->sp_Data; + for (j = 0; j < (1L << np) * 3; j += 3) { + amii_initmap[j / 3] = + amiv_init_map[j / 3] = + ((cmap[j+0] >> 4) << 8) + | ((cmap[j+1] >> 4) << 4) + | (cmap[j+2] >> 4); + } } - /* - for( i = 0; filenames[i]; ++i ) - memset( iffimg[i], 0, sizeof( struct BitMap ) ); - */ - for (i = 0; filenames[i]; ++i) { - iff = AllocIFF(); - if (!iff) { - FreeImageFiles(filenames, iffimg); - *errstrp = "can't start IFF processing"; - return bmhds; - } - iff->iff_Stream = Open(filenames[i], MODE_OLDFILE); - if (iff->iff_Stream == 0) { - char *buf = malloc(100 + strlen(filenames[i])); - FreeImageFiles(filenames, iffimg); - sprintf(buf, "Can't open %s: %s", filenames[i], strerror(errno)); - *errstrp = buf; - return bmhds; - } - InitIFFasDOS(iff); - OpenIFF(iff, IFFF_READ); - PropChunk(iff, ID_BMAP, ID_BMHD); - PropChunk(iff, ID_BMAP, ID_CMAP); - PropChunk(iff, ID_BMAP, ID_CAMG); - PropChunk(iff, ID_BMAP, ID_PDAT); - StopChunk(iff, ID_BMAP, ID_PLNE); - if ((j = ParseIFF(iff, IFFPARSE_SCAN)) != 0) { - char *buf = malloc(100); - FreeImageFiles(filenames, iffimg); - sprintf(buf, "ParseIFF failed for image %d, failure code: %d", i, - j); - *errstrp = buf; - return bmhds; - } + /* Load PDAT if present */ + prop = FindProp(iff, ID_BMAP, ID_PDAT); + if (prop) + pictdata = *(struct PDAT *) prop->sp_Data; - if (prop = FindProp(iff, ID_BMAP, ID_BMHD)) { - bmhd = (BitMapHeader *) prop->sp_Data; - } else { - FreeImageFiles(filenames, iffimg); - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - *errstrp = "No BMHD CHUNK in file"; - return bmhds; - } + *bmp = MyAllocBitMap(bmhd->w, bmhd->h, + np, MEMF_CHIP | MEMF_CLEAR); + if (!*bmp) + panic("Can't allocate bitmap for %s", filename); - if (prop = FindProp(iff, ID_BMAP, ID_CMAP)) { - cmap = prop->sp_Data; - for (j = 0; j < (1L << bmhd->nPlanes) * 3; j += 3) { -#if 0 - /* Some day we will want to use the larger palette - * resolution available under v39 and later. i.e. - * 32 instead of 12 bits of color. Ususally this - * just means shifting the color left by 16-20 bits - * depending on what intensity looks best. Experience - * says that the higher values are better intensities. - * - * For now though we won't do this. The color table - * structure is incompatible with earlier versions of - * intuition. We would have to do some funny things - * to make 3*AMII_MAXCOLORS longs work like 3*AMII_MAXCOLORS - * UWORD's at run time... A union would help, but... - */ - if( IntuitionBase->LibNode.lib_Version >= 39 ) - { - /* 8 bits of color, so shift to left end. */ - amiv_init_map[ j+0 ] = cmap[j+0]<<24; - amiv_init_map[ j+1 ] = cmap[j+1]<<24; - amiv_init_map[ j+2 ] = cmap[j+2]<<24; - } - else -#endif - { -/* We can only use 4 bits of the 8 that are stored in the - * cmap, so mask them and then shift them into position - * for the UWORD value to store. - */ -#ifndef TESTING - amii_initmap[j / 3] = amiv_init_map[j / 3] = - ((cmap[j + 0] >> 4) << 8) | ((cmap[j + 1] >> 4) << 4) - | (cmap[j + 2] >> 4); -#endif - } - } - } else { - FreeImageFiles(filenames, iffimg); - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - *errstrp = "No CMAP CHUNK in file"; - return bmhds; - } + for (j = 0; j < np; j++) + ReadChunkBytes(iff, (*bmp)->Planes[j], + RASSIZE(bmhd->w, bmhd->h)); - if (prop = FindProp(iff, ID_BMAP, ID_PDAT)) { - struct PDAT *pp; - - pp = (struct PDAT *) prop->sp_Data; - pictdata = *pp; - } else { - FreeImageFiles(filenames, iffimg); - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - *errstrp = "No PDAT CHUNK in file"; - return bmhds; - } - - iffimg[i] = MyAllocBitMap(bmhd->w, bmhd->h, - pictdata.nplanes + amii_extraplanes, - MEMF_CHIP | MEMF_CLEAR); - if (iffimg[i] == NULL) { - char *buf = malloc(80); - FreeImageFiles(filenames, iffimg); - sprintf(buf, "Can't allocate bitmap for image %d\n", i); - *errstrp = buf; - return bmhds; - } - for (j = 0; j < pictdata.nplanes + amii_extraplanes; ++j) { - ReadChunkBytes(iff, iffimg[i]->Planes[j], - RASSIZE(bmhd->w, bmhd->h)); - } - bmhds = *bmhd; - CloseIFF(iff); - Close(iff->iff_Stream); - FreeIFF(iff); - } + bmhds = *bmhd; + CloseIFF(iff); + Close(iff->iff_Stream); + FreeIFF(iff); CloseLibrary(IFFParseBase); - tile = MyAllocBitMap(pictdata.xsize, pictdata.ysize, - pictdata.nplanes + amii_extraplanes, - MEMF_CHIP | MEMF_CLEAR); - if (tile == NULL) { - FreeImageFiles(filenames, iffimg); - *errstrp = "Can't allocate tile bitmap for scaling"; + return bmhds; +} + +void +FreeImageFile(struct BitMap **bmp) +{ + if (*bmp) { + MyFreeBitMap(*bmp); + *bmp = NULL; } - return (bmhds); +} + +BitMapHeader +ReadTileImageFiles(void) +{ + BitMapHeader bmhds; + + bmhds = ReadImageFile(tilefile, &tileimg); + + tile = MyAllocBitMap(pictdata.xsize, pictdata.ysize, + pictdata.nplanes + amii_extraplanes, + MEMF_CHIP | MEMF_CLEAR); + if (!tile) + panic("Can't allocate tile temp bitmap"); + + return bmhds; } struct MyBitMap { @@ -401,8 +331,7 @@ MyFreeBitMap(struct BitMap *bmp) #ifdef TESTING void -panic(s, a1, a2, a3, a4) -char *s; +panic(char *s, long a1, long a2, long a3, long a4) { printf(s, a1, a2, a3, a4); putchar('\n'); @@ -420,24 +349,10 @@ alloc(unsigned int x) #endif void -FreeTileImageFiles() +FreeTileImageFiles(void) { - FreeImageFiles(tileimages, ifftimg); -} - -void -FreeImageFiles(char **filenames, struct BitMap **img) -{ - register int i; - - for (i = 0; filenames[i]; ++i) { - if (img[i]) - MyFreeBitMap(img[i]); - } - - /* REALLY ugly hack alert! */ - if (tile && img == ifftimg) - MyFreeBitMap(tile); + FreeImageFile(&tileimg); + FreeImageFile(&tile); } #ifndef TESTING @@ -456,8 +371,7 @@ struct amiv_glyph_node amiv_g_nodes[NUMBER_GLYPH_NODES]; static char amiv_glyph_buffer[GLYPH_BUFFER_SIZE]; void -flush_glyph_buffer(vw) -struct Window *vw; +flush_glyph_buffer(struct Window *vw) { if (WINVERS_AMIV) amiv_flush_glyph_buffer(vw); @@ -469,8 +383,7 @@ struct Window *vw; * Routine to flush whatever is buffered */ void -amiv_flush_glyph_buffer(vw) -struct Window *vw; +amiv_flush_glyph_buffer(struct Window *vw) { #if !defined(DISPMAP) || defined(OPT_DISPMAP) int xsize, ysize, x, y; @@ -481,7 +394,7 @@ struct Window *vw; struct BitMap *imgbm = 0, *bm = 0; int i, k; int scaling_needed; - register struct RastPort *rp = vw->RPort; + struct RastPort *rp = vw->RPort; #endif /* If nothing is buffered, return before we do anything */ @@ -577,7 +490,7 @@ struct Window *vw; /* Go ahead and start dumping the stuff */ for (i = 0; i < glyph_node_index; ++i) { /* Do it */ - register int offx, offy, j; + int offx, offy, j; struct BitMap *nodebm = amiv_g_nodes[i].bitmap; /* Get the unclipped coordinates */ @@ -596,10 +509,10 @@ struct Window *vw; * this code is generalized to handle any size tile * image... */ - memcpy(tile->Planes[j] + ((k * pictdata.ysize) / 8), + memcpy(tile->Planes[j] + k * tile->BytesPerRow, nodebm->Planes[j] + offx + offy + (nodebm->BytesPerRow * k), - pictdata.ysize / 8); + pictdata.xsize / 8); } } @@ -648,41 +561,30 @@ struct Window *vw; * Glyph buffering routine. Called instead of WindowPuts(). */ void -amiv_lprint_glyph(window, color_index, glyph) -winid window; -int color_index, glyph; +amiv_lprint_glyph(winid window, int color_index, int glyph) { int base; struct amii_WinDesc *cw; struct Window *w; int curx; int cury; - int tbl, icon; - register int xoff, yoff; + int icon; + int xoff, yoff; - /* Get the real icon index */ - if (glyph != NO_GLYPH) - icon = GlyphToIcon(glyph); + /* Skip NO_GLYPH — nothing to draw */ + if (glyph == NO_GLYPH) + return; + + icon = GlyphToIcon(glyph); if ((cw = amii_wins[window]) == (struct amii_WinDesc *) NULL) panic("bad winid in amiv_lprint_glyph: %d", window); w = cw->win; - if (glyph != NO_GLYPH && glyph < 10000) { - /* decide on which image has the needed picture */ - if (icon <= MAXMONTILE) { - tbl = TBLMONTILE; - base = 0; - } else if (icon <= MAXOBJTILE) { - tbl = TBLOBJTILE; - base = MAXMONTILE + 1; - } else if (icon <= MAXOTHTILE) { - tbl = TBLOTHTILE; - base = MAXOBJTILE + 1; - } else - panic("Bad icon #%d, glyph #%d, only %d icons known\n", icon, - glyph, MAXOTHTILE); + if (glyph < 10000) { + if (icon >= pictdata.npics) + icon = 0; /* fallback for out-of-range */ /* Get the relative offset in the page */ @@ -748,11 +650,11 @@ int color_index, glyph; amiv_g_nodes[glyph_node_index].odstx = cw->curx; amiv_g_nodes[glyph_node_index].srcx = xoff; amiv_g_nodes[glyph_node_index].srcy = yoff; - amiv_g_nodes[glyph_node_index].bitmap = ifftimg[tbl]; + amiv_g_nodes[glyph_node_index].bitmap = tileimg; ++glyph_node_index; } else { /* Do it */ - register int j, k, x, y, apen; + int j, k, x, y, apen; struct RastPort *rp = w->RPort; x = rp->cp_x - pictdata.xsize - 3; #ifdef OPT_DISPMAP @@ -770,17 +672,17 @@ int color_index, glyph; y = rp->cp_y - pictdata.ysize + 1; if (glyph != NO_GLYPH) { - struct BitMap *bm = ifftimg[tbl]; + struct BitMap *bm = tileimg; /* 8 bits per byte */ xoff /= 8; yoff *= bm->BytesPerRow; for (j = 0; j < pictdata.nplanes; ++j) { for (k = 0; k < pictdata.ysize; ++k) { - memcpy(tile->Planes[j] + ((k * pictdata.ysize) / 8), + memcpy(tile->Planes[j] + k * tile->BytesPerRow, bm->Planes[j] + xoff + yoff + (bm->BytesPerRow * k), - pictdata.ysize / 8); + pictdata.xsize / 8); } } @@ -824,8 +726,7 @@ static int usecolor; */ void -amiv_start_glyphout(window) -winid window; +amiv_start_glyphout(winid window) { struct amii_WinDesc *cw; struct Window *w; @@ -860,8 +761,7 @@ winid window; * General cleanup routine -- flushes and restores cursor */ void -amii_end_glyphout(window) -winid window; +amii_end_glyphout(winid window) { struct amii_WinDesc *cw; struct Window *w; @@ -891,7 +791,7 @@ winid window; Move(w->RPort, xsave, ysave); } -static maze_type = COL_MAZE_BRICK; +static int maze_type = COL_MAZE_BRICK; void SetMazeType(MazeType t) @@ -987,11 +887,10 @@ int backg[AMII_MAXCOLORS] = { * Routine to simply flush whatever is buffered */ void -amii_flush_glyph_buffer(w) -struct Window *w; +amii_flush_glyph_buffer(struct Window *w) { short i, x, y; - register struct RastPort *rp = w->RPort; + struct RastPort *rp = w->RPort; /* If nothing is buffered, return before we do anything */ if (glyph_node_index == 0) @@ -1013,6 +912,10 @@ struct Window *w; + rp->TxBaseline + 1; x = amii_g_nodes[i].x * rp->TxWidth + w->BorderLeft; + /* Skip if pixel coordinates are outside window */ + if (x < 0 || y < 0 || y >= w->Height || x >= w->Width) + continue; + /* Move pens to correct location */ Move(rp, (long) x, (long) y); @@ -1029,9 +932,7 @@ struct Window *w; glyph_node_index = glyph_buffer_index = 0; } void -amiga_print_glyph(window, color_index, glyph) -winid window; -int color_index, glyph; +amiga_print_glyph(winid window, int color_index, int glyph) { if (WINVERS_AMIV) amiv_lprint_glyph(window, color_index, glyph); @@ -1043,9 +944,7 @@ int color_index, glyph; * Glyph buffering routine. Called instead of WindowPuts(). */ void -amii_lprint_glyph(window, color_index, glyph) -winid window; -int color_index, glyph; +amii_lprint_glyph(winid window, int color_index, int glyph) { int fg_color, bg_color; struct amii_WinDesc *cw; @@ -1120,8 +1019,7 @@ static int usecolor; */ void -amii_start_glyphout(window) -winid window; +amii_start_glyphout(winid window) { struct amii_WinDesc *cw; struct Window *w; @@ -1195,7 +1093,7 @@ amii_end_glyphout(window) #ifdef OPT_DISPMAP /* don't use dispmap unless x & y are 8,16,24,32,48 and equal */ void -dispmap_sanity() +dispmap_sanity(void) { if (mxsize != mysize || dispmap_sanity1(mxsize) || dispmap_sanity1(mysize)) { @@ -1203,11 +1101,10 @@ dispmap_sanity() } } int -dispmap_sanity1(x) -int x; +dispmap_sanity1(int x) { static unsigned char valid[] = { 8, 16, 24, 32, 48, 0 }; - return !!strchr(valid, x); + return !strchr((char *)valid, x); } #endif /* OPT_DISPMAP */ #endif /* TESTING */ diff --git a/sys/amiga/windefs.h b/sys/amiga/windefs.h index 9e59da82f..cb6cbd3db 100644 --- a/sys/amiga/windefs.h +++ b/sys/amiga/windefs.h @@ -112,7 +112,7 @@ CLIPPING must be defined for the AMIGA version #endif #define WINVERS_AMII (strcmp("amii", windowprocs.name) == 0) -#define WINVERS_AMIV (strcmp("amitile", windowprocs.name) == 0) +#define WINVERS_AMIV (strcmp("amiv", windowprocs.name) == 0) #define WINVERS_AMIT (strcmp("amitty", windowprocs.name) == 0) /* cw->data[x] contains 2 characters worth of special information. These @@ -196,3 +196,4 @@ struct PDAT #undef MAXCOLORS #define MAXCOLORS 256 + diff --git a/sys/amiga/winfuncs.c b/sys/amiga/winfuncs.c index 9907ce1c6..7d451a665 100644 --- a/sys/amiga/winfuncs.c +++ b/sys/amiga/winfuncs.c @@ -14,7 +14,6 @@ #endif #include "patchlevel.h" -#include "date.h" extern struct TagItem scrntags[]; #ifndef CROSS_TO_AMIGA @@ -40,6 +39,11 @@ int xclipbord = 4, yclipbord = 2; #endif int mxsize, mysize; + +/* Track the last level we centered the clipping viewport on, so that + both amii_clear_nhwindow (pre-docrt centering) and amii_cliparound + (scroll/pan during play) can detect level changes. */ +static d_level clip_saved_level = { 127, 127 }; /* XXX */ struct Rectangle amii_oldover; struct Rectangle amii_oldmsg; @@ -58,8 +62,7 @@ int amii_otherBPen; long amii_libvers = LIBRARY_FONT_VERSION; void -ami_wininit_data(dir) -int dir; +ami_wininit_data(int dir) { extern unsigned short amii_init_map[AMII_MAXCOLORS]; extern unsigned short amiv_init_map[AMII_MAXCOLORS]; @@ -150,12 +153,13 @@ struct TagItem wintags[] = { }; #endif -void amii_destroy_nhwindow(win) /* just hide */ -register winid win; +void +amii_destroy_nhwindow(winid win) /* just hide */ { int i; int type; - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (win == WIN_ERR || (cw = amii_wins[win]) == NULL) { panic(winpanicstr, win, "destroy_nhwindow"); @@ -260,26 +264,37 @@ PPC_LayerFillHook(void) struct RastPort *rp = (struct RastPort *) REG_A2; struct FillParams *fp = (struct FillParams *) REG_A1; #else +/* Assembly trampoline: Intuition calls LayerFillHook with arguments + in registers a0 (hook), a1 (fillparams), a2 (rastport). + Push them onto the stack and call the C implementation. */ +__asm( +" .globl _LayerFillHook\n" +"_LayerFillHook:\n" +" move.l a1,-(sp)\n" +" move.l a2,-(sp)\n" +" move.l a0,-(sp)\n" +" jsr _LayerFillHook_impl\n" +" lea 12(sp),sp\n" +" rts\n" +); void -LayerFillHook(void) +LayerFillHook_impl(struct Hook *hk, struct RastPort *rp, + struct FillParams *fp) { - register struct Hook *hk asm("a0"); - register struct RastPort *rp asm("a2"); - register struct FillParams *fp asm("a1"); #endif #else void #ifndef _DCC __interrupt #endif - __saveds __asm LayerFillHook(register __a0 struct Hook *hk, - register __a2 struct RastPort *rp, - register __a1 struct FillParams *fp) + __saveds __asm LayerFillHook(__a0 struct Hook *hk, + __a2 struct RastPort *rp, + __a1 struct FillParams *fp) { #endif - register long x, y, xmax, ymax; - register int apen; + long x, y, xmax, ymax; + int apen; struct RastPort rptmp; memcpy(&rptmp, rp, sizeof(struct RastPort)); @@ -321,15 +336,17 @@ void } #endif -amii_create_nhwindow(type) register int type; +winid +amii_create_nhwindow(int type) { - register struct Window *w = NULL; - register struct NewWindow *nw = NULL; - register struct amii_WinDesc *wd = NULL; + struct Window *w = NULL; + struct NewWindow *nw = NULL; + struct amii_WinDesc *wd = NULL; struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL; - register int newid; + int newid; int maph, stath, scrfontysize; + scrfontysize = HackScreen->Font->ta_YSize; /* @@ -563,11 +580,7 @@ amii_create_nhwindow(type) register int type; case NHW_OVER: case NHW_MAP: if (wd) { -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) type; fillhook.h_SubEntry = 0; wd->hook = alloc(sizeof(fillhook)); @@ -665,6 +678,10 @@ amii_create_nhwindow(type) register int type; / w->RPort->TxHeight; wd->cols = (w->Width - w->BorderLeft - w->BorderRight - 2) / w->RPort->TxWidth; + /* Map window uses y+2 offset in amii_print_glyph, so cury + values go up to ROWNO+2. Ensure rows accommodates this. */ + if (type == NHW_MAP && wd->rows < ROWNO + 3) + wd->rows = ROWNO + 3; } /* Okay, now do the individual type initialization */ @@ -736,7 +753,9 @@ amii_create_nhwindow(type) register int type; */ wd->data = (char **) alloc(3 * sizeof(char *)); wd->data[0] = (char *) alloc(wd->cols + 10); + wd->data[0][0] = '\0'; wd->data[1] = (char *) alloc(wd->cols + 10); + wd->data[1][0] = '\0'; wd->data[2] = NULL; break; @@ -771,7 +790,7 @@ amii_create_nhwindow(type) register int type; SetMenuStrip(w, MenuStrip); /* Make our requesters come to our screen */ { - register struct Process *myProcess = + struct Process *myProcess = (struct Process *) FindTask(NULL); pr_WindowPtr = (struct Window *) (myProcess->pr_WindowPtr); myProcess->pr_WindowPtr = (APTR) w; @@ -787,17 +806,7 @@ amii_create_nhwindow(type) register int type; Abort(AG_OpenDev | AO_ConsoleDev); } - ConsoleDevice = -#ifndef CROSS_TO_AMIGA - (struct Library *) -#else - (struct Device * -# ifdef __CONSTLIBBASEDECL__ - __CONSTLIBBASEDECL__ -# endif /* __CONSTLIBBASEDECL__ */ - ) -#endif - ConsoleIO.io_Device; + ConsoleDevice = (struct Device *) ConsoleIO.io_Device; KbdBuffered = 0; #ifdef HACKFONT @@ -831,12 +840,23 @@ PPC_SM_Filter(void) ULONG modeID = (ULONG) REG_A1; struct ScreenModeRequester *smr = (struct ScreenModeRequester *) REG_A2; #else +/* Assembly trampoline for SM_Filter hook callback. + SM_Filter is the asm entry point; SM_Filter_impl is the C body. */ +extern void SM_Filter(void); +__asm( +" .globl _SM_Filter\n" +"_SM_Filter:\n" +" move.l a2,-(sp)\n" +" move.l a1,-(sp)\n" +" move.l a0,-(sp)\n" +" jsr _SM_Filter_impl\n" +" lea 12(sp),sp\n" +" rts\n" +); int -SM_Filter(void) +SM_Filter_impl(struct Hook *hk, ULONG modeID, + struct ScreenModeRequester *smr) { - register struct Hook *hk asm("a0"); - register ULONG modeID asm("a1"); - register struct ScreenModeRequester *smr asm("a2"); #endif #else int @@ -844,8 +864,8 @@ int __interrupt #endif __saveds __asm SM_Filter( - register __a0 struct Hook *hk, register __a1 ULONG modeID, - register __a2 struct ScreenModeRequester *smr) + __a0 struct Hook *hk, __a1 ULONG modeID, + __a2 struct ScreenModeRequester *smr) { #endif struct DimensionInfo dims; @@ -869,14 +889,13 @@ int /* Initialize the windowing environment */ void -amii_init_nhwindows(argcp, argv) -int *argcp; -char **argv; +amii_init_nhwindows(int *argcp, char **argv) { int i; struct Screen *wbscr; int forcenobig = 0; + if (HackScreen) panic("init_nhwindows() called twice", 0); @@ -1192,9 +1211,16 @@ char **argv; } #endif - if (WINVERS_AMIV) + if (WINVERS_AMIV) { + extern char *tilefile; + if (amii_numcolors >= 32) { + tilefile = "NetHack:tiles/tiles32.iff"; + amii_numcolors = 32; + } else { + tilefile = "NetHack:tiles/tiles16.iff"; + } amii_bmhd = ReadTileImageFiles(); - else + } else memcpy(amii_initmap, amii_init_map, sizeof(amii_initmap)); memcpy(sysflags.amii_curmap, amii_initmap, sizeof(sysflags.amii_curmap)); @@ -1361,11 +1387,11 @@ amii_setdrawpens(struct Window *w, int type) /* Clear the indicated window */ void -amii_clear_nhwindow(win) -register winid win; +amii_clear_nhwindow(winid win) { - register struct amii_WinDesc *cw; - register struct Window *w; + struct amii_WinDesc *cw; + struct Window *w; + if (reclip == 2) return; @@ -1394,6 +1420,40 @@ register winid win; amii_setfillpens(w, cw->type); SetDrMd(w->RPort, JAM2); +#ifdef CLIPPING + /* When clearing the map for a full redraw (docrt/cls), center the + clipping viewport on the player BEFORE the map is redrawn. + Without this, the first docrt() after a level change or new game + draws with stale clip coordinates (typically 0,0), leaving the + player off-screen until their first move triggers amii_cliparound. */ + if (cw->type == NHW_MAP && clipping && u.ux + && !on_level(&u.uz, &clip_saved_level)) { + int COx, LIx; + struct RastPort *rp = w->RPort; + + if (Is_rogue_level(&u.uz)) { + COx = (w->Width - w->BorderLeft - w->BorderRight) / rp->TxWidth; + LIx = (w->Height - w->BorderTop - w->BorderBottom) / rp->TxHeight; + } else { + COx = CO; + LIx = LI; + } + clipx = max(0, (int) u.ux - COx / 2); + clipxmax = clipx + COx; + if (clipxmax > COLNO) { + clipxmax = COLNO; + clipx = clipxmax - COx; + } + clipy = max(0, (int) u.uy - LIx / 2); + clipymax = clipy + LIx; + if (clipymax > ROWNO) { + clipymax = ROWNO; + clipy = clipymax - LIx; + } + clip_saved_level = u.uz; + } +#endif + if (cw->type == NHW_MENU || cw->type == NHW_TEXT) { RectFill(w->RPort, w->BorderLeft, w->BorderTop, w->Width - w->BorderRight - 1, @@ -1418,11 +1478,10 @@ register winid win; /* Dismiss the window from the screen */ void -dismiss_nhwindow(win) -register winid win; +dismiss_nhwindow(winid win) { - register struct Window *w; - register struct amii_WinDesc *cw; + struct Window *w; + struct amii_WinDesc *cw; if (win == WIN_ERR || (cw = amii_wins[win]) == NULL) { panic(winpanicstr, win, "dismiss_nhwindow"); @@ -1458,9 +1517,9 @@ register winid win; } void -amii_exit_nhwindows(str) -const char *str; +amii_exit_nhwindows(const char *str) { + /* Seems strange to have to do this... but we need the BASE window * left behind... */ @@ -1475,15 +1534,14 @@ const char *str; } void -amii_display_nhwindow(win, blocking) -winid win; -boolean blocking; +amii_display_nhwindow(winid win, boolean blocking) { menu_item *mip; int cnt; static int lastwin = -1; struct amii_WinDesc *cw; + if (!Initialized) return; lastwin = win; @@ -1513,13 +1571,12 @@ boolean blocking; } void -amii_curs(window, x, y) -winid window; -register int x, y; +amii_curs(winid window, int x, int y) { - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; + if (window == WIN_ERR || (cw = amii_wins[window]) == NULL) panic(winpanicstr, window, "curs"); @@ -1540,8 +1597,14 @@ register int x, y; cw->curx = x; cw->cury = y; + /* Silently skip rendering for out-of-bounds coordinates */ + if (cw->rows > 0 && y >= cw->rows) + return; + if (cw->cols > 0 && x >= cw->cols) + return; + #ifdef DEBUG - if (x < 0 || y < 0 || y >= cw->rows || x >= cw->cols) { + if (0 && (x < 0 || y < 0 || y >= cw->rows || x >= cw->cols)) { char *s = "[unknown type]"; switch (cw->type) { case NHW_MESSAGE: @@ -1663,12 +1726,10 @@ printf("pos: (%d,%d)->(%d,%d)\n",x,y,qqx,qqy); } void -amii_set_text_font(name, size) -char *name; -int size; +amii_set_text_font(char *name, int size) { - register int i; - register struct amii_WinDesc *cw; + int i; + struct amii_WinDesc *cw; int osize = TextsFont13.ta_YSize; static char nname[100]; @@ -1709,11 +1770,10 @@ int size; } void -kill_nhwindows(all) -register int all; +kill_nhwindows(int all) { - register int i; - register struct amii_WinDesc *cw; + int i; + struct amii_WinDesc *cw; /* Foreach open window in all of amii_wins[], CloseShWindow, free memory */ @@ -1726,12 +1786,10 @@ register int all; } void -amii_cl_end(cw, curs_pos) -register struct amii_WinDesc *cw; -register int curs_pos; +amii_cl_end(struct amii_WinDesc *cw, int curs_pos) { - register struct Window *w = cw->win; - register int oy, ox; + struct Window *w = cw->win; + int oy, ox; if (!w) panic("NULL window pointer in amii_cl_end()"); @@ -1745,12 +1803,11 @@ register int curs_pos; } void -cursor_off(window) -winid window; +cursor_off(winid window) { - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; int curx, cury; int x, y; long dmode; @@ -1805,13 +1862,12 @@ winid window; } void -cursor_on(window) -winid window; +cursor_on(winid window) { int x, y; - register struct amii_WinDesc *cw; - register struct Window *w; - register struct RastPort *rp; + struct amii_WinDesc *cw; + struct Window *w; + struct RastPort *rp; unsigned char ch; long dmode; short apen, bpen; @@ -1858,10 +1914,13 @@ winid window; if (WINVERS_AMIV && cw->type == NHW_MAP) { cursor_common(rp, x, y); } else { - Move(rp, x, y); - ch = CURSOR_CHAR; - Text(rp, &ch, 1); - Move(rp, x, y); + if (w && x >= 0 && y >= 0 + && x < w->Width && y < w->Height) { + Move(rp, x, y); + ch = CURSOR_CHAR; + Text(rp, &ch, 1); + Move(rp, x, y); + } } SetDrMd(rp, dmode); @@ -1870,9 +1929,7 @@ winid window; } static void -cursor_common(rp, x, y) -struct RastPort *rp; -int x, y; +cursor_common(struct RastPort *rp, int x, int y) { int x1, x2, y1, y2; @@ -1895,29 +1952,27 @@ int x, y; } void -amii_suspend_nhwindows(str) -const char *str; +amii_suspend_nhwindows(const char *str) { if (HackScreen) ScreenToBack(HackScreen); } void -amii_resume_nhwindows() +amii_resume_nhwindows(void) { if (HackScreen) ScreenToFront(HackScreen); } void -amii_bell() +amii_bell(void) { DisplayBeep(NULL); } void -removetopl(cnt) -int cnt; +removetopl(int cnt) { struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; /* NB - this is sufficient for @@ -1935,7 +1990,7 @@ int cnt; #ifdef PORT_HELP void -port_help() +port_help(void) { display_file(PORT_HELP, 1); } @@ -1951,17 +2006,20 @@ port_help() */ void -amii_print_glyph(win, x, y, glyph, bkglyph) -winid win; -coordxy x, y; -int glyph, bkglyph; +amii_print_glyph(winid win, coordxy x, coordxy y, + const glyph_info *glyphinfo, + const glyph_info *bkglyphinfo UNUSED) { struct amii_WinDesc *cw; uchar ch; + int glyph; int color, och; extern const int zapcolors[]; unsigned special; + + glyph = glyphinfo->glyph; + /* In order for the overview window to work, we can not clip here */ if (!WINVERS_AMIV) { #ifdef CLIPPING @@ -1993,14 +2051,8 @@ if(u.uz.dlevel != x){ } else /* AMII, or Rogue level in either version */ { /* map glyph to character and color */ -#if 0 - (void) mapglyph(glyph, &och, &color, &special, x, y, 0); - ch = (uchar) och; -#else - glyph_info gi; - map_glyphinfo(0, 0, glyph, 0, &gi); - ch = gi.ttychar; -#endif + ch = glyphinfo->ttychar; + color = glyphinfo->gm.sym.color; if (WINVERS_AMIV) { /* implies Rogue level here */ amii_curs(win, x, y); amiga_print_glyph(win, NO_COLOR, ch + 10000); @@ -2021,11 +2073,11 @@ if(u.uz.dlevel != x){ /* Make sure the user sees a text string when no windowing is available */ void -amii_raw_print(s) -register const char *s; +amii_raw_print(const char *s) { int argc = 0; + if (!s) return; if (amiIDisplay) @@ -2057,11 +2109,11 @@ register const char *s; */ void -amii_raw_print_bold(s) -register const char *s; +amii_raw_print_bold(const char *s) { int argc = 0; + if (!s) return; @@ -2092,9 +2144,10 @@ register const char *s; /* Rebuild/update the inventory if the window is up. */ void -amii_update_inventory() +amii_update_inventory(int arg UNUSED) { - register struct amii_WinDesc *cw; + struct amii_WinDesc *cw; + if (WIN_INVEN != WIN_ERR && (cw = amii_wins[WIN_INVEN]) && cw->type == NHW_MENU && cw->win) { @@ -2102,10 +2155,17 @@ amii_update_inventory() } } +/* Stub for ctrl_nhwindow - no special handling needed for Amiga */ +win_request_info * +amii_ctrl_nhwindow(winid window UNUSED, int request UNUSED, win_request_info *wri UNUSED) +{ + return (win_request_info *) 0; +} + /* Humm, doesn't really do anything useful */ void -amii_mark_synch() +amii_mark_synch(void) { if (!amiIDisplay) fflush(stderr); @@ -2116,7 +2176,7 @@ amii_mark_synch() * ask for a key to be pressed. */ void -amii_wait_synch() +amii_wait_synch(void) { if (!amiIDisplay || amiIDisplay->rawprint) { if (amiIDisplay) @@ -2130,7 +2190,7 @@ amii_wait_synch() } void -amii_setclipped() +amii_setclipped(void) { #ifdef CLIPPING clipping = TRUE; @@ -2141,12 +2201,35 @@ amii_setclipped() #endif } +/* Redraw a rectangular region of the map via newsym(). Used after + ScrollRaster() shifts existing pixels — only the exposed strip needs + redrawing. Does NOT flush; the caller flushes after all regions. */ +static void +redraw_map_region(int x1, int y1, int x2, int y2) +{ + int x, y; + + if (!u.ux) + return; + if (x1 < 1) x1 = 1; + if (y1 < 0) y1 = 0; + if (x2 >= COLNO) x2 = COLNO - 1; + if (y2 >= ROWNO) y2 = ROWNO - 1; + for (y = y1; y <= y2; y++) + for (x = x1; x <= x2; x++) { + /* Invalidate the glyph buffer so newsym() redraws even if + * the glyph hasn't changed — the pixels were shifted by + * ScrollRaster and no longer match the buffer. */ + gg.gbuf[y][x].glyphinfo.glyph = NO_GLYPH; + newsym(x, y); + } +} + /* XXX still to do: suppress scrolling if we violate the boundary but the * edge of the map is already displayed */ void -amii_cliparound(x, y) -register int x, y; +amii_cliparound(int x, int y) { #ifdef CLIPPING int oldx = clipx, oldy = clipy; @@ -2155,8 +2238,9 @@ register int x, y; #define SCROLLCNT 1 /* Get there in 3 moves... */ int scrollcnt = SCROLLCNT; /* ...or 1 if we changed level */ - if (!clipping) /* And 1 in anycase, cleaner, simpler, quicker */ + if (!clipping) { /* And 1 in anycase, cleaner, simpler, quicker */ return; + } if (Is_rogue_level(&u.uz)) { struct Window *w = amii_wins[WIN_MAP]->win; @@ -2173,16 +2257,22 @@ register int x, y; * reasonablely large window extra motion is avoided; for * the rogue level hopefully this means no motion at all. */ - { - static d_level saved_level = { 127, 127 }; /* XXX */ - - if (!on_level(&u.uz, &saved_level)) { - scrollcnt = 1; /* jump with blanking */ - clipx = clipy = 0; - clipxmax = COx; - clipymax = LIx; - saved_level = u.uz; /* save as new current level */ + if (!on_level(&u.uz, &clip_saved_level)) { + scrollcnt = 1; /* jump with blanking */ + /* Center viewport on the player for the new level. */ + clipx = max(0, x - COx / 2); + clipxmax = clipx + COx; + if (clipxmax > COLNO) { + clipxmax = COLNO; + clipx = clipxmax - COx; } + clipy = max(0, y - LIx / 2); + clipymax = clipy + LIx; + if (clipymax > ROWNO) { + clipymax = ROWNO; + clipy = clipymax - LIx; + } + clip_saved_level = u.uz; /* save as new current level */ } if (x <= clipx + xclipbord) { @@ -2204,13 +2294,12 @@ register int x, y; reclip = 1; if (clipx != oldx || clipy != oldy || clipxmax != oldxmax || clipymax != oldymax) { -#ifndef NOSCROLLRASTER struct Window *w = amii_wins[WIN_MAP]->win; struct RastPort *rp = w->RPort; - int xdelta, ydelta, xmod, ymod, i; - int incx, incy, mincx, mincy; - int savex, savey, savexmax, saveymax; - int scrx, scry; + int dx = clipx - oldx; + int dy = clipy - oldy; + int scrx, scry; /* tile pixel dimensions */ + int halfW, halfH; /* half viewport in tiles */ if (Is_rogue_level(&u.uz)) { scrx = rp->TxWidth; @@ -2220,129 +2309,63 @@ register int x, y; scry = mysize; } - /* Ask that the glyph routines not draw the overview window */ - reclip = 2; - cursor_off(WIN_MAP); + halfW = COx / 2; + halfH = LIx / 2; - /* Compute how far we are moving in terms of tiles */ - mincx = clipx - oldx; - mincy = clipy - oldy; + /* Erase the map cursor before shifting pixels, otherwise the + old cursor position leaves a COMPLEMENT artifact on screen. */ + if (WIN_MAP != WIN_ERR) + cursor_off(WIN_MAP); - /* How many tiles to get there in SCROLLCNT moves */ - incx = (clipx - oldx) / scrollcnt; - incy = (clipy - oldy) / scrollcnt; - - /* If less than SCROLLCNT tiles, then move by 1 tile if moving at all - */ - if (incx == 0) - incx = (mincx != 0); - if (incy == 0) - incy = (mincy != 0); - - /* Get count of pixels to move each iteration and final pixel count */ - xdelta = ((clipx - oldx) * scrx) / scrollcnt; - xmod = ((clipx - oldx) * scrx) % scrollcnt; - ydelta = ((clipy - oldy) * scry) / scrollcnt; - ymod = ((clipy - oldy) * scry) % scrollcnt; - - /* Preserve the final move location */ - savex = clipx; - savey = clipy; - saveymax = clipymax; - savexmax = clipxmax; - -/* - * Set clipping rectangle to be just the region that will be exposed so - * that drawing will be faster - */ -#if 0 /* Doesn't seem to work quite the way it should */ - /* In some cases hero is 'centered' offscreen */ - if( xdelta < 0 ) - { - clipx = oldx; - clipxmax = clipx + incx; - } - else if( xdelta > 0 ) - { - clipxmax = oldxmax; - clipx = clipxmax - incx; - } - else - { - clipx = oldx; - clipxmax = oldxmax; - } - - if( ydelta < 0 ) - { - clipy = oldy; - clipymax = clipy + incy; - } - else if( ydelta > 0 ) - { - clipymax = oldymax; - clipy = clipymax - incy; - } - else - { - clipy = oldy; - clipymax = oldymax; - } -#endif - /* Now, in scrollcnt moves, move the picture toward the final view */ - for (i = 0; i < scrollcnt; ++i) { -#ifdef DISPMAP - if (i == scrollcnt - 1 && (xmod != 0 || ymod != 0) - && (xdelta != 0 || ydelta != 0)) { - incx += (clipx - oldx) % scrollcnt; - incy += (clipy - oldy) % scrollcnt; - xdelta += xmod; - ydelta += ymod; + /* Large jumps (teleport, level change): just redraw everything. */ + if (abs(dx) > halfW || abs(dy) > halfH + || scrollcnt != SCROLLCNT) { + { + int savedAPen = rp->FgPen; + int savedDrMd = rp->DrawMode; + SetAPen(rp, amii_otherBPen); + SetDrMd(rp, JAM1); + RectFill(rp, w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight - 1, + w->Height - w->BorderBottom - 1); + SetAPen(rp, savedAPen); + SetDrMd(rp, savedDrMd); } -#endif - /* Scroll the raster if we are scrolling */ - if (xdelta != 0 || ydelta != 0) { - ScrollRaster(rp, xdelta, ydelta, w->BorderLeft, w->BorderTop, - w->Width - w->BorderRight - 1, - w->Height - w->BorderBottom - 1); + redraw_map(FALSE); + } else { + /* Flush pending glyphs — they reference old clip coords */ + flush_glyph_buffer(w); - if (mincx == 0) - incx = 0; - else - mincx -= incx; + /* Hardware-blit the viewport by the scroll delta */ + ScrollRaster(rp, dx * scrx, dy * scry, + w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight - 1, + w->Height - w->BorderBottom - 1); - clipx += incx; - clipxmax += incx; + /* Redraw only the exposed strip(s) */ + if (dx > 0) + redraw_map_region(clipxmax - dx, clipy, + clipxmax, clipymax - 1); + else if (dx < 0) + redraw_map_region(clipx, clipy, + clipx - dx, clipymax - 1); - if (mincy == 0) - incy = 0; - else - mincy -= incy; + if (dy > 0) + redraw_map_region(clipx, clipymax - dy, + clipxmax, clipymax - 1); + else if (dy < 0) + redraw_map_region(clipx, clipy, + clipxmax, clipy - dy - 1); - clipy += incy; - clipymax += incy; - - /* Draw the exposed portion */ - redraw_map(); - flush_glyph_buffer(amii_wins[WIN_MAP]->win); - } + flush_glyph_buffer(w); } - - clipx = savex; - clipy = savey; - clipymax = saveymax; - clipxmax = savexmax; -#endif - redraw_map(); - flush_glyph_buffer(amii_wins[WIN_MAP]->win); } reclip = 0; #endif } void -flushIDCMP(port) -struct MsgPort *port; +flushIDCMP(struct MsgPort *port) { struct Message *msg; while (msg = GetMsg(port)) diff --git a/sys/amiga/winkey.c b/sys/amiga/winkey.c index 9534c0c6d..f2686bfde 100644 --- a/sys/amiga/winkey.c +++ b/sys/amiga/winkey.c @@ -12,12 +12,14 @@ #include "winproto.h" #endif -amii_nh_poskey(x, y, mod) int *x, *y, *mod; +int +amii_nh_poskey(coordxy *x, coordxy *y, int *mod) { struct amii_WinDesc *cw; WETYPE type; struct RastPort *rp; struct Window *w; + /* No entry log for nh_poskey -- too noisy (called constantly) */ if (cw = amii_wins[WIN_MESSAGE]) { cw->wflags &= ~FLMAP_SKIP; @@ -59,10 +61,11 @@ amii_nh_poskey(x, y, mod) int *x, *y, *mod; } int -amii_nhgetch() +amii_nhgetch(void) { int ch; struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; + /* No entry log for nhgetch -- too noisy (called constantly) */ if (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP]) { cursor_on(WIN_MAP); @@ -75,15 +78,15 @@ amii_nhgetch() } void -amii_get_nh_event() +amii_get_nh_event(void) { /* nothing now - later I have no idea. Is this just a Mac hook? */ } void -amii_getret() +amii_getret(void) { - register int c; + int c; raw_print(""); raw_print("Press Return..."); diff --git a/sys/amiga/winproto.h b/sys/amiga/winproto.h index efa1e9b58..d855e50fe 100644 --- a/sys/amiga/winproto.h +++ b/sys/amiga/winproto.h @@ -8,10 +8,9 @@ void EditClipping(void); void DrawCol(struct Window *w, int idx, UWORD *colors); void DispCol(struct Window *w, int idx, UWORD *colors); void amii_change_color(int, long, int); -char *amii_get_color_string(); +char *amii_get_color_string(void); void amii_getlin(const char *prompt, char *bufp); void getlind(const char *prompt, char *bufp, const char *dflt); -char *amii_get_color_string(void); int filecopy(char *from, char *to); char *basename(char *str); char *dirname(char *str); @@ -33,15 +32,15 @@ void amii_scrollmsg(register struct Window *w, register struct amii_WinDesc *cw); /* winkey.c */ -int amii_nh_poskey(int *x, int *y, int *mod); +int amii_nh_poskey(coordxy *x, coordxy *y, int *mod); int amii_nhgetch(void); void amii_get_nh_event(void); void amii_getret(void); /* winmenu.c */ void amii_start_menu(winid window, unsigned long); -void amii_add_menu(winid, int, const anything *, CHAR_P, CHAR_P, int, - const char *, unsigned int); +void amii_add_menu(winid, const glyph_info *, const anything *, CHAR_P, CHAR_P, + int, int, const char *, unsigned int); void amii_end_menu(winid, const char *); int amii_select_menu(winid, int, menu_item **); int DoMenuScroll(int win, int blocking, int how, menu_item **); @@ -55,7 +54,6 @@ struct Window *OpenShWindow(struct NewWindow *nw); void CloseShWindow(struct Window *win); int ConvertKey(struct IntuiMessage *message); int kbhit(void); -int kbhit(void); int amikbhit(void); int WindowGetchar(void); WETYPE WindowGetevent(void); @@ -101,19 +99,19 @@ void amii_resume_nhwindows(void); void amii_bell(void); void removetopl(int cnt); void port_help(void); -void amii_print_glyph(winid win, coordxy x, coordxy y, int glyph, int bkglyph); +void amii_print_glyph(winid win, coordxy x, coordxy y, const glyph_info *glyphinfo, const glyph_info *bkglyphinfo); void amii_raw_print(const char *s); void amii_raw_print_bold(const char *s); -void amii_update_inventory(void); +void amii_update_inventory(int); void amii_mark_synch(void); void amii_wait_synch(void); void amii_setclipped(void); void amii_cliparound(int x, int y); void amii_set_text_font(char *font, int size); -BitMapHeader ReadImageFiles(char **, struct BitMap **, char **); +BitMapHeader ReadImageFile(const char *, struct BitMap **); +void FreeImageFile(struct BitMap **); BitMapHeader ReadTileImageFiles(void); -void FreeImageFiles(char **, struct BitMap **); -void FreeTileImageFiles(); +void FreeTileImageFiles(void); /* winami.c */ #ifdef SHAREDLIB @@ -124,12 +122,10 @@ void amii_askname(void); void amii_player_selection(void); void RandomWindow(char *name); int amii_get_ext_cmd(void); -char amii_yn_function(const char *prompt, const char *resp, char def); char amii_yn_function(const char *query, const char *resp, char def); void amii_display_file(const char *fn, boolean complain); void SetBorder(struct Gadget *gd); -void *malloc(register unsigned size); -void free(void *q); +/* malloc/free provided by stdlib.h */ #ifdef SHAREDLIB /* amilib.c */ @@ -141,6 +137,8 @@ void setup_librefs(WinamiBASE *base); void Abort(long rc); #endif +win_request_info *amii_ctrl_nhwindow(winid, int, win_request_info *); + /* amirip.c */ void amii_outrip(winid tmpwin, int how, time_t when); @@ -151,4 +149,3 @@ int GlyphToIcon(int glyph); void dispmap_sanity(void); int dispmap_sanity1(int); #endif -void FreeTileImageFiles(void); diff --git a/sys/amiga/winreq.c b/sys/amiga/winreq.c index af4c303de..910adeb86 100644 --- a/sys/amiga/winreq.c +++ b/sys/amiga/winreq.c @@ -67,16 +67,16 @@ struct NewWindow StrWindow = { void ClearCol(struct Window *w); void -EditColor() +EditColor(void) { - extern char configfile[]; + const char *configfile = get_configfile(); int i, done = 0, okay = 0; long code, qual, class; - register struct Gadget *gd, *dgad; - register struct Window *nw; - register struct IntuiMessage *imsg; - register struct PropInfo *pip; - register struct Screen *scrn; + struct Gadget *gd, *dgad; + struct Window *nw; + struct IntuiMessage *imsg; + struct PropInfo *pip; + struct Screen *scrn; long aidx; int msx, msy; int curcol = 0, drag = 0; @@ -128,11 +128,7 @@ EditColor() #ifdef INTUI_NEW_LOOK Col_NewWindowStructure1.Extension = wintags; Col_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) -2; fillhook.h_SubEntry = 0; #endif @@ -248,7 +244,7 @@ EditColor() for (i = 0; i < amii_numcolors; ++i) { fprintf(nfp, "%03x", colors[i]); if ((i + 1) < amii_numcolors) - putc(',', nfp); + putc('/', nfp); } putc('\n', nfp); } @@ -356,11 +352,11 @@ EditClipping(void) char buf[40]; int done = 0, okay = 0; long code, qual, class; - register struct Gadget *gd, *dgad; - register struct Window *nw; - register struct IntuiMessage *imsg; - register struct PropInfo *pip; - register struct Screen *scrn; + struct Gadget *gd, *dgad; + struct Window *nw; + struct IntuiMessage *imsg; + struct PropInfo *pip; + struct Screen *scrn; long aidx; int lmxsize = mxsize, lmysize = mysize; int lxclipbord = xclipbord, lyclipbord = yclipbord; @@ -388,11 +384,7 @@ EditClipping(void) #ifdef INTUI_NEW_LOOK ClipNewWindowStructure1.Extension = wintags; ClipNewWindowStructure1.Flags |= WFLG_NW_EXTENDED; -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) -2; fillhook.h_SubEntry = 0; #endif @@ -546,8 +538,7 @@ EditClipping(void) } char * -dirname(str) -char *str; +dirname(char *str) { char *t, c; static char dir[300]; @@ -555,9 +546,9 @@ char *str; t = strrchr(str, '/'); if (!t) t = strrchr(str, ':'); - if (!t) - t = str; - else { + if (!t) { + dir[0] = '\0'; + } else { c = *t; *t = 0; strcpy(dir, str); @@ -567,8 +558,7 @@ char *str; } char * -basename(str) -char *str; +basename(char *str) { char *t; @@ -582,7 +572,8 @@ char *str; return (t); } -filecopy(from, to) char *from, *to; +int +filecopy(char *from, char *to) { char *buf; int i = 0; @@ -606,7 +597,7 @@ filecopy(from, to) char *from, *to; } /* The colornames, and the default values for the pens */ -static struct COLDEF { +struct COLDEF { char *name, *defval; }; struct COLDEF amii_colnames[AMII_MAXCOLORS] = { @@ -657,10 +648,7 @@ ClearCol(struct Window *w) } void -DrawCol(w, idx, colors) -struct Window *w; -int idx; -UWORD *colors; +DrawCol(struct Window *w, int idx, UWORD *colors) { int bxorx, bxory, bxxlen, bxylen; int i, incx, incy, r, g, b; @@ -742,10 +730,7 @@ UWORD *colors; } void -DispCol(w, idx, colors) -struct Window *w; -int idx; -UWORD *colors; +DispCol(struct Window *w, int idx, UWORD *colors) { char buf[50]; char *colname, *defval; @@ -824,26 +809,21 @@ amii_setpens(int count) /* Generate a requester for a string value. */ void -amii_getlin(prompt, bufp) -const char *prompt; -char *bufp; +amii_getlin(const char *prompt, char *bufp) { getlind(prompt, bufp, 0); } /* and with default */ void -getlind(prompt, bufp, dflt) -const char *prompt; -char *bufp; -const char *dflt; +getlind(const char *prompt, char *bufp, const char *dflt) { #ifndef TOPL_GETLINE - register struct Window *cwin; - register struct IntuiMessage *imsg; - register long class, code, qual; - register int aredone = 0; - register struct Gadget *gd; + struct Window *cwin; + struct IntuiMessage *imsg; + long class, code, qual; + int aredone = 0; + struct Gadget *gd; static int once; *StrString = 0; @@ -872,11 +852,7 @@ const char *dflt; #ifdef INTUI_NEW_LOOK StrWindow.Extension = wintags; StrWindow.Flags |= WFLG_NW_EXTENDED; -#ifdef __GNUC__ fillhook.h_Entry = (void *) &LayerFillHook; -#else - fillhook.h_Entry = (ULONG (*) ()) LayerFillHook; -#endif fillhook.h_Data = (void *) -2; fillhook.h_SubEntry = 0; #endif @@ -1006,9 +982,7 @@ const char *dflt; } void -amii_change_color(pen, val, rev) -int pen, rev; -long val; +amii_change_color(int pen, long val, int rev) { if (rev) sysflags.amii_curmap[pen] = ~val; @@ -1020,12 +994,13 @@ long val; } char * -amii_get_color_string() +amii_get_color_string(void) { int i; char s[10]; static char buf[BUFSZ]; + *buf = 0; for (i = 0; i < min(32, amii_numcolors); ++i) { sprintf(s, "%s%03lx", i ? "/" : "", (long) sysflags.amii_curmap[i]); diff --git a/sys/amiga/winstr.c b/sys/amiga/winstr.c index ea7d65343..a3801fff1 100644 --- a/sys/amiga/winstr.c +++ b/sys/amiga/winstr.c @@ -14,10 +14,7 @@ /* Put a string into the indicated window using the indicated attribute */ void -amii_putstr(window, attr, str) -winid window; -int attr; -const char *str; +amii_putstr(winid window, int attr, const char *str) { int fudge; int len; @@ -27,6 +24,7 @@ const char *str; int i, j, n0, bottom, totalvis, wheight; static int wrapping = 0; + /* Always try to avoid a panic when there is no window */ if (window == WIN_ERR) { window = WIN_BASE; @@ -101,13 +99,13 @@ const char *str; memcpy(cw->data, &cw->data[1], (iflags.msg_history - 1) * sizeof(char *)); cw->data[iflags.msg_history - 1] = - (char *) alloc(strlen(gt.toplines) + 5); + (char *) alloc(strlen(gt.toplines) + SOFF + 4); strcpy(cw->data[i = iflags.msg_history - 1] + SOFF + (scrollmsg != 0), gt.toplines); } else { /* Otherwise, allocate a new one and copy the line in */ - cw->data[cw->maxrow] = (char *) alloc(strlen(gt.toplines) + 5); + cw->data[cw->maxrow] = (char *) alloc(strlen(gt.toplines) + SOFF + 4); strcpy(cw->data[i = cw->maxrow++] + SOFF + (scrollmsg != 0), gt.toplines); } @@ -196,7 +194,10 @@ const char *str; /* Display when beam at top to avoid flicker... */ WaitTOF(); - Text(w->RPort, (char *) str, strlen((char *) str)); + { int slen = strlen((char *) str); + if (slen > cw->cols) slen = cw->cols; + Text(w->RPort, (char *) str, slen); + } if (cw->cols > strlen(str)) TextSpaces(w->RPort, cw->cols - strlen(str)); @@ -286,9 +287,7 @@ const char *str; } void -amii_scrollmsg(w, cw) -register struct Window *w; -register struct amii_WinDesc *cw; +amii_scrollmsg(struct Window *w, struct amii_WinDesc *cw) { int bottom, wheight; @@ -311,8 +310,7 @@ register struct amii_WinDesc *cw; } int -amii_msgborder(w) -struct Window *w; +amii_msgborder(struct Window *w) { register int bottom; @@ -325,8 +323,7 @@ struct Window *w; } void -outmore(cw) -register struct amii_WinDesc *cw; +outmore(struct amii_WinDesc *cw) { struct Window *w = cw->win; @@ -359,11 +356,7 @@ register struct amii_WinDesc *cw; } void -outsubstr(cw, str, len, fudge) -register struct amii_WinDesc *cw; -char *str; -int len; -int fudge; +outsubstr(struct amii_WinDesc *cw, char *str, int len, int fudge) { struct Window *w = cw->win; @@ -387,10 +380,7 @@ int fudge; /* Put a graphics character onto the screen */ void -amii_putsym(st, i, y, c) -winid st; -int i, y; -CHAR_P c; +amii_putsym(winid st, int i, int y, CHAR_P c) { amii_curs(st, i, y); Text(amii_wins[st]->win->RPort, &c, 1); @@ -399,8 +389,7 @@ CHAR_P c; /* Add to the last line in the message window */ void -amii_addtopl(s) -const char *s; +amii_addtopl(const char *s) { register struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; @@ -413,9 +402,7 @@ const char *s; } void -TextSpaces(rp, nr) -struct RastPort *rp; -int nr; +TextSpaces(struct RastPort *rp, int nr) { if (nr < 1) return; @@ -429,7 +416,7 @@ int nr; } void -amii_remember_topl() +amii_remember_topl(void) { /* ignore for now. I think this will be done automatically by * the code writing to the message window, but I could be wrong. @@ -437,12 +424,13 @@ amii_remember_topl() } int -amii_doprev_message() +amii_doprev_message(void) { struct amii_WinDesc *cw; struct Window *w; char *str; + if (WIN_MESSAGE == WIN_ERR || (cw = amii_wins[WIN_MESSAGE]) == NULL || (w = cw->win) == NULL) { panic(winpanicstr, WIN_MESSAGE, "doprev_message"); diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index 8850e2d82..fdfc599c6 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -128,6 +128,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ choose_windows(DEFAULT_WINDOW_SYS); + #if !defined(AMIGA) && !defined(GNUDOS) /* Save current directory and make sure it gets restored when * the game is exited. @@ -147,6 +148,10 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/ if (dir == (char *) 0) dir = exepath(argv[0]); #endif +#if defined(AMIGA) && defined(HACKDIR) + if (dir == (char *) 0) + dir = HACKDIR; +#endif #ifdef _MSC_VER if (IsDebuggerPresent()) { static char exepath[_MAX_PATH]; diff --git a/sys/unix/hints/include/cross-post.370 b/sys/unix/hints/include/cross-post.370 index 01a998572..9d7b3a313 100644 --- a/sys/unix/hints/include/cross-post.370 +++ b/sys/unix/hints/include/cross-post.370 @@ -229,6 +229,76 @@ mipspkg: dodata $(GAMEBIN) $(TARGETPFX)recover @echo MIPS package zip file $(TARGETPFX)nh370mips.zip endif # CROSS_TO_MIPS + +ifdef CROSS_TO_AMIGA +$(TARGETPFX)amidos.o : ../sys/amiga/amidos.c $(HACK_H) +$(TARGETPFX)amigst.o : ../sys/amiga/amigst.c $(HACK_H) +$(TARGETPFX)amirip.o : ../sys/amiga/amirip.c $(HACK_H) +$(TARGETPFX)amistack.o : ../sys/amiga/amistack.c $(HACK_H) +$(TARGETPFX)amitty.o : ../sys/amiga/amitty.c $(HACK_H) +$(TARGETPFX)amiwind.o : ../sys/amiga/amiwind.c \ + ../sys/amiga/amimenu.c $(HACK_H) +$(TARGETPFX)winami.o : ../sys/amiga/winami.c $(HACK_H) +$(TARGETPFX)winchar.o : ../sys/amiga/winchar.c tile.c $(HACK_H) +$(TARGETPFX)winfuncs.o : ../sys/amiga/winfuncs.c $(HACK_H) +$(TARGETPFX)winkey.o : ../sys/amiga/winkey.c $(HACK_H) +$(TARGETPFX)winamenu.o : ../sys/amiga/winamenu.c $(HACK_H) +$(TARGETPFX)winreq.o : ../sys/amiga/winreq.c \ + ../sys/amiga/colorwin.c \ + ../sys/amiga/clipwin.c $(HACK_H) +$(TARGETPFX)winstr.o : ../sys/amiga/winstr.c $(HACK_H) +$(GAMEBIN) : $(HOBJ) $(LUACROSSLIB) + $(TARGET_LINK) $(TARGET_LFLAGS) -o $(GAMEBIN) \ + $(HOBJ) $(WINLIB) $(TARGET_LIBS) +# +# Host-side IFF tile conversion tools (run on Linux, produce Amiga IFF files) +# +AMISRC = ../sys/amiga + +$(TARGETPFX)xpm2iff_host: $(AMISRC)/xpm2iff_host.c + $(CC) $(CFLAGS) -o $@ $< +$(TARGETPFX)tomb.iff: $(AMISRC)/grave16.xpm $(TARGETPFX)xpm2iff_host + $(TARGETPFX)xpm2iff_host $(AMISRC)/grave16.xpm $@ + +$(TARGETPFX)bmp2iff_host: $(AMISRC)/bmp2iff_host.c + $(CC) $(CFLAGS) -o $@ $< +$(TARGETPFX)tiles16.iff: ../dat/nhtiles.bmp $(TARGETPFX)bmp2iff_host + $(TARGETPFX)bmp2iff_host -planes 4 ../dat/nhtiles.bmp $@ +$(TARGETPFX)tiles32.iff: ../dat/nhtiles.bmp $(TARGETPFX)bmp2iff_host + $(TARGETPFX)bmp2iff_host -planes 5 ../dat/nhtiles.bmp $@ + +AMITILES = $(TARGETPFX)tiles16.iff $(TARGETPFX)tiles32.iff $(TARGETPFX)tomb.iff + +.PHONY: amigapkg amitiles +amitiles: $(AMITILES) + +amigapkg: $(AMITILES) + mkdir -p $(TARGETPFX)pkg/tiles $(TARGETPFX)pkg/hack + cp $(GAMEBIN) $(TARGETPFX)pkg/nethack + cp ../dat/nhdat $(TARGETPFX)pkg/nhdat + cp ../dat/license $(TARGETPFX)pkg/license + cp ../dat/symbols $(TARGETPFX)pkg/symbols + cp $(TARGETPFX)tiles16.iff $(TARGETPFX)pkg/tiles/tiles16.iff + cp $(TARGETPFX)tiles32.iff $(TARGETPFX)pkg/tiles/tiles32.iff + cp $(TARGETPFX)tomb.iff $(TARGETPFX)pkg/tomb.iff + cp ../sys/msdos/sysconf $(TARGETPFX)pkg/sysconf + cp ../doc/nethack.txt $(TARGETPFX)pkg/nethack.txt + ( cd $(TARGETPFX)pkg && uudecode ../../../sys/amiga/amifont8.uu && mv 8 hack/8 ) + ( cd $(TARGETPFX)pkg && uudecode ../../../sys/amiga/amifont.uu ) + cp $(AMISRC)/nethack.cnf $(TARGETPFX)pkg/nethack.cnf + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/dflticon.uu && \ + uudecode ../../../sys/amiga/dflticon.uu ) + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/NHinfo.uu && \ + uudecode ../../../sys/amiga/NHinfo.uu ) + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/NewGame.uu && \ + uudecode ../../../sys/amiga/NewGame.uu ) + -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/HackWB.uu && \ + uudecode ../../../sys/amiga/HackWB.uu ) + touch $(TARGETPFX)pkg/record + ( cd $(TARGETPFX)pkg && zip -9r ../NH370AMI.ZIP * ) + @echo amiga package zip file $(TARGETPFX)NH370AMI.ZIP +endif # CROSS_TO_AMIGA + ifdef CROSS_SHARED # shared file dependencies $(TARGETPFX)pcmain.o : ../sys/share/pcmain.c $(HACK_H) diff --git a/sys/unix/hints/include/cross-pre1.370 b/sys/unix/hints/include/cross-pre1.370 index 203c06048..867886d9b 100644 --- a/sys/unix/hints/include/cross-pre1.370 +++ b/sys/unix/hints/include/cross-pre1.370 @@ -38,6 +38,16 @@ override TARGETPFX = $(TARGETDIR)/ override TARGET_LIBS= endif +ifdef CROSS_TO_AMIGA +CROSS=1 +BUILD_TARGET_LUA=1 +CROSS_SHARED=1 +override TARGET = amiga +override TARGETDIR=../targets/$(TARGET) +override TARGETPFX = $(TARGETDIR)/ +override TARGET_LIBS= +endif + ifdef CROSS override PREGAME= override BUILDMORE= diff --git a/sys/unix/hints/include/cross-pre2.370 b/sys/unix/hints/include/cross-pre2.370 index d0cdf513a..eca47550f 100644 --- a/sys/unix/hints/include/cross-pre2.370 +++ b/sys/unix/hints/include/cross-pre2.370 @@ -460,6 +460,96 @@ NCURSES_PLATFORM=MIPS endif # CROSS_TO_MIPS #================================================================= +#================================================================= + +ifdef CROSS_TO_AMIGA +#===============-================================================= +# AmigaOS m68k cross-compile recipe +#===============-================================================= +# Uses an Amiga M68K cross-compiler on linux or macOS. +# +# Cross-compiler: https://franke.ms/git/bebbo/amiga-gcc +# Install to /opt/amiga, then: +# make fetch-lua +# sys/unix/setup.sh sys/unix/hints/linux.370 +# make CROSS_TO_AMIGA=1 all +# make CROSS_TO_AMIGA=1 package +#================================================================= + +CFLAGS += -DCROSSCOMPILE + +# +# Override the build tools and some obj files to +# reflect the amiga-gcc cross-compiler. +# +TOOLTOP = /opt/amiga/bin +TOOLARCH = -m68000 +override REGEXOBJ = $(TARGETPFX)posixregex.o +AMIREGEXOBJ = $(TARGETPFX)regcomp.o $(TARGETPFX)regexec.o \ + $(TARGETPFX)regerror.o $(TARGETPFX)regfree.o +override TARGET_CC = $(TOOLTOP)/m68k-amigaos-gcc +override TARGET_CXX = $(TOOLTOP)/m68k-amigaos-c++ +override TARGET_AR = $(TOOLTOP)/m68k-amigaos-ar +override TARGET_STUBEDIT= +override TARGET_CFLAGS = -c -O2 -noixemul $(TOOLARCH) \ + -include sys/types.h \ + -I../include \ + -I../sys/amiga -I../win/share \ + $(LUAINCL) -DAMIGA -DNOTTYGRAPHICS -DNO_TERMS -DNO_SIGNAL \ + -DTILES_IN_GLYPHMAP $(PDCURSESDEF) \ + -DCROSSCOMPILE -DCROSSCOMPILE_TARGET -DCROSS_TO_AMIGA \ + -DAMIGA_VERSION_STRING=\""VER: NetHack 3.7.0"\" +override TARGET_CXXFLAGS = $(TARGET_CFLAGS) +LUA_TARGET_CFLAGS = $(TARGET_CFLAGS) -DLUA_32BITS=1 +ifeq "$(REGEXOBJ)" "$(TARGETPFX)cppregex.o" +override TARGET_LINK = $(TARGET_CXX) +else +override TARGET_LINK = $(TARGET_CC) +endif +override TARGET_LFLAGS= $(TOOLARCH) -noixemul -Wl,--allow-multiple-definition +override TARGET_LIBS += $(LIBLM) +VARDATND += nhtiles.bmp +override SYSSRC = ../sys/amiga/amidos.c ../sys/amiga/amigst.c \ + ../sys/amiga/amimenu.c ../sys/amiga/amirip.c \ + ../sys/amiga/amistack.c ../sys/amiga/amitty.c \ + ../sys/amiga/amiwind.c ../sys/amiga/clipwin.c \ + ../sys/amiga/colorwin.c \ + ../sys/amiga/winami.c ../sys/amiga/winchar.c \ + ../sys/amiga/winfuncs.c ../sys/amiga/winkey.c \ + ../sys/amiga/winamenu.c ../sys/amiga/winreq.c \ + ../sys/amiga/winstr.c ../sys/share/pcmain.c \ + ../win/share/bmptiles.c ../win/share/giftiles.c \ + ../win/share/tileset.c +override SYSOBJ = $(TARGETPFX)amidos.o $(TARGETPFX)amigst.o \ + $(TARGETPFX)amirip.o $(TARGETPFX)amistack.o \ + $(TARGETPFX)amitty.o $(TARGETPFX)amiwind.o \ + $(TARGETPFX)winami.o $(TARGETPFX)winchar.o \ + $(TARGETPFX)winfuncs.o $(TARGETPFX)winkey.o \ + $(TARGETPFX)winamenu.o $(TARGETPFX)winreq.o \ + $(TARGETPFX)winstr.o $(TARGETPFX)pcmain.o \ + $(TARGETPFX)bmptiles.o $(TARGETPFX)giftiles.o \ + $(TARGETPFX)tileset.o \ + $(AMIREGEXOBJ) +override WINLIB= +override LUALIB= +override LUALIBS= +override TOPLUALIB= +override DLLIB= +override WINOBJ= +override GAMEBIN = $(TARGETPFX)nethack +override PACKAGE = amigapkg +override PREGAME += mkdir -p $(TARGETDIR) ; +override CLEANMORE += rm -r $(TARGETDIR) ; +# +# Rule for files in sys/amiga +$(TARGETPFX)%.o : ../sys/amiga/%.c + $(TARGET_CC) $(TARGET_CFLAGS) -o$@ $< +# Rule for BSD regex in sys/amiga/regex +$(TARGETPFX)%.o : ../sys/amiga/regex/%.c + $(TARGET_CC) $(TARGET_CFLAGS) -I../sys/amiga/regex -o$@ $< +endif # CROSS_TO_AMIGA +#================================================================= + ifdef WANT_WIN_CURSES ifdef BUILD_PDCURSES # Rules for PDCurses files From cee390482c17112fd4bab0796840fd89eea780ca Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Mon, 23 Mar 2026 20:48:28 +0100 Subject: [PATCH 5/8] Add BSD POSIX regex for Amiga Add Henry Spencer's BSD regex implementation (from ixemul) to provide POSIX regular expressions for the Amiga port, enabling menu coloring and config file pattern matching. Copyright (c) 1992 Henry Spencer, The Regents of the University of California. BSD license. --- sys/amiga/regex/cclass.h | 72 ++ sys/amiga/regex/cname.h | 143 +++ sys/amiga/regex/engine.h | 1093 +++++++++++++++++++++++ sys/amiga/regex/regcomp.c | 1704 ++++++++++++++++++++++++++++++++++++ sys/amiga/regex/regerror.c | 186 ++++ sys/amiga/regex/regex2.h | 175 ++++ sys/amiga/regex/regexec.c | 187 ++++ sys/amiga/regex/regfree.c | 86 ++ sys/amiga/regex/utils.h | 59 ++ 9 files changed, 3705 insertions(+) create mode 100755 sys/amiga/regex/cclass.h create mode 100755 sys/amiga/regex/cname.h create mode 100755 sys/amiga/regex/engine.h create mode 100755 sys/amiga/regex/regcomp.c create mode 100755 sys/amiga/regex/regerror.c create mode 100755 sys/amiga/regex/regex2.h create mode 100755 sys/amiga/regex/regexec.c create mode 100755 sys/amiga/regex/regfree.c create mode 100755 sys/amiga/regex/utils.h diff --git a/sys/amiga/regex/cclass.h b/sys/amiga/regex/cclass.h new file mode 100755 index 000000000..52cd47b8f --- /dev/null +++ b/sys/amiga/regex/cclass.h @@ -0,0 +1,72 @@ +/* $NetBSD: cclass.h,v 1.3 1995/02/27 13:28:29 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)cclass.h 8.3 (Berkeley) 3/20/94 + */ + +/* character-class table */ +static struct cclass { + char *name; + char *chars; + char *multis; +} cclasses[] = { + "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789", "", + "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + "", + "blank", " \t", "", + "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ +\25\26\27\30\31\32\33\34\35\36\37\177", "", + "digit", "0123456789", "", + "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "", + "lower", "abcdefghijklmnopqrstuvwxyz", + "", + "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", + "", + "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "", + "space", "\t\n\v\f\r ", "", + "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "", + "xdigit", "0123456789ABCDEFabcdef", + "", + NULL, 0, "" +}; diff --git a/sys/amiga/regex/cname.h b/sys/amiga/regex/cname.h new file mode 100755 index 000000000..50479db08 --- /dev/null +++ b/sys/amiga/regex/cname.h @@ -0,0 +1,143 @@ +/* $NetBSD: cname.h,v 1.3 1995/02/27 13:28:33 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)cname.h 8.3 (Berkeley) 3/20/94 + */ + +/* character-name table */ +static struct cname { + char *name; + char code; +} cnames[] = { + "NUL", '\0', + "SOH", '\001', + "STX", '\002', + "ETX", '\003', + "EOT", '\004', + "ENQ", '\005', + "ACK", '\006', + "BEL", '\007', + "alert", '\007', + "BS", '\010', + "backspace", '\b', + "HT", '\011', + "tab", '\t', + "LF", '\012', + "newline", '\n', + "VT", '\013', + "vertical-tab", '\v', + "FF", '\014', + "form-feed", '\f', + "CR", '\015', + "carriage-return", '\r', + "SO", '\016', + "SI", '\017', + "DLE", '\020', + "DC1", '\021', + "DC2", '\022', + "DC3", '\023', + "DC4", '\024', + "NAK", '\025', + "SYN", '\026', + "ETB", '\027', + "CAN", '\030', + "EM", '\031', + "SUB", '\032', + "ESC", '\033', + "IS4", '\034', + "FS", '\034', + "IS3", '\035', + "GS", '\035', + "IS2", '\036', + "RS", '\036', + "IS1", '\037', + "US", '\037', + "space", ' ', + "exclamation-mark", '!', + "quotation-mark", '"', + "number-sign", '#', + "dollar-sign", '$', + "percent-sign", '%', + "ampersand", '&', + "apostrophe", '\'', + "left-parenthesis", '(', + "right-parenthesis", ')', + "asterisk", '*', + "plus-sign", '+', + "comma", ',', + "hyphen", '-', + "hyphen-minus", '-', + "period", '.', + "full-stop", '.', + "slash", '/', + "solidus", '/', + "zero", '0', + "one", '1', + "two", '2', + "three", '3', + "four", '4', + "five", '5', + "six", '6', + "seven", '7', + "eight", '8', + "nine", '9', + "colon", ':', + "semicolon", ';', + "less-than-sign", '<', + "equals-sign", '=', + "greater-than-sign", '>', + "question-mark", '?', + "commercial-at", '@', + "left-square-bracket", '[', + "backslash", '\\', + "reverse-solidus", '\\', + "right-square-bracket", ']', + "circumflex", '^', + "circumflex-accent", '^', + "underscore", '_', + "low-line", '_', + "grave-accent", '`', + "left-brace", '{', + "left-curly-bracket", '{', + "vertical-line", '|', + "right-brace", '}', + "right-curly-bracket", '}', + "tilde", '~', + "DEL", '\177', + NULL, 0, +}; diff --git a/sys/amiga/regex/engine.h b/sys/amiga/regex/engine.h new file mode 100755 index 000000000..93f6842ac --- /dev/null +++ b/sys/amiga/regex/engine.h @@ -0,0 +1,1093 @@ +/* $NetBSD: engine.c,v 1.5 1995/02/27 13:28:39 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)engine.c 8.5 (Berkeley) 3/20/94 + */ + +/* + * The matching engine and friends. This file is #included by regexec.c + * after suitable #defines of a variety of macros used herein, so that + * different state representations can be used without duplicating masses + * of code. + */ + +#ifdef SNAMES +#define matcher smatcher +#define fast sfast +#define slow sslow +#define dissect sdissect +#define backref sbackref +#define step sstep +#define print sprint +#define at sat +#define match smat +#endif +#ifdef LNAMES +#define matcher lmatcher +#define fast lfast +#define slow lslow +#define dissect ldissect +#define backref lbackref +#define step lstep +#define print lprint +#define at lat +#define match lmat +#endif + +/* another structure passed up and down to avoid zillions of parameters */ +struct match { + struct re_guts *g; + int eflags; + regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ + char *offp; /* offsets work from here */ + char *beginp; /* start of string -- virtual NUL precedes */ + char *endp; /* end of string -- virtual NUL here */ + char *coldp; /* can be no match starting before here */ + char **lastpos; /* [nplus+1] */ + STATEVARS; + states st; /* current states */ + states fresh; /* states for a fresh start */ + states tmp; /* temporary */ + states empty; /* empty set of states */ +}; + +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === engine.c === */ +static int matcher __P((struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags)); +static char *dissect __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst)); +static char *backref __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev)); +static char *fast __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst)); +static char *slow __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst)); +static states step __P((struct re_guts *g, sopno start, sopno stop, states bef, int ch, states aft)); +#define BOL (OUT+1) +#define EOL (BOL+1) +#define BOLEOL (BOL+2) +#define NOTHING (BOL+3) +#define BOW (BOL+4) +#define EOW (BOL+5) +#define CODEMAX (BOL+5) /* highest code used */ +#define NONCHAR(c) ((c) > CHAR_MAX) +#define NNONCHAR (CODEMAX-CHAR_MAX) +#ifdef REDEBUG +static void print __P((struct match *m, char *caption, states st, int ch, FILE *d)); +#endif +#ifdef REDEBUG +static void at __P((struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst)); +#endif +#ifdef REDEBUG +static char *pchar __P((int ch)); +#endif + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ + +#ifdef REDEBUG +#define SP(t, s, c) print(m, t, s, c, stdout) +#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) +#define NOTE(str) { if (m->eflags®_TRACE) printf("=%s\n", (str)); } +#else +#define SP(t, s, c) /* nothing */ +#define AT(t, p1, p2, s1, s2) /* nothing */ +#define NOTE(s) /* nothing */ +#endif + +/* + - matcher - the actual matching engine + == static int matcher(register struct re_guts *g, char *string, \ + == size_t nmatch, regmatch_t pmatch[], int eflags); + */ +static int /* 0 success, REG_NOMATCH failure */ +matcher(g, string, nmatch, pmatch, eflags) +register struct re_guts *g; +char *string; +size_t nmatch; +regmatch_t pmatch[]; +int eflags; +{ + register char *endp; + register int i; + struct match mv; + register struct match *m = &mv; + register char *dp; + const register sopno gf = g->firststate+1; /* +1 for OEND */ + const register sopno gl = g->laststate; + char *start; + char *stop; + + /* simplify the situation where possible */ + if (g->cflags®_NOSUB) + nmatch = 0; + if (eflags®_STARTEND) { + start = string + pmatch[0].rm_so; + stop = string + pmatch[0].rm_eo; + } else { + start = string; + stop = start + strlen(start); + } + if (stop < start) + return(REG_INVARG); + + /* prescreening; this does wonders for this rather slow code */ + if (g->must != NULL) { + for (dp = start; dp < stop; dp++) + if (*dp == g->must[0] && stop - dp >= g->mlen && + memcmp(dp, g->must, (size_t)g->mlen) == 0) + break; + if (dp == stop) /* we didn't find g->must */ + return(REG_NOMATCH); + } + + /* match struct setup */ + m->g = g; + m->eflags = eflags; + m->pmatch = NULL; + m->lastpos = NULL; + m->offp = string; + m->beginp = start; + m->endp = stop; + STATESETUP(m, 4); + SETUP(m->st); + SETUP(m->fresh); + SETUP(m->tmp); + SETUP(m->empty); + CLEAR(m->empty); + + /* this loop does only one repetition except for backrefs */ + for (;;) { + endp = fast(m, start, stop, gf, gl); + if (endp == NULL) { /* a miss */ + STATETEARDOWN(m); + return(REG_NOMATCH); + } + if (nmatch == 0 && !g->backrefs) + break; /* no further info needed */ + + /* where? */ + assert(m->coldp != NULL); + for (;;) { + NOTE("finding start"); + endp = slow(m, m->coldp, stop, gf, gl); + if (endp != NULL) + break; + assert(m->coldp < m->endp); + m->coldp++; + } + if (nmatch == 1 && !g->backrefs) + break; /* no further info needed */ + + /* oh my, he wants the subexpressions... */ + if (m->pmatch == NULL) + m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) * + sizeof(regmatch_t)); + if (m->pmatch == NULL) { + STATETEARDOWN(m); + return(REG_ESPACE); + } + for (i = 1; i <= m->g->nsub; i++) + m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; + if (!g->backrefs && !(m->eflags®_BACKR)) { + NOTE("dissecting"); + dp = dissect(m, m->coldp, endp, gf, gl); + } else { + if (g->nplus > 0 && m->lastpos == NULL) + m->lastpos = (char **)malloc((g->nplus+1) * + sizeof(char *)); + if (g->nplus > 0 && m->lastpos == NULL) { + free(m->pmatch); + STATETEARDOWN(m); + return(REG_ESPACE); + } + NOTE("backref dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); + } + if (dp != NULL) + break; + + /* uh-oh... we couldn't find a subexpression-level match */ + assert(g->backrefs); /* must be back references doing it */ + assert(g->nplus == 0 || m->lastpos != NULL); + for (;;) { + if (dp != NULL || endp <= m->coldp) + break; /* defeat */ + NOTE("backoff"); + endp = slow(m, m->coldp, endp-1, gf, gl); + if (endp == NULL) + break; /* defeat */ + /* try it on a shorter possibility */ +#ifndef NDEBUG + for (i = 1; i <= m->g->nsub; i++) { + assert(m->pmatch[i].rm_so == -1); + assert(m->pmatch[i].rm_eo == -1); + } +#endif + NOTE("backoff dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); + } + assert(dp == NULL || dp == endp); + if (dp != NULL) /* found a shorter one */ + break; + + /* despite initial appearances, there is no match here */ + NOTE("false alarm"); + start = m->coldp + 1; /* recycle starting later */ + assert(start <= stop); + } + + /* fill in the details if requested */ + if (nmatch > 0) { + pmatch[0].rm_so = m->coldp - m->offp; + pmatch[0].rm_eo = endp - m->offp; + } + if (nmatch > 1) { + assert(m->pmatch != NULL); + for (i = 1; i < nmatch; i++) + if (i <= m->g->nsub) + pmatch[i] = m->pmatch[i]; + else { + pmatch[i].rm_so = -1; + pmatch[i].rm_eo = -1; + } + } + + if (m->pmatch != NULL) + free((char *)m->pmatch); + if (m->lastpos != NULL) + free((char *)m->lastpos); + STATETEARDOWN(m); + return(0); +} + +/* + - dissect - figure out what matched what, no back references + == static char *dissect(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* == stop (success) always */ +dissect(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register int i; + register sopno ss; /* start sop of current subRE */ + register sopno es; /* end sop of current subRE */ + register char *sp; /* start of string matched by it */ + register char *stp; /* string matched by it cannot pass here */ + register char *rest; /* start of rest of string */ + register char *tail; /* string unmatched by rest of RE */ + register sopno ssub; /* start sop of subsubRE */ + register sopno esub; /* end sop of subsubRE */ + register char *ssp; /* start of string matched by subsubRE */ + register char *sep; /* end of string matched by subsubRE */ + register char *oldssp; /* previous ssp */ + register char *dp; + + AT("diss", start, stop, startst, stopst); + sp = start; + for (ss = startst; ss < stopst; ss = es) { + /* identify end of subRE */ + es = ss; + switch (OP(m->g->strip[es])) { + case OPLUS_: + case OQUEST_: + es += OPND(m->g->strip[es]); + break; + case OCH_: + while (OP(m->g->strip[es]) != O_CH) + es += OPND(m->g->strip[es]); + break; + } + es++; + + /* figure out what it matched */ + switch (OP(m->g->strip[ss])) { + case OEND: + assert(nope); + break; + case OCHAR: + sp++; + break; + case OBOL: + case OEOL: + case OBOW: + case OEOW: + break; + case OANY: + case OANYOF: + sp++; + break; + case OBACK_: + case O_BACK: + assert(nope); + break; + /* cases where length of match is hard to find */ + case OQUEST_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + /* did innards match? */ + if (slow(m, sp, rest, ssub, esub) != NULL) { + dp = dissect(m, sp, rest, ssub, esub); + assert(dp == rest); + } else /* no */ + assert(sp == rest); + sp = rest; + break; + case OPLUS_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + ssp = sp; + oldssp = ssp; + for (;;) { /* find last match of innards */ + sep = slow(m, ssp, rest, ssub, esub); + if (sep == NULL || sep == ssp) + break; /* failed or matched null */ + oldssp = ssp; /* on to next try */ + ssp = sep; + } + if (sep == NULL) { + /* last successful match */ + sep = ssp; + ssp = oldssp; + } + assert(sep == rest); /* must exhaust substring */ + assert(slow(m, ssp, sep, ssub, esub) == rest); + dp = dissect(m, ssp, sep, ssub, esub); + assert(dp == sep); + sp = rest; + break; + case OCH_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = ss + OPND(m->g->strip[ss]) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + if (slow(m, sp, rest, ssub, esub) == rest) + break; /* it matched all of it */ + /* that one missed, try next one */ + assert(OP(m->g->strip[esub]) == OOR1); + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + dp = dissect(m, sp, rest, ssub, esub); + assert(dp == rest); + sp = rest; + break; + case O_PLUS: + case O_QUEST: + case OOR1: + case OOR2: + case O_CH: + assert(nope); + break; + case OLPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_so = sp - m->offp; + break; + case ORPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_eo = sp - m->offp; + break; + default: /* uh oh */ + assert(nope); + break; + } + } + + assert(sp == stop); + return(sp); +} + +/* + - backref - figure out what matched what, figuring in back references + == static char *backref(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst, sopno lev); + */ +static char * /* == stop (success) or NULL (failure) */ +backref(m, start, stop, startst, stopst, lev) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +sopno lev; /* PLUS nesting level */ +{ + register int i; + register sopno ss; /* start sop of current subRE */ + register char *sp; /* start of string matched by it */ + register sopno ssub; /* start sop of subsubRE */ + register sopno esub; /* end sop of subsubRE */ + register char *ssp; /* start of string matched by subsubRE */ + register char *dp; + register size_t len; + register int hard; + register sop s; + register regoff_t offsave; + register cset *cs; + + AT("back", start, stop, startst, stopst); + sp = start; + + /* get as far as we can with easy stuff */ + hard = 0; + for (ss = startst; !hard && ss < stopst; ss++) + switch (OP(s = m->g->strip[ss])) { + case OCHAR: + if (sp == stop || *sp++ != (char)OPND(s)) + return(NULL); + break; + case OANY: + if (sp == stop) + return(NULL); + sp++; + break; + case OANYOF: + cs = &m->g->sets[OPND(s)]; + if (sp == stop || !CHIN(cs, *sp++)) + return(NULL); + break; + case OBOL: + if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp > m->beginp && + !ISWORD(*(sp-1))) ) && + (sp < m->endp && ISWORD(*sp)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOW: + if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp < m->endp && !ISWORD(*sp)) ) && + (sp > m->beginp && ISWORD(*(sp-1))) ) + { /* yes */ } + else + return(NULL); + break; + case O_QUEST: + break; + case OOR1: /* matches null but needs to skip */ + ss++; + s = m->g->strip[ss]; + do { + assert(OP(s) == OOR2); + ss += OPND(s); + } while (OP(s = m->g->strip[ss]) != O_CH); + /* note that the ss++ gets us past the O_CH */ + break; + default: /* have to make a choice */ + hard = 1; + break; + } + if (!hard) { /* that was it! */ + if (sp != stop) + return(NULL); + return(sp); + } + ss--; /* adjust for the for's final increment */ + + /* the hard stuff */ + AT("hard", sp, stop, ss, stopst); + s = m->g->strip[ss]; + switch (OP(s)) { + case OBACK_: /* the vilest depths */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + if (m->pmatch[i].rm_eo == -1) + return(NULL); + assert(m->pmatch[i].rm_so != -1); + len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; + assert(stop - m->beginp >= len); + if (sp > stop - len) + return(NULL); /* not enough left to match */ + ssp = m->offp + m->pmatch[i].rm_so; + if (memcmp(sp, ssp, len) != 0) + return(NULL); + while (m->g->strip[ss] != SOP(O_BACK, i)) + ss++; + return(backref(m, sp+len, stop, ss+1, stopst, lev)); + break; + case OQUEST_: /* to null or not */ + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); /* not */ + return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev)); + break; + case OPLUS_: + assert(m->lastpos != NULL); + assert(lev+1 <= m->g->nplus); + m->lastpos[lev+1] = sp; + return(backref(m, sp, stop, ss+1, stopst, lev+1)); + break; + case O_PLUS: + if (sp == m->lastpos[lev]) /* last pass matched null */ + return(backref(m, sp, stop, ss+1, stopst, lev-1)); + /* try another pass */ + m->lastpos[lev] = sp; + dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev); + if (dp == NULL) + return(backref(m, sp, stop, ss+1, stopst, lev-1)); + else + return(dp); + break; + case OCH_: /* find the right one, if any */ + ssub = ss + 1; + esub = ss + OPND(s) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + dp = backref(m, sp, stop, ssub, esub, lev); + if (dp != NULL) + return(dp); + /* that one missed, try next one */ + if (OP(m->g->strip[esub]) == O_CH) + return(NULL); /* there is none */ + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + break; + case OLPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_so; + m->pmatch[i].rm_so = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_so = offsave; + return(NULL); + break; + case ORPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_eo; + m->pmatch[i].rm_eo = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_eo = offsave; + return(NULL); + break; + default: /* uh oh */ + assert(nope); + break; + } + + /* "can't happen" */ + assert(nope); + /* NOTREACHED */ +} + +/* + - fast - step through the string at top speed + == static char *fast(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* where tentative match ended, or NULL */ +fast(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register states st = m->st; + register states fresh = m->fresh; + register states tmp = m->tmp; + register char *p = start; + register int c = (start == m->beginp) ? OUT : *(start-1); + register int lastc; /* previous c */ + register int flagch; + register int i; + register char *coldp; /* last p after which no match was underway */ + + CLEAR(st); + SET1(st, startst); + st = step(m->g, startst, stopst, st, NOTHING, st); + ASSIGN(fresh, st); + SP("start", st, *p); + coldp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + if (EQ(st, fresh)) + coldp = p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("boleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("boweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, fresh); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("aft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + assert(coldp != NULL); + m->coldp = coldp; + if (ISSET(st, stopst)) + return(p+1); + else + return(NULL); +} + +/* + - slow - step through the string more deliberately + == static char *slow(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* where it ended */ +slow(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register states st = m->st; + register states empty = m->empty; + register states tmp = m->tmp; + register char *p = start; + register int c = (start == m->beginp) ? OUT : *(start-1); + register int lastc; /* previous c */ + register int flagch; + register int i; + register char *matchp; /* last p at which a match ended */ + + AT("slow", start, stop, startst, stopst); + CLEAR(st); + SET1(st, startst); + SP("sstart", st, *p); + st = step(m->g, startst, stopst, st, NOTHING, st); + matchp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst)) + matchp = p; + if (EQ(st, empty) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, empty); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("saft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + return(matchp); +} + + +/* + - step - map set of states reachable before char to set reachable after + == static states step(register struct re_guts *g, sopno start, sopno stop, \ + == register states bef, int ch, register states aft); + == #define BOL (OUT+1) + == #define EOL (BOL+1) + == #define BOLEOL (BOL+2) + == #define NOTHING (BOL+3) + == #define BOW (BOL+4) + == #define EOW (BOL+5) + == #define CODEMAX (BOL+5) // highest code used + == #define NONCHAR(c) ((c) > CHAR_MAX) + == #define NNONCHAR (CODEMAX-CHAR_MAX) + */ +static states +step(g, start, stop, bef, ch, aft) +register struct re_guts *g; +sopno start; /* start state within strip */ +sopno stop; /* state after stop state within strip */ +register states bef; /* states reachable before */ +int ch; /* character or NONCHAR code */ +register states aft; /* states already known reachable after */ +{ + register cset *cs; + register sop s; + register sopno pc; + register onestate here; /* note, macros know this name */ + register sopno look; + register int i; + + for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { + s = g->strip[pc]; + switch (OP(s)) { + case OEND: + assert(pc == stop-1); + break; + case OCHAR: + /* only characters can match */ + assert(!NONCHAR(ch) || ch != (char)OPND(s)); + if (ch == (char)OPND(s)) + FWD(aft, bef, 1); + break; + case OBOL: + if (ch == BOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OEOL: + if (ch == EOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OBOW: + if (ch == BOW) + FWD(aft, bef, 1); + break; + case OEOW: + if (ch == EOW) + FWD(aft, bef, 1); + break; + case OANY: + if (!NONCHAR(ch)) + FWD(aft, bef, 1); + break; + case OANYOF: + cs = &g->sets[OPND(s)]; + if (!NONCHAR(ch) && CHIN(cs, ch)) + FWD(aft, bef, 1); + break; + case OBACK_: /* ignored here */ + case O_BACK: + FWD(aft, aft, 1); + break; + case OPLUS_: /* forward, this is just an empty */ + FWD(aft, aft, 1); + break; + case O_PLUS: /* both forward and back */ + FWD(aft, aft, 1); + i = ISSETBACK(aft, OPND(s)); + BACK(aft, aft, OPND(s)); + if (!i && ISSETBACK(aft, OPND(s))) { + /* oho, must reconsider loop body */ + pc -= OPND(s) + 1; + INIT(here, pc); + } + break; + case OQUEST_: /* two branches, both forward */ + FWD(aft, aft, 1); + FWD(aft, aft, OPND(s)); + break; + case O_QUEST: /* just an empty */ + FWD(aft, aft, 1); + break; + case OLPAREN: /* not significant here */ + case ORPAREN: + FWD(aft, aft, 1); + break; + case OCH_: /* mark the first two branches */ + FWD(aft, aft, 1); + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + break; + case OOR1: /* done a branch, find the O_CH */ + if (ISSTATEIN(aft, here)) { + for (look = 1; + OP(s = g->strip[pc+look]) != O_CH; + look += OPND(s)) + assert(OP(s) == OOR2); + FWD(aft, aft, look); + } + break; + case OOR2: /* propagate OCH_'s marking */ + FWD(aft, aft, 1); + if (OP(g->strip[pc+OPND(s)]) != O_CH) { + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + } + break; + case O_CH: /* just empty */ + FWD(aft, aft, 1); + break; + default: /* ooooops... */ + assert(nope); + break; + } + } + + return(aft); +} + +#ifdef REDEBUG +/* + - print - print a set of states + == #ifdef REDEBUG + == static void print(struct match *m, char *caption, states st, \ + == int ch, FILE *d); + == #endif + */ +static void +print(m, caption, st, ch, d) +struct match *m; +char *caption; +states st; +int ch; +FILE *d; +{ + register struct re_guts *g = m->g; + register int i; + register int first = 1; + + if (!(m->eflags®_TRACE)) + return; + + fprintf(d, "%s", caption); + if (ch != '\0') + fprintf(d, " %s", pchar(ch)); + for (i = 0; i < g->nstates; i++) + if (ISSET(st, i)) { + fprintf(d, "%s%d", (first) ? "\t" : ", ", i); + first = 0; + } + fprintf(d, "\n"); +} + +/* + - at - print current situation + == #ifdef REDEBUG + == static void at(struct match *m, char *title, char *start, char *stop, \ + == sopno startst, sopno stopst); + == #endif + */ +static void +at(m, title, start, stop, startst, stopst) +struct match *m; +char *title; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + if (!(m->eflags®_TRACE)) + return; + + printf("%s %s-", title, pchar(*start)); + printf("%s ", pchar(*stop)); + printf("%ld-%ld\n", (long)startst, (long)stopst); +} + +#ifndef PCHARDONE +#define PCHARDONE /* never again */ +/* + - pchar - make a character printable + == #ifdef REDEBUG + == static char *pchar(int ch); + == #endif + * + * Is this identical to regchar() over in debug.c? Well, yes. But a + * duplicate here avoids having a debugging-capable regexec.o tied to + * a matching debug.o, and this is convenient. It all disappears in + * the non-debug compilation anyway, so it doesn't matter much. + */ +static char * /* -> representation */ +pchar(ch) +int ch; +{ + static char pbuf[10]; + + if (isprint(ch) || ch == ' ') + sprintf(pbuf, "%c", ch); + else + sprintf(pbuf, "\\%o", ch); + return(pbuf); +} +#endif +#endif + +#undef matcher +#undef fast +#undef slow +#undef dissect +#undef backref +#undef step +#undef print +#undef at +#undef match diff --git a/sys/amiga/regex/regcomp.c b/sys/amiga/regex/regcomp.c new file mode 100755 index 000000000..9b64aa4b2 --- /dev/null +++ b/sys/amiga/regex/regcomp.c @@ -0,0 +1,1704 @@ +/* $NetBSD: regcomp.c,v 1.6 1995/02/27 13:29:01 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; +#else +static char rcsid[] = "$NetBSD: regcomp.c,v 1.6 1995/02/27 13:29:01 cgd Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "regex2.h" + +#include "cclass.h" +#include "cname.h" + +/* + * parse structure, passed up and down to avoid global variables and + * other clumsinesses + */ +struct parse { + char *next; /* next character in RE */ + char *end; /* end of string (-> NUL normally) */ + int error; /* has an error been seen? */ + sop *strip; /* malloced strip */ + sopno ssize; /* malloced strip size (allocated) */ + sopno slen; /* malloced strip length (used) */ + int ncsalloc; /* number of csets allocated */ + struct re_guts *g; +# define NPAREN 10 /* we need to remember () 1-9 for back refs */ + sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ + sopno pend[NPAREN]; /* -> ) ([0] unused) */ +}; + +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regcomp.c === */ +static void p_ere __P((struct parse *p, int stop)); +static void p_ere_exp __P((struct parse *p)); +static void p_str __P((struct parse *p)); +static void p_bre __P((struct parse *p, int end1, int end2)); +static int p_simp_re __P((struct parse *p, int starordinary)); +static int p_count __P((struct parse *p)); +static void p_bracket __P((struct parse *p)); +static void p_b_term __P((struct parse *p, cset *cs)); +static void p_b_cclass __P((struct parse *p, cset *cs)); +static void p_b_eclass __P((struct parse *p, cset *cs)); +static char p_b_symbol __P((struct parse *p)); +static char p_b_coll_elem __P((struct parse *p, int endc)); +static char othercase __P((int ch)); +static void bothcases __P((struct parse *p, int ch)); +static void ordinary __P((struct parse *p, int ch)); +static void nonnewline __P((struct parse *p)); +static void repeat __P((struct parse *p, sopno start, int from, int to)); +static int seterr __P((struct parse *p, int e)); +static cset *allocset __P((struct parse *p)); +static void freeset __P((struct parse *p, cset *cs)); +static int freezeset __P((struct parse *p, cset *cs)); +static int firstch __P((struct parse *p, cset *cs)); +static int nch __P((struct parse *p, cset *cs)); +static void mcadd __P((struct parse *p, cset *cs, char *cp)); +static void mcsub __P((cset *cs, char *cp)); +static int mcin __P((cset *cs, char *cp)); +static char *mcfind __P((cset *cs, char *cp)); +static void mcinvert __P((struct parse *p, cset *cs)); +static void mccase __P((struct parse *p, cset *cs)); +static int isinsets __P((struct re_guts *g, int c)); +static int samesets __P((struct re_guts *g, int c1, int c2)); +static void categorize __P((struct parse *p, struct re_guts *g)); +static sopno dupl __P((struct parse *p, sopno start, sopno finish)); +static void doemit __P((struct parse *p, sop op, size_t opnd)); +static void doinsert __P((struct parse *p, sop op, size_t opnd, sopno pos)); +static void dofwd __P((struct parse *p, sopno pos, sop value)); +static void enlarge __P((struct parse *p, sopno size)); +static void stripsnug __P((struct parse *p, struct re_guts *g)); +static void findmust __P((struct parse *p, struct re_guts *g)); +static sopno pluscount __P((struct parse *p, struct re_guts *g)); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ + +static char nuls[10]; /* place to point scanner in event of error */ + +/* + * macros for use with parse structure + * BEWARE: these know that the parse structure is named `p' !!! + */ +#define PEEK() (*p->next) +#define PEEK2() (*(p->next+1)) +#define MORE() (p->next < p->end) +#define MORE2() (p->next+1 < p->end) +#define SEE(c) (MORE() && PEEK() == (c)) +#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) +#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) +#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) +#define NEXT() (p->next++) +#define NEXT2() (p->next += 2) +#define NEXTn(n) (p->next += (n)) +#define GETNEXT() (*p->next++) +#define SETERROR(e) seterr(p, (e)) +#define REQUIRE(co, e) ((co) || SETERROR(e)) +#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) +#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) +#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) +#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) +#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) +#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) +#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) +#define HERE() (p->slen) +#define THERE() (p->slen - 1) +#define THERETHERE() (p->slen - 2) +#define DROP(n) (p->slen -= (n)) + +#ifndef NDEBUG +static int never = 0; /* for use in asserts; shuts lint up */ +#else +#define never 0 /* some s have bugs too */ +#endif + +/* + - regcomp - interface for parser and compilation + = extern int regcomp(regex_t *, const char *, int); + = #define REG_BASIC 0000 + = #define REG_EXTENDED 0001 + = #define REG_ICASE 0002 + = #define REG_NOSUB 0004 + = #define REG_NEWLINE 0010 + = #define REG_NOSPEC 0020 + = #define REG_PEND 0040 + = #define REG_DUMP 0200 + */ +int /* 0 success, otherwise REG_something */ +regcomp(preg, pattern, cflags) +regex_t *preg; +const char *pattern; +int cflags; +{ + struct parse pa; + register struct re_guts *g; + register struct parse *p = &pa; + register int i; + register size_t len; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&~REG_DUMP) +#endif + + cflags = GOODFLAGS(cflags); + if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_PEND) { + if (preg->re_endp < pattern) + return(REG_INVARG); + len = preg->re_endp - pattern; + } else + len = strlen((char *)pattern); + + /* do the mallocs early so failure handling is easy */ + g = (struct re_guts *)malloc(sizeof(struct re_guts) + + (NC-1)*sizeof(cat_t)); + if (g == NULL) + return(REG_ESPACE); + p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ + p->strip = (sop *)malloc(p->ssize * sizeof(sop)); + p->slen = 0; + if (p->strip == NULL) { + free((char *)g); + return(REG_ESPACE); + } + + /* set things up */ + p->g = g; + p->next = (char *)pattern; /* convenience; we do not modify it */ + p->end = p->next + len; + p->error = 0; + p->ncsalloc = 0; + for (i = 0; i < NPAREN; i++) { + p->pbegin[i] = 0; + p->pend[i] = 0; + } + g->csetsize = NC; + g->sets = NULL; + g->setbits = NULL; + g->ncsets = 0; + g->cflags = cflags; + g->iflags = 0; + g->nbol = 0; + g->neol = 0; + g->must = NULL; + g->mlen = 0; + g->nsub = 0; + g->ncategories = 1; /* category 0 is "everything else" */ + g->categories = &g->catspace[-(CHAR_MIN)]; + (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); + g->backrefs = 0; + + /* do it */ + EMIT(OEND, 0); + g->firststate = THERE(); + if (cflags®_EXTENDED) + p_ere(p, OUT); + else if (cflags®_NOSPEC) + p_str(p); + else + p_bre(p, OUT, OUT); + EMIT(OEND, 0); + g->laststate = THERE(); + + /* tidy up loose ends and fill things in */ + categorize(p, g); + stripsnug(p, g); + findmust(p, g); + g->nplus = pluscount(p, g); + g->magic = MAGIC2; + preg->re_nsub = g->nsub; + preg->re_g = g; + preg->re_magic = MAGIC1; +#ifndef REDEBUG + /* not debugging, so can't rely on the assert() in regexec() */ + if (g->iflags&BAD) + SETERROR(REG_ASSERT); +#endif + + /* win or lose, we're done */ + if (p->error != 0) /* lose */ + regfree(preg); + return(p->error); +} + +/* + - p_ere - ERE parser top level, concatenation and alternation + == static void p_ere(register struct parse *p, int stop); + */ +static void +p_ere(p, stop) +register struct parse *p; +int stop; /* character this ERE should end at */ +{ + register char c; + register sopno prevback; + register sopno prevfwd; + register sopno conc; + register int first = 1; /* is this the first alternative? */ + + for (;;) { + /* do a bunch of concatenated expressions */ + conc = HERE(); + while (MORE() && (c = PEEK()) != '|' && c != stop) + p_ere_exp(p); + REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ + + if (!EAT('|')) + break; /* NOTE BREAK OUT */ + + if (first) { + INSERT(OCH_, conc); /* offset is wrong */ + prevfwd = conc; + prevback = conc; + first = 0; + } + ASTERN(OOR1, prevback); + prevback = THERE(); + AHEAD(prevfwd); /* fix previous offset */ + prevfwd = HERE(); + EMIT(OOR2, 0); /* offset is very wrong */ + } + + if (!first) { /* tail-end fixups */ + AHEAD(prevfwd); + ASTERN(O_CH, prevback); + } + + assert(!MORE() || SEE(stop)); +} + +/* + - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op + == static void p_ere_exp(register struct parse *p); + */ +static void +p_ere_exp(p) +register struct parse *p; +{ + register char c; + register sopno pos; + register int count; + register int count2; + register sopno subno; + int wascaret = 0; + + assert(MORE()); /* caller should have ensured this */ + c = GETNEXT(); + + pos = HERE(); + switch (c) { + case '(': + REQUIRE(MORE(), REG_EPAREN); + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + if (!SEE(')')) + p_ere(p, ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + MUSTEAT(')', REG_EPAREN); + break; +#ifndef POSIX_MISTAKE + case ')': /* happens only if no current unmatched ( */ + /* + * You may ask, why the ifndef? Because I didn't notice + * this until slightly too late for 1003.2, and none of the + * other 1003.2 regular-expression reviewers noticed it at + * all. So an unmatched ) is legal POSIX, at least until + * we can get it fixed. + */ + SETERROR(REG_EPAREN); + break; +#endif + case '^': + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + wascaret = 1; + break; + case '$': + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + break; + case '|': + SETERROR(REG_EMPTY); + break; + case '*': + case '+': + case '?': + SETERROR(REG_BADRPT); + break; + case '.': + if (p->g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case '\\': + REQUIRE(MORE(), REG_EESCAPE); + c = GETNEXT(); + ordinary(p, c); + break; + case '{': /* okay as ordinary except if digit follows */ + REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c); + break; + } + + if (!MORE()) + return; + c = PEEK(); + /* we call { a repetition if followed by a digit */ + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit(PEEK2())) )) + return; /* no repetition, we're done */ + NEXT(); + + REQUIRE(!wascaret, REG_BADRPT); + switch (c) { + case '*': /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + break; + case '+': + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + break; + case '?': + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, pos); /* offset slightly wrong */ + ASTERN(OOR1, pos); /* this one's right */ + AHEAD(pos); /* fix the OCH_ */ + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + break; + case '{': + count = p_count(p); + if (EAT(',')) { + if (isdigit(PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EAT('}')) { /* error heuristics */ + while (MORE() && PEEK() != '}') + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + break; + } + + if (!MORE()) + return; + c = PEEK(); + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit(PEEK2())) ) ) + return; + SETERROR(REG_BADRPT); +} + +/* + - p_str - string (no metacharacters) "parser" + == static void p_str(register struct parse *p); + */ +static void +p_str(p) +register struct parse *p; +{ + REQUIRE(MORE(), REG_EMPTY); + while (MORE()) + ordinary(p, GETNEXT()); +} + +/* + - p_bre - BRE parser top level, anchoring and concatenation + == static void p_bre(register struct parse *p, register int end1, \ + == register int end2); + * Giving end1 as OUT essentially eliminates the end1/end2 check. + * + * This implementation is a bit of a kludge, in that a trailing $ is first + * taken as an ordinary character and then revised to be an anchor. The + * only undesirable side effect is that '$' gets included as a character + * category in such cases. This is fairly harmless; not worth fixing. + * The amount of lookahead needed to avoid this kludge is excessive. + */ +static void +p_bre(p, end1, end2) +register struct parse *p; +register int end1; /* first terminating character */ +register int end2; /* second terminating character */ +{ + register sopno start = HERE(); + register int first = 1; /* first subexpression? */ + register int wasdollar = 0; + + if (EAT('^')) { + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + } + while (MORE() && !SEETWO(end1, end2)) { + wasdollar = p_simp_re(p, first); + first = 0; + } + if (wasdollar) { /* oops, that was a trailing anchor */ + DROP(1); + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + } + + REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ +} + +/* + - p_simp_re - parse a simple RE, an atom possibly followed by a repetition + == static int p_simp_re(register struct parse *p, int starordinary); + */ +static int /* was the simple RE an unbackslashed $? */ +p_simp_re(p, starordinary) +register struct parse *p; +int starordinary; /* is a leading * an ordinary character? */ +{ + register int c; + register int count; + register int count2; + register sopno pos; + register int i; + register sopno subno; +# define BACKSL (1<g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case BACKSL|'{': + SETERROR(REG_BADRPT); + break; + case BACKSL|'(': + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + /* the MORE here is an error heuristic */ + if (MORE() && !SEETWO('\\', ')')) + p_bre(p, '\\', ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + REQUIRE(EATTWO('\\', ')'), REG_EPAREN); + break; + case BACKSL|')': /* should not get here -- must be user */ + case BACKSL|'}': + SETERROR(REG_EPAREN); + break; + case BACKSL|'1': + case BACKSL|'2': + case BACKSL|'3': + case BACKSL|'4': + case BACKSL|'5': + case BACKSL|'6': + case BACKSL|'7': + case BACKSL|'8': + case BACKSL|'9': + i = (c&~BACKSL) - '0'; + assert(i < NPAREN); + if (p->pend[i] != 0) { + assert(i <= p->g->nsub); + EMIT(OBACK_, i); + assert(p->pbegin[i] != 0); + assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); + assert(OP(p->strip[p->pend[i]]) == ORPAREN); + (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + EMIT(O_BACK, i); + } else + SETERROR(REG_ESUBREG); + p->g->backrefs = 1; + break; + case '*': + REQUIRE(starordinary, REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c &~ BACKSL); + break; + } + + if (EAT('*')) { /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + } else if (EATTWO('\\', '{')) { + count = p_count(p); + if (EAT(',')) { + if (MORE() && isdigit(PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EATTWO('\\', '}')) { /* error heuristics */ + while (MORE() && !SEETWO('\\', '}')) + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ + return(1); + + return(0); +} + +/* + - p_count - parse a repetition count + == static int p_count(register struct parse *p); + */ +static int /* the value */ +p_count(p) +register struct parse *p; +{ + register int count = 0; + register int ndigits = 0; + + while (MORE() && isdigit(PEEK()) && count <= DUPMAX) { + count = count*10 + (GETNEXT() - '0'); + ndigits++; + } + + REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); + return(count); +} + +/* + - p_bracket - parse a bracketed character list + == static void p_bracket(register struct parse *p); + * + * Note a significant property of this code: if the allocset() did SETERROR, + * no set operations are done. + */ +static void +p_bracket(p) +register struct parse *p; +{ + register char c; + register cset *cs = allocset(p); + register int invert = 0; + + /* Dept of Truly Sickening Special-Case Kludges */ + if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { + EMIT(OBOW, 0); + NEXTn(6); + return; + } + if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { + EMIT(OEOW, 0); + NEXTn(6); + return; + } + + if (EAT('^')) + invert++; /* make note to invert set at end */ + if (EAT(']')) + CHadd(cs, ']'); + else if (EAT('-')) + CHadd(cs, '-'); + while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) + p_b_term(p, cs); + if (EAT('-')) + CHadd(cs, '-'); + MUSTEAT(']', REG_EBRACK); + + if (p->error != 0) /* don't mess things up further */ + return; + + if (p->g->cflags®_ICASE) { + register int i; + register int ci; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i) && isalpha(i)) { + ci = othercase(i); + if (ci != i) + CHadd(cs, ci); + } + if (cs->multis != NULL) + mccase(p, cs); + } + if (invert) { + register int i; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i)) + CHsub(cs, i); + else + CHadd(cs, i); + if (p->g->cflags®_NEWLINE) + CHsub(cs, '\n'); + if (cs->multis != NULL) + mcinvert(p, cs); + } + + assert(cs->multis == NULL); /* xxx */ + + if (nch(p, cs) == 1) { /* optimize singleton sets */ + ordinary(p, firstch(p, cs)); + freeset(p, cs); + } else + EMIT(OANYOF, freezeset(p, cs)); +} + +/* + - p_b_term - parse one term of a bracketed character list + == static void p_b_term(register struct parse *p, register cset *cs); + */ +static void +p_b_term(p, cs) +register struct parse *p; +register cset *cs; +{ + register char c; + register char start, finish; + register int i; + + /* classify what we've got */ + switch ((MORE()) ? PEEK() : '\0') { + case '[': + c = (MORE2()) ? PEEK2() : '\0'; + break; + case '-': + SETERROR(REG_ERANGE); + return; /* NOTE RETURN */ + break; + default: + c = '\0'; + break; + } + + switch (c) { + case ':': /* character class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECTYPE); + p_b_cclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO(':', ']'), REG_ECTYPE); + break; + case '=': /* equivalence class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECOLLATE); + p_b_eclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); + break; + default: /* symbol, ordinary character, or range */ +/* xxx revision needed for multichar stuff */ + start = p_b_symbol(p); + if (SEE('-') && MORE2() && PEEK2() != ']') { + /* range */ + NEXT(); + if (EAT('-')) + finish = '-'; + else + finish = p_b_symbol(p); + } else + finish = start; +/* xxx what about signed chars here... */ + REQUIRE(start <= finish, REG_ERANGE); + for (i = start; i <= finish; i++) + CHadd(cs, i); + break; + } +} + +/* + - p_b_cclass - parse a character-class name and deal with it + == static void p_b_cclass(register struct parse *p, register cset *cs); + */ +static void +p_b_cclass(p, cs) +register struct parse *p; +register cset *cs; +{ + register char *sp = p->next; + register struct cclass *cp; + register size_t len; + register char *u; + register char c; + + while (MORE() && isalpha(PEEK())) + NEXT(); + len = p->next - sp; + for (cp = cclasses; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + break; + if (cp->name == NULL) { + /* oops, didn't find it */ + SETERROR(REG_ECTYPE); + return; + } + + u = cp->chars; + while ((c = *u++) != '\0') + CHadd(cs, c); + for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) + MCadd(p, cs, u); +} + +/* + - p_b_eclass - parse an equivalence-class name and deal with it + == static void p_b_eclass(register struct parse *p, register cset *cs); + * + * This implementation is incomplete. xxx + */ +static void +p_b_eclass(p, cs) +register struct parse *p; +register cset *cs; +{ + register char c; + + c = p_b_coll_elem(p, '='); + CHadd(cs, c); +} + +/* + - p_b_symbol - parse a character or [..]ed multicharacter collating symbol + == static char p_b_symbol(register struct parse *p); + */ +static char /* value of symbol */ +p_b_symbol(p) +register struct parse *p; +{ + register char value; + + REQUIRE(MORE(), REG_EBRACK); + if (!EATTWO('[', '.')) + return(GETNEXT()); + + /* collating symbol */ + value = p_b_coll_elem(p, '.'); + REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); + return(value); +} + +/* + - p_b_coll_elem - parse a collating-element name and look it up + == static char p_b_coll_elem(register struct parse *p, int endc); + */ +static char /* value of collating element */ +p_b_coll_elem(p, endc) +register struct parse *p; +int endc; /* name ended by endc,']' */ +{ + register char *sp = p->next; + register struct cname *cp; + register int len; + register char c; + + while (MORE() && !SEETWO(endc, ']')) + NEXT(); + if (!MORE()) { + SETERROR(REG_EBRACK); + return(0); + } + len = p->next - sp; + for (cp = cnames; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + return(cp->code); /* known name */ + if (len == 1) + return(*sp); /* single character */ + SETERROR(REG_ECOLLATE); /* neither */ + return(0); +} + +/* + - othercase - return the case counterpart of an alphabetic + == static char othercase(int ch); + */ +static char /* if no counterpart, return ch */ +othercase(ch) +int ch; +{ + assert(isalpha(ch)); + if (isupper(ch)) + return(tolower(ch)); + else if (islower(ch)) + return(toupper(ch)); + else /* peculiar, but could happen */ + return(ch); +} + +/* + - bothcases - emit a dualcase version of a two-case character + == static void bothcases(register struct parse *p, int ch); + * + * Boy, is this implementation ever a kludge... + */ +static void +bothcases(p, ch) +register struct parse *p; +int ch; +{ + register char *oldnext = p->next; + register char *oldend = p->end; + char bracket[3]; + + assert(othercase(ch) != ch); /* p_bracket() would recurse */ + p->next = bracket; + p->end = bracket+2; + bracket[0] = ch; + bracket[1] = ']'; + bracket[2] = '\0'; + p_bracket(p); + assert(p->next == bracket+2); + p->next = oldnext; + p->end = oldend; +} + +/* + - ordinary - emit an ordinary character + == static void ordinary(register struct parse *p, register int ch); + */ +static void +ordinary(p, ch) +register struct parse *p; +register int ch; +{ + register cat_t *cap = p->g->categories; + + if ((p->g->cflags®_ICASE) && isalpha(ch) && othercase(ch) != ch) + bothcases(p, ch); + else { + EMIT(OCHAR, (unsigned char)ch); + if (cap[ch] == 0) + cap[ch] = p->g->ncategories++; + } +} + +/* + - nonnewline - emit REG_NEWLINE version of OANY + == static void nonnewline(register struct parse *p); + * + * Boy, is this implementation ever a kludge... + */ +static void +nonnewline(p) +register struct parse *p; +{ + register char *oldnext = p->next; + register char *oldend = p->end; + char bracket[4]; + + p->next = bracket; + p->end = bracket+3; + bracket[0] = '^'; + bracket[1] = '\n'; + bracket[2] = ']'; + bracket[3] = '\0'; + p_bracket(p); + assert(p->next == bracket+3); + p->next = oldnext; + p->end = oldend; +} + +/* + - repeat - generate code for a bounded repetition, recursively if needed + == static void repeat(register struct parse *p, sopno start, int from, int to); + */ +static void +repeat(p, start, from, to) +register struct parse *p; +sopno start; /* operand from here to end of strip */ +int from; /* repeated from this number */ +int to; /* to this number of times (maybe INFINITY) */ +{ + register sopno finish = HERE(); +# define N 2 +# define INF 3 +# define REP(f, t) ((f)*8 + (t)) +# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) + register sopno copy; + + if (p->error != 0) /* head off possible runaway recursion */ + return; + + assert(from <= to); + + switch (REP(MAP(from), MAP(to))) { + case REP(0, 0): /* must be user doing this */ + DROP(finish-start); /* drop the operand */ + break; + case REP(0, 1): /* as x{1,1}? */ + case REP(0, N): /* as x{1,n}? */ + case REP(0, INF): /* as x{1,}? */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); /* offset is wrong... */ + repeat(p, start+1, 1, to); + ASTERN(OOR1, start); + AHEAD(start); /* ... fix it */ + EMIT(OOR2, 0); + AHEAD(THERE()); + ASTERN(O_CH, THERETHERE()); + break; + case REP(1, 1): /* trivial case */ + /* done */ + break; + case REP(1, N): /* as x?x{1,n-1} */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); + ASTERN(OOR1, start); + AHEAD(start); + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + copy = dupl(p, start+1, finish+1); + assert(copy == finish+4); + repeat(p, copy, 1, to-1); + break; + case REP(1, INF): /* as x+ */ + INSERT(OPLUS_, start); + ASTERN(O_PLUS, start); + break; + case REP(N, N): /* as xx{m-1,n-1} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to-1); + break; + case REP(N, INF): /* as xx{n-1,INF} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to); + break; + default: /* "can't happen" */ + SETERROR(REG_ASSERT); /* just in case */ + break; + } +} + +/* + - seterr - set an error condition + == static int seterr(register struct parse *p, int e); + */ +static int /* useless but makes type checking happy */ +seterr(p, e) +register struct parse *p; +int e; +{ + if (p->error == 0) /* keep earliest error condition */ + p->error = e; + p->next = nuls; /* try to bring things to a halt */ + p->end = nuls; + return(0); /* make the return value well-defined */ +} + +/* + - allocset - allocate a set of characters for [] + == static cset *allocset(register struct parse *p); + */ +static cset * +allocset(p) +register struct parse *p; +{ + register int no = p->g->ncsets++; + register size_t nc; + register size_t nbytes; + register cset *cs; + register size_t css = (size_t)p->g->csetsize; + register int i; + + if (no >= p->ncsalloc) { /* need another column of space */ + p->ncsalloc += CHAR_BIT; + nc = p->ncsalloc; + assert(nc % CHAR_BIT == 0); + nbytes = nc / CHAR_BIT * css; + if (p->g->sets == NULL) + p->g->sets = (cset *)malloc(nc * sizeof(cset)); + else + p->g->sets = (cset *)realloc((char *)p->g->sets, + nc * sizeof(cset)); + if (p->g->setbits == NULL) + p->g->setbits = (uch *)malloc(nbytes); + else { + p->g->setbits = (uch *)realloc((char *)p->g->setbits, + nbytes); + /* xxx this isn't right if setbits is now NULL */ + for (i = 0; i < no; i++) + p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); + } + if (p->g->sets != NULL && p->g->setbits != NULL) + (void) memset((char *)p->g->setbits + (nbytes - css), + 0, css); + else { + no = 0; + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + } + } + + assert(p->g->sets != NULL); /* xxx */ + cs = &p->g->sets[no]; + cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); + cs->mask = 1 << ((no) % CHAR_BIT); + cs->hash = 0; + cs->smultis = 0; + cs->multis = NULL; + + return(cs); +} + +/* + - freeset - free a now-unused set + == static void freeset(register struct parse *p, register cset *cs); + */ +static void +freeset(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register cset *top = &p->g->sets[p->g->ncsets]; + register size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + CHsub(cs, i); + if (cs == top-1) /* recover only the easy case */ + p->g->ncsets--; +} + +/* + - freezeset - final processing on a set of characters + == static int freezeset(register struct parse *p, register cset *cs); + * + * The main task here is merging identical sets. This is usually a waste + * of time (although the hash code minimizes the overhead), but can win + * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash + * is done using addition rather than xor -- all ASCII [aA] sets xor to + * the same value! + */ +static int /* set number */ +freezeset(p, cs) +register struct parse *p; +register cset *cs; +{ + register uch h = cs->hash; + register int i; + register cset *top = &p->g->sets[p->g->ncsets]; + register cset *cs2; + register size_t css = (size_t)p->g->csetsize; + + /* look for an earlier one which is the same */ + for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) + if (cs2->hash == h && cs2 != cs) { + /* maybe */ + for (i = 0; i < css; i++) + if (!!CHIN(cs2, i) != !!CHIN(cs, i)) + break; /* no */ + if (i == css) + break; /* yes */ + } + + if (cs2 < top) { /* found one */ + freeset(p, cs); + cs = cs2; + } + + return((int)(cs - p->g->sets)); +} + +/* + - firstch - return first character in a set (which must have at least one) + == static int firstch(register struct parse *p, register cset *cs); + */ +static int /* character; there is no "none" value */ +firstch(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + return((char)i); + assert(never); + return(0); /* arbitrary */ +} + +/* + - nch - number of characters in a set + == static int nch(register struct parse *p, register cset *cs); + */ +static int +nch(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register size_t css = (size_t)p->g->csetsize; + register int n = 0; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + n++; + return(n); +} + +/* + - mcadd - add a collating element to a cset + == static void mcadd(register struct parse *p, register cset *cs, \ + == register char *cp); + */ +static void +mcadd(p, cs, cp) +register struct parse *p; +register cset *cs; +register char *cp; +{ + register size_t oldend = cs->smultis; + + cs->smultis += strlen(cp) + 1; + if (cs->multis == NULL) + cs->multis = malloc(cs->smultis); + else + cs->multis = realloc(cs->multis, cs->smultis); + if (cs->multis == NULL) { + SETERROR(REG_ESPACE); + return; + } + + (void) strcpy(cs->multis + oldend - 1, cp); + cs->multis[cs->smultis - 1] = '\0'; +} + +/* + - mcsub - subtract a collating element from a cset + == static void mcsub(register cset *cs, register char *cp); + */ +static void +mcsub(cs, cp) +register cset *cs; +register char *cp; +{ + register char *fp = mcfind(cs, cp); + register size_t len = strlen(fp); + + assert(fp != NULL); + (void) memmove(fp, fp + len + 1, + cs->smultis - (fp + len + 1 - cs->multis)); + cs->smultis -= len; + + if (cs->smultis == 0) { + free(cs->multis); + cs->multis = NULL; + return; + } + + cs->multis = realloc(cs->multis, cs->smultis); + assert(cs->multis != NULL); +} + +/* + - mcin - is a collating element in a cset? + == static int mcin(register cset *cs, register char *cp); + */ +static int +mcin(cs, cp) +register cset *cs; +register char *cp; +{ + return(mcfind(cs, cp) != NULL); +} + +/* + - mcfind - find a collating element in a cset + == static char *mcfind(register cset *cs, register char *cp); + */ +static char * +mcfind(cs, cp) +register cset *cs; +register char *cp; +{ + register char *p; + + if (cs->multis == NULL) + return(NULL); + for (p = cs->multis; *p != '\0'; p += strlen(p) + 1) + if (strcmp(cp, p) == 0) + return(p); + return(NULL); +} + +/* + - mcinvert - invert the list of collating elements in a cset + == static void mcinvert(register struct parse *p, register cset *cs); + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +static void +mcinvert(p, cs) +register struct parse *p; +register cset *cs; +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - mccase - add case counterparts of the list of collating elements in a cset + == static void mccase(register struct parse *p, register cset *cs); + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +static void +mccase(p, cs) +register struct parse *p; +register cset *cs; +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - isinsets - is this character in any sets? + == static int isinsets(register struct re_guts *g, int c); + */ +static int /* predicate */ +isinsets(g, c) +register struct re_guts *g; +int c; +{ + register uch *col; + register int i; + register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + register unsigned uc = (unsigned char)c; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc] != 0) + return(1); + return(0); +} + +/* + - samesets - are these two characters in exactly the same sets? + == static int samesets(register struct re_guts *g, int c1, int c2); + */ +static int /* predicate */ +samesets(g, c1, c2) +register struct re_guts *g; +int c1; +int c2; +{ + register uch *col; + register int i; + register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + register unsigned uc1 = (unsigned char)c1; + register unsigned uc2 = (unsigned char)c2; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc1] != col[uc2]) + return(0); + return(1); +} + +/* + - categorize - sort out character categories + == static void categorize(struct parse *p, register struct re_guts *g); + */ +static void +categorize(p, g) +struct parse *p; +register struct re_guts *g; +{ + register cat_t *cats = g->categories; + register int c; + register int c2; + register cat_t cat; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (cats[c] == 0 && isinsets(g, c)) { + cat = g->ncategories++; + cats[c] = cat; + for (c2 = c+1; c2 <= CHAR_MAX; c2++) + if (cats[c2] == 0 && samesets(g, c, c2)) + cats[c2] = cat; + } +} + +/* + - dupl - emit a duplicate of a bunch of sops + == static sopno dupl(register struct parse *p, sopno start, sopno finish); + */ +static sopno /* start of duplicate */ +dupl(p, start, finish) +register struct parse *p; +sopno start; /* from here */ +sopno finish; /* to this less one */ +{ + register sopno ret = HERE(); + register sopno len = finish - start; + + assert(finish >= start); + if (len == 0) + return(ret); + enlarge(p, p->ssize + len); /* this many unexpected additions */ + assert(p->ssize >= p->slen + len); + (void) memcpy((char *)(p->strip + p->slen), + (char *)(p->strip + start), (size_t)len*sizeof(sop)); + p->slen += len; + return(ret); +} + +/* + - doemit - emit a strip operator + == static void doemit(register struct parse *p, sop op, size_t opnd); + * + * It might seem better to implement this as a macro with a function as + * hard-case backup, but it's just too big and messy unless there are + * some changes to the data structures. Maybe later. + */ +static void +doemit(p, op, opnd) +register struct parse *p; +sop op; +size_t opnd; +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* deal with oversize operands ("can't happen", more or less) */ + assert(opnd < 1<slen >= p->ssize) + enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ + assert(p->slen < p->ssize); + + /* finally, it's all reduced to the easy case */ + p->strip[p->slen++] = SOP(op, opnd); +} + +/* + - doinsert - insert a sop into the strip + == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); + */ +static void +doinsert(p, op, opnd, pos) +register struct parse *p; +sop op; +size_t opnd; +sopno pos; +{ + register sopno sn; + register sop s; + register int i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + sn = HERE(); + EMIT(op, opnd); /* do checks, ensure space */ + assert(HERE() == sn+1); + s = p->strip[sn]; + + /* adjust paren pointers */ + assert(pos > 0); + for (i = 1; i < NPAREN; i++) { + if (p->pbegin[i] >= pos) { + p->pbegin[i]++; + } + if (p->pend[i] >= pos) { + p->pend[i]++; + } + } + + memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], + (HERE()-pos-1)*sizeof(sop)); + p->strip[pos] = s; +} + +/* + - dofwd - complete a forward reference + == static void dofwd(register struct parse *p, sopno pos, sop value); + */ +static void +dofwd(p, pos, value) +register struct parse *p; +register sopno pos; +sop value; +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + assert(value < 1<strip[pos] = OP(p->strip[pos]) | value; +} + +/* + - enlarge - enlarge the strip + == static void enlarge(register struct parse *p, sopno size); + */ +static void +enlarge(p, size) +register struct parse *p; +register sopno size; +{ + register sop *sp; + + if (p->ssize >= size) + return; + + sp = (sop *)realloc(p->strip, size*sizeof(sop)); + if (sp == NULL) { + SETERROR(REG_ESPACE); + return; + } + p->strip = sp; + p->ssize = size; +} + +/* + - stripsnug - compact the strip + == static void stripsnug(register struct parse *p, register struct re_guts *g); + */ +static void +stripsnug(p, g) +register struct parse *p; +register struct re_guts *g; +{ + g->nstates = p->slen; + g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); + if (g->strip == NULL) { + SETERROR(REG_ESPACE); + g->strip = p->strip; + } +} + +/* + - findmust - fill in must and mlen with longest mandatory literal string + == static void findmust(register struct parse *p, register struct re_guts *g); + * + * This algorithm could do fancy things like analyzing the operands of | + * for common subsequences. Someday. This code is simple and finds most + * of the interesting cases. + * + * Note that must and mlen got initialized during setup. + */ +static void +findmust(p, g) +struct parse *p; +register struct re_guts *g; +{ + register sop *scan; + sop *start; + register sop *newstart; + register sopno newlen; + register sop s; + register char *cp; + register sopno i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* find the longest OCHAR sequence in strip */ + newlen = 0; + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OCHAR: /* sequence member */ + if (newlen == 0) /* new sequence */ + newstart = scan - 1; + newlen++; + break; + case OPLUS_: /* things that don't break one */ + case OLPAREN: + case ORPAREN: + break; + case OQUEST_: /* things that must be skipped */ + case OCH_: + scan--; + do { + scan += OPND(s); + s = *scan; + /* assert() interferes w debug printouts */ + if (OP(s) != O_QUEST && OP(s) != O_CH && + OP(s) != OOR2) { + g->iflags |= BAD; + return; + } + } while (OP(s) != O_QUEST && OP(s) != O_CH); + /* fallthrough */ + default: /* things that break a sequence */ + if (newlen > g->mlen) { /* ends one */ + start = newstart; + g->mlen = newlen; + } + newlen = 0; + break; + } + } while (OP(s) != OEND); + + if (g->mlen == 0) /* there isn't one */ + return; + + /* turn it into a character string */ + g->must = malloc((size_t)g->mlen + 1); + if (g->must == NULL) { /* argh; just forget it */ + g->mlen = 0; + return; + } + cp = g->must; + scan = start; + for (i = g->mlen; i > 0; i--) { + while (OP(s = *scan++) != OCHAR) + continue; + assert(cp < g->must + g->mlen); + *cp++ = (char)OPND(s); + } + assert(cp == g->must + g->mlen); + *cp++ = '\0'; /* just on general principles */ +} + +/* + - pluscount - count + nesting + == static sopno pluscount(register struct parse *p, register struct re_guts *g); + */ +static sopno /* nesting depth */ +pluscount(p, g) +struct parse *p; +register struct re_guts *g; +{ + register sop *scan; + register sop s; + register sopno plusnest = 0; + register sopno maxnest = 0; + + if (p->error != 0) + return(0); /* there may not be an OEND */ + + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OPLUS_: + plusnest++; + break; + case O_PLUS: + if (plusnest > maxnest) + maxnest = plusnest; + plusnest--; + break; + } + } while (OP(s) != OEND); + if (plusnest != 0) + g->iflags |= BAD; + return(maxnest); +} diff --git a/sys/amiga/regex/regerror.c b/sys/amiga/regex/regerror.c new file mode 100755 index 000000000..54c1333d9 --- /dev/null +++ b/sys/amiga/regex/regerror.c @@ -0,0 +1,186 @@ +/* $NetBSD: regerror.c,v 1.4 1995/02/27 13:29:20 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)regerror.c 8.4 (Berkeley) 3/20/94 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94"; +#else +static char rcsid[] = "$NetBSD: regerror.c,v 1.4 1995/02/27 13:29:20 cgd Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regerror.c === */ +static char *regatoi __P((const regex_t *preg, char *localbuf)); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ +/* + = #define REG_NOMATCH 1 + = #define REG_BADPAT 2 + = #define REG_ECOLLATE 3 + = #define REG_ECTYPE 4 + = #define REG_EESCAPE 5 + = #define REG_ESUBREG 6 + = #define REG_EBRACK 7 + = #define REG_EPAREN 8 + = #define REG_EBRACE 9 + = #define REG_BADBR 10 + = #define REG_ERANGE 11 + = #define REG_ESPACE 12 + = #define REG_BADRPT 13 + = #define REG_EMPTY 14 + = #define REG_ASSERT 15 + = #define REG_INVARG 16 + = #define REG_ATOI 255 // convert name to number (!) + = #define REG_ITOA 0400 // convert number to name (!) + */ +static struct rerr { + int code; + char *name; + char *explain; +} rerrs[] = { + REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match", + REG_BADPAT, "REG_BADPAT", "invalid regular expression", + REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element", + REG_ECTYPE, "REG_ECTYPE", "invalid character class", + REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)", + REG_ESUBREG, "REG_ESUBREG", "invalid backreference number", + REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced", + REG_EPAREN, "REG_EPAREN", "parentheses not balanced", + REG_EBRACE, "REG_EBRACE", "braces not balanced", + REG_BADBR, "REG_BADBR", "invalid repetition count(s)", + REG_ERANGE, "REG_ERANGE", "invalid character range", + REG_ESPACE, "REG_ESPACE", "out of memory", + REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid", + REG_EMPTY, "REG_EMPTY", "empty (sub)expression", + REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug", + REG_INVARG, "REG_INVARG", "invalid argument to regex routine", + 0, "", "*** unknown regexp error code ***", +}; + +/* + - regerror - the interface to error numbers + = extern size_t regerror(int, const regex_t *, char *, size_t); + */ +/* ARGSUSED */ +size_t +regerror(errcode, preg, errbuf, errbuf_size) +int errcode; +const regex_t *preg; +char *errbuf; +size_t errbuf_size; +{ + register struct rerr *r; + register size_t len; + register int target = errcode &~ REG_ITOA; + register char *s; + char convbuf[50]; + + if (errcode == REG_ATOI) + s = regatoi(preg, convbuf); + else { + for (r = rerrs; r->code != 0; r++) + if (r->code == target) + break; + + if (errcode®_ITOA) { + if (r->code != 0) + (void) strcpy(convbuf, r->name); + else + sprintf(convbuf, "REG_0x%x", target); + assert(strlen(convbuf) < sizeof(convbuf)); + s = convbuf; + } else + s = r->explain; + } + + len = strlen(s) + 1; + if (errbuf_size > 0) { + if (errbuf_size > len) + (void) strcpy(errbuf, s); + else { + (void) strncpy(errbuf, s, errbuf_size-1); + errbuf[errbuf_size-1] = '\0'; + } + } + + return(len); +} + +/* + - regatoi - internal routine to implement REG_ATOI + == static char *regatoi(const regex_t *preg, char *localbuf); + */ +static char * +regatoi(preg, localbuf) +const regex_t *preg; +char *localbuf; +{ + register struct rerr *r; + register size_t siz; + register char *p; + + for (r = rerrs; r->code != 0; r++) + if (strcmp(r->name, preg->re_endp) == 0) + break; + if (r->code == 0) + return("0"); + + sprintf(localbuf, "%d", r->code); + return(localbuf); +} diff --git a/sys/amiga/regex/regex2.h b/sys/amiga/regex/regex2.h new file mode 100755 index 000000000..901a6393b --- /dev/null +++ b/sys/amiga/regex/regex2.h @@ -0,0 +1,175 @@ +/* $NetBSD: regex2.h,v 1.5 1995/02/27 13:29:40 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)regex2.h 8.4 (Berkeley) 3/20/94 + */ + +/* + * First, the stuff that ends up in the outside-world include file + = typedef off_t regoff_t; + = typedef struct { + = int re_magic; + = size_t re_nsub; // number of parenthesized subexpressions + = const char *re_endp; // end pointer for REG_PEND + = struct re_guts *re_g; // none of your business :-) + = } regex_t; + = typedef struct { + = regoff_t rm_so; // start of match + = regoff_t rm_eo; // end of match + = } regmatch_t; + */ +/* + * internals of regex_t + */ +#define MAGIC1 ((('r'^0200)<<8) | 'e') + +/* + * The internal representation is a *strip*, a sequence of + * operators ending with an endmarker. (Some terminology etc. is a + * historical relic of earlier versions which used multiple strips.) + * Certain oddities in the representation are there to permit running + * the machinery backwards; in particular, any deviation from sequential + * flow must be marked at both its source and its destination. Some + * fine points: + * + * - OPLUS_ and O_PLUS are *inside* the loop they create. + * - OQUEST_ and O_QUEST are *outside* the bypass they create. + * - OCH_ and O_CH are *outside* the multi-way branch they create, while + * OOR1 and OOR2 are respectively the end and the beginning of one of + * the branches. Note that there is an implicit OOR2 following OCH_ + * and an implicit OOR1 preceding O_CH. + * + * In state representations, an operator's bit is on to signify a state + * immediately *preceding* "execution" of that operator. + */ +typedef unsigned long sop; /* strip operator */ +typedef long sopno; +#define OPRMASK 0xf8000000 +#define OPDMASK 0x07ffffff +#define OPSHIFT ((unsigned)27) +#define OP(n) ((n)&OPRMASK) +#define OPND(n) ((n)&OPDMASK) +#define SOP(op, opnd) ((op)|(opnd)) +/* operators meaning operand */ +/* (back, fwd are offsets) */ +#define OEND (1< uch [csetsize] */ + uch mask; /* bit within array */ + uch hash; /* hash code */ + size_t smultis; + char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ +} cset; +/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ +#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) +#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) +#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) +#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */ +#define MCsub(p, cs, cp) mcsub(p, cs, cp) +#define MCin(p, cs, cp) mcin(p, cs, cp) + +/* stuff for character categories */ +typedef unsigned char cat_t; + +/* + * main compiled-expression structure + */ +struct re_guts { + int magic; +# define MAGIC2 ((('R'^0200)<<8)|'E') + sop *strip; /* malloced area for strip */ + int csetsize; /* number of bits in a cset vector */ + int ncsets; /* number of csets in use */ + cset *sets; /* -> cset [ncsets] */ + uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ + int cflags; /* copy of regcomp() cflags argument */ + sopno nstates; /* = number of sops */ + sopno firststate; /* the initial OEND (normally 0) */ + sopno laststate; /* the final OEND */ + int iflags; /* internal flags */ +# define USEBOL 01 /* used ^ */ +# define USEEOL 02 /* used $ */ +# define BAD 04 /* something wrong */ + int nbol; /* number of ^ used */ + int neol; /* number of $ used */ + int ncategories; /* how many character categories */ + cat_t *categories; /* ->catspace[-CHAR_MIN] */ + char *must; /* match must contain this string */ + int mlen; /* length of must */ + size_t nsub; /* copy of re_nsub */ + int backrefs; /* does it use back references? */ + sopno nplus; /* how deep does it nest +s? */ + /* catspace must be last */ + cat_t catspace[1]; /* actually [NC] */ +}; + +/* misc utilities */ +#define OUT (CHAR_MAX+1) /* a non-character value */ +#define ISWORD(c) (isalnum(c) || (c) == '_') diff --git a/sys/amiga/regex/regexec.c b/sys/amiga/regex/regexec.c new file mode 100755 index 000000000..3b8ef5341 --- /dev/null +++ b/sys/amiga/regex/regexec.c @@ -0,0 +1,187 @@ +/* $NetBSD: regexec.c,v 1.6 1995/02/27 13:29:48 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)regexec.c 8.3 (Berkeley) 3/20/94 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94"; +#else +static char rcsid[] = "$NetBSD: regexec.c,v 1.6 1995/02/27 13:29:48 cgd Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * the outer shell of regexec() + * + * This file includes engine.h *twice*, after muchos fiddling with the + * macros that code uses. This lets the same code operate on two different + * representations for state sets. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "regex2.h" + +static int nope = 0; /* for use in asserts; shuts lint up */ + +/* macros for manipulating states, small version */ +#define states long +#define states1 states /* for later use in regexec() decision */ +#define CLEAR(v) ((v) = 0) +#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n))) +#define SET1(v, n) ((v) |= (unsigned long)1 << (n)) +#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0) +#define ASSIGN(d, s) ((d) = (s)) +#define EQ(a, b) ((a) == (b)) +#define STATEVARS long dummy /* dummy version */ +#define STATESETUP(m, n) /* nothing */ +#define STATETEARDOWN(m) /* nothing */ +#define SETUP(v) ((v) = 0) +#define onestate long +#define INIT(o, n) ((o) = (unsigned long)1 << (n)) +#define INC(o) ((o) = (unsigned long)(o) << 1) +#define ISSTATEIN(v, o) (((v) & (o)) != 0) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n)) +#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n)) +#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0) +/* function names */ +#define SNAMES /* engine.h looks after details */ + +#include "engine.h" + +/* now undo things */ +#undef states +#undef CLEAR +#undef SET0 +#undef SET1 +#undef ISSET +#undef ASSIGN +#undef EQ +#undef STATEVARS +#undef STATESETUP +#undef STATETEARDOWN +#undef SETUP +#undef onestate +#undef INIT +#undef INC +#undef ISSTATEIN +#undef FWD +#undef BACK +#undef ISSETBACK +#undef SNAMES + +/* macros for manipulating states, large version */ +#define states char * +#define CLEAR(v) memset(v, 0, m->g->nstates) +#define SET0(v, n) ((v)[n] = 0) +#define SET1(v, n) ((v)[n] = 1) +#define ISSET(v, n) ((v)[n]) +#define ASSIGN(d, s) memcpy(d, s, m->g->nstates) +#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) +#define STATEVARS long vn; char *space +#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ + if ((m)->space == NULL) return(REG_ESPACE); \ + (m)->vn = 0; } +#define STATETEARDOWN(m) { free((m)->space); } +#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) +#define onestate long +#define INIT(o, n) ((o) = (n)) +#define INC(o) ((o)++) +#define ISSTATEIN(v, o) ((v)[o]) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) +#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) +#define ISSETBACK(v, n) ((v)[here - (n)]) +/* function names */ +#define LNAMES /* flag */ + +#include "engine.h" + +/* + - regexec - interface for matching + = extern int regexec(const regex_t *, const char *, size_t, \ + = regmatch_t [], int); + = #define REG_NOTBOL 00001 + = #define REG_NOTEOL 00002 + = #define REG_STARTEND 00004 + = #define REG_TRACE 00400 // tracing of execution + = #define REG_LARGE 01000 // force large representation + = #define REG_BACKR 02000 // force use of backref code + * + * We put this here so we can exploit knowledge of the state representation + * when choosing which matcher to call. Also, by this point the matchers + * have been prototyped. + */ +int /* 0 success, REG_NOMATCH failure */ +regexec(preg, string, nmatch, pmatch, eflags) +const regex_t *preg; +const char *string; +size_t nmatch; +regmatch_t pmatch[]; +int eflags; +{ + register struct re_guts *g = preg->re_g; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) +#endif + + if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) + return(REG_BADPAT); + assert(!(g->iflags&BAD)); + if (g->iflags&BAD) /* backstop for no-debug case */ + return(REG_BADPAT); + eflags = GOODFLAGS(eflags); + + if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) + return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); + else + return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); +} diff --git a/sys/amiga/regex/regfree.c b/sys/amiga/regex/regfree.c new file mode 100755 index 000000000..e01e30627 --- /dev/null +++ b/sys/amiga/regex/regfree.c @@ -0,0 +1,86 @@ +/* $NetBSD: regfree.c,v 1.4 1995/02/27 13:29:56 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)regfree.c 8.3 (Berkeley) 3/20/94 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94"; +#else +static char rcsid[] = "$NetBSD: regfree.c,v 1.4 1995/02/27 13:29:56 cgd Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include + +#include "utils.h" +#include "regex2.h" + +/* + - regfree - free everything + = extern void regfree(regex_t *); + */ +void +regfree(preg) +regex_t *preg; +{ + register struct re_guts *g; + + if (preg->re_magic != MAGIC1) /* oops */ + return; /* nice to complain, but hard */ + + g = preg->re_g; + if (g == NULL || g->magic != MAGIC2) /* oops again */ + return; + preg->re_magic = 0; /* mark it invalid */ + g->magic = 0; /* mark it invalid */ + + if (g->strip != NULL) + free((char *)g->strip); + if (g->sets != NULL) + free((char *)g->sets); + if (g->setbits != NULL) + free((char *)g->setbits); + if (g->must != NULL) + free(g->must); + free((char *)g); +} diff --git a/sys/amiga/regex/utils.h b/sys/amiga/regex/utils.h new file mode 100755 index 000000000..2f372ce29 --- /dev/null +++ b/sys/amiga/regex/utils.h @@ -0,0 +1,59 @@ +/* $NetBSD: utils.h,v 1.5 1995/02/27 13:29:59 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * 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. + * + * @(#)utils.h 8.3 (Berkeley) 3/20/94 + */ + +/* utility definitions */ +#define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */ +#define INFINITY (DUPMAX + 1) +#define NC (CHAR_MAX - CHAR_MIN + 1) +typedef unsigned char uch; + +/* switch off assertions (if not already off) if no REDEBUG */ +#ifndef REDEBUG +#ifndef NDEBUG +#define NDEBUG /* no assertions please */ +#endif +#endif +#include + +/* for old systems with bcopy() but no memmove() */ +#ifdef USEBCOPY +#define memmove(d, s, c) bcopy(s, d, c) +#endif From cb0b11be112a2ddace1a56a65eb29f03bcc6d8bc Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Mon, 23 Mar 2026 20:50:14 +0100 Subject: [PATCH 6/8] Add portable utilities for creating tiles, add AmigaFont to symbols - bmp2iff_host: convert nhtiles.bmp to Amiga IFF tile files. Uses the AMIV UI palette in pens 0-15, remaining pens filled with tile colors sorted by frequency. Usage: bmp2iff_host -planes N input.bmp output.iff - xpm2iff_host: convert XPM to IFF for tomb.iff (RIP screen). Adapted from xpm2iff.c, Copyright (c) 1995 Gregg Wonderly. - Auto-select tiles32.iff (5 planes) or tiles16.iff (4 planes) based on screen color depth at runtime. - Fix NO_GLYPH in amiv_lprint_glyph: return early to prevent blitting with uninitialised data (caused black spots). - Add AmigaFont symbol set to dat/symbols for AMII text mode. --- dat/symbols | 78 +++++ sys/amiga/README.amiga | 2 +- sys/amiga/bmp2iff_host.c | 480 ++++++++++++++++++++++++++ sys/amiga/xpm2iff_host.c | 346 +++++++++++++++++++ sys/unix/hints/include/cross-pre2.370 | 2 +- 5 files changed, 906 insertions(+), 2 deletions(-) create mode 100644 sys/amiga/bmp2iff_host.c create mode 100644 sys/amiga/xpm2iff_host.c diff --git a/dat/symbols b/dat/symbols index af6c04ade..f2bc486fa 100644 --- a/dat/symbols +++ b/dat/symbols @@ -895,4 +895,82 @@ start: Enhanced1 G_trwall_mines: U+251C/113-126-142 finish +start: AmigaFont + Description: Amiga hack.font line-drawing and effect characters + # Dungeon features + S_stone: \x20 + S_vwall: \xc0 + S_hwall: \xc1 + S_tlcorn: \xc2 + S_trcorn: \xc3 + S_blcorn: \xc4 + S_brcorn: \xc5 + S_crwall: \xc6 + S_tuwall: \xd8 + S_tdwall: \xd6 + S_tlwall: \xd7 + S_trwall: \xd5 + S_ndoor: \xd9 + S_vodoor: \x91 + S_hodoor: \x92 + S_vcdoor: \x93 + S_hcdoor: \x94 + S_bars: '#' + S_tree: '#' + S_room: '.' + S_darkroom: \x20 + S_corr: \xe5 + S_litcorr: \xe5 + S_upstair: '<' + S_dnstair: '>' + S_upladder: '<' + S_dnladder: '>' + S_altar: '_' + S_grave: \x5c + S_throne: '#' + S_sink: '{' + S_fountain: '}' + S_pool: '*' + S_ice: '}' + S_lava: '*' + S_vodbridge: '*' + S_hodbridge: '#' + S_vcdbridge: '#' + S_hcdbridge: '.' + S_air: '#' + S_cloud: '}' + # Traps: all default to '^' except web + S_web: '"' + # Effects + S_vbeam: \xf1 + S_hbeam: \xf0 + S_lslant: \xf2 + S_rslant: \xf3 + S_digbeam: '*' + S_flashbeam: '!' + S_boomleft: '{' + S_boomright: '}' + S_ss1: '@' + S_ss2: '&' + S_ss3: '*' + S_ss4: '#' + S_sw_tl: \xf4 + S_sw_tc: \xf5 + S_sw_tr: \xf6 + S_sw_ml: \xf7 + S_sw_mr: \xef + S_sw_bl: \xf8 + S_sw_bc: \xf9 + S_sw_br: \xfa + S_explode1: \xe6 + S_explode2: \xea + S_explode3: \xe7 + S_explode4: \xec + S_explode5: \xd4 + S_explode6: \xed + S_explode7: \xe8 + S_explode8: \xeb + S_explode9: \xe9 +finish + # symbols EOF diff --git a/sys/amiga/README.amiga b/sys/amiga/README.amiga index 165501014..8eda92c31 100644 --- a/sys/amiga/README.amiga +++ b/sys/amiga/README.amiga @@ -73,8 +73,8 @@ Cross-compilation from Linux using bebbo's m68k-amigaos-gcc toolchain # Install toolchain to /opt/amiga # Clone NetHack 3.7 source cd NetHack - make fetch-lua sys/unix/setup.sh sys/unix/hints/linux.370 + make fetch-lua make CROSS_TO_AMIGA=1 all make CROSS_TO_AMIGA=1 package diff --git a/sys/amiga/bmp2iff_host.c b/sys/amiga/bmp2iff_host.c new file mode 100644 index 000000000..154335297 --- /dev/null +++ b/sys/amiga/bmp2iff_host.c @@ -0,0 +1,480 @@ +/* + * bmp2iff_host.c - Convert a BMP to Amiga BMAP IFF. + * Copyright (c) 2026 by Ingo Paschke. + * NetHack may be freely redistributed. See license for details. + * + * IFF BMAP format matches sys/amiga/xpm2iff.c by Gregg Wonderly. + * + * Usage: bmp2iff_host -planes N input.bmp output.iff + * + * This is a HOST tool -- runs on the build machine. + */ + +#include +#include +#include +#include + +#define TILE_X 16 +#define TILE_Y 16 + +#pragma pack(push,1) +typedef struct { + uint16_t bfType; + uint32_t bfSize; + uint16_t bfReserved1, bfReserved2; + uint32_t bfOffBits; +} BMPFILEHEADER; + +typedef struct { + uint32_t biSize; + int32_t biWidth, biHeight; + uint16_t biPlanes, biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + int32_t biXPelsPerMeter, biYPelsPerMeter; + uint32_t biClrUsed, biClrImportant; +} BMPINFOHEADER; +#pragma pack(pop) + +typedef struct { + uint8_t r, g, b; +} RGB; + +/* --------------------------------------------------------- */ +/* Fixed 16-color AMIV UI palette */ +/* Must match amiv_init_map[] in winami.c */ +/* --------------------------------------------------------- */ + +static const RGB amiv_pal[16] = { + {0x00,0x00,0x00}, /* 0 black */ + {0xFF,0xFF,0xFF}, /* 1 white */ + {0x00,0xBB,0xFF}, /* 2 cyan */ + {0xFF,0x66,0x00}, /* 3 orange */ + {0x00,0x00,0xFF}, /* 4 blue */ + {0x00,0x99,0x00}, /* 5 green */ + {0x66,0x99,0xBB}, /* 6 grey */ + {0xFF,0x00,0x00}, /* 7 red */ + {0x66,0xFF,0x00}, /* 8 ltgreen */ + {0xFF,0xFF,0x00}, /* 9 yellow */ + {0xFF,0x00,0xFF}, /* 10 magenta */ + {0x99,0x44,0x00}, /* 11 brown */ + {0x44,0x66,0x66}, /* 12 greyblue */ + {0xCC,0x44,0x00}, /* 13 ltbrown */ + {0xDD,0xDD,0xBB}, /* 14 ltgrey */ + {0xFF,0xBB,0x99}, /* 15 peach */ +}; + +/* --------------------------------------------------------- */ +/* Colour helpers */ +/* --------------------------------------------------------- */ + +static int +coldist(const RGB *a, const RGB *b) +{ + int dr = a->r - b->r; + int dg = a->g - b->g; + int db = a->b - b->b; + return dr*dr + dg*dg + db*db; +} + +static int +nearest(const RGB *c, const RGB *pal, int n) +{ + int best = 0, bestd = 0x7fffffff, i; + for (i = 0; i < n; i++) { + int d = coldist(c, &pal[i]); + if (d < bestd) { bestd = d; best = i; } + } + return best; +} + +/* --------------------------------------------------------- */ +/* IFF output */ +/* --------------------------------------------------------- */ + +static FILE *iff_fp; + +static void +wr32(uint32_t v) +{ + uint8_t b[4] = { v>>24, v>>16, v>>8, v }; + fwrite(b, 1, 4, iff_fp); +} + +static void +wr_chunk(const char *id, const void *d, uint32_t len) +{ + fwrite(id, 1, 4, iff_fp); + wr32(len); + fwrite(d, 1, len, iff_fp); + if (len & 1) fputc(0, iff_fp); +} + +static void +iff_write(int nplanes, int ncolors, uint8_t *cmap, + int w, int h, uint8_t **planes, + int ntiles, int across, int down) +{ + long spos; + uint32_t plsz = (uint32_t)(w / 8) * h; + int i; + + fwrite("FORM", 1, 4, iff_fp); + spos = ftell(iff_fp); + wr32(0); + fwrite("BMAP", 1, 4, iff_fp); + + /* BMHD */ + { + uint8_t bm[20]; + memset(bm, 0, 20); + bm[0] = w >> 8; bm[1] = w; + bm[2] = h >> 8; bm[3] = h; + bm[8] = (uint8_t)nplanes; + bm[14] = 100; bm[15] = 100; + wr_chunk("BMHD", bm, 20); + } + + /* CAMG */ + { + uint8_t c[4] = {0,0,0x80,0x04}; + wr_chunk("CAMG", c, 4); + } + + /* CMAP */ + wr_chunk("CMAP", cmap, (uint32_t)ncolors * 3); + + /* PDAT */ + { + uint8_t pd[28], *p = pd; + uint32_t v[7]; + v[0] = nplanes; + v[1] = plsz; + v[2] = across; + v[3] = down; + v[4] = ntiles; + v[5] = TILE_X; + v[6] = TILE_Y; + for (i = 0; i < 7; i++) { + p[0] = (v[i]>>24); p[1] = (v[i]>>16); + p[2] = (v[i]>> 8); p[3] = v[i]; + p += 4; + } + wr_chunk("PDAT", pd, 28); + } + + /* PLNE */ + fwrite("PLNE", 1, 4, iff_fp); + wr32(plsz * nplanes); + for (i = 0; i < nplanes; i++) + fwrite(planes[i], 1, plsz, iff_fp); + + /* fix FORM size */ + { + long end = ftell(iff_fp); + uint32_t sz = (uint32_t)(end - spos - 4); + fseek(iff_fp, spos, SEEK_SET); + wr32(sz); + fseek(iff_fp, 0, SEEK_END); + } +} + +/* --------------------------------------------------------- */ +/* Pixel-to-bitplane conversion */ +/* --------------------------------------------------------- */ + +static void +to_planes(uint8_t *pix, int w, int h, + int np, uint8_t **pl) +{ + int rb = w / 8; + int x, y, p; + + for (p = 0; p < np; p++) + memset(pl[p], 0, rb * h); + + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) { + uint8_t v = pix[y * w + x]; + int off = y * rb + x / 8; + int bit = 7 - (x & 7); + for (p = 0; p < np; p++) + if (v & (1 << p)) + pl[p][off] |= (1 << bit); + } +} + +/* --------------------------------------------------------- */ +/* Palette building */ +/* --------------------------------------------------------- */ + +/* + * Build an output palette of 'maxcol' entries: + * - slots 0-15: fixed AMIV UI colors + * - slots 16+: tile colors from the BMP + * + * Returns remap[0..nsrc-1] mapping BMP palette index + * to output palette index. + */ +static void +build_palette(const RGB *src, int nsrc, + const uint8_t *pix, int npix, + int maxcol, + RGB *out, int *remap) +{ + int freq[256] = {0}; + int order[256]; + int i, j, nfree, nuniq; + + /* count pixel frequency per BMP palette entry */ + for (i = 0; i < npix; i++) + freq[pix[i]]++; + + /* sort BMP colors by frequency (descending) */ + for (i = 0; i < nsrc; i++) order[i] = i; + for (i = 1; i < nsrc; i++) { + int k = order[i], kf = freq[k]; + j = i - 1; + while (j >= 0 && freq[order[j]] < kf) { + order[j+1] = order[j]; + j--; + } + order[j+1] = k; + } + + /* count unique colors actually used */ + nuniq = 0; + for (i = 0; i < nsrc; i++) + if (freq[i] > 0) nuniq++; + + /* first 16 slots are AMIV UI */ + for (i = 0; i < 16 && i < maxcol; i++) + out[i] = amiv_pal[i]; + for (i = 16; i < maxcol; i++) + memset(&out[i], 0, sizeof(RGB)); + + nfree = maxcol - 16; + if (nfree < 0) nfree = 0; + + /* + * Case 1: enough free slots for all unique colors. + * Assign each unique BMP color its own pen, exact + * AMIV matches share the UI pen. + */ + if (nuniq <= nfree) { + int next = 16; + for (i = 0; i < nsrc; i++) { + if (freq[i] == 0) { + remap[i] = 0; + continue; + } + /* exact match to an AMIV pen? */ + int best = nearest(&src[i], amiv_pal, 16); + if (coldist(&src[i], &amiv_pal[best]) == 0) { + remap[i] = best; + } else { + remap[i] = next; + out[next] = src[i]; + next++; + } + } + return; + } + + /* + * Case 2: more unique colors than free slots. + * - Direct/near AMIV matches use UI pens. + * - Remaining slots filled by most-frequent colors. + * - Leftovers mapped to nearest in final palette. + */ + { + int next = 16; + int assigned[256]; + memset(assigned, 0, sizeof(assigned)); + + /* pass 1: exact/near AMIV matches */ + for (i = 0; i < nsrc; i++) { + if (freq[i] == 0) { + remap[i] = 0; + assigned[i] = 1; + continue; + } + int best = nearest(&src[i], amiv_pal, 16); + int d = coldist(&src[i], &amiv_pal[best]); + if (d < 200) { /* near match threshold */ + remap[i] = best; + assigned[i] = 1; + } + } + + /* pass 2: fill free slots with most-frequent + * unassigned colors (order[] is freq-sorted) */ + for (i = 0; i < nsrc && next < maxcol; i++) { + int idx = order[i]; + if (assigned[idx] || freq[idx] == 0) + continue; + remap[idx] = next; + out[next] = src[idx]; + assigned[idx] = 1; + next++; + } + + /* pass 3: map remaining to nearest in palette */ + for (i = 0; i < nsrc; i++) { + if (!assigned[i]) + remap[i] = nearest(&src[i], out, next); + } + } +} + +/* --------------------------------------------------------- */ +/* Main */ +/* --------------------------------------------------------- */ + +int +main(int argc, char **argv) +{ + FILE *bmpfp; + BMPFILEHEADER fhdr; + BMPINFOHEADER ihdr; + RGB palette[256]; + int ncolors, img_w, img_h, rowstride; + uint8_t *bmpdata, *pixels; + int ntiles, across, down; + int nplanes, maxcol; + int i, y; + RGB outpal[256]; + int remap[256]; + uint8_t *remapped; + uint8_t *plane_data[8]; + uint8_t cmap_rgb[256 * 3]; + int planesize; + + /* parse args */ + if (argc != 5 + || strcmp(argv[1], "-planes") != 0) { + fprintf(stderr, + "Usage: %s -planes N input.bmp output.iff\n", + argv[0]); + return 1; + } + nplanes = atoi(argv[2]); + if (nplanes < 1 || nplanes > 8) { + fprintf(stderr, "planes must be 1-8\n"); + return 1; + } + maxcol = 1 << nplanes; + + /* read BMP */ + bmpfp = fopen(argv[3], "rb"); + if (!bmpfp) { perror(argv[3]); return 1; } + + if (fread(&fhdr, sizeof(fhdr), 1, bmpfp) != 1 + || fread(&ihdr, sizeof(ihdr), 1, bmpfp) != 1) { + fprintf(stderr, "Failed to read BMP header\n"); + return 1; + } + if (fhdr.bfType != 0x4D42) { + fprintf(stderr, "Not a BMP file\n"); + return 1; + } + if (ihdr.biBitCount != 8) { + fprintf(stderr, + "Expected 8-bit BMP, got %d-bit\n", + ihdr.biBitCount); + return 1; + } + + img_w = ihdr.biWidth; + img_h = abs(ihdr.biHeight); + ncolors = ihdr.biClrUsed ? ihdr.biClrUsed : 256; + if (ncolors > 256) ncolors = 256; + + /* read palette (BMP stores BGRx) */ + { + uint8_t raw[256][4]; + if (fread(raw, 4, ncolors, bmpfp) + != (size_t)ncolors) { + fprintf(stderr, "Failed to read palette\n"); + return 1; + } + for (i = 0; i < ncolors; i++) { + palette[i].r = raw[i][2]; + palette[i].g = raw[i][1]; + palette[i].b = raw[i][0]; + } + } + + /* read pixel data */ + rowstride = (img_w + 3) & ~3; + bmpdata = malloc(rowstride * img_h); + fseek(bmpfp, fhdr.bfOffBits, SEEK_SET); + if (fread(bmpdata, 1, rowstride * img_h, bmpfp) + != (size_t)(rowstride * img_h)) { + fprintf(stderr, "Failed to read pixel data\n"); + return 1; + } + fclose(bmpfp); + + /* flip bottom-up to top-down */ + pixels = malloc(img_w * img_h); + if (ihdr.biHeight > 0) { + for (y = 0; y < img_h; y++) + memcpy(pixels + y * img_w, + bmpdata + (img_h-1-y) * rowstride, + img_w); + } else { + for (y = 0; y < img_h; y++) + memcpy(pixels + y * img_w, + bmpdata + y * rowstride, img_w); + } + free(bmpdata); + + across = img_w / TILE_X; + down = img_h / TILE_Y; + ntiles = across * down; + + /* build palette and remap pixels */ + build_palette(palette, ncolors, + pixels, img_w * img_h, + maxcol, outpal, remap); + + remapped = malloc(img_w * img_h); + for (i = 0; i < img_w * img_h; i++) + remapped[i] = (uint8_t)remap[pixels[i]]; + + /* convert to bitplanes */ + planesize = (img_w / 8) * img_h; + for (i = 0; i < nplanes; i++) + plane_data[i] = calloc(1, planesize); + + to_planes(remapped, img_w, img_h, + nplanes, plane_data); + + /* build CMAP */ + for (i = 0; i < maxcol; i++) { + cmap_rgb[i*3+0] = outpal[i].r; + cmap_rgb[i*3+1] = outpal[i].g; + cmap_rgb[i*3+2] = outpal[i].b; + } + + /* write IFF */ + iff_fp = fopen(argv[4], "wb"); + if (!iff_fp) { perror(argv[4]); return 1; } + + iff_write(nplanes, maxcol, cmap_rgb, + img_w, img_h, plane_data, + ntiles, across, down); + fclose(iff_fp); + + printf("%s: %dx%d, %d colors (%d planes), " + "%d tiles\n", + argv[4], img_w, img_h, + maxcol, nplanes, ntiles); + + for (i = 0; i < nplanes; i++) free(plane_data[i]); + free(remapped); + free(pixels); + return 0; +} diff --git a/sys/amiga/xpm2iff_host.c b/sys/amiga/xpm2iff_host.c new file mode 100644 index 000000000..589d4f56f --- /dev/null +++ b/sys/amiga/xpm2iff_host.c @@ -0,0 +1,346 @@ +/* xpm2iff_host.c - host-side .xpm -> Amiga BMAP IFF converter. + * Copyright (c) 2026 by Ingo Paschke. + * NetHack may be freely redistributed. See license for details. + * + * Adapted from sys/amiga/xpm2iff.c, Copyright (c) 1995 by Gregg Wonderly. + * Rewritten for host-side cross-compilation using POSIX file I/O with + * explicit big-endian output instead of AmigaOS IFFParse library calls. + * + * Input: an XPM2 file, 1 char per pixel. + * Output: a BMAP IFF file readable by sys/amiga/winchar.c (tomb.iff). + */ + +#include +#include +#include +#include +#include + +/* ------------------------------------------------------------------ + * XPM screen descriptor and color translation table + * ------------------------------------------------------------------ */ + +static struct { + int Width; + int Height; + int Colors; + int BytesPerRow; +} XpmScreen; + +/* Translation table: indexed by the single XPM character code. + * slot = output palette index (0-based) + * flag = 1 if this entry is valid + * r,g,b = RGB components (0-255) */ +static struct { + unsigned char flag; + unsigned char r, g, b; + int slot; +} ttable[256]; + +/* ------------------------------------------------------------------ + * XPM parsing + * Adapted directly from sys/amiga/xpm2iff.c (already POSIX). + * ------------------------------------------------------------------ */ + +static FILE *xpmfh; + +#define XBUFSZ 2048 +static char xbuf[XBUFSZ]; + +/* Read the next quoted line from the XPM file. + * Returns a pointer to the content between the first pair of double-quotes, + * or NULL on EOF. Trailing ", and whitespace are stripped. */ +static char * +xpmgetline(void) +{ + char *bp; + do { + if (fgets(xbuf, XBUFSZ, xpmfh) == NULL) + return NULL; + } while (xbuf[0] != '"'); + + /* strip trailing <",> and whitespace */ + for (bp = xbuf; *bp; bp++) + ; + bp--; + while (isspace((unsigned char)*bp)) + bp--; + if (*bp == ',') + bp--; + if (*bp == '"') + bp--; + bp++; + *bp = '\0'; + + return &xbuf[1]; +} + +/* Open an XPM file and parse its header + color table. + * Populates XpmScreen and ttable[]. + * Returns 1 on success, 0 on failure. */ +static int +fopen_xpm_file(const char *fn) +{ + int temp; + char *xb; + + xpmfh = fopen(fn, "r"); + if (!xpmfh) + return 0; + + /* read dimensions header: "W H Colors 1" */ + xb = xpmgetline(); + if (!xb) + return 0; + if (sscanf(xb, "%d %d %d %d", + &XpmScreen.Width, &XpmScreen.Height, + &XpmScreen.Colors, &temp) != 4) + return 0; + if (temp != 1) { + fprintf(stderr, "xpm2iff_host: only 1 char/pixel XPM files supported\n"); + return 0; + } + + /* read color map: "%c c #rrggbb" */ + { + int ccount = 0; + while (ccount < XpmScreen.Colors) { + char idx; + int r, g, b; + xb = xpmgetline(); + if (!xb) + return 0; + if (sscanf(xb, "%c c #%2x%2x%2x", &idx, &r, &g, &b) != 4) { + fprintf(stderr, "xpm2iff_host: bad color entry: %s\n", xb); + return 0; + } + ttable[(unsigned char)idx].flag = 1; + ttable[(unsigned char)idx].r = (unsigned char)r; + ttable[(unsigned char)idx].g = (unsigned char)g; + ttable[(unsigned char)idx].b = (unsigned char)b; + ttable[(unsigned char)idx].slot = ccount; + ccount++; + } + } + return 1; +} + +/* ------------------------------------------------------------------ + * Bitplane packing + * ------------------------------------------------------------------ */ + +static char **planes; + +#define SETBIT(plane, plane_offset, col, value) \ + do { \ + if (value) \ + planes[plane][plane_offset + ((col) / 8)] \ + |= (char)(1 << (7 - ((col) & 7))); \ + } while (0) + +static void +conv_image(int nplanes) +{ + int row, col, planeno; + + for (row = 0; row < XpmScreen.Height; row++) { + char *xb = xpmgetline(); + int plane_offset; + if (!xb) + return; + plane_offset = row * XpmScreen.BytesPerRow; + for (col = 0; col < XpmScreen.Width; col++) { + int color = (unsigned char)xb[col]; + int slot; + if (!ttable[color].flag) { + fprintf(stderr, "xpm2iff_host: bad image data at row %d col %d\n", + row, col); + continue; + } + slot = ttable[color].slot; + for (planeno = 0; planeno < nplanes; planeno++) + SETBIT(planeno, plane_offset, col, slot & (1 << planeno)); + } + } +} + +/* ------------------------------------------------------------------ + * Big-endian IFF output helpers + * ------------------------------------------------------------------ */ + +static FILE *iff_out; + +static void +wr32(uint32_t v) +{ + fputc((v >> 24) & 0xff, iff_out); + fputc((v >> 16) & 0xff, iff_out); + fputc((v >> 8) & 0xff, iff_out); + fputc( v & 0xff, iff_out); +} + +static void +write_chunk(const char *id, const void *data, uint32_t size) +{ + fwrite(id, 1, 4, iff_out); + wr32(size); + fwrite(data, 1, size, iff_out); + if (size & 1) + fputc(0, iff_out); +} + +/* ------------------------------------------------------------------ + * main + * ------------------------------------------------------------------ */ + +int +main(int argc, char **argv) +{ + int i, nplanes, colors; + uint32_t pbytes, plne_size, form_size; + + if (argc != 3) { + fprintf(stderr, "Usage: %s source.xpm destination.iff\n", argv[0]); + return 1; + } + + if (!fopen_xpm_file(argv[1])) { + fprintf(stderr, "%s: failed to open or parse XPM file\n", argv[1]); + return 1; + } + + /* nplanes = ceil(log2(Colors)) */ + nplanes = 0; + i = XpmScreen.Colors - 1; + while (i > 0) { nplanes++; i >>= 1; } + + colors = 1 << nplanes; + + XpmScreen.BytesPerRow = ((XpmScreen.Width + 15) / 16) * 2; + pbytes = (uint32_t)XpmScreen.BytesPerRow * (uint32_t)XpmScreen.Height; + + /* Allocate zero-initialised bitplane buffers */ + planes = malloc(nplanes * sizeof(char *)); + if (!planes) { perror("malloc"); return 1; } + for (i = 0; i < nplanes; ++i) { + planes[i] = calloc(1, pbytes); + if (!planes[i]) { perror("calloc"); return 1; } + } + + /* Pack pixel data into bitplanes */ + conv_image(nplanes); + fclose(xpmfh); + + /* Open output IFF file */ + iff_out = fopen(argv[2], "wb"); + if (!iff_out) { perror(argv[2]); return 1; } + + /* Pre-compute FORM size: + * 4 (BMAP type tag) + * 8 + 20 (BMHD) + * 8 + 4 (CAMG) + * 8 + colors*3 (CMAP; colors is a power of 2, so colors*3 is even) + * 8 + 28 (PDAT: 7 x uint32_t) + * 8 + nplanes*pbytes (PLNE; pbytes is always even) + */ + plne_size = (uint32_t)nplanes * pbytes; + form_size = 4 + + (8 + 20) + + (8 + 4) + + (8 + (uint32_t)colors * 3) + + (8 + 28) + + (8 + plne_size); + + /* FORM header */ + fwrite("FORM", 1, 4, iff_out); + wr32(form_size); + fwrite("BMAP", 1, 4, iff_out); + + /* BMHD chunk */ + { + uint8_t bmhd[20]; + uint8_t *p = bmhd; + uint16_t w = (uint16_t)XpmScreen.Width; + uint16_t h = (uint16_t)XpmScreen.Height; + + p[0] = w >> 8; p[1] = w & 0xff; p += 2; /* w */ + p[0] = h >> 8; p[1] = h & 0xff; p += 2; /* h */ + memset(p, 0, 4); p += 4; /* x=0, y=0 */ + *p++ = (uint8_t)nplanes; /* nPlanes */ + *p++ = 0; /* masking: none */ + *p++ = 0; /* compression: none */ + *p++ = 0; /* reserved1 */ + p[0] = 0; p[1] = 0; p += 2; /* transparentColor */ + *p++ = 100; /* xAspect */ + *p++ = 100; /* yAspect */ + p[0] = 0; p[1] = 0; p += 2; /* pageWidth (not used) */ + p[0] = 0; p[1] = 0; p += 2; /* pageHeight (not used) */ + + write_chunk("BMHD", bmhd, 20); + } + + /* CAMG chunk: HIRES | LACE = 0x00008004 */ + { + uint8_t camg[4] = { 0x00, 0x00, 0x80, 0x04 }; + write_chunk("CAMG", camg, 4); + } + + /* CMAP chunk: built from ttable (no color reordering for XPM images) */ + { + uint8_t *cmap = calloc(colors, 3); + if (!cmap) { perror("calloc"); return 1; } + for (i = 0; i < 256; i++) { + if (ttable[i].flag) { + int s = ttable[i].slot; + cmap[s * 3 + 0] = ttable[i].r; + cmap[s * 3 + 1] = ttable[i].g; + cmap[s * 3 + 2] = ttable[i].b; + } + } + write_chunk("CMAP", cmap, (uint32_t)colors * 3); + free(cmap); + } + + /* PDAT chunk: 7 x uint32_t big-endian + * nplanes, pbytes, across=0, down=0, npics=1, xsize=Width, ysize=Height */ + { + uint32_t vals[7]; + uint8_t pdat[28]; + uint8_t *p = pdat; + + vals[0] = (uint32_t)nplanes; + vals[1] = pbytes; + vals[2] = 0; /* across: not a tile sheet */ + vals[3] = 0; /* down */ + vals[4] = 1; /* npics */ + vals[5] = (uint32_t)XpmScreen.Width; + vals[6] = (uint32_t)XpmScreen.Height; + + for (i = 0; i < 7; i++) { + p[0] = (vals[i] >> 24) & 0xff; + p[1] = (vals[i] >> 16) & 0xff; + p[2] = (vals[i] >> 8) & 0xff; + p[3] = vals[i] & 0xff; + p += 4; + } + write_chunk("PDAT", pdat, 28); + } + + /* PLNE chunk: concatenated bitplane data */ + fwrite("PLNE", 1, 4, iff_out); + wr32(plne_size); + for (i = 0; i < nplanes; ++i) + fwrite(planes[i], 1, pbytes, iff_out); + if (plne_size & 1) + fputc(0, iff_out); + + fclose(iff_out); + + for (i = 0; i < nplanes; ++i) free(planes[i]); + free(planes); + + printf("tomb.iff: %dx%d, %d colors (%d planes), %u bytes/plane\n", + XpmScreen.Width, XpmScreen.Height, colors, nplanes, + (unsigned)pbytes); + return 0; +} diff --git a/sys/unix/hints/include/cross-pre2.370 b/sys/unix/hints/include/cross-pre2.370 index eca47550f..d27301af1 100644 --- a/sys/unix/hints/include/cross-pre2.370 +++ b/sys/unix/hints/include/cross-pre2.370 @@ -470,8 +470,8 @@ ifdef CROSS_TO_AMIGA # # Cross-compiler: https://franke.ms/git/bebbo/amiga-gcc # Install to /opt/amiga, then: -# make fetch-lua # sys/unix/setup.sh sys/unix/hints/linux.370 +# make fetch-lua # make CROSS_TO_AMIGA=1 all # make CROSS_TO_AMIGA=1 package #================================================================= From c5dfd1fc5c0d1f261baf12d0e81e282a44e7b183 Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Tue, 24 Mar 2026 01:21:00 +0100 Subject: [PATCH 7/8] Fetch BSD regex from GitHub at build time Replace bundled Spencer regex with a fetch-regex build step that clones https://github.com/garyhouston/regex.git, generates the required .ih and regex.h headers via mkh, and copies the result into sys/amiga/regex/. Usage: make CROSS_TO_AMIGA=1 fetch-regex The fetched sources are not tracked in git. --- .gitignore | 2 + sys/amiga/README.amiga | 1 + sys/amiga/regex/cclass.h | 72 -- sys/amiga/regex/cname.h | 143 --- sys/amiga/regex/engine.h | 1093 ---------------- sys/amiga/regex/regcomp.c | 1704 ------------------------- sys/amiga/regex/regerror.c | 186 --- sys/amiga/regex/regex2.h | 175 --- sys/amiga/regex/regexec.c | 187 --- sys/amiga/regex/regfree.c | 86 -- sys/amiga/regex/utils.h | 59 - sys/unix/hints/include/cross-post.370 | 34 +- sys/unix/hints/include/cross-pre2.370 | 1 + 13 files changed, 37 insertions(+), 3706 deletions(-) delete mode 100755 sys/amiga/regex/cclass.h delete mode 100755 sys/amiga/regex/cname.h delete mode 100755 sys/amiga/regex/engine.h delete mode 100755 sys/amiga/regex/regcomp.c delete mode 100755 sys/amiga/regex/regerror.c delete mode 100755 sys/amiga/regex/regex2.h delete mode 100755 sys/amiga/regex/regexec.c delete mode 100755 sys/amiga/regex/regfree.c delete mode 100755 sys/amiga/regex/utils.h diff --git a/.gitignore b/.gitignore index f5a18b7e3..68c544da6 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,5 @@ bundle/* util/*.lib util/*.exp submodules/CHKSUMS.tmp +sys/amiga/regex/ +sys/amiga/regex/ diff --git a/sys/amiga/README.amiga b/sys/amiga/README.amiga index 8eda92c31..6aa2a2a95 100644 --- a/sys/amiga/README.amiga +++ b/sys/amiga/README.amiga @@ -75,6 +75,7 @@ Cross-compilation from Linux using bebbo's m68k-amigaos-gcc toolchain cd NetHack sys/unix/setup.sh sys/unix/hints/linux.370 make fetch-lua + make CROSS_TO_AMIGA=1 fetch-regex make CROSS_TO_AMIGA=1 all make CROSS_TO_AMIGA=1 package diff --git a/sys/amiga/regex/cclass.h b/sys/amiga/regex/cclass.h deleted file mode 100755 index 52cd47b8f..000000000 --- a/sys/amiga/regex/cclass.h +++ /dev/null @@ -1,72 +0,0 @@ -/* $NetBSD: cclass.h,v 1.3 1995/02/27 13:28:29 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)cclass.h 8.3 (Berkeley) 3/20/94 - */ - -/* character-class table */ -static struct cclass { - char *name; - char *chars; - char *multis; -} cclasses[] = { - "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ -0123456789", "", - "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", - "", - "blank", " \t", "", - "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ -\25\26\27\30\31\32\33\34\35\36\37\177", "", - "digit", "0123456789", "", - "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ -0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "", - "lower", "abcdefghijklmnopqrstuvwxyz", - "", - "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ -0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", - "", - "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - "", - "space", "\t\n\v\f\r ", "", - "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "", - "xdigit", "0123456789ABCDEFabcdef", - "", - NULL, 0, "" -}; diff --git a/sys/amiga/regex/cname.h b/sys/amiga/regex/cname.h deleted file mode 100755 index 50479db08..000000000 --- a/sys/amiga/regex/cname.h +++ /dev/null @@ -1,143 +0,0 @@ -/* $NetBSD: cname.h,v 1.3 1995/02/27 13:28:33 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)cname.h 8.3 (Berkeley) 3/20/94 - */ - -/* character-name table */ -static struct cname { - char *name; - char code; -} cnames[] = { - "NUL", '\0', - "SOH", '\001', - "STX", '\002', - "ETX", '\003', - "EOT", '\004', - "ENQ", '\005', - "ACK", '\006', - "BEL", '\007', - "alert", '\007', - "BS", '\010', - "backspace", '\b', - "HT", '\011', - "tab", '\t', - "LF", '\012', - "newline", '\n', - "VT", '\013', - "vertical-tab", '\v', - "FF", '\014', - "form-feed", '\f', - "CR", '\015', - "carriage-return", '\r', - "SO", '\016', - "SI", '\017', - "DLE", '\020', - "DC1", '\021', - "DC2", '\022', - "DC3", '\023', - "DC4", '\024', - "NAK", '\025', - "SYN", '\026', - "ETB", '\027', - "CAN", '\030', - "EM", '\031', - "SUB", '\032', - "ESC", '\033', - "IS4", '\034', - "FS", '\034', - "IS3", '\035', - "GS", '\035', - "IS2", '\036', - "RS", '\036', - "IS1", '\037', - "US", '\037', - "space", ' ', - "exclamation-mark", '!', - "quotation-mark", '"', - "number-sign", '#', - "dollar-sign", '$', - "percent-sign", '%', - "ampersand", '&', - "apostrophe", '\'', - "left-parenthesis", '(', - "right-parenthesis", ')', - "asterisk", '*', - "plus-sign", '+', - "comma", ',', - "hyphen", '-', - "hyphen-minus", '-', - "period", '.', - "full-stop", '.', - "slash", '/', - "solidus", '/', - "zero", '0', - "one", '1', - "two", '2', - "three", '3', - "four", '4', - "five", '5', - "six", '6', - "seven", '7', - "eight", '8', - "nine", '9', - "colon", ':', - "semicolon", ';', - "less-than-sign", '<', - "equals-sign", '=', - "greater-than-sign", '>', - "question-mark", '?', - "commercial-at", '@', - "left-square-bracket", '[', - "backslash", '\\', - "reverse-solidus", '\\', - "right-square-bracket", ']', - "circumflex", '^', - "circumflex-accent", '^', - "underscore", '_', - "low-line", '_', - "grave-accent", '`', - "left-brace", '{', - "left-curly-bracket", '{', - "vertical-line", '|', - "right-brace", '}', - "right-curly-bracket", '}', - "tilde", '~', - "DEL", '\177', - NULL, 0, -}; diff --git a/sys/amiga/regex/engine.h b/sys/amiga/regex/engine.h deleted file mode 100755 index 93f6842ac..000000000 --- a/sys/amiga/regex/engine.h +++ /dev/null @@ -1,1093 +0,0 @@ -/* $NetBSD: engine.c,v 1.5 1995/02/27 13:28:39 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)engine.c 8.5 (Berkeley) 3/20/94 - */ - -/* - * The matching engine and friends. This file is #included by regexec.c - * after suitable #defines of a variety of macros used herein, so that - * different state representations can be used without duplicating masses - * of code. - */ - -#ifdef SNAMES -#define matcher smatcher -#define fast sfast -#define slow sslow -#define dissect sdissect -#define backref sbackref -#define step sstep -#define print sprint -#define at sat -#define match smat -#endif -#ifdef LNAMES -#define matcher lmatcher -#define fast lfast -#define slow lslow -#define dissect ldissect -#define backref lbackref -#define step lstep -#define print lprint -#define at lat -#define match lmat -#endif - -/* another structure passed up and down to avoid zillions of parameters */ -struct match { - struct re_guts *g; - int eflags; - regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ - char *offp; /* offsets work from here */ - char *beginp; /* start of string -- virtual NUL precedes */ - char *endp; /* end of string -- virtual NUL here */ - char *coldp; /* can be no match starting before here */ - char **lastpos; /* [nplus+1] */ - STATEVARS; - states st; /* current states */ - states fresh; /* states for a fresh start */ - states tmp; /* temporary */ - states empty; /* empty set of states */ -}; - -/* ========= begin header generated by ./mkh ========= */ -#ifdef __cplusplus -extern "C" { -#endif - -/* === engine.c === */ -static int matcher __P((struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags)); -static char *dissect __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst)); -static char *backref __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev)); -static char *fast __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst)); -static char *slow __P((struct match *m, char *start, char *stop, sopno startst, sopno stopst)); -static states step __P((struct re_guts *g, sopno start, sopno stop, states bef, int ch, states aft)); -#define BOL (OUT+1) -#define EOL (BOL+1) -#define BOLEOL (BOL+2) -#define NOTHING (BOL+3) -#define BOW (BOL+4) -#define EOW (BOL+5) -#define CODEMAX (BOL+5) /* highest code used */ -#define NONCHAR(c) ((c) > CHAR_MAX) -#define NNONCHAR (CODEMAX-CHAR_MAX) -#ifdef REDEBUG -static void print __P((struct match *m, char *caption, states st, int ch, FILE *d)); -#endif -#ifdef REDEBUG -static void at __P((struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst)); -#endif -#ifdef REDEBUG -static char *pchar __P((int ch)); -#endif - -#ifdef __cplusplus -} -#endif -/* ========= end header generated by ./mkh ========= */ - -#ifdef REDEBUG -#define SP(t, s, c) print(m, t, s, c, stdout) -#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) -#define NOTE(str) { if (m->eflags®_TRACE) printf("=%s\n", (str)); } -#else -#define SP(t, s, c) /* nothing */ -#define AT(t, p1, p2, s1, s2) /* nothing */ -#define NOTE(s) /* nothing */ -#endif - -/* - - matcher - the actual matching engine - == static int matcher(register struct re_guts *g, char *string, \ - == size_t nmatch, regmatch_t pmatch[], int eflags); - */ -static int /* 0 success, REG_NOMATCH failure */ -matcher(g, string, nmatch, pmatch, eflags) -register struct re_guts *g; -char *string; -size_t nmatch; -regmatch_t pmatch[]; -int eflags; -{ - register char *endp; - register int i; - struct match mv; - register struct match *m = &mv; - register char *dp; - const register sopno gf = g->firststate+1; /* +1 for OEND */ - const register sopno gl = g->laststate; - char *start; - char *stop; - - /* simplify the situation where possible */ - if (g->cflags®_NOSUB) - nmatch = 0; - if (eflags®_STARTEND) { - start = string + pmatch[0].rm_so; - stop = string + pmatch[0].rm_eo; - } else { - start = string; - stop = start + strlen(start); - } - if (stop < start) - return(REG_INVARG); - - /* prescreening; this does wonders for this rather slow code */ - if (g->must != NULL) { - for (dp = start; dp < stop; dp++) - if (*dp == g->must[0] && stop - dp >= g->mlen && - memcmp(dp, g->must, (size_t)g->mlen) == 0) - break; - if (dp == stop) /* we didn't find g->must */ - return(REG_NOMATCH); - } - - /* match struct setup */ - m->g = g; - m->eflags = eflags; - m->pmatch = NULL; - m->lastpos = NULL; - m->offp = string; - m->beginp = start; - m->endp = stop; - STATESETUP(m, 4); - SETUP(m->st); - SETUP(m->fresh); - SETUP(m->tmp); - SETUP(m->empty); - CLEAR(m->empty); - - /* this loop does only one repetition except for backrefs */ - for (;;) { - endp = fast(m, start, stop, gf, gl); - if (endp == NULL) { /* a miss */ - STATETEARDOWN(m); - return(REG_NOMATCH); - } - if (nmatch == 0 && !g->backrefs) - break; /* no further info needed */ - - /* where? */ - assert(m->coldp != NULL); - for (;;) { - NOTE("finding start"); - endp = slow(m, m->coldp, stop, gf, gl); - if (endp != NULL) - break; - assert(m->coldp < m->endp); - m->coldp++; - } - if (nmatch == 1 && !g->backrefs) - break; /* no further info needed */ - - /* oh my, he wants the subexpressions... */ - if (m->pmatch == NULL) - m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) * - sizeof(regmatch_t)); - if (m->pmatch == NULL) { - STATETEARDOWN(m); - return(REG_ESPACE); - } - for (i = 1; i <= m->g->nsub; i++) - m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; - if (!g->backrefs && !(m->eflags®_BACKR)) { - NOTE("dissecting"); - dp = dissect(m, m->coldp, endp, gf, gl); - } else { - if (g->nplus > 0 && m->lastpos == NULL) - m->lastpos = (char **)malloc((g->nplus+1) * - sizeof(char *)); - if (g->nplus > 0 && m->lastpos == NULL) { - free(m->pmatch); - STATETEARDOWN(m); - return(REG_ESPACE); - } - NOTE("backref dissect"); - dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); - } - if (dp != NULL) - break; - - /* uh-oh... we couldn't find a subexpression-level match */ - assert(g->backrefs); /* must be back references doing it */ - assert(g->nplus == 0 || m->lastpos != NULL); - for (;;) { - if (dp != NULL || endp <= m->coldp) - break; /* defeat */ - NOTE("backoff"); - endp = slow(m, m->coldp, endp-1, gf, gl); - if (endp == NULL) - break; /* defeat */ - /* try it on a shorter possibility */ -#ifndef NDEBUG - for (i = 1; i <= m->g->nsub; i++) { - assert(m->pmatch[i].rm_so == -1); - assert(m->pmatch[i].rm_eo == -1); - } -#endif - NOTE("backoff dissect"); - dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); - } - assert(dp == NULL || dp == endp); - if (dp != NULL) /* found a shorter one */ - break; - - /* despite initial appearances, there is no match here */ - NOTE("false alarm"); - start = m->coldp + 1; /* recycle starting later */ - assert(start <= stop); - } - - /* fill in the details if requested */ - if (nmatch > 0) { - pmatch[0].rm_so = m->coldp - m->offp; - pmatch[0].rm_eo = endp - m->offp; - } - if (nmatch > 1) { - assert(m->pmatch != NULL); - for (i = 1; i < nmatch; i++) - if (i <= m->g->nsub) - pmatch[i] = m->pmatch[i]; - else { - pmatch[i].rm_so = -1; - pmatch[i].rm_eo = -1; - } - } - - if (m->pmatch != NULL) - free((char *)m->pmatch); - if (m->lastpos != NULL) - free((char *)m->lastpos); - STATETEARDOWN(m); - return(0); -} - -/* - - dissect - figure out what matched what, no back references - == static char *dissect(register struct match *m, char *start, \ - == char *stop, sopno startst, sopno stopst); - */ -static char * /* == stop (success) always */ -dissect(m, start, stop, startst, stopst) -register struct match *m; -char *start; -char *stop; -sopno startst; -sopno stopst; -{ - register int i; - register sopno ss; /* start sop of current subRE */ - register sopno es; /* end sop of current subRE */ - register char *sp; /* start of string matched by it */ - register char *stp; /* string matched by it cannot pass here */ - register char *rest; /* start of rest of string */ - register char *tail; /* string unmatched by rest of RE */ - register sopno ssub; /* start sop of subsubRE */ - register sopno esub; /* end sop of subsubRE */ - register char *ssp; /* start of string matched by subsubRE */ - register char *sep; /* end of string matched by subsubRE */ - register char *oldssp; /* previous ssp */ - register char *dp; - - AT("diss", start, stop, startst, stopst); - sp = start; - for (ss = startst; ss < stopst; ss = es) { - /* identify end of subRE */ - es = ss; - switch (OP(m->g->strip[es])) { - case OPLUS_: - case OQUEST_: - es += OPND(m->g->strip[es]); - break; - case OCH_: - while (OP(m->g->strip[es]) != O_CH) - es += OPND(m->g->strip[es]); - break; - } - es++; - - /* figure out what it matched */ - switch (OP(m->g->strip[ss])) { - case OEND: - assert(nope); - break; - case OCHAR: - sp++; - break; - case OBOL: - case OEOL: - case OBOW: - case OEOW: - break; - case OANY: - case OANYOF: - sp++; - break; - case OBACK_: - case O_BACK: - assert(nope); - break; - /* cases where length of match is hard to find */ - case OQUEST_: - stp = stop; - for (;;) { - /* how long could this one be? */ - rest = slow(m, sp, stp, ss, es); - assert(rest != NULL); /* it did match */ - /* could the rest match the rest? */ - tail = slow(m, rest, stop, es, stopst); - if (tail == stop) - break; /* yes! */ - /* no -- try a shorter match for this one */ - stp = rest - 1; - assert(stp >= sp); /* it did work */ - } - ssub = ss + 1; - esub = es - 1; - /* did innards match? */ - if (slow(m, sp, rest, ssub, esub) != NULL) { - dp = dissect(m, sp, rest, ssub, esub); - assert(dp == rest); - } else /* no */ - assert(sp == rest); - sp = rest; - break; - case OPLUS_: - stp = stop; - for (;;) { - /* how long could this one be? */ - rest = slow(m, sp, stp, ss, es); - assert(rest != NULL); /* it did match */ - /* could the rest match the rest? */ - tail = slow(m, rest, stop, es, stopst); - if (tail == stop) - break; /* yes! */ - /* no -- try a shorter match for this one */ - stp = rest - 1; - assert(stp >= sp); /* it did work */ - } - ssub = ss + 1; - esub = es - 1; - ssp = sp; - oldssp = ssp; - for (;;) { /* find last match of innards */ - sep = slow(m, ssp, rest, ssub, esub); - if (sep == NULL || sep == ssp) - break; /* failed or matched null */ - oldssp = ssp; /* on to next try */ - ssp = sep; - } - if (sep == NULL) { - /* last successful match */ - sep = ssp; - ssp = oldssp; - } - assert(sep == rest); /* must exhaust substring */ - assert(slow(m, ssp, sep, ssub, esub) == rest); - dp = dissect(m, ssp, sep, ssub, esub); - assert(dp == sep); - sp = rest; - break; - case OCH_: - stp = stop; - for (;;) { - /* how long could this one be? */ - rest = slow(m, sp, stp, ss, es); - assert(rest != NULL); /* it did match */ - /* could the rest match the rest? */ - tail = slow(m, rest, stop, es, stopst); - if (tail == stop) - break; /* yes! */ - /* no -- try a shorter match for this one */ - stp = rest - 1; - assert(stp >= sp); /* it did work */ - } - ssub = ss + 1; - esub = ss + OPND(m->g->strip[ss]) - 1; - assert(OP(m->g->strip[esub]) == OOR1); - for (;;) { /* find first matching branch */ - if (slow(m, sp, rest, ssub, esub) == rest) - break; /* it matched all of it */ - /* that one missed, try next one */ - assert(OP(m->g->strip[esub]) == OOR1); - esub++; - assert(OP(m->g->strip[esub]) == OOR2); - ssub = esub + 1; - esub += OPND(m->g->strip[esub]); - if (OP(m->g->strip[esub]) == OOR2) - esub--; - else - assert(OP(m->g->strip[esub]) == O_CH); - } - dp = dissect(m, sp, rest, ssub, esub); - assert(dp == rest); - sp = rest; - break; - case O_PLUS: - case O_QUEST: - case OOR1: - case OOR2: - case O_CH: - assert(nope); - break; - case OLPAREN: - i = OPND(m->g->strip[ss]); - assert(0 < i && i <= m->g->nsub); - m->pmatch[i].rm_so = sp - m->offp; - break; - case ORPAREN: - i = OPND(m->g->strip[ss]); - assert(0 < i && i <= m->g->nsub); - m->pmatch[i].rm_eo = sp - m->offp; - break; - default: /* uh oh */ - assert(nope); - break; - } - } - - assert(sp == stop); - return(sp); -} - -/* - - backref - figure out what matched what, figuring in back references - == static char *backref(register struct match *m, char *start, \ - == char *stop, sopno startst, sopno stopst, sopno lev); - */ -static char * /* == stop (success) or NULL (failure) */ -backref(m, start, stop, startst, stopst, lev) -register struct match *m; -char *start; -char *stop; -sopno startst; -sopno stopst; -sopno lev; /* PLUS nesting level */ -{ - register int i; - register sopno ss; /* start sop of current subRE */ - register char *sp; /* start of string matched by it */ - register sopno ssub; /* start sop of subsubRE */ - register sopno esub; /* end sop of subsubRE */ - register char *ssp; /* start of string matched by subsubRE */ - register char *dp; - register size_t len; - register int hard; - register sop s; - register regoff_t offsave; - register cset *cs; - - AT("back", start, stop, startst, stopst); - sp = start; - - /* get as far as we can with easy stuff */ - hard = 0; - for (ss = startst; !hard && ss < stopst; ss++) - switch (OP(s = m->g->strip[ss])) { - case OCHAR: - if (sp == stop || *sp++ != (char)OPND(s)) - return(NULL); - break; - case OANY: - if (sp == stop) - return(NULL); - sp++; - break; - case OANYOF: - cs = &m->g->sets[OPND(s)]; - if (sp == stop || !CHIN(cs, *sp++)) - return(NULL); - break; - case OBOL: - if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || - (sp < m->endp && *(sp-1) == '\n' && - (m->g->cflags®_NEWLINE)) ) - { /* yes */ } - else - return(NULL); - break; - case OEOL: - if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || - (sp < m->endp && *sp == '\n' && - (m->g->cflags®_NEWLINE)) ) - { /* yes */ } - else - return(NULL); - break; - case OBOW: - if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || - (sp < m->endp && *(sp-1) == '\n' && - (m->g->cflags®_NEWLINE)) || - (sp > m->beginp && - !ISWORD(*(sp-1))) ) && - (sp < m->endp && ISWORD(*sp)) ) - { /* yes */ } - else - return(NULL); - break; - case OEOW: - if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || - (sp < m->endp && *sp == '\n' && - (m->g->cflags®_NEWLINE)) || - (sp < m->endp && !ISWORD(*sp)) ) && - (sp > m->beginp && ISWORD(*(sp-1))) ) - { /* yes */ } - else - return(NULL); - break; - case O_QUEST: - break; - case OOR1: /* matches null but needs to skip */ - ss++; - s = m->g->strip[ss]; - do { - assert(OP(s) == OOR2); - ss += OPND(s); - } while (OP(s = m->g->strip[ss]) != O_CH); - /* note that the ss++ gets us past the O_CH */ - break; - default: /* have to make a choice */ - hard = 1; - break; - } - if (!hard) { /* that was it! */ - if (sp != stop) - return(NULL); - return(sp); - } - ss--; /* adjust for the for's final increment */ - - /* the hard stuff */ - AT("hard", sp, stop, ss, stopst); - s = m->g->strip[ss]; - switch (OP(s)) { - case OBACK_: /* the vilest depths */ - i = OPND(s); - assert(0 < i && i <= m->g->nsub); - if (m->pmatch[i].rm_eo == -1) - return(NULL); - assert(m->pmatch[i].rm_so != -1); - len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; - assert(stop - m->beginp >= len); - if (sp > stop - len) - return(NULL); /* not enough left to match */ - ssp = m->offp + m->pmatch[i].rm_so; - if (memcmp(sp, ssp, len) != 0) - return(NULL); - while (m->g->strip[ss] != SOP(O_BACK, i)) - ss++; - return(backref(m, sp+len, stop, ss+1, stopst, lev)); - break; - case OQUEST_: /* to null or not */ - dp = backref(m, sp, stop, ss+1, stopst, lev); - if (dp != NULL) - return(dp); /* not */ - return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev)); - break; - case OPLUS_: - assert(m->lastpos != NULL); - assert(lev+1 <= m->g->nplus); - m->lastpos[lev+1] = sp; - return(backref(m, sp, stop, ss+1, stopst, lev+1)); - break; - case O_PLUS: - if (sp == m->lastpos[lev]) /* last pass matched null */ - return(backref(m, sp, stop, ss+1, stopst, lev-1)); - /* try another pass */ - m->lastpos[lev] = sp; - dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev); - if (dp == NULL) - return(backref(m, sp, stop, ss+1, stopst, lev-1)); - else - return(dp); - break; - case OCH_: /* find the right one, if any */ - ssub = ss + 1; - esub = ss + OPND(s) - 1; - assert(OP(m->g->strip[esub]) == OOR1); - for (;;) { /* find first matching branch */ - dp = backref(m, sp, stop, ssub, esub, lev); - if (dp != NULL) - return(dp); - /* that one missed, try next one */ - if (OP(m->g->strip[esub]) == O_CH) - return(NULL); /* there is none */ - esub++; - assert(OP(m->g->strip[esub]) == OOR2); - ssub = esub + 1; - esub += OPND(m->g->strip[esub]); - if (OP(m->g->strip[esub]) == OOR2) - esub--; - else - assert(OP(m->g->strip[esub]) == O_CH); - } - break; - case OLPAREN: /* must undo assignment if rest fails */ - i = OPND(s); - assert(0 < i && i <= m->g->nsub); - offsave = m->pmatch[i].rm_so; - m->pmatch[i].rm_so = sp - m->offp; - dp = backref(m, sp, stop, ss+1, stopst, lev); - if (dp != NULL) - return(dp); - m->pmatch[i].rm_so = offsave; - return(NULL); - break; - case ORPAREN: /* must undo assignment if rest fails */ - i = OPND(s); - assert(0 < i && i <= m->g->nsub); - offsave = m->pmatch[i].rm_eo; - m->pmatch[i].rm_eo = sp - m->offp; - dp = backref(m, sp, stop, ss+1, stopst, lev); - if (dp != NULL) - return(dp); - m->pmatch[i].rm_eo = offsave; - return(NULL); - break; - default: /* uh oh */ - assert(nope); - break; - } - - /* "can't happen" */ - assert(nope); - /* NOTREACHED */ -} - -/* - - fast - step through the string at top speed - == static char *fast(register struct match *m, char *start, \ - == char *stop, sopno startst, sopno stopst); - */ -static char * /* where tentative match ended, or NULL */ -fast(m, start, stop, startst, stopst) -register struct match *m; -char *start; -char *stop; -sopno startst; -sopno stopst; -{ - register states st = m->st; - register states fresh = m->fresh; - register states tmp = m->tmp; - register char *p = start; - register int c = (start == m->beginp) ? OUT : *(start-1); - register int lastc; /* previous c */ - register int flagch; - register int i; - register char *coldp; /* last p after which no match was underway */ - - CLEAR(st); - SET1(st, startst); - st = step(m->g, startst, stopst, st, NOTHING, st); - ASSIGN(fresh, st); - SP("start", st, *p); - coldp = NULL; - for (;;) { - /* next character */ - lastc = c; - c = (p == m->endp) ? OUT : *p; - if (EQ(st, fresh)) - coldp = p; - - /* is there an EOL and/or BOL between lastc and c? */ - flagch = '\0'; - i = 0; - if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || - (lastc == OUT && !(m->eflags®_NOTBOL)) ) { - flagch = BOL; - i = m->g->nbol; - } - if ( (c == '\n' && m->g->cflags®_NEWLINE) || - (c == OUT && !(m->eflags®_NOTEOL)) ) { - flagch = (flagch == BOL) ? BOLEOL : EOL; - i += m->g->neol; - } - if (i != 0) { - for (; i > 0; i--) - st = step(m->g, startst, stopst, st, flagch, st); - SP("boleol", st, c); - } - - /* how about a word boundary? */ - if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && - (c != OUT && ISWORD(c)) ) { - flagch = BOW; - } - if ( (lastc != OUT && ISWORD(lastc)) && - (flagch == EOL || (c != OUT && !ISWORD(c))) ) { - flagch = EOW; - } - if (flagch == BOW || flagch == EOW) { - st = step(m->g, startst, stopst, st, flagch, st); - SP("boweow", st, c); - } - - /* are we done? */ - if (ISSET(st, stopst) || p == stop) - break; /* NOTE BREAK OUT */ - - /* no, we must deal with this character */ - ASSIGN(tmp, st); - ASSIGN(st, fresh); - assert(c != OUT); - st = step(m->g, startst, stopst, tmp, c, st); - SP("aft", st, c); - assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); - p++; - } - - assert(coldp != NULL); - m->coldp = coldp; - if (ISSET(st, stopst)) - return(p+1); - else - return(NULL); -} - -/* - - slow - step through the string more deliberately - == static char *slow(register struct match *m, char *start, \ - == char *stop, sopno startst, sopno stopst); - */ -static char * /* where it ended */ -slow(m, start, stop, startst, stopst) -register struct match *m; -char *start; -char *stop; -sopno startst; -sopno stopst; -{ - register states st = m->st; - register states empty = m->empty; - register states tmp = m->tmp; - register char *p = start; - register int c = (start == m->beginp) ? OUT : *(start-1); - register int lastc; /* previous c */ - register int flagch; - register int i; - register char *matchp; /* last p at which a match ended */ - - AT("slow", start, stop, startst, stopst); - CLEAR(st); - SET1(st, startst); - SP("sstart", st, *p); - st = step(m->g, startst, stopst, st, NOTHING, st); - matchp = NULL; - for (;;) { - /* next character */ - lastc = c; - c = (p == m->endp) ? OUT : *p; - - /* is there an EOL and/or BOL between lastc and c? */ - flagch = '\0'; - i = 0; - if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || - (lastc == OUT && !(m->eflags®_NOTBOL)) ) { - flagch = BOL; - i = m->g->nbol; - } - if ( (c == '\n' && m->g->cflags®_NEWLINE) || - (c == OUT && !(m->eflags®_NOTEOL)) ) { - flagch = (flagch == BOL) ? BOLEOL : EOL; - i += m->g->neol; - } - if (i != 0) { - for (; i > 0; i--) - st = step(m->g, startst, stopst, st, flagch, st); - SP("sboleol", st, c); - } - - /* how about a word boundary? */ - if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && - (c != OUT && ISWORD(c)) ) { - flagch = BOW; - } - if ( (lastc != OUT && ISWORD(lastc)) && - (flagch == EOL || (c != OUT && !ISWORD(c))) ) { - flagch = EOW; - } - if (flagch == BOW || flagch == EOW) { - st = step(m->g, startst, stopst, st, flagch, st); - SP("sboweow", st, c); - } - - /* are we done? */ - if (ISSET(st, stopst)) - matchp = p; - if (EQ(st, empty) || p == stop) - break; /* NOTE BREAK OUT */ - - /* no, we must deal with this character */ - ASSIGN(tmp, st); - ASSIGN(st, empty); - assert(c != OUT); - st = step(m->g, startst, stopst, tmp, c, st); - SP("saft", st, c); - assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); - p++; - } - - return(matchp); -} - - -/* - - step - map set of states reachable before char to set reachable after - == static states step(register struct re_guts *g, sopno start, sopno stop, \ - == register states bef, int ch, register states aft); - == #define BOL (OUT+1) - == #define EOL (BOL+1) - == #define BOLEOL (BOL+2) - == #define NOTHING (BOL+3) - == #define BOW (BOL+4) - == #define EOW (BOL+5) - == #define CODEMAX (BOL+5) // highest code used - == #define NONCHAR(c) ((c) > CHAR_MAX) - == #define NNONCHAR (CODEMAX-CHAR_MAX) - */ -static states -step(g, start, stop, bef, ch, aft) -register struct re_guts *g; -sopno start; /* start state within strip */ -sopno stop; /* state after stop state within strip */ -register states bef; /* states reachable before */ -int ch; /* character or NONCHAR code */ -register states aft; /* states already known reachable after */ -{ - register cset *cs; - register sop s; - register sopno pc; - register onestate here; /* note, macros know this name */ - register sopno look; - register int i; - - for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { - s = g->strip[pc]; - switch (OP(s)) { - case OEND: - assert(pc == stop-1); - break; - case OCHAR: - /* only characters can match */ - assert(!NONCHAR(ch) || ch != (char)OPND(s)); - if (ch == (char)OPND(s)) - FWD(aft, bef, 1); - break; - case OBOL: - if (ch == BOL || ch == BOLEOL) - FWD(aft, bef, 1); - break; - case OEOL: - if (ch == EOL || ch == BOLEOL) - FWD(aft, bef, 1); - break; - case OBOW: - if (ch == BOW) - FWD(aft, bef, 1); - break; - case OEOW: - if (ch == EOW) - FWD(aft, bef, 1); - break; - case OANY: - if (!NONCHAR(ch)) - FWD(aft, bef, 1); - break; - case OANYOF: - cs = &g->sets[OPND(s)]; - if (!NONCHAR(ch) && CHIN(cs, ch)) - FWD(aft, bef, 1); - break; - case OBACK_: /* ignored here */ - case O_BACK: - FWD(aft, aft, 1); - break; - case OPLUS_: /* forward, this is just an empty */ - FWD(aft, aft, 1); - break; - case O_PLUS: /* both forward and back */ - FWD(aft, aft, 1); - i = ISSETBACK(aft, OPND(s)); - BACK(aft, aft, OPND(s)); - if (!i && ISSETBACK(aft, OPND(s))) { - /* oho, must reconsider loop body */ - pc -= OPND(s) + 1; - INIT(here, pc); - } - break; - case OQUEST_: /* two branches, both forward */ - FWD(aft, aft, 1); - FWD(aft, aft, OPND(s)); - break; - case O_QUEST: /* just an empty */ - FWD(aft, aft, 1); - break; - case OLPAREN: /* not significant here */ - case ORPAREN: - FWD(aft, aft, 1); - break; - case OCH_: /* mark the first two branches */ - FWD(aft, aft, 1); - assert(OP(g->strip[pc+OPND(s)]) == OOR2); - FWD(aft, aft, OPND(s)); - break; - case OOR1: /* done a branch, find the O_CH */ - if (ISSTATEIN(aft, here)) { - for (look = 1; - OP(s = g->strip[pc+look]) != O_CH; - look += OPND(s)) - assert(OP(s) == OOR2); - FWD(aft, aft, look); - } - break; - case OOR2: /* propagate OCH_'s marking */ - FWD(aft, aft, 1); - if (OP(g->strip[pc+OPND(s)]) != O_CH) { - assert(OP(g->strip[pc+OPND(s)]) == OOR2); - FWD(aft, aft, OPND(s)); - } - break; - case O_CH: /* just empty */ - FWD(aft, aft, 1); - break; - default: /* ooooops... */ - assert(nope); - break; - } - } - - return(aft); -} - -#ifdef REDEBUG -/* - - print - print a set of states - == #ifdef REDEBUG - == static void print(struct match *m, char *caption, states st, \ - == int ch, FILE *d); - == #endif - */ -static void -print(m, caption, st, ch, d) -struct match *m; -char *caption; -states st; -int ch; -FILE *d; -{ - register struct re_guts *g = m->g; - register int i; - register int first = 1; - - if (!(m->eflags®_TRACE)) - return; - - fprintf(d, "%s", caption); - if (ch != '\0') - fprintf(d, " %s", pchar(ch)); - for (i = 0; i < g->nstates; i++) - if (ISSET(st, i)) { - fprintf(d, "%s%d", (first) ? "\t" : ", ", i); - first = 0; - } - fprintf(d, "\n"); -} - -/* - - at - print current situation - == #ifdef REDEBUG - == static void at(struct match *m, char *title, char *start, char *stop, \ - == sopno startst, sopno stopst); - == #endif - */ -static void -at(m, title, start, stop, startst, stopst) -struct match *m; -char *title; -char *start; -char *stop; -sopno startst; -sopno stopst; -{ - if (!(m->eflags®_TRACE)) - return; - - printf("%s %s-", title, pchar(*start)); - printf("%s ", pchar(*stop)); - printf("%ld-%ld\n", (long)startst, (long)stopst); -} - -#ifndef PCHARDONE -#define PCHARDONE /* never again */ -/* - - pchar - make a character printable - == #ifdef REDEBUG - == static char *pchar(int ch); - == #endif - * - * Is this identical to regchar() over in debug.c? Well, yes. But a - * duplicate here avoids having a debugging-capable regexec.o tied to - * a matching debug.o, and this is convenient. It all disappears in - * the non-debug compilation anyway, so it doesn't matter much. - */ -static char * /* -> representation */ -pchar(ch) -int ch; -{ - static char pbuf[10]; - - if (isprint(ch) || ch == ' ') - sprintf(pbuf, "%c", ch); - else - sprintf(pbuf, "\\%o", ch); - return(pbuf); -} -#endif -#endif - -#undef matcher -#undef fast -#undef slow -#undef dissect -#undef backref -#undef step -#undef print -#undef at -#undef match diff --git a/sys/amiga/regex/regcomp.c b/sys/amiga/regex/regcomp.c deleted file mode 100755 index 9b64aa4b2..000000000 --- a/sys/amiga/regex/regcomp.c +++ /dev/null @@ -1,1704 +0,0 @@ -/* $NetBSD: regcomp.c,v 1.6 1995/02/27 13:29:01 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; -#else -static char rcsid[] = "$NetBSD: regcomp.c,v 1.6 1995/02/27 13:29:01 cgd Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" -#include "regex2.h" - -#include "cclass.h" -#include "cname.h" - -/* - * parse structure, passed up and down to avoid global variables and - * other clumsinesses - */ -struct parse { - char *next; /* next character in RE */ - char *end; /* end of string (-> NUL normally) */ - int error; /* has an error been seen? */ - sop *strip; /* malloced strip */ - sopno ssize; /* malloced strip size (allocated) */ - sopno slen; /* malloced strip length (used) */ - int ncsalloc; /* number of csets allocated */ - struct re_guts *g; -# define NPAREN 10 /* we need to remember () 1-9 for back refs */ - sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ - sopno pend[NPAREN]; /* -> ) ([0] unused) */ -}; - -/* ========= begin header generated by ./mkh ========= */ -#ifdef __cplusplus -extern "C" { -#endif - -/* === regcomp.c === */ -static void p_ere __P((struct parse *p, int stop)); -static void p_ere_exp __P((struct parse *p)); -static void p_str __P((struct parse *p)); -static void p_bre __P((struct parse *p, int end1, int end2)); -static int p_simp_re __P((struct parse *p, int starordinary)); -static int p_count __P((struct parse *p)); -static void p_bracket __P((struct parse *p)); -static void p_b_term __P((struct parse *p, cset *cs)); -static void p_b_cclass __P((struct parse *p, cset *cs)); -static void p_b_eclass __P((struct parse *p, cset *cs)); -static char p_b_symbol __P((struct parse *p)); -static char p_b_coll_elem __P((struct parse *p, int endc)); -static char othercase __P((int ch)); -static void bothcases __P((struct parse *p, int ch)); -static void ordinary __P((struct parse *p, int ch)); -static void nonnewline __P((struct parse *p)); -static void repeat __P((struct parse *p, sopno start, int from, int to)); -static int seterr __P((struct parse *p, int e)); -static cset *allocset __P((struct parse *p)); -static void freeset __P((struct parse *p, cset *cs)); -static int freezeset __P((struct parse *p, cset *cs)); -static int firstch __P((struct parse *p, cset *cs)); -static int nch __P((struct parse *p, cset *cs)); -static void mcadd __P((struct parse *p, cset *cs, char *cp)); -static void mcsub __P((cset *cs, char *cp)); -static int mcin __P((cset *cs, char *cp)); -static char *mcfind __P((cset *cs, char *cp)); -static void mcinvert __P((struct parse *p, cset *cs)); -static void mccase __P((struct parse *p, cset *cs)); -static int isinsets __P((struct re_guts *g, int c)); -static int samesets __P((struct re_guts *g, int c1, int c2)); -static void categorize __P((struct parse *p, struct re_guts *g)); -static sopno dupl __P((struct parse *p, sopno start, sopno finish)); -static void doemit __P((struct parse *p, sop op, size_t opnd)); -static void doinsert __P((struct parse *p, sop op, size_t opnd, sopno pos)); -static void dofwd __P((struct parse *p, sopno pos, sop value)); -static void enlarge __P((struct parse *p, sopno size)); -static void stripsnug __P((struct parse *p, struct re_guts *g)); -static void findmust __P((struct parse *p, struct re_guts *g)); -static sopno pluscount __P((struct parse *p, struct re_guts *g)); - -#ifdef __cplusplus -} -#endif -/* ========= end header generated by ./mkh ========= */ - -static char nuls[10]; /* place to point scanner in event of error */ - -/* - * macros for use with parse structure - * BEWARE: these know that the parse structure is named `p' !!! - */ -#define PEEK() (*p->next) -#define PEEK2() (*(p->next+1)) -#define MORE() (p->next < p->end) -#define MORE2() (p->next+1 < p->end) -#define SEE(c) (MORE() && PEEK() == (c)) -#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) -#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) -#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) -#define NEXT() (p->next++) -#define NEXT2() (p->next += 2) -#define NEXTn(n) (p->next += (n)) -#define GETNEXT() (*p->next++) -#define SETERROR(e) seterr(p, (e)) -#define REQUIRE(co, e) ((co) || SETERROR(e)) -#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) -#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) -#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) -#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) -#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) -#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) -#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) -#define HERE() (p->slen) -#define THERE() (p->slen - 1) -#define THERETHERE() (p->slen - 2) -#define DROP(n) (p->slen -= (n)) - -#ifndef NDEBUG -static int never = 0; /* for use in asserts; shuts lint up */ -#else -#define never 0 /* some s have bugs too */ -#endif - -/* - - regcomp - interface for parser and compilation - = extern int regcomp(regex_t *, const char *, int); - = #define REG_BASIC 0000 - = #define REG_EXTENDED 0001 - = #define REG_ICASE 0002 - = #define REG_NOSUB 0004 - = #define REG_NEWLINE 0010 - = #define REG_NOSPEC 0020 - = #define REG_PEND 0040 - = #define REG_DUMP 0200 - */ -int /* 0 success, otherwise REG_something */ -regcomp(preg, pattern, cflags) -regex_t *preg; -const char *pattern; -int cflags; -{ - struct parse pa; - register struct re_guts *g; - register struct parse *p = &pa; - register int i; - register size_t len; -#ifdef REDEBUG -# define GOODFLAGS(f) (f) -#else -# define GOODFLAGS(f) ((f)&~REG_DUMP) -#endif - - cflags = GOODFLAGS(cflags); - if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) - return(REG_INVARG); - - if (cflags®_PEND) { - if (preg->re_endp < pattern) - return(REG_INVARG); - len = preg->re_endp - pattern; - } else - len = strlen((char *)pattern); - - /* do the mallocs early so failure handling is easy */ - g = (struct re_guts *)malloc(sizeof(struct re_guts) + - (NC-1)*sizeof(cat_t)); - if (g == NULL) - return(REG_ESPACE); - p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ - p->strip = (sop *)malloc(p->ssize * sizeof(sop)); - p->slen = 0; - if (p->strip == NULL) { - free((char *)g); - return(REG_ESPACE); - } - - /* set things up */ - p->g = g; - p->next = (char *)pattern; /* convenience; we do not modify it */ - p->end = p->next + len; - p->error = 0; - p->ncsalloc = 0; - for (i = 0; i < NPAREN; i++) { - p->pbegin[i] = 0; - p->pend[i] = 0; - } - g->csetsize = NC; - g->sets = NULL; - g->setbits = NULL; - g->ncsets = 0; - g->cflags = cflags; - g->iflags = 0; - g->nbol = 0; - g->neol = 0; - g->must = NULL; - g->mlen = 0; - g->nsub = 0; - g->ncategories = 1; /* category 0 is "everything else" */ - g->categories = &g->catspace[-(CHAR_MIN)]; - (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); - g->backrefs = 0; - - /* do it */ - EMIT(OEND, 0); - g->firststate = THERE(); - if (cflags®_EXTENDED) - p_ere(p, OUT); - else if (cflags®_NOSPEC) - p_str(p); - else - p_bre(p, OUT, OUT); - EMIT(OEND, 0); - g->laststate = THERE(); - - /* tidy up loose ends and fill things in */ - categorize(p, g); - stripsnug(p, g); - findmust(p, g); - g->nplus = pluscount(p, g); - g->magic = MAGIC2; - preg->re_nsub = g->nsub; - preg->re_g = g; - preg->re_magic = MAGIC1; -#ifndef REDEBUG - /* not debugging, so can't rely on the assert() in regexec() */ - if (g->iflags&BAD) - SETERROR(REG_ASSERT); -#endif - - /* win or lose, we're done */ - if (p->error != 0) /* lose */ - regfree(preg); - return(p->error); -} - -/* - - p_ere - ERE parser top level, concatenation and alternation - == static void p_ere(register struct parse *p, int stop); - */ -static void -p_ere(p, stop) -register struct parse *p; -int stop; /* character this ERE should end at */ -{ - register char c; - register sopno prevback; - register sopno prevfwd; - register sopno conc; - register int first = 1; /* is this the first alternative? */ - - for (;;) { - /* do a bunch of concatenated expressions */ - conc = HERE(); - while (MORE() && (c = PEEK()) != '|' && c != stop) - p_ere_exp(p); - REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ - - if (!EAT('|')) - break; /* NOTE BREAK OUT */ - - if (first) { - INSERT(OCH_, conc); /* offset is wrong */ - prevfwd = conc; - prevback = conc; - first = 0; - } - ASTERN(OOR1, prevback); - prevback = THERE(); - AHEAD(prevfwd); /* fix previous offset */ - prevfwd = HERE(); - EMIT(OOR2, 0); /* offset is very wrong */ - } - - if (!first) { /* tail-end fixups */ - AHEAD(prevfwd); - ASTERN(O_CH, prevback); - } - - assert(!MORE() || SEE(stop)); -} - -/* - - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op - == static void p_ere_exp(register struct parse *p); - */ -static void -p_ere_exp(p) -register struct parse *p; -{ - register char c; - register sopno pos; - register int count; - register int count2; - register sopno subno; - int wascaret = 0; - - assert(MORE()); /* caller should have ensured this */ - c = GETNEXT(); - - pos = HERE(); - switch (c) { - case '(': - REQUIRE(MORE(), REG_EPAREN); - p->g->nsub++; - subno = p->g->nsub; - if (subno < NPAREN) - p->pbegin[subno] = HERE(); - EMIT(OLPAREN, subno); - if (!SEE(')')) - p_ere(p, ')'); - if (subno < NPAREN) { - p->pend[subno] = HERE(); - assert(p->pend[subno] != 0); - } - EMIT(ORPAREN, subno); - MUSTEAT(')', REG_EPAREN); - break; -#ifndef POSIX_MISTAKE - case ')': /* happens only if no current unmatched ( */ - /* - * You may ask, why the ifndef? Because I didn't notice - * this until slightly too late for 1003.2, and none of the - * other 1003.2 regular-expression reviewers noticed it at - * all. So an unmatched ) is legal POSIX, at least until - * we can get it fixed. - */ - SETERROR(REG_EPAREN); - break; -#endif - case '^': - EMIT(OBOL, 0); - p->g->iflags |= USEBOL; - p->g->nbol++; - wascaret = 1; - break; - case '$': - EMIT(OEOL, 0); - p->g->iflags |= USEEOL; - p->g->neol++; - break; - case '|': - SETERROR(REG_EMPTY); - break; - case '*': - case '+': - case '?': - SETERROR(REG_BADRPT); - break; - case '.': - if (p->g->cflags®_NEWLINE) - nonnewline(p); - else - EMIT(OANY, 0); - break; - case '[': - p_bracket(p); - break; - case '\\': - REQUIRE(MORE(), REG_EESCAPE); - c = GETNEXT(); - ordinary(p, c); - break; - case '{': /* okay as ordinary except if digit follows */ - REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); - /* FALLTHROUGH */ - default: - ordinary(p, c); - break; - } - - if (!MORE()) - return; - c = PEEK(); - /* we call { a repetition if followed by a digit */ - if (!( c == '*' || c == '+' || c == '?' || - (c == '{' && MORE2() && isdigit(PEEK2())) )) - return; /* no repetition, we're done */ - NEXT(); - - REQUIRE(!wascaret, REG_BADRPT); - switch (c) { - case '*': /* implemented as +? */ - /* this case does not require the (y|) trick, noKLUDGE */ - INSERT(OPLUS_, pos); - ASTERN(O_PLUS, pos); - INSERT(OQUEST_, pos); - ASTERN(O_QUEST, pos); - break; - case '+': - INSERT(OPLUS_, pos); - ASTERN(O_PLUS, pos); - break; - case '?': - /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ - INSERT(OCH_, pos); /* offset slightly wrong */ - ASTERN(OOR1, pos); /* this one's right */ - AHEAD(pos); /* fix the OCH_ */ - EMIT(OOR2, 0); /* offset very wrong... */ - AHEAD(THERE()); /* ...so fix it */ - ASTERN(O_CH, THERETHERE()); - break; - case '{': - count = p_count(p); - if (EAT(',')) { - if (isdigit(PEEK())) { - count2 = p_count(p); - REQUIRE(count <= count2, REG_BADBR); - } else /* single number with comma */ - count2 = INFINITY; - } else /* just a single number */ - count2 = count; - repeat(p, pos, count, count2); - if (!EAT('}')) { /* error heuristics */ - while (MORE() && PEEK() != '}') - NEXT(); - REQUIRE(MORE(), REG_EBRACE); - SETERROR(REG_BADBR); - } - break; - } - - if (!MORE()) - return; - c = PEEK(); - if (!( c == '*' || c == '+' || c == '?' || - (c == '{' && MORE2() && isdigit(PEEK2())) ) ) - return; - SETERROR(REG_BADRPT); -} - -/* - - p_str - string (no metacharacters) "parser" - == static void p_str(register struct parse *p); - */ -static void -p_str(p) -register struct parse *p; -{ - REQUIRE(MORE(), REG_EMPTY); - while (MORE()) - ordinary(p, GETNEXT()); -} - -/* - - p_bre - BRE parser top level, anchoring and concatenation - == static void p_bre(register struct parse *p, register int end1, \ - == register int end2); - * Giving end1 as OUT essentially eliminates the end1/end2 check. - * - * This implementation is a bit of a kludge, in that a trailing $ is first - * taken as an ordinary character and then revised to be an anchor. The - * only undesirable side effect is that '$' gets included as a character - * category in such cases. This is fairly harmless; not worth fixing. - * The amount of lookahead needed to avoid this kludge is excessive. - */ -static void -p_bre(p, end1, end2) -register struct parse *p; -register int end1; /* first terminating character */ -register int end2; /* second terminating character */ -{ - register sopno start = HERE(); - register int first = 1; /* first subexpression? */ - register int wasdollar = 0; - - if (EAT('^')) { - EMIT(OBOL, 0); - p->g->iflags |= USEBOL; - p->g->nbol++; - } - while (MORE() && !SEETWO(end1, end2)) { - wasdollar = p_simp_re(p, first); - first = 0; - } - if (wasdollar) { /* oops, that was a trailing anchor */ - DROP(1); - EMIT(OEOL, 0); - p->g->iflags |= USEEOL; - p->g->neol++; - } - - REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ -} - -/* - - p_simp_re - parse a simple RE, an atom possibly followed by a repetition - == static int p_simp_re(register struct parse *p, int starordinary); - */ -static int /* was the simple RE an unbackslashed $? */ -p_simp_re(p, starordinary) -register struct parse *p; -int starordinary; /* is a leading * an ordinary character? */ -{ - register int c; - register int count; - register int count2; - register sopno pos; - register int i; - register sopno subno; -# define BACKSL (1<g->cflags®_NEWLINE) - nonnewline(p); - else - EMIT(OANY, 0); - break; - case '[': - p_bracket(p); - break; - case BACKSL|'{': - SETERROR(REG_BADRPT); - break; - case BACKSL|'(': - p->g->nsub++; - subno = p->g->nsub; - if (subno < NPAREN) - p->pbegin[subno] = HERE(); - EMIT(OLPAREN, subno); - /* the MORE here is an error heuristic */ - if (MORE() && !SEETWO('\\', ')')) - p_bre(p, '\\', ')'); - if (subno < NPAREN) { - p->pend[subno] = HERE(); - assert(p->pend[subno] != 0); - } - EMIT(ORPAREN, subno); - REQUIRE(EATTWO('\\', ')'), REG_EPAREN); - break; - case BACKSL|')': /* should not get here -- must be user */ - case BACKSL|'}': - SETERROR(REG_EPAREN); - break; - case BACKSL|'1': - case BACKSL|'2': - case BACKSL|'3': - case BACKSL|'4': - case BACKSL|'5': - case BACKSL|'6': - case BACKSL|'7': - case BACKSL|'8': - case BACKSL|'9': - i = (c&~BACKSL) - '0'; - assert(i < NPAREN); - if (p->pend[i] != 0) { - assert(i <= p->g->nsub); - EMIT(OBACK_, i); - assert(p->pbegin[i] != 0); - assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); - assert(OP(p->strip[p->pend[i]]) == ORPAREN); - (void) dupl(p, p->pbegin[i]+1, p->pend[i]); - EMIT(O_BACK, i); - } else - SETERROR(REG_ESUBREG); - p->g->backrefs = 1; - break; - case '*': - REQUIRE(starordinary, REG_BADRPT); - /* FALLTHROUGH */ - default: - ordinary(p, c &~ BACKSL); - break; - } - - if (EAT('*')) { /* implemented as +? */ - /* this case does not require the (y|) trick, noKLUDGE */ - INSERT(OPLUS_, pos); - ASTERN(O_PLUS, pos); - INSERT(OQUEST_, pos); - ASTERN(O_QUEST, pos); - } else if (EATTWO('\\', '{')) { - count = p_count(p); - if (EAT(',')) { - if (MORE() && isdigit(PEEK())) { - count2 = p_count(p); - REQUIRE(count <= count2, REG_BADBR); - } else /* single number with comma */ - count2 = INFINITY; - } else /* just a single number */ - count2 = count; - repeat(p, pos, count, count2); - if (!EATTWO('\\', '}')) { /* error heuristics */ - while (MORE() && !SEETWO('\\', '}')) - NEXT(); - REQUIRE(MORE(), REG_EBRACE); - SETERROR(REG_BADBR); - } - } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ - return(1); - - return(0); -} - -/* - - p_count - parse a repetition count - == static int p_count(register struct parse *p); - */ -static int /* the value */ -p_count(p) -register struct parse *p; -{ - register int count = 0; - register int ndigits = 0; - - while (MORE() && isdigit(PEEK()) && count <= DUPMAX) { - count = count*10 + (GETNEXT() - '0'); - ndigits++; - } - - REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); - return(count); -} - -/* - - p_bracket - parse a bracketed character list - == static void p_bracket(register struct parse *p); - * - * Note a significant property of this code: if the allocset() did SETERROR, - * no set operations are done. - */ -static void -p_bracket(p) -register struct parse *p; -{ - register char c; - register cset *cs = allocset(p); - register int invert = 0; - - /* Dept of Truly Sickening Special-Case Kludges */ - if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { - EMIT(OBOW, 0); - NEXTn(6); - return; - } - if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { - EMIT(OEOW, 0); - NEXTn(6); - return; - } - - if (EAT('^')) - invert++; /* make note to invert set at end */ - if (EAT(']')) - CHadd(cs, ']'); - else if (EAT('-')) - CHadd(cs, '-'); - while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) - p_b_term(p, cs); - if (EAT('-')) - CHadd(cs, '-'); - MUSTEAT(']', REG_EBRACK); - - if (p->error != 0) /* don't mess things up further */ - return; - - if (p->g->cflags®_ICASE) { - register int i; - register int ci; - - for (i = p->g->csetsize - 1; i >= 0; i--) - if (CHIN(cs, i) && isalpha(i)) { - ci = othercase(i); - if (ci != i) - CHadd(cs, ci); - } - if (cs->multis != NULL) - mccase(p, cs); - } - if (invert) { - register int i; - - for (i = p->g->csetsize - 1; i >= 0; i--) - if (CHIN(cs, i)) - CHsub(cs, i); - else - CHadd(cs, i); - if (p->g->cflags®_NEWLINE) - CHsub(cs, '\n'); - if (cs->multis != NULL) - mcinvert(p, cs); - } - - assert(cs->multis == NULL); /* xxx */ - - if (nch(p, cs) == 1) { /* optimize singleton sets */ - ordinary(p, firstch(p, cs)); - freeset(p, cs); - } else - EMIT(OANYOF, freezeset(p, cs)); -} - -/* - - p_b_term - parse one term of a bracketed character list - == static void p_b_term(register struct parse *p, register cset *cs); - */ -static void -p_b_term(p, cs) -register struct parse *p; -register cset *cs; -{ - register char c; - register char start, finish; - register int i; - - /* classify what we've got */ - switch ((MORE()) ? PEEK() : '\0') { - case '[': - c = (MORE2()) ? PEEK2() : '\0'; - break; - case '-': - SETERROR(REG_ERANGE); - return; /* NOTE RETURN */ - break; - default: - c = '\0'; - break; - } - - switch (c) { - case ':': /* character class */ - NEXT2(); - REQUIRE(MORE(), REG_EBRACK); - c = PEEK(); - REQUIRE(c != '-' && c != ']', REG_ECTYPE); - p_b_cclass(p, cs); - REQUIRE(MORE(), REG_EBRACK); - REQUIRE(EATTWO(':', ']'), REG_ECTYPE); - break; - case '=': /* equivalence class */ - NEXT2(); - REQUIRE(MORE(), REG_EBRACK); - c = PEEK(); - REQUIRE(c != '-' && c != ']', REG_ECOLLATE); - p_b_eclass(p, cs); - REQUIRE(MORE(), REG_EBRACK); - REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); - break; - default: /* symbol, ordinary character, or range */ -/* xxx revision needed for multichar stuff */ - start = p_b_symbol(p); - if (SEE('-') && MORE2() && PEEK2() != ']') { - /* range */ - NEXT(); - if (EAT('-')) - finish = '-'; - else - finish = p_b_symbol(p); - } else - finish = start; -/* xxx what about signed chars here... */ - REQUIRE(start <= finish, REG_ERANGE); - for (i = start; i <= finish; i++) - CHadd(cs, i); - break; - } -} - -/* - - p_b_cclass - parse a character-class name and deal with it - == static void p_b_cclass(register struct parse *p, register cset *cs); - */ -static void -p_b_cclass(p, cs) -register struct parse *p; -register cset *cs; -{ - register char *sp = p->next; - register struct cclass *cp; - register size_t len; - register char *u; - register char c; - - while (MORE() && isalpha(PEEK())) - NEXT(); - len = p->next - sp; - for (cp = cclasses; cp->name != NULL; cp++) - if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') - break; - if (cp->name == NULL) { - /* oops, didn't find it */ - SETERROR(REG_ECTYPE); - return; - } - - u = cp->chars; - while ((c = *u++) != '\0') - CHadd(cs, c); - for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) - MCadd(p, cs, u); -} - -/* - - p_b_eclass - parse an equivalence-class name and deal with it - == static void p_b_eclass(register struct parse *p, register cset *cs); - * - * This implementation is incomplete. xxx - */ -static void -p_b_eclass(p, cs) -register struct parse *p; -register cset *cs; -{ - register char c; - - c = p_b_coll_elem(p, '='); - CHadd(cs, c); -} - -/* - - p_b_symbol - parse a character or [..]ed multicharacter collating symbol - == static char p_b_symbol(register struct parse *p); - */ -static char /* value of symbol */ -p_b_symbol(p) -register struct parse *p; -{ - register char value; - - REQUIRE(MORE(), REG_EBRACK); - if (!EATTWO('[', '.')) - return(GETNEXT()); - - /* collating symbol */ - value = p_b_coll_elem(p, '.'); - REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); - return(value); -} - -/* - - p_b_coll_elem - parse a collating-element name and look it up - == static char p_b_coll_elem(register struct parse *p, int endc); - */ -static char /* value of collating element */ -p_b_coll_elem(p, endc) -register struct parse *p; -int endc; /* name ended by endc,']' */ -{ - register char *sp = p->next; - register struct cname *cp; - register int len; - register char c; - - while (MORE() && !SEETWO(endc, ']')) - NEXT(); - if (!MORE()) { - SETERROR(REG_EBRACK); - return(0); - } - len = p->next - sp; - for (cp = cnames; cp->name != NULL; cp++) - if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') - return(cp->code); /* known name */ - if (len == 1) - return(*sp); /* single character */ - SETERROR(REG_ECOLLATE); /* neither */ - return(0); -} - -/* - - othercase - return the case counterpart of an alphabetic - == static char othercase(int ch); - */ -static char /* if no counterpart, return ch */ -othercase(ch) -int ch; -{ - assert(isalpha(ch)); - if (isupper(ch)) - return(tolower(ch)); - else if (islower(ch)) - return(toupper(ch)); - else /* peculiar, but could happen */ - return(ch); -} - -/* - - bothcases - emit a dualcase version of a two-case character - == static void bothcases(register struct parse *p, int ch); - * - * Boy, is this implementation ever a kludge... - */ -static void -bothcases(p, ch) -register struct parse *p; -int ch; -{ - register char *oldnext = p->next; - register char *oldend = p->end; - char bracket[3]; - - assert(othercase(ch) != ch); /* p_bracket() would recurse */ - p->next = bracket; - p->end = bracket+2; - bracket[0] = ch; - bracket[1] = ']'; - bracket[2] = '\0'; - p_bracket(p); - assert(p->next == bracket+2); - p->next = oldnext; - p->end = oldend; -} - -/* - - ordinary - emit an ordinary character - == static void ordinary(register struct parse *p, register int ch); - */ -static void -ordinary(p, ch) -register struct parse *p; -register int ch; -{ - register cat_t *cap = p->g->categories; - - if ((p->g->cflags®_ICASE) && isalpha(ch) && othercase(ch) != ch) - bothcases(p, ch); - else { - EMIT(OCHAR, (unsigned char)ch); - if (cap[ch] == 0) - cap[ch] = p->g->ncategories++; - } -} - -/* - - nonnewline - emit REG_NEWLINE version of OANY - == static void nonnewline(register struct parse *p); - * - * Boy, is this implementation ever a kludge... - */ -static void -nonnewline(p) -register struct parse *p; -{ - register char *oldnext = p->next; - register char *oldend = p->end; - char bracket[4]; - - p->next = bracket; - p->end = bracket+3; - bracket[0] = '^'; - bracket[1] = '\n'; - bracket[2] = ']'; - bracket[3] = '\0'; - p_bracket(p); - assert(p->next == bracket+3); - p->next = oldnext; - p->end = oldend; -} - -/* - - repeat - generate code for a bounded repetition, recursively if needed - == static void repeat(register struct parse *p, sopno start, int from, int to); - */ -static void -repeat(p, start, from, to) -register struct parse *p; -sopno start; /* operand from here to end of strip */ -int from; /* repeated from this number */ -int to; /* to this number of times (maybe INFINITY) */ -{ - register sopno finish = HERE(); -# define N 2 -# define INF 3 -# define REP(f, t) ((f)*8 + (t)) -# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) - register sopno copy; - - if (p->error != 0) /* head off possible runaway recursion */ - return; - - assert(from <= to); - - switch (REP(MAP(from), MAP(to))) { - case REP(0, 0): /* must be user doing this */ - DROP(finish-start); /* drop the operand */ - break; - case REP(0, 1): /* as x{1,1}? */ - case REP(0, N): /* as x{1,n}? */ - case REP(0, INF): /* as x{1,}? */ - /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ - INSERT(OCH_, start); /* offset is wrong... */ - repeat(p, start+1, 1, to); - ASTERN(OOR1, start); - AHEAD(start); /* ... fix it */ - EMIT(OOR2, 0); - AHEAD(THERE()); - ASTERN(O_CH, THERETHERE()); - break; - case REP(1, 1): /* trivial case */ - /* done */ - break; - case REP(1, N): /* as x?x{1,n-1} */ - /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ - INSERT(OCH_, start); - ASTERN(OOR1, start); - AHEAD(start); - EMIT(OOR2, 0); /* offset very wrong... */ - AHEAD(THERE()); /* ...so fix it */ - ASTERN(O_CH, THERETHERE()); - copy = dupl(p, start+1, finish+1); - assert(copy == finish+4); - repeat(p, copy, 1, to-1); - break; - case REP(1, INF): /* as x+ */ - INSERT(OPLUS_, start); - ASTERN(O_PLUS, start); - break; - case REP(N, N): /* as xx{m-1,n-1} */ - copy = dupl(p, start, finish); - repeat(p, copy, from-1, to-1); - break; - case REP(N, INF): /* as xx{n-1,INF} */ - copy = dupl(p, start, finish); - repeat(p, copy, from-1, to); - break; - default: /* "can't happen" */ - SETERROR(REG_ASSERT); /* just in case */ - break; - } -} - -/* - - seterr - set an error condition - == static int seterr(register struct parse *p, int e); - */ -static int /* useless but makes type checking happy */ -seterr(p, e) -register struct parse *p; -int e; -{ - if (p->error == 0) /* keep earliest error condition */ - p->error = e; - p->next = nuls; /* try to bring things to a halt */ - p->end = nuls; - return(0); /* make the return value well-defined */ -} - -/* - - allocset - allocate a set of characters for [] - == static cset *allocset(register struct parse *p); - */ -static cset * -allocset(p) -register struct parse *p; -{ - register int no = p->g->ncsets++; - register size_t nc; - register size_t nbytes; - register cset *cs; - register size_t css = (size_t)p->g->csetsize; - register int i; - - if (no >= p->ncsalloc) { /* need another column of space */ - p->ncsalloc += CHAR_BIT; - nc = p->ncsalloc; - assert(nc % CHAR_BIT == 0); - nbytes = nc / CHAR_BIT * css; - if (p->g->sets == NULL) - p->g->sets = (cset *)malloc(nc * sizeof(cset)); - else - p->g->sets = (cset *)realloc((char *)p->g->sets, - nc * sizeof(cset)); - if (p->g->setbits == NULL) - p->g->setbits = (uch *)malloc(nbytes); - else { - p->g->setbits = (uch *)realloc((char *)p->g->setbits, - nbytes); - /* xxx this isn't right if setbits is now NULL */ - for (i = 0; i < no; i++) - p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); - } - if (p->g->sets != NULL && p->g->setbits != NULL) - (void) memset((char *)p->g->setbits + (nbytes - css), - 0, css); - else { - no = 0; - SETERROR(REG_ESPACE); - /* caller's responsibility not to do set ops */ - } - } - - assert(p->g->sets != NULL); /* xxx */ - cs = &p->g->sets[no]; - cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); - cs->mask = 1 << ((no) % CHAR_BIT); - cs->hash = 0; - cs->smultis = 0; - cs->multis = NULL; - - return(cs); -} - -/* - - freeset - free a now-unused set - == static void freeset(register struct parse *p, register cset *cs); - */ -static void -freeset(p, cs) -register struct parse *p; -register cset *cs; -{ - register int i; - register cset *top = &p->g->sets[p->g->ncsets]; - register size_t css = (size_t)p->g->csetsize; - - for (i = 0; i < css; i++) - CHsub(cs, i); - if (cs == top-1) /* recover only the easy case */ - p->g->ncsets--; -} - -/* - - freezeset - final processing on a set of characters - == static int freezeset(register struct parse *p, register cset *cs); - * - * The main task here is merging identical sets. This is usually a waste - * of time (although the hash code minimizes the overhead), but can win - * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash - * is done using addition rather than xor -- all ASCII [aA] sets xor to - * the same value! - */ -static int /* set number */ -freezeset(p, cs) -register struct parse *p; -register cset *cs; -{ - register uch h = cs->hash; - register int i; - register cset *top = &p->g->sets[p->g->ncsets]; - register cset *cs2; - register size_t css = (size_t)p->g->csetsize; - - /* look for an earlier one which is the same */ - for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) - if (cs2->hash == h && cs2 != cs) { - /* maybe */ - for (i = 0; i < css; i++) - if (!!CHIN(cs2, i) != !!CHIN(cs, i)) - break; /* no */ - if (i == css) - break; /* yes */ - } - - if (cs2 < top) { /* found one */ - freeset(p, cs); - cs = cs2; - } - - return((int)(cs - p->g->sets)); -} - -/* - - firstch - return first character in a set (which must have at least one) - == static int firstch(register struct parse *p, register cset *cs); - */ -static int /* character; there is no "none" value */ -firstch(p, cs) -register struct parse *p; -register cset *cs; -{ - register int i; - register size_t css = (size_t)p->g->csetsize; - - for (i = 0; i < css; i++) - if (CHIN(cs, i)) - return((char)i); - assert(never); - return(0); /* arbitrary */ -} - -/* - - nch - number of characters in a set - == static int nch(register struct parse *p, register cset *cs); - */ -static int -nch(p, cs) -register struct parse *p; -register cset *cs; -{ - register int i; - register size_t css = (size_t)p->g->csetsize; - register int n = 0; - - for (i = 0; i < css; i++) - if (CHIN(cs, i)) - n++; - return(n); -} - -/* - - mcadd - add a collating element to a cset - == static void mcadd(register struct parse *p, register cset *cs, \ - == register char *cp); - */ -static void -mcadd(p, cs, cp) -register struct parse *p; -register cset *cs; -register char *cp; -{ - register size_t oldend = cs->smultis; - - cs->smultis += strlen(cp) + 1; - if (cs->multis == NULL) - cs->multis = malloc(cs->smultis); - else - cs->multis = realloc(cs->multis, cs->smultis); - if (cs->multis == NULL) { - SETERROR(REG_ESPACE); - return; - } - - (void) strcpy(cs->multis + oldend - 1, cp); - cs->multis[cs->smultis - 1] = '\0'; -} - -/* - - mcsub - subtract a collating element from a cset - == static void mcsub(register cset *cs, register char *cp); - */ -static void -mcsub(cs, cp) -register cset *cs; -register char *cp; -{ - register char *fp = mcfind(cs, cp); - register size_t len = strlen(fp); - - assert(fp != NULL); - (void) memmove(fp, fp + len + 1, - cs->smultis - (fp + len + 1 - cs->multis)); - cs->smultis -= len; - - if (cs->smultis == 0) { - free(cs->multis); - cs->multis = NULL; - return; - } - - cs->multis = realloc(cs->multis, cs->smultis); - assert(cs->multis != NULL); -} - -/* - - mcin - is a collating element in a cset? - == static int mcin(register cset *cs, register char *cp); - */ -static int -mcin(cs, cp) -register cset *cs; -register char *cp; -{ - return(mcfind(cs, cp) != NULL); -} - -/* - - mcfind - find a collating element in a cset - == static char *mcfind(register cset *cs, register char *cp); - */ -static char * -mcfind(cs, cp) -register cset *cs; -register char *cp; -{ - register char *p; - - if (cs->multis == NULL) - return(NULL); - for (p = cs->multis; *p != '\0'; p += strlen(p) + 1) - if (strcmp(cp, p) == 0) - return(p); - return(NULL); -} - -/* - - mcinvert - invert the list of collating elements in a cset - == static void mcinvert(register struct parse *p, register cset *cs); - * - * This would have to know the set of possibilities. Implementation - * is deferred. - */ -static void -mcinvert(p, cs) -register struct parse *p; -register cset *cs; -{ - assert(cs->multis == NULL); /* xxx */ -} - -/* - - mccase - add case counterparts of the list of collating elements in a cset - == static void mccase(register struct parse *p, register cset *cs); - * - * This would have to know the set of possibilities. Implementation - * is deferred. - */ -static void -mccase(p, cs) -register struct parse *p; -register cset *cs; -{ - assert(cs->multis == NULL); /* xxx */ -} - -/* - - isinsets - is this character in any sets? - == static int isinsets(register struct re_guts *g, int c); - */ -static int /* predicate */ -isinsets(g, c) -register struct re_guts *g; -int c; -{ - register uch *col; - register int i; - register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; - register unsigned uc = (unsigned char)c; - - for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) - if (col[uc] != 0) - return(1); - return(0); -} - -/* - - samesets - are these two characters in exactly the same sets? - == static int samesets(register struct re_guts *g, int c1, int c2); - */ -static int /* predicate */ -samesets(g, c1, c2) -register struct re_guts *g; -int c1; -int c2; -{ - register uch *col; - register int i; - register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; - register unsigned uc1 = (unsigned char)c1; - register unsigned uc2 = (unsigned char)c2; - - for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) - if (col[uc1] != col[uc2]) - return(0); - return(1); -} - -/* - - categorize - sort out character categories - == static void categorize(struct parse *p, register struct re_guts *g); - */ -static void -categorize(p, g) -struct parse *p; -register struct re_guts *g; -{ - register cat_t *cats = g->categories; - register int c; - register int c2; - register cat_t cat; - - /* avoid making error situations worse */ - if (p->error != 0) - return; - - for (c = CHAR_MIN; c <= CHAR_MAX; c++) - if (cats[c] == 0 && isinsets(g, c)) { - cat = g->ncategories++; - cats[c] = cat; - for (c2 = c+1; c2 <= CHAR_MAX; c2++) - if (cats[c2] == 0 && samesets(g, c, c2)) - cats[c2] = cat; - } -} - -/* - - dupl - emit a duplicate of a bunch of sops - == static sopno dupl(register struct parse *p, sopno start, sopno finish); - */ -static sopno /* start of duplicate */ -dupl(p, start, finish) -register struct parse *p; -sopno start; /* from here */ -sopno finish; /* to this less one */ -{ - register sopno ret = HERE(); - register sopno len = finish - start; - - assert(finish >= start); - if (len == 0) - return(ret); - enlarge(p, p->ssize + len); /* this many unexpected additions */ - assert(p->ssize >= p->slen + len); - (void) memcpy((char *)(p->strip + p->slen), - (char *)(p->strip + start), (size_t)len*sizeof(sop)); - p->slen += len; - return(ret); -} - -/* - - doemit - emit a strip operator - == static void doemit(register struct parse *p, sop op, size_t opnd); - * - * It might seem better to implement this as a macro with a function as - * hard-case backup, but it's just too big and messy unless there are - * some changes to the data structures. Maybe later. - */ -static void -doemit(p, op, opnd) -register struct parse *p; -sop op; -size_t opnd; -{ - /* avoid making error situations worse */ - if (p->error != 0) - return; - - /* deal with oversize operands ("can't happen", more or less) */ - assert(opnd < 1<slen >= p->ssize) - enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ - assert(p->slen < p->ssize); - - /* finally, it's all reduced to the easy case */ - p->strip[p->slen++] = SOP(op, opnd); -} - -/* - - doinsert - insert a sop into the strip - == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); - */ -static void -doinsert(p, op, opnd, pos) -register struct parse *p; -sop op; -size_t opnd; -sopno pos; -{ - register sopno sn; - register sop s; - register int i; - - /* avoid making error situations worse */ - if (p->error != 0) - return; - - sn = HERE(); - EMIT(op, opnd); /* do checks, ensure space */ - assert(HERE() == sn+1); - s = p->strip[sn]; - - /* adjust paren pointers */ - assert(pos > 0); - for (i = 1; i < NPAREN; i++) { - if (p->pbegin[i] >= pos) { - p->pbegin[i]++; - } - if (p->pend[i] >= pos) { - p->pend[i]++; - } - } - - memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], - (HERE()-pos-1)*sizeof(sop)); - p->strip[pos] = s; -} - -/* - - dofwd - complete a forward reference - == static void dofwd(register struct parse *p, sopno pos, sop value); - */ -static void -dofwd(p, pos, value) -register struct parse *p; -register sopno pos; -sop value; -{ - /* avoid making error situations worse */ - if (p->error != 0) - return; - - assert(value < 1<strip[pos] = OP(p->strip[pos]) | value; -} - -/* - - enlarge - enlarge the strip - == static void enlarge(register struct parse *p, sopno size); - */ -static void -enlarge(p, size) -register struct parse *p; -register sopno size; -{ - register sop *sp; - - if (p->ssize >= size) - return; - - sp = (sop *)realloc(p->strip, size*sizeof(sop)); - if (sp == NULL) { - SETERROR(REG_ESPACE); - return; - } - p->strip = sp; - p->ssize = size; -} - -/* - - stripsnug - compact the strip - == static void stripsnug(register struct parse *p, register struct re_guts *g); - */ -static void -stripsnug(p, g) -register struct parse *p; -register struct re_guts *g; -{ - g->nstates = p->slen; - g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); - if (g->strip == NULL) { - SETERROR(REG_ESPACE); - g->strip = p->strip; - } -} - -/* - - findmust - fill in must and mlen with longest mandatory literal string - == static void findmust(register struct parse *p, register struct re_guts *g); - * - * This algorithm could do fancy things like analyzing the operands of | - * for common subsequences. Someday. This code is simple and finds most - * of the interesting cases. - * - * Note that must and mlen got initialized during setup. - */ -static void -findmust(p, g) -struct parse *p; -register struct re_guts *g; -{ - register sop *scan; - sop *start; - register sop *newstart; - register sopno newlen; - register sop s; - register char *cp; - register sopno i; - - /* avoid making error situations worse */ - if (p->error != 0) - return; - - /* find the longest OCHAR sequence in strip */ - newlen = 0; - scan = g->strip + 1; - do { - s = *scan++; - switch (OP(s)) { - case OCHAR: /* sequence member */ - if (newlen == 0) /* new sequence */ - newstart = scan - 1; - newlen++; - break; - case OPLUS_: /* things that don't break one */ - case OLPAREN: - case ORPAREN: - break; - case OQUEST_: /* things that must be skipped */ - case OCH_: - scan--; - do { - scan += OPND(s); - s = *scan; - /* assert() interferes w debug printouts */ - if (OP(s) != O_QUEST && OP(s) != O_CH && - OP(s) != OOR2) { - g->iflags |= BAD; - return; - } - } while (OP(s) != O_QUEST && OP(s) != O_CH); - /* fallthrough */ - default: /* things that break a sequence */ - if (newlen > g->mlen) { /* ends one */ - start = newstart; - g->mlen = newlen; - } - newlen = 0; - break; - } - } while (OP(s) != OEND); - - if (g->mlen == 0) /* there isn't one */ - return; - - /* turn it into a character string */ - g->must = malloc((size_t)g->mlen + 1); - if (g->must == NULL) { /* argh; just forget it */ - g->mlen = 0; - return; - } - cp = g->must; - scan = start; - for (i = g->mlen; i > 0; i--) { - while (OP(s = *scan++) != OCHAR) - continue; - assert(cp < g->must + g->mlen); - *cp++ = (char)OPND(s); - } - assert(cp == g->must + g->mlen); - *cp++ = '\0'; /* just on general principles */ -} - -/* - - pluscount - count + nesting - == static sopno pluscount(register struct parse *p, register struct re_guts *g); - */ -static sopno /* nesting depth */ -pluscount(p, g) -struct parse *p; -register struct re_guts *g; -{ - register sop *scan; - register sop s; - register sopno plusnest = 0; - register sopno maxnest = 0; - - if (p->error != 0) - return(0); /* there may not be an OEND */ - - scan = g->strip + 1; - do { - s = *scan++; - switch (OP(s)) { - case OPLUS_: - plusnest++; - break; - case O_PLUS: - if (plusnest > maxnest) - maxnest = plusnest; - plusnest--; - break; - } - } while (OP(s) != OEND); - if (plusnest != 0) - g->iflags |= BAD; - return(maxnest); -} diff --git a/sys/amiga/regex/regerror.c b/sys/amiga/regex/regerror.c deleted file mode 100755 index 54c1333d9..000000000 --- a/sys/amiga/regex/regerror.c +++ /dev/null @@ -1,186 +0,0 @@ -/* $NetBSD: regerror.c,v 1.4 1995/02/27 13:29:20 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)regerror.c 8.4 (Berkeley) 3/20/94 - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94"; -#else -static char rcsid[] = "$NetBSD: regerror.c,v 1.4 1995/02/27 13:29:20 cgd Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" - -/* ========= begin header generated by ./mkh ========= */ -#ifdef __cplusplus -extern "C" { -#endif - -/* === regerror.c === */ -static char *regatoi __P((const regex_t *preg, char *localbuf)); - -#ifdef __cplusplus -} -#endif -/* ========= end header generated by ./mkh ========= */ -/* - = #define REG_NOMATCH 1 - = #define REG_BADPAT 2 - = #define REG_ECOLLATE 3 - = #define REG_ECTYPE 4 - = #define REG_EESCAPE 5 - = #define REG_ESUBREG 6 - = #define REG_EBRACK 7 - = #define REG_EPAREN 8 - = #define REG_EBRACE 9 - = #define REG_BADBR 10 - = #define REG_ERANGE 11 - = #define REG_ESPACE 12 - = #define REG_BADRPT 13 - = #define REG_EMPTY 14 - = #define REG_ASSERT 15 - = #define REG_INVARG 16 - = #define REG_ATOI 255 // convert name to number (!) - = #define REG_ITOA 0400 // convert number to name (!) - */ -static struct rerr { - int code; - char *name; - char *explain; -} rerrs[] = { - REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match", - REG_BADPAT, "REG_BADPAT", "invalid regular expression", - REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element", - REG_ECTYPE, "REG_ECTYPE", "invalid character class", - REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)", - REG_ESUBREG, "REG_ESUBREG", "invalid backreference number", - REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced", - REG_EPAREN, "REG_EPAREN", "parentheses not balanced", - REG_EBRACE, "REG_EBRACE", "braces not balanced", - REG_BADBR, "REG_BADBR", "invalid repetition count(s)", - REG_ERANGE, "REG_ERANGE", "invalid character range", - REG_ESPACE, "REG_ESPACE", "out of memory", - REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid", - REG_EMPTY, "REG_EMPTY", "empty (sub)expression", - REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug", - REG_INVARG, "REG_INVARG", "invalid argument to regex routine", - 0, "", "*** unknown regexp error code ***", -}; - -/* - - regerror - the interface to error numbers - = extern size_t regerror(int, const regex_t *, char *, size_t); - */ -/* ARGSUSED */ -size_t -regerror(errcode, preg, errbuf, errbuf_size) -int errcode; -const regex_t *preg; -char *errbuf; -size_t errbuf_size; -{ - register struct rerr *r; - register size_t len; - register int target = errcode &~ REG_ITOA; - register char *s; - char convbuf[50]; - - if (errcode == REG_ATOI) - s = regatoi(preg, convbuf); - else { - for (r = rerrs; r->code != 0; r++) - if (r->code == target) - break; - - if (errcode®_ITOA) { - if (r->code != 0) - (void) strcpy(convbuf, r->name); - else - sprintf(convbuf, "REG_0x%x", target); - assert(strlen(convbuf) < sizeof(convbuf)); - s = convbuf; - } else - s = r->explain; - } - - len = strlen(s) + 1; - if (errbuf_size > 0) { - if (errbuf_size > len) - (void) strcpy(errbuf, s); - else { - (void) strncpy(errbuf, s, errbuf_size-1); - errbuf[errbuf_size-1] = '\0'; - } - } - - return(len); -} - -/* - - regatoi - internal routine to implement REG_ATOI - == static char *regatoi(const regex_t *preg, char *localbuf); - */ -static char * -regatoi(preg, localbuf) -const regex_t *preg; -char *localbuf; -{ - register struct rerr *r; - register size_t siz; - register char *p; - - for (r = rerrs; r->code != 0; r++) - if (strcmp(r->name, preg->re_endp) == 0) - break; - if (r->code == 0) - return("0"); - - sprintf(localbuf, "%d", r->code); - return(localbuf); -} diff --git a/sys/amiga/regex/regex2.h b/sys/amiga/regex/regex2.h deleted file mode 100755 index 901a6393b..000000000 --- a/sys/amiga/regex/regex2.h +++ /dev/null @@ -1,175 +0,0 @@ -/* $NetBSD: regex2.h,v 1.5 1995/02/27 13:29:40 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)regex2.h 8.4 (Berkeley) 3/20/94 - */ - -/* - * First, the stuff that ends up in the outside-world include file - = typedef off_t regoff_t; - = typedef struct { - = int re_magic; - = size_t re_nsub; // number of parenthesized subexpressions - = const char *re_endp; // end pointer for REG_PEND - = struct re_guts *re_g; // none of your business :-) - = } regex_t; - = typedef struct { - = regoff_t rm_so; // start of match - = regoff_t rm_eo; // end of match - = } regmatch_t; - */ -/* - * internals of regex_t - */ -#define MAGIC1 ((('r'^0200)<<8) | 'e') - -/* - * The internal representation is a *strip*, a sequence of - * operators ending with an endmarker. (Some terminology etc. is a - * historical relic of earlier versions which used multiple strips.) - * Certain oddities in the representation are there to permit running - * the machinery backwards; in particular, any deviation from sequential - * flow must be marked at both its source and its destination. Some - * fine points: - * - * - OPLUS_ and O_PLUS are *inside* the loop they create. - * - OQUEST_ and O_QUEST are *outside* the bypass they create. - * - OCH_ and O_CH are *outside* the multi-way branch they create, while - * OOR1 and OOR2 are respectively the end and the beginning of one of - * the branches. Note that there is an implicit OOR2 following OCH_ - * and an implicit OOR1 preceding O_CH. - * - * In state representations, an operator's bit is on to signify a state - * immediately *preceding* "execution" of that operator. - */ -typedef unsigned long sop; /* strip operator */ -typedef long sopno; -#define OPRMASK 0xf8000000 -#define OPDMASK 0x07ffffff -#define OPSHIFT ((unsigned)27) -#define OP(n) ((n)&OPRMASK) -#define OPND(n) ((n)&OPDMASK) -#define SOP(op, opnd) ((op)|(opnd)) -/* operators meaning operand */ -/* (back, fwd are offsets) */ -#define OEND (1< uch [csetsize] */ - uch mask; /* bit within array */ - uch hash; /* hash code */ - size_t smultis; - char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ -} cset; -/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ -#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) -#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) -#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) -#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */ -#define MCsub(p, cs, cp) mcsub(p, cs, cp) -#define MCin(p, cs, cp) mcin(p, cs, cp) - -/* stuff for character categories */ -typedef unsigned char cat_t; - -/* - * main compiled-expression structure - */ -struct re_guts { - int magic; -# define MAGIC2 ((('R'^0200)<<8)|'E') - sop *strip; /* malloced area for strip */ - int csetsize; /* number of bits in a cset vector */ - int ncsets; /* number of csets in use */ - cset *sets; /* -> cset [ncsets] */ - uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ - int cflags; /* copy of regcomp() cflags argument */ - sopno nstates; /* = number of sops */ - sopno firststate; /* the initial OEND (normally 0) */ - sopno laststate; /* the final OEND */ - int iflags; /* internal flags */ -# define USEBOL 01 /* used ^ */ -# define USEEOL 02 /* used $ */ -# define BAD 04 /* something wrong */ - int nbol; /* number of ^ used */ - int neol; /* number of $ used */ - int ncategories; /* how many character categories */ - cat_t *categories; /* ->catspace[-CHAR_MIN] */ - char *must; /* match must contain this string */ - int mlen; /* length of must */ - size_t nsub; /* copy of re_nsub */ - int backrefs; /* does it use back references? */ - sopno nplus; /* how deep does it nest +s? */ - /* catspace must be last */ - cat_t catspace[1]; /* actually [NC] */ -}; - -/* misc utilities */ -#define OUT (CHAR_MAX+1) /* a non-character value */ -#define ISWORD(c) (isalnum(c) || (c) == '_') diff --git a/sys/amiga/regex/regexec.c b/sys/amiga/regex/regexec.c deleted file mode 100755 index 3b8ef5341..000000000 --- a/sys/amiga/regex/regexec.c +++ /dev/null @@ -1,187 +0,0 @@ -/* $NetBSD: regexec.c,v 1.6 1995/02/27 13:29:48 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)regexec.c 8.3 (Berkeley) 3/20/94 - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94"; -#else -static char rcsid[] = "$NetBSD: regexec.c,v 1.6 1995/02/27 13:29:48 cgd Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -/* - * the outer shell of regexec() - * - * This file includes engine.h *twice*, after muchos fiddling with the - * macros that code uses. This lets the same code operate on two different - * representations for state sets. - */ -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" -#include "regex2.h" - -static int nope = 0; /* for use in asserts; shuts lint up */ - -/* macros for manipulating states, small version */ -#define states long -#define states1 states /* for later use in regexec() decision */ -#define CLEAR(v) ((v) = 0) -#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n))) -#define SET1(v, n) ((v) |= (unsigned long)1 << (n)) -#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0) -#define ASSIGN(d, s) ((d) = (s)) -#define EQ(a, b) ((a) == (b)) -#define STATEVARS long dummy /* dummy version */ -#define STATESETUP(m, n) /* nothing */ -#define STATETEARDOWN(m) /* nothing */ -#define SETUP(v) ((v) = 0) -#define onestate long -#define INIT(o, n) ((o) = (unsigned long)1 << (n)) -#define INC(o) ((o) = (unsigned long)(o) << 1) -#define ISSTATEIN(v, o) (((v) & (o)) != 0) -/* some abbreviations; note that some of these know variable names! */ -/* do "if I'm here, I can also be there" etc without branches */ -#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n)) -#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n)) -#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0) -/* function names */ -#define SNAMES /* engine.h looks after details */ - -#include "engine.h" - -/* now undo things */ -#undef states -#undef CLEAR -#undef SET0 -#undef SET1 -#undef ISSET -#undef ASSIGN -#undef EQ -#undef STATEVARS -#undef STATESETUP -#undef STATETEARDOWN -#undef SETUP -#undef onestate -#undef INIT -#undef INC -#undef ISSTATEIN -#undef FWD -#undef BACK -#undef ISSETBACK -#undef SNAMES - -/* macros for manipulating states, large version */ -#define states char * -#define CLEAR(v) memset(v, 0, m->g->nstates) -#define SET0(v, n) ((v)[n] = 0) -#define SET1(v, n) ((v)[n] = 1) -#define ISSET(v, n) ((v)[n]) -#define ASSIGN(d, s) memcpy(d, s, m->g->nstates) -#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) -#define STATEVARS long vn; char *space -#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ - if ((m)->space == NULL) return(REG_ESPACE); \ - (m)->vn = 0; } -#define STATETEARDOWN(m) { free((m)->space); } -#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) -#define onestate long -#define INIT(o, n) ((o) = (n)) -#define INC(o) ((o)++) -#define ISSTATEIN(v, o) ((v)[o]) -/* some abbreviations; note that some of these know variable names! */ -/* do "if I'm here, I can also be there" etc without branches */ -#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) -#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) -#define ISSETBACK(v, n) ((v)[here - (n)]) -/* function names */ -#define LNAMES /* flag */ - -#include "engine.h" - -/* - - regexec - interface for matching - = extern int regexec(const regex_t *, const char *, size_t, \ - = regmatch_t [], int); - = #define REG_NOTBOL 00001 - = #define REG_NOTEOL 00002 - = #define REG_STARTEND 00004 - = #define REG_TRACE 00400 // tracing of execution - = #define REG_LARGE 01000 // force large representation - = #define REG_BACKR 02000 // force use of backref code - * - * We put this here so we can exploit knowledge of the state representation - * when choosing which matcher to call. Also, by this point the matchers - * have been prototyped. - */ -int /* 0 success, REG_NOMATCH failure */ -regexec(preg, string, nmatch, pmatch, eflags) -const regex_t *preg; -const char *string; -size_t nmatch; -regmatch_t pmatch[]; -int eflags; -{ - register struct re_guts *g = preg->re_g; -#ifdef REDEBUG -# define GOODFLAGS(f) (f) -#else -# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) -#endif - - if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) - return(REG_BADPAT); - assert(!(g->iflags&BAD)); - if (g->iflags&BAD) /* backstop for no-debug case */ - return(REG_BADPAT); - eflags = GOODFLAGS(eflags); - - if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) - return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); - else - return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); -} diff --git a/sys/amiga/regex/regfree.c b/sys/amiga/regex/regfree.c deleted file mode 100755 index e01e30627..000000000 --- a/sys/amiga/regex/regfree.c +++ /dev/null @@ -1,86 +0,0 @@ -/* $NetBSD: regfree.c,v 1.4 1995/02/27 13:29:56 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)regfree.c 8.3 (Berkeley) 3/20/94 - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94"; -#else -static char rcsid[] = "$NetBSD: regfree.c,v 1.4 1995/02/27 13:29:56 cgd Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include - -#include "utils.h" -#include "regex2.h" - -/* - - regfree - free everything - = extern void regfree(regex_t *); - */ -void -regfree(preg) -regex_t *preg; -{ - register struct re_guts *g; - - if (preg->re_magic != MAGIC1) /* oops */ - return; /* nice to complain, but hard */ - - g = preg->re_g; - if (g == NULL || g->magic != MAGIC2) /* oops again */ - return; - preg->re_magic = 0; /* mark it invalid */ - g->magic = 0; /* mark it invalid */ - - if (g->strip != NULL) - free((char *)g->strip); - if (g->sets != NULL) - free((char *)g->sets); - if (g->setbits != NULL) - free((char *)g->setbits); - if (g->must != NULL) - free(g->must); - free((char *)g); -} diff --git a/sys/amiga/regex/utils.h b/sys/amiga/regex/utils.h deleted file mode 100755 index 2f372ce29..000000000 --- a/sys/amiga/regex/utils.h +++ /dev/null @@ -1,59 +0,0 @@ -/* $NetBSD: utils.h,v 1.5 1995/02/27 13:29:59 cgd Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 Henry Spencer. - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Henry Spencer. - * - * 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. - * - * @(#)utils.h 8.3 (Berkeley) 3/20/94 - */ - -/* utility definitions */ -#define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */ -#define INFINITY (DUPMAX + 1) -#define NC (CHAR_MAX - CHAR_MIN + 1) -typedef unsigned char uch; - -/* switch off assertions (if not already off) if no REDEBUG */ -#ifndef REDEBUG -#ifndef NDEBUG -#define NDEBUG /* no assertions please */ -#endif -#endif -#include - -/* for old systems with bcopy() but no memmove() */ -#ifdef USEBCOPY -#define memmove(d, s, c) bcopy(s, d, c) -#endif diff --git a/sys/unix/hints/include/cross-post.370 b/sys/unix/hints/include/cross-post.370 index 9d7b3a313..e3b792edd 100644 --- a/sys/unix/hints/include/cross-post.370 +++ b/sys/unix/hints/include/cross-post.370 @@ -269,7 +269,39 @@ $(TARGETPFX)tiles32.iff: ../dat/nhtiles.bmp $(TARGETPFX)bmp2iff_host AMITILES = $(TARGETPFX)tiles16.iff $(TARGETPFX)tiles32.iff $(TARGETPFX)tomb.iff -.PHONY: amigapkg amitiles +AMIREGEX_URL = https://github.com/garyhouston/regex.git +AMIREGEX_SRCDIR = $(AMISRC)/regex + +.PHONY: fetch-regex amigapkg amitiles + +fetch-regex: + @DSTDIR=sys/amiga/regex; \ + if [ ! -d src ]; then DSTDIR=../$$DSTDIR; fi; \ + if [ -f $$DSTDIR/regcomp.c ]; then \ + echo "BSD regex already present"; \ + else \ + echo "Fetching BSD regex from $(AMIREGEX_URL)"; \ + tmpdir=$$(mktemp -d) && \ + git clone --depth 1 $(AMIREGEX_URL) $$tmpdir && \ + cd $$tmpdir && \ + sh ./mkh -p regcomp.c > regcomp.ih && \ + sh ./mkh -p engine.c > engine.ih && \ + sh ./mkh -p regexec.c > regexec.ih && \ + sh ./mkh -p regerror.c > regerror.ih && \ + sh ./mkh -i _REGEX_H_ regex2.h regcomp.c \ + regexec.c regerror.c regfree.c > regex.h && \ + cd - > /dev/null && \ + mkdir -p $$DSTDIR && \ + for f in regcomp.c regexec.c regerror.c regfree.c \ + engine.c regex.h regex2.h cclass.h cname.h \ + utils.h regcomp.ih engine.ih regexec.ih \ + regerror.ih \ + COPYRIGHT; do \ + cp $$tmpdir/$$f $$DSTDIR/; \ + done && \ + rm -rf $$tmpdir && \ + echo "BSD regex installed in $$DSTDIR"; \ + fi amitiles: $(AMITILES) amigapkg: $(AMITILES) diff --git a/sys/unix/hints/include/cross-pre2.370 b/sys/unix/hints/include/cross-pre2.370 index d27301af1..9e873e978 100644 --- a/sys/unix/hints/include/cross-pre2.370 +++ b/sys/unix/hints/include/cross-pre2.370 @@ -472,6 +472,7 @@ ifdef CROSS_TO_AMIGA # Install to /opt/amiga, then: # sys/unix/setup.sh sys/unix/hints/linux.370 # make fetch-lua +# make CROSS_TO_AMIGA=1 fetch-regex # make CROSS_TO_AMIGA=1 all # make CROSS_TO_AMIGA=1 package #================================================================= From 2979030af146e65bfbab693073d649310530180b Mon Sep 17 00:00:00 2001 From: Ingo Paschke Date: Tue, 24 Mar 2026 02:37:02 +0100 Subject: [PATCH 8/8] Use NetHack's util/uudecode instead of system uudecode --- sys/unix/hints/include/cross-post.370 | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sys/unix/hints/include/cross-post.370 b/sys/unix/hints/include/cross-post.370 index e3b792edd..f28ec0fe1 100644 --- a/sys/unix/hints/include/cross-post.370 +++ b/sys/unix/hints/include/cross-post.370 @@ -304,7 +304,12 @@ fetch-regex: fi amitiles: $(AMITILES) -amigapkg: $(AMITILES) +UUDECODE = ../util/uudecode + +../util/uudecode: ../sys/share/uudecode.c + $(CC) $(CFLAGS) -o $@ $< + +amigapkg: $(AMITILES) ../util/uudecode mkdir -p $(TARGETPFX)pkg/tiles $(TARGETPFX)pkg/hack cp $(GAMEBIN) $(TARGETPFX)pkg/nethack cp ../dat/nhdat $(TARGETPFX)pkg/nhdat @@ -315,17 +320,17 @@ amigapkg: $(AMITILES) cp $(TARGETPFX)tomb.iff $(TARGETPFX)pkg/tomb.iff cp ../sys/msdos/sysconf $(TARGETPFX)pkg/sysconf cp ../doc/nethack.txt $(TARGETPFX)pkg/nethack.txt - ( cd $(TARGETPFX)pkg && uudecode ../../../sys/amiga/amifont8.uu && mv 8 hack/8 ) - ( cd $(TARGETPFX)pkg && uudecode ../../../sys/amiga/amifont.uu ) + ( cd $(TARGETPFX)pkg && ../../../util/uudecode ../../../sys/amiga/amifont8.uu && mv 8 hack/8 ) + ( cd $(TARGETPFX)pkg && ../../../util/uudecode ../../../sys/amiga/amifont.uu ) cp $(AMISRC)/nethack.cnf $(TARGETPFX)pkg/nethack.cnf -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/dflticon.uu && \ - uudecode ../../../sys/amiga/dflticon.uu ) + ../../../util/uudecode ../../../sys/amiga/dflticon.uu ) -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/NHinfo.uu && \ - uudecode ../../../sys/amiga/NHinfo.uu ) + ../../../util/uudecode ../../../sys/amiga/NHinfo.uu ) -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/NewGame.uu && \ - uudecode ../../../sys/amiga/NewGame.uu ) + ../../../util/uudecode ../../../sys/amiga/NewGame.uu ) -( cd $(TARGETPFX)pkg && test -f ../../../sys/amiga/HackWB.uu && \ - uudecode ../../../sys/amiga/HackWB.uu ) + ../../../util/uudecode ../../../sys/amiga/HackWB.uu ) touch $(TARGETPFX)pkg/record ( cd $(TARGETPFX)pkg && zip -9r ../NH370AMI.ZIP * ) @echo amiga package zip file $(TARGETPFX)NH370AMI.ZIP