mirror of
https://github.com/golang/go
synced 2024-11-23 02:30:02 -07:00
remove nacl
The recent linker changes broke NaCl support a month ago, and there are no known users of it. The NaCl code can always be recovered from the repository history. R=adg, r CC=golang-dev https://golang.org/cl/3671042
This commit is contained in:
parent
85f5bb8216
commit
0c54225b51
@ -89,8 +89,6 @@ Safe compilation mode: generate code that is guaranteed not to obtain an invalid
|
||||
<li>
|
||||
Gccgo: garbage collection.
|
||||
<li>
|
||||
Native Client (NaCl) support.
|
||||
<li>
|
||||
SWIG support.
|
||||
<li>
|
||||
Simpler semicolon rules.
|
||||
|
@ -62,7 +62,7 @@ support for segmented stacks, and a strong goroutine implementation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The compilers can target the FreeBSD, Linux, Native Client,
|
||||
The compilers can target the FreeBSD, Linux,
|
||||
and OS X (a.k.a. Darwin) operating systems.
|
||||
(A port to Microsoft Windows is in progress but incomplete. See the
|
||||
<a href="http://code.google.com/p/go/wiki/WindowsPort">Windows Port</a>
|
||||
@ -340,7 +340,6 @@ to override the defaults.
|
||||
Choices for <code>$GOOS</code> are <code>linux</code>,
|
||||
<code>freebsd</code>,
|
||||
<code>darwin</code> (Mac OS X 10.5 or 10.6),
|
||||
<code>nacl</code> (Native Client, an incomplete port),
|
||||
and <code>windows</code> (Windows, an incomplete port).
|
||||
Choices for <code>$GOARCH</code> are <code>amd64</code> (64-bit x86, the most mature port),
|
||||
<code>386</code> (32-bit x86), and
|
||||
@ -372,9 +371,6 @@ to override the defaults.
|
||||
<td></td><td><code>linux</code></td> <td><code>arm</code></td> <td><i>incomplete</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>nacl</code></td> <td><code>386</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>windows</code></td> <td><code>386</code></td> <td><i>incomplete</i></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -32,12 +32,11 @@ endif
|
||||
ifeq ($(GOOS),darwin)
|
||||
else ifeq ($(GOOS),freebsd)
|
||||
else ifeq ($(GOOS),linux)
|
||||
else ifeq ($(GOOS),nacl)
|
||||
else ifeq ($(GOOS),tiny)
|
||||
else ifeq ($(GOOS),plan9)
|
||||
else ifeq ($(GOOS),windows)
|
||||
else
|
||||
$(error Invalid $$GOOS '$(GOOS)'; must be darwin, freebsd, linux, nacl, tiny, plan9, or windows)
|
||||
$(error Invalid $$GOOS '$(GOOS)'; must be darwin, freebsd, linux, plan9, tiny, or windows)
|
||||
endif
|
||||
|
||||
ifeq ($(GOHOSTARCH),)
|
||||
|
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# TODO(rsc): delete in favor of all.bash once nacl support is complete
|
||||
|
||||
export GOARCH=386
|
||||
export GOOS=nacl
|
||||
export GORUN=${GORUN:-$GOROOT/misc/nacl/naclrun}
|
||||
|
||||
set -e
|
||||
bash make.bash
|
||||
|
||||
xcd() {
|
||||
echo
|
||||
echo --- cd $1
|
||||
builtin cd $1
|
||||
}
|
||||
|
||||
(xcd pkg
|
||||
make install
|
||||
make test
|
||||
) || exit $?
|
||||
|
||||
(xcd pkg/exp/nacl/srpc
|
||||
make clean
|
||||
make install
|
||||
) || exit $?
|
||||
|
||||
(xcd pkg/exp/nacl/av
|
||||
make clean
|
||||
make install
|
||||
) || exit $?
|
||||
|
||||
(xcd pkg/exp/4s
|
||||
make clean
|
||||
make
|
||||
) || exit $?
|
||||
|
||||
(xcd pkg/exp/spacewar
|
||||
make clean
|
||||
make
|
||||
) || exit $?
|
||||
|
||||
(xcd ../test
|
||||
./run
|
||||
) || exit $?
|
@ -535,8 +535,6 @@ asmb(void)
|
||||
|
||||
for(sect=segtext.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segrodata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segdata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
|
||||
|
@ -415,7 +415,7 @@ addpltsym(Sym *s)
|
||||
static void
|
||||
addgotsym(Sym *s)
|
||||
{
|
||||
Sym *got, *rela, *indir;
|
||||
Sym *got, *rela;
|
||||
|
||||
if(s->got >= 0)
|
||||
return;
|
||||
@ -976,8 +976,6 @@ asmb(void)
|
||||
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
|
||||
for(sect=segtext.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segrodata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segdata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "opt.h"
|
||||
|
||||
static Prog *pret;
|
||||
static Node *naclnop;
|
||||
|
||||
void
|
||||
compile(Node *fn)
|
||||
@ -24,7 +23,6 @@ compile(Node *fn)
|
||||
newproc = sysfunc("newproc");
|
||||
deferproc = sysfunc("deferproc");
|
||||
deferreturn = sysfunc("deferreturn");
|
||||
naclnop = sysfunc("naclnop");
|
||||
panicindex = sysfunc("panicindex");
|
||||
panicslice = sysfunc("panicslice");
|
||||
throwreturn = sysfunc("throwreturn");
|
||||
@ -96,16 +94,8 @@ compile(Node *fn)
|
||||
if(pret)
|
||||
patch(pret, pc);
|
||||
ginit();
|
||||
if(hasdefer) {
|
||||
// On Native client, insert call to no-op function
|
||||
// to force alignment immediately before call to deferreturn,
|
||||
// so that when jmpdefer subtracts 5 from the second CALL's
|
||||
// return address and then the return masks off the low bits,
|
||||
// we'll back up to the NOPs immediately after the dummy CALL.
|
||||
if(strcmp(getgoos(), "nacl") == 0)
|
||||
ginscall(naclnop, 0);
|
||||
if(hasdefer)
|
||||
ginscall(deferreturn, 0);
|
||||
}
|
||||
if(curfn->exit)
|
||||
genlist(curfn->exit);
|
||||
gclean();
|
||||
|
@ -539,8 +539,6 @@ doelf(void)
|
||||
elfstr[ElfStrData] = addstring(shstrtab, ".data");
|
||||
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
|
||||
addstring(shstrtab, ".elfdata");
|
||||
if(HEADTYPE == 8)
|
||||
addstring(shstrtab, ".closure");
|
||||
addstring(shstrtab, ".rodata");
|
||||
if(!debug['s']) {
|
||||
elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts");
|
||||
@ -674,8 +672,6 @@ asmb(void)
|
||||
sect = segtext.sect;
|
||||
seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0);
|
||||
codeblk(sect->vaddr, sect->len);
|
||||
|
||||
// TODO: NaCl: pad with HLT
|
||||
|
||||
/* output read-only data in text segment */
|
||||
sect = segtext.sect->next;
|
||||
@ -889,7 +885,7 @@ asmb(void)
|
||||
|
||||
Elfput:
|
||||
/* elf 386 */
|
||||
if(HEADTYPE == 8 || HEADTYPE == 11)
|
||||
if(HEADTYPE == 11)
|
||||
debug['d'] = 1;
|
||||
|
||||
eh = getElfEhdr();
|
||||
@ -901,17 +897,14 @@ asmb(void)
|
||||
/* This null SHdr must appear before all others */
|
||||
sh = newElfShdr(elfstr[ElfStrEmpty]);
|
||||
|
||||
/* program header info - but not on native client */
|
||||
pph = nil;
|
||||
if(HEADTYPE != 8) {
|
||||
pph = newElfPhdr();
|
||||
pph->type = PT_PHDR;
|
||||
pph->flags = PF_R + PF_X;
|
||||
pph->off = eh->ehsize;
|
||||
pph->vaddr = INITTEXT - HEADR + pph->off;
|
||||
pph->paddr = INITTEXT - HEADR + pph->off;
|
||||
pph->align = INITRND;
|
||||
}
|
||||
/* program header info */
|
||||
pph = newElfPhdr();
|
||||
pph->type = PT_PHDR;
|
||||
pph->flags = PF_R + PF_X;
|
||||
pph->off = eh->ehsize;
|
||||
pph->vaddr = INITTEXT - HEADR + pph->off;
|
||||
pph->paddr = INITTEXT - HEADR + pph->off;
|
||||
pph->align = INITRND;
|
||||
|
||||
if(!debug['d']) {
|
||||
/* interpreter */
|
||||
@ -935,8 +928,6 @@ asmb(void)
|
||||
}
|
||||
|
||||
elfphload(&segtext);
|
||||
if(segrodata.len > 0)
|
||||
elfphload(&segrodata);
|
||||
elfphload(&segdata);
|
||||
|
||||
/* Dynamic linking sections */
|
||||
@ -1038,8 +1029,6 @@ asmb(void)
|
||||
diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
|
||||
for(sect=segtext.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segrodata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
for(sect=segdata.sect; sect!=nil; sect=sect->next)
|
||||
elfshbits(sect);
|
||||
|
||||
@ -1073,11 +1062,6 @@ asmb(void)
|
||||
eh->ident[EI_DATA] = ELFDATA2LSB;
|
||||
eh->ident[EI_VERSION] = EV_CURRENT;
|
||||
switch(HEADTYPE) {
|
||||
case 8:
|
||||
eh->ident[EI_OSABI] = ELFOSABI_NACL;
|
||||
eh->ident[EI_ABIVERSION] = 7;
|
||||
eh->flags = 0x200000; // aligned mod 32
|
||||
break;
|
||||
case 9:
|
||||
eh->ident[EI_OSABI] = 9;
|
||||
break;
|
||||
|
@ -321,7 +321,6 @@ EXTERN int32 spsize;
|
||||
EXTERN Sym* symlist;
|
||||
EXTERN int32 symsize;
|
||||
EXTERN Sym* textp;
|
||||
EXTERN int32 textpad;
|
||||
EXTERN int32 textsize;
|
||||
EXTERN int version;
|
||||
EXTERN Prog zprg;
|
||||
|
@ -55,8 +55,10 @@ char *thestring = "386";
|
||||
* -H4 -Tx -Rx is fake MS-DOS .EXE
|
||||
* -H6 -Tx -Rx is Apple Mach-O
|
||||
* -H7 -Tx -Rx is Linux ELF32
|
||||
* -H8 -Tx -Rx is Google Native Client
|
||||
* -H8 -Tx -Rx was Google Native Client
|
||||
* -H9 -Tx -Rx is FreeBSD ELF32
|
||||
* -H10 -Tx -Rx is MS Windows PE
|
||||
* -H11 -Tx -Rx is tiny (os image)
|
||||
*/
|
||||
|
||||
void
|
||||
@ -133,9 +135,6 @@ main(int argc, char *argv[])
|
||||
if(strcmp(goos, "darwin") == 0)
|
||||
HEADTYPE = 6;
|
||||
else
|
||||
if(strcmp(goos, "nacl") == 0)
|
||||
HEADTYPE = 8;
|
||||
else
|
||||
if(strcmp(goos, "freebsd") == 0)
|
||||
HEADTYPE = 9;
|
||||
else
|
||||
@ -248,21 +247,6 @@ main(int argc, char *argv[])
|
||||
if(INITRND == -1)
|
||||
INITRND = 4096;
|
||||
break;
|
||||
case 8: /* native client elf32 executable */
|
||||
elfinit();
|
||||
HEADR = 4096;
|
||||
if(INITTEXT == -1)
|
||||
INITTEXT = 0x20000;
|
||||
if(INITDAT == -1)
|
||||
INITDAT = 0;
|
||||
if(INITRND == -1)
|
||||
INITRND = 65536;
|
||||
|
||||
// 512 kB of address space for closures.
|
||||
// (Doesn't take any space in the binary file.)
|
||||
// Closures are 64 bytes each, so this is 8,192 closures.
|
||||
textpad = 512*1024;
|
||||
break;
|
||||
case 10: /* PE executable */
|
||||
peinit();
|
||||
HEADR = PEFILEHEADR;
|
||||
|
@ -822,22 +822,6 @@ subreg(Prog *p, int from, int to)
|
||||
print("%P\n", p);
|
||||
}
|
||||
|
||||
// nacl RET:
|
||||
// POPL BX
|
||||
// ANDL BX, $~31
|
||||
// JMP BX
|
||||
uchar naclret[] = { 0x5b, 0x83, 0xe3, ~31, 0xff, 0xe3 };
|
||||
|
||||
// nacl JMP BX:
|
||||
// ANDL BX, $~31
|
||||
// JMP BX
|
||||
uchar nacljmpbx[] = { 0x83, 0xe3, ~31, 0xff, 0xe3 };
|
||||
|
||||
// nacl CALL BX:
|
||||
// ANDL BX, $~31
|
||||
// CALL BX
|
||||
uchar naclcallbx[] = { 0x83, 0xe3, ~31, 0xff, 0xd3 };
|
||||
|
||||
void
|
||||
doasm(Prog *p)
|
||||
{
|
||||
@ -906,12 +890,6 @@ found:
|
||||
break;
|
||||
|
||||
case Zlit:
|
||||
if(HEADTYPE == 8 && p->as == ARET) {
|
||||
// native client return.
|
||||
for(z=0; z<sizeof(naclret); z++)
|
||||
*andptr++ = naclret[z];
|
||||
break;
|
||||
}
|
||||
for(; op = o->op[z]; z++)
|
||||
*andptr++ = op;
|
||||
break;
|
||||
@ -945,42 +923,6 @@ found:
|
||||
break;
|
||||
|
||||
case Zo_m:
|
||||
if(HEADTYPE == 8) {
|
||||
Adr a;
|
||||
|
||||
switch(p->as) {
|
||||
case AJMP:
|
||||
if(p->to.type < D_AX || p->to.type > D_DI)
|
||||
diag("indirect jmp must use register in native client");
|
||||
// ANDL $~31, REG
|
||||
*andptr++ = 0x83;
|
||||
asmand(&p->to, 04);
|
||||
*andptr++ = ~31;
|
||||
// JMP REG
|
||||
*andptr++ = 0xFF;
|
||||
asmand(&p->to, 04);
|
||||
return;
|
||||
|
||||
case ACALL:
|
||||
a = p->to;
|
||||
// native client indirect call
|
||||
if(a.type < D_AX || a.type > D_DI) {
|
||||
// MOVL target into BX
|
||||
*andptr++ = 0x8b;
|
||||
asmand(&p->to, reg[D_BX]);
|
||||
memset(&a, 0, sizeof a);
|
||||
a.type = D_BX;
|
||||
}
|
||||
// ANDL $~31, REG
|
||||
*andptr++ = 0x83;
|
||||
asmand(&a, 04);
|
||||
*andptr++ = ~31;
|
||||
// CALL REG
|
||||
*andptr++ = 0xFF;
|
||||
asmand(&a, 02);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*andptr++ = op;
|
||||
asmand(&p->to, o->op[z+1]);
|
||||
break;
|
||||
@ -1004,12 +946,6 @@ found:
|
||||
else
|
||||
a = &p->to;
|
||||
v = vaddr(a, nil);
|
||||
if(HEADTYPE == 8 && p->as == AINT && v == 3) {
|
||||
// native client disallows all INT instructions.
|
||||
// translate INT $3 to HLT.
|
||||
*andptr++ = 0xf4;
|
||||
break;
|
||||
}
|
||||
*andptr++ = op;
|
||||
*andptr++ = v;
|
||||
break;
|
||||
@ -1380,51 +1316,8 @@ mfound:
|
||||
void
|
||||
asmins(Prog *p)
|
||||
{
|
||||
if(HEADTYPE == 8) {
|
||||
ulong npc;
|
||||
static Prog *prefix;
|
||||
|
||||
// TODO: adjust relocations, like 6l does for rex prefix
|
||||
|
||||
// native client
|
||||
// - pad indirect jump targets (aka ATEXT) to 32-byte boundary
|
||||
// - instructions cannot cross 32-byte boundary
|
||||
// - end of call (return address) must be on 32-byte boundary
|
||||
if(p->as == ATEXT)
|
||||
p->pc += 31 & -p->pc;
|
||||
if(p->as == ACALL) {
|
||||
// must end on 32-byte boundary.
|
||||
// doasm to find out how long the CALL encoding is.
|
||||
andptr = and;
|
||||
doasm(p);
|
||||
npc = p->pc + (andptr - and);
|
||||
p->pc += 31 & -npc;
|
||||
}
|
||||
if(p->as == AREP || p->as == AREPN) {
|
||||
// save prefix for next instruction,
|
||||
// so that inserted NOPs do not split (e.g.) REP / MOVSL sequence.
|
||||
prefix = p;
|
||||
andptr = and;
|
||||
return;
|
||||
}
|
||||
andptr = and;
|
||||
if(prefix)
|
||||
doasm(prefix);
|
||||
doasm(p);
|
||||
npc = p->pc + (andptr - and);
|
||||
if(andptr > and && (p->pc&~31) != ((npc-1)&~31)) {
|
||||
// crossed 32-byte boundary; pad to boundary and try again
|
||||
p->pc += 31 & -p->pc;
|
||||
andptr = and;
|
||||
if(prefix)
|
||||
doasm(prefix);
|
||||
doasm(p);
|
||||
}
|
||||
prefix = nil;
|
||||
} else {
|
||||
andptr = and;
|
||||
doasm(p);
|
||||
}
|
||||
andptr = and;
|
||||
doasm(p);
|
||||
if(andptr > and+sizeof and) {
|
||||
print("and[] is too short - %d byte instruction\n", andptr - and);
|
||||
errorexit();
|
||||
|
@ -400,6 +400,7 @@ dpcheck(Node *n)
|
||||
|
||||
i = l->param;
|
||||
b = n->right;
|
||||
a = Z;
|
||||
while(i > 0) {
|
||||
b = nextarg(b, &a);
|
||||
i--;
|
||||
|
@ -95,7 +95,6 @@ EXTERN char* thestring;
|
||||
|
||||
EXTERN Segment segtext;
|
||||
EXTERN Segment segdata;
|
||||
EXTERN Segment segrodata; // NaCl only
|
||||
EXTERN Segment segsym;
|
||||
|
||||
void addlib(char *src, char *obj);
|
||||
|
@ -186,27 +186,6 @@ ifeq ($(DISABLE_NET_TESTS),1)
|
||||
NOTEST+=http net
|
||||
endif
|
||||
|
||||
# Disable tests that NaCl cannot run yet.
|
||||
ifeq ($(GOOS),nacl)
|
||||
NOTEST+=archive/tar # no pipe
|
||||
NOTEST+=archive/zip # no pread
|
||||
NOTEST+=debug/dwarf # no pread
|
||||
NOTEST+=debug/macho # no pread
|
||||
NOTEST+=debug/elf # no pread
|
||||
NOTEST+=exec # no pipe
|
||||
NOTEST+=http # no network
|
||||
NOTEST+=log # no runtime.Caller
|
||||
NOTEST+=net # no network
|
||||
NOTEST+=netchan # no network
|
||||
NOTEST+=os # many things unimplemented
|
||||
NOTEST+=os/signal # no signals
|
||||
NOTEST+=path # tree walking does not work
|
||||
NOTEST+=rpc # no network
|
||||
NOTEST+=syslog # no network
|
||||
NOTEST+=time # no syscall.Kill, syscall.SIGCHLD for sleep tests
|
||||
NOTEST+=websocket # no network
|
||||
endif
|
||||
|
||||
# Disable tests that windows cannot run yet.
|
||||
ifeq ($(GOOS),windows)
|
||||
NOTEST+=os/signal # no signals
|
||||
|
@ -18,9 +18,6 @@ GOFILES_darwin=\
|
||||
GOFILES_linux=\
|
||||
rand_unix.go\
|
||||
|
||||
GOFILES_nacl=\
|
||||
rand_unix.go\
|
||||
|
||||
GOFILES_windows=\
|
||||
rand_windows.go\
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Process tracing is not supported on Native Client.
|
||||
|
||||
func Attach(pid int) (Process, os.Error) {
|
||||
return nil, os.NewSyscallError("ptrace", syscall.ENACL)
|
||||
}
|
||||
|
||||
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*os.File) (Process, os.Error) {
|
||||
return nil, os.NewSyscallError("fork/exec", syscall.ENACL)
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proc
|
@ -17,9 +17,6 @@ GOFILES_darwin=\
|
||||
GOFILES_linux=\
|
||||
lp_unix.go\
|
||||
|
||||
GOFILES_nacl=\
|
||||
lp_unix.go\
|
||||
|
||||
GOFILES_windows=\
|
||||
lp_windows.go\
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This is a simple demo of Go running under Native Client.
|
||||
// It is a tetris clone built on top of the exp/nacl/av and exp/draw
|
||||
// packages.
|
||||
//
|
||||
// See ../nacl/README for how to run it.
|
||||
package main
|
||||
|
||||
import (
|
||||
"exp/nacl/av"
|
||||
"exp/nacl/srpc"
|
||||
"log"
|
||||
"runtime"
|
||||
"os"
|
||||
)
|
||||
|
||||
var sndc chan []uint16
|
||||
|
||||
func main() {
|
||||
// Native Client requires that some calls are issued
|
||||
// consistently by the same OS thread.
|
||||
runtime.LockOSThread()
|
||||
|
||||
if srpc.Enabled() {
|
||||
go srpc.ServeRuntime()
|
||||
}
|
||||
|
||||
args := os.Args
|
||||
p := pieces4
|
||||
if len(args) > 1 && args[1] == "-5" {
|
||||
p = pieces5
|
||||
}
|
||||
dx, dy := 500, 500
|
||||
w, err := av.Init(av.SubsystemVideo|av.SubsystemAudio, dx, dy)
|
||||
if err != nil {
|
||||
log.Exit(err)
|
||||
}
|
||||
|
||||
sndc = make(chan []uint16, 10)
|
||||
go audioServer()
|
||||
Play(p, w)
|
||||
}
|
||||
|
||||
func audioServer() {
|
||||
// Native Client requires that all audio calls
|
||||
// original from a single OS thread.
|
||||
runtime.LockOSThread()
|
||||
|
||||
n, err := av.AudioStream(nil)
|
||||
if err != nil {
|
||||
log.Exit(err)
|
||||
}
|
||||
for {
|
||||
b := <-sndc
|
||||
for len(b)*2 >= n {
|
||||
var a []uint16
|
||||
a, b = b[0:n/2], b[n/2:]
|
||||
n, err = av.AudioStream(a)
|
||||
if err != nil {
|
||||
log.Exit(err)
|
||||
}
|
||||
println(n, len(b)*2)
|
||||
}
|
||||
a := make([]uint16, n/2)
|
||||
copy(a, b)
|
||||
n, err = av.AudioStream(a)
|
||||
}
|
||||
}
|
||||
|
||||
func PlaySound(b []uint16) { sndc <- b }
|
||||
|
||||
var whoosh = []uint16{
|
||||
// Insert your favorite sound samples here.
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
|
||||
|
||||
<h1>games/4s</h1>
|
||||
<table><tr><td valign=top>
|
||||
<embed name="nacl_module" id="pluginobj" src="8.out" type="application/x-nacl-srpc" width=400 height=600>
|
||||
<td valign=top>
|
||||
This is a simple block stacking game, a port of Plan 9's
|
||||
<a href="http://plan9.bell-labs.com/magic/man2html/1/games">games/4s</a>
|
||||
<br><br>
|
||||
To play using the keyboard:
|
||||
as the blocks fall, the <i>a</i>, <i>s</i>, <i>d</i>, and <i>f</i> keys
|
||||
move the block left, rotate the block left, rotate the block right,
|
||||
anad move the block right, respectively.
|
||||
To drop a block, type the space key.
|
||||
<b>You may need to click on the game window to
|
||||
focus the keyboard on it.</b>
|
||||
<br><br>
|
||||
To play using the mouse:
|
||||
as the blocks fall, moving the mouse horizontally positions
|
||||
the block; left or right clicks rotate the block left or right.
|
||||
A middle click drops the block.
|
||||
(Unfortunately, some environments seem to intercept
|
||||
the middle click before it gets to Native Client.)
|
||||
<br><br>
|
||||
To pause the game, type <i>z</i>, <i>p</i>, or the escape key.
|
||||
</table>
|
@ -1,9 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Hack to produce a binary that defaults to 5s.
|
||||
|
||||
package main
|
||||
|
||||
func init() { pieces4 = pieces5 }
|
@ -1,26 +0,0 @@
|
||||
|
||||
|
||||
<h1>games/5s</h1>
|
||||
<table><tr><td valign=top>
|
||||
<embed name="nacl_module" id="pluginobj" src="8.5s" type="application/x-nacl-srpc" width=400 height=600>
|
||||
<td valign=top>
|
||||
This is a simple block stacking game, a port of Plan 9's
|
||||
<a href="http://plan9.bell-labs.com/magic/man2html/1/games">games/5s</a>
|
||||
<br><br>
|
||||
To play using the keyboard:
|
||||
as the blocks fall, the <i>a</i>, <i>s</i>, <i>d</i>, and <i>f</i> keys
|
||||
move the block left, rotate the block left, rotate the block right,
|
||||
anad move the block right, respectively.
|
||||
To drop a block, type the space key.
|
||||
<b>You may need to click on the game window to
|
||||
focus the keyboard on it.</b>
|
||||
<br><br>
|
||||
To play using the mouse:
|
||||
as the blocks fall, moving the mouse horizontally positions
|
||||
the block; left or right clicks rotate the block left or right.
|
||||
A middle click drops the block.
|
||||
(Unfortunately, some environments seem to intercept
|
||||
the middle click before it gets to Native Client.)
|
||||
<br><br>
|
||||
To pause the game, type <i>z</i>, <i>p</i>, or the escape key.
|
||||
</table>
|
@ -1,20 +0,0 @@
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
all: 8.out 8.5s
|
||||
|
||||
4s.8: 4s.go data.go xs.go
|
||||
8g 4s.go data.go xs.go
|
||||
|
||||
5s.8: 5s.go 4s.go data.go xs.go
|
||||
8g 5s.go 4s.go data.go xs.go
|
||||
|
||||
8.out: 4s.8
|
||||
8l 4s.8
|
||||
|
||||
8.5s: 5s.8
|
||||
8l -o 8.5s 5s.8
|
||||
|
||||
clean:
|
||||
rm -f *.8 8.out
|
@ -1,142 +0,0 @@
|
||||
// games/4s - a tetris clone
|
||||
//
|
||||
// Derived from Plan 9's /sys/src/games/xs.c
|
||||
// http://plan9.bell-labs.com/sources/plan9/sys/src/games/xs.c
|
||||
//
|
||||
// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
|
||||
// Portions Copyright 2009 The Go Authors. All Rights Reserved.
|
||||
// Distributed under the terms of the Lucent Public License Version 1.02
|
||||
// See http://plan9.bell-labs.com/plan9/license.html
|
||||
|
||||
package main
|
||||
|
||||
import . "image"
|
||||
|
||||
var pieces4 = []Piece{
|
||||
{0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
|
||||
{2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
|
||||
{1, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
|
||||
{2, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
|
||||
{3, 3, Point{2, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}, nil, nil},
|
||||
|
||||
{0, 1, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{1, 1, Point{2, 3}, []Point{{1, 0}, {0, 1}, {0, 1}, {-1, 0}}, nil, nil},
|
||||
{2, 1, Point{3, 2}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 1, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 2, Point{3, 2}, []Point{{0, 1}, {1, 0}, {1, 0}, {0, -1}}, nil, nil},
|
||||
{1, 2, Point{2, 3}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{2, 2, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
|
||||
{3, 2, Point{2, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 4, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{1, 4, Point{2, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 4, Point{3, 2}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 4, Point{2, 3}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, -1}}, nil, nil},
|
||||
|
||||
{0, 5, Point{3, 2}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{1, 5, Point{2, 3}, []Point{{1, 0}, {0, 1}, {-1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 5, Point{3, 2}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{3, 5, Point{2, 3}, []Point{{1, 0}, {0, 1}, {-1, 0}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 6, Point{3, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {1, 0}}, nil, nil},
|
||||
{1, 6, Point{2, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 6, Point{3, 2}, []Point{{0, 1}, {1, 0}, {0, -1}, {1, 0}}, nil, nil},
|
||||
{3, 6, Point{2, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
}
|
||||
|
||||
var pieces5 = []Piece{
|
||||
{0, 1, Point{5, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{1, 1, Point{1, 5}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
|
||||
{2, 1, Point{5, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 1, Point{1, 5}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 0, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{1, 0, Point{2, 4}, []Point{{1, 0}, {0, 1}, {0, 1}, {0, 1}, {-1, 0}}, nil, nil},
|
||||
{2, 0, Point{4, 2}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 0, Point{2, 4}, []Point{{0, 0}, {1, 0}, {-1, 1}, {0, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 2, Point{4, 2}, []Point{{0, 0}, {0, 1}, {1, -1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{1, 2, Point{2, 4}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
|
||||
{2, 2, Point{4, 2}, []Point{{0, 1}, {1, 0}, {1, 0}, {1, 0}, {0, -1}}, nil, nil},
|
||||
{3, 2, Point{2, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
|
||||
|
||||
{0, 7, Point{3, 3}, []Point{{0, 0}, {1, 0}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
|
||||
{1, 7, Point{3, 3}, []Point{{0, 2}, {1, 0}, {1, 0}, {0, -1}, {0, -1}}, nil, nil},
|
||||
{2, 7, Point{3, 3}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 7, Point{3, 3}, []Point{{0, 2}, {0, -1}, {0, -1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
|
||||
{0, 3, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-2, 1}, {1, 0}}, nil, nil},
|
||||
{1, 3, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 3, Point{3, 2}, []Point{{1, 0}, {1, 0}, {-2, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 3, Point{2, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {-1, 1}, {1, 0}}, nil, nil},
|
||||
|
||||
{0, 4, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-1, 1}, {1, 0}}, nil, nil},
|
||||
{1, 4, Point{2, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {-1, 1}, {1, 0}}, nil, nil},
|
||||
{2, 4, Point{3, 2}, []Point{{0, 0}, {1, 0}, {-1, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 4, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
|
||||
{0, 7, Point{3, 2}, []Point{{0, 0}, {2, 0}, {-2, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{1, 7, Point{2, 3}, []Point{{0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{2, 7, Point{3, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {-2, 1}, {2, 0}}, nil, nil},
|
||||
{3, 7, Point{2, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {-1, 1}, {1, 0}}, nil, nil},
|
||||
|
||||
{0, 5, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{1, 5, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{2, 5, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{3, 5, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
|
||||
|
||||
{0, 6, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-2, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{1, 6, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 6, Point{3, 3}, []Point{{1, 0}, {0, 1}, {1, 0}, {-2, 1}, {1, 0}}, nil, nil},
|
||||
{3, 6, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
|
||||
{0, 0, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
|
||||
{1, 0, Point{2, 4}, []Point{{1, 0}, {-1, 1}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
|
||||
{2, 0, Point{4, 2}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 0, Point{2, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
|
||||
{0, 2, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{1, 2, Point{2, 4}, []Point{{1, 0}, {0, 1}, {-1, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 2, Point{4, 2}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 2, Point{2, 4}, []Point{{0, 0}, {0, 1}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 1, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{1, 1, Point{3, 3}, []Point{{2, 0}, {-1, 1}, {1, 0}, {-2, 1}, {1, 0}}, nil, nil},
|
||||
{2, 1, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{3, 1, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-2, 1}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
|
||||
{0, 3, Point{3, 3}, []Point{{0, 0}, {1, 0}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
|
||||
{1, 3, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 3, Point{3, 3}, []Point{{1, 0}, {0, 1}, {-1, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{3, 3, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
|
||||
|
||||
{0, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{1, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{2, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
{3, 4, Point{3, 3}, []Point{{1, 0}, {-1, 1}, {1, 0}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
|
||||
{0, 8, Point{4, 2}, []Point{{0, 0}, {1, 0}, {0, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{1, 8, Point{2, 4}, []Point{{1, 0}, {-1, 1}, {1, 0}, {-1, 1}, {0, 1}}, nil, nil},
|
||||
{2, 8, Point{4, 2}, []Point{{0, 0}, {1, 0}, {1, 0}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{3, 8, Point{2, 4}, []Point{{1, 0}, {0, 1}, {-1, 1}, {1, 0}, {-1, 1}}, nil, nil},
|
||||
|
||||
{0, 9, Point{4, 2}, []Point{{2, 0}, {1, 0}, {-3, 1}, {1, 0}, {1, 0}}, nil, nil},
|
||||
{1, 9, Point{2, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{2, 9, Point{4, 2}, []Point{{1, 0}, {1, 0}, {1, 0}, {-3, 1}, {1, 0}}, nil, nil},
|
||||
{3, 9, Point{2, 4}, []Point{{0, 0}, {0, 1}, {1, 0}, {0, 1}, {0, 1}}, nil, nil},
|
||||
|
||||
{0, 5, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{1, 5, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-1, 1}, {-1, 1}, {1, 0}}, nil, nil},
|
||||
{2, 5, Point{3, 3}, []Point{{0, 0}, {0, 1}, {1, 0}, {1, 0}, {0, 1}}, nil, nil},
|
||||
{3, 5, Point{3, 3}, []Point{{1, 0}, {1, 0}, {-1, 1}, {-1, 1}, {1, 0}}, nil, nil},
|
||||
|
||||
{0, 6, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
|
||||
{1, 6, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
|
||||
{2, 6, Point{3, 3}, []Point{{2, 0}, {-2, 1}, {1, 0}, {1, 0}, {-2, 1}}, nil, nil},
|
||||
{3, 6, Point{3, 3}, []Point{{0, 0}, {1, 0}, {0, 1}, {0, 1}, {1, 0}}, nil, nil},
|
||||
}
|
@ -1,750 +0,0 @@
|
||||
// games/4s - a tetris clone
|
||||
//
|
||||
// Derived from Plan 9's /sys/src/games/xs.c
|
||||
// http://plan9.bell-labs.com/sources/plan9/sys/src/games/xs.c
|
||||
//
|
||||
// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
|
||||
// Portions Copyright 2009 The Go Authors. All Rights Reserved.
|
||||
// Distributed under the terms of the Lucent Public License Version 1.02
|
||||
// See http://plan9.bell-labs.com/plan9/license.html
|
||||
|
||||
/*
|
||||
* engine for 4s, 5s, etc
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"exp/draw"
|
||||
"image"
|
||||
"log"
|
||||
"os"
|
||||
"rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
Cursor whitearrow = {
|
||||
{0, 0},
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
|
||||
0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC,
|
||||
0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
|
||||
0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C,
|
||||
0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C,
|
||||
0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C,
|
||||
0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
|
||||
};
|
||||
*/
|
||||
|
||||
const (
|
||||
CNone = 0
|
||||
CBounds = 1
|
||||
CPiece = 2
|
||||
NX = 10
|
||||
NY = 20
|
||||
|
||||
NCOL = 10
|
||||
|
||||
MAXN = 5
|
||||
)
|
||||
|
||||
var (
|
||||
N int
|
||||
display draw.Window
|
||||
screen draw.Image
|
||||
screenr image.Rectangle
|
||||
board [NY][NX]byte
|
||||
rboard image.Rectangle
|
||||
pscore image.Point
|
||||
scoresz image.Point
|
||||
pcsz = 32
|
||||
pos image.Point
|
||||
bbr, bb2r image.Rectangle
|
||||
bb, bbmask, bb2, bb2mask *image.RGBA
|
||||
whitemask image.Image
|
||||
br, br2 image.Rectangle
|
||||
points int
|
||||
dt int
|
||||
DY int
|
||||
DMOUSE int
|
||||
lastmx int
|
||||
mouse draw.MouseEvent
|
||||
newscreen bool
|
||||
timerc <-chan int64
|
||||
suspc chan bool
|
||||
mousec chan draw.MouseEvent
|
||||
resizec chan bool
|
||||
kbdc chan int
|
||||
suspended bool
|
||||
tsleep int
|
||||
piece *Piece
|
||||
pieces []Piece
|
||||
)
|
||||
|
||||
type Piece struct {
|
||||
rot int
|
||||
tx int
|
||||
sz image.Point
|
||||
d []image.Point
|
||||
left *Piece
|
||||
right *Piece
|
||||
}
|
||||
|
||||
var txbits = [NCOL][32]byte{
|
||||
{0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
|
||||
0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
|
||||
0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
|
||||
0xDD, 0xDD, 0xFF, 0xFF, 0x77, 0x77, 0xFF, 0xFF,
|
||||
},
|
||||
{0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
|
||||
0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
|
||||
0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
|
||||
0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
|
||||
},
|
||||
{0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
},
|
||||
{0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
|
||||
},
|
||||
{0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
|
||||
0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
|
||||
0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
|
||||
0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
|
||||
},
|
||||
{0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
|
||||
0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
|
||||
0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
|
||||
0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
|
||||
},
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
{0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
},
|
||||
{0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
|
||||
0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
|
||||
},
|
||||
}
|
||||
|
||||
var txpix = [NCOL]image.Image{
|
||||
image.NewColorImage(image.RGBAColor{0xFF, 0xFF, 0x00, 0xFF}), /* yellow */
|
||||
image.NewColorImage(image.RGBAColor{0x00, 0xFF, 0xFF, 0xFF}), /* cyan */
|
||||
image.NewColorImage(image.RGBAColor{0x00, 0xFF, 0x00, 0xFF}), /* lime green */
|
||||
image.NewColorImage(image.RGBAColor{0x00, 0x5D, 0xBB, 0xFF}), /* slate */
|
||||
image.NewColorImage(image.RGBAColor{0xFF, 0x00, 0x00, 0xFF}), /* red */
|
||||
image.NewColorImage(image.RGBAColor{0x55, 0xAA, 0xAA, 0xFF}), /* olive green */
|
||||
image.NewColorImage(image.RGBAColor{0x00, 0x00, 0xFF, 0xFF}), /* blue */
|
||||
image.NewColorImage(image.RGBAColor{0xFF, 0x55, 0xAA, 0xFF}), /* pink */
|
||||
image.NewColorImage(image.RGBAColor{0xFF, 0xAA, 0xFF, 0xFF}), /* lavender */
|
||||
image.NewColorImage(image.RGBAColor{0xBB, 0x00, 0x5D, 0xFF}), /* maroon */
|
||||
}
|
||||
|
||||
func movemouse() int {
|
||||
//mouse.image.Point = image.Pt(rboard.Min.X + rboard.Dx()/2, rboard.Min.Y + rboard.Dy()/2);
|
||||
//moveto(mousectl, mouse.Xy);
|
||||
return mouse.Loc.X
|
||||
}
|
||||
|
||||
func warp(p image.Point, x int) int {
|
||||
if !suspended && piece != nil {
|
||||
x = pos.X + piece.sz.X*pcsz/2
|
||||
if p.Y < rboard.Min.Y {
|
||||
p.Y = rboard.Min.Y
|
||||
}
|
||||
if p.Y >= rboard.Max.Y {
|
||||
p.Y = rboard.Max.Y - 1
|
||||
}
|
||||
//moveto(mousectl, image.Pt(x, p.Y));
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func initPieces() {
|
||||
for i := range pieces {
|
||||
p := &pieces[i]
|
||||
if p.rot == 3 {
|
||||
p.right = &pieces[i-3]
|
||||
} else {
|
||||
p.right = &pieces[i+1]
|
||||
}
|
||||
if p.rot == 0 {
|
||||
p.left = &pieces[i+3]
|
||||
} else {
|
||||
p.left = &pieces[i-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func collide(pt image.Point, p *Piece) bool {
|
||||
pt.X = (pt.X - rboard.Min.X) / pcsz
|
||||
pt.Y = (pt.Y - rboard.Min.Y) / pcsz
|
||||
for _, q := range p.d {
|
||||
pt.X += q.X
|
||||
pt.Y += q.Y
|
||||
if pt.X < 0 || pt.X >= NX || pt.Y < 0 || pt.Y >= NY {
|
||||
return true
|
||||
continue
|
||||
}
|
||||
if board[pt.Y][pt.X] != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func collider(pt, pmax image.Point) bool {
|
||||
pi := (pt.X - rboard.Min.X) / pcsz
|
||||
pj := (pt.Y - rboard.Min.Y) / pcsz
|
||||
n := pmax.X / pcsz
|
||||
m := pmax.Y/pcsz + 1
|
||||
for i := pi; i < pi+n && i < NX; i++ {
|
||||
for j := pj; j < pj+m && j < NY; j++ {
|
||||
if board[j][i] != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func setpiece(p *Piece) {
|
||||
draw.Draw(bb, bbr, image.White, image.ZP)
|
||||
draw.Draw(bbmask, bbr, image.Transparent, image.ZP)
|
||||
br = image.Rect(0, 0, 0, 0)
|
||||
br2 = br
|
||||
piece = p
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
var op image.Point
|
||||
var r image.Rectangle
|
||||
r.Min = bbr.Min
|
||||
for i, pt := range p.d {
|
||||
r.Min.X += pt.X * pcsz
|
||||
r.Min.Y += pt.Y * pcsz
|
||||
r.Max.X = r.Min.X + pcsz
|
||||
r.Max.Y = r.Min.Y + pcsz
|
||||
if i == 0 {
|
||||
draw.Draw(bb, r, image.Black, image.ZP)
|
||||
draw.Draw(bb, r.Inset(1), txpix[piece.tx], image.ZP)
|
||||
draw.Draw(bbmask, r, image.Opaque, image.ZP)
|
||||
op = r.Min
|
||||
} else {
|
||||
draw.Draw(bb, r, bb, op)
|
||||
draw.Draw(bbmask, r, bbmask, op)
|
||||
}
|
||||
if br.Max.X < r.Max.X {
|
||||
br.Max.X = r.Max.X
|
||||
}
|
||||
if br.Max.Y < r.Max.Y {
|
||||
br.Max.Y = r.Max.Y
|
||||
}
|
||||
}
|
||||
br.Max = br.Max.Sub(bbr.Min)
|
||||
delta := image.Pt(0, DY)
|
||||
br2.Max = br.Max.Add(delta)
|
||||
r = br.Add(bb2r.Min)
|
||||
r2 := br2.Add(bb2r.Min)
|
||||
draw.Draw(bb2, r2, image.White, image.ZP)
|
||||
draw.Draw(bb2, r.Add(delta), bb, bbr.Min)
|
||||
draw.Draw(bb2mask, r2, image.Transparent, image.ZP)
|
||||
draw.DrawMask(bb2mask, r, image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over)
|
||||
draw.DrawMask(bb2mask, r.Add(delta), image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over)
|
||||
}
|
||||
|
||||
func drawpiece() {
|
||||
draw.DrawMask(screen, br.Add(pos), bb, bbr.Min, bbmask, image.ZP, draw.Over)
|
||||
if suspended {
|
||||
draw.DrawMask(screen, br.Add(pos), image.White, image.ZP, whitemask, image.ZP, draw.Over)
|
||||
}
|
||||
}
|
||||
|
||||
func undrawpiece() {
|
||||
var mask image.Image
|
||||
if collider(pos, br.Max) {
|
||||
mask = bbmask
|
||||
}
|
||||
draw.DrawMask(screen, br.Add(pos), image.White, bbr.Min, mask, bbr.Min, draw.Over)
|
||||
}
|
||||
|
||||
func rest() {
|
||||
pt := pos.Sub(rboard.Min)
|
||||
pt.X /= pcsz
|
||||
pt.Y /= pcsz
|
||||
for _, p := range piece.d {
|
||||
pt.X += p.X
|
||||
pt.Y += p.Y
|
||||
board[pt.Y][pt.X] = byte(piece.tx + 16)
|
||||
}
|
||||
}
|
||||
|
||||
func canfit(p *Piece) bool {
|
||||
var dx = [...]int{0, -1, 1, -2, 2, -3, 3, 4, -4}
|
||||
j := N + 1
|
||||
if j >= 4 {
|
||||
j = p.sz.X
|
||||
if j < p.sz.Y {
|
||||
j = p.sz.Y
|
||||
}
|
||||
j = 2*j - 1
|
||||
}
|
||||
for i := 0; i < j; i++ {
|
||||
var z image.Point
|
||||
z.X = pos.X + dx[i]*pcsz
|
||||
z.Y = pos.Y
|
||||
if !collide(z, p) {
|
||||
z.Y = pos.Y + pcsz - 1
|
||||
if !collide(z, p) {
|
||||
undrawpiece()
|
||||
pos.X = z.X
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func score(p int) {
|
||||
points += p
|
||||
// snprint(buf, sizeof(buf), "%.6ld", points);
|
||||
// draw.Draw(screen, draw.Rpt(pscore, pscore.Add(scoresz)), image.White, image.ZP);
|
||||
// string(screen, pscore, image.Black, image.ZP, font, buf);
|
||||
}
|
||||
|
||||
func drawsq(b draw.Image, p image.Point, ptx int) {
|
||||
var r image.Rectangle
|
||||
r.Min = p
|
||||
r.Max.X = r.Min.X + pcsz
|
||||
r.Max.Y = r.Min.Y + pcsz
|
||||
draw.Draw(b, r, image.Black, image.ZP)
|
||||
draw.Draw(b, r.Inset(1), txpix[ptx], image.ZP)
|
||||
}
|
||||
|
||||
func drawboard() {
|
||||
draw.Border(screen, rboard.Inset(-2), 2, image.Black, image.ZP)
|
||||
draw.Draw(screen, image.Rect(rboard.Min.X, rboard.Min.Y-2, rboard.Max.X, rboard.Min.Y),
|
||||
image.White, image.ZP)
|
||||
for i := 0; i < NY; i++ {
|
||||
for j := 0; j < NX; j++ {
|
||||
if board[i][j] != 0 {
|
||||
drawsq(screen, image.Pt(rboard.Min.X+j*pcsz, rboard.Min.Y+i*pcsz), int(board[i][j]-16))
|
||||
}
|
||||
}
|
||||
}
|
||||
score(0)
|
||||
if suspended {
|
||||
draw.DrawMask(screen, screenr, image.White, image.ZP, whitemask, image.ZP, draw.Over)
|
||||
}
|
||||
}
|
||||
|
||||
func choosepiece() {
|
||||
for {
|
||||
i := rand.Intn(len(pieces))
|
||||
setpiece(&pieces[i])
|
||||
pos = rboard.Min
|
||||
pos.X += rand.Intn(NX) * pcsz
|
||||
if !collide(image.Pt(pos.X, pos.Y+pcsz-DY), piece) {
|
||||
break
|
||||
}
|
||||
}
|
||||
drawpiece()
|
||||
display.FlushImage()
|
||||
}
|
||||
|
||||
func movepiece() bool {
|
||||
var mask image.Image
|
||||
if collide(image.Pt(pos.X, pos.Y+pcsz), piece) {
|
||||
return false
|
||||
}
|
||||
if collider(pos, br2.Max) {
|
||||
mask = bb2mask
|
||||
}
|
||||
draw.DrawMask(screen, br2.Add(pos), bb2, bb2r.Min, mask, bb2r.Min, draw.Over)
|
||||
pos.Y += DY
|
||||
display.FlushImage()
|
||||
return true
|
||||
}
|
||||
|
||||
func suspend(s bool) {
|
||||
suspended = s
|
||||
/*
|
||||
if suspended {
|
||||
setcursor(mousectl, &whitearrow);
|
||||
} else {
|
||||
setcursor(mousectl, nil);
|
||||
}
|
||||
*/
|
||||
if !suspended {
|
||||
drawpiece()
|
||||
}
|
||||
drawboard()
|
||||
display.FlushImage()
|
||||
}
|
||||
|
||||
func pause(t int) {
|
||||
display.FlushImage()
|
||||
for {
|
||||
select {
|
||||
case s := <-suspc:
|
||||
if !suspended && s {
|
||||
suspend(true)
|
||||
} else if suspended && !s {
|
||||
suspend(false)
|
||||
lastmx = warp(mouse.Loc, lastmx)
|
||||
}
|
||||
case <-timerc:
|
||||
if suspended {
|
||||
break
|
||||
}
|
||||
t -= tsleep
|
||||
if t < 0 {
|
||||
return
|
||||
}
|
||||
case <-resizec:
|
||||
//redraw(true);
|
||||
case mouse = <-mousec:
|
||||
case <-kbdc:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func horiz() bool {
|
||||
var lev [MAXN]int
|
||||
h := 0
|
||||
for i := 0; i < NY; i++ {
|
||||
for j := 0; board[i][j] != 0; j++ {
|
||||
if j == NX-1 {
|
||||
lev[h] = i
|
||||
h++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if h == 0 {
|
||||
return false
|
||||
}
|
||||
r := rboard
|
||||
newscreen = false
|
||||
for j := 0; j < h; j++ {
|
||||
r.Min.Y = rboard.Min.Y + lev[j]*pcsz
|
||||
r.Max.Y = r.Min.Y + pcsz
|
||||
draw.DrawMask(screen, r, image.White, image.ZP, whitemask, image.ZP, draw.Over)
|
||||
display.FlushImage()
|
||||
}
|
||||
PlaySound(whoosh)
|
||||
for i := 0; i < 3; i++ {
|
||||
pause(250)
|
||||
if newscreen {
|
||||
drawboard()
|
||||
break
|
||||
}
|
||||
for j := 0; j < h; j++ {
|
||||
r.Min.Y = rboard.Min.Y + lev[j]*pcsz
|
||||
r.Max.Y = r.Min.Y + pcsz
|
||||
draw.DrawMask(screen, r, image.White, image.ZP, whitemask, image.ZP, draw.Over)
|
||||
}
|
||||
display.FlushImage()
|
||||
}
|
||||
r = rboard
|
||||
for j := 0; j < h; j++ {
|
||||
i := NY - lev[j] - 1
|
||||
score(250 + 10*i*i)
|
||||
r.Min.Y = rboard.Min.Y
|
||||
r.Max.Y = rboard.Min.Y + lev[j]*pcsz
|
||||
draw.Draw(screen, r.Add(image.Pt(0, pcsz)), screen, r.Min)
|
||||
r.Max.Y = rboard.Min.Y + pcsz
|
||||
draw.Draw(screen, r, image.White, image.ZP)
|
||||
for k := lev[j] - 1; k >= 0; k-- {
|
||||
board[k+1] = board[k]
|
||||
}
|
||||
board[0] = [NX]byte{}
|
||||
}
|
||||
display.FlushImage()
|
||||
return true
|
||||
}
|
||||
|
||||
func mright() {
|
||||
if !collide(image.Pt(pos.X+pcsz, pos.Y), piece) &&
|
||||
!collide(image.Pt(pos.X+pcsz, pos.Y+pcsz-DY), piece) {
|
||||
undrawpiece()
|
||||
pos.X += pcsz
|
||||
drawpiece()
|
||||
display.FlushImage()
|
||||
}
|
||||
}
|
||||
|
||||
func mleft() {
|
||||
if !collide(image.Pt(pos.X-pcsz, pos.Y), piece) &&
|
||||
!collide(image.Pt(pos.X-pcsz, pos.Y+pcsz-DY), piece) {
|
||||
undrawpiece()
|
||||
pos.X -= pcsz
|
||||
drawpiece()
|
||||
display.FlushImage()
|
||||
}
|
||||
}
|
||||
|
||||
func rright() {
|
||||
if canfit(piece.right) {
|
||||
setpiece(piece.right)
|
||||
drawpiece()
|
||||
display.FlushImage()
|
||||
}
|
||||
}
|
||||
|
||||
func rleft() {
|
||||
if canfit(piece.left) {
|
||||
setpiece(piece.left)
|
||||
drawpiece()
|
||||
display.FlushImage()
|
||||
}
|
||||
}
|
||||
|
||||
var fusst = 0
|
||||
|
||||
func drop(f bool) bool {
|
||||
if f {
|
||||
score(5 * (rboard.Max.Y - pos.Y) / pcsz)
|
||||
for movepiece() {
|
||||
}
|
||||
}
|
||||
fusst = 0
|
||||
rest()
|
||||
if pos.Y == rboard.Min.Y && !horiz() {
|
||||
return true
|
||||
}
|
||||
horiz()
|
||||
setpiece(nil)
|
||||
pause(1500)
|
||||
choosepiece()
|
||||
lastmx = warp(mouse.Loc, lastmx)
|
||||
return false
|
||||
}
|
||||
|
||||
func play() {
|
||||
var om draw.MouseEvent
|
||||
dt = 64
|
||||
lastmx = -1
|
||||
lastmx = movemouse()
|
||||
choosepiece()
|
||||
lastmx = warp(mouse.Loc, lastmx)
|
||||
for {
|
||||
select {
|
||||
case mouse = <-mousec:
|
||||
if suspended {
|
||||
om = mouse
|
||||
break
|
||||
}
|
||||
if lastmx < 0 {
|
||||
lastmx = mouse.Loc.X
|
||||
}
|
||||
if mouse.Loc.X > lastmx+DMOUSE {
|
||||
mright()
|
||||
lastmx = mouse.Loc.X
|
||||
}
|
||||
if mouse.Loc.X < lastmx-DMOUSE {
|
||||
mleft()
|
||||
lastmx = mouse.Loc.X
|
||||
}
|
||||
if mouse.Buttons&^om.Buttons&1 == 1 {
|
||||
rleft()
|
||||
}
|
||||
if mouse.Buttons&^om.Buttons&2 == 2 {
|
||||
if drop(true) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if mouse.Buttons&^om.Buttons&4 == 4 {
|
||||
rright()
|
||||
}
|
||||
om = mouse
|
||||
|
||||
case s := <-suspc:
|
||||
if !suspended && s {
|
||||
suspend(true)
|
||||
} else if suspended && !s {
|
||||
suspend(false)
|
||||
lastmx = warp(mouse.Loc, lastmx)
|
||||
}
|
||||
|
||||
case <-resizec:
|
||||
//redraw(true);
|
||||
|
||||
case r := <-kbdc:
|
||||
if suspended {
|
||||
break
|
||||
}
|
||||
switch r {
|
||||
case 'f', ';':
|
||||
mright()
|
||||
case 'a', 'j':
|
||||
mleft()
|
||||
case 'd', 'l':
|
||||
rright()
|
||||
case 's', 'k':
|
||||
rleft()
|
||||
case ' ':
|
||||
if drop(true) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
case <-timerc:
|
||||
if suspended {
|
||||
break
|
||||
}
|
||||
dt -= tsleep
|
||||
if dt < 0 {
|
||||
i := 1
|
||||
dt = 16 * (points + rand.Intn(10000) - 5000) / 10000
|
||||
if dt >= 32 {
|
||||
i += (dt - 32) / 16
|
||||
dt = 32
|
||||
}
|
||||
dt = 52 - dt
|
||||
for ; i > 0; i-- {
|
||||
if movepiece() {
|
||||
continue
|
||||
}
|
||||
fusst++
|
||||
if fusst == 40 {
|
||||
if drop(false) {
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func suspproc() {
|
||||
s := false
|
||||
for {
|
||||
select {
|
||||
case mouse = <-mousec:
|
||||
mousec <- mouse
|
||||
case r := <-kbdc:
|
||||
switch r {
|
||||
case 'q', 'Q', 0x04, 0x7F:
|
||||
os.Exit(0)
|
||||
default:
|
||||
if s {
|
||||
s = false
|
||||
suspc <- s
|
||||
break
|
||||
}
|
||||
switch r {
|
||||
case 'z', 'Z', 'p', 'P', 0x1B:
|
||||
s = true
|
||||
suspc <- s
|
||||
default:
|
||||
kbdc <- r
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func redraw(new bool) {
|
||||
// if new && getwindow(display, Refmesg) < 0 {
|
||||
// sysfatal("can't reattach to window");
|
||||
// }
|
||||
r := screen.Bounds()
|
||||
pos.X = (pos.X - rboard.Min.X) / pcsz
|
||||
pos.Y = (pos.Y - rboard.Min.Y) / pcsz
|
||||
dx := r.Max.X - r.Min.X
|
||||
dy := r.Max.Y - r.Min.Y - 2*32
|
||||
DY = dx / NX
|
||||
if DY > dy/NY {
|
||||
DY = dy / NY
|
||||
}
|
||||
DY /= 8
|
||||
if DY > 4 {
|
||||
DY = 4
|
||||
}
|
||||
pcsz = DY * 8
|
||||
DMOUSE = pcsz / 3
|
||||
if pcsz < 8 {
|
||||
log.Exitf("screen too small: %d", pcsz)
|
||||
}
|
||||
rboard = screenr
|
||||
rboard.Min.X += (dx - pcsz*NX) / 2
|
||||
rboard.Min.Y += (dy-pcsz*NY)/2 + 32
|
||||
rboard.Max.X = rboard.Min.X + NX*pcsz
|
||||
rboard.Max.Y = rboard.Min.Y + NY*pcsz
|
||||
pscore.X = rboard.Min.X + 8
|
||||
pscore.Y = rboard.Min.Y - 32
|
||||
// scoresz = stringsize(font, "000000");
|
||||
pos.X = pos.X*pcsz + rboard.Min.X
|
||||
pos.Y = pos.Y*pcsz + rboard.Min.Y
|
||||
bbr = image.Rect(0, 0, N*pcsz, N*pcsz)
|
||||
bb = image.NewRGBA(bbr.Max.X, bbr.Max.Y)
|
||||
bbmask = image.NewRGBA(bbr.Max.X, bbr.Max.Y) // actually just a bitmap
|
||||
bb2r = image.Rect(0, 0, N*pcsz, N*pcsz+DY)
|
||||
bb2 = image.NewRGBA(bb2r.Dx(), bb2r.Dy())
|
||||
bb2mask = image.NewRGBA(bb2r.Dx(), bb2r.Dy()) // actually just a bitmap
|
||||
draw.Draw(screen, screenr, image.White, image.ZP)
|
||||
drawboard()
|
||||
setpiece(piece)
|
||||
if piece != nil {
|
||||
drawpiece()
|
||||
}
|
||||
lastmx = movemouse()
|
||||
newscreen = true
|
||||
display.FlushImage()
|
||||
}
|
||||
|
||||
func demuxEvents(w draw.Window) {
|
||||
for event := range w.EventChan() {
|
||||
switch e := event.(type) {
|
||||
case draw.MouseEvent:
|
||||
mousec <- e
|
||||
case draw.ConfigEvent:
|
||||
resizec <- true
|
||||
case draw.KeyEvent:
|
||||
kbdc <- e.Key
|
||||
}
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func Play(pp []Piece, ctxt draw.Window) {
|
||||
display = ctxt
|
||||
screen = ctxt.Screen()
|
||||
screenr = screen.Bounds()
|
||||
pieces = pp
|
||||
N = len(pieces[0].d)
|
||||
initPieces()
|
||||
rand.Seed(int64(time.Nanoseconds() % (1e9 - 1)))
|
||||
whitemask = image.NewColorImage(image.AlphaColor{0x7F})
|
||||
tsleep = 50
|
||||
timerc = time.Tick(int64(tsleep/2) * 1e6)
|
||||
suspc = make(chan bool)
|
||||
mousec = make(chan draw.MouseEvent)
|
||||
resizec = make(chan bool)
|
||||
kbdc = make(chan int)
|
||||
go demuxEvents(ctxt)
|
||||
go suspproc()
|
||||
points = 0
|
||||
redraw(false)
|
||||
play()
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
To try Native Client by running 4s (tetris) or 5s or Spacewar:
|
||||
|
||||
1. Build the Go distribution for your native system.
|
||||
|
||||
2. Download the Native Client SDK and install it.
|
||||
http://code.google.com/p/nativeclient-sdk/wiki/HowTo_GetStarted
|
||||
* You only need to do steps 1 and 2.
|
||||
|
||||
3. Copy "./native_client*/toolchain/*/bin/sel_ldr"
|
||||
from the Native Client distribution somewhere in your path as "nacl".
|
||||
This will let you run binaries using "nacl -M 8.out".
|
||||
The -M flag enables multithreaded access to the video library.
|
||||
|
||||
4. Build the Go distribution again, this time for Native Client:
|
||||
cd $GOROOT/src
|
||||
./all-nacl.bash
|
||||
* If you didn't do step 3, the tests at the end will fail, but that's okay.
|
||||
* If you are on a Mac, your dock will flicker as the "nacl" binary
|
||||
starts and stops while the tests run. You can stop the tests at any time.
|
||||
|
||||
5. Run the programs by using
|
||||
nacl -M $GOROOT/src/pkg/exp/4s/8.out
|
||||
nacl -M $GOROOT/src/pkg/exp/4s/8.5s
|
||||
nacl -M $GOROOT/src/pkg/exp/spacewar/8.out
|
||||
|
||||
6. If you have an old copy of the Native Client plugin, you may be
|
||||
able to run the programs in your browser, by running
|
||||
"godoc --http=:5103" and then visiting
|
||||
* http://localhost:5103/src/pkg/exp/4s/4s.html
|
||||
* http://localhost:5103/src/pkg/exp/4s/5s.html [sic]
|
||||
* http://localhost:5103/src/pkg/exp/spacewar/spacewar.html
|
||||
|
||||
This usage is deprecated in favor of newere APIs in recent
|
||||
releases of Native Client. More work will be necessary to support
|
||||
interactive graphics when using those releases.
|
||||
|
@ -1,13 +0,0 @@
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../../../Make.inc
|
||||
|
||||
TARG=exp/nacl/av
|
||||
GOFILES=\
|
||||
av.go\
|
||||
event.go\
|
||||
image.go\
|
||||
|
||||
include ../../../../Make.pkg
|
@ -1,289 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Native Client audio/video
|
||||
|
||||
// Package av implements audio and video access for Native Client
|
||||
// binaries running standalone or embedded in a web browser window.
|
||||
//
|
||||
// The C version of the API is documented at
|
||||
// http://nativeclient.googlecode.com/svn/data/docs_tarball/nacl/googleclient/native_client/scons-out/doc/html/group__audio__video.html
|
||||
package av
|
||||
|
||||
import (
|
||||
"exp/draw"
|
||||
"exp/nacl/srpc"
|
||||
"log"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var srpcEnabled = srpc.Enabled()
|
||||
|
||||
// native_client/src/trusted/service_runtime/include/sys/audio_video.h
|
||||
|
||||
// Subsystem values for Init.
|
||||
const (
|
||||
SubsystemVideo = 1 << iota
|
||||
SubsystemAudio
|
||||
SubsystemEmbed
|
||||
)
|
||||
// SubsystemRawEvents;
|
||||
|
||||
// Audio formats.
|
||||
const (
|
||||
AudioFormatStereo44K = iota
|
||||
AudioFormatStereo48K
|
||||
)
|
||||
|
||||
// A Window represents a connection to the Native Client window.
|
||||
// It implements draw.Context.
|
||||
type Window struct {
|
||||
Embedded bool // running as part of a web page?
|
||||
*Image // screen image
|
||||
eventc chan interface{}
|
||||
}
|
||||
|
||||
// *Window implements draw.Window.
|
||||
var _ draw.Window = (*Window)(nil)
|
||||
|
||||
func (w *Window) EventChan() <-chan interface{} { return w.eventc }
|
||||
|
||||
func (w *Window) Close() os.Error {
|
||||
// TODO(nigeltao): implement.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Window) Screen() draw.Image { return w.Image }
|
||||
|
||||
// Init initializes the Native Client subsystems specified by subsys.
|
||||
// Init must be called before using any of the other functions
|
||||
// in this package, and it must be called only once.
|
||||
//
|
||||
// If the SubsystemVideo flag is set, Init requests a window of size dx×dy.
|
||||
// When embedded in a web page, the web page's window specification
|
||||
// overrides the parameters to Init, so the returned Window may have
|
||||
// a different size than requested.
|
||||
//
|
||||
// If the SubsystemAudio flag is set, Init requests a connection to the
|
||||
// audio device carrying 44 kHz 16-bit stereo PCM audio samples.
|
||||
func Init(subsys int, dx, dy int) (*Window, os.Error) {
|
||||
xsubsys := subsys
|
||||
if srpcEnabled {
|
||||
waitBridge()
|
||||
xsubsys &^= SubsystemVideo | SubsystemEmbed
|
||||
}
|
||||
|
||||
if xsubsys&SubsystemEmbed != 0 {
|
||||
return nil, os.NewError("not embedded")
|
||||
}
|
||||
|
||||
w := new(Window)
|
||||
err := multimediaInit(xsubsys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if subsys&SubsystemVideo != 0 {
|
||||
if dx, dy, err = videoInit(dx, dy); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.Image = newImage(dx, dy, bridge.pixel)
|
||||
w.eventc = make(chan interface{}, 64)
|
||||
}
|
||||
|
||||
if subsys&SubsystemAudio != 0 {
|
||||
var n int
|
||||
if n, err = audioInit(AudioFormatStereo44K, 2048); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
println("audio", n)
|
||||
}
|
||||
|
||||
if subsys&SubsystemVideo != 0 {
|
||||
go w.readEvents()
|
||||
}
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (w *Window) FlushImage() {
|
||||
if w.Image == nil {
|
||||
return
|
||||
}
|
||||
videoUpdate(w.Image.Linear)
|
||||
}
|
||||
|
||||
func multimediaInit(subsys int) (err os.Error) {
|
||||
return os.NewSyscallError("multimedia_init", syscall.MultimediaInit(subsys))
|
||||
}
|
||||
|
||||
func videoInit(dx, dy int) (ndx, ndy int, err os.Error) {
|
||||
if srpcEnabled {
|
||||
bridge.share.ready = 1
|
||||
return int(bridge.share.width), int(bridge.share.height), nil
|
||||
}
|
||||
if e := syscall.VideoInit(dx, dy); e != 0 {
|
||||
return 0, 0, os.NewSyscallError("video_init", int(e))
|
||||
}
|
||||
return dx, dy, nil
|
||||
}
|
||||
|
||||
func videoUpdate(data []Color) (err os.Error) {
|
||||
if srpcEnabled {
|
||||
bridge.flushRPC.Call("upcall", nil)
|
||||
return
|
||||
}
|
||||
return os.NewSyscallError("video_update", syscall.VideoUpdate((*uint32)(&data[0])))
|
||||
}
|
||||
|
||||
var noEvents = os.NewError("no events")
|
||||
|
||||
func videoPollEvent(ev []byte) (err os.Error) {
|
||||
if srpcEnabled {
|
||||
r := bridge.share.eq.ri
|
||||
if r == bridge.share.eq.wi {
|
||||
return noEvents
|
||||
}
|
||||
copy(ev, bridge.share.eq.event[r][0:])
|
||||
bridge.share.eq.ri = (r + 1) % eqsize
|
||||
return nil
|
||||
}
|
||||
return os.NewSyscallError("video_poll_event", syscall.VideoPollEvent(&ev[0]))
|
||||
}
|
||||
|
||||
func audioInit(fmt int, want int) (got int, err os.Error) {
|
||||
var x int
|
||||
e := syscall.AudioInit(fmt, want, &x)
|
||||
if e == 0 {
|
||||
return x, nil
|
||||
}
|
||||
return 0, os.NewSyscallError("audio_init", e)
|
||||
}
|
||||
|
||||
var audioSize uintptr
|
||||
|
||||
// AudioStream provides access to the audio device.
|
||||
// Each call to AudioStream writes the given data,
|
||||
// which should be a slice of 16-bit stereo PCM audio samples,
|
||||
// and returns the number of samples required by the next
|
||||
// call to AudioStream.
|
||||
//
|
||||
// To find out the initial number of samples to write, call AudioStream(nil).
|
||||
//
|
||||
func AudioStream(data []uint16) (nextSize int, err os.Error) {
|
||||
if audioSize == 0 {
|
||||
e := os.NewSyscallError("audio_stream", syscall.AudioStream(nil, &audioSize))
|
||||
return int(audioSize), e
|
||||
}
|
||||
if data == nil {
|
||||
return int(audioSize), nil
|
||||
}
|
||||
if uintptr(len(data))*2 != audioSize {
|
||||
log.Printf("invalid audio size want %d got %d", audioSize, len(data))
|
||||
}
|
||||
e := os.NewSyscallError("audio_stream", syscall.AudioStream(&data[0], &audioSize))
|
||||
return int(audioSize), e
|
||||
}
|
||||
|
||||
// Synchronization structure to wait for bridge to become ready.
|
||||
var bridge struct {
|
||||
c chan bool
|
||||
displayFd int
|
||||
rpcFd int
|
||||
share *videoShare
|
||||
pixel []Color
|
||||
client *srpc.Client
|
||||
flushRPC *srpc.RPC
|
||||
}
|
||||
|
||||
// Wait for bridge to become ready.
|
||||
// When chan is first created, there is nothing in it,
|
||||
// so this blocks. Once the bridge is ready, multimediaBridge.Run
|
||||
// will drop a value into the channel. Then any calls
|
||||
// to waitBridge will finish, taking the value out and immediately putting it back.
|
||||
func waitBridge() { bridge.c <- <-bridge.c }
|
||||
|
||||
const eqsize = 64
|
||||
|
||||
// Data structure shared with host via mmap.
|
||||
type videoShare struct {
|
||||
revision int32 // definition below is rev 100 unless noted
|
||||
mapSize int32
|
||||
|
||||
// event queue
|
||||
eq struct {
|
||||
ri uint32 // read index [0,eqsize)
|
||||
wi uint32 // write index [0,eqsize)
|
||||
eof int32
|
||||
event [eqsize][64]byte
|
||||
}
|
||||
|
||||
// now unused
|
||||
_, _, _, _ int32
|
||||
|
||||
// video backing store information
|
||||
width, height, _, size int32
|
||||
ready int32 // rev 0x101
|
||||
}
|
||||
|
||||
// The frame buffer data is videoShareSize bytes after
|
||||
// the videoShare begins.
|
||||
const videoShareSize = 16 * 1024
|
||||
|
||||
type multimediaBridge struct{}
|
||||
|
||||
// If using SRPC, the runtime will call this method to pass in two file descriptors,
|
||||
// one to mmap to get the display memory, and another to use for SRPCs back
|
||||
// to the main process.
|
||||
func (multimediaBridge) Run(arg, ret []interface{}, size []int) srpc.Errno {
|
||||
bridge.displayFd = arg[0].(int)
|
||||
bridge.rpcFd = arg[1].(int)
|
||||
|
||||
var st syscall.Stat_t
|
||||
if errno := syscall.Fstat(bridge.displayFd, &st); errno != 0 {
|
||||
log.Exitf("mmbridge stat display: %s", os.Errno(errno))
|
||||
}
|
||||
|
||||
addr, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
|
||||
0,
|
||||
uintptr(st.Size),
|
||||
syscall.PROT_READ|syscall.PROT_WRITE,
|
||||
syscall.MAP_SHARED,
|
||||
uintptr(bridge.displayFd),
|
||||
0)
|
||||
if errno != 0 {
|
||||
log.Exitf("mmap display: %s", os.Errno(errno))
|
||||
}
|
||||
|
||||
bridge.share = (*videoShare)(unsafe.Pointer(addr))
|
||||
|
||||
// Overestimate frame buffer size
|
||||
// (must use a compile-time constant)
|
||||
// and then reslice. 256 megapixels (1 GB) should be enough.
|
||||
fb := (*[256 * 1024 * 1024]Color)(unsafe.Pointer(addr + videoShareSize))
|
||||
bridge.pixel = fb[0 : (st.Size-videoShareSize)/4]
|
||||
|
||||
// Configure RPC connection back to client.
|
||||
var err os.Error
|
||||
bridge.client, err = srpc.NewClient(bridge.rpcFd)
|
||||
if err != nil {
|
||||
log.Exitf("NewClient: %s", err)
|
||||
}
|
||||
bridge.flushRPC = bridge.client.NewRPC(nil)
|
||||
|
||||
// Notify waiters that the bridge is ready.
|
||||
println("bridged", bridge.share.revision)
|
||||
bridge.c <- true
|
||||
|
||||
return srpc.OK
|
||||
}
|
||||
|
||||
func init() {
|
||||
bridge.c = make(chan bool, 1)
|
||||
if srpcEnabled {
|
||||
srpc.Add("nacl_multimedia_bridge", "hh:", multimediaBridge{})
|
||||
}
|
||||
}
|
@ -1,473 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// NaCl GUI events.
|
||||
// Clients do not have raw access to the event stream
|
||||
// (only filtered through the lens of package draw)
|
||||
// but perhaps they will.
|
||||
|
||||
package av
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"exp/draw"
|
||||
"image"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// An eventType identifies the type of a Native Client Event.
|
||||
type eventType uint8
|
||||
|
||||
const (
|
||||
eventActive = 1 + iota
|
||||
eventExpose
|
||||
eventKeyDown
|
||||
eventKeyUp
|
||||
eventMouseMotion
|
||||
eventMouseButtonDown
|
||||
eventMouseButtonUp
|
||||
eventQuit
|
||||
eventUnsupported
|
||||
)
|
||||
|
||||
// A key represents a key on a keyboard.
|
||||
type key uint16
|
||||
|
||||
const (
|
||||
keyUnknown = 0
|
||||
keyFirst = 0
|
||||
keyBackspace = 8
|
||||
keyTab = 9
|
||||
keyClear = 12
|
||||
keyReturn = 13
|
||||
keyPause = 19
|
||||
keyEscape = 27
|
||||
keySpace = 32
|
||||
keyExclaim = 33
|
||||
keyQuotedbl = 34
|
||||
keyHash = 35
|
||||
keyDollar = 36
|
||||
keyAmpersand = 38
|
||||
keyQuote = 39
|
||||
keyLeftparen = 40
|
||||
keyRightparen = 41
|
||||
keyAsterisk = 42
|
||||
keyPlus = 43
|
||||
keyComma = 44
|
||||
keyMinus = 45
|
||||
keyPeriod = 46
|
||||
keySlash = 47
|
||||
key0 = 48
|
||||
key1 = 49
|
||||
key2 = 50
|
||||
key3 = 51
|
||||
key4 = 52
|
||||
key5 = 53
|
||||
key6 = 54
|
||||
key7 = 55
|
||||
key8 = 56
|
||||
key9 = 57
|
||||
keyColon = 58
|
||||
keySemicolon = 59
|
||||
keyLess = 60
|
||||
keyEquals = 61
|
||||
keyGreater = 62
|
||||
keyQuestion = 63
|
||||
keyAt = 64
|
||||
keyLeftbracket = 91
|
||||
keyBackslash = 92
|
||||
keyRightbracket = 93
|
||||
keyCaret = 94
|
||||
keyUnderscore = 95
|
||||
keyBackquote = 96
|
||||
keyA = 97
|
||||
keyB = 98
|
||||
keyC = 99
|
||||
keyD = 100
|
||||
keyE = 101
|
||||
keyF = 102
|
||||
keyG = 103
|
||||
keyH = 104
|
||||
keyI = 105
|
||||
keyJ = 106
|
||||
keyK = 107
|
||||
keyL = 108
|
||||
keyM = 109
|
||||
keyN = 110
|
||||
keyO = 111
|
||||
keyP = 112
|
||||
keyQ = 113
|
||||
keyR = 114
|
||||
keyS = 115
|
||||
keyT = 116
|
||||
keyU = 117
|
||||
keyV = 118
|
||||
keyW = 119
|
||||
keyX = 120
|
||||
keyY = 121
|
||||
keyZ = 122
|
||||
keyDelete = 127
|
||||
keyWorld0 = 160
|
||||
keyWorld1 = 161
|
||||
keyWorld2 = 162
|
||||
keyWorld3 = 163
|
||||
keyWorld4 = 164
|
||||
keyWorld5 = 165
|
||||
keyWorld6 = 166
|
||||
keyWorld7 = 167
|
||||
keyWorld8 = 168
|
||||
keyWorld9 = 169
|
||||
keyWorld10 = 170
|
||||
keyWorld11 = 171
|
||||
keyWorld12 = 172
|
||||
keyWorld13 = 173
|
||||
keyWorld14 = 174
|
||||
keyWorld15 = 175
|
||||
keyWorld16 = 176
|
||||
keyWorld17 = 177
|
||||
keyWorld18 = 178
|
||||
keyWorld19 = 179
|
||||
keyWorld20 = 180
|
||||
keyWorld21 = 181
|
||||
keyWorld22 = 182
|
||||
keyWorld23 = 183
|
||||
keyWorld24 = 184
|
||||
keyWorld25 = 185
|
||||
keyWorld26 = 186
|
||||
keyWorld27 = 187
|
||||
keyWorld28 = 188
|
||||
keyWorld29 = 189
|
||||
keyWorld30 = 190
|
||||
keyWorld31 = 191
|
||||
keyWorld32 = 192
|
||||
keyWorld33 = 193
|
||||
keyWorld34 = 194
|
||||
keyWorld35 = 195
|
||||
keyWorld36 = 196
|
||||
keyWorld37 = 197
|
||||
keyWorld38 = 198
|
||||
keyWorld39 = 199
|
||||
keyWorld40 = 200
|
||||
keyWorld41 = 201
|
||||
keyWorld42 = 202
|
||||
keyWorld43 = 203
|
||||
keyWorld44 = 204
|
||||
keyWorld45 = 205
|
||||
keyWorld46 = 206
|
||||
keyWorld47 = 207
|
||||
keyWorld48 = 208
|
||||
keyWorld49 = 209
|
||||
keyWorld50 = 210
|
||||
keyWorld51 = 211
|
||||
keyWorld52 = 212
|
||||
keyWorld53 = 213
|
||||
keyWorld54 = 214
|
||||
keyWorld55 = 215
|
||||
keyWorld56 = 216
|
||||
keyWorld57 = 217
|
||||
keyWorld58 = 218
|
||||
keyWorld59 = 219
|
||||
keyWorld60 = 220
|
||||
keyWorld61 = 221
|
||||
keyWorld62 = 222
|
||||
keyWorld63 = 223
|
||||
keyWorld64 = 224
|
||||
keyWorld65 = 225
|
||||
keyWorld66 = 226
|
||||
keyWorld67 = 227
|
||||
keyWorld68 = 228
|
||||
keyWorld69 = 229
|
||||
keyWorld70 = 230
|
||||
keyWorld71 = 231
|
||||
keyWorld72 = 232
|
||||
keyWorld73 = 233
|
||||
keyWorld74 = 234
|
||||
keyWorld75 = 235
|
||||
keyWorld76 = 236
|
||||
keyWorld77 = 237
|
||||
keyWorld78 = 238
|
||||
keyWorld79 = 239
|
||||
keyWorld80 = 240
|
||||
keyWorld81 = 241
|
||||
keyWorld82 = 242
|
||||
keyWorld83 = 243
|
||||
keyWorld84 = 244
|
||||
keyWorld85 = 245
|
||||
keyWorld86 = 246
|
||||
keyWorld87 = 247
|
||||
keyWorld88 = 248
|
||||
keyWorld89 = 249
|
||||
keyWorld90 = 250
|
||||
keyWorld91 = 251
|
||||
keyWorld92 = 252
|
||||
keyWorld93 = 253
|
||||
keyWorld94 = 254
|
||||
keyWorld95 = 255
|
||||
|
||||
// Numeric keypad
|
||||
keyKp0 = 256
|
||||
keyKp1 = 257
|
||||
keyKp2 = 258
|
||||
keyKp3 = 259
|
||||
keyKp4 = 260
|
||||
keyKp5 = 261
|
||||
keyKp6 = 262
|
||||
keyKp7 = 263
|
||||
keyKp8 = 264
|
||||
keyKp9 = 265
|
||||
keyKpPeriod = 266
|
||||
keyKpDivide = 267
|
||||
keyKpMultiply = 268
|
||||
keyKpMinus = 269
|
||||
keyKpPlus = 270
|
||||
keyKpEnter = 271
|
||||
keyKpEquals = 272
|
||||
|
||||
// Arrow & insert/delete pad
|
||||
keyUp = 273
|
||||
keyDown = 274
|
||||
keyRight = 275
|
||||
keyLeft = 276
|
||||
keyInsert = 277
|
||||
keyHome = 278
|
||||
keyEnd = 279
|
||||
keyPageup = 280
|
||||
keyPagedown = 281
|
||||
|
||||
// Function keys
|
||||
keyF1 = 282
|
||||
keyF2 = 283
|
||||
keyF3 = 284
|
||||
keyF4 = 285
|
||||
keyF5 = 286
|
||||
keyF6 = 287
|
||||
keyF7 = 288
|
||||
keyF8 = 289
|
||||
keyF9 = 290
|
||||
keyF10 = 291
|
||||
keyF11 = 292
|
||||
keyF12 = 293
|
||||
keyF13 = 294
|
||||
keyF14 = 295
|
||||
keyF15 = 296
|
||||
|
||||
// Modifier keys
|
||||
keyNumlock = 300
|
||||
keyCapslock = 301
|
||||
keyScrollock = 302
|
||||
keyRshift = 303
|
||||
keyLshift = 304
|
||||
keyRctrl = 305
|
||||
keyLctrl = 306
|
||||
keyRalt = 307
|
||||
keyLalt = 308
|
||||
keyRmeta = 309
|
||||
keyLmeta = 310
|
||||
keyLsuper = 311
|
||||
keyRsuper = 312
|
||||
keyMode = 313
|
||||
keyCompose = 314
|
||||
|
||||
// Misc keys
|
||||
keyHelp = 315
|
||||
keyPrint = 316
|
||||
keySysreq = 317
|
||||
keyBreak = 318
|
||||
keyMenu = 319
|
||||
keyPower = 320
|
||||
keyEuro = 321
|
||||
keyUndo = 322
|
||||
|
||||
// Add any other keys here
|
||||
keyLast
|
||||
)
|
||||
|
||||
// A keymod is a set of bit flags
|
||||
type keymod uint16
|
||||
|
||||
const (
|
||||
keymodNone = 0x0000
|
||||
keymodLshift = 0x0001
|
||||
keymodRshift = 0x0002
|
||||
keymodLctrl = 0x0040
|
||||
keymodRctrl = 0x0080
|
||||
keymodLalt = 0x0100
|
||||
keymodRalt = 0x0200
|
||||
keymodLmeta = 0x0400
|
||||
keymodRmeta = 0x0800
|
||||
keymodNum = 0x1000
|
||||
keymodCaps = 0x2000
|
||||
keymodMode = 0x4000
|
||||
keymodReserved = 0x8000
|
||||
)
|
||||
|
||||
const (
|
||||
mouseButtonLeft = 1
|
||||
mouseButtonMiddle = 2
|
||||
mouseButtonRight = 3
|
||||
mouseScrollUp = 4
|
||||
mouseScrollDown = 5
|
||||
)
|
||||
|
||||
const (
|
||||
mouseStateLeftButtonPressed = 1
|
||||
mouseStateMiddleButtonPressed = 2
|
||||
mouseStateRightButtonPressed = 4
|
||||
)
|
||||
|
||||
const (
|
||||
activeMouse = 1 // mouse leaving/entering
|
||||
activeInputFocus = 2 // input focus lost/restored
|
||||
activeApplication = 4 // application minimized/restored
|
||||
)
|
||||
|
||||
const maxEventBytes = 64
|
||||
|
||||
type activeEvent struct {
|
||||
EventType eventType
|
||||
Gain uint8
|
||||
State uint8
|
||||
}
|
||||
|
||||
type exposeEvent struct {
|
||||
EventType eventType
|
||||
}
|
||||
|
||||
type keyboardEvent struct {
|
||||
EventType eventType
|
||||
Device uint8
|
||||
State uint8
|
||||
Pad uint8
|
||||
ScanCode uint8
|
||||
Pad1 uint8
|
||||
Key key
|
||||
Mod keymod
|
||||
Unicode uint16
|
||||
}
|
||||
|
||||
type mouseMotionEvent struct {
|
||||
EventType eventType
|
||||
Device uint8
|
||||
Buttons uint8
|
||||
Pad uint8
|
||||
X uint16
|
||||
Y uint16
|
||||
Xrel int16
|
||||
Yrel int16
|
||||
}
|
||||
|
||||
type mouseButtonEvent struct {
|
||||
EventType eventType
|
||||
Device uint8
|
||||
Button uint8
|
||||
State uint8
|
||||
X uint16
|
||||
Y uint16
|
||||
}
|
||||
|
||||
type quitEvent struct {
|
||||
EventType eventType
|
||||
}
|
||||
|
||||
type syncEvent struct{}
|
||||
|
||||
type event interface{}
|
||||
|
||||
type reader []byte
|
||||
|
||||
func (r *reader) Read(p []byte) (n int, err os.Error) {
|
||||
b := *r
|
||||
if len(b) == 0 && len(p) > 0 {
|
||||
return 0, os.EOF
|
||||
}
|
||||
n = copy(p, b)
|
||||
*r = b[n:]
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Window) readEvents() {
|
||||
buf := make([]byte, maxEventBytes)
|
||||
clean := false
|
||||
var (
|
||||
ea *activeEvent
|
||||
ee *exposeEvent
|
||||
ke *keyboardEvent
|
||||
mme *mouseMotionEvent
|
||||
mbe *mouseButtonEvent
|
||||
qe *quitEvent
|
||||
)
|
||||
var m draw.MouseEvent
|
||||
for {
|
||||
if err := videoPollEvent(buf); err != nil {
|
||||
if !clean {
|
||||
clean = w.eventc <- draw.ConfigEvent{image.Config{ColorModel, w.Image.Bounds().Dx(), w.Image.Bounds().Dy()}}
|
||||
}
|
||||
time.Sleep(10e6) // 10ms
|
||||
continue
|
||||
}
|
||||
clean = false
|
||||
var e event
|
||||
switch buf[0] {
|
||||
default:
|
||||
log.Print("unsupported event type", buf[0])
|
||||
continue
|
||||
case eventActive:
|
||||
ea = new(activeEvent)
|
||||
e = ea
|
||||
case eventExpose:
|
||||
ee = new(exposeEvent)
|
||||
e = ee
|
||||
case eventKeyDown, eventKeyUp:
|
||||
ke = new(keyboardEvent)
|
||||
e = ke
|
||||
case eventMouseMotion:
|
||||
mme = new(mouseMotionEvent)
|
||||
e = mme
|
||||
case eventMouseButtonDown, eventMouseButtonUp:
|
||||
mbe = new(mouseButtonEvent)
|
||||
e = mbe
|
||||
case eventQuit:
|
||||
qe = new(quitEvent)
|
||||
e = qe
|
||||
}
|
||||
r := reader(buf)
|
||||
if err := binary.Read(&r, binary.LittleEndian, e); err != nil {
|
||||
log.Printf("unpacking %T event: %s", e, err)
|
||||
continue
|
||||
}
|
||||
// log.Printf("%#v\n", e);
|
||||
switch buf[0] {
|
||||
case eventExpose:
|
||||
w.eventc <- draw.ConfigEvent{image.Config{ColorModel, w.Image.Bounds().Dx(), w.Image.Bounds().Dy()}}
|
||||
case eventKeyDown:
|
||||
w.eventc <- draw.KeyEvent{int(ke.Key)}
|
||||
case eventKeyUp:
|
||||
w.eventc <- draw.KeyEvent{-int(ke.Key)}
|
||||
case eventMouseMotion:
|
||||
m.Loc.X = int(mme.X)
|
||||
m.Loc.Y = int(mme.Y)
|
||||
m.Buttons = int(mme.Buttons)
|
||||
m.Nsec = time.Nanoseconds()
|
||||
_ = w.eventc <- m
|
||||
case eventMouseButtonDown:
|
||||
m.Loc.X = int(mbe.X)
|
||||
m.Loc.Y = int(mbe.Y)
|
||||
// TODO(rsc): Remove uint cast once 8g bug is fixed.
|
||||
m.Buttons |= 1 << uint(mbe.Button-1)
|
||||
m.Nsec = time.Nanoseconds()
|
||||
_ = w.eventc <- m
|
||||
case eventMouseButtonUp:
|
||||
m.Loc.X = int(mbe.X)
|
||||
m.Loc.Y = int(mbe.Y)
|
||||
// TODO(rsc): Remove uint cast once 8g bug is fixed.
|
||||
m.Buttons &^= 1 << uint(mbe.Button-1)
|
||||
m.Nsec = time.Nanoseconds()
|
||||
_ = w.eventc <- m
|
||||
case eventQuit:
|
||||
close(w.eventc)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package av
|
||||
|
||||
import (
|
||||
"image"
|
||||
)
|
||||
|
||||
// Native Client image format:
|
||||
// a single linear array of 32-bit ARGB as packed uint32s.
|
||||
|
||||
// An Image represents a Native Client frame buffer.
|
||||
// The pixels in the image can be accessed as a single
|
||||
// linear slice or as a two-dimensional slice of slices.
|
||||
// Image implements image.Image.
|
||||
type Image struct {
|
||||
Linear []Color
|
||||
Pixel [][]Color
|
||||
}
|
||||
|
||||
var _ image.Image = (*Image)(nil)
|
||||
|
||||
func (m *Image) ColorModel() image.ColorModel { return ColorModel }
|
||||
|
||||
func (m *Image) Bounds() image.Rectangle {
|
||||
if len(m.Pixel) == 0 {
|
||||
return image.ZR
|
||||
}
|
||||
return image.Rectangle{image.ZP, image.Point{len(m.Pixel[0]), len(m.Pixel)}}
|
||||
}
|
||||
|
||||
func (m *Image) At(x, y int) image.Color { return m.Pixel[y][x] }
|
||||
|
||||
func (m *Image) Set(x, y int, color image.Color) {
|
||||
if c, ok := color.(Color); ok {
|
||||
m.Pixel[y][x] = c
|
||||
return
|
||||
}
|
||||
m.Pixel[y][x] = makeColor(color.RGBA())
|
||||
}
|
||||
|
||||
func newImage(dx, dy int, linear []Color) *Image {
|
||||
if linear == nil {
|
||||
linear = make([]Color, dx*dy)
|
||||
}
|
||||
pix := make([][]Color, dy)
|
||||
for i := range pix {
|
||||
pix[i] = linear[dx*i : dx*(i+1)]
|
||||
}
|
||||
return &Image{linear, pix}
|
||||
}
|
||||
|
||||
// A Color represents a Native Client color value,
|
||||
// a 32-bit R, G, B, A value packed as 0xAARRGGBB.
|
||||
type Color uint32
|
||||
|
||||
func (p Color) RGBA() (r, g, b, a uint32) {
|
||||
x := uint32(p)
|
||||
a = x >> 24
|
||||
a |= a << 8
|
||||
r = (x >> 16) & 0xFF
|
||||
r |= r << 8
|
||||
g = (x >> 8) & 0xFF
|
||||
g |= g << 8
|
||||
b = x & 0xFF
|
||||
b |= b << 8
|
||||
return
|
||||
}
|
||||
|
||||
func makeColor(r, g, b, a uint32) Color {
|
||||
return Color(a>>8<<24 | r>>8<<16 | g>>8<<8 | b>>8)
|
||||
}
|
||||
|
||||
func toColor(color image.Color) image.Color {
|
||||
if c, ok := color.(Color); ok {
|
||||
return c
|
||||
}
|
||||
return makeColor(color.RGBA())
|
||||
}
|
||||
|
||||
// ColorModel is the color model corresponding to the Native Client Color.
|
||||
var ColorModel = image.ColorModelFunc(toColor)
|
@ -1,13 +0,0 @@
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../../../Make.inc
|
||||
|
||||
TARG=exp/nacl/srpc
|
||||
GOFILES=\
|
||||
client.go\
|
||||
msg.go\
|
||||
server.go\
|
||||
|
||||
include ../../../../Make.pkg
|
@ -1,210 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements Native Client's simple RPC (SRPC).
|
||||
package srpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A Client represents the client side of an SRPC connection.
|
||||
type Client struct {
|
||||
fd int // fd to server
|
||||
r msgReceiver
|
||||
s msgSender
|
||||
service map[string]srv // services by name
|
||||
out chan *msg // send to out to write to connection
|
||||
|
||||
mu sync.Mutex // protects pending, idGen
|
||||
pending map[uint64]*RPC
|
||||
idGen uint64 // generator for request IDs
|
||||
}
|
||||
|
||||
// A srv is a single method that the server offers.
|
||||
type srv struct {
|
||||
num uint32 // method number
|
||||
fmt string // argument format
|
||||
}
|
||||
|
||||
// An RPC represents a single RPC issued by a client.
|
||||
type RPC struct {
|
||||
Ret []interface{} // Return values
|
||||
Done chan *RPC // Channel where notification of done arrives
|
||||
Errno Errno // Status code
|
||||
c *Client
|
||||
id uint64 // request id
|
||||
}
|
||||
|
||||
// NewClient allocates a new client using the file descriptor fd.
|
||||
func NewClient(fd int) (c *Client, err os.Error) {
|
||||
c = new(Client)
|
||||
c.fd = fd
|
||||
c.r.fd = fd
|
||||
c.s.fd = fd
|
||||
c.service = make(map[string]srv)
|
||||
c.pending = make(map[uint64]*RPC)
|
||||
|
||||
// service discovery request
|
||||
m := &msg{
|
||||
protocol: protocol,
|
||||
isReq: true,
|
||||
Ret: []interface{}{[]byte(nil)},
|
||||
Size: []int{4000},
|
||||
}
|
||||
m.packRequest()
|
||||
c.s.send(m)
|
||||
m, err = c.r.recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.unpackResponse()
|
||||
if m.status != OK {
|
||||
log.Printf("NewClient service_discovery: %s", m.status)
|
||||
return nil, m.status
|
||||
}
|
||||
for n, line := range bytes.Split(m.Ret[0].([]byte), []byte{'\n'}, -1) {
|
||||
i := bytes.Index(line, []byte{':'})
|
||||
if i < 0 {
|
||||
continue
|
||||
}
|
||||
c.service[string(line[0:i])] = srv{uint32(n), string(line[i+1:])}
|
||||
}
|
||||
|
||||
c.out = make(chan *msg)
|
||||
go c.input()
|
||||
go c.output()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Client) input() {
|
||||
for {
|
||||
m, err := c.r.recv()
|
||||
if err != nil {
|
||||
log.Exitf("client recv: %s", err)
|
||||
}
|
||||
if m.unpackResponse(); m.status != OK {
|
||||
log.Printf("invalid message: %s", m.status)
|
||||
continue
|
||||
}
|
||||
c.mu.Lock()
|
||||
rpc, ok := c.pending[m.requestId]
|
||||
if ok {
|
||||
c.pending[m.requestId] = nil, false
|
||||
}
|
||||
c.mu.Unlock()
|
||||
if !ok {
|
||||
log.Print("unexpected response")
|
||||
continue
|
||||
}
|
||||
rpc.Ret = m.Ret
|
||||
rpc.Done <- rpc
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) output() {
|
||||
for m := range c.out {
|
||||
c.s.send(m)
|
||||
}
|
||||
}
|
||||
|
||||
// NewRPC creates a new RPC on the client connection.
|
||||
func (c *Client) NewRPC(done chan *RPC) *RPC {
|
||||
if done == nil {
|
||||
done = make(chan *RPC)
|
||||
}
|
||||
c.mu.Lock()
|
||||
id := c.idGen
|
||||
c.idGen++
|
||||
c.mu.Unlock()
|
||||
return &RPC{nil, done, OK, c, id}
|
||||
}
|
||||
|
||||
// Start issues an RPC request for method name with the given arguments.
|
||||
// The RPC r must not be in use for another pending request.
|
||||
// To wait for the RPC to finish, receive from r.Done and then
|
||||
// inspect r.Ret and r.Errno.
|
||||
func (r *RPC) Start(name string, arg []interface{}) {
|
||||
var m msg
|
||||
|
||||
r.Errno = OK
|
||||
r.c.mu.Lock()
|
||||
srv, ok := r.c.service[name]
|
||||
if !ok {
|
||||
r.c.mu.Unlock()
|
||||
r.Errno = ErrBadRPCNumber
|
||||
r.Done <- r
|
||||
return
|
||||
}
|
||||
r.c.pending[r.id] = r
|
||||
r.c.mu.Unlock()
|
||||
|
||||
m.protocol = protocol
|
||||
m.requestId = r.id
|
||||
m.isReq = true
|
||||
m.rpcNumber = srv.num
|
||||
m.Arg = arg
|
||||
|
||||
// Fill in the return values and sizes to generate
|
||||
// the right type chars. We'll take most any size.
|
||||
|
||||
// Skip over input arguments.
|
||||
// We could check them against arg, but the server
|
||||
// will do that anyway.
|
||||
i := 0
|
||||
for srv.fmt[i] != ':' {
|
||||
i++
|
||||
}
|
||||
fmt := srv.fmt[i+1:]
|
||||
|
||||
// Now the return prototypes.
|
||||
m.Ret = make([]interface{}, len(fmt)-i)
|
||||
m.Size = make([]int, len(fmt)-i)
|
||||
for i := 0; i < len(fmt); i++ {
|
||||
switch fmt[i] {
|
||||
default:
|
||||
log.Exitf("unexpected service type %c", fmt[i])
|
||||
case 'b':
|
||||
m.Ret[i] = false
|
||||
case 'C':
|
||||
m.Ret[i] = []byte(nil)
|
||||
m.Size[i] = 1 << 30
|
||||
case 'd':
|
||||
m.Ret[i] = float64(0)
|
||||
case 'D':
|
||||
m.Ret[i] = []float64(nil)
|
||||
m.Size[i] = 1 << 30
|
||||
case 'h':
|
||||
m.Ret[i] = int(-1)
|
||||
case 'i':
|
||||
m.Ret[i] = int32(0)
|
||||
case 'I':
|
||||
m.Ret[i] = []int32(nil)
|
||||
m.Size[i] = 1 << 30
|
||||
case 's':
|
||||
m.Ret[i] = ""
|
||||
m.Size[i] = 1 << 30
|
||||
}
|
||||
}
|
||||
|
||||
m.packRequest()
|
||||
r.c.out <- &m
|
||||
}
|
||||
|
||||
// Call is a convenient wrapper that starts the RPC request,
|
||||
// waits for it to finish, and then returns the results.
|
||||
// Its implementation is:
|
||||
//
|
||||
// r.Start(name, arg)
|
||||
// <-r.Done
|
||||
// return r.Ret, r.Errno
|
||||
//
|
||||
func (r *RPC) Call(name string, arg []interface{}) (ret []interface{}, err Errno) {
|
||||
r.Start(name, arg)
|
||||
<-r.Done
|
||||
return r.Ret, r.Errno
|
||||
}
|
@ -1,522 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// SRPC constants, data structures, and parsing.
|
||||
|
||||
package srpc
|
||||
|
||||
import (
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// An Errno is an SRPC status code.
|
||||
type Errno uint32
|
||||
|
||||
const (
|
||||
OK Errno = 256 + iota
|
||||
ErrBreak
|
||||
ErrMessageTruncated
|
||||
ErrNoMemory
|
||||
ErrProtocolMismatch
|
||||
ErrBadRPCNumber
|
||||
ErrBadArgType
|
||||
ErrTooFewArgs
|
||||
ErrTooManyArgs
|
||||
ErrInArgTypeMismatch
|
||||
ErrOutArgTypeMismatch
|
||||
ErrInternalError
|
||||
ErrAppError
|
||||
)
|
||||
|
||||
var errstr = [...]string{
|
||||
OK - OK: "ok",
|
||||
ErrBreak - OK: "break",
|
||||
ErrMessageTruncated - OK: "message truncated",
|
||||
ErrNoMemory - OK: "out of memory",
|
||||
ErrProtocolMismatch - OK: "protocol mismatch",
|
||||
ErrBadRPCNumber - OK: "invalid RPC method number",
|
||||
ErrBadArgType - OK: "unexpected argument type",
|
||||
ErrTooFewArgs - OK: "too few arguments",
|
||||
ErrTooManyArgs - OK: "too many arguments",
|
||||
ErrInArgTypeMismatch - OK: "input argument type mismatch",
|
||||
ErrOutArgTypeMismatch - OK: "output argument type mismatch",
|
||||
ErrInternalError - OK: "internal error",
|
||||
ErrAppError - OK: "application error",
|
||||
}
|
||||
|
||||
func (e Errno) String() string {
|
||||
if e < OK || int(e-OK) >= len(errstr) {
|
||||
return "Errno(" + strconv.Itoa64(int64(e)) + ")"
|
||||
}
|
||||
return errstr[e-OK]
|
||||
}
|
||||
|
||||
// A *msgHdr is the data argument to the imc_recvmsg
|
||||
// and imc_sendmsg system calls. Because it contains unchecked
|
||||
// counts trusted by the system calls, the data structure is unsafe
|
||||
// to expose to package clients.
|
||||
type msgHdr struct {
|
||||
iov *iov
|
||||
niov int32
|
||||
desc *int32
|
||||
ndesc int32
|
||||
flags uint32
|
||||
}
|
||||
|
||||
// A single region for I/O. Just as unsafe as msgHdr.
|
||||
type iov struct {
|
||||
base *byte
|
||||
len int32
|
||||
}
|
||||
|
||||
// A msg is the Go representation of a message.
|
||||
type msg struct {
|
||||
rdata []byte // data being consumed during message parsing
|
||||
rdesc []int32 // file descriptors being consumed during message parsing
|
||||
wdata []byte // data being generated when replying
|
||||
|
||||
// parsed version of message
|
||||
protocol uint32
|
||||
requestId uint64
|
||||
isReq bool
|
||||
rpcNumber uint32
|
||||
gotHeader bool
|
||||
status Errno // error code sent in response
|
||||
Arg []interface{} // method arguments
|
||||
Ret []interface{} // method results
|
||||
Size []int // max sizes for arrays in method results
|
||||
fmt string // accumulated format string of arg+":"+ret
|
||||
}
|
||||
|
||||
// A msgReceiver receives messages from a file descriptor.
|
||||
type msgReceiver struct {
|
||||
fd int
|
||||
data [128 * 1024]byte
|
||||
desc [8]int32
|
||||
hdr msgHdr
|
||||
iov iov
|
||||
}
|
||||
|
||||
func (r *msgReceiver) recv() (*msg, os.Error) {
|
||||
// Init pointers to buffers where syscall recvmsg can write.
|
||||
r.iov.base = &r.data[0]
|
||||
r.iov.len = int32(len(r.data))
|
||||
r.hdr.iov = &r.iov
|
||||
r.hdr.niov = 1
|
||||
r.hdr.desc = &r.desc[0]
|
||||
r.hdr.ndesc = int32(len(r.desc))
|
||||
n, _, e := syscall.Syscall(syscall.SYS_IMC_RECVMSG, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0)
|
||||
if e != 0 {
|
||||
return nil, os.NewSyscallError("imc_recvmsg", int(e))
|
||||
}
|
||||
|
||||
// Make a copy of the data so that the next recvmsg doesn't
|
||||
// smash it. The system call did not update r.iov.len. Instead it
|
||||
// returned the total byte count as n.
|
||||
m := new(msg)
|
||||
m.rdata = make([]byte, n)
|
||||
copy(m.rdata, r.data[0:])
|
||||
|
||||
// Make a copy of the desc too.
|
||||
// The system call *did* update r.hdr.ndesc.
|
||||
if r.hdr.ndesc > 0 {
|
||||
m.rdesc = make([]int32, r.hdr.ndesc)
|
||||
copy(m.rdesc, r.desc)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// A msgSender sends messages on a file descriptor.
|
||||
type msgSender struct {
|
||||
fd int
|
||||
hdr msgHdr
|
||||
iov iov
|
||||
}
|
||||
|
||||
func (s *msgSender) send(m *msg) os.Error {
|
||||
if len(m.wdata) > 0 {
|
||||
s.iov.base = &m.wdata[0]
|
||||
}
|
||||
s.iov.len = int32(len(m.wdata))
|
||||
s.hdr.iov = &s.iov
|
||||
s.hdr.niov = 1
|
||||
s.hdr.desc = nil
|
||||
s.hdr.ndesc = 0
|
||||
_, _, e := syscall.Syscall(syscall.SYS_IMC_SENDMSG, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0)
|
||||
if e != 0 {
|
||||
return os.NewSyscallError("imc_sendmsg", int(e))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reading from msg.rdata.
|
||||
func (m *msg) uint8() uint8 {
|
||||
if m.status != OK {
|
||||
return 0
|
||||
}
|
||||
if len(m.rdata) < 1 {
|
||||
m.status = ErrMessageTruncated
|
||||
return 0
|
||||
}
|
||||
x := m.rdata[0]
|
||||
m.rdata = m.rdata[1:]
|
||||
return x
|
||||
}
|
||||
|
||||
func (m *msg) uint32() uint32 {
|
||||
if m.status != OK {
|
||||
return 0
|
||||
}
|
||||
if len(m.rdata) < 4 {
|
||||
m.status = ErrMessageTruncated
|
||||
return 0
|
||||
}
|
||||
b := m.rdata[0:4]
|
||||
x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||
m.rdata = m.rdata[4:]
|
||||
return x
|
||||
}
|
||||
|
||||
func (m *msg) uint64() uint64 {
|
||||
if m.status != OK {
|
||||
return 0
|
||||
}
|
||||
if len(m.rdata) < 8 {
|
||||
m.status = ErrMessageTruncated
|
||||
return 0
|
||||
}
|
||||
b := m.rdata[0:8]
|
||||
x := uint64(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
|
||||
x |= uint64(uint32(b[4])|uint32(b[5])<<8|uint32(b[6])<<16|uint32(b[7])<<24) << 32
|
||||
m.rdata = m.rdata[8:]
|
||||
return x
|
||||
}
|
||||
|
||||
func (m *msg) bytes(n int) []byte {
|
||||
if m.status != OK {
|
||||
return nil
|
||||
}
|
||||
if len(m.rdata) < n {
|
||||
m.status = ErrMessageTruncated
|
||||
return nil
|
||||
}
|
||||
x := m.rdata[0:n]
|
||||
m.rdata = m.rdata[n:]
|
||||
return x
|
||||
}
|
||||
|
||||
// Writing to msg.wdata.
|
||||
func (m *msg) grow(n int) []byte {
|
||||
i := len(m.wdata)
|
||||
if i+n > cap(m.wdata) {
|
||||
a := make([]byte, i, (i+n)*2)
|
||||
copy(a, m.wdata)
|
||||
m.wdata = a
|
||||
}
|
||||
m.wdata = m.wdata[0 : i+n]
|
||||
return m.wdata[i : i+n]
|
||||
}
|
||||
|
||||
func (m *msg) wuint8(x uint8) { m.grow(1)[0] = x }
|
||||
|
||||
func (m *msg) wuint32(x uint32) {
|
||||
b := m.grow(4)
|
||||
b[0] = byte(x)
|
||||
b[1] = byte(x >> 8)
|
||||
b[2] = byte(x >> 16)
|
||||
b[3] = byte(x >> 24)
|
||||
}
|
||||
|
||||
func (m *msg) wuint64(x uint64) {
|
||||
b := m.grow(8)
|
||||
lo := uint32(x)
|
||||
b[0] = byte(lo)
|
||||
b[1] = byte(lo >> 8)
|
||||
b[2] = byte(lo >> 16)
|
||||
b[3] = byte(lo >> 24)
|
||||
hi := uint32(x >> 32)
|
||||
b[4] = byte(hi)
|
||||
b[5] = byte(hi >> 8)
|
||||
b[6] = byte(hi >> 16)
|
||||
b[7] = byte(hi >> 24)
|
||||
}
|
||||
|
||||
func (m *msg) wbytes(p []byte) { copy(m.grow(len(p)), p) }
|
||||
|
||||
func (m *msg) wstring(s string) {
|
||||
b := m.grow(len(s))
|
||||
copy(b, s)
|
||||
}
|
||||
|
||||
// Parsing of RPC header and arguments.
|
||||
//
|
||||
// The header format is:
|
||||
// protocol uint32;
|
||||
// requestId uint64;
|
||||
// isReq bool;
|
||||
// rpcNumber uint32;
|
||||
// status uint32; // only for response
|
||||
//
|
||||
// Then a sequence of values follow, preceded by the length:
|
||||
// nvalue uint32;
|
||||
//
|
||||
// Each value begins with a one-byte type followed by
|
||||
// type-specific data.
|
||||
//
|
||||
// type uint8;
|
||||
// 'b': x bool;
|
||||
// 'C': len uint32; x [len]byte;
|
||||
// 'd': x float64;
|
||||
// 'D': len uint32; x [len]float64;
|
||||
// 'h': x int; // handle aka file descriptor
|
||||
// 'i': x int32;
|
||||
// 'I': len uint32; x [len]int32;
|
||||
// 's': len uint32; x [len]byte;
|
||||
//
|
||||
// If this is a request, a sequence of pseudo-values follows,
|
||||
// preceded by its length (nvalue uint32).
|
||||
//
|
||||
// Each pseudo-value is a one-byte type as above,
|
||||
// followed by a maximum length (len uint32)
|
||||
// for the 'C', 'D', 'I', and 's' types.
|
||||
//
|
||||
// In the Go msg, we represent each argument by
|
||||
// an empty interface containing the type of x in the
|
||||
// corresponding case.
|
||||
|
||||
// The current protocol number.
|
||||
const protocol = 0xc0da0002
|
||||
|
||||
func (m *msg) unpackHeader() {
|
||||
m.protocol = m.uint32()
|
||||
m.requestId = m.uint64()
|
||||
m.isReq = m.uint8() != 0
|
||||
m.rpcNumber = m.uint32()
|
||||
m.gotHeader = m.status == OK // signal that header parsed successfully
|
||||
if m.gotHeader && !m.isReq {
|
||||
status := Errno(m.uint32())
|
||||
m.gotHeader = m.status == OK // still ok?
|
||||
if m.gotHeader {
|
||||
m.status = status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *msg) packHeader() {
|
||||
m.wuint32(m.protocol)
|
||||
m.wuint64(m.requestId)
|
||||
if m.isReq {
|
||||
m.wuint8(1)
|
||||
} else {
|
||||
m.wuint8(0)
|
||||
}
|
||||
m.wuint32(m.rpcNumber)
|
||||
if !m.isReq {
|
||||
m.wuint32(uint32(m.status))
|
||||
}
|
||||
}
|
||||
|
||||
func (m *msg) unpackValues(v []interface{}) {
|
||||
for i := range v {
|
||||
t := m.uint8()
|
||||
m.fmt += string(t)
|
||||
switch t {
|
||||
default:
|
||||
if m.status == OK {
|
||||
m.status = ErrBadArgType
|
||||
}
|
||||
return
|
||||
case 'b': // bool[1]
|
||||
v[i] = m.uint8() > 0
|
||||
case 'C': // char array
|
||||
v[i] = m.bytes(int(m.uint32()))
|
||||
case 'd': // double
|
||||
v[i] = math.Float64frombits(m.uint64())
|
||||
case 'D': // double array
|
||||
a := make([]float64, int(m.uint32()))
|
||||
for j := range a {
|
||||
a[j] = math.Float64frombits(m.uint64())
|
||||
}
|
||||
v[i] = a
|
||||
case 'h': // file descriptor (handle)
|
||||
if len(m.rdesc) == 0 {
|
||||
if m.status == OK {
|
||||
m.status = ErrBadArgType
|
||||
}
|
||||
return
|
||||
}
|
||||
v[i] = int(m.rdesc[0])
|
||||
m.rdesc = m.rdesc[1:]
|
||||
case 'i': // int
|
||||
v[i] = int32(m.uint32())
|
||||
case 'I': // int array
|
||||
a := make([]int32, int(m.uint32()))
|
||||
for j := range a {
|
||||
a[j] = int32(m.uint32())
|
||||
}
|
||||
v[i] = a
|
||||
case 's': // string
|
||||
v[i] = string(m.bytes(int(m.uint32())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *msg) packValues(v []interface{}) {
|
||||
for i := range v {
|
||||
switch x := v[i].(type) {
|
||||
default:
|
||||
if m.status == OK {
|
||||
m.status = ErrInternalError
|
||||
}
|
||||
return
|
||||
case bool:
|
||||
m.wuint8('b')
|
||||
if x {
|
||||
m.wuint8(1)
|
||||
} else {
|
||||
m.wuint8(0)
|
||||
}
|
||||
case []byte:
|
||||
m.wuint8('C')
|
||||
m.wuint32(uint32(len(x)))
|
||||
m.wbytes(x)
|
||||
case float64:
|
||||
m.wuint8('d')
|
||||
m.wuint64(math.Float64bits(x))
|
||||
case []float64:
|
||||
m.wuint8('D')
|
||||
m.wuint32(uint32(len(x)))
|
||||
for _, f := range x {
|
||||
m.wuint64(math.Float64bits(f))
|
||||
}
|
||||
case int32:
|
||||
m.wuint8('i')
|
||||
m.wuint32(uint32(x))
|
||||
case []int32:
|
||||
m.wuint8('I')
|
||||
m.wuint32(uint32(len(x)))
|
||||
for _, i := range x {
|
||||
m.wuint32(uint32(i))
|
||||
}
|
||||
case string:
|
||||
m.wuint8('s')
|
||||
m.wuint32(uint32(len(x)))
|
||||
m.wstring(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *msg) unpackRequest() {
|
||||
m.status = OK
|
||||
if m.unpackHeader(); m.status != OK {
|
||||
return
|
||||
}
|
||||
if m.protocol != protocol || !m.isReq {
|
||||
m.status = ErrProtocolMismatch
|
||||
return
|
||||
}
|
||||
|
||||
// type-tagged argument values
|
||||
m.Arg = make([]interface{}, m.uint32())
|
||||
m.unpackValues(m.Arg)
|
||||
if m.status != OK {
|
||||
return
|
||||
}
|
||||
|
||||
// type-tagged expected return sizes.
|
||||
// fill in zero values for each return value
|
||||
// and save sizes.
|
||||
m.fmt += ":"
|
||||
m.Ret = make([]interface{}, m.uint32())
|
||||
m.Size = make([]int, len(m.Ret))
|
||||
for i := range m.Ret {
|
||||
t := m.uint8()
|
||||
m.fmt += string(t)
|
||||
switch t {
|
||||
default:
|
||||
if m.status == OK {
|
||||
m.status = ErrBadArgType
|
||||
}
|
||||
return
|
||||
case 'b': // bool[1]
|
||||
m.Ret[i] = false
|
||||
case 'C': // char array
|
||||
m.Size[i] = int(m.uint32())
|
||||
m.Ret[i] = []byte(nil)
|
||||
case 'd': // double
|
||||
m.Ret[i] = float64(0)
|
||||
case 'D': // double array
|
||||
m.Size[i] = int(m.uint32())
|
||||
m.Ret[i] = []float64(nil)
|
||||
case 'h': // file descriptor (handle)
|
||||
m.Ret[i] = int(-1)
|
||||
case 'i': // int
|
||||
m.Ret[i] = int32(0)
|
||||
case 'I': // int array
|
||||
m.Size[i] = int(m.uint32())
|
||||
m.Ret[i] = []int32(nil)
|
||||
case 's': // string
|
||||
m.Size[i] = int(m.uint32())
|
||||
m.Ret[i] = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *msg) packRequest() {
|
||||
m.packHeader()
|
||||
m.wuint32(uint32(len(m.Arg)))
|
||||
m.packValues(m.Arg)
|
||||
m.wuint32(uint32(len(m.Ret)))
|
||||
for i, v := range m.Ret {
|
||||
switch x := v.(type) {
|
||||
case bool:
|
||||
m.wuint8('b')
|
||||
case []byte:
|
||||
m.wuint8('C')
|
||||
m.wuint32(uint32(m.Size[i]))
|
||||
case float64:
|
||||
m.wuint8('d')
|
||||
case []float64:
|
||||
m.wuint8('D')
|
||||
m.wuint32(uint32(m.Size[i]))
|
||||
case int:
|
||||
m.wuint8('h')
|
||||
case int32:
|
||||
m.wuint8('i')
|
||||
case []int32:
|
||||
m.wuint8('I')
|
||||
m.wuint32(uint32(m.Size[i]))
|
||||
case string:
|
||||
m.wuint8('s')
|
||||
m.wuint32(uint32(m.Size[i]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *msg) unpackResponse() {
|
||||
m.status = OK
|
||||
if m.unpackHeader(); m.status != OK {
|
||||
return
|
||||
}
|
||||
if m.protocol != protocol || m.isReq {
|
||||
m.status = ErrProtocolMismatch
|
||||
return
|
||||
}
|
||||
|
||||
// type-tagged return values
|
||||
m.fmt = ""
|
||||
m.Ret = make([]interface{}, m.uint32())
|
||||
m.unpackValues(m.Ret)
|
||||
}
|
||||
|
||||
func (m *msg) packResponse() {
|
||||
m.packHeader()
|
||||
m.wuint32(uint32(len(m.Ret)))
|
||||
m.packValues(m.Ret)
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// SRPC server
|
||||
|
||||
package srpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// TODO(rsc): I'd prefer to make this
|
||||
// type Handler func(m *msg) Errno
|
||||
// but NaCl can't use closures.
|
||||
// The explicit interface is a way to attach state.
|
||||
|
||||
// A Handler is a handler for an SRPC method.
|
||||
// It reads arguments from arg, checks size for array limits,
|
||||
// writes return values to ret, and returns an Errno status code.
|
||||
type Handler interface {
|
||||
Run(arg, ret []interface{}, size []int) Errno
|
||||
}
|
||||
|
||||
type method struct {
|
||||
name string
|
||||
fmt string
|
||||
handler Handler
|
||||
}
|
||||
|
||||
var rpcMethod []method
|
||||
|
||||
// BUG(rsc): Add's format string should be replaced by analyzing the
|
||||
// type of an arbitrary func passed in an interface{} using reflection.
|
||||
|
||||
// Add registers a handler for the named method.
|
||||
// Fmt is a Native Client format string, a sequence of
|
||||
// alphabetic characters representing the types of the parameter values,
|
||||
// a colon, and then a sequence of alphabetic characters
|
||||
// representing the types of the returned values.
|
||||
// The format characters and corresponding dynamic types are:
|
||||
//
|
||||
// b bool
|
||||
// C []byte
|
||||
// d float64
|
||||
// D []float64
|
||||
// h int // a file descriptor (aka handle)
|
||||
// i int32
|
||||
// I []int32
|
||||
// s string
|
||||
//
|
||||
func Add(name, fmt string, handler Handler) {
|
||||
rpcMethod = append(rpcMethod, method{name, fmt, handler})
|
||||
}
|
||||
|
||||
// Serve accepts new SRPC connections from the file descriptor fd
|
||||
// and answers RPCs issued on those connections.
|
||||
// It closes fd and returns an error if the imc_accept system call fails.
|
||||
func Serve(fd int) os.Error {
|
||||
defer syscall.Close(fd)
|
||||
|
||||
for {
|
||||
cfd, _, e := syscall.Syscall(syscall.SYS_IMC_ACCEPT, uintptr(fd), 0, 0)
|
||||
if e != 0 {
|
||||
return os.NewSyscallError("imc_accept", int(e))
|
||||
}
|
||||
go serveLoop(int(cfd))
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func serveLoop(fd int) {
|
||||
c := make(chan *msg)
|
||||
go sendLoop(fd, c)
|
||||
|
||||
var r msgReceiver
|
||||
r.fd = fd
|
||||
for {
|
||||
m, err := r.recv()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
m.unpackRequest()
|
||||
if !m.gotHeader {
|
||||
log.Printf("cannot unpack header: %s", m.status)
|
||||
continue
|
||||
}
|
||||
// log.Printf("<- %#v", m);
|
||||
m.isReq = false // set up for response
|
||||
go serveMsg(m, c)
|
||||
}
|
||||
close(c)
|
||||
}
|
||||
|
||||
func sendLoop(fd int, c <-chan *msg) {
|
||||
var s msgSender
|
||||
s.fd = fd
|
||||
for m := range c {
|
||||
// log.Printf("-> %#v", m);
|
||||
m.packResponse()
|
||||
s.send(m)
|
||||
}
|
||||
syscall.Close(fd)
|
||||
}
|
||||
|
||||
func serveMsg(m *msg, c chan<- *msg) {
|
||||
if m.status != OK {
|
||||
c <- m
|
||||
return
|
||||
}
|
||||
if m.rpcNumber >= uint32(len(rpcMethod)) {
|
||||
m.status = ErrBadRPCNumber
|
||||
c <- m
|
||||
return
|
||||
}
|
||||
|
||||
meth := &rpcMethod[m.rpcNumber]
|
||||
if meth.fmt != m.fmt {
|
||||
switch {
|
||||
case len(m.fmt) < len(meth.fmt):
|
||||
m.status = ErrTooFewArgs
|
||||
case len(m.fmt) > len(meth.fmt):
|
||||
m.status = ErrTooManyArgs
|
||||
default:
|
||||
// There's a type mismatch.
|
||||
// It's an in-arg mismatch if the mismatch happens
|
||||
// before the colon; otherwise it's an out-arg mismatch.
|
||||
m.status = ErrInArgTypeMismatch
|
||||
for i := 0; i < len(m.fmt) && m.fmt[i] == meth.fmt[i]; i++ {
|
||||
if m.fmt[i] == ':' {
|
||||
m.status = ErrOutArgTypeMismatch
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
c <- m
|
||||
return
|
||||
}
|
||||
|
||||
m.status = meth.handler.Run(m.Arg, m.Ret, m.Size)
|
||||
c <- m
|
||||
}
|
||||
|
||||
// ServeRuntime serves RPCs issued by the Native Client embedded runtime.
|
||||
// This should be called by main once all methods have been registered using Add.
|
||||
func ServeRuntime() os.Error {
|
||||
// Call getFd to check that we are running embedded.
|
||||
if _, err := getFd(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We are running embedded.
|
||||
// The fd returned by getFd is a red herring.
|
||||
// Accept connections on magic fd 3.
|
||||
return Serve(3)
|
||||
}
|
||||
|
||||
// getFd runs the srpc_get_fd system call.
|
||||
func getFd() (fd int, err os.Error) {
|
||||
r1, _, e := syscall.Syscall(syscall.SYS_SRPC_GET_FD, 0, 0, 0)
|
||||
return int(r1), os.NewSyscallError("srpc_get_fd", int(e))
|
||||
}
|
||||
|
||||
// Enabled returns true if SRPC is enabled in the Native Client runtime.
|
||||
func Enabled() bool {
|
||||
_, err := getFd()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Service #0, service_discovery, returns a list of the other services
|
||||
// and their argument formats.
|
||||
type serviceDiscovery struct{}
|
||||
|
||||
func (serviceDiscovery) Run(arg, ret []interface{}, size []int) Errno {
|
||||
var b bytes.Buffer
|
||||
for _, m := range rpcMethod {
|
||||
b.WriteString(m.name)
|
||||
b.WriteByte(':')
|
||||
b.WriteString(m.fmt)
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
if b.Len() > size[0] {
|
||||
return ErrNoMemory
|
||||
}
|
||||
ret[0] = b.Bytes()
|
||||
return OK
|
||||
}
|
||||
|
||||
func init() { Add("service_discovery", ":C", serviceDiscovery{}) }
|
@ -1,18 +0,0 @@
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
all: 8.out
|
||||
|
||||
pdp1.8: pdp1.go
|
||||
8g pdp1.go
|
||||
|
||||
spacewar.8: spacewar.go code.go pdp1.8
|
||||
8g spacewar.go code.go
|
||||
|
||||
8.out: spacewar.8
|
||||
8l spacewar.8
|
||||
|
||||
clean:
|
||||
rm -f *.8 8.out
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,389 +0,0 @@
|
||||
// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
|
||||
// Portions Copyright (c) 2009 The Go Authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// This package and spacewar.go implement a simple PDP-1 emulator
|
||||
// complete enough to run the original PDP-1 video game Spacewar!
|
||||
// See ../../nacl/README for details on running them.
|
||||
//
|
||||
// They are a translation of the Java emulator pdp1.java in
|
||||
// http://spacewar.oversigma.com/sources/sources.zip.
|
||||
//
|
||||
// See also the PDP-1 handbook at http://www.dbit.com/~greeng3/pdp1/pdp1.html
|
||||
//
|
||||
// http://spacewar.oversigma.com/readme.html reads:
|
||||
//
|
||||
// Spacewar! was conceived in 1961 by Martin Graetz, Stephen Russell,
|
||||
// and Wayne Wiitanen. It was first realized on the PDP-1 in 1962 by
|
||||
// Stephen Russell, Peter Samson, Dan Edwards, and Martin Graetz,
|
||||
// together with Alan Kotok, Steve Piner, and Robert A Saunders.
|
||||
// Spacewar! is in the public domain, but this credit paragraph must
|
||||
// accompany all distributed versions of the program.
|
||||
//
|
||||
// This is the original version! Martin Graetz provided us with a
|
||||
// printed version of the source. We typed in in again - it was about
|
||||
// 40 pages long - and re-assembled it with a PDP-1 assembler written
|
||||
// in PERL. The resulting binary runs on a PDP-1 emulator written as
|
||||
// a Java applet. The code is extremely faithful to the original. There
|
||||
// are only two changes. 1)The spaceships have been made bigger and
|
||||
// 2) The overall timing has been special cased to deal with varying
|
||||
// machine speeds.
|
||||
//
|
||||
// The "a", "s", "d", "f" keys control one of the spaceships. The "k",
|
||||
// "l", ";", "'" keys control the other. The controls are spin one
|
||||
// way, spin the other, thrust, and fire.
|
||||
//
|
||||
// Barry Silverman
|
||||
// Brian Silverman
|
||||
// Vadim Gerasimov
|
||||
//
|
||||
package pdp1
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Word uint32
|
||||
|
||||
const mask = 0777777
|
||||
const sign = 0400000
|
||||
|
||||
const (
|
||||
_ = iota // 00
|
||||
opAND
|
||||
opIOR
|
||||
opXOR
|
||||
opXCT
|
||||
_
|
||||
_
|
||||
opCALJDA
|
||||
|
||||
opLAC // 10
|
||||
opLIO
|
||||
opDAC
|
||||
opDAP
|
||||
_
|
||||
opDIO
|
||||
opDZM
|
||||
_
|
||||
|
||||
opADD // 20
|
||||
opSUB
|
||||
opIDX
|
||||
opISP
|
||||
opSAD
|
||||
opSAS
|
||||
opMUS
|
||||
opDIS
|
||||
|
||||
opJMP // 30
|
||||
opJSP
|
||||
opSKP
|
||||
opSFT
|
||||
opLAW
|
||||
opIOT
|
||||
_
|
||||
opOPR
|
||||
)
|
||||
|
||||
// A Trapper represents an object with a Trap method.
|
||||
// The machine calls the Trap method to implement the
|
||||
// PDP-1 IOT instruction.
|
||||
type Trapper interface {
|
||||
Trap(y Word)
|
||||
}
|
||||
|
||||
// An M represents the machine state of a PDP-1.
|
||||
// Clients can set Display to install an output device.
|
||||
type M struct {
|
||||
AC, IO, PC, OV Word
|
||||
Mem [010000]Word
|
||||
Flag [7]bool
|
||||
Sense [7]bool
|
||||
Halt bool
|
||||
}
|
||||
|
||||
|
||||
// Step runs a single machine instruction.
|
||||
func (m *M) Step(t Trapper) os.Error {
|
||||
inst := m.Mem[m.PC]
|
||||
m.PC++
|
||||
return m.run(inst, t)
|
||||
}
|
||||
|
||||
// Normalize actual 32-bit integer i to 18-bit ones-complement integer.
|
||||
// Interpret mod 0777777, because 0777777 == -0 == +0 == 0000000.
|
||||
func norm(i Word) Word {
|
||||
i += i >> 18
|
||||
i &= mask
|
||||
if i == mask {
|
||||
i = 0
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
type UnknownInstrError struct {
|
||||
Inst Word
|
||||
PC Word
|
||||
}
|
||||
|
||||
func (e UnknownInstrError) String() string {
|
||||
return fmt.Sprintf("unknown instruction %06o at %06o", e.Inst, e.PC)
|
||||
}
|
||||
|
||||
type HaltError Word
|
||||
|
||||
func (e HaltError) String() string {
|
||||
return fmt.Sprintf("executed HLT instruction at %06o", e)
|
||||
}
|
||||
|
||||
type LoopError Word
|
||||
|
||||
func (e LoopError) String() string { return fmt.Sprintf("indirect load looping at %06o", e) }
|
||||
|
||||
func (m *M) run(inst Word, t Trapper) os.Error {
|
||||
ib, y := (inst>>12)&1, inst&07777
|
||||
op := inst >> 13
|
||||
if op < opSKP && op != opCALJDA {
|
||||
for n := 0; ib != 0; n++ {
|
||||
if n > 07777 {
|
||||
return LoopError(m.PC - 1)
|
||||
}
|
||||
ib = (m.Mem[y] >> 12) & 1
|
||||
y = m.Mem[y] & 07777
|
||||
}
|
||||
}
|
||||
|
||||
switch op {
|
||||
case opAND:
|
||||
m.AC &= m.Mem[y]
|
||||
case opIOR:
|
||||
m.AC |= m.Mem[y]
|
||||
case opXOR:
|
||||
m.AC ^= m.Mem[y]
|
||||
case opXCT:
|
||||
m.run(m.Mem[y], t)
|
||||
case opCALJDA:
|
||||
a := y
|
||||
if ib == 0 {
|
||||
a = 64
|
||||
}
|
||||
m.Mem[a] = m.AC
|
||||
m.AC = (m.OV << 17) + m.PC
|
||||
m.PC = a + 1
|
||||
case opLAC:
|
||||
m.AC = m.Mem[y]
|
||||
case opLIO:
|
||||
m.IO = m.Mem[y]
|
||||
case opDAC:
|
||||
m.Mem[y] = m.AC
|
||||
case opDAP:
|
||||
m.Mem[y] = m.Mem[y]&0770000 | m.AC&07777
|
||||
case opDIO:
|
||||
m.Mem[y] = m.IO
|
||||
case opDZM:
|
||||
m.Mem[y] = 0
|
||||
case opADD:
|
||||
m.AC += m.Mem[y]
|
||||
m.OV = m.AC >> 18
|
||||
m.AC = norm(m.AC)
|
||||
case opSUB:
|
||||
diffSigns := (m.AC^m.Mem[y])>>17 == 1
|
||||
m.AC += m.Mem[y] ^ mask
|
||||
m.AC = norm(m.AC)
|
||||
if diffSigns && m.Mem[y]>>17 == m.AC>>17 {
|
||||
m.OV = 1
|
||||
}
|
||||
case opIDX:
|
||||
m.AC = norm(m.Mem[y] + 1)
|
||||
m.Mem[y] = m.AC
|
||||
case opISP:
|
||||
m.AC = norm(m.Mem[y] + 1)
|
||||
m.Mem[y] = m.AC
|
||||
if m.AC&sign == 0 {
|
||||
m.PC++
|
||||
}
|
||||
case opSAD:
|
||||
if m.AC != m.Mem[y] {
|
||||
m.PC++
|
||||
}
|
||||
case opSAS:
|
||||
if m.AC == m.Mem[y] {
|
||||
m.PC++
|
||||
}
|
||||
case opMUS:
|
||||
if m.IO&1 == 1 {
|
||||
m.AC += m.Mem[y]
|
||||
m.AC = norm(m.AC)
|
||||
}
|
||||
m.IO = (m.IO>>1 | m.AC<<17) & mask
|
||||
m.AC >>= 1
|
||||
case opDIS:
|
||||
m.AC, m.IO = (m.AC<<1|m.IO>>17)&mask,
|
||||
((m.IO<<1|m.AC>>17)&mask)^1
|
||||
if m.IO&1 == 1 {
|
||||
m.AC = m.AC + (m.Mem[y] ^ mask)
|
||||
} else {
|
||||
m.AC = m.AC + 1 + m.Mem[y]
|
||||
}
|
||||
m.AC = norm(m.AC)
|
||||
case opJMP:
|
||||
m.PC = y
|
||||
case opJSP:
|
||||
m.AC = (m.OV << 17) + m.PC
|
||||
m.PC = y
|
||||
case opSKP:
|
||||
cond := y&0100 == 0100 && m.AC == 0 ||
|
||||
y&0200 == 0200 && m.AC>>17 == 0 ||
|
||||
y&0400 == 0400 && m.AC>>17 == 1 ||
|
||||
y&01000 == 01000 && m.OV == 0 ||
|
||||
y&02000 == 02000 && m.IO>>17 == 0 ||
|
||||
y&7 != 0 && !m.Flag[y&7] ||
|
||||
y&070 != 0 && !m.Sense[(y&070)>>3] ||
|
||||
y&070 == 010
|
||||
if (ib == 0) == cond {
|
||||
m.PC++
|
||||
}
|
||||
if y&01000 == 01000 {
|
||||
m.OV = 0
|
||||
}
|
||||
case opSFT:
|
||||
for count := inst & 0777; count != 0; count >>= 1 {
|
||||
if count&1 == 0 {
|
||||
continue
|
||||
}
|
||||
switch (inst >> 9) & 017 {
|
||||
case 001: // rotate AC left
|
||||
m.AC = (m.AC<<1 | m.AC>>17) & mask
|
||||
case 002: // rotate IO left
|
||||
m.IO = (m.IO<<1 | m.IO>>17) & mask
|
||||
case 003: // rotate AC and IO left.
|
||||
w := uint64(m.AC)<<18 | uint64(m.IO)
|
||||
w = w<<1 | w>>35
|
||||
m.AC = Word(w>>18) & mask
|
||||
m.IO = Word(w) & mask
|
||||
case 005: // shift AC left (excluding sign bit)
|
||||
m.AC = (m.AC<<1|m.AC>>17)&mask&^sign | m.AC&sign
|
||||
case 006: // shift IO left (excluding sign bit)
|
||||
m.IO = (m.IO<<1|m.IO>>17)&mask&^sign | m.IO&sign
|
||||
case 007: // shift AC and IO left (excluding AC's sign bit)
|
||||
w := uint64(m.AC)<<18 | uint64(m.IO)
|
||||
w = w<<1 | w>>35
|
||||
m.AC = Word(w>>18)&mask&^sign | m.AC&sign
|
||||
m.IO = Word(w)&mask&^sign | m.AC&sign
|
||||
case 011: // rotate AC right
|
||||
m.AC = (m.AC>>1 | m.AC<<17) & mask
|
||||
case 012: // rotate IO right
|
||||
m.IO = (m.IO>>1 | m.IO<<17) & mask
|
||||
case 013: // rotate AC and IO right
|
||||
w := uint64(m.AC)<<18 | uint64(m.IO)
|
||||
w = w>>1 | w<<35
|
||||
m.AC = Word(w>>18) & mask
|
||||
m.IO = Word(w) & mask
|
||||
case 015: // shift AC right (excluding sign bit)
|
||||
m.AC = m.AC>>1 | m.AC&sign
|
||||
case 016: // shift IO right (excluding sign bit)
|
||||
m.IO = m.IO>>1 | m.IO&sign
|
||||
case 017: // shift AC and IO right (excluding AC's sign bit)
|
||||
w := uint64(m.AC)<<18 | uint64(m.IO)
|
||||
w = w >> 1
|
||||
m.AC = Word(w>>18) | m.AC&sign
|
||||
m.IO = Word(w) & mask
|
||||
default:
|
||||
goto Unknown
|
||||
}
|
||||
}
|
||||
case opLAW:
|
||||
if ib == 0 {
|
||||
m.AC = y
|
||||
} else {
|
||||
m.AC = y ^ mask
|
||||
}
|
||||
case opIOT:
|
||||
t.Trap(y)
|
||||
case opOPR:
|
||||
if y&0200 == 0200 {
|
||||
m.AC = 0
|
||||
}
|
||||
if y&04000 == 04000 {
|
||||
m.IO = 0
|
||||
}
|
||||
if y&01000 == 01000 {
|
||||
m.AC ^= mask
|
||||
}
|
||||
if y&0400 == 0400 {
|
||||
m.PC--
|
||||
return HaltError(m.PC)
|
||||
}
|
||||
switch i, f := y&7, y&010 == 010; {
|
||||
case i == 7:
|
||||
for i := 2; i < 7; i++ {
|
||||
m.Flag[i] = f
|
||||
}
|
||||
case i >= 2:
|
||||
m.Flag[i] = f
|
||||
}
|
||||
default:
|
||||
Unknown:
|
||||
return UnknownInstrError{inst, m.PC - 1}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load loads the machine's memory from a text input file
|
||||
// listing octal address-value pairs, one per line, matching the
|
||||
// regular expression ^[ +]([0-7]+)\t([0-7]+).
|
||||
func (m *M) Load(r io.Reader) os.Error {
|
||||
b := bufio.NewReader(r)
|
||||
for {
|
||||
line, err := b.ReadString('\n')
|
||||
if err != nil {
|
||||
if err != os.EOF {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
// look for ^[ +]([0-9]+)\t([0-9]+)
|
||||
if line[0] != ' ' && line[0] != '+' {
|
||||
continue
|
||||
}
|
||||
i := 1
|
||||
a := Word(0)
|
||||
for ; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
|
||||
a = a*8 + Word(line[i]-'0')
|
||||
}
|
||||
if i >= len(line) || line[i] != '\t' || i == 1 {
|
||||
continue
|
||||
}
|
||||
v := Word(0)
|
||||
j := i
|
||||
for i++; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
|
||||
v = v*8 + Word(line[i]-'0')
|
||||
}
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
m.Mem[a] = v
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
|
||||
// Portions Copyright (c) 2009 The Go Authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// See ../../nacl/README.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"exp/draw"
|
||||
"exp/nacl/av"
|
||||
"exp/nacl/srpc"
|
||||
"image"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
"./pdp1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
if srpc.Enabled() {
|
||||
go srpc.ServeRuntime()
|
||||
}
|
||||
|
||||
w, err := av.Init(av.SubsystemVideo, 512, 512)
|
||||
if err != nil {
|
||||
log.Exitf("av.Init: %s", err)
|
||||
}
|
||||
|
||||
kc := make(chan int)
|
||||
go demuxEvents(w, kc)
|
||||
|
||||
var m SpacewarPDP1
|
||||
m.Init(w, kc)
|
||||
m.PC = 4
|
||||
f := bytes.NewBuffer([]byte(spacewarCode))
|
||||
if err = m.Load(f); err != nil {
|
||||
log.Exitf("loading %s: %s", "spacewar.lst", err)
|
||||
}
|
||||
for err == nil {
|
||||
//fmt.Printf("step PC=%06o ", m.PC);
|
||||
//fmt.Printf("inst=%06o AC=%06o IO=%06o OV=%o\n",
|
||||
// m.Mem[m.PC], m.AC, m.IO, m.OV);
|
||||
err = m.Step()
|
||||
}
|
||||
log.Exitf("step: %s", err)
|
||||
}
|
||||
|
||||
func demuxEvents(w draw.Window, kc chan int) {
|
||||
for event := range w.EventChan() {
|
||||
switch e := event.(type) {
|
||||
case draw.KeyEvent:
|
||||
kc <- e.Key
|
||||
}
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// A SpacewarPDP1 is a PDP-1 machine configured to run Spacewar!
|
||||
// It responds to traps by drawing on the display, and it flushes the
|
||||
// display and pauses every second time the program counter reaches
|
||||
// instruction 02051.
|
||||
type SpacewarPDP1 struct {
|
||||
pdp1.M
|
||||
nframe int
|
||||
frameTime int64
|
||||
ctxt draw.Window
|
||||
dx, dy int
|
||||
screen draw.Image
|
||||
ctl pdp1.Word
|
||||
kc <-chan int
|
||||
colorModel image.ColorModel
|
||||
cmap []image.Color
|
||||
pix [][]uint8
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (m *SpacewarPDP1) Init(ctxt draw.Window, kc chan int) {
|
||||
m.ctxt = ctxt
|
||||
m.kc = kc
|
||||
m.screen = ctxt.Screen()
|
||||
m.dx = m.screen.Bounds().Dx()
|
||||
m.dy = m.screen.Bounds().Dy()
|
||||
m.colorModel = m.screen.ColorModel()
|
||||
m.pix = make([][]uint8, m.dy)
|
||||
for i := range m.pix {
|
||||
m.pix[i] = make([]uint8, m.dx)
|
||||
}
|
||||
m.cmap = make([]image.Color, 256)
|
||||
for i := range m.cmap {
|
||||
var r, g, b uint8
|
||||
r = uint8(min(0, 255))
|
||||
g = uint8(min(i*2, 255))
|
||||
b = uint8(min(0, 255))
|
||||
m.cmap[i] = m.colorModel.Convert(image.RGBAColor{r, g, b, 0xff})
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
frameDelay = 56 * 1e6 // 56 ms
|
||||
)
|
||||
|
||||
var ctlBits = [...]pdp1.Word{
|
||||
'f': 0000001,
|
||||
'd': 0000002,
|
||||
'a': 0000004,
|
||||
's': 0000010,
|
||||
'\'': 0040000,
|
||||
';': 0100000,
|
||||
'k': 0200000,
|
||||
'l': 0400000,
|
||||
}
|
||||
|
||||
func (m *SpacewarPDP1) Step() os.Error {
|
||||
if m.PC == 02051 {
|
||||
m.pollInput()
|
||||
m.nframe++
|
||||
if m.nframe&1 == 0 {
|
||||
m.flush()
|
||||
t := time.Nanoseconds()
|
||||
if t >= m.frameTime+3*frameDelay {
|
||||
m.frameTime = t
|
||||
} else {
|
||||
m.frameTime += frameDelay
|
||||
for t < m.frameTime {
|
||||
time.Sleep(m.frameTime - t)
|
||||
t = time.Nanoseconds()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m.M.Step(m)
|
||||
}
|
||||
|
||||
func (m *SpacewarPDP1) Trap(y pdp1.Word) {
|
||||
switch y & 077 {
|
||||
case 7:
|
||||
x := int(m.AC+0400000) & 0777777
|
||||
y := int(m.IO+0400000) & 0777777
|
||||
x = x * m.dx / 0777777
|
||||
y = y * m.dy / 0777777
|
||||
if 0 <= x && x < m.dx && 0 <= y && y < m.dy {
|
||||
n := uint8(min(int(m.pix[y][x])+128, 255))
|
||||
m.pix[y][x] = n
|
||||
}
|
||||
case 011:
|
||||
m.IO = m.ctl
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SpacewarPDP1) flush() {
|
||||
// Update screen image; simulate phosphor decay.
|
||||
for y := 0; y < m.dy; y++ {
|
||||
for x := 0; x < m.dx; x++ {
|
||||
m.screen.Set(x, y, m.cmap[m.pix[y][x]])
|
||||
m.pix[y][x] >>= 1
|
||||
}
|
||||
}
|
||||
m.ctxt.FlushImage()
|
||||
}
|
||||
|
||||
func (m *SpacewarPDP1) pollInput() {
|
||||
for {
|
||||
select {
|
||||
case ch := <-m.kc:
|
||||
if 0 <= ch && ch < len(ctlBits) {
|
||||
m.ctl |= ctlBits[ch]
|
||||
}
|
||||
if 0 <= -ch && -ch < len(ctlBits) {
|
||||
m.ctl &^= ctlBits[-ch]
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
|
||||
<h1>Spacewar</h1>
|
||||
<table>
|
||||
<tr><td valign=top>
|
||||
<embed name="nacl_module" id="pluginobj" src="8.out" type="application/x-nacl-srpc" width=512 height=512>
|
||||
<td valign=top>
|
||||
This is a Go translation of the Java emulator pdp1.java in
|
||||
<a href="http://spacewar.oversigma.com/sources/sources.zip">http://spacewar.oversigma.com/sources/sources.zip</a>.
|
||||
See <a href="pdp1.go">pdp1.go</a>, <a href="spacewar.go">spacewar.go</a>,
|
||||
and
|
||||
<a href="http://spacewar.oversigma.com/readme.html">http://spacewar.oversigma.com/readme.html</a>.
|
||||
<br><br>
|
||||
The <i>a</i>, <i>s</i>, <i>d</i>, <i>f</i> keys control one of the spaceships. The <i>k</i>,
|
||||
<i>l</i>, <i>;</i>, <i>'</i> keys control the other. The controls are spin one
|
||||
way, spin the other, thrust, and fire.
|
||||
<br>
|
||||
<br>
|
||||
<b>You may need to click on the game window to
|
||||
focus the keyboard on it.</b>
|
||||
|
||||
</table>
|
@ -41,13 +41,6 @@ GOFILES_linux=\
|
||||
dnsconfig.go\
|
||||
dnsclient.go\
|
||||
port.go\
|
||||
|
||||
GOFILES_nacl=\
|
||||
newpollserver.go\
|
||||
fd.go\
|
||||
dnsconfig.go\
|
||||
dnsclient.go\
|
||||
port.go\
|
||||
|
||||
GOFILES_windows=\
|
||||
resolv_windows.go\
|
||||
|
@ -1,33 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type pollster struct{}
|
||||
|
||||
func newpollster() (p *pollster, err os.Error) {
|
||||
return nil, os.NewSyscallError("networking", syscall.ENACL)
|
||||
}
|
||||
|
||||
func (p *pollster) AddFD(fd int, mode int, repeat bool) os.Error {
|
||||
_, err := newpollster()
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *pollster) StopWaiting(fd int, bits uint) {
|
||||
}
|
||||
|
||||
func (p *pollster) DelFD(fd int, mode int) {}
|
||||
|
||||
func (p *pollster) WaitFD(nsec int64) (fd int, mode int, err os.Error) {
|
||||
_, err = newpollster()
|
||||
return
|
||||
}
|
||||
|
||||
func (p *pollster) Close() os.Error { return nil }
|
@ -33,11 +33,6 @@ GOFILES_linux=\
|
||||
file_unix.go\
|
||||
sys_linux.go\
|
||||
|
||||
GOFILES_nacl=\
|
||||
env_unix.go\
|
||||
file_unix.go\
|
||||
sys_nacl.go\
|
||||
|
||||
GOFILES_windows=\
|
||||
env_windows.go\
|
||||
file_windows.go\
|
||||
|
@ -1,69 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
blockSize = 4096 // TODO(r): use statfs
|
||||
)
|
||||
|
||||
func clen(n []byte) int {
|
||||
for i := 0; i < len(n); i++ {
|
||||
if n[i] == 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return len(n)
|
||||
}
|
||||
|
||||
func (file *File) Readdirnames(count int) (names []string, err Error) {
|
||||
// If this file has no dirinfo, create one.
|
||||
if file.dirinfo == nil {
|
||||
file.dirinfo = new(dirInfo)
|
||||
// The buffer must be at least a block long.
|
||||
// TODO(r): use fstatfs to find fs block size.
|
||||
file.dirinfo.buf = make([]byte, blockSize)
|
||||
}
|
||||
d := file.dirinfo
|
||||
size := count
|
||||
if size < 0 {
|
||||
size = 100
|
||||
}
|
||||
names = make([]string, 0, size) // Empty with room to grow.
|
||||
for count != 0 {
|
||||
// Refill the buffer if necessary
|
||||
if d.bufp >= d.nbuf {
|
||||
var errno int
|
||||
d.nbuf, errno = syscall.Getdents(file.fd, d.buf)
|
||||
if errno != 0 {
|
||||
return names, NewSyscallError("getdents", errno)
|
||||
}
|
||||
if d.nbuf <= 0 {
|
||||
break // EOF
|
||||
}
|
||||
d.bufp = 0
|
||||
}
|
||||
// Drain the buffer
|
||||
for count != 0 && d.bufp < d.nbuf {
|
||||
dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp]))
|
||||
d.bufp += int(dirent.Reclen)
|
||||
if dirent.Ino == 0 { // File absent in directory.
|
||||
continue
|
||||
}
|
||||
bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
|
||||
var name = string(bytes[0:clen(bytes[0:])])
|
||||
if name == "." || name == ".." { // Useless names
|
||||
continue
|
||||
}
|
||||
count--
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
return names, nil
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package os
|
||||
|
||||
import "syscall"
|
||||
|
||||
func isSymlink(stat *syscall.Stat_t) bool {
|
||||
return stat.Mode&syscall.S_IFMT == syscall.S_IFLNK
|
||||
}
|
||||
|
||||
func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *FileInfo {
|
||||
fi.Dev = uint64(stat.Dev)
|
||||
fi.Ino = uint64(stat.Ino)
|
||||
fi.Nlink = uint64(stat.Nlink)
|
||||
fi.Mode = stat.Mode
|
||||
fi.Uid = int(stat.Uid)
|
||||
fi.Gid = int(stat.Gid)
|
||||
fi.Rdev = uint64(stat.Rdev)
|
||||
fi.Size = int64(stat.Size)
|
||||
fi.Blksize = int64(stat.Blksize)
|
||||
fi.Blocks = int64(stat.Blocks)
|
||||
fi.Atime_ns = int64(stat.Atime) * 1e9
|
||||
fi.Mtime_ns = int64(stat.Mtime) * 1e9
|
||||
fi.Ctime_ns = int64(stat.Ctime) * 1e9
|
||||
for i := len(name) - 1; i >= 0; i-- {
|
||||
if name[i] == '/' {
|
||||
name = name[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
fi.Name = name
|
||||
if isSymlink(lstat) && !isSymlink(stat) {
|
||||
fi.FollowedSymlink = true
|
||||
}
|
||||
return fi
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package os
|
||||
|
||||
func Hostname() (name string, err Error) { return "nacl", nil }
|
@ -18,9 +18,6 @@ GOFILES_darwin=\
|
||||
GOFILES_linux=\
|
||||
path_unix.go
|
||||
|
||||
GOFILES_nacl=\
|
||||
path_unix.go
|
||||
|
||||
GOFILES_windows=\
|
||||
path_windows.go
|
||||
|
||||
|
@ -15,9 +15,6 @@ runtime·closure(int32 siz, byte *fn, byte *arg0)
|
||||
int32 i, n;
|
||||
int32 pcrel;
|
||||
|
||||
if(runtime·goos != nil && runtime·strcmp((uint8*)runtime·goos, (uint8*)"nacl") == 0)
|
||||
runtime·throw("no closures in native client yet");
|
||||
|
||||
if(siz < 0 || siz%4 != 0)
|
||||
runtime·throw("bad closure size");
|
||||
|
||||
|
@ -165,9 +165,3 @@ ifeq ($(GOARCH),386)
|
||||
traceback.$O: amd64/traceback.c
|
||||
$(CC) $(CFLAGS) $<
|
||||
endif
|
||||
|
||||
# NaCl closure is special.
|
||||
ifeq ($(GOOS),nacl)
|
||||
closure.$O: nacl/$(GOARCH)/closure.c
|
||||
$(CC) $(CFLAGS) $<
|
||||
endif
|
||||
|
@ -327,10 +327,6 @@ struct MHeap
|
||||
byte *min;
|
||||
byte *max;
|
||||
|
||||
// range of addresses we might see in a Native Client closure
|
||||
byte *closure_min;
|
||||
byte *closure_max;
|
||||
|
||||
// central free lists for small size classes.
|
||||
// the union makes sure that the MCentrals are
|
||||
// spaced 64 bytes apart, so that each MCentral.Lock
|
||||
|
@ -76,22 +76,6 @@ scanblock(byte *b, int64 n)
|
||||
obj = vp[i];
|
||||
if(obj == nil)
|
||||
continue;
|
||||
if(runtime·mheap.closure_min != nil && runtime·mheap.closure_min <= (byte*)obj && (byte*)obj < runtime·mheap.closure_max) {
|
||||
if((((uintptr)obj) & 63) != 0)
|
||||
continue;
|
||||
|
||||
// Looks like a Native Client closure.
|
||||
// Actual pointer is pointed at by address in first instruction.
|
||||
// Embedded pointer starts at byte 2.
|
||||
// If it is f4f4f4f4 then that space hasn't been
|
||||
// used for a closure yet (f4 is the HLT instruction).
|
||||
// See nacl/386/closure.c for more.
|
||||
void **pp;
|
||||
pp = *(void***)((byte*)obj+2);
|
||||
if(pp == (void**)0xf4f4f4f4) // HLT... - not a closure after all
|
||||
continue;
|
||||
obj = *pp;
|
||||
}
|
||||
if(runtime·mheap.min <= (byte*)obj && (byte*)obj < runtime·mheap.max) {
|
||||
if(runtime·mlookup(obj, &obj, &size, nil, &refp)) {
|
||||
ref = *refp;
|
||||
|
@ -165,7 +165,7 @@ MHeap_Grow(MHeap *h, uintptr npage)
|
||||
// Ask for a big chunk, to reduce the number of mappings
|
||||
// the operating system needs to track; also amortizes
|
||||
// the overhead of an operating system mapping.
|
||||
// For Native Client, allocate a multiple of 64kB (16 pages).
|
||||
// Allocate a multiple of 64kB (16 pages).
|
||||
npage = (npage+15)&~15;
|
||||
ask = npage<<PageShift;
|
||||
if(ask < HeapAllocChunk)
|
||||
|
@ -1,249 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
* Closure implementation for Native Client.
|
||||
* Native Client imposes some interesting restrictions.
|
||||
*
|
||||
* First, we can only add new code to the code segment
|
||||
* through a special system call, and we have to pick the
|
||||
* maximum amount of code we're going to add that way
|
||||
* at link time (8l reserves 512 kB for us).
|
||||
*
|
||||
* Second, once we've added the code we can't ever
|
||||
* change it or delete it. If we want to garbage collect
|
||||
* the memory and then reuse it for another closure,
|
||||
* we have to do so without editing the code.
|
||||
*
|
||||
* To address both of these, we fill the code segment pieces
|
||||
* with very stylized closures. Each has the form given below
|
||||
* in the comments on the closasm array, with ** replaced by
|
||||
* a pointer to a single word of memory. The garbage collector
|
||||
* treats a pointer to such a closure as equivalent to the value
|
||||
* held in **. This tiled run of closures is called the closure array.
|
||||
*
|
||||
* The ptr points at a ClosureData structure, defined below,
|
||||
* which gives the function, arguments, and size for the
|
||||
* closuretramp function. The ClosureData structure has
|
||||
* in it a pointer to a ClosureFreeList structure holding the index
|
||||
* of the closure in the closure array (but not a pointer to it).
|
||||
* That structure has a finalizer: when the garbage collector
|
||||
* notices that the ClosureFreeList structure is not referenced
|
||||
* anymore, that means the closure is not referenced, so it
|
||||
* can be reused. To do that, the ClosureFreeList entry is put
|
||||
* onto an actual free list.
|
||||
*/
|
||||
#include "runtime.h"
|
||||
#include "malloc.h"
|
||||
|
||||
// NaCl system call to copy data into text segment.
|
||||
extern int32 runtime·dyncode_copy(void*, void*, int32);
|
||||
|
||||
enum{
|
||||
// Allocate chunks of 4096 bytes worth of closures:
|
||||
// at 64 bytes each, that's 64 closures.
|
||||
ClosureChunk = 4096,
|
||||
ClosureSize = 64,
|
||||
};
|
||||
|
||||
typedef struct ClosureFreeList ClosureFreeList;
|
||||
struct ClosureFreeList
|
||||
{
|
||||
ClosureFreeList *next;
|
||||
int32 index; // into closure array
|
||||
};
|
||||
|
||||
// Known to closasm
|
||||
typedef struct ClosureData ClosureData;
|
||||
struct ClosureData
|
||||
{
|
||||
ClosureFreeList *free;
|
||||
byte *fn;
|
||||
int32 siz;
|
||||
// then args
|
||||
};
|
||||
|
||||
// List of the closure data pointer blocks we've allocated
|
||||
// and hard-coded in the closure text segments.
|
||||
// The list keeps the pointer blocks from getting collected.
|
||||
typedef struct ClosureDataList ClosureDataList;
|
||||
struct ClosureDataList
|
||||
{
|
||||
ClosureData **block;
|
||||
ClosureDataList *next;
|
||||
};
|
||||
|
||||
static struct {
|
||||
Lock;
|
||||
byte *code;
|
||||
byte *ecode;
|
||||
ClosureFreeList *free;
|
||||
ClosureDataList *datalist;
|
||||
byte buf[ClosureChunk];
|
||||
} clos;
|
||||
|
||||
static byte closasm[64] = {
|
||||
0x8b, 0x1d, 0, 0, 0, 0, // MOVL **, BX
|
||||
0x8b, 0x4b, 8, // MOVL 8(BX), CX
|
||||
0x8d, 0x73, 12, // LEAL 12(BX), SI
|
||||
0x29, 0xcc, // SUBL CX, SP
|
||||
0x89, 0xe7, // MOVL SP, DI
|
||||
0xc1, 0xe9, 2, // SHRL $2, CX
|
||||
0xf3, 0xa5, // REP MOVSL
|
||||
0x8b, 0x5b, 4, // MOVL 4(BX), BX
|
||||
0x90, 0x90, 0x90, // NOP...
|
||||
0x83, 0xe3, ~31, // ANDL $~31, BX
|
||||
0xff, 0xd3, // CALL *BX
|
||||
// --- 32-byte boundary
|
||||
0x8b, 0x1d, 0, 0, 0, 0, // MOVL **, BX
|
||||
0x03, 0x63, 8, // ADDL 8(BX), SP
|
||||
0x5b, // POPL BX
|
||||
0x83, 0xe3, ~31, // ANDL $~31, BX
|
||||
0xff, 0xe3, // JMP *BX
|
||||
0xf4, // HLT...
|
||||
0xf4, 0xf4, 0xf4, 0xf4,
|
||||
0xf4, 0xf4, 0xf4, 0xf4,
|
||||
0xf4, 0xf4, 0xf4, 0xf4,
|
||||
0xf4, 0xf4, 0xf4, 0xf4,
|
||||
// --- 32-byte boundary
|
||||
};
|
||||
|
||||
// Returns immediate pointer from closure code block.
|
||||
// Triple pointer:
|
||||
// p is the instruction stream
|
||||
// p+2 is the location of the immediate value
|
||||
// *(p+2) is the immediate value, a word in the pointer block
|
||||
// permanently associated with this closure.
|
||||
// **(p+2) is the ClosureData* pointer temporarily associated
|
||||
// with this closure.
|
||||
//
|
||||
#define codeptr(p) *(ClosureData***)((byte*)(p)+2)
|
||||
|
||||
void
|
||||
runtime·finclosure(void *v)
|
||||
{
|
||||
byte *p;
|
||||
ClosureFreeList *f;
|
||||
|
||||
f = v;
|
||||
p = clos.code + f->index*ClosureSize;
|
||||
*codeptr(p) = nil;
|
||||
|
||||
runtime·lock(&clos);
|
||||
f->next = clos.free;
|
||||
clos.free = f;
|
||||
runtime·unlock(&clos);
|
||||
}
|
||||
|
||||
#pragma textflag 7
|
||||
// func closure(siz int32,
|
||||
// fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
|
||||
// arg0, arg1, arg2 *ptr) (func(xxx) yyy)
|
||||
void
|
||||
runtime·closure(int32 siz, byte *fn, byte *arg0)
|
||||
{
|
||||
byte *p, **ret;
|
||||
int32 e, i, n, off;
|
||||
extern byte rodata[], etext[];
|
||||
ClosureData *d, **block;
|
||||
ClosureDataList *l;
|
||||
ClosureFreeList *f;
|
||||
|
||||
if(siz < 0 || siz%4 != 0)
|
||||
runtime·throw("bad closure size");
|
||||
|
||||
ret = (byte**)((byte*)&arg0 + siz);
|
||||
|
||||
if(siz > 100) {
|
||||
// TODO(rsc): implement stack growth preamble?
|
||||
runtime·throw("closure too big");
|
||||
}
|
||||
|
||||
runtime·lock(&clos);
|
||||
if(clos.free == nil) {
|
||||
// Allocate more closures.
|
||||
if(clos.code == nil) {
|
||||
// First time: find closure space, between end of text
|
||||
// segment and beginning of data.
|
||||
clos.code = (byte*)(((uintptr)etext + 65535) & ~65535);
|
||||
clos.ecode = clos.code;
|
||||
runtime·mheap.closure_min = clos.code;
|
||||
runtime·mheap.closure_max = rodata;
|
||||
}
|
||||
if(clos.ecode+ClosureChunk > rodata) {
|
||||
// Last ditch effort: garbage collect and hope.
|
||||
runtime·unlock(&clos);
|
||||
runtime·gc(1);
|
||||
runtime·lock(&clos);
|
||||
if(clos.free != nil)
|
||||
goto alloc;
|
||||
runtime·throw("ran out of room for closures in text segment");
|
||||
}
|
||||
|
||||
n = ClosureChunk/ClosureSize;
|
||||
|
||||
// Allocate the pointer block as opaque to the
|
||||
// garbage collector. Finalizers will clean up.
|
||||
block = runtime·mallocgc(n*sizeof block[0], RefNoPointers, 1, 1);
|
||||
|
||||
// Pointers into the pointer block are getting added
|
||||
// to the text segment; keep a pointer here in the data
|
||||
// segment so that the garbage collector doesn't free
|
||||
// the block itself.
|
||||
l = runtime·mal(sizeof *l);
|
||||
l->block = block;
|
||||
l->next = clos.datalist;
|
||||
clos.datalist = l;
|
||||
|
||||
p = clos.buf;
|
||||
off = (clos.ecode - clos.code)/ClosureSize;
|
||||
for(i=0; i<n; i++) {
|
||||
f = runtime·mal(sizeof *f);
|
||||
f->index = off++;
|
||||
f->next = clos.free;
|
||||
clos.free = f;
|
||||
|
||||
// There are two hard-coded immediate values in
|
||||
// the assembly that need to be pp+i, one 2 bytes in
|
||||
// and one 2 bytes after the 32-byte boundary.
|
||||
runtime·mcpy(p, closasm, ClosureSize);
|
||||
*(ClosureData***)(p+2) = block+i;
|
||||
*(ClosureData***)(p+32+2) = block+i;
|
||||
p += ClosureSize;
|
||||
}
|
||||
|
||||
if(p != clos.buf+sizeof clos.buf)
|
||||
runtime·throw("bad buf math in closure");
|
||||
|
||||
e = runtime·dyncode_copy(clos.ecode, clos.buf, ClosureChunk);
|
||||
if(e != 0) {
|
||||
runtime·fd = 2;
|
||||
if(e == -22)
|
||||
runtime·throw("NaCl running with dyncode_copy disabled; export NACLDYNCODE=1 in your environment");
|
||||
runtime·printf("dyncode_copy: error %d\n", e);
|
||||
runtime·throw("dyncode_copy");
|
||||
}
|
||||
clos.ecode += ClosureChunk;
|
||||
}
|
||||
|
||||
alloc:
|
||||
// Grab a free closure and save the data pointer in its indirect pointer.
|
||||
f = clos.free;
|
||||
clos.free = f->next;
|
||||
f->next = nil;
|
||||
p = clos.code + f->index*ClosureSize;
|
||||
|
||||
d = runtime·mal(sizeof(*d)+siz);
|
||||
d->free = f;
|
||||
d->fn = fn;
|
||||
d->siz = siz;
|
||||
runtime·mcpy((byte*)(d+1), (byte*)&arg0, siz);
|
||||
*codeptr(p) = d;
|
||||
runtime·addfinalizer(f, runtime·finclosure, 0);
|
||||
runtime·unlock(&clos);
|
||||
|
||||
*ret = p;
|
||||
}
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
// godefs -f-m32 -f-I/home/rsc/pub/nacl/native_client/src/third_party/nacl_sdk/linux/sdk/nacl-sdk/nacl/include -f-I/home/rsc/pub/nacl/native_client defs.c
|
||||
|
||||
// MACHINE GENERATED - DO NOT EDIT.
|
||||
|
||||
// Constants
|
||||
enum {
|
||||
PROT_NONE = 0,
|
||||
PROT_READ = 0x1,
|
||||
PROT_WRITE = 0x2,
|
||||
PROT_EXEC = 0x4,
|
||||
MAP_ANON = 0x20,
|
||||
MAP_PRIVATE = 0x2,
|
||||
};
|
||||
|
||||
// Types
|
||||
#pragma pack on
|
||||
#pragma pack off
|
@ -1,8 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Native Client and Linux use the same linkage to main
|
||||
|
||||
TEXT _rt0_386_nacl(SB),7,$0
|
||||
JMP _rt0_386(SB)
|
@ -1,14 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "runtime.h"
|
||||
#include "defs.h"
|
||||
#include "signals.h"
|
||||
#include "os.h"
|
||||
|
||||
void
|
||||
runtime·initsig(int32 queue)
|
||||
{
|
||||
}
|
||||
|
@ -1,142 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//
|
||||
// System calls and other sys.stuff for 386, Linux
|
||||
//
|
||||
|
||||
#include "386/asm.h"
|
||||
|
||||
// http://code.google.com/p/nativeclient/source/browse/trunk/src/native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h
|
||||
#define SYS_exit 30
|
||||
#define SYS_mmap 21
|
||||
#define SYS_munmap 22
|
||||
#define SYS_thread_create 80
|
||||
#define SYS_thread_exit 81
|
||||
#define SYS_tls_init 82
|
||||
#define SYS_write 13
|
||||
#define SYS_close 11
|
||||
#define SYS_mutex_create 70
|
||||
#define SYS_mutex_lock 71
|
||||
#define SYS_mutex_unlock 73
|
||||
#define SYS_gettimeofday 40
|
||||
#define SYS_dyncode_copy 104
|
||||
|
||||
|
||||
#define SYSCALL(x) $(0x10000+SYS_/**/x * 32)
|
||||
|
||||
TEXT runtime·exit(SB),7,$4
|
||||
MOVL code+0(FP), AX
|
||||
MOVL AX, 0(SP)
|
||||
CALL SYSCALL(exit)
|
||||
INT $3 // not reached
|
||||
RET
|
||||
|
||||
TEXT runtime·exit1(SB),7,$4
|
||||
MOVL code+0(FP), AX
|
||||
MOVL AX, 0(SP)
|
||||
CALL SYSCALL(thread_exit)
|
||||
INT $3 // not reached
|
||||
RET
|
||||
|
||||
TEXT runtime·write(SB),7,$0
|
||||
JMP SYSCALL(write)
|
||||
|
||||
TEXT runtime·close(SB),7,$0
|
||||
JMP SYSCALL(close)
|
||||
|
||||
TEXT runtime·mutex_create(SB),7,$0
|
||||
JMP SYSCALL(mutex_create)
|
||||
|
||||
TEXT runtime·mutex_lock(SB),7,$0
|
||||
JMP SYSCALL(mutex_lock)
|
||||
|
||||
TEXT runtime·mutex_unlock(SB),7,$0
|
||||
JMP SYSCALL(mutex_unlock)
|
||||
|
||||
TEXT runtime·thread_create(SB),7,$0
|
||||
JMP SYSCALL(thread_create)
|
||||
|
||||
TEXT runtime·dyncode_copy(SB),7,$0
|
||||
JMP SYSCALL(dyncode_copy)
|
||||
|
||||
// For Native Client: a simple no-op function.
|
||||
// Inserting a call to this no-op is a simple way
|
||||
// to trigger an alignment.
|
||||
TEXT runtime·naclnop(SB),7,$0
|
||||
RET
|
||||
|
||||
TEXT runtime·mmap(SB),7,$24
|
||||
MOVL a1+0(FP), BX
|
||||
MOVL a2+4(FP), CX // round up to 64 kB boundary; silences nacl warning
|
||||
ADDL $(64*1024-1), CX
|
||||
ANDL $~(64*1024-1), CX
|
||||
MOVL a3+8(FP), DX
|
||||
MOVL a4+12(FP), SI
|
||||
MOVL a5+16(FP), DI
|
||||
MOVL a6+20(FP), BP
|
||||
MOVL BX, 0(SP)
|
||||
MOVL CX, 4(SP)
|
||||
MOVL DX, 8(SP)
|
||||
MOVL SI, 12(SP)
|
||||
MOVL DI, 16(SP)
|
||||
MOVL BP, 20(SP)
|
||||
CALL SYSCALL(mmap)
|
||||
CMPL AX, $0xfffff001
|
||||
JLS 6(PC)
|
||||
MOVL $1, 0(SP)
|
||||
MOVL $runtime·mmap_failed(SB), 4(SP)
|
||||
MOVL $12, 8(SP) // "mmap failed\n"
|
||||
CALL SYSCALL(write)
|
||||
INT $3
|
||||
RET
|
||||
|
||||
TEXT runtime·munmap(SB),7,$0
|
||||
JMP SYSCALL(munmap)
|
||||
|
||||
TEXT runtime·gettime(SB),7,$32
|
||||
LEAL 8(SP), BX
|
||||
MOVL BX, 0(SP)
|
||||
MOVL $0, 4(SP)
|
||||
CALL SYSCALL(gettimeofday)
|
||||
|
||||
MOVL 8(SP), BX // sec
|
||||
MOVL sec+0(FP), DI
|
||||
MOVL BX, (DI)
|
||||
MOVL $0, 4(DI) // zero extend 32 -> 64 bits
|
||||
|
||||
MOVL 12(SP), BX // usec
|
||||
MOVL usec+4(FP), DI
|
||||
MOVL BX, (DI)
|
||||
RET
|
||||
|
||||
// setldt(int entry, int address, int limit)
|
||||
TEXT runtime·setldt(SB),7,$32
|
||||
// entry is ignored - nacl tells us the
|
||||
// segment selector to use and stores it in GS.
|
||||
MOVL address+4(FP), BX
|
||||
MOVL limit+8(FP), CX
|
||||
MOVL BX, 0(SP)
|
||||
MOVL CX, 4(SP)
|
||||
CALL SYSCALL(tls_init)
|
||||
CMPL AX, $0xfffff001
|
||||
JLS 6(PC)
|
||||
MOVL $1, 0(SP)
|
||||
MOVL $runtime·tls_init_failed(SB), 4(SP)
|
||||
MOVL $16, 8(SP) // "tls_init failed\n"
|
||||
CALL SYSCALL(write)
|
||||
INT $3
|
||||
RET
|
||||
|
||||
// There's no good way (yet?) to get stack traces out of a
|
||||
// broken NaCl process, so if something goes wrong,
|
||||
// print an error string before dying.
|
||||
|
||||
DATA runtime·mmap_failed(SB)/8, $"mmap fai"
|
||||
DATA mmap_failed+8(SB)/4, $"led\n"
|
||||
GLOBL runtime·mmap_failed(SB), $12
|
||||
|
||||
DATA runtime·tls_init_failed(SB)/8, $"tls_init"
|
||||
DATA tls_init_failed+8(SB)/8, $" failed\n"
|
||||
GLOBL runtime·tls_init_failed(SB), $16
|
@ -1,27 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Input to godefs.
|
||||
|
||||
godefs -f-m32 -f-I/home/rsc/pub/nacl/native_client/src/third_party/nacl_sdk/linux/sdk/nacl-sdk/nacl/include -f-I/home/rsc/pub/nacl/native_client defs.c >386/defs.h
|
||||
*/
|
||||
|
||||
#define __native_client__ 1
|
||||
|
||||
#define suseconds_t nacl_suseconds_t_1
|
||||
#include <sys/types.h>
|
||||
#undef suseconds_t
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
enum {
|
||||
$PROT_NONE = PROT_NONE,
|
||||
$PROT_READ = PROT_READ,
|
||||
$PROT_WRITE = PROT_WRITE,
|
||||
$PROT_EXEC = PROT_EXEC,
|
||||
|
||||
$MAP_ANON = MAP_ANONYMOUS,
|
||||
$MAP_PRIVATE = MAP_PRIVATE,
|
||||
};
|
@ -1,37 +0,0 @@
|
||||
#include "runtime.h"
|
||||
#include "defs.h"
|
||||
#include "os.h"
|
||||
#include "malloc.h"
|
||||
|
||||
enum {
|
||||
NaclPage = 0x10000
|
||||
};
|
||||
|
||||
void*
|
||||
runtime·SysAlloc(uintptr n)
|
||||
{
|
||||
mstats.sys += n;
|
||||
return runtime·mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·SysUnused(void *v, uintptr n)
|
||||
{
|
||||
USED(v);
|
||||
USED(n);
|
||||
// TODO(rsc): call madvise MADV_DONTNEED
|
||||
}
|
||||
|
||||
void
|
||||
runtime·SysFree(void *v, uintptr n)
|
||||
{
|
||||
// round to page size or else nacl prints annoying log messages
|
||||
mstats.sys -= n;
|
||||
n = (n+NaclPage-1) & ~(NaclPage-1);
|
||||
runtime·munmap(v, n);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·SysMemInit(void)
|
||||
{
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
int32 runtime·thread_create(void(*fn)(void), void *stk, void *tls, int32 tlssize);
|
||||
void runtime·close(int32);
|
||||
int32 runtime·mutex_create(void);
|
||||
int32 runtime·mutex_lock(int32);
|
||||
int32 runtime·mutex_unlock(int32);
|
@ -1,14 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// OS-Specific Go definitions of internal structures. Master is runtime.h
|
||||
|
||||
package runtime
|
||||
|
||||
type lock struct {
|
||||
key uint32
|
||||
sema uint32
|
||||
}
|
||||
|
||||
type note lock
|
@ -1,164 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "runtime.h"
|
||||
#include "defs.h"
|
||||
#include "os.h"
|
||||
|
||||
int8 *goos = "nacl";
|
||||
|
||||
// Thread-safe allocation of a mutex.
|
||||
// (The name sema is left over from the Darwin implementation.
|
||||
// Native Client implements semaphores too, but it is just a shim
|
||||
// over the host implementation, which on some hosts imposes a very
|
||||
// low limit on how many semaphores can be created.)
|
||||
//
|
||||
// Psema points at a mutex descriptor.
|
||||
// It starts out zero, meaning no mutex.
|
||||
// Fill it in, being careful of others calling initsema
|
||||
// simultaneously.
|
||||
static void
|
||||
initsema(uint32 *psema)
|
||||
{
|
||||
uint32 sema;
|
||||
|
||||
if(*psema != 0) // already have one
|
||||
return;
|
||||
|
||||
sema = runtime·mutex_create();
|
||||
if((int32)sema < 0) {
|
||||
runtime·printf("mutex_create failed\n");
|
||||
runtime·breakpoint();
|
||||
}
|
||||
// mutex_create returns a file descriptor;
|
||||
// shift it up and add the 1 bit so that can
|
||||
// distinguish unintialized from fd 0.
|
||||
sema = (sema<<1) | 1;
|
||||
if(!cas(psema, 0, sema)){
|
||||
// Someone else filled it in. Use theirs.
|
||||
runtime·close(sema);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Lock and unlock.
|
||||
// Defer entirely to Native Client.
|
||||
// The expense of a call into Native Client is more like
|
||||
// a function call than a system call, so as long as the
|
||||
// Native Client lock implementation is good, we can't
|
||||
// do better ourselves.
|
||||
|
||||
static void
|
||||
xlock(int32 fd)
|
||||
{
|
||||
if(mutex_lock(fd) < 0) {
|
||||
runtime·printf("mutex_lock failed\n");
|
||||
runtime·breakpoint();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xunlock(int32 fd)
|
||||
{
|
||||
if(mutex_unlock(fd) < 0) {
|
||||
runtime·printf("mutex_lock failed\n");
|
||||
runtime·breakpoint();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
runtime·lock(Lock *l)
|
||||
{
|
||||
if(m->locks < 0)
|
||||
runtime·throw("lock count");
|
||||
m->locks++;
|
||||
if(l->sema == 0)
|
||||
runtime·initsema(&l->sema);
|
||||
runtime·xlock(l->sema>>1);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·unlock(Lock *l)
|
||||
{
|
||||
m->locks--;
|
||||
if(m->locks < 0)
|
||||
runtime·throw("lock count");
|
||||
runtime·xunlock(l->sema>>1);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·destroylock(Lock*)
|
||||
{
|
||||
}
|
||||
|
||||
// One-time notifications.
|
||||
//
|
||||
// Since the lock/unlock implementation already
|
||||
// takes care of sleeping in the kernel, we just reuse it.
|
||||
// (But it's a weird use, so it gets its own interface.)
|
||||
//
|
||||
// We use a lock to represent the event:
|
||||
// unlocked == event has happened.
|
||||
// Thus the lock starts out locked, and to wait for the
|
||||
// event you try to lock the lock. To signal the event,
|
||||
// you unlock the lock.
|
||||
//
|
||||
// Native Client does not require that the thread acquiring
|
||||
// a lock be the thread that releases the lock, so this is safe.
|
||||
|
||||
void
|
||||
runtime·noteclear(Note *n)
|
||||
{
|
||||
if(n->lock.sema == 0)
|
||||
runtime·initsema(&n->lock.sema);
|
||||
runtime·xlock(n->lock.sema>>1);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·notewakeup(Note *n)
|
||||
{
|
||||
if(n->lock.sema == 0) {
|
||||
runtime·printf("notewakeup without noteclear");
|
||||
runtime·breakpoint();
|
||||
}
|
||||
runtime·xunlock(n->lock.sema>>1);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·notesleep(Note *n)
|
||||
{
|
||||
if(n->lock.sema == 0) {
|
||||
runtime·printf("notesleep without noteclear");
|
||||
runtime·breakpoint();
|
||||
}
|
||||
runtime·xlock(n->lock.sema>>1);
|
||||
runtime·xunlock(n->lock.sema>>1); // Let other sleepers find out too.
|
||||
}
|
||||
|
||||
void
|
||||
runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
|
||||
{
|
||||
void **vstk;
|
||||
|
||||
// I wish every OS made thread creation this easy.
|
||||
m->tls[0] = (uint32)g;
|
||||
m->tls[1] = (uint32)m;
|
||||
vstk = stk;
|
||||
*--vstk = nil;
|
||||
if(thread_create(fn, vstk, m->tls, sizeof m->tls) < 0) {
|
||||
runtime·printf("thread_create failed\n");
|
||||
runtime·breakpoint();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
runtime·osinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
// Called to initialize a new m (including the bootstrap m).
|
||||
void
|
||||
runtime·minit(void)
|
||||
{
|
||||
}
|
@ -30,10 +30,6 @@ GOFILES_linux=\
|
||||
syscall_unix.go\
|
||||
exec_unix.go\
|
||||
|
||||
GOFILES_nacl=\
|
||||
syscall_unix.go\
|
||||
exec_unix.go\
|
||||
|
||||
GOFILES_windows=\
|
||||
exec_windows.go
|
||||
|
||||
|
@ -1,119 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//
|
||||
// System calls for 386, Native Client
|
||||
//
|
||||
|
||||
#define SYSCALL(x) $(0x10000+x * 32)
|
||||
|
||||
// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr);
|
||||
// Trap # in AX, args in BX CX DX SI DI, return in AX
|
||||
|
||||
TEXT ·Syscall(SB),7,$20
|
||||
CALL runtime·entersyscall(SB)
|
||||
MOVL trap+0(FP), AX // syscall entry
|
||||
MOVL a1+4(FP), BX
|
||||
MOVL a2+8(FP), CX
|
||||
MOVL a3+12(FP), DX
|
||||
MOVL $0, SI
|
||||
MOVL $0, DI
|
||||
|
||||
MOVL BX, 0(SP)
|
||||
MOVL CX, 4(SP)
|
||||
MOVL DX, 8(SP)
|
||||
MOVL SI, 12(SP)
|
||||
MOVL DI, 16(SP)
|
||||
|
||||
// Call $(0x10000+32*AX)
|
||||
SHLL $5, AX
|
||||
ADDL $0x10000, AX
|
||||
CALL AX
|
||||
|
||||
CMPL AX, $0xfffff001
|
||||
JLS ok
|
||||
MOVL $-1, r1+16(FP)
|
||||
MOVL $0, r2+20(FP)
|
||||
NEGL AX
|
||||
MOVL AX, errno+24(FP)
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
ok:
|
||||
MOVL AX, r1+16(FP)
|
||||
MOVL DX, r2+20(FP)
|
||||
MOVL $0, errno+24(FP)
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
// func Syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
|
||||
TEXT ·Syscall6(SB),7,$24
|
||||
CALL runtime·entersyscall(SB)
|
||||
MOVL a1+4(FP), BX
|
||||
MOVL a2+8(FP), CX
|
||||
MOVL a3+12(FP), DX
|
||||
MOVL a4+16(FP), SI
|
||||
MOVL a5+20(FP), DI
|
||||
MOVL a6+24(FP), AX
|
||||
|
||||
MOVL BX, 0(SP)
|
||||
MOVL CX, 4(SP)
|
||||
MOVL DX, 8(SP)
|
||||
MOVL SI, 12(SP)
|
||||
MOVL DI, 16(SP)
|
||||
MOVL AX, 20(SP)
|
||||
|
||||
// Call $(0x10000+32*trap)
|
||||
MOVL trap+0(FP), AX // syscall entry
|
||||
SHLL $5, AX
|
||||
ADDL $0x10000, AX
|
||||
CALL AX
|
||||
|
||||
CMPL AX, $0xfffff001
|
||||
JLS ok6
|
||||
MOVL $-1, r1+28(FP)
|
||||
MOVL $0, r2+32(FP)
|
||||
NEGL AX
|
||||
MOVL AX, errno+36(FP)
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
ok6:
|
||||
MOVL AX, r1+28(FP)
|
||||
MOVL DX, r2+32(FP)
|
||||
MOVL $0, errno+36(FP)
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr);
|
||||
TEXT ·RawSyscall(SB),7,$20
|
||||
MOVL trap+0(FP), AX // syscall entry
|
||||
MOVL a1+4(FP), BX
|
||||
MOVL a2+8(FP), CX
|
||||
MOVL a3+12(FP), DX
|
||||
MOVL $0, SI
|
||||
MOVL $0, DI
|
||||
|
||||
MOVL BX, 0(SP)
|
||||
MOVL CX, 4(SP)
|
||||
MOVL DX, 8(SP)
|
||||
MOVL SI, 12(SP)
|
||||
MOVL DI, 16(SP)
|
||||
|
||||
// Call $(0x10000+32*AX)
|
||||
SHLL $5, AX
|
||||
ADDL $0x10000, AX
|
||||
CALL AX
|
||||
|
||||
CMPL AX, $0xfffff001
|
||||
JLS ok1
|
||||
MOVL $-1, r1+16(FP)
|
||||
MOVL $0, r2+20(FP)
|
||||
NEGL AX
|
||||
MOVL AX, errno+24(FP)
|
||||
RET
|
||||
ok1:
|
||||
MOVL AX, r1+16(FP)
|
||||
MOVL DX, r2+20(FP)
|
||||
MOVL $0, errno+24(FP)
|
||||
RET
|
||||
|
@ -1,41 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# Generate Go code listing error values (ENAMETOOLONG etc)
|
||||
# for Native Client.
|
||||
|
||||
echo '// mkerrors_nacl.sh' "$@"
|
||||
echo '// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT'
|
||||
echo
|
||||
echo 'package syscall'
|
||||
echo
|
||||
echo 'const ('
|
||||
perl -n -e '
|
||||
if(/#define\s+NACL_ABI_(\S*)\s+([0-9]+)/) {
|
||||
print "\t$1 = $2;\n"
|
||||
}
|
||||
' $1
|
||||
echo ' ENACL = 99; /* otherwise unused */'
|
||||
echo ')'
|
||||
echo
|
||||
echo
|
||||
echo '// Error table'
|
||||
echo 'var errors = [...]string {'
|
||||
perl -n -e '
|
||||
if(/#define\s+NACL_ABI_(\S*)\s+([0-9]+)\s+\/\* (.*) \*\//) {
|
||||
$err = $1;
|
||||
$text = $3;
|
||||
if($text =~ /^[A-Z][a-z]/) {
|
||||
# lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||
$l = substr($text, 0, 1);
|
||||
$rest = substr($text, 1);
|
||||
$l =~ y/A-Z/a-z/;
|
||||
$text = $l . $rest;
|
||||
}
|
||||
print "\t$err: \"$text\",\n";
|
||||
}
|
||||
' $1
|
||||
echo ' ENACL: "not supported by native client",'
|
||||
echo '}'
|
@ -1,29 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
# Copyright 2009 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
my $command = "mksysnum_nacl.sh ". join(' ', @ARGV);
|
||||
|
||||
print <<EOF;
|
||||
// $command
|
||||
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||
|
||||
package syscall
|
||||
|
||||
const(
|
||||
EOF
|
||||
|
||||
while(<>){
|
||||
if(/^#define NACL_sys_(\w+)\s+([0-9]+)/){
|
||||
my $name = "SYS_$1";
|
||||
my $num = $2;
|
||||
$name =~ y/a-z/A-Z/;
|
||||
print " $name = $num;\n";
|
||||
}
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
)
|
||||
|
||||
EOF
|
@ -1,357 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Native Client system calls.
|
||||
|
||||
package syscall
|
||||
|
||||
const OS = "nacl"
|
||||
|
||||
var _zero [1]byte // pointer used for zero-length writes
|
||||
|
||||
// Auto-generated
|
||||
|
||||
//sys Chmod(path string, mode uint32) (errno int)
|
||||
//sys Clock() (clock int)
|
||||
//sys Close(fd int) (errno int)
|
||||
//sys Exit(code int)
|
||||
//sys Fstat(fd int, stat *Stat_t) (errno int)
|
||||
//sys Getdents(fd int, buf []byte) (n int, errno int)
|
||||
//sys Getpid() (pid int)
|
||||
//sys Gettimeofday(tv *Timeval) (errno int)
|
||||
//sys Open(path string, mode int, perm uint32) (fd int, errno int)
|
||||
//sys Read(fd int, p []byte) (n int, errno int)
|
||||
//sys read(fd int, buf *byte, nbuf int) (n int, errno int)
|
||||
//sys Stat(path string, stat *Stat_t) (errno int)
|
||||
//sys Write(fd int, p []byte) (n int, errno int)
|
||||
|
||||
//sys MultimediaInit(subsys int) (errno int)
|
||||
//sys MultimediaShutdown() (errno int)
|
||||
|
||||
//sys CondCreate() (cv int, errno int)
|
||||
//sys CondWait(cv int, mutex int) (errno int)
|
||||
//sys CondSignal(cv int) (errno int)
|
||||
//sys CondBroadcast(cv int) (errno int)
|
||||
//sys CondTimedWaitAbs(cv int, mutex int, abstime *Timespec) (errno int)
|
||||
//sys MutexCreate() (mutex int, errno int)
|
||||
//sys MutexLock(mutex int) (errno int)
|
||||
//sys MutexUnlock(mutex int) (errno int)
|
||||
//sys MutexTryLock(mutex int) (errno int) = SYS_MUTEX_TRYLOCK
|
||||
//sys SemCreate() (sema int, errno int)
|
||||
//sys SemWait(sema int) (errno int)
|
||||
//sys SemPost(sema int) (errno int)
|
||||
//sys VideoInit(dx int, dy int) (errno int)
|
||||
//sys VideoUpdate(data *uint32) (errno int)
|
||||
//sys VideoPollEvent(ev *byte) (errno int)
|
||||
//sys VideoShutdown() (errno int)
|
||||
//sys AudioInit(fmt int, nreq int, data *int) (errno int)
|
||||
//sys AudioShutdown() (errno int)
|
||||
//sys AudioStream(data *uint16, size *uintptr) (errno int)
|
||||
|
||||
// Hand-written
|
||||
|
||||
func Seek(fd int, offset int64, whence int) (newoffset int64, errno int) {
|
||||
// Offset passed to system call is 32 bits. Failure of vision by NaCl.
|
||||
if int64(int32(offset)) != offset {
|
||||
return 0, ERANGE
|
||||
}
|
||||
o, _, e := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
|
||||
return int64(o), int(e)
|
||||
}
|
||||
|
||||
// Sleep by waiting on a condition variable that will never be signaled.
|
||||
// TODO(rsc): Replace when NaCl adds a proper sleep system call.
|
||||
var tcv, tmu int
|
||||
|
||||
func init() {
|
||||
tmu, _ = MutexCreate()
|
||||
tcv, _ = CondCreate()
|
||||
}
|
||||
|
||||
func Sleep(ns int64) (errno int) {
|
||||
ts := NsecToTimespec(ns)
|
||||
var tv Timeval
|
||||
if errno = Gettimeofday(&tv); errno != 0 {
|
||||
return
|
||||
}
|
||||
ts.Sec += tv.Sec
|
||||
ts.Nsec += tv.Usec * 1000
|
||||
switch {
|
||||
case ts.Nsec >= 1e9:
|
||||
ts.Nsec -= 1e9
|
||||
ts.Sec++
|
||||
case ts.Nsec <= -1e9:
|
||||
ts.Nsec += 1e9
|
||||
ts.Sec--
|
||||
}
|
||||
if errno = MutexLock(tmu); errno != 0 {
|
||||
return
|
||||
}
|
||||
errno = CondTimedWaitAbs(tcv, tmu, &ts)
|
||||
if e := MutexUnlock(tmu); e != 0 && errno == 0 {
|
||||
errno = e
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Implemented in NaCl but not here; maybe later:
|
||||
// SYS_IOCTL
|
||||
// SYS_IMC_*
|
||||
// SYS_MMAP ???
|
||||
// SYS_SRPC_*
|
||||
// SYS_SYSCONF
|
||||
|
||||
// Implemented in NaCl but not here; used by runtime instead:
|
||||
// SYS_SYSBRK
|
||||
// SYS_MMAP
|
||||
// SYS_MUNMAP
|
||||
// SYS_THREAD_*
|
||||
// SYS_TLS_*
|
||||
// SYS_SCHED_YIELD
|
||||
|
||||
// #define'd in NaCl but not picked up by mkerrors_nacl.sh.
|
||||
|
||||
const EWOULDBLOCK = EAGAIN
|
||||
|
||||
// Not implemented in NaCl but needed to compile other packages.
|
||||
|
||||
const (
|
||||
SIGTRAP = 5
|
||||
)
|
||||
|
||||
func Pipe(p []int) (errno int) { return ENACL }
|
||||
|
||||
func fcntl(fd, cmd, arg int) (val int, errno int) {
|
||||
return 0, ENACL
|
||||
}
|
||||
|
||||
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
|
||||
return 0, ENACL
|
||||
}
|
||||
|
||||
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
|
||||
return 0, ENACL
|
||||
}
|
||||
|
||||
func Mkdir(path string, mode uint32) (errno int) { return ENACL }
|
||||
|
||||
func Lstat(path string, stat *Stat_t) (errno int) {
|
||||
return Stat(path, stat)
|
||||
}
|
||||
|
||||
func Chdir(path string) (errno int) { return ENACL }
|
||||
|
||||
func Fchdir(fd int) (errno int) { return ENACL }
|
||||
|
||||
func Unlink(path string) (errno int) { return ENACL }
|
||||
|
||||
func Rmdir(path string) (errno int) { return ENACL }
|
||||
|
||||
func Link(oldpath, newpath string) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Symlink(path, link string) (errno int) { return ENACL }
|
||||
|
||||
func Readlink(path string, buf []byte) (n int, errno int) {
|
||||
return 0, ENACL
|
||||
}
|
||||
|
||||
func Rename(oldpath, newpath string) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Fchmod(fd int, mode uint32) (errno int) { return ENACL }
|
||||
|
||||
func Chown(path string, uid int, gid int) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Lchown(path string, uid int, gid int) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Fchown(fd int, uid int, gid int) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Utimes(path string, tv []Timeval) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Futimes(fd int, tv []Timeval) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Truncate(name string, size int64) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Ftruncate(fd int, length int64) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
// NaCL doesn't actually implement Getwd, but it also
|
||||
// don't implement Chdir, so the fallback algorithm
|
||||
// fails worse than calling Getwd does.
|
||||
|
||||
const ImplementsGetwd = true
|
||||
|
||||
func Getwd() (wd string, errno int) { return "", ENACL }
|
||||
|
||||
func Getuid() (uid int) { return -1 }
|
||||
|
||||
func Geteuid() (euid int) { return -1 }
|
||||
|
||||
func Getgid() (gid int) { return -1 }
|
||||
|
||||
func Getegid() (egid int) { return -1 }
|
||||
|
||||
func Getppid() (ppid int) { return -1 }
|
||||
|
||||
func Getgroups() (gids []int, errno int) { return nil, ENACL }
|
||||
|
||||
type Sockaddr interface {
|
||||
sockaddr()
|
||||
}
|
||||
|
||||
type SockaddrInet4 struct {
|
||||
Port int
|
||||
Addr [4]byte
|
||||
}
|
||||
|
||||
func (*SockaddrInet4) sockaddr() {}
|
||||
|
||||
type SockaddrInet6 struct {
|
||||
Port int
|
||||
Addr [16]byte
|
||||
}
|
||||
|
||||
func (*SockaddrInet6) sockaddr() {}
|
||||
|
||||
type SockaddrUnix struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (*SockaddrUnix) sockaddr() {}
|
||||
|
||||
const (
|
||||
AF_INET = 1 + iota
|
||||
AF_INET6
|
||||
AF_UNIX
|
||||
IPPROTO_TCP
|
||||
SOCK_DGRAM
|
||||
SOCK_STREAM
|
||||
SOCK_RAW
|
||||
SOL_SOCKET
|
||||
SOMAXCONN
|
||||
SO_DONTROUTE
|
||||
SO_KEEPALIVE
|
||||
SO_LINGER
|
||||
SO_RCVBUF
|
||||
SO_REUSEADDR
|
||||
SO_SNDBUF
|
||||
IPPROTO_IPV6
|
||||
IPV6_V6ONLY
|
||||
TCP_NODELAY
|
||||
WNOHANG
|
||||
WSTOPPED
|
||||
PTRACE_TRACEME
|
||||
SO_BROADCAST = 0
|
||||
SHUT_RDWR = 0
|
||||
)
|
||||
|
||||
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
|
||||
return 0, nil, ENACL
|
||||
}
|
||||
|
||||
func Getsockname(fd int) (sa Sockaddr, errno int) {
|
||||
return nil, ENACL
|
||||
}
|
||||
|
||||
func Getpeername(fd int) (sa Sockaddr, errno int) {
|
||||
return nil, ENACL
|
||||
}
|
||||
|
||||
func Bind(fd int, sa Sockaddr) (errno int) { return ENACL }
|
||||
|
||||
func BindToDevice(fd int, device string) (errno int) { return ENACL }
|
||||
|
||||
func Connect(fd int, sa Sockaddr) (errno int) { return ENACL }
|
||||
|
||||
func Socket(domain, typ, proto int) (fd, errno int) {
|
||||
return 0, ENACL
|
||||
}
|
||||
|
||||
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Shutdown(fd, how int) (errno int) { return ENACL }
|
||||
|
||||
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
|
||||
return 0, nil, ENACL
|
||||
}
|
||||
|
||||
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
type Linger struct {
|
||||
Onoff int32
|
||||
Linger int32
|
||||
}
|
||||
|
||||
func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
|
||||
return ENACL
|
||||
}
|
||||
|
||||
func Listen(s int, n int) (errno int) { return ENACL }
|
||||
|
||||
type Rusage struct {
|
||||
Utime Timeval
|
||||
Stime Timeval
|
||||
Maxrss int32
|
||||
Ixrss int32
|
||||
Idrss int32
|
||||
Isrss int32
|
||||
Minflt int32
|
||||
Majflt int32
|
||||
Nswap int32
|
||||
Inblock int32
|
||||
Oublock int32
|
||||
Msgsnd int32
|
||||
Msgrcv int32
|
||||
Nsignals int32
|
||||
Nvcsw int32
|
||||
Nivcsw int32
|
||||
}
|
||||
|
||||
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||
return 0, ENACL
|
||||
}
|
||||
|
||||
type WaitStatus uint32
|
||||
|
||||
func (WaitStatus) Exited() bool { return false }
|
||||
|
||||
func (WaitStatus) ExitStatus() int { return -1 }
|
||||
|
||||
func (WaitStatus) Signal() int { return -1 }
|
||||
|
||||
func (WaitStatus) CoreDump() bool { return false }
|
||||
|
||||
func (WaitStatus) Stopped() bool { return false }
|
||||
|
||||
func (WaitStatus) Continued() bool { return false }
|
||||
|
||||
func (WaitStatus) StopSignal() int { return -1 }
|
||||
|
||||
func (WaitStatus) Signaled() bool { return false }
|
||||
|
||||
func (WaitStatus) TrapCause() int { return -1 }
|
@ -1,19 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package syscall
|
||||
|
||||
func Getpagesize() int { return 4096 }
|
||||
|
||||
func NsecToTimeval(nsec int64) (tv Timeval) {
|
||||
tv.Sec = int32(nsec / 1e9)
|
||||
tv.Usec = int32(nsec % 1e9 / 1e3)
|
||||
return
|
||||
}
|
||||
|
||||
func NsecToTimespec(nsec int64) (ts Timespec) {
|
||||
ts.Sec = int32(nsec / 1e9)
|
||||
ts.Nsec = int32(nsec % 1e9)
|
||||
return
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Input to godefs. See also mkerrors.sh and mkall.sh
|
||||
*/
|
||||
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#define __native_client__ 1
|
||||
|
||||
#define suseconds_t nacl_suseconds_t_1
|
||||
#include <sys/types.h>
|
||||
#undef suseconds_t
|
||||
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// Machine characteristics; for internal use.
|
||||
|
||||
enum
|
||||
{
|
||||
$sizeofPtr = sizeof(void*),
|
||||
$sizeofShort = sizeof(short),
|
||||
$sizeofInt = sizeof(int),
|
||||
$sizeofLong = sizeof(long),
|
||||
$sizeofLongLong = sizeof(long long),
|
||||
};
|
||||
|
||||
// Mmap constants
|
||||
enum {
|
||||
$PROT_READ = PROT_READ,
|
||||
$PROT_WRITE = PROT_WRITE,
|
||||
$MAP_SHARED = MAP_SHARED,
|
||||
};
|
||||
|
||||
// Unimplemented system calls
|
||||
enum {
|
||||
$SYS_FORK = 0,
|
||||
$SYS_PTRACE = 0,
|
||||
$SYS_CHDIR = 0,
|
||||
$SYS_DUP2 = 0,
|
||||
$SYS_FCNTL = 0,
|
||||
$SYS_EXECVE = 0,
|
||||
};
|
||||
|
||||
// Basic types
|
||||
|
||||
typedef short $_C_short;
|
||||
typedef int $_C_int;
|
||||
typedef long $_C_long;
|
||||
typedef long long $_C_long_long;
|
||||
typedef off_t $_C_off_t;
|
||||
|
||||
// Time
|
||||
|
||||
typedef struct timespec $Timespec;
|
||||
typedef struct timeval $Timeval;
|
||||
typedef time_t $Time_t;
|
||||
|
||||
// Processes
|
||||
|
||||
//typedef struct rusage $Rusage;
|
||||
//typedef struct rlimit $Rlimit;
|
||||
|
||||
typedef gid_t $_Gid_t;
|
||||
|
||||
// Files
|
||||
|
||||
enum
|
||||
{
|
||||
$O_RDONLY = O_RDONLY,
|
||||
$O_WRONLY = O_WRONLY,
|
||||
$O_RDWR = O_RDWR,
|
||||
$O_APPEND = O_APPEND,
|
||||
$O_ASYNC = O_ASYNC,
|
||||
$O_CREAT = O_CREAT,
|
||||
$O_NOCTTY = 0, // not supported
|
||||
$O_NONBLOCK = O_NONBLOCK,
|
||||
$O_SYNC = O_SYNC,
|
||||
$O_TRUNC = O_TRUNC,
|
||||
$O_EXCL = O_EXCL,
|
||||
$O_CLOEXEC = 0, // not supported
|
||||
|
||||
$F_GETFD = F_GETFD,
|
||||
$F_SETFD = F_SETFD,
|
||||
|
||||
$F_GETFL = F_GETFL,
|
||||
$F_SETFL = F_SETFL,
|
||||
|
||||
$FD_CLOEXEC = 0, // not supported
|
||||
};
|
||||
|
||||
enum
|
||||
{ // Directory mode bits
|
||||
$S_IFMT = S_IFMT,
|
||||
$S_IFIFO = S_IFIFO,
|
||||
$S_IFCHR = S_IFCHR,
|
||||
$S_IFDIR = S_IFDIR,
|
||||
$S_IFBLK = S_IFBLK,
|
||||
$S_IFREG = S_IFREG,
|
||||
$S_IFLNK = S_IFLNK,
|
||||
$S_IFSOCK = S_IFSOCK,
|
||||
$S_ISUID = S_ISUID,
|
||||
$S_ISGID = S_ISGID,
|
||||
$S_ISVTX = S_ISVTX,
|
||||
$S_IRUSR = S_IRUSR,
|
||||
$S_IWUSR = S_IWUSR,
|
||||
$S_IXUSR = S_IXUSR,
|
||||
};
|
||||
|
||||
typedef struct stat $Stat_t;
|
||||
|
||||
typedef struct dirent $Dirent;
|
@ -1,246 +0,0 @@
|
||||
// mkerrors_nacl.sh /home/rsc/pub/nacl/native_client/src/trusted/service_runtime/include/sys/errno.h
|
||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
package syscall
|
||||
|
||||
const (
|
||||
EPERM = 1
|
||||
ENOENT = 2
|
||||
ESRCH = 3
|
||||
EINTR = 4
|
||||
EIO = 5
|
||||
ENXIO = 6
|
||||
E2BIG = 7
|
||||
ENOEXEC = 8
|
||||
EBADF = 9
|
||||
ECHILD = 10
|
||||
EAGAIN = 11
|
||||
ENOMEM = 12
|
||||
EACCES = 13
|
||||
EFAULT = 14
|
||||
EBUSY = 16
|
||||
EEXIST = 17
|
||||
EXDEV = 18
|
||||
ENODEV = 19
|
||||
ENOTDIR = 20
|
||||
EISDIR = 21
|
||||
EINVAL = 22
|
||||
ENFILE = 23
|
||||
EMFILE = 24
|
||||
ENOTTY = 25
|
||||
EFBIG = 27
|
||||
ENOSPC = 28
|
||||
ESPIPE = 29
|
||||
EROFS = 30
|
||||
EMLINK = 31
|
||||
EPIPE = 32
|
||||
ENAMETOOLONG = 36
|
||||
ENOSYS = 38
|
||||
EDQUOT = 122
|
||||
EDOM = 33
|
||||
ERANGE = 34
|
||||
ENOMSG = 35
|
||||
ECHRNG = 37
|
||||
EL3HLT = 39
|
||||
EL3RST = 40
|
||||
ELNRNG = 41
|
||||
EUNATCH = 42
|
||||
ENOCSI = 43
|
||||
EL2HLT = 44
|
||||
EDEADLK = 45
|
||||
ENOLCK = 46
|
||||
EBADE = 50
|
||||
EBADR = 51
|
||||
EXFULL = 52
|
||||
ENOANO = 53
|
||||
EBADRQC = 54
|
||||
EBADSLT = 55
|
||||
EBFONT = 57
|
||||
ENOSTR = 60
|
||||
ENODATA = 61
|
||||
ETIME = 62
|
||||
ENOSR = 63
|
||||
ENONET = 64
|
||||
ENOPKG = 65
|
||||
EREMOTE = 66
|
||||
ENOLINK = 67
|
||||
EADV = 68
|
||||
ESRMNT = 69
|
||||
ECOMM = 70
|
||||
EPROTO = 71
|
||||
EMULTIHOP = 74
|
||||
ELBIN = 75
|
||||
EDOTDOT = 76
|
||||
EBADMSG = 77
|
||||
EFTYPE = 79
|
||||
ENOTUNIQ = 80
|
||||
EBADFD = 81
|
||||
EREMCHG = 82
|
||||
ELIBACC = 83
|
||||
ELIBBAD = 84
|
||||
ELIBSCN = 85
|
||||
ELIBMAX = 86
|
||||
ELIBEXEC = 87
|
||||
ENMFILE = 89
|
||||
ENOTEMPTY = 90
|
||||
ELOOP = 92
|
||||
EOPNOTSUPP = 95
|
||||
EPFNOSUPPORT = 96
|
||||
ECONNRESET = 104
|
||||
ENOBUFS = 105
|
||||
EAFNOSUPPORT = 106
|
||||
EPROTOTYPE = 107
|
||||
ENOTSOCK = 108
|
||||
ENOPROTOOPT = 109
|
||||
ESHUTDOWN = 110
|
||||
ECONNREFUSED = 111
|
||||
EADDRINUSE = 112
|
||||
ECONNABORTED = 113
|
||||
ENETUNREACH = 114
|
||||
ENETDOWN = 115
|
||||
ETIMEDOUT = 116
|
||||
EHOSTDOWN = 117
|
||||
EHOSTUNREACH = 118
|
||||
EINPROGRESS = 119
|
||||
EALREADY = 120
|
||||
EDESTADDRREQ = 121
|
||||
EPROTONOSUPPORT = 123
|
||||
ESOCKTNOSUPPORT = 124
|
||||
EADDRNOTAVAIL = 125
|
||||
ENETRESET = 126
|
||||
EISCONN = 127
|
||||
ENOTCONN = 128
|
||||
ETOOMANYREFS = 129
|
||||
EPROCLIM = 130
|
||||
EUSERS = 131
|
||||
ESTALE = 133
|
||||
ENOMEDIUM = 135
|
||||
ENOSHARE = 136
|
||||
ECASECLASH = 137
|
||||
EILSEQ = 138
|
||||
EOVERFLOW = 139
|
||||
ECANCELED = 140
|
||||
EL2NSYNC = 88
|
||||
EIDRM = 91
|
||||
EMSGSIZE = 132
|
||||
ENACL = 99 /* otherwise unused */
|
||||
)
|
||||
|
||||
|
||||
// Error table
|
||||
var errors = [...]string{
|
||||
EPERM: "operation not permitted",
|
||||
ENOENT: "no such file or directory",
|
||||
ESRCH: "no such process",
|
||||
EINTR: "interrupted system call",
|
||||
EIO: "I/O error",
|
||||
ENXIO: "no such device or address",
|
||||
E2BIG: "argument list too long",
|
||||
ENOEXEC: "exec format error",
|
||||
EBADF: "bad file number",
|
||||
ECHILD: "no child processes",
|
||||
EAGAIN: "try again",
|
||||
ENOMEM: "out of memory",
|
||||
EACCES: "permission denied",
|
||||
EFAULT: "bad address",
|
||||
EBUSY: "device or resource busy",
|
||||
EEXIST: "file exists",
|
||||
EXDEV: "cross-device link",
|
||||
ENODEV: "no such device",
|
||||
ENOTDIR: "not a directory",
|
||||
EISDIR: "is a directory",
|
||||
EINVAL: "invalid argument",
|
||||
ENFILE: "file table overflow",
|
||||
EMFILE: "too many open files",
|
||||
ENOTTY: "not a typewriter",
|
||||
EFBIG: "file too large",
|
||||
ENOSPC: "no space left on device",
|
||||
ESPIPE: "illegal seek",
|
||||
EROFS: "read-only file system",
|
||||
EMLINK: "too many links",
|
||||
EPIPE: "broken pipe",
|
||||
ENAMETOOLONG: "file name too long",
|
||||
ENOSYS: "function not implemented",
|
||||
EDQUOT: "quota exceeded",
|
||||
EDOM: "math arg out of domain of func",
|
||||
ERANGE: "math result not representable",
|
||||
ENOMSG: "no message of desired type",
|
||||
ECHRNG: "channel number out of range",
|
||||
EL3HLT: "level 3 halted",
|
||||
EL3RST: "level 3 reset",
|
||||
ELNRNG: "link number out of range",
|
||||
EUNATCH: "protocol driver not attached",
|
||||
ENOCSI: "no CSI structure available",
|
||||
EL2HLT: "level 2 halted",
|
||||
EDEADLK: "deadlock condition",
|
||||
ENOLCK: "no record locks available",
|
||||
EBADE: "invalid exchange",
|
||||
EBADR: "invalid request descriptor",
|
||||
EXFULL: "exchange full",
|
||||
ENOANO: "no anode",
|
||||
EBADRQC: "invalid request code",
|
||||
EBADSLT: "invalid slot",
|
||||
EBFONT: "bad font file fmt",
|
||||
ENOSTR: "device not a stream",
|
||||
ENODATA: "no data (for no delay io)",
|
||||
ETIME: "timer expired",
|
||||
ENOSR: "out of streams resources",
|
||||
ENONET: "machine is not on the network",
|
||||
ENOPKG: "package not installed",
|
||||
EREMOTE: "the object is remote",
|
||||
ENOLINK: "the link has been severed",
|
||||
EADV: "advertise error",
|
||||
ESRMNT: "srmount error",
|
||||
ECOMM: "communication error on send",
|
||||
EPROTO: "protocol error",
|
||||
EMULTIHOP: "multihop attempted",
|
||||
ELBIN: "inode is remote (not really error)",
|
||||
EDOTDOT: "cross mount point (not really error)",
|
||||
EBADMSG: "trying to read unreadable message",
|
||||
EFTYPE: "inappropriate file type or format",
|
||||
ENOTUNIQ: "given log. name not unique",
|
||||
EBADFD: "f.d. invalid for this operation",
|
||||
EREMCHG: "remote address changed",
|
||||
ELIBACC: "can't access a needed shared lib",
|
||||
ELIBBAD: "accessing a corrupted shared lib",
|
||||
ELIBSCN: ".lib section in a.out corrupted",
|
||||
ELIBMAX: "attempting to link in too many libs",
|
||||
ELIBEXEC: "attempting to exec a shared library",
|
||||
ENMFILE: "no more files",
|
||||
ENOTEMPTY: "directory not empty",
|
||||
ELOOP: "too many symbolic links",
|
||||
EOPNOTSUPP: "operation not supported on transport endpoint",
|
||||
EPFNOSUPPORT: "protocol family not supported",
|
||||
ECONNRESET: "connection reset by peer",
|
||||
ENOBUFS: "no buffer space available",
|
||||
EAFNOSUPPORT: "address family not supported by protocol family",
|
||||
EPROTOTYPE: "protocol wrong type for socket",
|
||||
ENOTSOCK: "socket operation on non-socket",
|
||||
ENOPROTOOPT: "protocol not available",
|
||||
ESHUTDOWN: "can't send after socket shutdown",
|
||||
ECONNREFUSED: "connection refused",
|
||||
EADDRINUSE: "address already in use",
|
||||
ECONNABORTED: "connection aborted",
|
||||
ENETUNREACH: "network is unreachable",
|
||||
ENETDOWN: "network interface is not configured",
|
||||
ETIMEDOUT: "connection timed out",
|
||||
EHOSTDOWN: "host is down",
|
||||
EHOSTUNREACH: "host is unreachable",
|
||||
EINPROGRESS: "connection already in progress",
|
||||
EALREADY: "socket already connected",
|
||||
EDESTADDRREQ: "destination address required",
|
||||
EPROTONOSUPPORT: "unknown protocol",
|
||||
ESOCKTNOSUPPORT: "socket type not supported",
|
||||
EADDRNOTAVAIL: "address not available",
|
||||
EISCONN: "socket is already connected",
|
||||
ENOTCONN: "socket is not connected",
|
||||
ENOMEDIUM: "no medium (in tape drive)",
|
||||
ENOSHARE: "no such host or network path",
|
||||
ECASECLASH: "filename exists with different case",
|
||||
EOVERFLOW: "value too large for defined data type",
|
||||
ECANCELED: "operation canceled.",
|
||||
EL2NSYNC: "level 2 not synchronized",
|
||||
EIDRM: "identifier removed",
|
||||
EMSGSIZE: "message too long",
|
||||
ENACL: "not supported by native client",
|
||||
}
|
@ -1,303 +0,0 @@
|
||||
// mksyscall.sh -l32 -nacl syscall_nacl.go syscall_nacl_386.go
|
||||
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
package syscall
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Chmod(path string, mode uint32) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Clock() (clock int) {
|
||||
r0, _, _ := Syscall(SYS_CLOCK, 0, 0, 0)
|
||||
clock = int(r0)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Close(fd int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Exit(code int) {
|
||||
Syscall(SYS_EXIT, uintptr(code), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Fstat(fd int, stat *Stat_t) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Getdents(fd int, buf []byte) (n int, errno int) {
|
||||
var _p0 unsafe.Pointer
|
||||
if len(buf) > 0 {
|
||||
_p0 = unsafe.Pointer(&buf[0])
|
||||
} else {
|
||||
_p0 = unsafe.Pointer(&_zero[0])
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
|
||||
n = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Getpid() (pid int) {
|
||||
r0, _, _ := Syscall(SYS_GETPID, 0, 0, 0)
|
||||
pid = int(r0)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Gettimeofday(tv *Timeval) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Open(path string, mode int, perm uint32) (fd int, errno int) {
|
||||
r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(mode), uintptr(perm))
|
||||
fd = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Read(fd int, p []byte) (n int, errno int) {
|
||||
var _p0 unsafe.Pointer
|
||||
if len(p) > 0 {
|
||||
_p0 = unsafe.Pointer(&p[0])
|
||||
} else {
|
||||
_p0 = unsafe.Pointer(&_zero[0])
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
|
||||
n = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func read(fd int, buf *byte, nbuf int) (n int, errno int) {
|
||||
r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
|
||||
n = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Stat(path string, stat *Stat_t) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(unsafe.Pointer(stat)), 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Write(fd int, p []byte) (n int, errno int) {
|
||||
var _p0 unsafe.Pointer
|
||||
if len(p) > 0 {
|
||||
_p0 = unsafe.Pointer(&p[0])
|
||||
} else {
|
||||
_p0 = unsafe.Pointer(&_zero[0])
|
||||
}
|
||||
r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
|
||||
n = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func MultimediaInit(subsys int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_MULTIMEDIA_INIT, uintptr(subsys), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func MultimediaShutdown() (errno int) {
|
||||
_, _, e1 := Syscall(SYS_MULTIMEDIA_SHUTDOWN, 0, 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func CondCreate() (cv int, errno int) {
|
||||
r0, _, e1 := Syscall(SYS_COND_CREATE, 0, 0, 0)
|
||||
cv = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func CondWait(cv int, mutex int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_COND_WAIT, uintptr(cv), uintptr(mutex), 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func CondSignal(cv int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_COND_SIGNAL, uintptr(cv), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func CondBroadcast(cv int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_COND_BROADCAST, uintptr(cv), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func CondTimedWaitAbs(cv int, mutex int, abstime *Timespec) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_COND_TIMED_WAIT_ABS, uintptr(cv), uintptr(mutex), uintptr(unsafe.Pointer(abstime)))
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func MutexCreate() (mutex int, errno int) {
|
||||
r0, _, e1 := Syscall(SYS_MUTEX_CREATE, 0, 0, 0)
|
||||
mutex = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func MutexLock(mutex int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_MUTEX_LOCK, uintptr(mutex), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func MutexUnlock(mutex int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_MUTEX_UNLOCK, uintptr(mutex), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func MutexTryLock(mutex int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_MUTEX_TRYLOCK, uintptr(mutex), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func SemCreate() (sema int, errno int) {
|
||||
r0, _, e1 := Syscall(SYS_SEM_CREATE, 0, 0, 0)
|
||||
sema = int(r0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func SemWait(sema int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_SEM_WAIT, uintptr(sema), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func SemPost(sema int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_SEM_POST, uintptr(sema), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func VideoInit(dx int, dy int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_VIDEO_INIT, uintptr(dx), uintptr(dy), 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func VideoUpdate(data *uint32) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_VIDEO_UPDATE, uintptr(unsafe.Pointer(data)), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func VideoPollEvent(ev *byte) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_VIDEO_POLL_EVENT, uintptr(unsafe.Pointer(ev)), 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func VideoShutdown() (errno int) {
|
||||
_, _, e1 := Syscall(SYS_VIDEO_SHUTDOWN, 0, 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func AudioInit(fmt int, nreq int, data *int) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_AUDIO_INIT, uintptr(fmt), uintptr(nreq), uintptr(unsafe.Pointer(data)))
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func AudioShutdown() (errno int) {
|
||||
_, _, e1 := Syscall(SYS_AUDIO_SHUTDOWN, 0, 0, 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func AudioStream(data *uint16, size *uintptr) (errno int) {
|
||||
_, _, e1 := Syscall(SYS_AUDIO_STREAM, uintptr(unsafe.Pointer(data)), uintptr(unsafe.Pointer(size)), 0)
|
||||
errno = int(e1)
|
||||
return
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// mksysnum_nacl.sh /home/rsc/pub/nacl/native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h
|
||||
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||
|
||||
package syscall
|
||||
|
||||
const (
|
||||
SYS_NULL = 1
|
||||
SYS_OPEN = 10
|
||||
SYS_CLOSE = 11
|
||||
SYS_READ = 12
|
||||
SYS_WRITE = 13
|
||||
SYS_LSEEK = 14
|
||||
SYS_IOCTL = 15
|
||||
SYS_STAT = 16
|
||||
SYS_FSTAT = 17
|
||||
SYS_CHMOD = 18
|
||||
SYS_SYSBRK = 20
|
||||
SYS_MMAP = 21
|
||||
SYS_MUNMAP = 22
|
||||
SYS_GETDENTS = 23
|
||||
SYS_EXIT = 30
|
||||
SYS_GETPID = 31
|
||||
SYS_SCHED_YIELD = 32
|
||||
SYS_SYSCONF = 33
|
||||
SYS_GETTIMEOFDAY = 40
|
||||
SYS_CLOCK = 41
|
||||
SYS_NANOSLEEP = 42
|
||||
SYS_MULTIMEDIA_INIT = 50
|
||||
SYS_MULTIMEDIA_SHUTDOWN = 51
|
||||
SYS_VIDEO_INIT = 52
|
||||
SYS_VIDEO_SHUTDOWN = 53
|
||||
SYS_VIDEO_UPDATE = 54
|
||||
SYS_VIDEO_POLL_EVENT = 55
|
||||
SYS_AUDIO_INIT = 56
|
||||
SYS_AUDIO_SHUTDOWN = 57
|
||||
SYS_AUDIO_STREAM = 58
|
||||
SYS_IMC_MAKEBOUNDSOCK = 60
|
||||
SYS_IMC_ACCEPT = 61
|
||||
SYS_IMC_CONNECT = 62
|
||||
SYS_IMC_SENDMSG = 63
|
||||
SYS_IMC_RECVMSG = 64
|
||||
SYS_IMC_MEM_OBJ_CREATE = 65
|
||||
SYS_IMC_SOCKETPAIR = 66
|
||||
SYS_MUTEX_CREATE = 70
|
||||
SYS_MUTEX_LOCK = 71
|
||||
SYS_MUTEX_TRYLOCK = 72
|
||||
SYS_MUTEX_UNLOCK = 73
|
||||
SYS_COND_CREATE = 74
|
||||
SYS_COND_WAIT = 75
|
||||
SYS_COND_SIGNAL = 76
|
||||
SYS_COND_BROADCAST = 77
|
||||
SYS_COND_TIMED_WAIT_ABS = 79
|
||||
SYS_THREAD_CREATE = 80
|
||||
SYS_THREAD_EXIT = 81
|
||||
SYS_TLS_INIT = 82
|
||||
SYS_THREAD_NICE = 83
|
||||
SYS_TLS_GET = 84
|
||||
SYS_SRPC_GET_FD = 90
|
||||
SYS_SEM_CREATE = 100
|
||||
SYS_SEM_WAIT = 101
|
||||
SYS_SEM_POST = 102
|
||||
SYS_SEM_GET_VALUE = 103
|
||||
SYS_DYNCODE_COPY = 104
|
||||
)
|
@ -1,4 +1,3 @@
|
||||
// mksysnum_nacl.sh /home/rsc/pub/nacl/native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h
|
||||
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||
// nothing to see here
|
||||
|
||||
package syscall
|
||||
|
@ -1,9 +0,0 @@
|
||||
// godefs -gsyscall -f-m32 -f-I/home/rsc/pub/nacl/native_client/src/third_party/nacl_sdk/linux/sdk/nacl-sdk/nacl/include -f-I/home/rsc/pub/nacl/native_client/src/trusted/service_runtime/include types_nacl.c
|
||||
|
||||
// MACHINE GENERATED - DO NOT EDIT.
|
||||
|
||||
package syscall
|
||||
|
||||
// Constants
|
||||
|
||||
// Types
|
@ -1,105 +0,0 @@
|
||||
// godefs -gsyscall -f-m32 -f-I/home/rsc/pub/nacl/native_client/src/third_party/nacl_sdk/linux/sdk/nacl-sdk/nacl/include -f-I/home/rsc/pub/nacl/native_client types_nacl.c
|
||||
|
||||
// MACHINE GENERATED - DO NOT EDIT.
|
||||
|
||||
package syscall
|
||||
|
||||
// Constants
|
||||
const (
|
||||
sizeofPtr = 0x4
|
||||
sizeofShort = 0x2
|
||||
sizeofInt = 0x4
|
||||
sizeofLong = 0x4
|
||||
sizeofLongLong = 0x8
|
||||
PROT_READ = 0x1
|
||||
PROT_WRITE = 0x2
|
||||
MAP_SHARED = 0x1
|
||||
SYS_FORK = 0
|
||||
SYS_PTRACE = 0
|
||||
SYS_CHDIR = 0
|
||||
SYS_DUP2 = 0
|
||||
SYS_FCNTL = 0
|
||||
SYS_EXECVE = 0
|
||||
O_RDONLY = 0
|
||||
O_WRONLY = 0x1
|
||||
O_RDWR = 0x2
|
||||
O_APPEND = 0x400
|
||||
O_ASYNC = 0x2000
|
||||
O_CREAT = 0x40
|
||||
O_NOCTTY = 0
|
||||
O_NONBLOCK = 0x800
|
||||
O_SYNC = 0x1000
|
||||
O_TRUNC = 0x200
|
||||
O_EXCL = 0x80
|
||||
O_CLOEXEC = 0
|
||||
F_GETFD = 0x1
|
||||
F_SETFD = 0x2
|
||||
F_GETFL = 0x3
|
||||
F_SETFL = 0x4
|
||||
FD_CLOEXEC = 0
|
||||
S_IFMT = 0x1f000
|
||||
S_IFIFO = 0x1000
|
||||
S_IFCHR = 0x2000
|
||||
S_IFDIR = 0x4000
|
||||
S_IFBLK = 0x6000
|
||||
S_IFREG = 0x8000
|
||||
S_IFLNK = 0xa000
|
||||
S_IFSOCK = 0xc000
|
||||
S_ISUID = 0x800
|
||||
S_ISGID = 0x400
|
||||
S_ISVTX = 0x200
|
||||
S_IRUSR = 0x100
|
||||
S_IWUSR = 0x80
|
||||
S_IXUSR = 0x40
|
||||
)
|
||||
|
||||
// Types
|
||||
|
||||
type _C_short int16
|
||||
|
||||
type _C_int int32
|
||||
|
||||
type _C_long int32
|
||||
|
||||
type _C_long_long int64
|
||||
|
||||
type _C_off_t int32
|
||||
|
||||
type Timespec struct {
|
||||
Sec int32
|
||||
Nsec int32
|
||||
}
|
||||
|
||||
type Timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
|
||||
type Time_t int32
|
||||
|
||||
type _Gid_t uint32
|
||||
|
||||
type Stat_t struct {
|
||||
Dev int64
|
||||
Ino uint32
|
||||
Mode uint32
|
||||
Nlink uint32
|
||||
Uid uint32
|
||||
Gid uint32
|
||||
X__padding int32
|
||||
Rdev int64
|
||||
Size int32
|
||||
Blksize int32
|
||||
Blocks int32
|
||||
Atime int32
|
||||
Mtime int32
|
||||
Ctime int32
|
||||
}
|
||||
|
||||
type Dirent struct {
|
||||
Ino uint32
|
||||
Off int32
|
||||
Reclen uint16
|
||||
Name [256]int8
|
||||
Pad0 [2]byte
|
||||
}
|
@ -20,9 +20,6 @@ GOFILES_darwin=\
|
||||
GOFILES_linux=\
|
||||
zoneinfo_unix.go\
|
||||
|
||||
GOFILES_nacl=\
|
||||
zoneinfo_unix.go\
|
||||
|
||||
GOFILES_windows=\
|
||||
zoneinfo_windows.go\
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # NaCl runner does not expose environment
|
||||
// $G $F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # no network
|
||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # do not bother on NaCl
|
||||
// $G $D/$F.go && $L $F.$A &&
|
||||
// ((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # NaCl runner elides NUL in output
|
||||
// [ "$GORUN" == "" ] || exit 0 # Android runner gets confused by the NUL output
|
||||
// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
|
||||
// errchk $G -e tmp.go
|
||||
|
@ -7,7 +7,6 @@
|
||||
// Test of recover for run-time errors.
|
||||
|
||||
// TODO(rsc):
|
||||
// integer divide by zero?
|
||||
// null pointer accesses
|
||||
|
||||
package main
|
||||
@ -15,7 +14,6 @@ package main
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var x = make([]byte, 10)
|
||||
@ -83,10 +81,6 @@ func test6() {
|
||||
}
|
||||
|
||||
func test7() {
|
||||
if syscall.OS == "nacl" {
|
||||
// NaCl cannot handle traps
|
||||
return
|
||||
}
|
||||
defer mustRecover("divide by zero")
|
||||
var x, y int
|
||||
println(x / y)
|
||||
|
@ -1,4 +1,3 @@
|
||||
// [ $GOOS != nacl ] || exit 0 # NaCl cannot recover from signals
|
||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
|
@ -1,4 +1,3 @@
|
||||
// if [ $GOOS == nacl ]; then echo survived SIGCHLD; exit 0; fi # NaCl has no signals.
|
||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Error interface {
|
||||
@ -163,7 +162,7 @@ func alike(a, b float64) bool {
|
||||
func main() {
|
||||
bad := false
|
||||
for _, t := range errorTests {
|
||||
if t.err != "" && syscall.OS == "nacl" {
|
||||
if t.err != "" {
|
||||
continue
|
||||
}
|
||||
err := error(t.fn)
|
||||
|
Loading…
Reference in New Issue
Block a user