aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbhgv <bhgv.empire@gmail.com>2019-03-06 02:50:05 +0300
committerbhgv <bhgv.empire@gmail.com>2019-03-06 02:50:05 +0300
commitd1a1a29bd5779e3a7e0d6ac4a6572eda5b28a943 (patch)
tree77264b473051fc6569dc4e30c609804d725c37b2
parentc8a8f18fa610d27eb73d1d79a5f9f6a306fdf225 (diff)
Linux-Framebuffer graphics output was added. now no X needed for Inferno-graphics/GUI.
-rw-r--r--Linux/arm/include/emu.h6
-rw-r--r--appl/alphabet/typesets/mkfile2
-rw-r--r--appl/mkfile2
-rwxr-xr-xbld-lin-fb-arm.sh14
-rwxr-xr-xbld-lin.sh2
-rwxr-xr-xcln.sh9
-rw-r--r--emu/Linux/emu2
-rw-r--r--emu/Linux/mkfile5
-rw-r--r--emu/Linux/win-fb.c1387
-rw-r--r--emu/port/devdraw.c1
-rw-r--r--libinterp/runt.h4
-rw-r--r--mkconfig4
-rw-r--r--mkfile2
-rw-r--r--mkfiles/mkfile-Linux-arm8
-rw-r--r--os/port/sysfile.c1
15 files changed, 1427 insertions, 22 deletions
diff --git a/Linux/arm/include/emu.h b/Linux/arm/include/emu.h
index 7f2b101..c05e230 100644
--- a/Linux/arm/include/emu.h
+++ b/Linux/arm/include/emu.h
@@ -4,6 +4,9 @@
* implementation of the current-process variable `up'.
*/
+#ifndef _EMU_H_
+#define _EMU_H_
+
/*
* This structure must agree with FPsave and FPrestore asm routines
*/
@@ -32,3 +35,6 @@ extern Proc* getup(void);
typedef sigjmp_buf osjmpbuf;
#define ossetjmp(buf) sigsetjmp(buf, 1)
+
+
+#endif //_EMU_H_ \ No newline at end of file
diff --git a/appl/alphabet/typesets/mkfile b/appl/alphabet/typesets/mkfile
index dc0a0a8..517409d 100644
--- a/appl/alphabet/typesets/mkfile
+++ b/appl/alphabet/typesets/mkfile
@@ -28,7 +28,7 @@ DISBIN=$ROOT/dis/alphabet
<$ROOT/mkfiles/mkdis
-LIMBOFLAGS=$LIMBOFLAGS -i -F
+LIMBOFLAGS=$LIMBOFLAGS -i -Ialphabet -F
#%.b %types.b %.m %types.m: %.typeset
# mktypeset $stem.typeset
diff --git a/appl/mkfile b/appl/mkfile
index 9a30387..dcf7f56 100644
--- a/appl/mkfile
+++ b/appl/mkfile
@@ -2,7 +2,7 @@
DIRS=\
acme\
- alphabet\
+# alphabet\
charon\
cmd\
collab\
diff --git a/bld-lin-fb-arm.sh b/bld-lin-fb-arm.sh
new file mode 100755
index 0000000..ecdb9d0
--- /dev/null
+++ b/bld-lin-fb-arm.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+mkdir Linux/arm/bin
+mkdir Linux/arm/lib
+
+export PATH=/opt/gcc-arm-8.2-2018.11-x86_64-arm-linux-gnueabihf/bin:$PWD/Linux/386/bin:$PATH
+
+export ROOT=$PWD
+
+export CROSS=arm-linux-gnueabihf-
+
+unzip -n dis_folders.zip
+
+mk install
diff --git a/bld-lin.sh b/bld-lin.sh
index d904cf3..611f953 100755
--- a/bld-lin.sh
+++ b/bld-lin.sh
@@ -1,5 +1,7 @@
#!/bin/sh
+mkdir acme/dis
+
export ROOT=$PWD
export PATH=$PWD/Linux/386/bin:$PATH
diff --git a/cln.sh b/cln.sh
index 95798d1..819d940 100755
--- a/cln.sh
+++ b/cln.sh
@@ -1,13 +1,6 @@
#!/bin/sh
-#export NDK=$PWD/../android-ndk-r10e
-
-#python %NDK%/build/tools/make_standalone_toolchain.py -v --arch arm --api 17 --install-dir=ndk_toolchain
-
-export ANDR_TOOLCHAIN=$PWD/../toolchain
-#$(NDK)/build/tools/make-standalone-toolchain.sh --platform=android-14 --arch=arm --install-dir=$(ANDR_TOOLCHAIN) --ndk-dir=$(NDK) #--system=windows-x86_64
-
-export PATH=$PWD/Linux/386/bin:$ANDR_TOOLCHAIN/bin:$PATH
+export PATH=$PWD/Linux/386/bin:$PATH
export ROOT=$PWD
diff --git a/emu/Linux/emu b/emu/Linux/emu
index addbf49..d1ab248 100644
--- a/emu/Linux/emu
+++ b/emu/Linux/emu
@@ -14,7 +14,7 @@ dev
cmd cmd
indir
- draw win-x11a
+ draw win-$WINDOW_BACKEND
pointer
snarf
diff --git a/emu/Linux/mkfile b/emu/Linux/mkfile
index 3b072d5..2c0b00c 100644
--- a/emu/Linux/mkfile
+++ b/emu/Linux/mkfile
@@ -35,9 +35,10 @@ LIBNAMES=${LIBS:%=lib%.a}
HFILES=\
+KERNDATE=1234567 #`{$NDATE}
CFLAGS='-DROOT="'$ROOT'"' -DEMU -I. -I../port -I$ROOT/$SYSTARG/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp $CTHREADFLAGS $CFLAGS $EMUOPTIONS
-SYSLIBS= $X11LIBS -lm -lpthread
-KERNDATE=`{$NDATE}
+#SYSLIBS= $X11LIBS -lm -lpthread
+SYSLIBS= -lm -lpthread
default:V: $O.$CONF
diff --git a/emu/Linux/win-fb.c b/emu/Linux/win-fb.c
new file mode 100644
index 0000000..f924ed2
--- /dev/null
+++ b/emu/Linux/win-fb.c
@@ -0,0 +1,1387 @@
+/*
+ * This implementation of the screen functions for X11 uses the
+ * portable implementation of the Inferno drawing operations (libmemdraw)
+ * to do the work, then has flushmemscreen copy the result to the X11 display.
+ * Thus it potentially supports all colour depths but with a possible
+ * performance penalty (although it tries to use the X11 shared memory extension
+ * to copy the result to the screen, which might reduce the latter).
+ *
+ * CraigN
+ */
+
+#define _GNU_SOURCE 1
+//#define XTHREADS
+#include "dat.h"
+#include "fns.h"
+#undef log2
+#include <draw.h>
+#include "cursor.h"
+#include "keyboard.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <linux/fb.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+
+//#include "keysym2ucs.h"
+
+#include <sys/ipc.h>
+//#include <sys/shm.h>
+
+#define LOG_TAG "Inferno WIN"
+#define LOGI(...) printf(__VA_ARGS__)
+#define LOGW(...) printf(__VA_ARGS__)
+#define LOGE(...) printf(__VA_ARGS__)
+
+
+
+static int displaydepth = 32;
+static ulong displaychan = CHAN4(CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8);
+
+enum
+{
+ DblTime = 300 /* double click time in msec */
+};
+
+/* screen data .... */
+static uchar* gscreendata = NULL;
+static uchar* xscreendata = NULL;
+
+//typedef unsigned int XColor;
+
+uchar map7to8[128][2];
+
+/* for copy/paste, lifted from plan9ports via drawterm */
+//static Atom clipboard;
+//static Atom utf8string;
+//static Atom targets;
+//static Atom text;
+//static Atom compoundtext;
+
+//static Atom cursorchange;
+
+static int triedscreen = 0;
+
+void xexpose(); //XEvent*);
+static void xmouse(); //XEvent*);
+static void xkeyboard(); ///*XEvent*/void*);
+//static void xsetcursor(/*XEvent*/void*);
+static void xkbdproc(void*);
+//static void xdestroy(XEvent*);
+//static void xselect(XEvent*, XDisplay*);
+static void xproc(void*);
+
+static int xscreendepth;
+
+static int putsnarf, assertsnarf;
+//char *gkscanid = "emu_x11";
+
+
+extern int Xsize;
+extern int Ysize;
+
+
+/*
+ * The documentation for the XSHM extension implies that if the server
+ * supports XSHM but is not the local machine, the XShm calls will
+ * return False; but this turns out not to be the case. Instead, the
+ * server throws a BadAccess error. So, we need to catch X errors
+ * around all of our XSHM calls, sigh.
+ */
+//static int shm_got_x_error = 0;
+//static XErrorHandler old_handler = 0;
+//static XErrorHandler old_io_handler = 0;
+
+
+
+struct {
+ int fd;
+ uchar* base;
+ uchar* data;
+
+ int width;
+ int height;
+ int bpp;
+ int stride;
+
+ int alloc;
+} fb;
+
+
+
+static uchar*
+attach_fb()
+{
+ struct fb_var_screeninfo fb_var;
+ struct fb_fix_screeninfo fb_fix;
+ int off;
+
+ fb.alloc = 0;
+ fb.fd = -1;
+
+ if ((fb.fd = open ("/dev/fb0", O_RDWR)) < 0)
+ {
+ LOGE ("Error opening /dev/fb0");
+ return NULL;
+ }
+
+ if (ioctl (fb.fd, FBIOGET_VSCREENINFO, &fb_var) == -1)
+ {
+ LOGE ("Error getting variable framebuffer info");
+ return NULL;
+ }
+
+ if (fb_var.bits_per_pixel < 16)
+ {
+ fprintf(stderr,
+ "Error, no support currently for %i bpp frame buffers\n"
+ "Trying to change pixel format...\n",
+ fb_var.bits_per_pixel);
+ return NULL;
+ }
+
+ if (ioctl (fb.fd, FBIOGET_VSCREENINFO, &fb_var) == -1)
+ {
+ LOGE ("Error getting variable framebuffer info (2)");
+ return NULL;
+ }
+
+ /* NB: It looks like the fbdev concept of fixed vs variable screen info is
+ * broken. The line_length is part of the fixed info but it can be changed
+ * if you set a new pixel format. */
+ if (ioctl (fb.fd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
+ {
+ LOGE ("Error getting fixed framebuffer info");
+ return NULL;
+ }
+ /*fb.real_width =*/ Xsize = fb.width = fb_var.xres;
+ /*fb.real_height =*/ Ysize = fb.height = fb_var.yres;
+
+ fb.bpp = fb_var.bits_per_pixel;
+ fb.stride = fb_fix.line_length;
+
+/*
+ fb.type = fb_fix.type;
+ fb.visual = fb_fix.visual;
+
+ fb.red_offset = fb_var.red.offset;
+ fb.red_length = fb_var.red.length;
+ fb.green_offset = fb_var.green.offset;
+ fb.green_length = fb_var.green.length;
+ fb.blue_offset = fb_var.blue.offset;
+ fb.blue_length = fb_var.blue.length;
+
+ if (fb.red_offset == 11 && fb.red_length == 5 &&
+ fb.green_offset == 5 && fb.green_length == 6 &&
+ fb.blue_offset == 0 && fb.blue_length == 5) {
+ fb.rgbmode = RGB565;
+ } else if (fb.red_offset == 0 && fb.red_length == 5 &&
+ fb.green_offset == 5 && fb.green_length == 6 &&
+ fb.blue_offset == 11 && fb.blue_length == 5) {
+ fb.rgbmode = BGR565;
+ } else if (fb.red_offset == 16 && fb.red_length == 8 &&
+ fb.green_offset == 8 && fb.green_length == 8 &&
+ fb.blue_offset == 0 && fb.blue_length == 8) {
+ fb.rgbmode = fb.bpp == 32 ? ARGB888 : RGB888;
+ } else if (fb.red_offset == 0 && fb.red_length == 8 &&
+ fb.green_offset == 8 && fb.green_length == 8 &&
+ fb.blue_offset == 8 && fb.blue_length == 8) {
+ fb.rgbmode = fb.bpp == 32 ? ABGR888 : BGR888;
+ } else {
+ fb.rgbmode = GENERIC;
+ }
+*/
+ LOGI("width: %i, height: %i, bpp: %i, stride: %i\n",
+ fb.width, fb.height, fb.bpp, fb.stride);
+
+ size_t size = fb.stride * fb.height;
+
+ fb.base = (char *) mmap ((caddr_t) NULL,
+ /*fb_fix.smem_len */
+ size,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ fb.fd, 0);
+
+ if (fb.base == (char *)-1)
+ {
+ LOGE("Error cannot mmap framebuffer. Using malloc instead.\n");
+ fb.base = (char*)malloc(size);
+ if (!fb.base)
+ {
+ LOGE("Error cannot allocate memory.");
+ return NULL;
+ }
+ fb.alloc = 1;
+ }
+
+ off = (unsigned long) fb_fix.smem_start % (unsigned long) getpagesize();
+
+ fb.data = fb.base + off;
+
+ return fb.data;
+}
+
+
+
+uchar*
+attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen)
+{
+ int depth;
+LOGE("attachscreen\n");
+
+ if(triedscreen)
+ return gscreendata;
+
+ triedscreen = 1;
+
+ //if(gscreendata != xscreendata)
+ // kproc("xproc", xproc, NULL/*xmcon*/, 0);
+// kproc("xkbdproc", xkbdproc, NULL/*xkbdcon*/, 0/*KPX11*/); /* silly stack size for bloated X11 */
+
+//#undef malloc
+//#define malloc malloc_
+ xscreendata = attach_fb(); //malloc(Xsize * Ysize * 4);
+ xscreendepth = fb.bpp; //32;
+
+ Xsize &= ~0x3; /* ensure multiple of 4 */
+
+ r->min.x = 0;
+ r->min.y = 0;
+ r->max.x = Xsize;
+ r->max.y = Ysize;
+
+ /*
+ * moved xproc from here to end since it could cause an expose event and
+ * hence a flushmemscreen before xscreendata is initialized
+ */
+
+ *chan = displaychan; /* not every channel description will work */
+ *d = chantodepth(displaychan);
+ displaydepth = *d;
+
+ printf("%s:%d displaychan=%X, displaydepth=%d\n", __func__, __LINE__, displaychan, displaydepth);
+
+// gscreendata = xscreendata;
+ gscreendata = malloc(Xsize * (Ysize+1) * (displaydepth >> 3));
+
+ LOGE("attachscreen: gscreendata=%x, (displaydepth>>3)=%d\n", gscreendata, (displaydepth>>3));
+
+ *width = (Xsize/4)*(*d/8);
+ *softscreen = 1;
+
+ return gscreendata;
+}
+
+
+static void
+copy32to32(Rectangle r)
+{
+ int dx, width;
+ uchar *p, *ep, *cp;
+ u32int v, w, *dp, *wp, *edp, *lp;
+
+LOGE("copy32to32");
+ width = Dx(r);
+ dx = Xsize - width;
+ dp = (u32int*)(gscreendata + (r.min.y * Xsize + r.min.x) * 4);
+ wp = (u32int*)(xscreendata + (r.min.y * Xsize + r.min.x) * 4);
+ edp = (u32int*)(gscreendata + (r.max.y * Xsize + r.max.x) * 4);
+ while(dp < edp) {
+ lp = dp + width;
+ while(dp < lp){
+ v = *dp++;
+ //w = v
+// infernortox11[ (v >> 16) & 0xff ] << 16
+// | infernogtox11[ (v >> 8) & 0xff ] << 8
+// | infernobtox11[ (v >> 0) & 0xff ] << 0
+ //;
+ *wp++ = v; //w;
+ }
+ dp += dx;
+ wp += dx;
+ }
+}
+
+static void
+copy8to32(Rectangle r)
+{
+ int dx, width;
+ uchar *p, *ep, *lp;
+ u32int *wp;
+
+LOGE("copy8to32");
+ width = Dx(r);
+ dx = Xsize - width;
+ p = gscreendata + r.min.y * Xsize + r.min.x;
+ wp = (u32int *)(xscreendata + (r.min.y * Xsize + r.min.x) * 4);
+ ep = gscreendata + r.max.y * Xsize + r.max.x;
+ while(p < ep) {
+ lp = p + width;
+ while(p < lp)
+ *wp++ = *p++; //infernotox11[*p++];
+ p += dx;
+ wp += dx;
+ }
+}
+
+static void
+copy8to24(Rectangle r)
+{
+ int dx, width, v;
+ uchar *p, *cp, *ep, *lp;
+
+LOGE("copy8to24");
+ width = Dx(r);
+ dx = Xsize - width;
+ p = gscreendata + r.min.y * Xsize + r.min.x;
+ cp = xscreendata + (r.min.y * Xsize + r.min.x) * 3;
+ ep = gscreendata + r.max.y * Xsize + r.max.x;
+ while(p < ep) {
+ lp = p + width;
+ while(p < lp){
+ v = *p++; //infernotox11[*p++];
+ cp[0] = (v>>16)&0xff;
+ cp[1] = (v>>8)&0xff;
+ cp[2] = (v>>0)&0xff;
+ cp += 3;
+ }
+ p += dx;
+ cp += 3*dx;
+ }
+}
+
+static void
+copy8to16(Rectangle r)
+{
+ int dx, width;
+ uchar *p, *ep, *lp;
+ u16int *sp;
+
+LOGE("copy8to16");
+ width = Dx(r);
+ dx = Xsize - width;
+ p = gscreendata + r.min.y * Xsize + r.min.x;
+ sp = (unsigned short *)(xscreendata + (r.min.y * Xsize + r.min.x) * 2);
+ ep = gscreendata + r.max.y * Xsize + r.max.x;
+ while(p < ep) {
+ lp = p + width;
+ while(p < lp)
+ *sp++ = *p++; //infernotox11[*p++];
+ p += dx;
+ sp += dx;
+ }
+}
+
+static void
+copy8to8(Rectangle r)
+{
+ int dx, width;
+ uchar *p, *cp, *ep, *lp;
+
+LOGE("copy8to8");
+ width = Dx(r);
+ dx = Xsize - width;
+ p = gscreendata + r.min.y * Xsize + r.min.x;
+ cp = xscreendata + r.min.y * Xsize + r.min.x;
+ ep = gscreendata + r.max.y * Xsize + r.max.x;
+ while(p < ep) {
+ lp = p + width;
+ while(p < lp)
+ *cp++ = *p++; //infernotox11[*p++];
+ p += dx;
+ cp += dx;
+ }
+}
+
+static void
+copy8topixel(Rectangle r)
+{
+ int x, y;
+ uchar *p;
+
+LOGE("copy8topixel");
+ if(xscreendata == NULL)
+ return;
+
+ /* mainly for 4-bit greyscale */
+ for (y = r.min.y; y < r.max.y; y++) {
+ x = r.min.x;
+ p = gscreendata + y * Xsize + x;
+ while (x < r.max.x){
+ xscreendata[y * Xsize * 4 + x] = *p++;
+ x++;
+// XPutPixel(img, x++, y, infernotox11[*p++]);
+ }
+ }
+}
+
+
+//extern void int_refresh(int xb_, int yb_, int xe_, int ye_);
+
+void
+flushmemscreen(Rectangle r)
+{
+ char chanbuf[16];
+
+ // Clip to screen
+ if(r.min.x < 0)
+ r.min.x = 0;
+ if(r.min.y < 0)
+ r.min.y = 0;
+ if(r.max.x >= Xsize)
+ r.max.x = Xsize - 1;
+ if(r.max.y >= Ysize)
+ r.max.y = Ysize - 1;
+
+ if(r.max.x <= r.min.x || r.max.y <= r.min.y)
+ return;
+
+ if(xscreendata == NULL)
+ return;
+
+ LOGE("flushmemscreen: rect=(%d, %d)-(%d, %d), xscreendata=%x, displaydepth=%d, xscreendepth=%d\n",
+ r.min.x, r.min.y, r.max.x, r.max.y, xscreendata, displaydepth, xscreendepth
+ );
+
+#if 1
+ if(gscreendata != xscreendata)
+ switch(displaydepth){
+ case 32:
+ copy32to32(r);
+ break;
+ case 8:
+ switch(xscreendepth){
+ case 24:
+ /* copy8to24(r); */ /* doesn't happen? */
+ /* break */
+ case 32:
+ copy8to32(r);
+ break;
+ case 16:
+ copy8to16(r);
+ break;
+ case 8:
+ copy8to8(r);
+ break;
+ default:
+ copy8topixel(r);
+ break;
+ }
+ break;
+ default:
+ fprint(2, "emu: bad display depth %d chan %s xscreendepth %d\n", displaydepth,
+ chantostr(chanbuf, displaychan), xscreendepth);
+ cleanexit(0);
+ }
+#endif
+
+// int_refresh(r.min.x, r.min.y, r.max.x, r.max.y);
+}
+
+static int
+revbyte(int b)
+{
+ int r;
+
+ r = 0;
+ r |= (b&0x01) << 7;
+ r |= (b&0x02) << 5;
+ r |= (b&0x04) << 3;
+ r |= (b&0x08) << 1;
+ r |= (b&0x10) >> 1;
+ r |= (b&0x20) >> 3;
+ r |= (b&0x40) >> 5;
+ r |= (b&0x80) >> 7;
+ return r;
+}
+
+void
+setpointer(int x, int y)
+{
+/*
+ drawqlock();
+ XLockDisplay(xdisplay);
+ XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, x, y);
+ XFlush(xdisplay);
+ XUnlockDisplay(xdisplay);
+ drawqunlock();
+*/
+}
+
+static void
+xkbdproc(void *arg)
+{
+// XEvent event;
+// XDisplay *xd;
+
+// xd = arg;
+
+ /* BEWARE: the value of up is not defined for this proc on some systems */
+
+// XLockDisplay(xd); /* should be ours alone */
+// XSelectInput(xd, xdrawable, KeyPressMask | KeyReleaseMask);
+ for(;;){
+// XNextEvent(xd, &event);
+ xkeyboard(); //&event);
+// xsetcursor(); //&event);
+ }
+}
+
+static void
+xproc(void *arg)
+{
+// ulong mask;
+// XEvent event;
+// XDisplay *xd;
+
+ closepgrp(up->env->pgrp);
+ closefgrp(up->env->fgrp);
+ closeegrp(up->env->egrp);
+ closesigs(up->env->sigs);
+
+#if 0
+ xd = arg;
+ mask = ButtonPressMask|
+ ButtonReleaseMask|
+ PointerMotionMask|
+ Button1MotionMask|
+ Button2MotionMask|
+ Button3MotionMask|
+ Button4MotionMask|
+ Button5MotionMask|
+ ExposureMask|
+ StructureNotifyMask;
+
+ XLockDisplay(xd); /* should be ours alone */
+ XSelectInput(xd, xdrawable, mask);
+#endif
+ for(;;){
+ osmillisleep(10);
+// XNextEvent(xd, &event);
+// xselect(&event, xd);
+// xmouse(); //&event);
+ xexpose(); //&event);
+// xdestroy(&event);
+ }
+}
+
+/*
+ * this crud is here because X11 can put huge amount of data
+ * on the stack during keyboard translation and cursor changing(!).
+ * we do both in a dedicated process with lots of stack, perhaps even enough.
+ */
+
+enum {
+ CursorSize= 32 /* biggest cursor size */
+};
+
+typedef struct ICursor ICursor;
+struct ICursor {
+ int inuse;
+ int modify;
+ int hotx;
+ int hoty;
+ int w;
+ int h;
+ uchar src[(CursorSize/8)*CursorSize]; /* image and mask bitmaps */
+ uchar mask[(CursorSize/8)*CursorSize];
+};
+static ICursor icursor;
+
+static void
+xcurslock(void)
+{
+ while(_tas(&icursor.inuse) != 0)
+ osyield();
+}
+
+static void
+xcursunlock(void)
+{
+ coherence();
+ icursor.inuse = 0;
+}
+
+#if 0
+static void
+xcursnotify(void)
+{
+ XClientMessageEvent e;
+
+ memset(&e, 0, sizeof e);
+ e.type = ClientMessage;
+ e.window = xdrawable;
+ e.message_type = cursorchange;
+ e.format = 8;
+ XLockDisplay(xdisplay);
+ XSendEvent(xdisplay, xdrawable, True, KeyPressMask, (XEvent*)&e);
+ XFlush(xdisplay);
+ XUnlockDisplay(xdisplay);
+}
+#endif
+
+void
+drawcursor(Drawcursor* c)
+{
+#if 0
+ uchar *bs, *bc, *ps, *pm;
+ int i, j, w, h, bpl;
+
+ if(c->data == nil){
+ drawqlock();
+ if(icursor.h != 0){
+ xcurslock();
+ icursor.h = 0;
+ icursor.modify = 1;
+ xcursunlock();
+ }
+ xcursnotify();
+ drawqunlock();
+ return;
+ }
+
+ drawqlock();
+ xcurslock();
+ icursor.modify = 0; /* xsetcursor will now ignore it */
+ xcursunlock();
+
+ h = (c->maxy-c->miny)/2; /* image, then mask */
+ if(h > CursorSize)
+ h = CursorSize;
+ bpl = bytesperline(Rect(c->minx, c->miny, c->maxx, c->maxy), 1);
+ w = bpl;
+ if(w > CursorSize/8)
+ w = CursorSize/8;
+
+ ps = icursor.src;
+ pm = icursor.mask;
+ bc = c->data;
+ bs = c->data + h*bpl;
+ for(i = 0; i < h; i++){
+ for(j = 0; j < bpl && j < w; j++) {
+ *ps++ = revbyte(bs[j]);
+ *pm++ = revbyte(bs[j] | bc[j]);
+ }
+ bs += bpl;
+ bc += bpl;
+ }
+ icursor.h = h;
+ icursor.w = w*8;
+ icursor.hotx = c->hotx;
+ icursor.hoty = c->hoty;
+ icursor.modify = 1;
+ xcursnotify();
+ drawqunlock();
+#endif
+}
+
+#if 0
+static void
+xsetcursor(XEvent *e)
+{
+ ICursor ic;
+ XCursor xc;
+ XColor fg, bg;
+ Pixmap xsrc, xmask;
+ static XCursor xcursor;
+
+ if(e->type != ClientMessage || !e->xclient.send_event || e->xclient.message_type != cursorchange)
+ return;
+
+ xcurslock();
+ if(icursor.modify == 0){
+ xcursunlock();
+ return;
+ }
+ icursor.modify = 0;
+ if(icursor.h == 0){
+ xcursunlock();
+ /* set the default system cursor */
+ if(xcursor != 0) {
+ XFreeCursor(xkbdcon, xcursor);
+ xcursor = 0;
+ }
+ XUndefineCursor(xkbdcon, xdrawable);
+ XFlush(xkbdcon);
+ return;
+ }
+ ic = icursor;
+ xcursunlock();
+
+ xsrc = XCreateBitmapFromData(xkbdcon, xdrawable, (char*)ic.src, ic.w, ic.h);
+ xmask = XCreateBitmapFromData(xkbdcon, xdrawable, (char*)ic.mask, ic.w, ic.h);
+
+ fg = map[0];
+ bg = map[255];
+ fg.pixel = infernotox11[0];
+ bg.pixel = infernotox11[255];
+ xc = XCreatePixmapCursor(xkbdcon, xsrc, xmask, &fg, &bg, -ic.hotx, -ic.hoty);
+ if(xc != 0) {
+ XDefineCursor(xkbdcon, xdrawable, xc);
+ if(xcursor != 0)
+ XFreeCursor(xkbdcon, xcursor);
+ xcursor = xc;
+ }
+ XFreePixmap(xkbdcon, xsrc);
+ XFreePixmap(xkbdcon, xmask);
+ XFlush(xkbdcon);
+}
+#endif
+
+typedef struct Mg Mg;
+struct Mg
+{
+ int code;
+ int bit;
+ int len;
+ ulong mask;
+};
+
+static int
+maskx(Mg* g, int code, ulong mask)
+{
+ int i;
+
+ for(i=0; i<32; i++)
+ if(mask & (1<<i))
+ break;
+ if(i == 32)
+ return 0;
+ g->code = code;
+ g->bit = i;
+ g->mask = mask;
+ for(g->len = 0; i<32 && (mask & (1<<i))!=0; i++)
+ g->len++;
+ return 1;
+}
+
+/*
+ * for a given depth, we need to check the available formats
+ * to find how many actual bits are used per pixel.
+ */
+#if 0
+static int
+xactualdepth(int screenno, int depth)
+{
+ XPixmapFormatValues *pfmt;
+ int i, n;
+
+ pfmt = XListPixmapFormats(xdisplay, &n);
+ for(i=0; i<n; i++)
+ if(pfmt[i].depth == depth)
+ return pfmt[i].bits_per_pixel;
+ return -1;
+}
+
+static int
+xtruevisual(int screenno, int reqdepth, XVisualInfo *vi, ulong *chan)
+{
+ XVisual *xv;
+ Mg r, g, b;
+ int pad, d;
+ ulong c;
+ char buf[30];
+
+ if(XMatchVisualInfo(xdisplay, screenno, reqdepth, TrueColor, vi) ||
+ XMatchVisualInfo(xdisplay, screenno, reqdepth, DirectColor, vi)){
+ xv = vi->visual;
+ if(maskx(&r, CRed, xv->red_mask) &&
+ maskx(&g, CGreen, xv->green_mask) &&
+ maskx(&b, CBlue, xv->blue_mask)){
+ d = xactualdepth(screenno, reqdepth);
+ if(d < 0)
+ return 0;
+ pad = d - (r.len + g.len + b.len);
+ if(0){
+ fprint(2, "r: %8.8lux %d %d\ng: %8.8lux %d %d\nb: %8.8lux %d %d\n",
+ xv->red_mask, r.bit, r.len, xv->green_mask, g.bit, g.len, xv->blue_mask, b.bit, b.len);
+ }
+ if(r.bit > b.bit)
+ c = CHAN3(CRed, r.len, CGreen, g.len, CBlue, b.len);
+ else
+ c = CHAN3(CBlue, b.len, CGreen, g.len, CRed, r.len);
+ if(pad > 0)
+ c |= CHAN1(CIgnore, pad) << 24;
+ *chan = c;
+ xscreendepth = reqdepth;
+ if(0)
+ fprint(2, "chan=%s reqdepth=%d bits=%d\n", chantostr(buf, c), reqdepth, d);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+xmapvisual(int screenno, XVisualInfo *vi, ulong *chan)
+{
+ if(XMatchVisualInfo(xdisplay, screenno, 8, PseudoColor, vi) ||
+ XMatchVisualInfo(xdisplay, screenno, 8, StaticColor, vi)){
+ *chan = CMAP8;
+ xscreendepth = 8;
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+
+/*
+ * Initialize and install the Inferno colormap as a private colormap for this
+ * application. Inferno gets the best colors here when it has the cursor focus.
+ */
+#if 0
+static void
+xdestroy(XEvent *e)
+{
+ XDestroyWindowEvent *xe;
+ if(e->type != DestroyNotify)
+ return;
+ xe = (XDestroyWindowEvent*)e;
+ if(xe->window == xdrawable)
+ cleanexit(0);
+}
+#endif
+
+void
+xexpose() //XEvent *e)
+{
+ static int cntr = 0;
+ Rectangle r;
+// XExposeEvent *xe;
+
+// cntr++;
+// if(cntr == 100000)
+// cntr = 0;
+
+// if(cntr != 1) // e->type != Expose)
+// return;
+// xe = (XExposeEvent*)e;
+ r.min.x = 0; //xe->x;
+ r.min.y = 0; //xe->y;
+ r.max.x = Xsize; //xe->x + xe->width;
+ r.max.y = Ysize; //xe->y + xe->height;
+
+LOGE("xexpose");
+ drawqlock();
+ flushmemscreen(r);
+ drawqunlock();
+}
+
+static void
+xkeyboard() ///*XEvent*/void *e)
+{
+ int ind, md;
+// KeySym k;
+ int k;
+
+// if(gkscanq != nil && (e->type == KeyPress || e->type == KeyRelease)){
+// uchar ch = e->xkey.keycode;
+// if(e->xany.type == KeyRelease)
+// ch |= 0x80;
+// qproduce(gkscanq, &ch, 1);
+// return;
+// }
+
+#if 0
+ /*
+ * I tried using XtGetActionKeysym, but it didn't seem to
+ * do case conversion properly
+ * (at least, with Xterminal servers and R4 intrinsics)
+ */
+ if(e->xany.type != KeyPress)
+ return;
+
+ md = e->xkey.state;
+ ind = 0;
+ if(md & ShiftMask)
+ ind = 1;
+ if(0){
+ k = XKeycodeToKeysym(e->xany.display, (KeyCode)e->xkey.keycode, ind);
+
+ /* May have to try unshifted version */
+ if(k == NoSymbol && ind == 1)
+ k = XKeycodeToKeysym(e->xany.display, (KeyCode)e->xkey.keycode, 0);
+ }else
+ XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL);
+
+ if(k == XK_Multi_key || k == NoSymbol)
+ return;
+ if(k&0xFF00){
+ switch(k){
+ case XK_BackSpace:
+ case XK_Tab:
+ case XK_Escape:
+ case XK_Delete:
+ case XK_KP_0:
+ case XK_KP_1:
+ case XK_KP_2:
+ case XK_KP_3:
+ case XK_KP_4:
+ case XK_KP_5:
+ case XK_KP_6:
+ case XK_KP_7:
+ case XK_KP_8:
+ case XK_KP_9:
+ case XK_KP_Divide:
+ case XK_KP_Multiply:
+ case XK_KP_Subtract:
+ case XK_KP_Add:
+ case XK_KP_Decimal:
+ k &= 0x7F;
+ break;
+ case XK_Linefeed:
+ k = '\r';
+ break;
+ case XK_KP_Space:
+ k = ' ';
+ break;
+ case XK_Home:
+ case XK_KP_Home:
+ k = Home;
+ break;
+ case XK_Left:
+ case XK_KP_Left:
+ k = Left;
+ break;
+ case XK_Up:
+ case XK_KP_Up:
+ k = Up;
+ break;
+ case XK_Down:
+ case XK_KP_Down:
+ k = Down;
+ break;
+ case XK_Right:
+ case XK_KP_Right:
+ k = Right;
+ break;
+ case XK_Page_Down:
+ case XK_KP_Page_Down:
+ k = Pgdown;
+ break;
+ case XK_End:
+ case XK_KP_End:
+ k = End;
+ break;
+ case XK_Page_Up:
+ case XK_KP_Page_Up:
+ k = Pgup;
+ break;
+ case XK_Insert:
+ case XK_KP_Insert:
+ k = Ins;
+ break;
+ case XK_KP_Enter:
+ case XK_Return:
+ k = '\n';
+ break;
+ case XK_Alt_L:
+ case XK_Alt_R:
+ k = Latin;
+ break;
+ case XK_Shift_L:
+ case XK_Shift_R:
+ case XK_Control_L:
+ case XK_Control_R:
+ case XK_Caps_Lock:
+ case XK_Shift_Lock:
+
+ case XK_Meta_L:
+ case XK_Meta_R:
+ case XK_Super_L:
+ case XK_Super_R:
+ case XK_Hyper_L:
+ case XK_Hyper_R:
+ return;
+ default: /* not ISO-1 or tty control */
+ if(k>0xff){
+ k = keysym2ucs(k); /* supplied by X */
+ if(k == -1)
+ return;
+ }
+ break;
+ }
+ }
+
+ /* Compensate for servers that call a minus a hyphen */
+ if(k == XK_hyphen)
+ k = XK_minus;
+ /* Do control mapping ourselves if translator doesn't */
+ if(md & ControlMask)
+ k &= 0x9f;
+#endif
+/*
+ if(0){
+ if(k == '\t' && ind)
+ k = BackTab;
+
+ if(md & Mod1Mask)
+ k = APP|(k&0xff);
+ }
+ if(k == NoSymbol)
+ return;
+
+*/
+ gkbdputc(gkbdq, k);
+}
+
+static void
+xmouse() //XEvent *e)
+{
+ int s, dbl;
+// XButtonEvent *be;
+// XMotionEvent *me;
+// XEvent motion;
+ int x=0, y=0, b=0;
+// static ulong lastb, lastt;
+
+// if(putsnarf != assertsnarf){
+// assertsnarf = putsnarf;
+// XSetSelectionOwner(xmcon, XA_PRIMARY, xdrawable, CurrentTime);
+// if(clipboard != None)
+// XSetSelectionOwner(xmcon, clipboard, xdrawable, CurrentTime);
+// XFlush(xmcon);
+// }
+
+#if 0
+ dbl = 0;
+ switch(e->type){
+ case ButtonPress:
+ be = (XButtonEvent *)e;
+ /*
+ * Fake message, just sent to make us announce snarf.
+ * Apparently state and button are 16 and 8 bits on
+ * the wire, since they are truncated by the time they
+ * get to us.
+ */
+ if(be->send_event
+ && (~be->state&0xFFFF)==0
+ && (~be->button&0xFF)==0)
+ return;
+ x = be->x;
+ y = be->y;
+ s = be->state;
+ if(be->button == lastb && be->time - lastt < DblTime)
+ dbl = 1;
+ lastb = be->button;
+ lastt = be->time;
+ switch(be->button){
+ case 1:
+ s |= Button1Mask;
+ break;
+ case 2:
+ s |= Button2Mask;
+ break;
+ case 3:
+ s |= Button3Mask;
+ break;
+ case 4:
+ s |= Button4Mask;
+ break;
+ case 5:
+ s |= Button5Mask;
+ break;
+ }
+ break;
+ case ButtonRelease:
+ be = (XButtonEvent *)e;
+ x = be->x;
+ y = be->y;
+ s = be->state;
+ switch(be->button){
+ case 1:
+ s &= ~Button1Mask;
+ break;
+ case 2:
+ s &= ~Button2Mask;
+ break;
+ case 3:
+ s &= ~Button3Mask;
+ break;
+ case 4:
+ s &= ~Button4Mask;
+ break;
+ case 5:
+ s &= ~Button5Mask;
+ break;
+ }
+ break;
+ case MotionNotify:
+ me = (XMotionEvent *) e;
+
+ /* remove excess MotionNotify events from queue and keep last one */
+ while(XCheckTypedWindowEvent(xmcon, xdrawable, MotionNotify, &motion) == True)
+ me = (XMotionEvent *) &motion;
+
+ s = me->state;
+ x = me->x;
+ y = me->y;
+ break;
+ default:
+ return;
+ }
+
+ b = 0;
+ if(s & Button1Mask)
+ b |= 1;
+ if(s & Button2Mask)
+ b |= 2;
+ if(s & Button3Mask)
+ b |= 4;
+ if(s & Button4Mask)
+ b |= 8;
+ if(s & Button5Mask)
+ b |= 16;
+ if(dbl)
+ b |= 1<<8;
+#endif
+
+ mousetrack(b, x, y, 0);
+}
+
+
+void xmouse_btn(int x, int y, int btn){
+ mousetrack(btn, x, y, 0);
+}
+
+
+//#include "x11-keysym2ucs.c"
+
+/*
+ * Cut and paste. Just couldn't stand to make this simple...
+ */
+
+enum{
+ SnarfSize= 100*1024
+};
+
+typedef struct Clip Clip;
+struct Clip
+{
+ char buf[SnarfSize];
+ QLock lk;
+};
+Clip clip;
+
+#undef long /* sic */
+#undef ulong
+
+#if 0
+static char*
+_xgetsnarf(XDisplay *xd)
+{
+ uchar *data, *xdata;
+ Atom clipboard, type, prop;
+ unsigned long len, lastlen, dummy;
+ int fmt, i;
+ XWindow w;
+
+ qlock(&clip.lk);
+ /*
+ * Have we snarfed recently and the X server hasn't caught up?
+ */
+ if(putsnarf != assertsnarf)
+ goto mine;
+
+ /*
+ * Is there a primary selection (highlighted text in an xterm)?
+ */
+ clipboard = XA_PRIMARY;
+ w = XGetSelectionOwner(xd, XA_PRIMARY);
+ if(w == xdrawable){
+ mine:
+ data = (uchar*)strdup(clip.buf);
+ goto out;
+ }
+
+ /*
+ * If not, is there a clipboard selection?
+ */
+ if(w == None && clipboard != None){
+ clipboard = clipboard;
+ w = XGetSelectionOwner(xd, clipboard);
+ if(w == xdrawable)
+ goto mine;
+ }
+
+ /*
+ * If not, give up.
+ */
+ if(w == None){
+ data = nil;
+ goto out;
+ }
+
+ /*
+ * We should be waiting for SelectionNotify here, but it might never
+ * come, and we have no way to time out. Instead, we will clear
+ * local property #1, request our buddy to fill it in for us, and poll
+ * until he's done or we get tired of waiting.
+ *
+ * We should try to go for utf8string instead of XA_STRING,
+ * but that would add to the polling.
+ */
+ prop = 1;
+ XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0);
+ XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime);
+ XFlush(xd);
+ lastlen = 0;
+ for(i=0; i<10 || (lastlen!=0 && i<30); i++){
+ osmillisleep(100);
+ XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType,
+ &type, &fmt, &dummy, &len, &data);
+ if(lastlen == len && len > 0)
+ break;
+ lastlen = len;
+ }
+ if(i == 10){
+ data = nil;
+ goto out;
+ }
+ /* get the property */
+ data = nil;
+ XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0,
+ AnyPropertyType, &type, &fmt, &len, &dummy, &xdata);
+ if((type != XA_STRING && type != utf8string) || len == 0){
+ if(xdata)
+ XFree(xdata);
+ data = nil;
+ }else{
+ if(xdata){
+ data = (uchar*)strdup((char*)xdata);
+ XFree(xdata);
+ }else
+ data = nil;
+ }
+out:
+ qunlock(&clip.lk);
+ return (char*)data;
+}
+
+static void
+_xputsnarf(XDisplay *xd, char *data)
+{
+ XButtonEvent e;
+
+ if(strlen(data) >= SnarfSize)
+ return;
+ qlock(&clip.lk);
+ strcpy(clip.buf, data);
+
+ /* leave note for mouse proc to assert selection ownership */
+ putsnarf++;
+
+ /* send mouse a fake event so snarf is announced */
+ memset(&e, 0, sizeof e);
+ e.type = ButtonPress;
+ e.window = xdrawable;
+ e.state = ~0;
+ e.button = ~0;
+ XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e);
+ XFlush(xd);
+ qunlock(&clip.lk);
+}
+
+static void
+xselect(XEvent *e, XDisplay *xd)
+{
+ char *name;
+ XEvent r;
+ XSelectionRequestEvent *xe;
+ Atom a[4];
+
+ if(e->xany.type != SelectionRequest)
+ return;
+
+ memset(&r, 0, sizeof r);
+ xe = (XSelectionRequestEvent*)e;
+if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n",
+ xe->target, xe->requestor, xe->property, xe->selection);
+ r.xselection.property = xe->property;
+ if(xe->target == targets){
+ a[0] = XA_STRING;
+ a[1] = utf8string;
+ a[2] = text;
+ a[3] = compoundtext;
+
+ XChangeProperty(xd, xe->requestor, xe->property, xe->target,
+ 8, PropModeReplace, (uchar*)a, sizeof a);
+ }else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){
+ /* if the target is STRING we're supposed to reply with Latin1 XXX */
+ qlock(&clip.lk);
+ XChangeProperty(xd, xe->requestor, xe->property, xe->target,
+ 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf));
+ qunlock(&clip.lk);
+ }else{
+ iprint("get %d\n", xe->target);
+ name = XGetAtomName(xd, xe->target);
+ if(name == nil)
+ iprint("XGetAtomName failed\n");
+ else if(strcmp(name, "TIMESTAMP") != 0)
+ iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target);
+ r.xselection.property = None;
+ }
+
+ r.xselection.display = xe->display;
+ /* r.xselection.property filled above */
+ r.xselection.target = xe->target;
+ r.xselection.type = SelectionNotify;
+ r.xselection.requestor = xe->requestor;
+ r.xselection.time = xe->time;
+ r.xselection.send_event = True;
+ r.xselection.selection = xe->selection;
+ XSendEvent(xd, xe->requestor, False, 0, &r);
+ XFlush(xd);
+}
+#endif
+
+
+char *snarf_buf = nil;
+
+char*
+clipread(void)
+{
+ char *p = NULL;
+
+// if(xsnarfcon == nil)
+// return nil;
+// XLockDisplay(xsnarfcon);
+// p = _xgetsnarf(xsnarfcon);
+// XUnlockDisplay(xsnarfcon);
+
+ p = strdup(snarf_buf);
+
+ return p;
+}
+
+int
+clipwrite(char *buf)
+{
+// buf = NULL;
+
+// if(xsnarfcon == nil)
+// return 0;
+// XLockDisplay(xsnarfcon);
+// _xputsnarf(xsnarfcon, buf);
+// XUnlockDisplay(xsnarfcon);
+ int l = strlen(buf);
+
+ if(snarf_buf)
+ free(snarf_buf);
+ snarf_buf = nil;
+
+ if(l >= SnarfSize)
+ return 0;
+
+ snarf_buf = strdup(buf);
+
+ /* leave note for mouse proc to assert selection ownership */
+ putsnarf++;
+
+ return 0;
+}
diff --git a/emu/port/devdraw.c b/emu/port/devdraw.c
index 012e02e..893182e 100644
--- a/emu/port/devdraw.c
+++ b/emu/port/devdraw.c
@@ -1183,7 +1183,6 @@ drawwrite(Chan *c, void *a, long n, vlong off)
int i, m, red, green, blue, x;
ulong offset = off;
-
//print("<< %s: %d prog=%p, proc=%p, qid=%d\n", "drawwrite", __LINE__, currun(), up, QID(c->qid));
USED(offset);
diff --git a/libinterp/runt.h b/libinterp/runt.h
index df226d5..3aebf93 100644
--- a/libinterp/runt.h
+++ b/libinterp/runt.h
@@ -3096,8 +3096,8 @@ struct F_Math_yn
#define Math_Infinity Infinity
#define Math_NaN NaN
#define Math_MachEps 2.220446049250313e-16
-#define Math_Pi 3.141592653589793
-#define Math_Degree .017453292519943292
+#define Math_Pi 3.1415927410125732
+#define Math_Degree .01745329238474369
#define Math_INVAL 1
#define Math_ZDIV 2
#define Math_OVFL 4
diff --git a/mkconfig b/mkconfig
index 9f5365d..e66a052 100644
--- a/mkconfig
+++ b/mkconfig
@@ -11,7 +11,7 @@ ROOT=$ROOT
#
TKSTYLE=std
-WINDOW_BACKEND=clutter # andr, clutter
+WINDOW_BACKEND=fb # andr, clutter, x11a, fb
#
# Except for building kernels, SYSTARG must always be the same as SYSHOST
@@ -23,7 +23,7 @@ SYSTARG=Linux #Android #Linux #$SYSHOST # target system OS type (Hp, Inferno,
# specify the architecture of the target system - Plan 9 imports it from the
# environment; for other systems it is usually just hard-coded
#
-OBJTYPE=386 #arm #386 # target system object type (eg, 386, arm, mips, power, s800, sparc)
+OBJTYPE=arm #386 #arm #386 # target system object type (eg, 386, arm, mips, power, s800, sparc)
#OBJTYPE=$objtype
#
diff --git a/mkfile b/mkfile
index 585055e..898fbd5 100644
--- a/mkfile
+++ b/mkfile
@@ -14,6 +14,8 @@ EMUDIRS=\
libmath\
# utils/iyacc\
# limbo\
+ utils/iyacc\
+ limbo\
libinterp\
libkeyring\
libdraw\
diff --git a/mkfiles/mkfile-Linux-arm b/mkfiles/mkfile-Linux-arm
index a0c7b17..86885fe 100644
--- a/mkfiles/mkfile-Linux-arm
+++ b/mkfiles/mkfile-Linux-arm
@@ -5,13 +5,13 @@ CPUS= arm
O= o
OS= o
-AR= ar
+AR= ${CROSS}ar
ARFLAGS= ruvs
-AS= arm-gcc -c
+AS= ${CROSS}gcc -c
ASFLAGS=
-CC= arm-gcc -c
+CC= ${CROSS}gcc -c
CFLAGS= -O\
-Wuninitialized -Wunused-variable -Wreturn-type -Wimplicit\
-I$ROOT/Linux/arm/include\
@@ -19,7 +19,7 @@ CFLAGS= -O\
-DLINUX_ARM
ANSICPP=
-LD= arm-gcc
+LD= ${CROSS}gcc
LDFLAGS=
SYSLIBS=
diff --git a/os/port/sysfile.c b/os/port/sysfile.c
index 6f73da2..143d29d 100644
--- a/os/port/sysfile.c
+++ b/os/port/sysfile.c
@@ -106,6 +106,7 @@ kchanio(void *vc, void *buf, int n, int mode)
r = devtab[c->type]->read(c, buf, n, c->offset);
else
r = devtab[c->type]->write(c, buf, n, c->offset);
+printf("%s:%d mode=%d, r=%d\n", __func__, __LINE__, mode, r);
lock(c);
c->offset += r;