Get nnn compile and run on Haiku (#403)

* Add support for Haiku OS

* Adjust DISTFILES and dist rule in haiku
This commit is contained in:
Anna Arad 2019-12-27 19:02:20 +01:00 committed by Mischievous Meerkat
parent d3ddff6690
commit fd9fcf741e
7 changed files with 317 additions and 5 deletions

View file

@ -1,4 +1,4 @@
VERSION = 2.8.1
include VERSION.mk
PREFIX ?= /usr/local
MANPREFIX ?= $(PREFIX)/share/man
@ -57,7 +57,7 @@ CFLAGS += $(CFLAGS_CURSES)
LDLIBS += $(LDLIBS_CURSES)
DISTFILES = src nnn.1 Makefile README.md LICENSE
DISTFILES = src nnn.1 Makefile README.md LICENSE VERSION.mk
SRC = src/nnn.c
HEADERS = src/nnn.h
BIN = nnn

1
VERSION.mk Normal file
View file

@ -0,0 +1 @@
VERSION = 2.8.1

117
misc/haiku/Makefile Normal file
View file

@ -0,0 +1,117 @@
include VERSION.mk
PREFIX ?= /boot/system/non-packaged
MANPREFIX ?= /boot/system/non-packaged/documentation/man
STRIP ?= strip
PKG_CONFIG ?= pkg-config
INSTALL ?= install
CP ?= cp
CFLAGS_OPTIMIZATION ?= -O3
O_DEBUG := 0
O_NORL := 0 # no readline support
O_NOLOC := 0 # no locale support
# convert targets to flags for backwards compatibility
ifneq ($(filter debug,$(MAKECMDGOALS)),)
O_DEBUG := 1
endif
ifneq ($(filter norl,$(MAKECMDGOALS)),)
O_NORL := 1
endif
ifneq ($(filter noloc,$(MAKECMDGOALS)),)
O_NORL := 1
O_NOLOC := 1
endif
ifeq ($(O_DEBUG),1)
CPPFLAGS += -DDBGMODE
CFLAGS += -g
LDLIBS += -lrt
endif
ifeq ($(O_NORL),1)
CPPFLAGS += -DNORL
else
LDLIBS += -lreadline
endif
ifeq ($(O_NOLOC),1)
CPPFLAGS += -DNOLOCALE
endif
ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw)
LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs ncursesw)
else ifeq ($(shell $(PKG_CONFIG) ncurses && echo 1),1)
CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncurses)
LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs ncurses)
else
LDLIBS_CURSES ?= -lncurses
endif
ifeq ($(shell uname -s), Haiku)
LDLIBS_HAIKU ?= -lstdc++ -lbe
SRC_HAIKU ?= misc/haiku/nm.cpp
OBJS_HAIKU ?= misc/haiku/nm.o
endif
CFLAGS += -Wall -Wextra
CFLAGS += $(CFLAGS_OPTIMIZATION)
CFLAGS += $(CFLAGS_CURSES)
LDLIBS += $(LDLIBS_CURSES) $(LDLIBS_HAIKU)
DISTFILES = src nnn.1 Makefile README.md LICENSE VERSION.mk
SRC = src/nnn.c
HEADERS = src/nnn.h
BIN = nnn
OBJS := nnn.o $(OBJS_HAIKU)
all: $(BIN)
ifeq ($(shell uname -s), Haiku)
$(OBJS_HAIKU): $(SRC_HAIKU)
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
endif
nnn.o: $(SRC) $(HEADERS)
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
# targets for backwards compatibility
debug: $(BIN)
norl: $(BIN)
noloc: $(BIN)
install: all
$(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin
$(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin
$(INSTALL) -m 0755 -d $(DESTDIR)$(MANPREFIX)/man1
$(INSTALL) -m 0644 $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1
uninstall:
$(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN)
$(RM) $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1
strip: $(BIN)
$(STRIP) $^
dist:
mkdir -p nnn-$(VERSION)
$(CP) -r $(DISTFILES) nnn-$(VERSION)
mkdir -p nnn-$(VERSION)/misc
$(CP) -r misc/haiku nnn-$(VERSION)/misc
tar -cf nnn-$(VERSION).tar nnn-$(VERSION)
gzip nnn-$(VERSION).tar
$(RM) -r nnn-$(VERSION)
clean:
$(RM) -f $(BIN) $(OBJS) nnn-$(VERSION).tar.gz
skip: ;
.PHONY: all debug install uninstall strip dist clean

View file

@ -0,0 +1,14 @@
#ifdef __cplusplus
extern "C" {
#endif
typedef struct haiku_nm_t *haiku_nm_h;
haiku_nm_h haiku_init_nm();
void haiku_close_nm(haiku_nm_h hnd);
int haiku_watch_dir(haiku_nm_h hnd, const char *path);
int haiku_stop_watch(haiku_nm_h hnd);
int haiku_is_update_needed(haiku_nm_h hnd);
#ifdef __cplusplus
}
#endif

83
misc/haiku/nm.cpp Normal file
View file

@ -0,0 +1,83 @@
#include <Directory.h>
#include <Looper.h>
#include <NodeMonitor.h>
#include <MessageFilter.h>
#include "haiku_interop.h"
filter_result dir_mon_flt(BMessage *message, BHandler **hnd, BMessageFilter *fltr) {
(void) hnd;
(void) fltr;
if (message->what == B_NODE_MONITOR) {
int32 val;
message->FindInt32("opcode", &val);
switch (val) {
case B_ENTRY_CREATED:
case B_ENTRY_MOVED:
case B_ENTRY_REMOVED:
return B_DISPATCH_MESSAGE;
}
}
return B_SKIP_MESSAGE;
}
class DirectoryListener : public BLooper {
public:
bool recv_reset() {
Lock();
bool val = _ev_on;
_ev_on = false;
Unlock();
return val;
}
private:
void MessageReceived(BMessage * message) override {
Lock();
_ev_on = true;
Unlock();
BLooper::MessageReceived(message);
}
bool _ev_on = false;
};
struct haiku_nm_t {
haiku_nm_t() {
dl = new DirectoryListener();
flt = new BMessageFilter(B_PROGRAMMED_DELIVERY, B_LOCAL_SOURCE, dir_mon_flt);
dl->AddCommonFilter(flt);
dl->Run();
}
DirectoryListener *dl;
BMessageFilter *flt;
node_ref nr;
};
haiku_nm_h haiku_init_nm() {
return new haiku_nm_t();
}
void haiku_close_nm(haiku_nm_h hnd) {
delete hnd->flt;
// This is the way of deleting a BLooper
hnd->dl->PostMessage(B_QUIT_REQUESTED);
delete hnd;
}
int haiku_watch_dir(haiku_nm_h hnd, const char *path) {
BDirectory dir(path);
dir.GetNodeRef(&(hnd->nr));
return watch_node(&(hnd->nr), B_WATCH_DIRECTORY, nullptr, hnd->dl);
}
int haiku_stop_watch(haiku_nm_h hnd) {
return watch_node(&(hnd->nr), B_STOP_WATCHING, nullptr, hnd->dl);
}
int haiku_is_update_needed(haiku_nm_h hnd) {
return hnd->dl->recv_reset();
}

View file

@ -0,0 +1,52 @@
SUMMARY="The missing terminal file manager for X"
DESCRIPTION="
nnn is a full-featured terminal file manager. It's tiny and nearly 0-config with an incredible performance.
nnn is also a du analyzer, an app launcher, a batch renamer and a file picker. The plugin repository has tons of plugins and documentation to extend the capabilities further. You can plug new functionality and play with a custom keybind instantly. There's an independent (neo)vim plugin.
It runs smoothly on the Raspberry Pi, Termux on Android, Linux, macOS, BSD, Cygwin, WSL and works seamlessly with DEs and GUI utilities.
Visit the Wiki for concepts, program usage, how-tos and troubleshooting.
"
HOMEPAGE="https://github.com/jarun/nnn"
COPYRIGHT="2016-2019 Arun Prakash Jana"
LICENSE="BSD (2-clause)"
REVISION="1"
SOURCE_URI="git://github.com/jarun/nnn.git"
ARCHITECTURES="x86 x86_64"
PROVIDES="
nnn = $portVersion
cmd:nnn = $portVersion
"
REQUIRES="
haiku
lib:libncurses
lib:libreadline
"
BUILD_REQUIRES="
haiku_devel
pkgconfig
devel:libncurses
devel:libreadline
"
BUILD_PREREQUIRES="
cmd:make
cmd:gcc
cmd:g++
cmd:ld
cmd:install
"
BUILD()
{
make -f misc/haiku/Makefile
}
INSTALL()
{
make -f misc/haiku/Makefile PREFIX=$prefix MANPREFIX=$manDir install
}

View file

@ -49,6 +49,9 @@
#include <sys/event.h>
#include <sys/time.h>
#define BSD_KQUEUE
#elif defined(__HAIKU__)
#include "../misc/haiku/haiku_interop.h"
#define HAIKU_NM
#else
#include <sys/sysmacros.h>
#endif
@ -570,6 +573,9 @@ static struct kevent events_to_monitor[NUM_EVENT_FDS];
static uint KQUEUE_FFLAGS = NOTE_DELETE | NOTE_EXTEND | NOTE_LINK
| NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE;
static struct timespec gtimeout;
#elif defined(HAIKU_NM)
static bool haiku_nm_active = FALSE;
static haiku_nm_h haiku_hnd = NULL;
#endif
/* Function macros */
@ -1892,6 +1898,8 @@ static int nextsel(int presel)
struct kevent event_data[NUM_EVENT_SLOTS];
memset((void *)event_data, 0x0, sizeof(struct kevent) * NUM_EVENT_SLOTS);
#elif defined(HAIKU_NM)
// TODO: Do some Haiku declarations
#endif
if (c == 0 || c == MSGWAIT) {
@ -1947,6 +1955,9 @@ static int nextsel(int presel)
&& kevent(kq, events_to_monitor, NUM_EVENT_SLOTS,
event_data, NUM_EVENT_FDS, &gtimeout) > 0)
c = CONTROL('L');
#elif defined(HAIKU_NM)
if (!cfg.selmode && !cfg.blkorder && haiku_nm_active && idle & 1 && haiku_is_update_needed(haiku_hnd))
c = CONTROL('L');
#endif
} else
idle = 0;
@ -3250,12 +3261,25 @@ static bool xmktree(char* path, bool dir)
/* Create folder from path to '\0' inserted at p */
if (mkdir(path, 0777) == -1 && errno != EEXIST) {
#ifdef __HAIKU__
// XDG_CONFIG_HOME contains a directory
// that is read-only, but the full path
// is writeable.
// Try to continue and see what happens.
// TODO: Find a more robust solution.
if (errno == B_READ_ONLY_DEVICE) {
goto next;
}
#endif
DPRINTF_S("mkdir1!");
DPRINTF_S(strerror(errno));
*slash = '/';
return FALSE;
}
#ifdef __HAIKU__
next:
#endif
/* Restore path */
*slash = '/';
++p;
@ -3774,7 +3798,7 @@ static int dentfill(char *path, struct entry **dents)
if (!dp)
goto exit;
#ifdef __sun
#if defined(__sun) || defined(__HAIKU__)
flags = AT_SYMLINK_NOFOLLOW; /* no d_type */
#else
if (cfg.blkorder || dp->d_type == DT_UNKNOWN) {
@ -3878,7 +3902,7 @@ static int dentfill(char *path, struct entry **dents)
/* Copy other fields */
dentp->t = cfg.mtime ? sb.st_mtime : sb.st_atime;
#ifndef __sun
#if !(defined(__sun) || defined(__HAIKU__))
if (!flags && dp->d_type == DT_LNK) {
/* Do not add sizes for links */
dentp->mode = (sb.st_mode & ~S_IFMT) | S_IFLNK;
@ -3926,7 +3950,7 @@ static int dentfill(char *path, struct entry **dents)
if (S_ISDIR(sb.st_mode))
dentp->flags |= DIR_OR_LINK_TO_DIR;
#ifndef __sun /* no d_type */
#if !(defined(__sun) || defined(__HAIKU__)) /* no d_type */
} else if (dp->d_type == DT_DIR || (dp->d_type == DT_LNK && S_ISDIR(sb.st_mode))) {
dentp->flags |= DIR_OR_LINK_TO_DIR;
#endif
@ -4321,6 +4345,12 @@ begin:
event_fd = -1;
dir_changed = FALSE;
}
#elif defined(HAIKU_NM)
if ((presel == FILTER || dir_changed) && haiku_hnd != NULL) {
haiku_stop_watch(haiku_hnd);
haiku_nm_active = FALSE;
dir_changed = FALSE;
}
#endif
/* Can fail when permissions change while browsing.
@ -4352,6 +4382,8 @@ begin:
EV_SET(&events_to_monitor[0], event_fd, EVFILT_VNODE,
EV_ADD | EV_CLEAR, KQUEUE_FFLAGS, 0, path);
}
#elif defined(HAIKU_NM)
haiku_nm_active = haiku_watch_dir(haiku_hnd, path) == _SUCCESS;
#endif
while (1) {
@ -4726,6 +4758,11 @@ nochange:
close(event_fd);
event_fd = -1;
}
#elif defined(HAIKU_NM)
if (haiku_nm_active) {
haiku_stop_watch(haiku_hnd);
haiku_nm_active = FALSE;
}
#endif
presel = filterentries(path, lastname);
@ -5852,6 +5889,12 @@ int main(int argc, char *argv[])
xerror();
return _FAILURE;
}
#elif defined(HAIKU_NM)
haiku_hnd = haiku_init_nm();
if (!haiku_hnd) {
xerror();
return _FAILURE;
}
#endif
/* Set nnn nesting level */
@ -5950,6 +5993,8 @@ int main(int argc, char *argv[])
if (event_fd >= 0)
close(event_fd);
close(kq);
#elif defined(HAIKU_NM)
haiku_close_nm(haiku_hnd);
#endif
return _SUCCESS;