diff options
Diffstat (limited to 'src')
243 files changed, 14822 insertions, 9330 deletions
diff --git a/src/Make.pkg b/src/Make.pkg index 966bc61c7..86a2e9fd0 100644 --- a/src/Make.pkg +++ b/src/Make.pkg @@ -79,7 +79,7 @@ testpackage-clean: install: $(INSTALLFILES) $(TARGDIR)/$(TARG).a: _obj/$(TARG).a - @test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/$(dir) + @mkdir -p $(TARGDIR)/$(dir) cp _obj/$(TARG).a "$@" _go_.$O: $(GOFILES) $(PREREQ) @@ -227,7 +227,7 @@ _obj/$(SWIG_PREFIX)-%.so: _obj/%_wrapcxx.o $(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS)) $(TARGDIR)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so - @test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(TARGDIR)/swig + @mkdir -p $(TARGDIR)/swig cp $< "$@" all: $(SWIG_SOS) diff --git a/src/cmd/5g/Makefile b/src/cmd/5g/Makefile index 6873fbc68..b47014a4e 100644 --- a/src/cmd/5g/Makefile +++ b/src/cmd/5g/Makefile @@ -15,16 +15,17 @@ HFILES=\ OFILES=\ ../5l/enam.$O\ - list.$O\ - galign.$O\ - gobj.$O\ - ggen.$O\ - gsubr.$O\ cgen.$O\ cgen64.$O\ cplx.$O\ - reg.$O\ + galign.$O\ + ggen.$O\ + gobj.$O\ + gsubr.$O\ + list.$O\ peep.$O\ + pgen.$O\ + reg.$O\ LIB=\ ../gc/gc.a\ diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 4e5f7ebcd..76e2707fa 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -1190,7 +1190,8 @@ void sgen(Node *n, Node *res, int32 w) { Node dst, src, tmp, nend; - int32 c, q, odst, osrc; + int32 c, odst, osrc; + int dir, align, op; Prog *p, *ploop; if(debug['g']) { @@ -1200,17 +1201,39 @@ sgen(Node *n, Node *res, int32 w) } if(w == 0) return; - if(n->ullman >= UINF && res->ullman >= UINF) { - fatal("sgen UINF"); - } - if(w < 0) fatal("sgen copy %d", w); + if(n->ullman >= UINF && res->ullman >= UINF) + fatal("sgen UINF"); + if(n->type == T) + fatal("sgen: missing type"); + + // determine alignment. + // want to avoid unaligned access, so have to use + // smaller operations for less aligned types. + // for example moving [4]byte must use 4 MOVB not 1 MOVW. + align = n->type->align; + op = 0; + switch(align) { + default: + fatal("sgen: invalid alignment %d for %T", align, n->type); + case 1: + op = AMOVB; + break; + case 2: + op = AMOVH; + break; + case 4: + op = AMOVW; + break; + } + if(w%align) + fatal("sgen: unaligned size %d (align=%d) for %T", w, align, n->type); + c = w / align; // offset on the stack osrc = stkof(n); odst = stkof(res); - if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) { // osrc and odst both on stack, and at least one is in // an unknown position. Could generate code to test @@ -1221,12 +1244,15 @@ sgen(Node *n, Node *res, int32 w) sgen(&tmp, res, w); return; } - - if(osrc % 4 != 0 || odst %4 != 0) - fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst); + if(osrc%align != 0 || odst%align != 0) + fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align); + // if we are copying forward on the stack and + // the src and dst overlap, then reverse direction + dir = align; + if(osrc < odst && odst < osrc+w) + dir = -dir; regalloc(&dst, types[tptr], res); - if(n->ullman >= res->ullman) { agen(n, &dst); // temporarily use dst regalloc(&src, types[tptr], N); @@ -1240,141 +1266,64 @@ sgen(Node *n, Node *res, int32 w) regalloc(&tmp, types[TUINT32], N); - c = w % 4; // bytes - q = w / 4; // quads - - // if we are copying forward on the stack and - // the src and dst overlap, then reverse direction - if(osrc < odst && odst < osrc+w) { - if(c != 0) - fatal("sgen: reverse character copy not implemented"); - if(q >= 4) { - regalloc(&nend, types[TUINT32], N); - // set up end marker to 4 bytes before source - p = gins(AMOVW, &src, &nend); - p->from.type = D_CONST; - p->from.offset = -4; - - // move src and dest to the end of block - p = gins(AMOVW, &src, &src); - p->from.type = D_CONST; - p->from.offset = (q-1)*4; - - p = gins(AMOVW, &dst, &dst); - p->from.type = D_CONST; - p->from.offset = (q-1)*4; - - p = gins(AMOVW, &src, &tmp); - p->from.type = D_OREG; - p->from.offset = -4; - p->scond |= C_PBIT; - ploop = p; + // set up end marker + memset(&nend, 0, sizeof nend); + if(c >= 4) { + regalloc(&nend, types[TUINT32], N); - p = gins(AMOVW, &tmp, &dst); - p->to.type = D_OREG; - p->to.offset = -4; - p->scond |= C_PBIT; - - p = gins(ACMP, &src, N); - raddr(&nend, p); + p = gins(AMOVW, &src, &nend); + p->from.type = D_CONST; + if(dir < 0) + p->from.offset = dir; + else + p->from.offset = w; + } - patch(gbranch(ABNE, T), ploop); + // move src and dest to the end of block if necessary + if(dir < 0) { + p = gins(AMOVW, &src, &src); + p->from.type = D_CONST; + p->from.offset = w + dir; - regfree(&nend); - } else { - // move src and dest to the end of block - p = gins(AMOVW, &src, &src); - p->from.type = D_CONST; - p->from.offset = (q-1)*4; - - p = gins(AMOVW, &dst, &dst); - p->from.type = D_CONST; - p->from.offset = (q-1)*4; - - while(q > 0) { - p = gins(AMOVW, &src, &tmp); - p->from.type = D_OREG; - p->from.offset = -4; - p->scond |= C_PBIT; - - p = gins(AMOVW, &tmp, &dst); - p->to.type = D_OREG; - p->to.offset = -4; - p->scond |= C_PBIT; - - q--; - } - } + p = gins(AMOVW, &dst, &dst); + p->from.type = D_CONST; + p->from.offset = w + dir; + } + + // move + if(c >= 4) { + p = gins(op, &src, &tmp); + p->from.type = D_OREG; + p->from.offset = dir; + p->scond |= C_PBIT; + ploop = p; + + p = gins(op, &tmp, &dst); + p->to.type = D_OREG; + p->to.offset = dir; + p->scond |= C_PBIT; + + p = gins(ACMP, &src, N); + raddr(&nend, p); + + patch(gbranch(ABNE, T), ploop); + regfree(&nend); } else { - // normal direction - if(q >= 4) { - regalloc(&nend, types[TUINT32], N); - p = gins(AMOVW, &src, &nend); - p->from.type = D_CONST; - p->from.offset = q*4; - - p = gins(AMOVW, &src, &tmp); + while(c-- > 0) { + p = gins(op, &src, &tmp); p->from.type = D_OREG; - p->from.offset = 4; + p->from.offset = dir; p->scond |= C_PBIT; ploop = p; - - p = gins(AMOVW, &tmp, &dst); + + p = gins(op, &tmp, &dst); p->to.type = D_OREG; - p->to.offset = 4; + p->to.offset = dir; p->scond |= C_PBIT; - - p = gins(ACMP, &src, N); - raddr(&nend, p); - - patch(gbranch(ABNE, T), ploop); - - regfree(&nend); - } else - while(q > 0) { - p = gins(AMOVW, &src, &tmp); - p->from.type = D_OREG; - p->from.offset = 4; - p->scond |= C_PBIT; - - p = gins(AMOVW, &tmp, &dst); - p->to.type = D_OREG; - p->to.offset = 4; - p->scond |= C_PBIT; - - q--; - } - - if (c != 0) { - // MOVW (src), tmp - p = gins(AMOVW, &src, &tmp); - p->from.type = D_OREG; - - // MOVW tmp<<((4-c)*8),src - gshift(AMOVW, &tmp, SHIFT_LL, ((4-c)*8), &src); - - // MOVW src>>((4-c)*8),src - gshift(AMOVW, &src, SHIFT_LR, ((4-c)*8), &src); - - // MOVW (dst), tmp - p = gins(AMOVW, &dst, &tmp); - p->from.type = D_OREG; - - // MOVW tmp>>(c*8),tmp - gshift(AMOVW, &tmp, SHIFT_LR, (c*8), &tmp); - - // MOVW tmp<<(c*8),tmp - gshift(AMOVW, &tmp, SHIFT_LL, c*8, &tmp); - - // ORR src, tmp - gins(AORR, &src, &tmp); - - // MOVW tmp, (dst) - p = gins(AMOVW, &tmp, &dst); - p->to.type = D_OREG; } } - regfree(&dst); + + regfree(&dst); regfree(&src); regfree(&tmp); } diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c index 7197709d4..0bc1b38fc 100644 --- a/src/cmd/5g/ggen.c +++ b/src/cmd/5g/ggen.c @@ -7,107 +7,9 @@ #include "gg.h" #include "opt.h" -static Prog *pret; - void -compile(Node *fn) +defframe(Prog *ptxt) { - Plist *pl; - Node nod1; - Prog *ptxt; - int32 lno; - Type *t; - Iter save; - - if(newproc == N) { - newproc = sysfunc("newproc"); - deferproc = sysfunc("deferproc"); - deferreturn = sysfunc("deferreturn"); - panicindex = sysfunc("panicindex"); - panicslice = sysfunc("panicslice"); - throwreturn = sysfunc("throwreturn"); - } - - if(fn->nbody == nil) - return; - - // set up domain for labels - clearlabels(); - - lno = setlineno(fn); - - curfn = fn; - dowidth(curfn->type); - - if(curfn->type->outnamed) { - // add clearing of the output parameters - t = structfirst(&save, getoutarg(curfn->type)); - while(t != T) { - if(t->nname != N) - curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody); - t = structnext(&save); - } - } - - hasdefer = 0; - walk(curfn); - if(nerrors != 0 || isblank(curfn->nname)) - goto ret; - - allocparams(); - - continpc = P; - breakpc = P; - - pl = newplist(); - pl->name = curfn->nname; - - setlineno(curfn); - - nodconst(&nod1, types[TINT32], 0); - ptxt = gins(ATEXT, curfn->nname, &nod1); - afunclit(&ptxt->from); - - ginit(); - genlist(curfn->enter); - - pret = nil; - if(hasdefer || curfn->exit) { - Prog *p1; - - p1 = gjmp(nil); - pret = gjmp(nil); - patch(p1, pc); - } - - genlist(curfn->nbody); - gclean(); - checklabels(); - if(nerrors != 0) - goto ret; - - if(curfn->type->outtuple != 0) - ginscall(throwreturn, 0); - - if(pret) - patch(pret, pc); - ginit(); - if(hasdefer) - ginscall(deferreturn, 0); - if(curfn->exit) - genlist(curfn->exit); - gclean(); - if(nerrors != 0) - goto ret; - if(curfn->endlineno) - lineno = curfn->endlineno; - pc->as = ARET; // overwrite AEND - pc->lineno = lineno; - - if(!debug['N'] || debug['R'] || debug['P']) { - regopt(ptxt); - } - // fill in argument size ptxt->to.type = D_CONST2; ptxt->reg = 0; // flags @@ -118,12 +20,6 @@ compile(Node *fn) maxstksize = stksize; ptxt->to.offset = rnd(maxstksize+maxarg, widthptr); maxstksize = 0; - - if(debug['f']) - frame(0); - -ret: - lineno = lno; } /* @@ -197,7 +93,7 @@ ginscall(Node *f, int proc) nodconst(&con, types[TINT32], 0); p = gins(ACMP, &con, N); p->reg = 0; - patch(gbranch(ABNE, T), pret); + patch(gbranch(ABNE, T), retpc); } break; } @@ -401,7 +297,7 @@ cgen_ret(Node *n) { genlist(n->list); // copy out args if(hasdefer || curfn->exit) - gjmp(pret); + gjmp(retpc); else gins(ARET, N, N); } diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 9e9c2c1eb..81c08e353 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -1977,3 +1977,9 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) Bprint(&bso, "symsize = %ud\n", symsize); Bflush(&bso); } + +void +setpersrc(Sym *s) +{ + USED(s); +} diff --git a/src/cmd/6g/Makefile b/src/cmd/6g/Makefile index 023f5d111..64fa15399 100644 --- a/src/cmd/6g/Makefile +++ b/src/cmd/6g/Makefile @@ -14,16 +14,17 @@ HFILES=\ opt.h\ OFILES=\ - list.$O\ - gobj.$O\ - galign.$O\ - ggen.$O\ + ../6l/enam.$O\ cgen.$O\ cplx.$O\ + galign.$O\ + ggen.$O\ + gobj.$O\ gsubr.$O\ + list.$O\ peep.$O\ + pgen.$O\ reg.$O\ - ../6l/enam.$O\ LIB=\ ../gc/gc.a\ diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index ce66b43f0..5260335df 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -7,121 +7,18 @@ #include "gg.h" #include "opt.h" -static Prog *pret; - void -compile(Node *fn) +defframe(Prog *ptxt) { - Plist *pl; - Node nod1; - Prog *ptxt; - int32 lno; - Type *t; - Iter save; - - if(newproc == N) { - newproc = sysfunc("newproc"); - deferproc = sysfunc("deferproc"); - deferreturn = sysfunc("deferreturn"); - panicindex = sysfunc("panicindex"); - panicslice = sysfunc("panicslice"); - throwreturn = sysfunc("throwreturn"); - } - - if(fn->nbody == nil) - return; - - // set up domain for labels - clearlabels(); - - lno = setlineno(fn); - - curfn = fn; - dowidth(curfn->type); - - if(curfn->type->outnamed) { - // add clearing of the output parameters - t = structfirst(&save, getoutarg(curfn->type)); - while(t != T) { - if(t->nname != N) - curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody); - t = structnext(&save); - } - } - - hasdefer = 0; - walk(curfn); - if(nerrors != 0 || isblank(curfn->nname)) - goto ret; - - allocparams(); - - continpc = P; - breakpc = P; - - pl = newplist(); - pl->name = curfn->nname; - - setlineno(curfn); - - nodconst(&nod1, types[TINT32], 0); - ptxt = gins(ATEXT, curfn->nname, &nod1); - afunclit(&ptxt->from); - - ginit(); - genlist(curfn->enter); - - pret = nil; - if(hasdefer || curfn->exit) { - Prog *p1; - - p1 = gjmp(nil); - pret = gjmp(nil); - patch(p1, pc); - } - - genlist(curfn->nbody); - gclean(); - checklabels(); - if(nerrors != 0) - goto ret; - if(curfn->endlineno) - lineno = curfn->endlineno; - - if(curfn->type->outtuple != 0) - ginscall(throwreturn, 0); - - if(pret) - patch(pret, pc); - ginit(); - if(hasdefer) - ginscall(deferreturn, 0); - if(curfn->exit) - genlist(curfn->exit); - gclean(); - if(nerrors != 0) - goto ret; - pc->as = ARET; // overwrite AEND - pc->lineno = lineno; - - if(!debug['N'] || debug['R'] || debug['P']) { - regopt(ptxt); - } - // fill in argument size ptxt->to.offset = rnd(curfn->type->argwid, widthptr); // fill in final stack size ptxt->to.offset <<= 32; ptxt->to.offset |= rnd(stksize+maxarg, widthptr); - - if(debug['f']) - frame(0); - -ret: - lineno = lno; } + /* * generate: * call f @@ -163,7 +60,7 @@ ginscall(Node *f, int proc) if(proc == 2) { nodreg(®, types[TINT64], D_AX); gins(ATESTQ, ®, ®); - patch(gbranch(AJNE, T), pret); + patch(gbranch(AJNE, T), retpc); } break; } @@ -355,7 +252,7 @@ cgen_ret(Node *n) { genlist(n->list); // copy out args if(hasdefer || curfn->exit) - gjmp(pret); + gjmp(retpc); else gins(ARET, N, N); } diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index 6dffa20f2..320f4c9e9 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -828,6 +828,7 @@ asmb(void) dwarfemitdebugsections(); } break; + case Hdarwin: case Hwindows: seek(cout, symo, 0); if(debug['v']) diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index d53814a74..e3191bb4d 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -177,7 +177,7 @@ main(int argc, char *argv[]) */ tlsoffset = 0x8a0; machoinit(); - HEADR = MACHORESERVE; + HEADR = INITIAL_MACHO_HEADR; if(INITRND == -1) INITRND = 4096; if(INITTEXT == -1) diff --git a/src/cmd/8g/Makefile b/src/cmd/8g/Makefile index 09cf8d4e3..b459782a3 100644 --- a/src/cmd/8g/Makefile +++ b/src/cmd/8g/Makefile @@ -15,15 +15,16 @@ HFILES=\ OFILES=\ ../8l/enam.$O\ - list.$O\ - galign.$O\ - gobj.$O\ - ggen.$O\ - gsubr.$O\ cgen.$O\ cgen64.$O\ cplx.$O\ + galign.$O\ + ggen.$O\ + gobj.$O\ + gsubr.$O\ + list.$O\ peep.$O\ + pgen.$O\ reg.$O\ LIB=\ diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 223152536..25adb38c0 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -7,106 +7,9 @@ #include "gg.h" #include "opt.h" -static Prog *pret; - void -compile(Node *fn) +defframe(Prog *ptxt) { - Plist *pl; - Node nod1; - Prog *ptxt; - int32 lno; - Type *t; - Iter save; - - if(newproc == N) { - newproc = sysfunc("newproc"); - deferproc = sysfunc("deferproc"); - deferreturn = sysfunc("deferreturn"); - panicindex = sysfunc("panicindex"); - panicslice = sysfunc("panicslice"); - throwreturn = sysfunc("throwreturn"); - } - - if(fn->nbody == nil) - return; - - // set up domain for labels - clearlabels(); - - lno = setlineno(fn); - - curfn = fn; - dowidth(curfn->type); - - if(curfn->type->outnamed) { - // add clearing of the output parameters - t = structfirst(&save, getoutarg(curfn->type)); - while(t != T) { - if(t->nname != N) - curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody); - t = structnext(&save); - } - } - - hasdefer = 0; - walk(curfn); - if(nerrors != 0 || isblank(curfn->nname)) - goto ret; - - allocparams(); - - continpc = P; - breakpc = P; - - pl = newplist(); - pl->name = curfn->nname; - - setlineno(curfn); - - nodconst(&nod1, types[TINT32], 0); - ptxt = gins(ATEXT, curfn->nname, &nod1); - afunclit(&ptxt->from); - - ginit(); - genlist(curfn->enter); - - pret = nil; - if(hasdefer || curfn->exit) { - Prog *p1; - - p1 = gjmp(nil); - pret = gjmp(nil); - patch(p1, pc); - } - - genlist(curfn->nbody); - gclean(); - checklabels(); - if(nerrors != 0) - goto ret; - if(curfn->endlineno) - lineno = curfn->endlineno; - - if(curfn->type->outtuple != 0) - ginscall(throwreturn, 0); - - if(pret) - patch(pret, pc); - ginit(); - if(hasdefer) - ginscall(deferreturn, 0); - if(curfn->exit) - genlist(curfn->exit); - gclean(); - if(nerrors != 0) - goto ret; - pc->as = ARET; // overwrite AEND - pc->lineno = lineno; - - if(!debug['N'] || debug['R'] || debug['P']) { - regopt(ptxt); - } // fill in argument size ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr); @@ -115,12 +18,6 @@ compile(Node *fn) maxstksize = stksize; ptxt->to.offset = rnd(maxstksize+maxarg, widthptr); maxstksize = 0; - - if(debug['f']) - frame(0); - -ret: - lineno = lno; } void @@ -200,7 +97,7 @@ ginscall(Node *f, int proc) if(proc == 2) { nodreg(®, types[TINT64], D_AX); gins(ATESTL, ®, ®); - patch(gbranch(AJNE, T), pret); + patch(gbranch(AJNE, T), retpc); } break; } @@ -391,8 +288,8 @@ void cgen_ret(Node *n) { genlist(n->list); // copy out args - if(pret) - gjmp(pret); + if(retpc) + gjmp(retpc); else gins(ARET, N, N); } diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 7de7753a2..c426a88a4 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -781,6 +781,7 @@ asmb(void) cflush(); } break; + case Hdarwin: case Hwindows: seek(cout, symo, 0); if(debug['v']) diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index f84a30f39..440dcb77f 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -218,7 +218,7 @@ main(int argc, char *argv[]) */ tlsoffset = 0x468; machoinit(); - HEADR = MACHORESERVE; + HEADR = INITIAL_MACHO_HEADR; if(INITTEXT == -1) INITTEXT = 4096+HEADR; if(INITDAT == -1) diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index b3aa9aded..064725c1d 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -35,9 +35,17 @@ systems. For example: // #include <png.h> import "C" -C identifiers or field names that are keywords in Go can be -accessed by prefixing them with an underscore: if x points at -a C struct with a field named "type", x._type accesses the field. +Alternatively, CFLAGS and LDFLAGS may be obtained via the pkg-config +tool using a '#cgo pkg-config:' directive followed by the package names. +For example: + + // #cgo pkg-config: png cairo + // #include <png.h> + import "C" + +Within the Go file, C identifiers or field names that are keywords in Go +can be accessed by prefixing them with an underscore: if x points at a C +struct with a field named "type", x._type accesses the field. The standard C numeric types are available under the names C.char, C.schar (signed char), C.uchar (unsigned char), diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index ac6561345..fa7602cf2 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -100,27 +100,81 @@ NextLine: fatalf("%s: bad #cgo option: %s", srcfile, fields[0]) } - if k != "CFLAGS" && k != "LDFLAGS" { - fatalf("%s: unsupported #cgo option %s", srcfile, k) - } - - v := strings.TrimSpace(fields[1]) - args, err := splitQuoted(v) + args, err := splitQuoted(fields[1]) if err != nil { - fatalf("%s: bad #cgo option %s: %s", srcfile, k, err.String()) + fatalf("%s: bad #cgo option %s: %s", srcfile, k, err) } - if oldv, ok := p.CgoFlags[k]; ok { - p.CgoFlags[k] = oldv + " " + v - } else { - p.CgoFlags[k] = v + for _, arg := range args { + if !safeName(arg) { + fatalf("%s: #cgo option %s is unsafe: %s", srcfile, k, arg) + } } - if k == "CFLAGS" { - p.GccOptions = append(p.GccOptions, args...) + + switch k { + + case "CFLAGS", "LDFLAGS": + p.addToFlag(k, args) + + case "pkg-config": + cflags, ldflags, err := pkgConfig(args) + if err != nil { + fatalf("%s: bad #cgo option %s: %s", srcfile, k, err) + } + p.addToFlag("CFLAGS", cflags) + p.addToFlag("LDFLAGS", ldflags) + + default: + fatalf("%s: unsupported #cgo option %s", srcfile, k) + } } f.Preamble = strings.Join(linesOut, "\n") } +// addToFlag appends args to flag. All flags are later written out onto the +// _cgo_flags file for the build system to use. +func (p *Package) addToFlag(flag string, args []string) { + if oldv, ok := p.CgoFlags[flag]; ok { + p.CgoFlags[flag] = oldv + " " + strings.Join(args, " ") + } else { + p.CgoFlags[flag] = strings.Join(args, " ") + } + if flag == "CFLAGS" { + // We'll also need these when preprocessing for dwarf information. + p.GccOptions = append(p.GccOptions, args...) + } +} + +// pkgConfig runs pkg-config and extracts --libs and --cflags information +// for packages. +func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) { + for _, name := range packages { + if len(name) == 0 || name[0] == '-' { + return nil, nil, os.NewError(fmt.Sprintf("invalid name: %q", name)) + } + } + + args := append([]string{"pkg-config", "--cflags"}, packages...) + stdout, stderr, ok := run(nil, args) + if !ok { + os.Stderr.Write(stderr) + return nil, nil, os.NewError("pkg-config failed") + } + cflags, err = splitQuoted(string(stdout)) + if err != nil { + return + } + + args = append([]string{"pkg-config", "--libs"}, packages...) + stdout, stderr, ok = run(nil, args) + if !ok { + os.Stderr.Write(stderr) + return nil, nil, os.NewError("pkg-config failed") + } + ldflags, err = splitQuoted(string(stdout)) + return +} + // splitQuoted splits the string s around each instance of one or more consecutive // white space characters while taking into account quotes and escaping, and // returns an array of substrings of s or an empty list if s contains only white space. @@ -182,6 +236,20 @@ func splitQuoted(s string) (r []string, err os.Error) { return args, err } +var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz") + +func safeName(s string) bool { + if s == "" { + return false + } + for i := 0; i < len(s); i++ { + if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 { + return false + } + } + return true +} + // Translate rewrites f.AST, the original Go input, to remove // references to the imported package C, replacing them with // references to the equivalent Go types, functions, and variables. diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 2ce4e9752..dbc7bcf69 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -142,7 +142,7 @@ func dynimport(obj string) { if f, err := pe.Open(obj); err == nil { sym, err := f.ImportedSymbols() if err != nil { - fatalf("cannot load imported symbols from PE file %s: v", obj, err) + fatalf("cannot load imported symbols from PE file %s: %v", obj, err) } for _, s := range sym { ss := strings.Split(s, ":", -1) diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile index dbfd86474..286618ec1 100644 --- a/src/cmd/gc/Makefile +++ b/src/cmd/gc/Makefile @@ -49,7 +49,7 @@ include ../../Make.clib install: $(LIB) y1.tab.c: y.tab.c # make yystate global, yytname mutable - cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/' >y1.tab.c + cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/; s/char const \*yymsgp/char *yymsgp/' >y1.tab.c yerr.h: bisonerrors go.errors y.tab.h # y.tab.h rule generates y.output too awk -f bisonerrors y.output go.errors >yerr.h diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c index a8454bf13..7fcac4833 100644 --- a/src/cmd/gc/align.c +++ b/src/cmd/gc/align.c @@ -234,9 +234,11 @@ dowidth(Type *t) if(t->bound > cap) yyerror("type %lT larger than address space", t); w = t->bound * t->type->width; - if(w == 0) - w = 1; t->align = t->type->align; + if(w == 0) { + w = 1; + t->align = 1; + } } else if(t->bound == -1) { w = sizeof_Array; @@ -253,10 +255,10 @@ dowidth(Type *t) if(t->funarg) fatal("dowidth fn struct %T", t); w = widstruct(t, 0, 1); - if(w == 0) + if(w == 0) { w = 1; - //if(t->align < widthptr) - // warn("align %d: %T\n", t->align, t); + t->align = 1; + } break; case TFUNC: diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c index eb7014366..906dadbc9 100644 --- a/src/cmd/gc/closure.c +++ b/src/cmd/gc/closure.c @@ -75,7 +75,7 @@ closurebody(NodeList *body) } void -typecheckclosure(Node *func) +typecheckclosure(Node *func, int top) { Node *oldfn; NodeList *l; @@ -106,6 +106,10 @@ typecheckclosure(Node *func) v->op = 0; continue; } + // For a closure that is called in place, but not + // inside a go statement, avoid moving variables to the heap. + if ((top & (Ecall|Eproc)) == Ecall) + v->heapaddr->etype = 1; typecheck(&v->heapaddr, Erv); func->enter = list(func->enter, v->heapaddr); v->heapaddr = N; @@ -199,3 +203,41 @@ walkclosure(Node *func, NodeList **init) walkexpr(&call, init); return call; } + +// Special case for closures that get called in place. +// Optimize runtime.closure(X, __func__xxxx_, .... ) away +// to __func__xxxx_(Y ....). +// On entry, expect n->op == OCALL, n->left->op == OCLOSURE. +void +walkcallclosure(Node *n, NodeList **init) +{ + Node *z; + NodeList *ll, *cargs; + + walkexpr(&n->left, init); + cargs = n->left // FUNC runtime.closure + ->list // arguments + ->next // skip first + ->next; // skip second + + n->left = n->left // FUNC runtime.closure + ->list // arguments + ->next // skip first + ->n // AS (to indreg) + ->right; // argument == the generated function + + // New arg list for n. First the closure-args, stolen from + // runtime.closure's 3rd and following, + ll = nil; + for (; cargs; cargs = cargs->next) + ll = list(ll, cargs->n->right); // cargs->n is the OAS(INDREG, arg) + + // then an extra zero, to fill the dummy return pointer slot, + z = nod(OXXX, N, N); + nodconst(z, types[TUINTPTR], 0); + z->typecheck = 1; + ll = list(ll, z); + + // and finally the original parameter list. + n->list = concat(ll, n->list); +} diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c index a36ec68c0..8fe9072b2 100644 --- a/src/cmd/gc/const.c +++ b/src/cmd/gc/const.c @@ -103,6 +103,8 @@ convlit1(Node **np, Type *t, int explicit) case ORSH: convlit1(&n->left, t, explicit && isideal(n->left->type)); t = n->left->type; + if(t != T && t->etype == TIDEAL && n->val.ctype != CTINT) + n->val = toint(n->val); if(t != T && !isint[t->etype]) { yyerror("invalid operation: %#N (shift of type %T)", n, t); t = T; @@ -514,6 +516,8 @@ evconst(Node *n) n->right = nr; if(nr->type && (issigned[nr->type->etype] || !isint[nr->type->etype])) goto illegal; + nl->val = toint(nl->val); + nr->val = toint(nr->val); break; } diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 99af18d9f..78c676346 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -188,6 +188,7 @@ declare(Node *n, int ctxt) else if(n->op == ONAME) gen = ++vargen; pushdcl(s); + n->curfn = curfn; } if(ctxt == PAUTO) n->xoffset = BADWIDTH; @@ -524,6 +525,30 @@ colas(NodeList *left, NodeList *right) } /* + * declare the arguments in an + * interface field declaration. + */ +void +ifacedcl(Node *n) +{ + if(n->op != ODCLFIELD || n->right == N) + fatal("ifacedcl"); + + dclcontext = PAUTO; + markdcl(); + funcdepth++; + n->outer = curfn; + curfn = n; + funcargs(n->right); + + // funcbody is normally called after the parser has + // seen the body of a function but since an interface + // field declaration does not have a body, we must + // call it now to pop the current declaration context. + funcbody(n); +} + +/* * declare the function proper * and declare the arguments. * called in extern-declaration context @@ -1226,9 +1251,6 @@ funccompile(Node *n, int isclosure) if(curfn) fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym); - curfn = n; - typechecklist(n->nbody, Etop); - curfn = nil; stksize = 0; dclcontext = PAUTO; diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index 8ad6c437d..0b6f5bbd8 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -59,6 +59,8 @@ allocparams(void) fatal("bad width"); stksize += w; stksize = rnd(stksize, n->type->align); + if(thechar == '5') + stksize = rnd(stksize, widthptr); n->xoffset = -stksize; } lineno = lno; @@ -698,6 +700,8 @@ tempname(Node *n, Type *t) w = t->width; stksize += w; stksize = rnd(stksize, t->align); + if(thechar == '5') + stksize = rnd(stksize, widthptr); n->xoffset = -stksize; n->pun = anyregalloc(); } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 359881e11..f5c0443f8 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -254,6 +254,7 @@ struct Node Node* ntype; Node* defn; Node* pack; // real package for import . names + Node* curfn; // function for local variables // ONAME func param with PHEAP Node* heapaddr; // temp holding heap address of param @@ -517,15 +518,16 @@ enum enum { - Etop = 1<<1, // evaluated at statement level - Erv = 1<<2, // evaluated in value context + Etop = 1<<1, // evaluated at statement level + Erv = 1<<2, // evaluated in value context Etype = 1<<3, - Ecall = 1<<4, // call-only expressions are ok + Ecall = 1<<4, // call-only expressions are ok Efnstruct = 1<<5, // multivalue function returns are ok Eiota = 1<<6, // iota is ok Easgn = 1<<7, // assigning to expression Eindir = 1<<8, // indirecting through expression Eaddr = 1<<9, // taking address of expression + Eproc = 1<<10, // inside a go statement }; #define BITS 5 @@ -815,8 +817,9 @@ int bset(Bits a, uint n); */ Node* closurebody(NodeList *body); void closurehdr(Node *ntype); -void typecheckclosure(Node *func); +void typecheckclosure(Node *func, int top); Node* walkclosure(Node *func, NodeList **init); +void walkcallclosure(Node *n, NodeList **init); /* * const.c @@ -870,6 +873,7 @@ void funcbody(Node *n); void funccompile(Node *n, int isclosure); void funchdr(Node *n); Type* functype(Node *this, NodeList *in, NodeList *out); +void ifacedcl(Node *n); int isifacemethod(Type *f); void markdcl(void); Node* methodname(Node *n, Type *t); @@ -1209,6 +1213,7 @@ EXTERN Prog* continpc; EXTERN Prog* breakpc; EXTERN Prog* pc; EXTERN Prog* firstpc; +EXTERN Prog* retpc; EXTERN Node* nodfp; @@ -1222,6 +1227,7 @@ void cgen_callinter(Node *n, Node *res, int proc); void cgen_ret(Node *n); void clearfat(Node *n); void compile(Node*); +void defframe(Prog*); int dgostringptr(Sym*, int off, char *str); int dgostrlitptr(Sym*, int off, Strlit*); int dstringptr(Sym *s, int off, char *str); diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 7adfd002a..fdaab4fa4 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -1380,6 +1380,7 @@ interfacedcl: new_name indcl { $$ = nod(ODCLFIELD, $1, $2); + ifacedcl($$); } | packname { diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c index af4eb0336..8818db08c 100644 --- a/src/cmd/gc/init.c +++ b/src/cmd/gc/init.c @@ -182,11 +182,14 @@ fninit(NodeList *n) // (11) a = nod(ORETURN, N, N); r = list(r, a); - exportsym(fn->nname); fn->nbody = r; funcbody(fn); + + curfn = fn; typecheck(&fn, Etop); + typechecklist(r, Etop); + curfn = nil; funccompile(fn, 0); } diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 04dd0d5b9..5e2f73fc5 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -235,13 +235,14 @@ main(int argc, char *argv[]) if(debug['f']) frame(1); - // Process top-level declarations in three phases. + // Process top-level declarations in four phases. // Phase 1: const, type, and names and types of funcs. // This will gather all the information about types // and methods but doesn't depend on any of it. // Phase 2: Variable assignments. // To check interface assignments, depends on phase 1. - // Phase 3: Function bodies. + // Phase 3: Type check function bodies. + // Phase 4: Compile function bodies. defercheckwidth(); for(l=xtop; l; l=l->next) if(l->n->op != ODCL && l->n->op != OAS) @@ -251,17 +252,28 @@ main(int argc, char *argv[]) typecheck(&l->n, Etop); resumetypecopy(); resumecheckwidth(); + + for(l=xtop; l; l=l->next) + if(l->n->op == ODCLFUNC) { + curfn = l->n; + typechecklist(l->n->nbody, Etop); + } + curfn = nil; + for(l=xtop; l; l=l->next) if(l->n->op == ODCLFUNC) funccompile(l->n, 0); + if(nerrors == 0) fninit(xtop); + while(closures) { l = closures; closures = nil; for(; l; l=l->next) funccompile(l->n, 1); } + dclchecks(); if(nerrors) diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index 9f4b7b318..f34fc76c8 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -284,6 +284,7 @@ stringsym(char *s, int len) off = dsname(sym, off, s+n, m); } off = duint8(sym, off, 0); // terminating NUL for runtime + off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment ggloblsym(sym, off, 1); text(); diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c new file mode 100644 index 000000000..9bd845dde --- /dev/null +++ b/src/cmd/gc/pgen.c @@ -0,0 +1,119 @@ +// Copyright 2011 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. + +#undef EXTERN +#define EXTERN +#include "gg.h" +#include "opt.h" + +void +compile(Node *fn) +{ + Plist *pl; + Node nod1, *n; + Prog *ptxt; + int32 lno; + Type *t; + Iter save; + + if(newproc == N) { + newproc = sysfunc("newproc"); + deferproc = sysfunc("deferproc"); + deferreturn = sysfunc("deferreturn"); + panicindex = sysfunc("panicindex"); + panicslice = sysfunc("panicslice"); + throwreturn = sysfunc("throwreturn"); + } + + if(fn->nbody == nil) + return; + + // set up domain for labels + clearlabels(); + + lno = setlineno(fn); + + curfn = fn; + dowidth(curfn->type); + + if(curfn->type->outnamed) { + // add clearing of the output parameters + t = structfirst(&save, getoutarg(curfn->type)); + while(t != T) { + if(t->nname != N) { + n = nod(OAS, t->nname, N); + typecheck(&n, Etop); + curfn->nbody = concat(list1(n), curfn->nbody); + } + t = structnext(&save); + } + } + + hasdefer = 0; + walk(curfn); + if(nerrors != 0 || isblank(curfn->nname)) + goto ret; + + allocparams(); + + continpc = P; + breakpc = P; + + pl = newplist(); + pl->name = curfn->nname; + + setlineno(curfn); + + nodconst(&nod1, types[TINT32], 0); + ptxt = gins(ATEXT, curfn->nname, &nod1); + afunclit(&ptxt->from); + + ginit(); + genlist(curfn->enter); + + retpc = nil; + if(hasdefer || curfn->exit) { + Prog *p1; + + p1 = gjmp(nil); + retpc = gjmp(nil); + patch(p1, pc); + } + + genlist(curfn->nbody); + gclean(); + checklabels(); + if(nerrors != 0) + goto ret; + if(curfn->endlineno) + lineno = curfn->endlineno; + + if(curfn->type->outtuple != 0) + ginscall(throwreturn, 0); + + if(retpc) + patch(retpc, pc); + ginit(); + if(hasdefer) + ginscall(deferreturn, 0); + if(curfn->exit) + genlist(curfn->exit); + gclean(); + if(nerrors != 0) + goto ret; + pc->as = ARET; // overwrite AEND + pc->lineno = lineno; + + if(!debug['N'] || debug['R'] || debug['P']) { + regopt(ptxt); + } + + defframe(ptxt); + + if(debug['f']) + frame(0); + +ret: + lineno = lno; +} diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index be96a1477..eb7ef31ec 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -173,10 +173,10 @@ initfix(NodeList *l) /* * from here down is the walk analysis - * of composit literals. + * of composite literals. * most of the work is to generate * data statements for the constant - * part of the composit literal. + * part of the composite literal. */ static void structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init); diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 326a5ba74..4c0819cd8 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -3170,7 +3170,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) dumplist("genwrapper body", fn->nbody); funcbody(fn); + curfn = fn; typecheck(&fn, Etop); + typechecklist(fn->nbody, Etop); + curfn = nil; funccompile(fn, 0); } diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 9aaf3e6ef..44d08352d 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -29,8 +29,8 @@ static void typecheckfunc(Node*); static void checklvalue(Node*, char*); static void checkassign(Node*); static void checkassignlist(NodeList*); -static void stringtoarraylit(Node**); -static Node* resolve(Node*); +static void stringtoarraylit(Node**); +static Node* resolve(Node*); static Type* getforwtype(Node*); /* @@ -780,7 +780,7 @@ reswitch: n = r; goto reswitch; } - typecheck(&n->left, Erv | Etype | Ecall); + typecheck(&n->left, Erv | Etype | Ecall |(top&Eproc)); l = n->left; if(l->op == ONAME && l->etype != 0) { if(n->isddd && l->etype != OAPPEND) @@ -794,7 +794,7 @@ reswitch: defaultlit(&n->left, T); l = n->left; if(l->op == OTYPE) { - if(n->isddd) + if(n->isddd || l->type->bound == -100) yyerror("invalid use of ... in type conversion", l); // pick off before type-checking arguments ok |= Erv; @@ -822,7 +822,13 @@ reswitch: case ODOTMETH: n->op = OCALLMETH; - typecheckaste(OCALL, n->left, 0, getthisx(t), list1(l->left), "method receiver"); + // typecheckaste was used here but there wasn't enough + // information further down the call chain to know if we + // were testing a method receiver for unexported fields. + // It isn't necessary, so just do a sanity check. + tp = getthisx(t)->type->type; + if(l->left == N || !eqtype(l->left->type, tp)) + fatal("method receiver"); break; default: @@ -1021,9 +1027,9 @@ reswitch: // copy([]byte, string) if(isslice(n->left->type) && n->right->type->etype == TSTRING) { - if (n->left->type->type ==types[TUINT8]) - goto ret; - yyerror("arguments to copy have different element types: %lT and string", n->left->type); + if (n->left->type->type == types[TUINT8]) + goto ret; + yyerror("arguments to copy have different element types: %lT and string", n->left->type); goto error; } @@ -1211,7 +1217,7 @@ reswitch: case OCLOSURE: ok |= Erv; - typecheckclosure(n); + typecheckclosure(n, top); if(n->type == T) goto error; goto ret; @@ -1240,11 +1246,15 @@ reswitch: goto ret; case ODEFER: - case OPROC: ok |= Etop; typecheck(&n->left, Etop); goto ret; + case OPROC: + ok |= Etop; + typecheck(&n->left, Etop|Eproc); + goto ret; + case OFOR: ok |= Etop; typechecklist(n->ninit, Etop); @@ -2159,7 +2169,9 @@ addrescapes(Node *n) if(n->noescape) break; switch(n->class) { - case PAUTO: + case PPARAMREF: + addrescapes(n->defn); + break; case PPARAM: case PPARAMOUT: // if func param, need separate temporary @@ -2167,16 +2179,17 @@ addrescapes(Node *n) // the function type has already been checked // (we're in the function body) // so the param already has a valid xoffset. - if(n->class == PPARAM || n->class == PPARAMOUT) { - // expression to refer to stack copy - n->stackparam = nod(OPARAM, n, N); - n->stackparam->type = n->type; - n->stackparam->addable = 1; - if(n->xoffset == BADWIDTH) - fatal("addrescapes before param assignment"); - n->stackparam->xoffset = n->xoffset; - n->xoffset = 0; - } + + // expression to refer to stack copy + n->stackparam = nod(OPARAM, n, N); + n->stackparam->type = n->type; + n->stackparam->addable = 1; + if(n->xoffset == BADWIDTH) + fatal("addrescapes before param assignment"); + n->stackparam->xoffset = n->xoffset; + n->xoffset = 0; + // fallthrough + case PAUTO: n->class |= PHEAP; n->addable = 0; @@ -2189,7 +2202,9 @@ addrescapes(Node *n) snprint(buf, sizeof buf, "&%S", n->sym); n->heapaddr->sym = lookup(buf); n->heapaddr->class = PHEAP-1; // defer tempname to allocparams - curfn->dcl = list(curfn->dcl, n->heapaddr); + n->heapaddr->ullman = 1; + n->curfn->dcl = list(n->curfn->dcl, n->heapaddr); + break; } break; diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index b3b400556..ccc65ff21 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -66,6 +66,7 @@ walk(Node *fn) int lno; curfn = fn; + if(debug['W']) { snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym); dumplist(s, curfn->nbody); @@ -73,7 +74,7 @@ walk(Node *fn) if(curfn->type->outtuple) if(walkret(curfn->nbody)) yyerror("function ends without a return statement"); - typechecklist(curfn->nbody, Etop); + lno = lineno; for(l=fn->dcl; l; l=l->next) { n = l->n; @@ -468,8 +469,10 @@ walkstmt(Node **np) case OPANIC: case OEMPTY: case ORECOVER: - if(n->typecheck == 0) + if(n->typecheck == 0) { + dump("missing typecheck:", n); fatal("missing typecheck"); + } init = n->ninit; n->ninit = nil; walkexpr(&n, &init); @@ -770,8 +773,15 @@ walkexpr(Node **np, NodeList **init) t = n->left->type; if(n->list && n->list->n->op == OAS) goto ret; - walkexpr(&n->left, init); + + if(n->left->op == OCLOSURE) { + walkcallclosure(n, init); + t = n->left->type; + } else + walkexpr(&n->left, init); + walkexprlist(n->list, init); + ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init); n->list = reorder1(ll); if(isselect(n)) { @@ -1525,7 +1535,7 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init) static int fncall(Node *l, Type *rt) { - if(l->ullman >= UINF) + if(l->ullman >= UINF || l->op == OINDEXMAP) return 1; if(eqtype(l->type, rt)) return 0; diff --git a/src/cmd/godoc/spec.go b/src/cmd/godoc/spec.go index f8b95e387..d863ca0d8 100644 --- a/src/cmd/godoc/spec.go +++ b/src/cmd/godoc/spec.go @@ -99,7 +99,8 @@ func (p *ebnfParser) parseTerm() bool { case token.STRING: p.next() - if p.tok == token.ELLIPSIS { + const ellipsis = "…" // U+2026, the horizontal ellipsis character + if p.tok == token.ILLEGAL && p.lit == ellipsis { p.next() p.expect(token.STRING) } @@ -157,7 +158,7 @@ func (p *ebnfParser) parse(fset *token.FileSet, out io.Writer, src []byte) { p.out = out p.src = src p.file = fset.AddFile("", fset.Base(), len(src)) - p.scanner.Init(p.file, src, p, 0) + p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars) p.next() // initializes pos, tok, lit // process source diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go index 4f7e923e3..ba2061a00 100644 --- a/src/cmd/gofix/main.go +++ b/src/cmd/gofix/main.go @@ -248,17 +248,5 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) { f1.Write(b1) f2.Write(b2) - diffcmd, err := exec.LookPath("diff") - if err != nil { - return nil, err - } - - c, err := exec.Run(diffcmd, []string{"diff", f1.Name(), f2.Name()}, nil, "", - exec.DevNull, exec.Pipe, exec.MergeWithStdout) - if err != nil { - return nil, err - } - defer c.Close() - - return ioutil.ReadAll(c.Stdout) + return exec.Command("diff", f1.Name(), f2.Name()).CombinedOutput() } diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 5dd801d90..16bcd3c4d 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -245,14 +245,14 @@ func gofmtMain() { func diff(b1, b2 []byte) (data []byte, err os.Error) { f1, err := ioutil.TempFile("", "gofmt") if err != nil { - return nil, err + return } defer os.Remove(f1.Name()) defer f1.Close() f2, err := ioutil.TempFile("", "gofmt") if err != nil { - return nil, err + return } defer os.Remove(f2.Name()) defer f2.Close() @@ -260,17 +260,5 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) { f1.Write(b1) f2.Write(b2) - diffcmd, err := exec.LookPath("diff") - if err != nil { - return nil, err - } - - c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()}, - nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout) - if err != nil { - return nil, err - } - defer c.Close() - - return ioutil.ReadAll(c.Stdout) + return exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput() } diff --git a/src/cmd/goinstall/doc.go b/src/cmd/goinstall/doc.go index 15845b574..13c37d0a2 100644 --- a/src/cmd/goinstall/doc.go +++ b/src/cmd/goinstall/doc.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. /* - Goinstall is an experiment in automatic package installation. It installs packages, possibly downloading them from the internet. It maintains a list of public Go packages at http://godashboard.appspot.com/package. @@ -100,5 +99,59 @@ Instead, it invokes "make install" after locating the package sources. For local packages without a Makefile and all remote packages, goinstall creates and uses a temporary Makefile constructed from the import path and the list of Go files in the package. + + +The GOPATH Environment Variable + +GOPATH may be set to a colon-separated list of paths inside which Go code, +package objects, and executables may be found. + +Set a GOPATH to use goinstall to build and install your own code and +external libraries outside of the Go tree (and to avoid writing Makefiles). + +The top-level directory structure of a GOPATH is prescribed: + +The 'src' directory is for source code. The directory naming inside 'src' +determines the package import path or executable name. + +The 'pkg' directory is for package objects. Like the Go tree, package objects +are stored inside a directory named after the target operating system and +processor architecture ('pkg/$GOOS_$GOARCH'). +A package whose source is located at '$GOPATH/src/foo/bar' would be imported +as 'foo/bar' and installed as '$GOPATH/pkg/$GOOS_$GOARCH/foo/bar.a'. + +The 'bin' directory is for executable files. +Goinstall installs program binaries using the name of the source folder. +A binary whose source is at 'src/foo/qux' would be built and installed to +'$GOPATH/bin/qux'. (Note 'bin/qux', not 'bin/foo/qux' - this is such that +you can put the bin directory in your PATH.) + +Here's an example directory layout: + + GOPATH=/home/user/gocode + + /home/user/gocode/ + src/foo/ + bar/ (go code in package bar) + qux/ (go code in package main) + bin/qux (executable file) + pkg/linux_amd64/foo/bar.a (object file) + +Run 'goinstall foo/bar' to build and install the package 'foo/bar' +(and its dependencies). +Goinstall will search each GOPATH (in order) for 'src/foo/bar'. +If the directory cannot be found, goinstall will attempt to fetch the +source from a remote repository and write it to the 'src' directory of the +first GOPATH (or $GOROOT/src/pkg if GOPATH is not set). + +Goinstall recognizes relative and absolute paths (paths beginning with / or .). +The following commands would build our example packages: + + goinstall /home/user/gocode/src/foo/bar # build and install foo/bar + cd /home/user/gocode/src/foo + goinstall ./bar # build and install foo/bar (again) + cd qux + goinstall . # build and install foo/qux + */ package documentation diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go index 7dad596ab..2edf85efd 100644 --- a/src/cmd/goinstall/download.go +++ b/src/cmd/goinstall/download.go @@ -31,23 +31,36 @@ func maybeReportToDashboard(path string) { } } -var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`) -var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`) -var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`) -var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`) +var vcsPatterns = map[string]*regexp.Regexp{ + "googlecode": regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`), + "github": regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), + "bitbucket": regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`), + "launchpad": regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`), +} + +// isRemote returns true if the provided package path +// matches one of the supported remote repositories. +func isRemote(pkg string) bool { + for _, r := range vcsPatterns { + if r.MatchString(pkg) { + return true + } + } + return false +} // download checks out or updates pkg from the remote server. func download(pkg, srcDir string) os.Error { if strings.Contains(pkg, "..") { return os.ErrorString("invalid path (contains ..)") } - if m := bitbucket.FindStringSubmatch(pkg); m != nil { + if m := vcsPatterns["bitbucket"].FindStringSubmatch(pkg); m != nil { if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil { return err } return nil } - if m := googlecode.FindStringSubmatch(pkg); m != nil { + if m := vcsPatterns["googlecode"].FindStringSubmatch(pkg); m != nil { var v *vcs switch m[2] { case "hg": @@ -63,7 +76,7 @@ func download(pkg, srcDir string) os.Error { } return nil } - if m := github.FindStringSubmatch(pkg); m != nil { + if m := vcsPatterns["github"].FindStringSubmatch(pkg); m != nil { if strings.HasSuffix(m[1], ".git") { return os.ErrorString("repository " + pkg + " should not have .git suffix") } @@ -72,7 +85,7 @@ func download(pkg, srcDir string) os.Error { } return nil } - if m := launchpad.FindStringSubmatch(pkg); m != nil { + if m := vcsPatterns["launchpad"].FindStringSubmatch(pkg); m != nil { // Either lp.net/<project>[/<series>[/<path>]] // or lp.net/~<user or team>/<project>/<branch>[/<path>] if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil { diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go index 6cd92907a..721e719d2 100644 --- a/src/cmd/goinstall/main.go +++ b/src/cmd/goinstall/main.go @@ -12,7 +12,6 @@ import ( "flag" "fmt" "go/token" - "io" "io/ioutil" "os" "path/filepath" @@ -32,9 +31,8 @@ var ( argv0 = os.Args[0] errors = false parents = make(map[string]string) - root = runtime.GOROOT() visit = make(map[string]status) - logfile = filepath.Join(root, "goinstall.log") + logfile = filepath.Join(runtime.GOROOT(), "goinstall.log") installedPkgs = make(map[string]bool) allpkg = flag.Bool("a", false, "install all previously installed packages") @@ -52,14 +50,30 @@ const ( done ) +func logf(format string, args ...interface{}) { + format = "%s: " + format + args = append([]interface{}{argv0}, args...) + fmt.Fprintf(os.Stderr, format, args...) +} + +func vlogf(format string, args ...interface{}) { + if *verbose { + logf(format, args...) + } +} + +func errorf(format string, args ...interface{}) { + errors = true + logf(format, args...) +} + func main() { flag.Usage = usage flag.Parse() - if root == "" { + if runtime.GOROOT() == "" { fmt.Fprintf(os.Stderr, "%s: no $GOROOT\n", argv0) os.Exit(1) } - root += filepath.FromSlash("/src/pkg/") // special case - "unsafe" is already installed visit["unsafe"] = done @@ -88,6 +102,11 @@ func main() { usage() } for _, path := range args { + if strings.HasPrefix(path, "http://") { + errorf("'http://' used in remote path, try '%s'\n", path[7:]) + continue + } + install(path, "") } if errors { @@ -143,49 +162,44 @@ func install(pkg, parent string) { } visit[pkg] = visiting parents[pkg] = parent - if *verbose { - fmt.Println(pkg) - } + + vlogf("%s: visit\n", pkg) // Check whether package is local or remote. // If remote, download or update it. - var dir string - proot := gopath[0] // default to GOROOT - local := false - if strings.HasPrefix(pkg, "http://") { - fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:]) - errors = true + proot, pkg, err := findPackageRoot(pkg) + // Don't build the standard library. + if err == nil && proot.goroot && isStandardPath(pkg) { + if parent == "" { + errorf("%s: can not goinstall the standard library\n", pkg) + } else { + vlogf("%s: skipping standard library\n", pkg) + } + visit[pkg] = done return } - if isLocalPath(pkg) { - dir = pkg - local = true - } else if isStandardPath(pkg) { - dir = filepath.Join(root, filepath.FromSlash(pkg)) - local = true - } else { - proot = findPkgroot(pkg) - err := download(pkg, proot.srcDir()) - dir = filepath.Join(proot.srcDir(), pkg) - if err != nil { - fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err) - errors = true - visit[pkg] = done - return - } + // Download remote packages if not found or forced with -u flag. + remote := isRemote(pkg) + if remote && (err == ErrPackageNotFound || (err == nil && *update)) { + vlogf("%s: download\n", pkg) + err = download(pkg, proot.srcDir()) } + if err != nil { + errorf("%s: %v\n", pkg, err) + visit[pkg] = done + return + } + dir := filepath.Join(proot.srcDir(), pkg) // Install prerequisites. dirInfo, err := scanDir(dir, parent == "") if err != nil { - fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err) - errors = true + errorf("%s: %v\n", pkg, err) visit[pkg] = done return } if len(dirInfo.goFiles) == 0 { - fmt.Fprintf(os.Stderr, "%s: %s: package has no files\n", argv0, pkg) - errors = true + errorf("%s: package has no files\n", pkg) visit[pkg] = done return } @@ -198,22 +212,16 @@ func install(pkg, parent string) { // Install this package. if !errors { isCmd := dirInfo.pkgName == "main" - if err := domake(dir, pkg, proot, local, isCmd); err != nil { - fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err) - errors = true - } else if !local && *logPkgs { - // mark this package as installed in $GOROOT/goinstall.log + if err := domake(dir, pkg, proot, isCmd); err != nil { + errorf("installing: %v\n", err) + } else if remote && *logPkgs { + // mark package as installed in $GOROOT/goinstall.log logPackage(pkg) } } visit[pkg] = done } -// Is this a local path? /foo ./foo ../foo . .. -func isLocalPath(s string) bool { - const sep = string(filepath.Separator) - return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".." -} // Is this a standard package path? strings container/vector etc. // Assume that if the first element has a dot, it's a domain name @@ -237,40 +245,22 @@ func quietRun(dir string, stdin []byte, cmd ...string) os.Error { } // genRun implements run and quietRun. -func genRun(dir string, stdin []byte, cmd []string, quiet bool) os.Error { - bin, err := exec.LookPath(cmd[0]) +func genRun(dir string, stdin []byte, arg []string, quiet bool) os.Error { + cmd := exec.Command(arg[0], arg[1:]...) + cmd.Stdin = bytes.NewBuffer(stdin) + cmd.Dir = dir + vlogf("%s: %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " ")) + out, err := cmd.CombinedOutput() if err != nil { - return err - } - p, err := exec.Run(bin, cmd, os.Environ(), dir, exec.Pipe, exec.Pipe, exec.MergeWithStdout) - if *verbose { - fmt.Fprintf(os.Stderr, "%s: %s; %s %s\n", argv0, dir, bin, strings.Join(cmd[1:], " ")) - } - if err != nil { - return err - } - go func() { - p.Stdin.Write(stdin) - p.Stdin.Close() - }() - var buf bytes.Buffer - io.Copy(&buf, p.Stdout) - io.Copy(&buf, p.Stdout) - w, err := p.Wait(0) - p.Close() - if err != nil { - return err - } - if !w.Exited() || w.ExitStatus() != 0 { if !quiet || *verbose { if dir != "" { dir = "cd " + dir + "; " } - fmt.Fprintf(os.Stderr, "%s: === %s%s\n", argv0, dir, strings.Join(cmd, " ")) - os.Stderr.Write(buf.Bytes()) - fmt.Fprintf(os.Stderr, "--- %s\n", w) + fmt.Fprintf(os.Stderr, "%s: === %s%s\n", cmd.Path, dir, strings.Join(cmd.Args, " ")) + os.Stderr.Write(out) + fmt.Fprintf(os.Stderr, "--- %s\n", err) } - return os.ErrorString("running " + cmd[0] + ": " + w.String()) + return os.ErrorString("running " + arg[0] + ": " + err.String()) } return nil } diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go index b2ca82b46..0c44481d7 100644 --- a/src/cmd/goinstall/make.go +++ b/src/cmd/goinstall/make.go @@ -14,26 +14,14 @@ import ( ) // domake builds the package in dir. -// If local is false, the package was copied from an external system. -// For non-local packages or packages without Makefiles, // domake generates a standard Makefile and passes it // to make on standard input. -func domake(dir, pkg string, root *pkgroot, local, isCmd bool) (err os.Error) { - needMakefile := true - if local { - _, err := os.Stat(dir + "/Makefile") - if err == nil { - needMakefile = false - } - } - cmd := []string{"gomake"} - var makefile []byte - if needMakefile { - if makefile, err = makeMakefile(dir, pkg, root, isCmd); err != nil { - return err - } - cmd = append(cmd, "-f-") +func domake(dir, pkg string, root *pkgroot, isCmd bool) (err os.Error) { + makefile, err := makeMakefile(dir, pkg, root, isCmd) + if err != nil { + return err } + cmd := []string{"bash", "gomake", "-f-"} if *clean { cmd = append(cmd, "clean") } @@ -51,16 +39,8 @@ func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error) targ := pkg targDir := root.pkgDir() if isCmd { - // use the last part of the package name only + // use the last part of the package name for targ _, targ = filepath.Split(pkg) - // if building the working dir use the directory name - if targ == "." { - d, err := filepath.Abs(dir) - if err != nil { - return nil, os.NewError("finding path: " + err.String()) - } - _, targ = filepath.Split(d) - } targDir = root.binDir() } dirInfo, err := scanDir(dir, isCmd) diff --git a/src/cmd/goinstall/path.go b/src/cmd/goinstall/path.go index 1153e0471..b8c392931 100644 --- a/src/cmd/goinstall/path.go +++ b/src/cmd/goinstall/path.go @@ -5,10 +5,12 @@ package main import ( + "fmt" "log" "os" "path/filepath" "runtime" + "strings" ) var ( @@ -19,6 +21,7 @@ var ( // set up gopath: parse and validate GOROOT and GOPATH variables func init() { + root := runtime.GOROOT() p, err := newPkgroot(root) if err != nil { log.Fatalf("Invalid GOROOT %q: %v", root, err) @@ -105,13 +108,42 @@ func (r *pkgroot) hasPkg(name string) bool { // TODO(adg): check object version is consistent } -// findPkgroot searches each of the gopath roots -// for the source code for the given import path. -func findPkgroot(importPath string) *pkgroot { + +var ErrPackageNotFound = os.NewError("package could not be found locally") + +// findPackageRoot takes an import or filesystem path and returns the +// root where the package source should be and the package import path. +func findPackageRoot(path string) (root *pkgroot, pkg string, err os.Error) { + if isLocalPath(path) { + if path, err = filepath.Abs(path); err != nil { + return + } + for _, r := range gopath { + rpath := r.srcDir() + string(filepath.Separator) + if !strings.HasPrefix(path, rpath) { + continue + } + root = r + pkg = path[len(rpath):] + return + } + err = fmt.Errorf("path %q not inside a GOPATH", path) + return + } + root = defaultRoot + pkg = path for _, r := range gopath { - if r.hasSrcDir(importPath) { - return r + if r.hasSrcDir(path) { + root = r + return } } - return defaultRoot + err = ErrPackageNotFound + return +} + +// Is this a local path? /foo ./foo ../foo . .. +func isLocalPath(s string) bool { + const sep = string(filepath.Separator) + return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".." } diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go index 8c81baf97..4cb3da23c 100644 --- a/src/cmd/gotest/gotest.go +++ b/src/cmd/gotest/gotest.go @@ -285,8 +285,8 @@ func doRun(argv []string, returnStdout bool) string { } cmd += `"` + v + `"` } - command = "sh" - argv = []string{"sh", "-c", cmd} + command = "bash" + argv = []string{"bash", "-c", cmd} } var err os.Error argv[0], err = exec.LookPath(argv[0]) diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go index 2dcb5234c..8ee3422e2 100644 --- a/src/cmd/hgpatch/main.go +++ b/src/cmd/hgpatch/main.go @@ -10,7 +10,6 @@ import ( "exec" "flag" "fmt" - "io" "io/ioutil" "os" "patch" @@ -333,6 +332,7 @@ func run(argv []string, input []byte) (out string, err os.Error) { err = os.EINVAL goto Error } + prog, ok := lookPathCache[argv[0]] if !ok { prog, err = exec.LookPath(argv[0]) @@ -341,40 +341,15 @@ func run(argv []string, input []byte) (out string, err os.Error) { } lookPathCache[argv[0]] = prog } - // fmt.Fprintf(os.Stderr, "%v\n", argv); - var cmd *exec.Cmd - if len(input) == 0 { - cmd, err = exec.Run(prog, argv, os.Environ(), "", exec.DevNull, exec.Pipe, exec.MergeWithStdout) - if err != nil { - goto Error - } - } else { - cmd, err = exec.Run(prog, argv, os.Environ(), "", exec.Pipe, exec.Pipe, exec.MergeWithStdout) - if err != nil { - goto Error - } - go func() { - cmd.Stdin.Write(input) - cmd.Stdin.Close() - }() - } - defer cmd.Close() - var buf bytes.Buffer - _, err = io.Copy(&buf, cmd.Stdout) - out = buf.String() - if err != nil { - cmd.Wait(0) - goto Error - } - w, err := cmd.Wait(0) - if err != nil { - goto Error + + cmd := exec.Command(prog, argv[1:]...) + if len(input) > 0 { + cmd.Stdin = bytes.NewBuffer(input) } - if !w.Exited() || w.ExitStatus() != 0 { - err = w - goto Error + bs, err := cmd.CombinedOutput() + if err == nil { + return string(bs), nil } - return Error: err = &runError{dup(argv), err} diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index ed11f5e5a..de600f555 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -529,8 +529,10 @@ find_or_diag(DWDie *die, char* name) { DWDie *r; r = find(die, name); - if (r == nil) + if (r == nil) { diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name); + errorexit(); + } return r; } @@ -613,7 +615,7 @@ putattr(int form, int cls, vlong value, char *data) case DW_FORM_ref_addr: // reference to a DIE in the .info section if (data == nil) { - diag("null dwarf reference"); + diag("dwarf: null reference"); LPUT(0); // invalid dwarf, gdb will complain. } else { if (((DWDie*)data)->offs == 0) @@ -631,7 +633,7 @@ putattr(int form, int cls, vlong value, char *data) case DW_FORM_strp: // string case DW_FORM_indirect: // (see Section 7.5.3) default: - diag("Unsupported atribute form %d / class %d", form, cls); + diag("dwarf: unsupported attribute form %d / class %d", form, cls); errorexit(); } } @@ -823,7 +825,7 @@ decode_inuxi(uchar* p, int sz) inuxi = inuxi8; break; default: - diag("decode inuxi %d", sz); + diag("dwarf: decode inuxi %d", sz); errorexit(); } for (i = 0; i < sz; i++) @@ -1013,7 +1015,7 @@ defgotype(Sym *gotype) return find_or_diag(&dwtypes, "<unspecified>"); if (strncmp("type.", gotype->name, 5) != 0) { - diag("Type name doesn't start with \".type\": %s", gotype->name); + diag("dwarf: type name doesn't start with \".type\": %s", gotype->name); return find_or_diag(&dwtypes, "<unspecified>"); } name = gotype->name + 5; // could also decode from Type.string @@ -1164,7 +1166,7 @@ defgotype(Sym *gotype) break; default: - diag("definition of unknown kind %d: %s", kind, gotype->name); + diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name); die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name); newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>")); } @@ -1513,12 +1515,12 @@ decodez(char *s) ss = s + 1; // first is 0 while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) { if (o < 0 || o >= ftabsize) { - diag("corrupt z entry"); + diag("dwarf: corrupt z entry"); return 0; } f = ftab[o]; if (f == nil) { - diag("corrupt z entry"); + diag("dwarf: corrupt z entry"); return 0; } len += strlen(f) + 1; // for the '/' @@ -1630,11 +1632,11 @@ checknesting(void) int i; if (includetop < 0) { - diag("corrupt z stack"); + diag("dwarf: corrupt z stack"); errorexit(); } if (includetop >= nelem(includestack)) { - diag("nesting too deep"); + diag("dwarf: nesting too deep"); for (i = 0; i < nelem(includestack); i++) diag("\t%s", histfile[includestack[i].file]); errorexit(); @@ -1660,7 +1662,7 @@ inithist(Auto *a) // We have a new history. They are guaranteed to come completely // at the beginning of the compilation unit. if (a->aoffset != 1) { - diag("stray 'z' with offset %d", a->aoffset); + diag("dwarf: stray 'z' with offset %d", a->aoffset); return 0; } @@ -1915,7 +1917,7 @@ writelines(void) continue; if (unitstart < 0) { - diag("reachable code before seeing any history: %P", s->text); + diag("dwarf: reachable code before seeing any history: %P", s->text); continue; } @@ -1932,7 +1934,7 @@ writelines(void) for(q = s->text; q != P; q = q->link) { lh = searchhist(q->line); if (lh == nil) { - diag("corrupt history or bad absolute line: %P", q); + diag("dwarf: corrupt history or bad absolute line: %P", q); continue; } @@ -2066,7 +2068,7 @@ writeframes(void) // 4 is to exclude the length field. pad = CIERESERVE + frameo + 4 - cpos(); if (pad < 0) { - diag("CIERESERVE too small by %lld bytes.", -pad); + diag("dwarf: CIERESERVE too small by %lld bytes.", -pad); errorexit(); } strnput("", pad); @@ -2296,6 +2298,9 @@ dwarfemitdebugsections(void) vlong infoe; DWDie* die; + if(debug['w']) // disable dwarf + return; + // For diagnostic messages. newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, strlen("dwtypes"), "dwtypes"); @@ -2348,11 +2353,11 @@ dwarfemitdebugsections(void) seek(cout, infoo, 0); writeinfo(); if (fwdcount > 0) { - diag("unresolved references after first dwarf info pass"); + diag("dwarf: unresolved references after first dwarf info pass"); errorexit(); } if (infoe != cpos()) { - diag("inconsistent second dwarf info pass"); + diag("dwarf: inconsistent second dwarf info pass"); errorexit(); } } @@ -2401,6 +2406,9 @@ vlong elfstrdbg[NElfStrDbg]; void dwarfaddshstrings(Sym *shstrtab) { + if(debug['w']) // disable dwarf + return; + elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev"); elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges"); elfstrdbg[ElfStrDebugFrame] = addstring(shstrtab, ".debug_frame"); @@ -2420,6 +2428,9 @@ dwarfaddelfheaders(void) { ElfShdr *sh; + if(debug['w']) // disable dwarf + return; + sh = newElfShdr(elfstrdbg[ElfStrDebugAbbrev]); sh->type = SHT_PROGBITS; sh->off = abbrevo; @@ -2488,6 +2499,9 @@ dwarfaddmachoheaders(void) vlong fakestart; int nsect; + if(debug['w']) // disable dwarf + return; + // Zero vsize segments won't be loaded in memory, even so they // have to be page aligned in the file. fakestart = abbrevo & ~0xfff; @@ -2562,6 +2576,9 @@ dwarfaddmachoheaders(void) void dwarfaddpeheaders(void) { + if(debug['w']) // disable dwarf + return; + newPEDWARFSection(".debug_abbrev", abbrevsize); newPEDWARFSection(".debug_line", linesize); newPEDWARFSection(".debug_frame", framesize); diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c index d8b0a6fc2..d6aa267c4 100644 --- a/src/cmd/ld/ldpe.c +++ b/src/cmd/ld/ldpe.c @@ -147,7 +147,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn) goto bad; obj->sect[i].size = obj->sect[i].sh.SizeOfRawData; obj->sect[i].name = (char*)obj->sect[i].sh.Name; - // TODO return error if found .cormeta .rsrc + // TODO return error if found .cormeta } // load string table Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0); @@ -222,6 +222,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn) etextp = s; } sect->sym = s; + if(strcmp(sect->name, ".rsrc") == 0) + setpersrc(sect->sym); } // load relocations @@ -259,6 +261,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn) rp->type = D_PCREL; rp->add = 0; break; + case IMAGE_REL_I386_DIR32NB: case IMAGE_REL_I386_DIR32: rp->type = D_ADDR; // load addend from image diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index cd4608085..f69f5a35d 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -202,6 +202,7 @@ void addexport(void); void dostkcheck(void); void undef(void); void doweak(void); +void setpersrc(Sym*); int pathchar(void); void* mal(uint32); diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c index 01349bb10..0b12ac17b 100644 --- a/src/cmd/ld/macho.c +++ b/src/cmd/ld/macho.c @@ -17,6 +17,14 @@ static MachoSeg seg[16]; static MachoDebug xdebug[16]; static int nload, mload, nseg, ndebug, nsect; +// Amount of space left for adding load commands +// that refer to dynamic libraries. Because these have +// to go in the Mach-O header, we can't just pick a +// "big enough" header size. The initial header is +// one page, the non-dynamic library stuff takes +// up about 1300 bytes; we overestimate that as 2k. +static int load_budget = INITIAL_MACHO_HEADR - 2*1024; + void machoinit(void) { @@ -267,6 +275,17 @@ domacho(void) void machoadddynlib(char *lib) { + // Will need to store the library name rounded up + // and 24 bytes of header metadata. If not enough + // space, grab another page of initial space at the + // beginning of the output file. + load_budget -= (strlen(lib)+7)/8*8 + 24; + if(load_budget < 0) { + HEADR += 4096; + INITTEXT += 4096; + load_budget += 4096; + } + if(ndylib%32 == 0) { dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]); if(dylib == nil) { @@ -463,8 +482,8 @@ asmbmacho(void) } a = machowrite(); - if(a > MACHORESERVE) - diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE); + if(a > HEADR) + diag("HEADR too small: %d > %d", a, HEADR); } vlong diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h index 4cc7edc80..f55104150 100644 --- a/src/cmd/ld/macho.h +++ b/src/cmd/ld/macho.h @@ -63,7 +63,7 @@ void machoinit(void); * for Header, PHeaders, and SHeaders. * May waste some. */ -#define MACHORESERVE 3*1024 +#define INITIAL_MACHO_HEADR 4*1024 enum { MACHO_CPU_AMD64 = (1<<24)|7, diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c index 1c0c66538..91e15d343 100644 --- a/src/cmd/ld/pe.c +++ b/src/cmd/ld/pe.c @@ -34,6 +34,8 @@ static char dosstub[] = 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static Sym *rsrcsym; + static char symnames[256]; static int nextsymoff; @@ -459,6 +461,48 @@ addsymtable(void) } void +setpersrc(Sym *sym) +{ + if(rsrcsym != nil) + diag("too many .rsrc sections"); + + rsrcsym = sym; +} + +void +addpersrc(void) +{ + IMAGE_SECTION_HEADER *h; + uchar *p; + uint32 val; + Reloc *r; + + if(rsrcsym == nil) + return; + + h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0); + h->Characteristics = IMAGE_SCN_MEM_READ| + IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; + // relocation + for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) { + p = rsrcsym->p + r->off; + val = h->VirtualAddress + r->add; + // 32-bit little-endian + p[0] = val; + p[1] = val>>8; + p[2] = val>>16; + p[3] = val>>24; + } + ewrite(cout, rsrcsym->p, rsrcsym->size); + strnput("", h->SizeOfRawData - rsrcsym->size); + cflush(); + + // update data directory + dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress; + dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize; +} + +void asmbpe(void) { IMAGE_SECTION_HEADER *t, *d; @@ -492,7 +536,9 @@ asmbpe(void) addexports(nextfileoff); addsymtable(); - + + addpersrc(); + fh.NumberOfSections = nsect; fh.TimeDateStamp = time(0); fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED| diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h index 2180fb88c..7aa938829 100644 --- a/src/cmd/ld/pe.h +++ b/src/cmd/ld/pe.h @@ -175,3 +175,5 @@ typedef struct { uint32 NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[16]; } PE64_IMAGE_OPTIONAL_HEADER; + +void setpersrc(Sym *sym); diff --git a/src/libmach/darwin.c b/src/libmach/darwin.c index d44fd5612..c443a4fba 100644 --- a/src/libmach/darwin.c +++ b/src/libmach/darwin.c @@ -170,7 +170,7 @@ me(kern_return_t r) // handles to tasks (processes), and handles to threads within a // process. All of them are small integers. // -// To accomodate Mach, we employ a clumsy hack: in this interface, +// To accommodate Mach, we employ a clumsy hack: in this interface, // if you pass in a positive number, that's a process id. // If you pass in a negative number, that identifies a thread that // has been previously returned by procthreadpids (it indexes diff --git a/src/pkg/Makefile b/src/pkg/Makefile index c84da57f2..fc5548e98 100644 --- a/src/pkg/Makefile +++ b/src/pkg/Makefile @@ -74,7 +74,6 @@ DIRS=\ encoding/binary\ encoding/git85\ encoding/hex\ - encoding/line\ encoding/pem\ exec\ exp/datafmt\ @@ -117,6 +116,7 @@ DIRS=\ io/ioutil\ json\ log\ + mail\ math\ mime\ mime/multipart\ diff --git a/src/pkg/asn1/marshal.go b/src/pkg/asn1/marshal.go index 771ac2824..7212c91ef 100644 --- a/src/pkg/asn1/marshal.go +++ b/src/pkg/asn1/marshal.go @@ -458,11 +458,12 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) return marshalField(out, v.Elem(), params) } + if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { + return + } + if v.Type() == rawValueType { rv := v.Interface().(RawValue) - if rv.Class == 0 && rv.Tag == 0 && len(rv.Bytes) == 0 && params.optional { - return - } err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}) if err != nil { return @@ -471,10 +472,6 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) return } - if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { - return - } - tag, isCompound, ok := getUniversalType(v.Type()) if !ok { err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} diff --git a/src/pkg/asn1/marshal_test.go b/src/pkg/asn1/marshal_test.go index cd165d203..a9517634d 100644 --- a/src/pkg/asn1/marshal_test.go +++ b/src/pkg/asn1/marshal_test.go @@ -45,6 +45,10 @@ type printableStringTest struct { A string "printable" } +type optionalRawValueTest struct { + A RawValue "optional" +} + type testSET []int func setPST(t *time.Time) *time.Time { @@ -102,6 +106,7 @@ var marshalTests = []marshalTest{ "7878787878787878787878787878787878787878787878787878787878787878", }, {ia5StringTest{"test"}, "3006160474657374"}, + {optionalRawValueTest{}, "3000"}, {printableStringTest{"test"}, "3006130474657374"}, {printableStringTest{"test*"}, "30071305746573742a"}, {rawContentsStruct{nil, 64}, "3003020140"}, diff --git a/src/pkg/big/arith.go b/src/pkg/big/arith.go index df3808f5e..b9aeea968 100644 --- a/src/pkg/big/arith.go +++ b/src/pkg/big/arith.go @@ -188,7 +188,7 @@ func subVW_g(z, x []Word, y Word) (c Word) { } -func shlVW_g(z, x []Word, s Word) (c Word) { +func shlVU_g(z, x []Word, s uint) (c Word) { if n := len(z); n > 0 { ŝ := _W - s w1 := x[n-1] @@ -204,7 +204,7 @@ func shlVW_g(z, x []Word, s Word) (c Word) { } -func shrVW_g(z, x []Word, s Word) (c Word) { +func shrVU_g(z, x []Word, s uint) (c Word) { if n := len(z); n > 0 { ŝ := _W - s w1 := x[0] diff --git a/src/pkg/big/arith_386.s b/src/pkg/big/arith_386.s index 21521635b..07c07b02c 100644 --- a/src/pkg/big/arith_386.s +++ b/src/pkg/big/arith_386.s @@ -118,8 +118,8 @@ E4: CMPL BX, BP // i < n RET -// func shlVW(z, x []Word, s Word) (c Word) -TEXT ·shlVW(SB),7,$0 +// func shlVU(z, x []Word, s uint) (c Word) +TEXT ·shlVU(SB),7,$0 MOVL n+4(FP), BX // i = n SUBL $1, BX // i-- JL X8b // i < 0 (n <= 0) @@ -153,8 +153,8 @@ X8b: MOVL $0, c+28(FP) RET -// func shrVW(z, x []Word, s Word) (c Word) -TEXT ·shrVW(SB),7,$0 +// func shrVU(z, x []Word, s uint) (c Word) +TEXT ·shrVU(SB),7,$0 MOVL n+4(FP), BP SUBL $1, BP // n-- JL X9b // n < 0 (n <= 0) diff --git a/src/pkg/big/arith_amd64.s b/src/pkg/big/arith_amd64.s index c740565a7..89b65f38a 100644 --- a/src/pkg/big/arith_amd64.s +++ b/src/pkg/big/arith_amd64.s @@ -120,8 +120,8 @@ E4: CMPQ BX, R11 // i < n RET -// func shlVW(z, x []Word, s Word) (c Word) -TEXT ·shlVW(SB),7,$0 +// func shlVU(z, x []Word, s uint) (c Word) +TEXT ·shlVU(SB),7,$0 MOVL n+8(FP), BX // i = n SUBL $1, BX // i-- JL X8b // i < 0 (n <= 0) @@ -129,7 +129,7 @@ TEXT ·shlVW(SB),7,$0 // n > 0 MOVQ z+0(FP), R10 MOVQ x+16(FP), R8 - MOVQ s+32(FP), CX + MOVL s+32(FP), CX MOVQ (R8)(BX*8), AX // w1 = x[n-1] MOVQ $0, DX SHLQ CX, DX:AX // w1>>ŝ @@ -155,8 +155,8 @@ X8b: MOVQ $0, c+40(FP) RET -// func shrVW(z, x []Word, s Word) (c Word) -TEXT ·shrVW(SB),7,$0 +// func shrVU(z, x []Word, s uint) (c Word) +TEXT ·shrVU(SB),7,$0 MOVL n+8(FP), R11 SUBL $1, R11 // n-- JL X9b // n < 0 (n <= 0) @@ -164,7 +164,7 @@ TEXT ·shrVW(SB),7,$0 // n > 0 MOVQ z+0(FP), R10 MOVQ x+16(FP), R8 - MOVQ s+32(FP), CX + MOVL s+32(FP), CX MOVQ (R8), AX // w1 = x[0] MOVQ $0, DX SHRQ CX, DX:AX // w1<<ŝ diff --git a/src/pkg/big/arith_arm.s b/src/pkg/big/arith_arm.s index e4a9a962c..60abe6eaa 100644 --- a/src/pkg/big/arith_arm.s +++ b/src/pkg/big/arith_arm.s @@ -97,6 +97,7 @@ E3: RET +// func subVW(z, x []Word, y Word) (c Word) TEXT ·subVW(SB),7,$0 MOVW z+0(FP), R1 MOVW x+12(FP), R2 @@ -131,8 +132,8 @@ E4: RET -// func shlVW(z, x []Word, s Word) (c Word) -TEXT ·shlVW(SB),7,$0 +// func shlVU(z, x []Word, s uint) (c Word) +TEXT ·shlVU(SB),7,$0 MOVW n+4(FP), R5 CMP $0, R5 BEQ X7 @@ -180,7 +181,8 @@ X7: RET -TEXT ·shrVW(SB),7,$0 +// func shrVU(z, x []Word, s uint) (c Word) +TEXT ·shrVU(SB),7,$0 MOVW n+4(FP), R5 CMP $0, R5 BEQ X6 @@ -229,6 +231,7 @@ X6: RET +// func mulAddVWW(z, x []Word, y, r Word) (c Word) TEXT ·mulAddVWW(SB),7,$0 MOVW $0, R0 MOVW z+0(FP), R1 @@ -256,6 +259,7 @@ E8: RET +// func addMulVVW(z, x []Word, y Word) (c Word) TEXT ·addMulVVW(SB),7,$0 MOVW $0, R0 MOVW z+0(FP), R1 @@ -286,11 +290,13 @@ E9: RET +// divWVW(z* Word, xn Word, x []Word, y Word) (r Word) TEXT ·divWVW(SB),7,$0 // ARM has no multiword division, so use portable code. B ·divWVW_g(SB) +// func divWW(x1, x0, y Word) (q, r Word) TEXT ·divWW(SB),7,$0 // ARM has no multiword division, so use portable code. B ·divWW_g(SB) diff --git a/src/pkg/big/arith_decl.go b/src/pkg/big/arith_decl.go index c456d5f67..95fcd8b94 100644 --- a/src/pkg/big/arith_decl.go +++ b/src/pkg/big/arith_decl.go @@ -11,8 +11,8 @@ func addVV(z, x, y []Word) (c Word) func subVV(z, x, y []Word) (c Word) func addVW(z, x []Word, y Word) (c Word) func subVW(z, x []Word, y Word) (c Word) -func shlVW(z, x []Word, s Word) (c Word) -func shrVW(z, x []Word, s Word) (c Word) +func shlVU(z, x []Word, s uint) (c Word) +func shrVU(z, x []Word, s uint) (c Word) func mulAddVWW(z, x []Word, y, r Word) (c Word) func addMulVVW(z, x []Word, y Word) (c Word) func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) diff --git a/src/pkg/big/arith_test.go b/src/pkg/big/arith_test.go index 934b302df..f3e2d4735 100644 --- a/src/pkg/big/arith_test.go +++ b/src/pkg/big/arith_test.go @@ -185,6 +185,13 @@ func testFunVW(t *testing.T, msg string, f funVW, a argVW) { } +func makeFunVW(f func(z, x []Word, s uint) (c Word)) funVW { + return func(z, x []Word, s Word) (c Word) { + return f(z, x, uint(s)) + } +} + + func TestFunVW(t *testing.T) { for _, a := range sumVW { arg := a @@ -196,16 +203,20 @@ func TestFunVW(t *testing.T) { testFunVW(t, "subVW", subVW, arg) } + shlVW_g := makeFunVW(shlVU_g) + shlVW := makeFunVW(shlVU) for _, a := range lshVW { arg := a - testFunVW(t, "shlVW_g", shlVW_g, arg) - testFunVW(t, "shlVW", shlVW, arg) + testFunVW(t, "shlVU_g", shlVW_g, arg) + testFunVW(t, "shlVU", shlVW, arg) } + shrVW_g := makeFunVW(shrVU_g) + shrVW := makeFunVW(shrVU) for _, a := range rshVW { arg := a - testFunVW(t, "shrVW_g", shrVW_g, arg) - testFunVW(t, "shrVW", shrVW, arg) + testFunVW(t, "shrVU_g", shrVW_g, arg) + testFunVW(t, "shrVU", shrVW, arg) } } diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go index 74fbef48d..e66c34a83 100755 --- a/src/pkg/big/int.go +++ b/src/pkg/big/int.go @@ -8,8 +8,10 @@ package big import ( "fmt" + "io" "os" "rand" + "strings" ) // An Int represents a signed multi-precision integer. @@ -325,7 +327,7 @@ func charset(ch int) string { return lowercaseDigits[0:2] case 'o': return lowercaseDigits[0:8] - case 'd', 'v': + case 'd', 's', 'v': return lowercaseDigits[0:10] case 'x': return lowercaseDigits[0:16] @@ -374,8 +376,69 @@ func (x *Int) Format(s fmt.State, ch int) { } -// Int64 returns the int64 representation of z. -// If z cannot be represented in an int64, the result is undefined. +// scan sets z to the integer value corresponding to the longest possible prefix +// read from r representing a signed integer number in a given conversion base. +// It returns z, the actual conversion base used, and an error, if any. In the +// error case, the value of z is undefined. The syntax follows the syntax of +// integer literals in Go. +// +// The base argument must be 0 or a value from 2 through MaxBase. If the base +// is 0, the string prefix determines the actual conversion base. A prefix of +// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a +// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. +// +func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, os.Error) { + // determine sign + ch, _, err := r.ReadRune() + if err != nil { + return z, 0, err + } + neg := false + switch ch { + case '-': + neg = true + case '+': // nothing to do + default: + r.UnreadRune() + } + + // determine mantissa + z.abs, base, err = z.abs.scan(r, base) + if err != nil { + return z, base, err + } + z.neg = len(z.abs) > 0 && neg // 0 has no sign + + return z, base, nil +} + + +// Scan is a support routine for fmt.Scanner; it sets z to the value of +// the scanned number. It accepts the formats 'b' (binary), 'o' (octal), +// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal). +func (z *Int) Scan(s fmt.ScanState, ch int) os.Error { + base := 0 + switch ch { + case 'b': + base = 2 + case 'o': + base = 8 + case 'd': + base = 10 + case 'x', 'X': + base = 16 + case 's', 'v': + // let scan determine the base + default: + return os.ErrorString("Int.Scan: invalid verb") + } + _, _, err := z.scan(s, base) + return err +} + + +// Int64 returns the int64 representation of x. +// If x cannot be represented in an int64, the result is undefined. func (x *Int) Int64() int64 { if len(x.abs) == 0 { return 0 @@ -395,32 +458,19 @@ func (x *Int) Int64() int64 { // and returns z and a boolean indicating success. If SetString fails, // the value of z is undefined. // -// If the base argument is 0, the string prefix determines the actual -// conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the -// ``0'' prefix selects base 8, and a ``0b'' or ``0B'' prefix selects -// base 2. Otherwise the selected base is 10. +// The base argument must be 0 or a value from 2 through MaxBase. If the base +// is 0, the string prefix determines the actual conversion base. A prefix of +// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a +// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. // func (z *Int) SetString(s string, base int) (*Int, bool) { - if len(s) == 0 || base < 0 || base == 1 || 16 < base { + r := strings.NewReader(s) + _, _, err := z.scan(r, base) + if err != nil { return z, false } - - neg := s[0] == '-' - if neg || s[0] == '+' { - s = s[1:] - if len(s) == 0 { - return z, false - } - } - - var scanned int - z.abs, _, scanned = z.abs.scan(s, base) - if scanned != len(s) { - return z, false - } - z.neg = len(z.abs) > 0 && neg // 0 has no sign - - return z, true + _, _, err = r.ReadRune() + return z, err == os.EOF // err == os.EOF => scan consumed all of s } @@ -784,11 +834,11 @@ func (z *Int) GobEncode() ([]byte, os.Error) { // GobDecode implements the gob.GobDecoder interface. func (z *Int) GobDecode(buf []byte) os.Error { if len(buf) == 0 { - return os.NewError("Int.GobDecode: no data") + return os.ErrorString("Int.GobDecode: no data") } b := buf[0] if b>>1 != version { - return os.NewError(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1)) + return os.ErrorString(fmt.Sprintf("Int.GobDecode: encoding version %d not supported", b>>1)) } z.neg = b&1 != 0 z.abs = z.abs.setBytes(buf[1:]) diff --git a/src/pkg/big/int_test.go b/src/pkg/big/int_test.go index 595f04956..1a492925b 100755 --- a/src/pkg/big/int_test.go +++ b/src/pkg/big/int_test.go @@ -397,6 +397,49 @@ func TestFormat(t *testing.T) { } +var scanTests = []struct { + input string + format string + output string + remaining int +}{ + {"1010", "%b", "10", 0}, + {"0b1010", "%v", "10", 0}, + {"12", "%o", "10", 0}, + {"012", "%v", "10", 0}, + {"10", "%d", "10", 0}, + {"10", "%v", "10", 0}, + {"a", "%x", "10", 0}, + {"0xa", "%v", "10", 0}, + {"A", "%X", "10", 0}, + {"-A", "%X", "-10", 0}, + {"+0b1011001", "%v", "89", 0}, + {"0xA", "%v", "10", 0}, + {"0 ", "%v", "0", 1}, + {"2+3", "%v", "2", 2}, + {"0XABC 12", "%v", "2748", 3}, +} + + +func TestScan(t *testing.T) { + var buf bytes.Buffer + for i, test := range scanTests { + x := new(Int) + buf.Reset() + buf.WriteString(test.input) + if _, err := fmt.Fscanf(&buf, test.format, x); err != nil { + t.Errorf("#%d error: %s", i, err.String()) + } + if x.String() != test.output { + t.Errorf("#%d got %s; want %s", i, x.String(), test.output) + } + if buf.Len() != test.remaining { + t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining) + } + } +} + + // Examples from the Go Language Spec, section "Arithmetic operators" var divisionSignsTests = []struct { x, y int64 diff --git a/src/pkg/big/nat.go b/src/pkg/big/nat.go index c2b95e8a2..fa09d6531 100755 --- a/src/pkg/big/nat.go +++ b/src/pkg/big/nat.go @@ -18,7 +18,11 @@ package big // These are the building blocks for the operations on signed integers // and rationals. -import "rand" +import ( + "io" + "os" + "rand" +) // An unsigned integer x of the form @@ -546,9 +550,14 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) { u.clear() // D1. - shift := Word(leadingZeros(v[n-1])) - shlVW(v, v, shift) - u[len(uIn)] = shlVW(u[0:len(uIn)], uIn, shift) + shift := leadingZeros(v[n-1]) + if shift > 0 { + // do not modify v, it may be used by another goroutine simultaneously + v1 := make(nat, n) + shlVU(v1, v, shift) + v = v1 + } + u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift) // D2. for j := m; j >= 0; j-- { @@ -587,8 +596,7 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) { } q = q.norm() - shrVW(u, u, shift) - shrVW(v, v, shift) + shrVU(u, u, shift) r = u.norm() return q, r @@ -604,68 +612,118 @@ func (x nat) bitLen() int { } -func hexValue(ch byte) int { - var d byte +// MaxBase is the largest number base accepted for string conversions. +const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1 + +func hexValue(ch int) Word { + d := MaxBase + 1 // illegal base switch { case '0' <= ch && ch <= '9': d = ch - '0' - case 'a' <= ch && ch <= 'f': + case 'a' <= ch && ch <= 'z': d = ch - 'a' + 10 - case 'A' <= ch && ch <= 'F': + case 'A' <= ch && ch <= 'Z': d = ch - 'A' + 10 - default: - return -1 } - return int(d) + return Word(d) } -// scan returns the natural number corresponding to the -// longest possible prefix of s representing a natural number in a -// given conversion base, the actual conversion base used, and the -// prefix length. The syntax of natural numbers follows the syntax -// of unsigned integer literals in Go. +// scan sets z to the natural number corresponding to the longest possible prefix +// read from r representing an unsigned integer in a given conversion base. +// It returns z, the actual conversion base used, and an error, if any. In the +// error case, the value of z is undefined. The syntax follows the syntax of +// unsigned integer literals in Go. // -// If the base argument is 0, the string prefix determines the actual -// conversion base. A prefix of ``0x'' or ``0X'' selects base 16; the -// ``0'' prefix selects base 8, and a ``0b'' or ``0B'' prefix selects -// base 2. Otherwise the selected base is 10. +// The base argument must be 0 or a value from 2 through MaxBase. If the base +// is 0, the string prefix determines the actual conversion base. A prefix of +// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a +// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. // -func (z nat) scan(s string, base int) (nat, int, int) { +func (z nat) scan(r io.RuneScanner, base int) (nat, int, os.Error) { + // reject illegal bases + if base < 0 || base == 1 || MaxBase < base { + return z, 0, os.ErrorString("illegal number base") + } + + // one char look-ahead + ch, _, err := r.ReadRune() + if err != nil { + return z, 0, err + } + // determine base if necessary - i, n := 0, len(s) + b := Word(base) if base == 0 { - base = 10 - if n > 0 && s[0] == '0' { - base, i = 8, 1 - if n > 1 { - switch s[1] { + b = 10 + if ch == '0' { + switch ch, _, err = r.ReadRune(); err { + case nil: + b = 8 + switch ch { case 'x', 'X': - base, i = 16, 2 + b = 16 case 'b', 'B': - base, i = 2, 2 + b = 2 + } + if b == 2 || b == 16 { + if ch, _, err = r.ReadRune(); err != nil { + return z, 0, err + } } + case os.EOF: + return z, 10, nil + default: + return z, 10, err } } } - // reject illegal bases or strings consisting only of prefix - if base < 2 || 16 < base || (base != 8 && i >= n) { - return z, 0, 0 - } - // convert string + // - group as many digits d as possible together into a "super-digit" dd with "super-base" bb + // - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd z = z.make(0) - for ; i < n; i++ { - d := hexValue(s[i]) - if 0 <= d && d < base { - z = z.mulAddWW(z, Word(base), Word(d)) + bb := Word(1) + dd := Word(0) + for max := _M / b; ; { + d := hexValue(ch) + if d >= b { + r.UnreadRune() // ch does not belong to number anymore + break + } + + if bb <= max { + bb *= b + dd = dd*b + d } else { + // bb * b would overflow + z = z.mulAddWW(z, bb, dd) + bb = b + dd = d + } + + if ch, _, err = r.ReadRune(); err != nil { + if err != os.EOF { + return z, int(b), err + } break } } - return z.norm(), base, i + switch { + case bb > 1: + // there was at least one mantissa digit + z = z.mulAddWW(z, bb, dd) + case base == 0 && b == 8: + // there was only the octal prefix 0 (possibly followed by digits > 7); + // return base 10, not 8 + return z, 10, nil + case base != 0 || b != 8: + // there was neither a mantissa digit nor the octal prefix 0 + return z, int(b), os.ErrorString("syntax error scanning number") + } + + return z.norm(), int(b), nil } @@ -766,7 +824,7 @@ func (z nat) shl(x nat, s uint) nat { n := m + int(s/_W) z = z.make(n + 1) - z[n] = shlVW(z[n-m:n], x, Word(s%_W)) + z[n] = shlVU(z[n-m:n], x, s%_W) z[0 : n-m].clear() return z.norm() @@ -783,7 +841,7 @@ func (z nat) shr(x nat, s uint) nat { // n > 0 z = z.make(n) - shrVW(z, x[m-n:], Word(s%_W)) + shrVU(z, x[m-n:], s%_W) return z.norm() } @@ -914,25 +972,26 @@ func (x nat) modW(d Word) (r Word) { } -// powersOfTwoDecompose finds q and k such that q * 1<<k = n and q is odd. -func (n nat) powersOfTwoDecompose() (q nat, k Word) { - if len(n) == 0 { - return n, 0 +// powersOfTwoDecompose finds q and k with x = q * 1<<k and q is odd, or q and k are 0. +func (x nat) powersOfTwoDecompose() (q nat, k int) { + if len(x) == 0 { + return x, 0 } - zeroWords := 0 - for n[zeroWords] == 0 { - zeroWords++ + // One of the words must be non-zero by definition, + // so this loop will terminate with i < len(x), and + // i is the number of 0 words. + i := 0 + for x[i] == 0 { + i++ } - // One of the words must be non-zero by invariant, therefore - // zeroWords < len(n). - x := trailingZeroBits(n[zeroWords]) + n := trailingZeroBits(x[i]) // x[i] != 0 - q = q.make(len(n) - zeroWords) - shrVW(q, n[zeroWords:], Word(x)) - q = q.norm() + q = make(nat, len(x)-i) + shrVU(q, x[i:], uint(n)) - k = Word(_W*zeroWords + x) + q = q.norm() + k = i*_W + n return } @@ -1103,7 +1162,7 @@ NextRandom: if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 { continue } - for j := Word(1); j < k; j++ { + for j := 1; j < k; j++ { y = y.mul(y, y) quotient, y = quotient.div(y, y, n) if y.cmp(nm1) == 0 { diff --git a/src/pkg/big/nat_test.go b/src/pkg/big/nat_test.go index a29843a3f..50ea469be 100755 --- a/src/pkg/big/nat_test.go +++ b/src/pkg/big/nat_test.go @@ -4,7 +4,11 @@ package big -import "testing" +import ( + "os" + "strings" + "testing" +) var cmpTests = []struct { x, y nat @@ -180,6 +184,8 @@ var strTests = []struct { {nat{1234567890}, uppercaseDigits[0:10], "1234567890"}, {nat{0xdeadbeef}, lowercaseDigits[0:16], "deadbeef"}, {nat{0xdeadbeef}, uppercaseDigits[0:16], "DEADBEEF"}, + {nat{0x229be7}, lowercaseDigits[0:17], "1a2b3c"}, + {nat{0x309663e6}, uppercaseDigits[0:32], "O9COV6"}, } @@ -190,20 +196,170 @@ func TestString(t *testing.T) { t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s) } - x, b, n := nat(nil).scan(a.s, len(a.c)) + x, b, err := nat(nil).scan(strings.NewReader(a.s), len(a.c)) if x.cmp(a.x) != 0 { t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x) } if b != len(a.c) { t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c)) } - if n != len(a.s) { - t.Errorf("scan%+v\n\tgot n = %d; want %d", a, n, len(a.s)) + if err != nil { + t.Errorf("scan%+v\n\tgot error = %s", a, err) } } } +var natScanTests = []struct { + s string // string to be scanned + base int // input base + x nat // expected nat + b int // expected base + ok bool // expected success + next int // next character (or 0, if at EOF) +}{ + // error: illegal base + {base: -1}, + {base: 1}, + {base: 37}, + + // error: no mantissa + {}, + {s: "?"}, + {base: 10}, + {base: 36}, + {s: "?", base: 10}, + {s: "0x"}, + {s: "345", base: 2}, + + // no errors + {"0", 0, nil, 10, true, 0}, + {"0", 10, nil, 10, true, 0}, + {"0", 36, nil, 36, true, 0}, + {"1", 0, nat{1}, 10, true, 0}, + {"1", 10, nat{1}, 10, true, 0}, + {"0 ", 0, nil, 10, true, ' '}, + {"08", 0, nil, 10, true, '8'}, + {"018", 0, nat{1}, 8, true, '8'}, + {"0b1", 0, nat{1}, 2, true, 0}, + {"0b11000101", 0, nat{0xc5}, 2, true, 0}, + {"03271", 0, nat{03271}, 8, true, 0}, + {"10ab", 0, nat{10}, 10, true, 'a'}, + {"1234567890", 0, nat{1234567890}, 10, true, 0}, + {"xyz", 36, nat{(33*36+34)*36 + 35}, 36, true, 0}, + {"xyz?", 36, nat{(33*36+34)*36 + 35}, 36, true, '?'}, + {"0x", 16, nil, 16, true, 'x'}, + {"0xdeadbeef", 0, nat{0xdeadbeef}, 16, true, 0}, + {"0XDEADBEEF", 0, nat{0xdeadbeef}, 16, true, 0}, +} + + +func TestScanBase(t *testing.T) { + for _, a := range natScanTests { + r := strings.NewReader(a.s) + x, b, err := nat(nil).scan(r, a.base) + if err == nil && !a.ok { + t.Errorf("scan%+v\n\texpected error", a) + } + if err != nil { + if a.ok { + t.Errorf("scan%+v\n\tgot error = %s", a, err) + } + continue + } + if x.cmp(a.x) != 0 { + t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x) + } + if b != a.b { + t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.base) + } + next, _, err := r.ReadRune() + if err == os.EOF { + next = 0 + err = nil + } + if err == nil && next != a.next { + t.Errorf("scan%+v\n\tgot next = %q; want %q", a, next, a.next) + } + } +} + + +var pi = "3" + + "14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651" + + "32823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461" + + "28475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920" + + "96282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179" + + "31051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798" + + "60943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901" + + "22495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837" + + "29780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083" + + "81420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909" + + "21642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151" + + "55748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035" + + "63707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104" + + "75216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992" + + "45863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818" + + "34797753566369807426542527862551818417574672890977772793800081647060016145249192173217214772350141441973568548" + + "16136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179" + + "04946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886" + + "26945604241965285022210661186306744278622039194945047123713786960956364371917287467764657573962413890865832645" + + "99581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745" + + "53050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382" + + "68683868942774155991855925245953959431049972524680845987273644695848653836736222626099124608051243884390451244" + + "13654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767" + + "88952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288" + + "79710893145669136867228748940560101503308617928680920874760917824938589009714909675985261365549781893129784821" + + "68299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610" + + "21359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435" + + "06430218453191048481005370614680674919278191197939952061419663428754440643745123718192179998391015919561814675" + + "14269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672" + + "21825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539" + + "05796268561005508106658796998163574736384052571459102897064140110971206280439039759515677157700420337869936007" + + "23055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816" + + "90915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398" + + "31501970165151168517143765761835155650884909989859982387345528331635507647918535893226185489632132933089857064" + + "20467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325" + + "97463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100" + + "44929321516084244485963766983895228684783123552658213144957685726243344189303968642624341077322697802807318915" + + "44110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201" + + "85581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318" + + "58676975145661406800700237877659134401712749470420562230538994561314071127000407854733269939081454664645880797" + + "27082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923" + + "09907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111" + + "79042978285647503203198691514028708085990480109412147221317947647772622414254854540332157185306142288137585043" + + "06332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120" + + "91807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862" + + "94726547364252308177036751590673502350728354056704038674351362222477158915049530984448933309634087807693259939" + + "78054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229" + + "24654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001" + + "59377647165122893578601588161755782973523344604281512627203734314653197777416031990665541876397929334419521541" + + "34189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759" + + "88281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267" + + "94561275318134078330336254232783944975382437205835311477119926063813346776879695970309833913077109870408591337" + + +// Test case for BenchmarkScanPi. +func TestScanPi(t *testing.T) { + var x nat + z, _, err := x.scan(strings.NewReader(pi), 10) + if err != nil { + t.Errorf("scanning pi: %s", err) + } + if s := z.decimalString(); s != pi { + t.Errorf("scanning pi: got %s", s) + } +} + + +func BenchmarkScanPi(b *testing.B) { + for i := 0; i < b.N; i++ { + var x nat + x.scan(strings.NewReader(pi), 10) + } +} + + func TestLeadingZeros(t *testing.T) { var x Word = _B >> 1 for i := 0; i <= _W; i++ { @@ -344,14 +500,14 @@ var expNNTests = []struct { func TestExpNN(t *testing.T) { for i, test := range expNNTests { - x, _, _ := nat(nil).scan(test.x, 0) - y, _, _ := nat(nil).scan(test.y, 0) - out, _, _ := nat(nil).scan(test.out, 0) + x, _, _ := nat(nil).scan(strings.NewReader(test.x), 0) + y, _, _ := nat(nil).scan(strings.NewReader(test.y), 0) + out, _, _ := nat(nil).scan(strings.NewReader(test.out), 0) var m nat if len(test.m) > 0 { - m, _, _ = nat(nil).scan(test.m, 0) + m, _, _ = nat(nil).scan(strings.NewReader(test.m), 0) } z := nat(nil).expNN(x, y, m) diff --git a/src/pkg/big/rat.go b/src/pkg/big/rat.go index 2adf316e6..f11c27425 100644 --- a/src/pkg/big/rat.go +++ b/src/pkg/big/rat.go @@ -6,7 +6,11 @@ package big -import "strings" +import ( + "fmt" + "os" + "strings" +) // A Rat represents a quotient a/b of arbitrary precision. The zero value for // a Rat, 0/0, is not a legal Rat. @@ -209,6 +213,28 @@ func (z *Rat) Set(x *Rat) *Rat { } +func ratTok(ch int) bool { + return strings.IndexRune("+-/0123456789.eE", ch) >= 0 +} + + +// Scan is a support routine for fmt.Scanner. It accepts the formats +// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent. +func (z *Rat) Scan(s fmt.ScanState, ch int) os.Error { + tok, err := s.Token(true, ratTok) + if err != nil { + return err + } + if strings.IndexRune("efgEFGv", ch) < 0 { + return os.ErrorString("Rat.Scan: invalid verb") + } + if _, ok := z.SetString(string(tok)); !ok { + return os.ErrorString("Rat.Scan: invalid syntax") + } + return nil +} + + // SetString sets z to the value of s and returns z and a boolean indicating // success. s can be given as a fraction "a/b" or as a floating-point number // optionally followed by an exponent. If the operation failed, the value of z @@ -225,8 +251,8 @@ func (z *Rat) SetString(s string) (*Rat, bool) { return z, false } s = s[sep+1:] - var n int - if z.b, _, n = z.b.scan(s, 10); n != len(s) { + var err os.Error + if z.b, _, err = z.b.scan(strings.NewReader(s), 10); err != nil { return z, false } return z.norm(), true diff --git a/src/pkg/big/rat_test.go b/src/pkg/big/rat_test.go index 8f42949b0..ae5c7c993 100644 --- a/src/pkg/big/rat_test.go +++ b/src/pkg/big/rat_test.go @@ -4,7 +4,11 @@ package big -import "testing" +import ( + "bytes" + "fmt" + "testing" +) var setStringTests = []struct { @@ -53,6 +57,29 @@ func TestRatSetString(t *testing.T) { } +func TestRatScan(t *testing.T) { + var buf bytes.Buffer + for i, test := range setStringTests { + x := new(Rat) + buf.Reset() + buf.WriteString(test.in) + + _, err := fmt.Fscanf(&buf, "%v", x) + if err == nil != test.ok { + if test.ok { + t.Errorf("#%d error: %s", i, err.String()) + } else { + t.Errorf("#%d expected error", i) + } + continue + } + if err == nil && x.RatString() != test.out { + t.Errorf("#%d got %s want %s", i, x.RatString(), test.out) + } + } +} + + var floatStringTests = []struct { in string prec int diff --git a/src/pkg/compress/flate/deflate.go b/src/pkg/compress/flate/deflate.go index a02a5e8d9..b1cee0b2f 100644 --- a/src/pkg/compress/flate/deflate.go +++ b/src/pkg/compress/flate/deflate.go @@ -11,16 +11,18 @@ import ( ) const ( - NoCompression = 0 - BestSpeed = 1 - fastCompression = 3 - BestCompression = 9 - DefaultCompression = -1 - logMaxOffsetSize = 15 // Standard DEFLATE - wideLogMaxOffsetSize = 22 // Wide DEFLATE - minMatchLength = 3 // The smallest match that the compressor looks for - maxMatchLength = 258 // The longest match for the compressor - minOffsetSize = 1 // The shortest offset that makes any sence + NoCompression = 0 + BestSpeed = 1 + fastCompression = 3 + BestCompression = 9 + DefaultCompression = -1 + logWindowSize = 15 + windowSize = 1 << logWindowSize + windowMask = windowSize - 1 + logMaxOffsetSize = 15 // Standard DEFLATE + minMatchLength = 3 // The smallest match that the compressor looks for + maxMatchLength = 258 // The longest match for the compressor + minOffsetSize = 1 // The shortest offset that makes any sence // The maximum number of tokens we put into a single flat block, just too // stop things from getting too large. @@ -32,22 +34,6 @@ const ( hashShift = (hashBits + minMatchLength - 1) / minMatchLength ) -type syncPipeReader struct { - *io.PipeReader - closeChan chan bool -} - -func (sr *syncPipeReader) CloseWithError(err os.Error) os.Error { - retErr := sr.PipeReader.CloseWithError(err) - sr.closeChan <- true // finish writer close - return retErr -} - -type syncPipeWriter struct { - *io.PipeWriter - closeChan chan bool -} - type compressionLevel struct { good, lazy, nice, chain, fastSkipHashing int } @@ -68,105 +54,73 @@ var levels = []compressionLevel{ {32, 258, 258, 4096, math.MaxInt32}, } -func (sw *syncPipeWriter) Close() os.Error { - err := sw.PipeWriter.Close() - <-sw.closeChan // wait for reader close - return err -} - -func syncPipe() (*syncPipeReader, *syncPipeWriter) { - r, w := io.Pipe() - sr := &syncPipeReader{r, make(chan bool, 1)} - sw := &syncPipeWriter{w, sr.closeChan} - return sr, sw -} - type compressor struct { - level int - logWindowSize uint - w *huffmanBitWriter - r io.Reader - // (1 << logWindowSize) - 1. - windowMask int + compressionLevel - eof bool // has eof been reached on input? - sync bool // writer wants to flush - syncChan chan os.Error + w *huffmanBitWriter - // hashHead[hashValue] contains the largest inputIndex with the specified hash value - hashHead []int + // compression algorithm + fill func(*compressor, []byte) int // copy data to window + step func(*compressor) // process window + sync bool // requesting flush + // Input hash chains + // hashHead[hashValue] contains the largest inputIndex with the specified hash value // If hashHead[hashValue] is within the current window, then // hashPrev[hashHead[hashValue] & windowMask] contains the previous index // with the same hash value. - hashPrev []int - - // If we find a match of length >= niceMatch, then we don't bother searching - // any further. - niceMatch int - - // If we find a match of length >= goodMatch, we only do a half-hearted - // effort at doing lazy matching starting at the next character - goodMatch int - - // The maximum number of chains we look at when finding a match - maxChainLength int - - // The sliding window we use for matching - window []byte - - // The index just past the last valid character - windowEnd int - - // index in "window" at which current block starts - blockStart int -} - -func (d *compressor) flush() os.Error { - d.w.flush() - return d.w.err + chainHead int + hashHead []int + hashPrev []int + + // input window: unprocessed data is window[index:windowEnd] + index int + window []byte + windowEnd int + blockStart int // window index where current tokens start + byteAvailable bool // if true, still need to process window[index-1]. + + // queued output tokens: tokens[:ti] + tokens []token + ti int + + // deflate state + length int + offset int + hash int + maxInsertIndex int + err os.Error } -func (d *compressor) fillWindow(index int) (int, os.Error) { - if d.sync { - return index, nil - } - wSize := d.windowMask + 1 - if index >= wSize+wSize-(minMatchLength+maxMatchLength) { - // shift the window by wSize - copy(d.window, d.window[wSize:2*wSize]) - index -= wSize - d.windowEnd -= wSize - if d.blockStart >= wSize { - d.blockStart -= wSize +func (d *compressor) fillDeflate(b []byte) int { + if d.index >= 2*windowSize-(minMatchLength+maxMatchLength) { + // shift the window by windowSize + copy(d.window, d.window[windowSize:2*windowSize]) + d.index -= windowSize + d.windowEnd -= windowSize + if d.blockStart >= windowSize { + d.blockStart -= windowSize } else { d.blockStart = math.MaxInt32 } for i, h := range d.hashHead { - v := h - wSize + v := h - windowSize if v < -1 { v = -1 } d.hashHead[i] = v } for i, h := range d.hashPrev { - v := -h - wSize + v := -h - windowSize if v < -1 { v = -1 } d.hashPrev[i] = v } } - count, err := d.r.Read(d.window[d.windowEnd:]) - d.windowEnd += count - if count == 0 && err == nil { - d.sync = true - } - if err == os.EOF { - d.eof = true - err = nil - } - return index, err + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n } func (d *compressor) writeBlock(tokens []token, index int, eof bool) os.Error { @@ -194,21 +148,21 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead // We quit when we get a match that's at least nice long nice := len(win) - pos - if d.niceMatch < nice { - nice = d.niceMatch + if d.nice < nice { + nice = d.nice } // If we've got a match that's good enough, only look in 1/4 the chain. - tries := d.maxChainLength + tries := d.chain length = prevLength - if length >= d.goodMatch { + if length >= d.good { tries >>= 2 } w0 := win[pos] w1 := win[pos+1] wEnd := win[pos+length] - minIndex := pos - (d.windowMask + 1) + minIndex := pos - windowSize for i := prevHead; tries > 0; tries-- { if w0 == win[i] && w1 == win[i+1] && wEnd == win[i+length] { @@ -233,7 +187,7 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead // hashPrev[i & windowMask] has already been overwritten, so stop now. break } - if i = d.hashPrev[i&d.windowMask]; i < minIndex || i < 0 { + if i = d.hashPrev[i&windowMask]; i < minIndex || i < 0 { break } } @@ -248,234 +202,224 @@ func (d *compressor) writeStoredBlock(buf []byte) os.Error { return d.w.err } -func (d *compressor) storedDeflate() os.Error { - buf := make([]byte, maxStoreBlockSize) - for { - n, err := d.r.Read(buf) - if n == 0 && err == nil { - d.sync = true - } - if n > 0 || d.sync { - if err := d.writeStoredBlock(buf[0:n]); err != nil { - return err - } - if d.sync { - d.syncChan <- nil - d.sync = false - } - } - if err != nil { - if err == os.EOF { - break - } - return err - } - } - return nil -} - -func (d *compressor) doDeflate() (err os.Error) { - // init - d.windowMask = 1<<d.logWindowSize - 1 +func (d *compressor) initDeflate() { d.hashHead = make([]int, hashSize) - d.hashPrev = make([]int, 1<<d.logWindowSize) - d.window = make([]byte, 2<<d.logWindowSize) + d.hashPrev = make([]int, windowSize) + d.window = make([]byte, 2*windowSize) fillInts(d.hashHead, -1) - tokens := make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1) - l := levels[d.level] - d.goodMatch = l.good - d.niceMatch = l.nice - d.maxChainLength = l.chain - lazyMatch := l.lazy - length := minMatchLength - 1 - offset := 0 - byteAvailable := false - isFastDeflate := l.fastSkipHashing != 0 - index := 0 - // run - if index, err = d.fillWindow(index); err != nil { + d.tokens = make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1) + d.length = minMatchLength - 1 + d.offset = 0 + d.byteAvailable = false + d.index = 0 + d.ti = 0 + d.hash = 0 + d.chainHead = -1 +} + +func (d *compressor) deflate() { + if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync { return } - maxOffset := d.windowMask + 1 // (1 << logWindowSize); - // only need to change when you refill the window - windowEnd := d.windowEnd - maxInsertIndex := windowEnd - (minMatchLength - 1) - ti := 0 - - hash := int(0) - if index < maxInsertIndex { - hash = int(d.window[index])<<hashShift + int(d.window[index+1]) + + d.maxInsertIndex = d.windowEnd - (minMatchLength - 1) + if d.index < d.maxInsertIndex { + d.hash = int(d.window[d.index])<<hashShift + int(d.window[d.index+1]) } - chainHead := -1 + Loop: for { - if index > windowEnd { + if d.index > d.windowEnd { panic("index > windowEnd") } - lookahead := windowEnd - index + lookahead := d.windowEnd - d.index if lookahead < minMatchLength+maxMatchLength { - if index, err = d.fillWindow(index); err != nil { - return + if !d.sync { + break Loop } - windowEnd = d.windowEnd - if index > windowEnd { + if d.index > d.windowEnd { panic("index > windowEnd") } - maxInsertIndex = windowEnd - (minMatchLength - 1) - lookahead = windowEnd - index if lookahead == 0 { // Flush current output block if any. - if byteAvailable { + if d.byteAvailable { // There is still one pending token that needs to be flushed - tokens[ti] = literalToken(uint32(d.window[index-1]) & 0xFF) - ti++ - byteAvailable = false + d.tokens[d.ti] = literalToken(uint32(d.window[d.index-1])) + d.ti++ + d.byteAvailable = false } - if ti > 0 { - if err = d.writeBlock(tokens[0:ti], index, false); err != nil { + if d.ti > 0 { + if d.err = d.writeBlock(d.tokens[0:d.ti], d.index, false); d.err != nil { return } - ti = 0 - } - if d.sync { - d.w.writeStoredHeader(0, false) - d.w.flush() - d.syncChan <- d.w.err - d.sync = false - } - - // If this was only a sync (not at EOF) keep going. - if !d.eof { - continue + d.ti = 0 } break Loop } } - if index < maxInsertIndex { + if d.index < d.maxInsertIndex { // Update the hash - hash = (hash<<hashShift + int(d.window[index+2])) & hashMask - chainHead = d.hashHead[hash] - d.hashPrev[index&d.windowMask] = chainHead - d.hashHead[hash] = index + d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask + d.chainHead = d.hashHead[d.hash] + d.hashPrev[d.index&windowMask] = d.chainHead + d.hashHead[d.hash] = d.index } - prevLength := length - prevOffset := offset - length = minMatchLength - 1 - offset = 0 - minIndex := index - maxOffset + prevLength := d.length + prevOffset := d.offset + d.length = minMatchLength - 1 + d.offset = 0 + minIndex := d.index - windowSize if minIndex < 0 { minIndex = 0 } - if chainHead >= minIndex && - (isFastDeflate && lookahead > minMatchLength-1 || - !isFastDeflate && lookahead > prevLength && prevLength < lazyMatch) { - if newLength, newOffset, ok := d.findMatch(index, chainHead, minMatchLength-1, lookahead); ok { - length = newLength - offset = newOffset + if d.chainHead >= minIndex && + (d.fastSkipHashing != 0 && lookahead > minMatchLength-1 || + d.fastSkipHashing == 0 && lookahead > prevLength && prevLength < d.lazy) { + if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead, minMatchLength-1, lookahead); ok { + d.length = newLength + d.offset = newOffset } } - if isFastDeflate && length >= minMatchLength || - !isFastDeflate && prevLength >= minMatchLength && length <= prevLength { + if d.fastSkipHashing != 0 && d.length >= minMatchLength || + d.fastSkipHashing == 0 && prevLength >= minMatchLength && d.length <= prevLength { // There was a match at the previous step, and the current match is // not better. Output the previous match. - if isFastDeflate { - tokens[ti] = matchToken(uint32(length-minMatchLength), uint32(offset-minOffsetSize)) + if d.fastSkipHashing != 0 { + d.tokens[d.ti] = matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize)) } else { - tokens[ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize)) + d.tokens[d.ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize)) } - ti++ + d.ti++ // Insert in the hash table all strings up to the end of the match. // index and index-1 are already inserted. If there is not enough // lookahead, the last two strings are not inserted into the hash // table. - if length <= l.fastSkipHashing { + if d.length <= d.fastSkipHashing { var newIndex int - if isFastDeflate { - newIndex = index + length + if d.fastSkipHashing != 0 { + newIndex = d.index + d.length } else { newIndex = prevLength - 1 } - for index++; index < newIndex; index++ { - if index < maxInsertIndex { - hash = (hash<<hashShift + int(d.window[index+2])) & hashMask + for d.index++; d.index < newIndex; d.index++ { + if d.index < d.maxInsertIndex { + d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask // Get previous value with the same hash. // Our chain should point to the previous value. - d.hashPrev[index&d.windowMask] = d.hashHead[hash] + d.hashPrev[d.index&windowMask] = d.hashHead[d.hash] // Set the head of the hash chain to us. - d.hashHead[hash] = index + d.hashHead[d.hash] = d.index } } - if !isFastDeflate { - byteAvailable = false - length = minMatchLength - 1 + if d.fastSkipHashing == 0 { + d.byteAvailable = false + d.length = minMatchLength - 1 } } else { // For matches this long, we don't bother inserting each individual // item into the table. - index += length - hash = (int(d.window[index])<<hashShift + int(d.window[index+1])) + d.index += d.length + d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1])) } - if ti == maxFlateBlockTokens { + if d.ti == maxFlateBlockTokens { // The block includes the current character - if err = d.writeBlock(tokens, index, false); err != nil { + if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil { return } - ti = 0 + d.ti = 0 } } else { - if isFastDeflate || byteAvailable { - i := index - 1 - if isFastDeflate { - i = index + if d.fastSkipHashing != 0 || d.byteAvailable { + i := d.index - 1 + if d.fastSkipHashing != 0 { + i = d.index } - tokens[ti] = literalToken(uint32(d.window[i]) & 0xFF) - ti++ - if ti == maxFlateBlockTokens { - if err = d.writeBlock(tokens, i+1, false); err != nil { + d.tokens[d.ti] = literalToken(uint32(d.window[i])) + d.ti++ + if d.ti == maxFlateBlockTokens { + if d.err = d.writeBlock(d.tokens, i+1, false); d.err != nil { return } - ti = 0 + d.ti = 0 } } - index++ - if !isFastDeflate { - byteAvailable = true + d.index++ + if d.fastSkipHashing == 0 { + d.byteAvailable = true } } } - return } -func (d *compressor) compress(r io.Reader, w io.Writer, level int, logWindowSize uint) (err os.Error) { - d.r = r +func (d *compressor) fillStore(b []byte) int { + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +func (d *compressor) store() { + if d.windowEnd > 0 { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + } + d.windowEnd = 0 +} + +func (d *compressor) write(b []byte) (n int, err os.Error) { + n = len(b) + b = b[d.fill(d, b):] + for len(b) > 0 { + d.step(d) + b = b[d.fill(d, b):] + } + return n, d.err +} + +func (d *compressor) syncFlush() os.Error { + d.sync = true + d.step(d) + if d.err == nil { + d.w.writeStoredHeader(0, false) + d.w.flush() + d.err = d.w.err + } + d.sync = false + return d.err +} + +func (d *compressor) init(w io.Writer, level int) (err os.Error) { d.w = newHuffmanBitWriter(w) - d.level = level - d.logWindowSize = logWindowSize switch { case level == NoCompression: - err = d.storedDeflate() + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillStore + d.step = (*compressor).store case level == DefaultCompression: - d.level = 6 + level = 6 fallthrough case 1 <= level && level <= 9: - err = d.doDeflate() + d.compressionLevel = levels[level] + d.initDeflate() + d.fill = (*compressor).fillDeflate + d.step = (*compressor).deflate default: return WrongValueError{"level", 0, 9, int32(level)} } + return nil +} - if d.sync { - d.syncChan <- err - d.sync = false - } - if err != nil { - return err +func (d *compressor) close() os.Error { + d.sync = true + d.step(d) + if d.err != nil { + return d.err } if d.w.writeStoredHeader(0, true); d.w.err != nil { return d.w.err } - return d.flush() + d.w.flush() + return d.w.err } // NewWriter returns a new Writer compressing @@ -486,14 +430,9 @@ func (d *compressor) compress(r io.Reader, w io.Writer, level int, logWindowSize // compression; it only adds the necessary DEFLATE framing. func NewWriter(w io.Writer, level int) *Writer { const logWindowSize = logMaxOffsetSize - var d compressor - d.syncChan = make(chan os.Error, 1) - pr, pw := syncPipe() - go func() { - err := d.compress(pr, w, level, logWindowSize) - pr.CloseWithError(err) - }() - return &Writer{pw, &d} + var dw Writer + dw.d.init(w, level) + return &dw } // NewWriterDict is like NewWriter but initializes the new @@ -526,18 +465,13 @@ func (w *dictWriter) Write(b []byte) (n int, err os.Error) { // A Writer takes data written to it and writes the compressed // form of that data to an underlying writer (see NewWriter). type Writer struct { - w *syncPipeWriter - d *compressor + d compressor } // Write writes data to w, which will eventually write the // compressed form of data to its underlying writer. func (w *Writer) Write(data []byte) (n int, err os.Error) { - if len(data) == 0 { - // no point, and nil interferes with sync - return - } - return w.w.Write(data) + return w.d.write(data) } // Flush flushes any pending compressed data to the underlying writer. @@ -550,18 +484,10 @@ func (w *Writer) Write(data []byte) (n int, err os.Error) { func (w *Writer) Flush() os.Error { // For more about flushing: // http://www.bolet.org/~pornin/deflate-flush.html - if w.d.sync { - panic("compress/flate: double Flush") - } - _, err := w.w.Write(nil) - err1 := <-w.d.syncChan - if err == nil { - err = err1 - } - return err + return w.d.syncFlush() } // Close flushes and closes the writer. func (w *Writer) Close() os.Error { - return w.w.Close() + return w.d.close() } diff --git a/src/pkg/compress/flate/deflate_test.go b/src/pkg/compress/flate/deflate_test.go index 650a8059a..2ac811c38 100644 --- a/src/pkg/compress/flate/deflate_test.go +++ b/src/pkg/compress/flate/deflate_test.go @@ -57,7 +57,7 @@ var deflateInflateTests = []*deflateInflateTest{ &deflateInflateTest{[]byte{0x11, 0x12}}, &deflateInflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}, &deflateInflateTest{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}}, - &deflateInflateTest{getLargeDataChunk()}, + &deflateInflateTest{largeDataChunk()}, } var reverseBitsTests = []*reverseBitsTest{ @@ -71,23 +71,22 @@ var reverseBitsTests = []*reverseBitsTest{ &reverseBitsTest{29, 5, 23}, } -func getLargeDataChunk() []byte { +func largeDataChunk() []byte { result := make([]byte, 100000) for i := range result { - result[i] = byte(int64(i) * int64(i) & 0xFF) + result[i] = byte(i * i & 0xFF) } return result } func TestDeflate(t *testing.T) { for _, h := range deflateTests { - buffer := bytes.NewBuffer(nil) - w := NewWriter(buffer, h.level) + var buf bytes.Buffer + w := NewWriter(&buf, h.level) w.Write(h.in) w.Close() - if bytes.Compare(buffer.Bytes(), h.out) != 0 { - t.Errorf("buffer is wrong; level = %v, buffer.Bytes() = %v, expected output = %v", - h.level, buffer.Bytes(), h.out) + if !bytes.Equal(buf.Bytes(), h.out) { + t.Errorf("Deflate(%d, %x) = %x, want %x", h.level, h.in, buf.Bytes(), h.out) } } } diff --git a/src/pkg/compress/flate/huffman_bit_writer.go b/src/pkg/compress/flate/huffman_bit_writer.go index 5df4510a2..3981df5cb 100644 --- a/src/pkg/compress/flate/huffman_bit_writer.go +++ b/src/pkg/compress/flate/huffman_bit_writer.go @@ -15,9 +15,6 @@ const ( // The largest offset code. offsetCodeCount = 30 - // The largest offset code in the extensions. - extendedOffsetCodeCount = 42 - // The special code used to mark the end of a block. endBlockMarker = 256 @@ -100,11 +97,11 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter { return &huffmanBitWriter{ w: w, literalFreq: make([]int32, maxLit), - offsetFreq: make([]int32, extendedOffsetCodeCount), - codegen: make([]uint8, maxLit+extendedOffsetCodeCount+1), + offsetFreq: make([]int32, offsetCodeCount), + codegen: make([]uint8, maxLit+offsetCodeCount+1), codegenFreq: make([]int32, codegenCodeCount), literalEncoding: newHuffmanEncoder(maxLit), - offsetEncoding: newHuffmanEncoder(extendedOffsetCodeCount), + offsetEncoding: newHuffmanEncoder(offsetCodeCount), codegenEncoding: newHuffmanEncoder(codegenCodeCount), } } @@ -290,13 +287,7 @@ func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, n } w.writeBits(firstBits, 3) w.writeBits(int32(numLiterals-257), 5) - if numOffsets > offsetCodeCount { - // Extended version of decompressor - w.writeBits(int32(offsetCodeCount+((numOffsets-(1+offsetCodeCount))>>3)), 5) - w.writeBits(int32((numOffsets-(1+offsetCodeCount))&0x7), 3) - } else { - w.writeBits(int32(numOffsets-1), 5) - } + w.writeBits(int32(numOffsets-1), 5) w.writeBits(int32(numCodegens-4), 4) for i := 0; i < numCodegens; i++ { @@ -368,24 +359,17 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) { tokens = tokens[0 : n+1] tokens[n] = endBlockMarker - totalLength := -1 // Subtract 1 for endBlock. for _, t := range tokens { switch t.typ() { case literalType: w.literalFreq[t.literal()]++ - totalLength++ - break case matchType: length := t.length() offset := t.offset() - totalLength += int(length + 3) w.literalFreq[lengthCodesStart+lengthCode(length)]++ w.offsetFreq[offsetCode(offset)]++ - break } } - w.literalEncoding.generate(w.literalFreq, 15) - w.offsetEncoding.generate(w.offsetFreq, 15) // get the number of literals numLiterals := len(w.literalFreq) @@ -394,15 +378,25 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) { } // get the number of offsets numOffsets := len(w.offsetFreq) - for numOffsets > 1 && w.offsetFreq[numOffsets-1] == 0 { + for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 { numOffsets-- } + if numOffsets == 0 { + // We haven't found a single match. If we want to go with the dynamic encoding, + // we should count at least one offset to be sure that the offset huffman tree could be encoded. + w.offsetFreq[0] = 1 + numOffsets = 1 + } + + w.literalEncoding.generate(w.literalFreq, 15) + w.offsetEncoding.generate(w.offsetFreq, 15) + storedBytes := 0 if input != nil { storedBytes = len(input) } var extraBits int64 - var storedSize int64 + var storedSize int64 = math.MaxInt64 if storedBytes <= maxStoreBlockSize && input != nil { storedSize = int64((storedBytes + 5) * 8) // We only bother calculating the costs of the extra bits required by @@ -417,34 +411,29 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) { // First four offset codes have extra size = 0. extraBits += int64(w.offsetFreq[offsetCode]) * int64(offsetExtraBits[offsetCode]) } - } else { - storedSize = math.MaxInt32 } - // Figure out which generates smaller code, fixed Huffman, dynamic - // Huffman, or just storing the data. - var fixedSize int64 = math.MaxInt64 - if numOffsets <= offsetCodeCount { - fixedSize = int64(3) + - fixedLiteralEncoding.bitLength(w.literalFreq) + - fixedOffsetEncoding.bitLength(w.offsetFreq) + - extraBits - } + // Figure out smallest code. + // Fixed Huffman baseline. + var size = int64(3) + + fixedLiteralEncoding.bitLength(w.literalFreq) + + fixedOffsetEncoding.bitLength(w.offsetFreq) + + extraBits + var literalEncoding = fixedLiteralEncoding + var offsetEncoding = fixedOffsetEncoding + + // Dynamic Huffman? + var numCodegens int + // Generate codegen and codegenFrequencies, which indicates how to encode // the literalEncoding and the offsetEncoding. w.generateCodegen(numLiterals, numOffsets) w.codegenEncoding.generate(w.codegenFreq, 7) - numCodegens := len(w.codegenFreq) + numCodegens = len(w.codegenFreq) for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { numCodegens-- } - extensionSummand := 0 - if numOffsets > offsetCodeCount { - extensionSummand = 3 - } dynamicHeader := int64(3+5+5+4+(3*numCodegens)) + - // Following line is an extension. - int64(extensionSummand) + w.codegenEncoding.bitLength(w.codegenFreq) + int64(extraBits) + int64(w.codegenFreq[16]*2) + @@ -454,26 +443,25 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) { w.literalEncoding.bitLength(w.literalFreq) + w.offsetEncoding.bitLength(w.offsetFreq) - if storedSize < fixedSize && storedSize < dynamicSize { + if dynamicSize < size { + size = dynamicSize + literalEncoding = w.literalEncoding + offsetEncoding = w.offsetEncoding + } + + // Stored bytes? + if storedSize < size { w.writeStoredHeader(storedBytes, eof) w.writeBytes(input[0:storedBytes]) return } - var literalEncoding *huffmanEncoder - var offsetEncoding *huffmanEncoder - if fixedSize <= dynamicSize { + // Huffman. + if literalEncoding == fixedLiteralEncoding { w.writeFixedHeader(eof) - literalEncoding = fixedLiteralEncoding - offsetEncoding = fixedOffsetEncoding } else { - // Write the header. w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) - literalEncoding = w.literalEncoding - offsetEncoding = w.offsetEncoding } - - // Write the tokens. for _, t := range tokens { switch t.typ() { case literalType: diff --git a/src/pkg/compress/flate/huffman_code.go b/src/pkg/compress/flate/huffman_code.go index 6be605f0a..7ed603a4f 100644 --- a/src/pkg/compress/flate/huffman_code.go +++ b/src/pkg/compress/flate/huffman_code.go @@ -363,7 +363,12 @@ func (s literalNodeSorter) Less(i, j int) bool { func (s literalNodeSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] } func sortByFreq(a []literalNode) { - s := &literalNodeSorter{a, func(i, j int) bool { return a[i].freq < a[j].freq }} + s := &literalNodeSorter{a, func(i, j int) bool { + if a[i].freq == a[j].freq { + return a[i].literal < a[j].literal + } + return a[i].freq < a[j].freq + }} sort.Sort(s) } diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go index 320b80d06..3845f1204 100644 --- a/src/pkg/compress/flate/inflate.go +++ b/src/pkg/compress/flate/inflate.go @@ -77,8 +77,6 @@ type huffmanDecoder struct { // Initialize Huffman decoding tables from array of code lengths. func (h *huffmanDecoder) init(bits []int) bool { - // TODO(rsc): Return false sometimes. - // Count number of codes of each length, // compute min and max length. var count [maxCodeLen + 1]int @@ -197,9 +195,8 @@ type Reader interface { // Decompress state. type decompressor struct { - // Input/output sources. + // Input source. r Reader - w io.Writer roffset int64 woffset int64 @@ -222,38 +219,79 @@ type decompressor struct { // Temporary buffer (avoids repeated allocation). buf [4]byte + + // Next step in the decompression, + // and decompression state. + step func(*decompressor) + final bool + err os.Error + toRead []byte + hl, hd *huffmanDecoder + copyLen int + copyDist int } -func (f *decompressor) inflate() (err os.Error) { - final := false - for err == nil && !final { - for f.nb < 1+2 { - if err = f.moreBits(); err != nil { - return - } +func (f *decompressor) nextBlock() { + if f.final { + if f.hw != f.hp { + f.flush((*decompressor).nextBlock) + return } - final = f.b&1 == 1 - f.b >>= 1 - typ := f.b & 3 - f.b >>= 2 - f.nb -= 1 + 2 - switch typ { - case 0: - err = f.dataBlock() - case 1: - // compressed, fixed Huffman tables - err = f.decodeBlock(&fixedHuffmanDecoder, nil) - case 2: - // compressed, dynamic Huffman tables - if err = f.readHuffman(); err == nil { - err = f.decodeBlock(&f.h1, &f.h2) - } - default: - // 3 is reserved. - err = CorruptInputError(f.roffset) + f.err = os.EOF + return + } + for f.nb < 1+2 { + if f.err = f.moreBits(); f.err != nil { + return + } + } + f.final = f.b&1 == 1 + f.b >>= 1 + typ := f.b & 3 + f.b >>= 2 + f.nb -= 1 + 2 + switch typ { + case 0: + f.dataBlock() + case 1: + // compressed, fixed Huffman tables + f.hl = &fixedHuffmanDecoder + f.hd = nil + f.huffmanBlock() + case 2: + // compressed, dynamic Huffman tables + if f.err = f.readHuffman(); f.err != nil { + break + } + f.hl = &f.h1 + f.hd = &f.h2 + f.huffmanBlock() + default: + // 3 is reserved. + f.err = CorruptInputError(f.roffset) + } +} + +func (f *decompressor) Read(b []byte) (int, os.Error) { + for { + if len(f.toRead) > 0 { + n := copy(b, f.toRead) + f.toRead = f.toRead[n:] + return n, nil + } + if f.err != nil { + return 0, f.err } + f.step(f) } - return + panic("unreachable") +} + +func (f *decompressor) Close() os.Error { + if f.err == os.EOF { + return nil + } + return f.err } // RFC 1951 section 3.2.7. @@ -358,11 +396,12 @@ func (f *decompressor) readHuffman() os.Error { // hl and hd are the Huffman states for the lit/length values // and the distance values, respectively. If hd == nil, using the // fixed distance encoding associated with fixed Huffman blocks. -func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { +func (f *decompressor) huffmanBlock() { for { - v, err := f.huffSym(hl) + v, err := f.huffSym(f.hl) if err != nil { - return err + f.err = err + return } var n uint // number of bits extra var length int @@ -371,13 +410,15 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { f.hist[f.hp] = byte(v) f.hp++ if f.hp == len(f.hist) { - if err = f.flush(); err != nil { - return err - } + // After the flush, continue this loop. + f.flush((*decompressor).huffmanBlock) + return } continue case v == 256: - return nil + // Done with huffman block; read next block. + f.step = (*decompressor).nextBlock + return // otherwise, reference to older data case v < 265: length = v - (257 - 3) @@ -404,7 +445,8 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { if n > 0 { for f.nb < n { if err = f.moreBits(); err != nil { - return err + f.err = err + return } } length += int(f.b & uint32(1<<n-1)) @@ -413,18 +455,20 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { } var dist int - if hd == nil { + if f.hd == nil { for f.nb < 5 { if err = f.moreBits(); err != nil { - return err + f.err = err + return } } dist = int(reverseByte[(f.b&0x1F)<<3]) f.b >>= 5 f.nb -= 5 } else { - if dist, err = f.huffSym(hd); err != nil { - return err + if dist, err = f.huffSym(f.hd); err != nil { + f.err = err + return } } @@ -432,14 +476,16 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { case dist < 4: dist++ case dist >= 30: - return CorruptInputError(f.roffset) + f.err = CorruptInputError(f.roffset) + return default: nb := uint(dist-2) >> 1 // have 1 bit in bottom of dist, need nb more. extra := (dist & 1) << nb for f.nb < nb { if err = f.moreBits(); err != nil { - return err + f.err = err + return } } extra |= int(f.b & uint32(1<<nb-1)) @@ -450,12 +496,14 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { // Copy history[-dist:-dist+length] into output. if dist > len(f.hist) { - return InternalError("bad history distance") + f.err = InternalError("bad history distance") + return } // No check on length; encoding can be prescient. if !f.hfull && dist > f.hp { - return CorruptInputError(f.roffset) + f.err = CorruptInputError(f.roffset) + return } p := f.hp - dist @@ -467,9 +515,11 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { f.hp++ p++ if f.hp == len(f.hist) { - if err = f.flush(); err != nil { - return err - } + // After flush continue copying out of history. + f.copyLen = length - (i + 1) + f.copyDist = dist + f.flush((*decompressor).copyHuff) + return } if p == len(f.hist) { p = 0 @@ -479,8 +529,33 @@ func (f *decompressor) decodeBlock(hl, hd *huffmanDecoder) os.Error { panic("unreached") } +func (f *decompressor) copyHuff() { + length := f.copyLen + dist := f.copyDist + p := f.hp - dist + if p < 0 { + p += len(f.hist) + } + for i := 0; i < length; i++ { + f.hist[f.hp] = f.hist[p] + f.hp++ + p++ + if f.hp == len(f.hist) { + f.copyLen = length - (i + 1) + f.flush((*decompressor).copyHuff) + return + } + if p == len(f.hist) { + p = 0 + } + } + + // Continue processing Huffman block. + f.huffmanBlock() +} + // Copy a single uncompressed data block from input to output. -func (f *decompressor) dataBlock() os.Error { +func (f *decompressor) dataBlock() { // Uncompressed. // Discard current half-byte. f.nb = 0 @@ -490,21 +565,30 @@ func (f *decompressor) dataBlock() os.Error { nr, err := io.ReadFull(f.r, f.buf[0:4]) f.roffset += int64(nr) if err != nil { - return &ReadError{f.roffset, err} + f.err = &ReadError{f.roffset, err} + return } n := int(f.buf[0]) | int(f.buf[1])<<8 nn := int(f.buf[2]) | int(f.buf[3])<<8 if uint16(nn) != uint16(^n) { - return CorruptInputError(f.roffset) + f.err = CorruptInputError(f.roffset) + return } if n == 0 { // 0-length block means sync - return f.flush() + f.flush((*decompressor).nextBlock) + return } - // Read len bytes into history, - // writing as history fills. + f.copyLen = n + f.copyData() +} + +func (f *decompressor) copyData() { + // Read f.dataLen bytes into history, + // pausing for reads as history fills. + n := f.copyLen for n > 0 { m := len(f.hist) - f.hp if m > n { @@ -513,17 +597,18 @@ func (f *decompressor) dataBlock() os.Error { m, err := io.ReadFull(f.r, f.hist[f.hp:f.hp+m]) f.roffset += int64(m) if err != nil { - return &ReadError{f.roffset, err} + f.err = &ReadError{f.roffset, err} + return } n -= m f.hp += m if f.hp == len(f.hist) { - if err = f.flush(); err != nil { - return err - } + f.copyLen = n + f.flush((*decompressor).copyData) + return } } - return nil + f.step = (*decompressor).nextBlock } func (f *decompressor) setDict(dict []byte) { @@ -579,17 +664,8 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, os.Error) { } // Flush any buffered output to the underlying writer. -func (f *decompressor) flush() os.Error { - if f.hw == f.hp { - return nil - } - n, err := f.w.Write(f.hist[f.hw:f.hp]) - if n != f.hp-f.hw && err == nil { - err = io.ErrShortWrite - } - if err != nil { - return &WriteError{f.woffset, err} - } +func (f *decompressor) flush(step func(*decompressor)) { + f.toRead = f.hist[f.hw:f.hp] f.woffset += int64(f.hp - f.hw) f.hw = f.hp if f.hp == len(f.hist) { @@ -597,7 +673,7 @@ func (f *decompressor) flush() os.Error { f.hw = 0 f.hfull = true } - return nil + f.step = step } func makeReader(r io.Reader) Reader { @@ -607,30 +683,15 @@ func makeReader(r io.Reader) Reader { return bufio.NewReader(r) } -// decompress reads DEFLATE-compressed data from r and writes -// the uncompressed data to w. -func (f *decompressor) decompress(r io.Reader, w io.Writer) os.Error { - f.r = makeReader(r) - f.w = w - f.woffset = 0 - if err := f.inflate(); err != nil { - return err - } - if err := f.flush(); err != nil { - return err - } - return nil -} - // NewReader returns a new ReadCloser that can be used // to read the uncompressed version of r. It is the caller's // responsibility to call Close on the ReadCloser when // finished reading. func NewReader(r io.Reader) io.ReadCloser { var f decompressor - pr, pw := io.Pipe() - go func() { pw.CloseWithError(f.decompress(r, pw)) }() - return pr + f.r = makeReader(r) + f.step = (*decompressor).nextBlock + return &f } // NewReaderDict is like NewReader but initializes the reader @@ -641,7 +702,7 @@ func NewReader(r io.Reader) io.ReadCloser { func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser { var f decompressor f.setDict(dict) - pr, pw := io.Pipe() - go func() { pw.CloseWithError(f.decompress(r, pw)) }() - return pr + f.r = makeReader(r) + f.step = (*decompressor).nextBlock + return &f } diff --git a/src/pkg/compress/zlib/writer_test.go b/src/pkg/compress/zlib/writer_test.go index a06689ee5..32f05ab68 100644 --- a/src/pkg/compress/zlib/writer_test.go +++ b/src/pkg/compress/zlib/writer_test.go @@ -6,6 +6,7 @@ package zlib import ( "bytes" + "fmt" "io" "io/ioutil" "os" @@ -17,15 +18,13 @@ var filenames = []string{ "../testdata/pi.txt", } +var data = []string{ + "test a reasonable sized string that can be compressed", +} + // Tests that compressing and then decompressing the given file at the given compression level and dictionary // yields equivalent bytes to the original file. func testFileLevelDict(t *testing.T, fn string, level int, d string) { - // Read dictionary, if given. - var dict []byte - if d != "" { - dict = []byte(d) - } - // Read the file, as golden output. golden, err := os.Open(fn) if err != nil { @@ -33,17 +32,25 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) { return } defer golden.Close() - - // Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end. - raw, err := os.Open(fn) - if err != nil { - t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err) + b0, err0 := ioutil.ReadAll(golden) + if err0 != nil { + t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0) return } + testLevelDict(t, fn, b0, level, d) +} + +func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) { + // Make dictionary, if given. + var dict []byte + if d != "" { + dict = []byte(d) + } + + // Push data through a pipe that compresses at the write end, and decompresses at the read end. piper, pipew := io.Pipe() defer piper.Close() go func() { - defer raw.Close() defer pipew.Close() zlibw, err := NewWriterDict(pipew, level, dict) if err != nil { @@ -51,25 +58,14 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) { return } defer zlibw.Close() - var b [1024]byte - for { - n, err0 := raw.Read(b[0:]) - if err0 != nil && err0 != os.EOF { - t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0) - return - } - _, err1 := zlibw.Write(b[0:n]) - if err1 == os.EPIPE { - // Fail, but do not report the error, as some other (presumably reportable) error broke the pipe. - return - } - if err1 != nil { - t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1) - return - } - if err0 == os.EOF { - break - } + _, err = zlibw.Write(b0) + if err == os.EPIPE { + // Fail, but do not report the error, as some other (presumably reported) error broke the pipe. + return + } + if err != nil { + t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err) + return } }() zlibr, err := NewReaderDict(piper, dict) @@ -79,13 +75,8 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) { } defer zlibr.Close() - // Compare the two. - b0, err0 := ioutil.ReadAll(golden) + // Compare the decompressed data. b1, err1 := ioutil.ReadAll(zlibr) - if err0 != nil { - t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0) - return - } if err1 != nil { t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1) return @@ -103,6 +94,18 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) { } func TestWriter(t *testing.T) { + for i, s := range data { + b := []byte(s) + tag := fmt.Sprintf("#%d", i) + testLevelDict(t, tag, b, DefaultCompression, "") + testLevelDict(t, tag, b, NoCompression, "") + for level := BestSpeed; level <= BestCompression; level++ { + testLevelDict(t, tag, b, level, "") + } + } +} + +func TestWriterBig(t *testing.T) { for _, fn := range filenames { testFileLevelDict(t, fn, DefaultCompression, "") testFileLevelDict(t, fn, NoCompression, "") diff --git a/src/pkg/crypto/cipher/ocfb.go b/src/pkg/crypto/cipher/ocfb.go index b2d877591..031e74a9d 100644 --- a/src/pkg/crypto/cipher/ocfb.go +++ b/src/pkg/crypto/cipher/ocfb.go @@ -80,9 +80,10 @@ type ocfbDecrypter struct { // NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher // feedback mode using the given Block. Prefix must be the first blockSize + 2 // bytes of the ciphertext, where blockSize is the Block's block size. If an -// incorrect key is detected then nil is returned. Resync determines if the -// "resynchronization step" from RFC 4880, 13.9 step 7 is performed. Different -// parts of OpenPGP vary on this point. +// incorrect key is detected then nil is returned. On successful exit, +// blockSize+2 bytes of decrypted data are written into prefix. Resync +// determines if the "resynchronization step" from RFC 4880, 13.9 step 7 is +// performed. Different parts of OpenPGP vary on this point. func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Stream { blockSize := block.BlockSize() if len(prefix) != blockSize+2 { @@ -118,6 +119,7 @@ func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Strea x.fre[1] = prefix[blockSize+1] x.outUsed = 2 } + copy(prefix, prefixCopy) return x } diff --git a/src/pkg/crypto/openpgp/packet/literal.go b/src/pkg/crypto/openpgp/packet/literal.go index 04f50e53e..9411572d7 100644 --- a/src/pkg/crypto/openpgp/packet/literal.go +++ b/src/pkg/crypto/openpgp/packet/literal.go @@ -51,3 +51,40 @@ func (l *LiteralData) parse(r io.Reader) (err os.Error) { l.Body = r return } + +// SerializeLiteral serializes a literal data packet to w and returns a +// WriteCloser to which the data itself can be written and which MUST be closed +// on completion. The fileName is truncated to 255 bytes. +func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err os.Error) { + var buf [4]byte + buf[0] = 't' + if isBinary { + buf[0] = 'b' + } + if len(fileName) > 255 { + fileName = fileName[:255] + } + buf[1] = byte(len(fileName)) + + inner, err := serializeStreamHeader(w, packetTypeLiteralData) + if err != nil { + return + } + + _, err = inner.Write(buf[:2]) + if err != nil { + return + } + _, err = inner.Write([]byte(fileName)) + if err != nil { + return + } + binary.BigEndian.PutUint32(buf[:], time) + _, err = inner.Write(buf[:]) + if err != nil { + return + } + + plaintext = inner + return +} diff --git a/src/pkg/crypto/openpgp/packet/packet.go b/src/pkg/crypto/openpgp/packet/packet.go index e583670fb..640a5b76f 100644 --- a/src/pkg/crypto/openpgp/packet/packet.go +++ b/src/pkg/crypto/openpgp/packet/packet.go @@ -92,6 +92,46 @@ func (r *partialLengthReader) Read(p []byte) (n int, err os.Error) { return } +// partialLengthWriter writes a stream of data using OpenPGP partial lengths. +// See RFC 4880, section 4.2.2.4. +type partialLengthWriter struct { + w io.WriteCloser + lengthByte [1]byte +} + +func (w *partialLengthWriter) Write(p []byte) (n int, err os.Error) { + for len(p) > 0 { + for power := uint(14); power < 32; power-- { + l := 1 << power + if len(p) >= l { + w.lengthByte[0] = 224 + uint8(power) + _, err = w.w.Write(w.lengthByte[:]) + if err != nil { + return + } + var m int + m, err = w.w.Write(p[:l]) + n += m + if err != nil { + return + } + p = p[l:] + break + } + } + } + return +} + +func (w *partialLengthWriter) Close() os.Error { + w.lengthByte[0] = 0 + _, err := w.w.Write(w.lengthByte[:]) + if err != nil { + return err + } + return w.w.Close() +} + // A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the // underlying Reader returns EOF before the limit has been reached. type spanReader struct { @@ -195,6 +235,20 @@ func serializeHeader(w io.Writer, ptype packetType, length int) (err os.Error) { return } +// serializeStreamHeader writes an OpenPGP packet header to w where the +// length of the packet is unknown. It returns a io.WriteCloser which can be +// used to write the contents of the packet. See RFC 4880, section 4.2. +func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err os.Error) { + var buf [1]byte + buf[0] = 0x80 | 0x40 | byte(ptype) + _, err = w.Write(buf[:]) + if err != nil { + return + } + out = &partialLengthWriter{w: w} + return +} + // Packet represents an OpenPGP packet. Users are expected to try casting // instances of this interface to specific packet types. type Packet interface { @@ -327,10 +381,10 @@ const ( type CipherFunction uint8 const ( - CipherCAST5 = 3 - CipherAES128 = 7 - CipherAES192 = 8 - CipherAES256 = 9 + CipherCAST5 CipherFunction = 3 + CipherAES128 CipherFunction = 7 + CipherAES192 CipherFunction = 8 + CipherAES256 CipherFunction = 9 ) // keySize returns the key size, in bytes, of cipher. diff --git a/src/pkg/crypto/openpgp/packet/packet_test.go b/src/pkg/crypto/openpgp/packet/packet_test.go index 1a4692cd4..23d9978ae 100644 --- a/src/pkg/crypto/openpgp/packet/packet_test.go +++ b/src/pkg/crypto/openpgp/packet/packet_test.go @@ -210,3 +210,47 @@ func TestSerializeHeader(t *testing.T) { } } } + +func TestPartialLengths(t *testing.T) { + buf := bytes.NewBuffer(nil) + w := new(partialLengthWriter) + w.w = noOpCloser{buf} + + const maxChunkSize = 64 + + var b [maxChunkSize]byte + var n uint8 + for l := 1; l <= maxChunkSize; l++ { + for i := 0; i < l; i++ { + b[i] = n + n++ + } + m, err := w.Write(b[:l]) + if m != l { + t.Errorf("short write got: %d want: %d", m, l) + } + if err != nil { + t.Errorf("error from write: %s", err) + } + } + w.Close() + + want := (maxChunkSize * (maxChunkSize + 1)) / 2 + copyBuf := bytes.NewBuffer(nil) + r := &partialLengthReader{buf, 0, true} + m, err := io.Copy(copyBuf, r) + if m != int64(want) { + t.Errorf("short copy got: %d want: %d", m, want) + } + if err != nil { + t.Errorf("error from copy: %s", err) + } + + copyBytes := copyBuf.Bytes() + for i := 0; i < want; i++ { + if copyBytes[i] != uint8(i) { + t.Errorf("bad pattern in copy at %d", i) + break + } + } +} diff --git a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go index d9010f88a..25d264acf 100644 --- a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go +++ b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted.go @@ -5,6 +5,7 @@ package packet import ( + "bytes" "crypto/cipher" "crypto/openpgp/error" "crypto/openpgp/s2k" @@ -27,6 +28,8 @@ type SymmetricKeyEncrypted struct { encryptedKey []byte } +const symmetricKeyEncryptedVersion = 4 + func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) { // RFC 4880, section 5.3. var buf [2]byte @@ -34,7 +37,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) { if err != nil { return } - if buf[0] != 4 { + if buf[0] != symmetricKeyEncryptedVersion { return error.UnsupportedError("SymmetricKeyEncrypted version") } ske.CipherFunc = CipherFunction(buf[1]) @@ -100,3 +103,60 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) os.Error { ske.Encrypted = false return nil } + +// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The +// packet contains a random session key, encrypted by a key derived from the +// given passphrase. The session key is returned and must be passed to +// SerializeSymmetricallyEncrypted. +func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err os.Error) { + keySize := cipherFunc.keySize() + if keySize == 0 { + return nil, error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + + s2kBuf := new(bytes.Buffer) + keyEncryptingKey := make([]byte, keySize) + // s2k.Serialize salts and stretches the passphrase, and writes the + // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. + err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase) + if err != nil { + return + } + s2kBytes := s2kBuf.Bytes() + + packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize + err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) + if err != nil { + return + } + + var buf [2]byte + buf[0] = symmetricKeyEncryptedVersion + buf[1] = byte(cipherFunc) + _, err = w.Write(buf[:]) + if err != nil { + return + } + _, err = w.Write(s2kBytes) + if err != nil { + return + } + + sessionKey := make([]byte, keySize) + _, err = io.ReadFull(rand, sessionKey) + if err != nil { + return + } + iv := make([]byte, cipherFunc.blockSize()) + c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) + encryptedCipherAndKey := make([]byte, keySize+1) + c.XORKeyStream(encryptedCipherAndKey, buf[1:]) + c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) + _, err = w.Write(encryptedCipherAndKey) + if err != nil { + return + } + + key = sessionKey + return +} diff --git a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go index 717c8ffa6..823ec400d 100644 --- a/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go +++ b/src/pkg/crypto/openpgp/packet/symmetric_key_encrypted_test.go @@ -6,6 +6,7 @@ package packet import ( "bytes" + "crypto/rand" "encoding/hex" "io/ioutil" "os" @@ -60,3 +61,41 @@ func TestSymmetricKeyEncrypted(t *testing.T) { const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf" const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a" + +func TestSerializeSymmetricKeyEncrypted(t *testing.T) { + buf := bytes.NewBuffer(nil) + passphrase := []byte("testing") + cipherFunc := CipherAES128 + + key, err := SerializeSymmetricKeyEncrypted(buf, rand.Reader, passphrase, cipherFunc) + if err != nil { + t.Errorf("failed to serialize: %s", err) + return + } + + p, err := Read(buf) + if err != nil { + t.Errorf("failed to reparse: %s", err) + return + } + ske, ok := p.(*SymmetricKeyEncrypted) + if !ok { + t.Errorf("parsed a different packet type: %#v", p) + return + } + + if !ske.Encrypted { + t.Errorf("SKE not encrypted but should be") + } + if ske.CipherFunc != cipherFunc { + t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, cipherFunc) + } + err = ske.Decrypt(passphrase) + if err != nil { + t.Errorf("failed to decrypt reparsed SKE: %s", err) + return + } + if !bytes.Equal(key, ske.Key) { + t.Errorf("keys don't match after Decrpyt: %x (original) vs %x (parsed)", key, ske.Key) + } +} diff --git a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go index fc19ffe80..236c36774 100644 --- a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go +++ b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted.go @@ -7,6 +7,7 @@ package packet import ( "crypto/cipher" "crypto/openpgp/error" + "crypto/rand" "crypto/sha1" "crypto/subtle" "hash" @@ -24,6 +25,8 @@ type SymmetricallyEncrypted struct { prefix []byte } +const symmetricallyEncryptedVersion = 1 + func (se *SymmetricallyEncrypted) parse(r io.Reader) os.Error { if se.MDC { // See RFC 4880, section 5.13. @@ -32,7 +35,7 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) os.Error { if err != nil { return err } - if buf[0] != 1 { + if buf[0] != symmetricallyEncryptedVersion { return error.UnsupportedError("unknown SymmetricallyEncrypted version") } } @@ -174,6 +177,9 @@ func (ser *seMDCReader) Read(buf []byte) (n int, err os.Error) { return } +// This is a new-format packet tag byte for a type 19 (MDC) packet. +const mdcPacketTagByte = byte(0x80) | 0x40 | 19 + func (ser *seMDCReader) Close() os.Error { if ser.error { return error.SignatureError("error during reading") @@ -191,16 +197,95 @@ func (ser *seMDCReader) Close() os.Error { } } - // This is a new-format packet tag byte for a type 19 (MDC) packet. - const mdcPacketTagByte = byte(0x80) | 0x40 | 19 if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { return error.SignatureError("MDC packet not found") } ser.h.Write(ser.trailer[:2]) final := ser.h.Sum() - if subtle.ConstantTimeCompare(final, ser.trailer[2:]) == 1 { + if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { return error.SignatureError("hash mismatch") } return nil } + +// An seMDCWriter writes through to an io.WriteCloser while maintains a running +// hash of the data written. On close, it emits an MDC packet containing the +// running hash. +type seMDCWriter struct { + w io.WriteCloser + h hash.Hash +} + +func (w *seMDCWriter) Write(buf []byte) (n int, err os.Error) { + w.h.Write(buf) + return w.w.Write(buf) +} + +func (w *seMDCWriter) Close() (err os.Error) { + var buf [mdcTrailerSize]byte + + buf[0] = mdcPacketTagByte + buf[1] = sha1.Size + w.h.Write(buf[:2]) + digest := w.h.Sum() + copy(buf[2:], digest) + + _, err = w.w.Write(buf[:]) + if err != nil { + return + } + return w.w.Close() +} + +// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err os.Error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() os.Error { + return nil +} + +// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet +// to w and returns a WriteCloser to which the to-be-encrypted packets can be +// written. +func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte) (contents io.WriteCloser, err os.Error) { + if c.keySize() != len(key) { + return nil, error.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") + } + writeCloser := noOpCloser{w} + ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) + if err != nil { + return + } + + _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) + if err != nil { + return + } + + block := c.new(key) + blockSize := block.BlockSize() + iv := make([]byte, blockSize) + _, err = rand.Reader.Read(iv) + if err != nil { + return + } + s, prefix := cipher.NewOCFBEncrypter(block, iv, cipher.OCFBNoResync) + _, err = ciphertext.Write(prefix) + if err != nil { + return + } + plaintext := cipher.StreamWriter{S: s, W: ciphertext} + + h := sha1.New() + h.Write(iv) + h.Write(iv[blockSize-2:]) + contents = &seMDCWriter{w: plaintext, h: h} + return +} diff --git a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go index 5543b2029..ba5606e6c 100644 --- a/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go +++ b/src/pkg/crypto/openpgp/packet/symmetrically_encrypted_test.go @@ -9,6 +9,7 @@ import ( "crypto/openpgp/error" "crypto/sha1" "encoding/hex" + "io" "io/ioutil" "os" "testing" @@ -76,3 +77,48 @@ func testMDCReader(t *testing.T) { } const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980" + +func TestSerialize(t *testing.T) { + buf := bytes.NewBuffer(nil) + c := CipherAES128 + key := make([]byte, c.keySize()) + + w, err := SerializeSymmetricallyEncrypted(buf, c, key) + if err != nil { + t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err) + return + } + + contents := []byte("hello world\n") + + w.Write(contents) + w.Close() + + p, err := Read(buf) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + + se, ok := p.(*SymmetricallyEncrypted) + if !ok { + t.Errorf("didn't read a *SymmetricallyEncrypted") + return + } + + r, err := se.Decrypt(c, key) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + contentsCopy := bytes.NewBuffer(nil) + _, err = io.Copy(contentsCopy, r) + if err != nil { + t.Errorf("error from io.Copy: %s", err) + return + } + if !bytes.Equal(contentsCopy.Bytes(), contents) { + t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents) + } +} diff --git a/src/pkg/crypto/openpgp/s2k/s2k.go b/src/pkg/crypto/openpgp/s2k/s2k.go index 80b81bd3a..da926a76e 100644 --- a/src/pkg/crypto/openpgp/s2k/s2k.go +++ b/src/pkg/crypto/openpgp/s2k/s2k.go @@ -123,6 +123,26 @@ func Parse(r io.Reader) (f func(out, in []byte), err os.Error) { return nil, error.UnsupportedError("S2K function") } +// Serialize salts and stretches the given passphrase and writes the resulting +// key into key. It also serializes an S2K descriptor to w. +func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte) os.Error { + var buf [11]byte + buf[0] = 3 /* iterated and salted */ + buf[1], _ = HashToHashId(crypto.SHA1) + salt := buf[2:10] + if _, err := io.ReadFull(rand, salt); err != nil { + return err + } + const count = 65536 // this is the default in gpg + buf[10] = 96 // 65536 iterations + if _, err := w.Write(buf[:]); err != nil { + return err + } + + Iterated(key, crypto.SHA1.New(), passphrase, salt, count) + return nil +} + // hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with // Go's crypto.Hash type. See RFC 4880, section 9.4. var hashToHashIdMapping = []struct { diff --git a/src/pkg/crypto/openpgp/s2k/s2k_test.go b/src/pkg/crypto/openpgp/s2k/s2k_test.go index 75bc47ec1..27d2e9ae0 100644 --- a/src/pkg/crypto/openpgp/s2k/s2k_test.go +++ b/src/pkg/crypto/openpgp/s2k/s2k_test.go @@ -7,6 +7,7 @@ package s2k import ( "bytes" "crypto/sha1" + "crypto/rand" "encoding/hex" "testing" ) @@ -95,3 +96,26 @@ func TestParse(t *testing.T) { } } } + + +func TestSerialize(t *testing.T) { + buf := bytes.NewBuffer(nil) + key := make([]byte, 16) + passphrase := []byte("testing") + err := Serialize(buf, key, rand.Reader, passphrase) + if err != nil { + t.Errorf("failed to serialize: %s", err) + return + } + + f, err := Parse(buf) + if err != nil { + t.Errorf("failed to reparse: %s", err) + return + } + key2 := make([]byte, len(key)) + f(key2, passphrase) + if !bytes.Equal(key2, key) { + t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2) + } +} diff --git a/src/pkg/crypto/openpgp/write.go b/src/pkg/crypto/openpgp/write.go index a1ede564e..48c86f604 100644 --- a/src/pkg/crypto/openpgp/write.go +++ b/src/pkg/crypto/openpgp/write.go @@ -9,6 +9,7 @@ import ( "crypto/openpgp/armor" "crypto/openpgp/error" "crypto/openpgp/packet" + "crypto/rand" _ "crypto/sha256" "io" "os" @@ -81,3 +82,36 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S return sig.Serialize(w) } + +// FileHints contains metadata about encrypted files. This metadata is, itself, +// encrypted. +type FileHints struct { + // IsBinary can be set to hint that the contents are binary data. + IsBinary bool + // FileName hints at the name of the file that should be written. It's + // truncated to 255 bytes if longer. It may be empty to suggest that the + // file should not be written to disk. It may be equal to "_CONSOLE" to + // suggest the data should not be written to disk. + FileName string + // EpochSeconds contains the modification time of the file, or 0 if not applicable. + EpochSeconds uint32 +} + +// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. +// The resulting WriteCloser MUST be closed after the contents of the file have +// been written. +func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints) (plaintext io.WriteCloser, err os.Error) { + if hints == nil { + hints = &FileHints{} + } + + key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, rand.Reader, passphrase, packet.CipherAES128) + if err != nil { + return + } + w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, packet.CipherAES128, key) + if err != nil { + return + } + return packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, hints.EpochSeconds) +} diff --git a/src/pkg/crypto/openpgp/write_test.go b/src/pkg/crypto/openpgp/write_test.go index a74a84b2b..8551aeb63 100644 --- a/src/pkg/crypto/openpgp/write_test.go +++ b/src/pkg/crypto/openpgp/write_test.go @@ -7,6 +7,8 @@ package openpgp import ( "bytes" "crypto/rand" + "os" + "io" "testing" "time" ) @@ -85,3 +87,36 @@ func TestNewEntity(t *testing.T) { t.Errorf("results differed") } } + +func TestSymmetricEncryption(t *testing.T) { + buf := new(bytes.Buffer) + plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil) + if err != nil { + t.Errorf("error writing headers: %s", err) + return + } + message := []byte("hello world\n") + _, err = plaintext.Write(message) + if err != nil { + t.Errorf("error writing to plaintext writer: %s", err) + } + err = plaintext.Close() + if err != nil { + t.Errorf("error closing plaintext writer: %s", err) + } + + md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, os.Error) { + return []byte("testing"), nil + }) + if err != nil { + t.Errorf("error rereading message: %s", err) + } + messageBuf := bytes.NewBuffer(nil) + _, err = io.Copy(messageBuf, md.UnverifiedBody) + if err != nil { + t.Errorf("error rereading message: %s", err) + } + if !bytes.Equal(message, messageBuf.Bytes()) { + t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message) + } +} diff --git a/src/pkg/crypto/tls/generate_cert.go b/src/pkg/crypto/tls/generate_cert.go index 5b8c700e5..f46188879 100644 --- a/src/pkg/crypto/tls/generate_cert.go +++ b/src/pkg/crypto/tls/generate_cert.go @@ -59,7 +59,7 @@ func main() { certOut.Close() log.Print("written cert.pem\n") - keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0600) + keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Print("failed to open key.pem for writing:", err) return diff --git a/src/pkg/ebnf/ebnf_test.go b/src/pkg/ebnf/ebnf_test.go index e77cf64ad..2055f872a 100644 --- a/src/pkg/ebnf/ebnf_test.go +++ b/src/pkg/ebnf/ebnf_test.go @@ -22,7 +22,7 @@ var grammars = []string{ `Program = "a" | "b" "c" .`, - `Program = "a" ... "z" .`, + `Program = "a" … "z" .`, `Program = Song . Song = { Note } . diff --git a/src/pkg/ebnf/parser.go b/src/pkg/ebnf/parser.go index 818168e11..166412f99 100644 --- a/src/pkg/ebnf/parser.go +++ b/src/pkg/ebnf/parser.go @@ -95,7 +95,8 @@ func (p *parser) parseTerm() (x Expression) { case token.STRING: tok := p.parseToken() x = tok - if p.tok == token.ELLIPSIS { + const ellipsis = "…" // U+2026, the horizontal ellipsis character + if p.tok == token.ILLEGAL && p.lit == ellipsis { p.next() x = &Range{tok, p.parseToken()} } @@ -177,7 +178,7 @@ func (p *parser) parse(fset *token.FileSet, filename string, src []byte) Grammar // initialize parser p.fset = fset p.ErrorVector.Reset() - p.scanner.Init(fset.AddFile(filename, fset.Base(), len(src)), src, p, 0) + p.scanner.Init(fset.AddFile(filename, fset.Base(), len(src)), src, p, scanner.AllowIllegalChars) p.next() // initializes pos, tok, lit grammar := make(Grammar) diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go index 496129798..c6b2a13e4 100644 --- a/src/pkg/encoding/base64/base64.go +++ b/src/pkg/encoding/base64/base64.go @@ -106,6 +106,13 @@ func (enc *Encoding) Encode(dst, src []byte) { } } +// EncodeToString returns the base64 encoding of src. +func (enc *Encoding) EncodeToString(src []byte) string { + buf := make([]byte, enc.EncodedLen(len(src))) + enc.Encode(buf, src) + return string(buf) +} + type encoder struct { err os.Error enc *Encoding @@ -260,6 +267,13 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err os.Error) { return } +// DecodeString returns the bytes represented by the base64 string s. +func (enc *Encoding) DecodeString(s string) ([]byte, os.Error) { + dbuf := make([]byte, enc.DecodedLen(len(s))) + n, err := enc.Decode(dbuf, []byte(s)) + return dbuf[:n], err +} + type decoder struct { err os.Error enc *Encoding diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go index de41e704b..c163dae84 100644 --- a/src/pkg/encoding/base64/base64_test.go +++ b/src/pkg/encoding/base64/base64_test.go @@ -56,9 +56,8 @@ func testEqual(t *testing.T, msg string, args ...interface{}) bool { func TestEncode(t *testing.T) { for _, p := range pairs { - buf := make([]byte, StdEncoding.EncodedLen(len(p.decoded))) - StdEncoding.Encode(buf, []byte(p.decoded)) - testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded) + got := StdEncoding.EncodeToString([]byte(p.decoded)) + testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded) } } @@ -102,6 +101,10 @@ func TestDecode(t *testing.T) { testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '=')) } testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) + + dbuf, err = StdEncoding.DecodeString(p.encoded) + testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, os.Error(nil)) + testEqual(t, "DecodeString(%q) = %q, want %q", string(dbuf), p.decoded) } } diff --git a/src/pkg/encoding/binary/binary.go b/src/pkg/encoding/binary/binary.go index a01d0e024..8e55cb23b 100644 --- a/src/pkg/encoding/binary/binary.go +++ b/src/pkg/encoding/binary/binary.go @@ -125,6 +125,35 @@ func (bigEndian) GoString() string { return "binary.BigEndian" } // Bytes read from r are decoded using the specified byte order // and written to successive fields of the data. func Read(r io.Reader, order ByteOrder, data interface{}) os.Error { + // Fast path for basic types. + if n := intDestSize(data); n != 0 { + var b [8]byte + bs := b[:n] + if _, err := io.ReadFull(r, bs); err != nil { + return err + } + switch v := data.(type) { + case *int8: + *v = int8(b[0]) + case *uint8: + *v = b[0] + case *int16: + *v = int16(order.Uint16(bs)) + case *uint16: + *v = order.Uint16(bs) + case *int32: + *v = int32(order.Uint32(bs)) + case *uint32: + *v = order.Uint32(bs) + case *int64: + *v = int64(order.Uint64(bs)) + case *uint64: + *v = order.Uint64(bs) + } + return nil + } + + // Fallback to reflect-based. var v reflect.Value switch d := reflect.ValueOf(data); d.Kind() { case reflect.Ptr: @@ -155,6 +184,63 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error { // Bytes written to w are encoded using the specified byte order // and read from successive fields of the data. func Write(w io.Writer, order ByteOrder, data interface{}) os.Error { + // Fast path for basic types. + var b [8]byte + var bs []byte + switch v := data.(type) { + case *int8: + bs = b[:1] + b[0] = byte(*v) + case int8: + bs = b[:1] + b[0] = byte(v) + case *uint8: + bs = b[:1] + b[0] = *v + case uint8: + bs = b[:1] + b[0] = byte(v) + case *int16: + bs = b[:2] + order.PutUint16(bs, uint16(*v)) + case int16: + bs = b[:2] + order.PutUint16(bs, uint16(v)) + case *uint16: + bs = b[:2] + order.PutUint16(bs, *v) + case uint16: + bs = b[:2] + order.PutUint16(bs, v) + case *int32: + bs = b[:4] + order.PutUint32(bs, uint32(*v)) + case int32: + bs = b[:4] + order.PutUint32(bs, uint32(v)) + case *uint32: + bs = b[:4] + order.PutUint32(bs, *v) + case uint32: + bs = b[:4] + order.PutUint32(bs, v) + case *int64: + bs = b[:8] + order.PutUint64(bs, uint64(*v)) + case int64: + bs = b[:8] + order.PutUint64(bs, uint64(v)) + case *uint64: + bs = b[:8] + order.PutUint64(bs, *v) + case uint64: + bs = b[:8] + order.PutUint64(bs, v) + } + if bs != nil { + _, err := w.Write(bs) + return err + } v := reflect.Indirect(reflect.ValueOf(data)) size := TotalSize(v) if size < 0 { @@ -394,3 +480,19 @@ func (e *encoder) value(v reflect.Value) { } } } + +// intDestSize returns the size of the integer that ptrType points to, +// or 0 if the type is not supported. +func intDestSize(ptrType interface{}) int { + switch ptrType.(type) { + case *int8, *uint8: + return 1 + case *int16, *uint16: + return 2 + case *int32, *uint32: + return 4 + case *int64, *uint64: + return 8 + } + return 0 +} diff --git a/src/pkg/encoding/binary/binary_test.go b/src/pkg/encoding/binary/binary_test.go index 7857c68d3..b266996f6 100644 --- a/src/pkg/encoding/binary/binary_test.go +++ b/src/pkg/encoding/binary/binary_test.go @@ -5,6 +5,7 @@ package binary import ( + "io" "os" "bytes" "math" @@ -160,3 +161,75 @@ func TestWriteT(t *testing.T) { } } } + +type byteSliceReader struct { + remain []byte +} + +func (br *byteSliceReader) Read(p []byte) (int, os.Error) { + n := copy(p, br.remain) + br.remain = br.remain[n:] + return n, nil +} + +func BenchmarkRead(b *testing.B) { + var ls Struct + bsr := &byteSliceReader{} + var r io.Reader = bsr + + for i := 0; i < b.N; i++ { + bsr.remain = big + Read(r, BigEndian, &ls.Int8) + Read(r, BigEndian, &ls.Int16) + Read(r, BigEndian, &ls.Int32) + Read(r, BigEndian, &ls.Int64) + Read(r, BigEndian, &ls.Uint8) + Read(r, BigEndian, &ls.Uint16) + Read(r, BigEndian, &ls.Uint32) + Read(r, BigEndian, &ls.Uint64) + } + + want := s + want.Float32 = 0 + want.Float64 = 0 + want.Complex64 = 0 + want.Complex128 = 0 + for i := range want.Array { + want.Array[i] = 0 + } + if !reflect.DeepEqual(ls, want) { + panic("no match") + } +} + +func BenchmarkWrite(b *testing.B) { + buf := new(bytes.Buffer) + var w io.Writer = buf + + for i := 0; i < b.N; i++ { + buf.Reset() + Write(w, BigEndian, &s.Int8) + Write(w, BigEndian, &s.Int16) + Write(w, BigEndian, &s.Int32) + Write(w, BigEndian, &s.Int64) + Write(w, BigEndian, &s.Uint8) + Write(w, BigEndian, &s.Uint16) + Write(w, BigEndian, &s.Uint32) + Write(w, BigEndian, &s.Uint64) + Write(w, BigEndian, s.Int8) + Write(w, BigEndian, s.Int16) + Write(w, BigEndian, s.Int32) + Write(w, BigEndian, s.Int64) + Write(w, BigEndian, s.Uint8) + Write(w, BigEndian, s.Uint16) + Write(w, BigEndian, s.Uint32) + Write(w, BigEndian, s.Uint64) + } + + if !bytes.Equal(buf.Bytes()[:30], big[:30]) { + panic("first half doesn't match") + } + if !bytes.Equal(buf.Bytes()[30:], big[:30]) { + panic("second half doesn't match") + } +} diff --git a/src/pkg/encoding/hex/hex.go b/src/pkg/encoding/hex/hex.go index 891de1861..47cdedd60 100644 --- a/src/pkg/encoding/hex/hex.go +++ b/src/pkg/encoding/hex/hex.go @@ -6,6 +6,8 @@ package hex import ( + "bytes" + "io" "os" "strconv" ) @@ -99,3 +101,117 @@ func DecodeString(s string) ([]byte, os.Error) { } return dst, nil } + +// Dump returns a string that contains a hex dump of the given data. The format +// of the hex dump matches the output of `hexdump -C` on the command line. +func Dump(data []byte) string { + buf := bytes.NewBuffer(nil) + dumper := Dumper(buf) + dumper.Write(data) + dumper.Close() + return string(buf.Bytes()) +} + +// Dumper returns a WriteCloser that writes a hex dump of all written data to +// w. The format of the dump matches the output of `hexdump -C` on the command +// line. +func Dumper(w io.Writer) io.WriteCloser { + return &dumper{w: w} +} + +type dumper struct { + w io.Writer + rightChars [18]byte + buf [14]byte + used int // number of bytes in the current line + n uint // number of bytes, total +} + +func toChar(b byte) byte { + if b < 32 || b > 126 { + return '.' + } + return b +} + +func (h *dumper) Write(data []byte) (n int, err os.Error) { + // Output lines look like: + // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| + // ^ offset ^ extra space ^ ASCII of line. + for i := range data { + if h.used == 0 { + // At the beginning of a line we print the current + // offset in hex. + h.buf[0] = byte(h.n >> 24) + h.buf[1] = byte(h.n >> 16) + h.buf[2] = byte(h.n >> 8) + h.buf[3] = byte(h.n) + Encode(h.buf[4:], h.buf[:4]) + h.buf[12] = ' ' + h.buf[13] = ' ' + _, err = h.w.Write(h.buf[4:]) + } + Encode(h.buf[:], data[i:i+1]) + h.buf[2] = ' ' + l := 3 + if h.used == 7 { + // There's an additional space after the 8th byte. + h.buf[3] = ' ' + l = 4 + } else if h.used == 15 { + // At the end of the line there's an extra space and + // the bar for the right column. + h.buf[3] = ' ' + h.buf[4] = '|' + l = 5 + } + _, err = h.w.Write(h.buf[:l]) + if err != nil { + return + } + n++ + h.rightChars[h.used] = toChar(data[i]) + h.used++ + h.n++ + if h.used == 16 { + h.rightChars[16] = '|' + h.rightChars[17] = '\n' + _, err = h.w.Write(h.rightChars[:]) + if err != nil { + return + } + h.used = 0 + } + } + return +} + +func (h *dumper) Close() (err os.Error) { + // See the comments in Write() for the details of this format. + if h.used == 0 { + return + } + h.buf[0] = ' ' + h.buf[1] = ' ' + h.buf[2] = ' ' + h.buf[3] = ' ' + h.buf[4] = '|' + nBytes := h.used + for h.used < 16 { + l := 3 + if h.used == 7 { + l = 4 + } else if h.used == 15 { + l = 5 + } + _, err = h.w.Write(h.buf[:l]) + if err != nil { + return + } + h.used++ + } + h.rightChars[nBytes] = '|' + h.rightChars[nBytes+1] = '\n' + _, err = h.w.Write(h.rightChars[:nBytes+2]) + return +} diff --git a/src/pkg/encoding/hex/hex_test.go b/src/pkg/encoding/hex/hex_test.go index a14c9d4f4..8e1838e51 100644 --- a/src/pkg/encoding/hex/hex_test.go +++ b/src/pkg/encoding/hex/hex_test.go @@ -147,3 +147,46 @@ func TestDecodeString(t *testing.T) { } } } + +func TestDumper(t *testing.T) { + var in [40]byte + for i := range in { + in[i] = byte(i + 30) + } + + for stride := 1; stride < len(in); stride++ { + out := bytes.NewBuffer(nil) + dumper := Dumper(out) + done := 0 + for done < len(in) { + todo := done + stride + if todo > len(in) { + todo = len(in) + } + dumper.Write(in[done:todo]) + done = todo + } + + dumper.Close() + if !bytes.Equal(out.Bytes(), expectedHexDump) { + t.Errorf("stride: %d failed. got:\n%s\nwant:\n%s", stride, out.Bytes(), expectedHexDump) + } + } +} + +func TestDump(t *testing.T) { + var in [40]byte + for i := range in { + in[i] = byte(i + 30) + } + + out := []byte(Dump(in[:])) + if !bytes.Equal(out, expectedHexDump) { + t.Errorf("got:\n%s\nwant:\n%s", out, expectedHexDump) + } +} + +var expectedHexDump = []byte(`00000000 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d |.. !"#$%&'()*+,-| +00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| +00000020 3e 3f 40 41 42 43 44 45 |>?@ABCDE| +`) diff --git a/src/pkg/encoding/line/Makefile b/src/pkg/encoding/line/Makefile deleted file mode 100644 index 1af355c27..000000000 --- a/src/pkg/encoding/line/Makefile +++ /dev/null @@ -1,11 +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. - -include ../../../Make.inc - -TARG=encoding/line -GOFILES=\ - line.go\ - -include ../../../Make.pkg diff --git a/src/pkg/encoding/line/line.go b/src/pkg/encoding/line/line.go deleted file mode 100644 index 123962b1f..000000000 --- a/src/pkg/encoding/line/line.go +++ /dev/null @@ -1,115 +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. - -// Package line implements a Reader that reads lines delimited by '\n' or -// ' \r\n'. -package line - -import ( - "io" - "os" -) - -// Reader reads lines, delimited by '\n' or \r\n', from an io.Reader. -type Reader struct { - buf []byte - consumed int - in io.Reader - err os.Error -} - -// NewReader returns a new Reader that will read successive -// lines from the input Reader. -func NewReader(input io.Reader, maxLineLength int) *Reader { - return &Reader{ - buf: make([]byte, 0, maxLineLength), - consumed: 0, - in: input, - } -} - -// Read reads from any buffered data past the last line read, or from the underlying -// io.Reader if the buffer is empty. -func (l *Reader) Read(p []byte) (n int, err os.Error) { - l.removeConsumedFromBuffer() - if len(l.buf) > 0 { - n = copy(p, l.buf) - l.consumed += n - return - } - return l.in.Read(p) -} - -func (l *Reader) removeConsumedFromBuffer() { - if l.consumed > 0 { - n := copy(l.buf, l.buf[l.consumed:]) - l.buf = l.buf[:n] - l.consumed = 0 - } -} - -// ReadLine tries to return a single line, not including the end-of-line bytes. -// If the line was found to be longer than the maximum length then isPrefix is -// set and the beginning of the line is returned. The rest of the line will be -// returned from future calls. isPrefix will be false when returning the last -// fragment of the line. The returned buffer points into the internal state of -// the Reader and is only valid until the next call to ReadLine. ReadLine -// either returns a non-nil line or it returns an error, never both. -func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) { - l.removeConsumedFromBuffer() - - if len(l.buf) == 0 && l.err != nil { - err = l.err - return - } - - scannedTo := 0 - - for { - i := scannedTo - for ; i < len(l.buf); i++ { - if l.buf[i] == '\r' && len(l.buf) > i+1 && l.buf[i+1] == '\n' { - line = l.buf[:i] - l.consumed = i + 2 - return - } else if l.buf[i] == '\n' { - line = l.buf[:i] - l.consumed = i + 1 - return - } - } - - if i == cap(l.buf) { - line = l.buf[:i] - l.consumed = i - isPrefix = true - return - } - - if l.err != nil { - line = l.buf - l.consumed = i - return - } - - // We don't want to rescan the input that we just scanned. - // However, we need to back up one byte because the last byte - // could have been a '\r' and we do need to rescan that. - scannedTo = i - if scannedTo > 0 { - scannedTo-- - } - oldLen := len(l.buf) - l.buf = l.buf[:cap(l.buf)] - n, readErr := l.in.Read(l.buf[oldLen:]) - l.buf = l.buf[:oldLen+n] - if readErr != nil { - l.err = readErr - if len(l.buf) == 0 { - return nil, false, readErr - } - } - } - panic("unreachable") -} diff --git a/src/pkg/encoding/line/line_test.go b/src/pkg/encoding/line/line_test.go deleted file mode 100644 index ff3d51669..000000000 --- a/src/pkg/encoding/line/line_test.go +++ /dev/null @@ -1,133 +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. - -package line - -import ( - "bytes" - "io" - "io/ioutil" - "os" - "testing" -) - -var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy") -var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy") -var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n") - -// TestReader wraps a []byte and returns reads of a specific length. -type testReader struct { - data []byte - stride int -} - -func (t *testReader) Read(buf []byte) (n int, err os.Error) { - n = t.stride - if n > len(t.data) { - n = len(t.data) - } - if n > len(buf) { - n = len(buf) - } - copy(buf, t.data) - t.data = t.data[n:] - if len(t.data) == 0 { - err = os.EOF - } - return -} - -func testLineReader(t *testing.T, input []byte) { - for stride := 1; stride < len(input); stride++ { - done := 0 - reader := testReader{input, stride} - l := NewReader(&reader, len(input)+1) - for { - line, isPrefix, err := l.ReadLine() - if len(line) > 0 && err != nil { - t.Errorf("ReadLine returned both data and error: %s", err) - } - if isPrefix { - t.Errorf("ReadLine returned prefix") - } - if err != nil { - if err != os.EOF { - t.Fatalf("Got unknown error: %s", err) - } - break - } - if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) { - t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line) - } - done += len(line) - } - if done != len(testOutput) { - t.Error("ReadLine didn't return everything") - } - } -} - -func TestReader(t *testing.T) { - testLineReader(t, testInput) - testLineReader(t, testInputrn) -} - -func TestLineTooLong(t *testing.T) { - buf := bytes.NewBuffer([]byte("aaabbbcc\n")) - l := NewReader(buf, 3) - line, isPrefix, err := l.ReadLine() - if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil { - t.Errorf("bad result for first line: %x %s", line, err) - } - line, isPrefix, err = l.ReadLine() - if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil { - t.Errorf("bad result for second line: %x", line) - } - line, isPrefix, err = l.ReadLine() - if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil { - t.Errorf("bad result for third line: %x", line) - } -} - -func TestReadAfterLines(t *testing.T) { - line1 := "line1" - restData := "line2\nline 3\n" - inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData)) - outbuf := new(bytes.Buffer) - maxLineLength := len(line1) + len(restData)/2 - l := NewReader(inbuf, maxLineLength) - line, isPrefix, err := l.ReadLine() - if isPrefix || err != nil || string(line) != line1 { - t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line)) - } - n, err := io.Copy(outbuf, l) - if int(n) != len(restData) || err != nil { - t.Errorf("bad result for Read: n=%d err=%v", n, err) - } - if outbuf.String() != restData { - t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData) - } -} - -func TestReadEmptyBuffer(t *testing.T) { - l := NewReader(bytes.NewBuffer(nil), 10) - line, isPrefix, err := l.ReadLine() - if err != os.EOF { - t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err) - } -} - -func TestLinesAfterRead(t *testing.T) { - l := NewReader(bytes.NewBuffer([]byte("foo")), 10) - _, err := ioutil.ReadAll(l) - if err != nil { - t.Error(err) - return - } - - line, isPrefix, err := l.ReadLine() - if err != os.EOF { - t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err) - } -} diff --git a/src/pkg/exec/exec.go b/src/pkg/exec/exec.go index 043f84728..c6a5e06bb 100644 --- a/src/pkg/exec/exec.go +++ b/src/pkg/exec/exec.go @@ -7,198 +7,361 @@ // adjustments. package exec -// BUG(r): This package should be made even easier to use or merged into os. - import ( + "bytes" + "io" "os" "strconv" ) -// Arguments to Run. -const ( - DevNull = iota - PassThrough - Pipe - MergeWithStdout -) +// Error records the name of a binary that failed to be be executed +// and the reason it failed. +type Error struct { + Name string + Error os.Error +} -// A Cmd represents a running command. -// Stdin, Stdout, and Stderr are Files representing pipes -// connected to the running command's standard input, output, and error, -// or else nil, depending on the arguments to Run. -// Process represents the underlying operating system process. +func (e *Error) String() string { + return "exec: " + strconv.Quote(e.Name) + ": " + e.Error.String() +} + +// Cmd represents an external command being prepared or run. type Cmd struct { - Stdin *os.File - Stdout *os.File - Stderr *os.File - Process *os.Process + // Path is the path of the command to run. + // + // This is the only field that must be set to a non-zero + // value. + Path string + + // Args holds command line arguments, including the command as Args[0]. + // If the Args field is empty or nil, Run uses {Path}. + // + // In typical use, both Path and Args are set by calling Command. + Args []string + + // Env specifies the environment of the process. + // If Env is nil, Run uses the current process's environment. + Env []string + + // Dir specifies the working directory of the command. + // If Dir is the empty string, Run runs the command in the + // calling process's current directory. + Dir string + + // Stdin specifies the process's standard input. + // If Stdin is nil, the process reads from DevNull. + Stdin io.Reader + + // Stdout and Stderr specify the process's standard output and error. + // + // If either is nil, Run connects the + // corresponding file descriptor to /dev/null. + // + // If Stdout and Stderr are are the same writer, at most one + // goroutine at a time will call Write. + Stdout io.Writer + Stderr io.Writer + + err os.Error // last error (from LookPath, stdin, stdout, stderr) + process *os.Process + finished bool // when Wait was called + childFiles []*os.File + closeAfterStart []io.Closer + closeAfterWait []io.Closer + goroutine []func() os.Error + errch chan os.Error // one send per goroutine +} + +// Command returns the Cmd struct to execute the named program with +// the given arguments. +// +// It sets Path and Args in the returned structure and zeroes the +// other fields. +// +// If name contains no path separators, Command uses LookPath to +// resolve the path to a complete name if possible. Otherwise it uses +// name directly. +// +// The returned Cmd's Args field is constructed from the command name +// followed by the elements of arg, so arg should not include the +// command name itself. For example, Command("echo", "hello") +func Command(name string, arg ...string) *Cmd { + aname, err := LookPath(name) + if err != nil { + aname = name + } + return &Cmd{ + Path: aname, + Args: append([]string{name}, arg...), + err: err, + } } -// PathError records the name of a binary that was not -// found on the current $PATH. -type PathError struct { - Name string +// interfaceEqual protects against panics from doing equality tests on +// two interfaces with non-comparable underlying types +func interfaceEqual(a, b interface{}) bool { + defer func() { + recover() + }() + return a == b } -func (e *PathError) String() string { - return "command " + strconv.Quote(e.Name) + " not found in $PATH" +func (c *Cmd) envv() []string { + if c.Env != nil { + return c.Env + } + return os.Environ() } -// Given mode (DevNull, etc), return file for child -// and file to record in Cmd structure. -func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) { - switch mode { - case DevNull: - rw := os.O_WRONLY - if fd == 0 { - rw = os.O_RDONLY - } - f, err := os.OpenFile(os.DevNull, rw, 0) - return f, nil, err - case PassThrough: - switch fd { - case 0: - return os.Stdin, nil, nil - case 1: - return os.Stdout, nil, nil - case 2: - return os.Stderr, nil, nil +func (c *Cmd) argv() []string { + if len(c.Args) > 0 { + return c.Args + } + return []string{c.Path} +} + +func (c *Cmd) stdin() (f *os.File, err os.Error) { + if c.Stdin == nil { + f, err = os.Open(os.DevNull) + c.closeAfterStart = append(c.closeAfterStart, f) + return + } + + if f, ok := c.Stdin.(*os.File); ok { + return f, nil + } + + pr, pw, err := os.Pipe() + if err != nil { + return + } + + c.closeAfterStart = append(c.closeAfterStart, pr) + c.closeAfterWait = append(c.closeAfterWait, pw) + c.goroutine = append(c.goroutine, func() os.Error { + _, err := io.Copy(pw, c.Stdin) + if err1 := pw.Close(); err == nil { + err = err1 } - case Pipe: - r, w, err := os.Pipe() + return err + }) + return pr, nil +} + +func (c *Cmd) stdout() (f *os.File, err os.Error) { + return c.writerDescriptor(c.Stdout) +} + +func (c *Cmd) stderr() (f *os.File, err os.Error) { + if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) { + return c.childFiles[1], nil + } + return c.writerDescriptor(c.Stderr) +} + +func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err os.Error) { + if w == nil { + f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0) + c.closeAfterStart = append(c.closeAfterStart, f) + return + } + + if f, ok := w.(*os.File); ok { + return f, nil + } + + pr, pw, err := os.Pipe() + if err != nil { + return + } + + c.closeAfterStart = append(c.closeAfterStart, pw) + c.closeAfterWait = append(c.closeAfterWait, pr) + c.goroutine = append(c.goroutine, func() os.Error { + _, err := io.Copy(w, pr) + return err + }) + return pw, nil +} + +// Run starts the specified command and waits for it to complete. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the command fails to run or doesn't complete successfully, the +// error is of type *os.Waitmsg. Other error types may be +// returned for I/O problems. +func (c *Cmd) Run() os.Error { + if err := c.Start(); err != nil { + return err + } + return c.Wait() +} + +// Start starts the specified command but does not wait for it to complete. +func (c *Cmd) Start() os.Error { + if c.err != nil { + return c.err + } + if c.process != nil { + return os.NewError("exec: already started") + } + + type F func(*Cmd) (*os.File, os.Error) + for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { + fd, err := setupFd(c) if err != nil { - return nil, nil, err - } - if fd == 0 { - return r, w, nil + return err } - return w, r, nil + c.childFiles = append(c.childFiles, fd) + } + + var err os.Error + c.process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ + Dir: c.Dir, + Files: c.childFiles, + Env: c.envv(), + }) + if err != nil { + return err + } + + for _, fd := range c.closeAfterStart { + fd.Close() + } + + c.errch = make(chan os.Error, len(c.goroutine)) + for _, fn := range c.goroutine { + go func(fn func() os.Error) { + c.errch <- fn() + }(fn) } - return nil, nil, os.EINVAL + + return nil } -// Run starts the named binary running with -// arguments argv and environment envv. -// If the dir argument is not empty, the child changes -// into the directory before executing the binary. -// It returns a pointer to a new Cmd representing -// the command or an error. +// Wait waits for the command to exit. +// It must have been started by Start. // -// The arguments stdin, stdout, and stderr -// specify how to handle standard input, output, and error. -// The choices are DevNull (connect to /dev/null), -// PassThrough (connect to the current process's standard stream), -// Pipe (connect to an operating system pipe), and -// MergeWithStdout (only for standard error; use the same -// file descriptor as was used for standard output). -// If an argument is Pipe, then the corresponding field (Stdin, Stdout, Stderr) -// of the returned Cmd is the other end of the pipe. -// Otherwise the field in Cmd is nil. -func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) { - c = new(Cmd) - var fd [3]*os.File - - if fd[0], c.Stdin, err = modeToFiles(stdin, 0); err != nil { - goto Error - } - if fd[1], c.Stdout, err = modeToFiles(stdout, 1); err != nil { - goto Error - } - if stderr == MergeWithStdout { - fd[2] = fd[1] - } else if fd[2], c.Stderr, err = modeToFiles(stderr, 2); err != nil { - goto Error - } - - // Run command. - c.Process, err = os.StartProcess(name, argv, &os.ProcAttr{Dir: dir, Files: fd[:], Env: envv}) - if err != nil { - goto Error +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the command fails to run or doesn't complete successfully, the +// error is of type *os.Waitmsg. Other error types may be +// returned for I/O problems. +func (c *Cmd) Wait() os.Error { + if c.process == nil { + return os.NewError("exec: not started") } - if fd[0] != os.Stdin { - fd[0].Close() + if c.finished { + return os.NewError("exec: Wait was already called") } - if fd[1] != os.Stdout { - fd[1].Close() + c.finished = true + msg, err := c.process.Wait(0) + + var copyError os.Error + for _ = range c.goroutine { + if err := <-c.errch; err != nil && copyError == nil { + copyError = err + } } - if fd[2] != os.Stderr && fd[2] != fd[1] { - fd[2].Close() + + for _, fd := range c.closeAfterWait { + fd.Close() } - return c, nil -Error: - if fd[0] != os.Stdin && fd[0] != nil { - fd[0].Close() + if err != nil { + return err + } else if !msg.Exited() || msg.ExitStatus() != 0 { + return msg } - if fd[1] != os.Stdout && fd[1] != nil { - fd[1].Close() + + return copyError +} + +// Output runs the command and returns its standard output. +func (c *Cmd) Output() ([]byte, os.Error) { + if c.Stdout != nil { + return nil, os.NewError("exec: Stdout already set") } - if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] { - fd[2].Close() + var b bytes.Buffer + c.Stdout = &b + err := c.Run() + return b.Bytes(), err +} + +// CombinedOutput runs the command and returns its combined standard +// output and standard error. +func (c *Cmd) CombinedOutput() ([]byte, os.Error) { + if c.Stdout != nil { + return nil, os.NewError("exec: Stdout already set") + } + if c.Stderr != nil { + return nil, os.NewError("exec: Stderr already set") } + var b bytes.Buffer + c.Stdout = &b + c.Stderr = &b + err := c.Run() + return b.Bytes(), err +} + +// StdinPipe returns a pipe that will be connected to the command's +// standard input when the command starts. +func (c *Cmd) StdinPipe() (io.WriteCloser, os.Error) { if c.Stdin != nil { - c.Stdin.Close() + return nil, os.NewError("exec: Stdin already set") + } + if c.process != nil { + return nil, os.NewError("exec: StdinPipe after process started") } + pr, pw, err := os.Pipe() + if err != nil { + return nil, err + } + c.Stdin = pr + c.closeAfterStart = append(c.closeAfterStart, pr) + c.closeAfterWait = append(c.closeAfterStart, pw) + return pw, nil +} + +// StdoutPipe returns a pipe that will be connected to the command's +// standard output when the command starts. +func (c *Cmd) StdoutPipe() (io.Reader, os.Error) { if c.Stdout != nil { - c.Stdout.Close() + return nil, os.NewError("exec: Stdout already set") } - if c.Stderr != nil { - c.Stderr.Close() - } - if c.Process != nil { - c.Process.Release() - } - return nil, err -} - -// Wait waits for the running command c, -// returning the Waitmsg returned when the process exits. -// The options are passed to the process's Wait method. -// Setting options to 0 waits for c to exit; -// other options cause Wait to return for other -// process events; see package os for details. -func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) { - if c.Process == nil { - return nil, os.ErrorString("exec: invalid use of Cmd.Wait") - } - w, err := c.Process.Wait(options) - if w != nil && (w.Exited() || w.Signaled()) { - c.Process.Release() - c.Process = nil - } - return w, err -} - -// Close waits for the running command c to exit, -// if it hasn't already, and then closes the non-nil file descriptors -// c.Stdin, c.Stdout, and c.Stderr. -func (c *Cmd) Close() os.Error { - if c.Process != nil { - // Loop on interrupt, but - // ignore other errors -- maybe - // caller has already waited for pid. - _, err := c.Wait(0) - for err == os.EINTR { - _, err = c.Wait(0) - } + if c.process != nil { + return nil, os.NewError("exec: StdoutPipe after process started") } + pr, pw, err := os.Pipe() + if err != nil { + return nil, err + } + c.Stdout = pw + c.closeAfterStart = append(c.closeAfterStart, pw) + c.closeAfterWait = append(c.closeAfterStart, pr) + return pr, nil +} - // Close the FDs that are still open. - var err os.Error - if c.Stdin != nil && c.Stdin.Fd() >= 0 { - if err1 := c.Stdin.Close(); err1 != nil { - err = err1 - } +// StderrPipe returns a pipe that will be connected to the command's +// standard error when the command starts. +func (c *Cmd) StderrPipe() (io.Reader, os.Error) { + if c.Stderr != nil { + return nil, os.NewError("exec: Stderr already set") } - if c.Stdout != nil && c.Stdout.Fd() >= 0 { - if err1 := c.Stdout.Close(); err1 != nil && err != nil { - err = err1 - } + if c.process != nil { + return nil, os.NewError("exec: StderrPipe after process started") } - if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 { - if err1 := c.Stderr.Close(); err1 != nil && err != nil { - err = err1 - } + pr, pw, err := os.Pipe() + if err != nil { + return nil, err } - return err + c.Stderr = pw + c.closeAfterStart = append(c.closeAfterStart, pw) + c.closeAfterWait = append(c.closeAfterStart, pr) + return pr, nil } diff --git a/src/pkg/exec/exec_test.go b/src/pkg/exec/exec_test.go index eb8cd5fec..c45a7d70a 100644 --- a/src/pkg/exec/exec_test.go +++ b/src/pkg/exec/exec_test.go @@ -5,163 +5,211 @@ package exec import ( + "bufio" + "bytes" + "fmt" "io" - "io/ioutil" "testing" "os" + "strconv" + "strings" ) -func run(argv []string, stdin, stdout, stderr int) (p *Cmd, err os.Error) { - exe, err := LookPath(argv[0]) - if err != nil { - return nil, err - } - return Run(exe, argv, nil, "", stdin, stdout, stderr) +func helperCommand(s ...string) *Cmd { + cs := []string{"-test.run=exec.TestHelperProcess", "--"} + cs = append(cs, s...) + cmd := Command(os.Args[0], cs...) + cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...) + return cmd } -func TestRunCat(t *testing.T) { - cmd, err := run([]string{"cat"}, Pipe, Pipe, DevNull) +func TestEcho(t *testing.T) { + bs, err := helperCommand("echo", "foo bar", "baz").Output() if err != nil { - t.Fatal("run:", err) - } - io.WriteString(cmd.Stdin, "hello, world\n") - cmd.Stdin.Close() - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) - } - if string(buf) != "hello, world\n" { - t.Fatalf("read: got %q", buf) + t.Errorf("echo: %v", err) } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + if g, e := string(bs), "foo bar baz\n"; g != e { + t.Errorf("echo: want %q, got %q", e, g) } } -func TestRunEcho(t *testing.T) { - cmd, err := run([]string{"sh", "-c", "echo hello world"}, - DevNull, Pipe, DevNull) +func TestCatStdin(t *testing.T) { + // Cat, testing stdin and stdout. + input := "Input string\nLine 2" + p := helperCommand("cat") + p.Stdin = strings.NewReader(input) + bs, err := p.Output() if err != nil { - t.Fatal("run:", err) + t.Errorf("cat: %v", err) } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) - } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) - } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + s := string(bs) + if s != input { + t.Errorf("cat: want %q, got %q", input, s) } } -func TestStderr(t *testing.T) { - cmd, err := run([]string{"sh", "-c", "echo hello world 1>&2"}, - DevNull, DevNull, Pipe) - if err != nil { - t.Fatal("run:", err) +func TestCatGoodAndBadFile(t *testing.T) { + // Testing combined output and error values. + bs, err := helperCommand("cat", "/bogus/file.foo", "exec_test.go").CombinedOutput() + if _, ok := err.(*os.Waitmsg); !ok { + t.Errorf("expected Waitmsg from cat combined; got %T: %v", err, err) } - buf, err := ioutil.ReadAll(cmd.Stderr) - if err != nil { - t.Fatal("read:", err) + s := string(bs) + sp := strings.Split(s, "\n", 2) + if len(sp) != 2 { + t.Fatalf("expected two lines from cat; got %q", s) } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) + errLine, body := sp[0], sp[1] + if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") { + t.Errorf("expected stderr to complain about file; got %q", errLine) } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") { + t.Errorf("expected test code; got %q (len %d)", body, len(body)) } } -func TestMergeWithStdout(t *testing.T) { - cmd, err := run([]string{"sh", "-c", "echo hello world 1>&2"}, - DevNull, Pipe, MergeWithStdout) - if err != nil { - t.Fatal("run:", err) - } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) - } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) + +func TestNoExistBinary(t *testing.T) { + // Can't run a non-existent binary + err := Command("/no-exist-binary").Run() + if err == nil { + t.Error("expected error from /no-exist-binary") } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) +} + +func TestExitStatus(t *testing.T) { + // Test that exit values are returned correctly + err := helperCommand("exit", "42").Run() + if werr, ok := err.(*os.Waitmsg); ok { + if s, e := werr.String(), "exit status 42"; s != e { + t.Errorf("from exit 42 got exit %q, want %q", s, e) + } + } else { + t.Fatalf("expected Waitmsg from exit 42; got %T: %v", err, err) } } -func TestAddEnvVar(t *testing.T) { - err := os.Setenv("NEWVAR", "hello world") - if err != nil { - t.Fatal("setenv:", err) +func TestPipes(t *testing.T) { + check := func(what string, err os.Error) { + if err != nil { + t.Fatalf("%s: %v", what, err) + } } - cmd, err := run([]string{"sh", "-c", "echo $NEWVAR"}, - DevNull, Pipe, DevNull) - if err != nil { - t.Fatal("run:", err) + // Cat, testing stdin and stdout. + c := helperCommand("pipetest") + stdin, err := c.StdinPipe() + check("StdinPipe", err) + stdout, err := c.StdoutPipe() + check("StdoutPipe", err) + stderr, err := c.StderrPipe() + check("StderrPipe", err) + + outbr := bufio.NewReader(stdout) + errbr := bufio.NewReader(stderr) + line := func(what string, br *bufio.Reader) string { + line, _, err := br.ReadLine() + if err != nil { + t.Fatalf("%s: %v", what, err) + } + return string(line) } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) + + err = c.Start() + check("Start", err) + + _, err = stdin.Write([]byte("O:I am output\n")) + check("first stdin Write", err) + if g, e := line("first output line", outbr), "O:I am output"; g != e { + t.Errorf("got %q, want %q", g, e) } - if string(buf) != "hello world\n" { - t.Fatalf("read: got %q", buf) + + _, err = stdin.Write([]byte("E:I am error\n")) + check("second stdin Write", err) + if g, e := line("first error line", errbr), "E:I am error"; g != e { + t.Errorf("got %q, want %q", g, e) } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + + _, err = stdin.Write([]byte("O:I am output2\n")) + check("third stdin Write 3", err) + if g, e := line("second output line", outbr), "O:I am output2"; g != e { + t.Errorf("got %q, want %q", g, e) } -} -var tryargs = []string{ - `2`, - `2 `, - "2 \t", - `2" "`, - `2 ab `, - `2 "ab" `, - `2 \ `, - `2 \\ `, - `2 \" `, - `2 \`, - `2\`, - `2"`, - `2\"`, - `2 "`, - `2 \"`, - ``, - `2 ^ `, - `2 \^`, + stdin.Close() + err = c.Wait() + check("Wait", err) } -func TestArgs(t *testing.T) { - for _, a := range tryargs { - argv := []string{ - "awk", - `BEGIN{printf("%s|%s|%s",ARGV[1],ARGV[2],ARGV[3])}`, - "/dev/null", - a, - "EOF", - } - exe, err := LookPath(argv[0]) - if err != nil { - t.Fatal("run:", err) +// TestHelperProcess isn't a real test. It's used as a helper process +// for TestParameterRun. +func TestHelperProcess(*testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { + return + } + defer os.Exit(0) + + args := os.Args + for len(args) > 0 { + if args[0] == "--" { + args = args[1:] + break } - cmd, err := Run(exe, argv, nil, "", DevNull, Pipe, DevNull) - if err != nil { - t.Fatal("run:", err) + args = args[1:] + } + if len(args) == 0 { + fmt.Fprintf(os.Stderr, "No command\n") + os.Exit(2) + } + + cmd, args := args[0], args[1:] + switch cmd { + case "echo": + iargs := []interface{}{} + for _, s := range args { + iargs = append(iargs, s) } - buf, err := ioutil.ReadAll(cmd.Stdout) - if err != nil { - t.Fatal("read:", err) + fmt.Println(iargs...) + case "cat": + if len(args) == 0 { + io.Copy(os.Stdout, os.Stdin) + return } - expect := "/dev/null|" + a + "|EOF" - if string(buf) != expect { - t.Errorf("read: got %q expect %q", buf, expect) + exit := 0 + for _, fn := range args { + f, err := os.Open(fn) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + exit = 2 + } else { + defer f.Close() + io.Copy(os.Stdout, f) + } } - if err = cmd.Close(); err != nil { - t.Fatal("close:", err) + os.Exit(exit) + case "pipetest": + bufr := bufio.NewReader(os.Stdin) + for { + line, _, err := bufr.ReadLine() + if err == os.EOF { + break + } else if err != nil { + os.Exit(1) + } + if bytes.HasPrefix(line, []byte("O:")) { + os.Stdout.Write(line) + os.Stdout.Write([]byte{'\n'}) + } else if bytes.HasPrefix(line, []byte("E:")) { + os.Stderr.Write(line) + os.Stderr.Write([]byte{'\n'}) + } else { + os.Exit(1) + } } + case "exit": + n, _ := strconv.Atoi(args[0]) + os.Exit(n) + default: + fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) + os.Exit(2) } } diff --git a/src/pkg/exec/lp_test.go b/src/pkg/exec/lp_test.go index 54081771e..77d8e848c 100644 --- a/src/pkg/exec/lp_test.go +++ b/src/pkg/exec/lp_test.go @@ -22,12 +22,12 @@ func TestLookPathNotFound(t *testing.T) { if path != "" { t.Fatalf("LookPath path == %q when err != nil", path) } - perr, ok := err.(*PathError) + perr, ok := err.(*Error) if !ok { - t.Fatal("LookPath error is not a PathError") + t.Fatal("LookPath error is not an exec.Error") } if perr.Name != name { - t.Fatalf("want PathError name %q, got %q", name, perr.Name) + t.Fatalf("want Error name %q, got %q", name, perr.Name) } } } diff --git a/src/pkg/exec/lp_unix.go b/src/pkg/exec/lp_unix.go index 44f84347b..3fc3be832 100644 --- a/src/pkg/exec/lp_unix.go +++ b/src/pkg/exec/lp_unix.go @@ -9,12 +9,18 @@ import ( "strings" ) -func canExec(file string) bool { +// ErrNotFound is the error resulting if a path search failed to find an executable file. +var ErrNotFound = os.ErrorString("executable file not found in $PATH") + +func findExecutable(file string) os.Error { d, err := os.Stat(file) if err != nil { - return false + return err + } + if d.IsRegular() && d.Permission()&0111 != 0 { + return nil } - return d.IsRegular() && d.Permission()&0111 != 0 + return os.EPERM } // LookPath searches for an executable binary named file @@ -26,10 +32,11 @@ func LookPath(file string) (string, os.Error) { // but that would not match all the Unix shells. if strings.Contains(file, "/") { - if canExec(file) { + err := findExecutable(file) + if err == nil { return file, nil } - return "", &PathError{file} + return "", &Error{file, err} } pathenv := os.Getenv("PATH") for _, dir := range strings.Split(pathenv, ":", -1) { @@ -37,9 +44,9 @@ func LookPath(file string) (string, os.Error) { // Unix shell semantics: path element "" means "." dir = "." } - if canExec(dir + "/" + file) { + if err := findExecutable(dir + "/" + file); err == nil { return dir + "/" + file, nil } } - return "", &PathError{file} + return "", &Error{file, ErrNotFound} } diff --git a/src/pkg/exec/lp_windows.go b/src/pkg/exec/lp_windows.go index d357575fd..758861021 100644 --- a/src/pkg/exec/lp_windows.go +++ b/src/pkg/exec/lp_windows.go @@ -9,15 +9,21 @@ import ( "strings" ) -func chkStat(file string) bool { +// ErrNotFound is the error resulting if a path search failed to find an executable file. +var ErrNotFound = os.ErrorString("executable file not found in %PATH%") + +func chkStat(file string) os.Error { d, err := os.Stat(file) if err != nil { - return false + return err + } + if d.IsRegular() { + return nil } - return d.IsRegular() + return os.EPERM } -func canExec(file string, exts []string) (string, bool) { +func findExecutable(file string, exts []string) (string, os.Error) { if len(exts) == 0 { return file, chkStat(file) } @@ -28,14 +34,14 @@ func canExec(file string, exts []string) (string, bool) { } } for _, e := range exts { - if f := file + e; chkStat(f) { - return f, true + if f := file + e; chkStat(f) == nil { + return f, nil } } - return ``, false + return ``, ErrNotFound } -func LookPath(file string) (string, os.Error) { +func LookPath(file string) (f string, err os.Error) { exts := []string{} if x := os.Getenv(`PATHEXT`); x != `` { exts = strings.Split(strings.ToLower(x), `;`, -1) @@ -46,21 +52,21 @@ func LookPath(file string) (string, os.Error) { } } if strings.Contains(file, `\`) || strings.Contains(file, `/`) { - if f, ok := canExec(file, exts); ok { - return f, nil + if f, err = findExecutable(file, exts); err == nil { + return } - return ``, &PathError{file} + return ``, &Error{file, err} } if pathenv := os.Getenv(`PATH`); pathenv == `` { - if f, ok := canExec(`.\`+file, exts); ok { - return f, nil + if f, err = findExecutable(`.\`+file, exts); err == nil { + return } } else { for _, dir := range strings.Split(pathenv, `;`, -1) { - if f, ok := canExec(dir+`\`+file, exts); ok { - return f, nil + if f, err = findExecutable(dir+`\`+file, exts); err == nil { + return } } } - return ``, &PathError{file} + return ``, &Error{file, ErrNotFound} } diff --git a/src/pkg/exp/eval/gen.go b/src/pkg/exp/eval/gen.go index de98a5d15..1e00bdcd0 100644 --- a/src/pkg/exp/eval/gen.go +++ b/src/pkg/exp/eval/gen.go @@ -366,10 +366,10 @@ func main() { t.SetDelims("«", "»") err := t.Parse(templateStr) if err != nil { - log.Exit(err) + log.Fatal(err) } err = t.Execute(os.Stdout, data) if err != nil { - log.Exit(err) + log.Fatal(err) } } diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go index 08609ca64..79fe5758c 100644 --- a/src/pkg/fmt/doc.go +++ b/src/pkg/fmt/doc.go @@ -25,6 +25,7 @@ %c the character represented by the corresponding Unicode code point %d base 10 %o base 8 + %q a single-quoted character literal safely escaped with Go syntax. %x base 16, with lower-case letters for a-f %X base 16, with upper-case letters for A-F %U Unicode format: U+1234; same as "U+%04X" diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go index b3c0c5abe..caecb6fb8 100644 --- a/src/pkg/fmt/fmt_test.go +++ b/src/pkg/fmt/fmt_test.go @@ -135,6 +135,17 @@ var fmttests = []struct { {"%q", "\u263a", `"\u263a"`}, {"%q", "\U0010ffff", `"\U0010ffff"`}, + // escaped characters + {"%q", 'x', `'x'`}, + {"%q", 0, `'\x00'`}, + {"%q", '\n', `'\n'`}, + {"%q", '\u1234', `'\u1234'`}, + {"%q", '\U00012345', `'\U00012345'`}, + {"%q", int64(0x7FFFFFFF), `%!q(int64=2147483647)`}, + {"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`}, + {"%q", '"', `'"'`}, + {"%q", '\'', `'\''`}, + // width {"%5s", "abc", " abc"}, {"%2s", "\u263a", " \u263a"}, diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go index f9d2b4fca..5dcfb9677 100644 --- a/src/pkg/fmt/format.go +++ b/src/pkg/fmt/format.go @@ -296,6 +296,13 @@ func (f *fmt) fmt_q(s string) { f.padString(quoted) } +// fmt_qc formats the integer as a single-quoted, escaped Go character constant. +// If the character is not valid Unicode, it will print '\ufffd'. +func (f *fmt) fmt_qc(c int64) { + quoted := strconv.QuoteRune(int(c)) + f.padString(quoted) +} + // floating-point func doPrec(f *fmt, def int) int { diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go index 8885cebdf..c18a8ea38 100644 --- a/src/pkg/fmt/print.go +++ b/src/pkg/fmt/print.go @@ -9,6 +9,7 @@ import ( "io" "os" "reflect" + "unicode" "utf8" ) @@ -332,6 +333,12 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) { p.fmt.integer(v, 10, signed, ldigits) case 'o': p.fmt.integer(v, 8, signed, ldigits) + case 'q': + if 0 <= v && v <= unicode.MaxRune { + p.fmt.fmt_qc(v) + } else { + p.badVerb(verb, value) + } case 'x': p.fmt.integer(v, 16, signed, ldigits) case 'U': @@ -385,6 +392,12 @@ func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) { } case 'o': p.fmt.integer(int64(v), 8, unsigned, ldigits) + case 'q': + if 0 <= v && v <= unicode.MaxRune { + p.fmt.fmt_qc(int64(v)) + } else { + p.badVerb(verb, value) + } case 'x': p.fmt.integer(int64(v), 16, unsigned, ldigits) case 'X': diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go index 42bc52c92..dd8548ceb 100644 --- a/src/pkg/fmt/scan.go +++ b/src/pkg/fmt/scan.go @@ -231,6 +231,7 @@ func (s *ss) UnreadRune() os.Error { } else { s.peekRune = s.prevRune } + s.prevRune = -1 s.count-- return nil } @@ -457,6 +458,14 @@ func (s *ss) peek(ok string) bool { return strings.IndexRune(ok, rune) >= 0 } +func (s *ss) notEOF() { + // Guarantee there is data to be read. + if rune := s.getRune(); rune == eof { + panic(os.EOF) + } + s.UnreadRune() +} + // accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the // buffer and returns true. Otherwise it return false. func (s *ss) accept(ok string) bool { @@ -476,11 +485,13 @@ func (s *ss) okVerb(verb int, okVerbs, typ string) bool { // scanBool returns the value of the boolean represented by the next token. func (s *ss) scanBool(verb int) bool { + s.skipSpace(false) + s.notEOF() if !s.okVerb(verb, "tv", "boolean") { return false } // Syntax-checking a boolean is annoying. We're not fastidious about case. - switch s.mustReadRune() { + switch s.getRune() { case '0': return false case '1': @@ -531,6 +542,7 @@ func (s *ss) getBase(verb int) (base int, digits string) { // scanNumber returns the numerical string with specified digits starting here. func (s *ss) scanNumber(digits string, haveDigits bool) string { + s.notEOF() if !haveDigits && !s.accept(digits) { s.errorString("expected integer") } @@ -541,7 +553,8 @@ func (s *ss) scanNumber(digits string, haveDigits bool) string { // scanRune returns the next rune value in the input. func (s *ss) scanRune(bitSize int) int64 { - rune := int64(s.mustReadRune()) + s.notEOF() + rune := int64(s.getRune()) n := uint(bitSize) x := (rune << (64 - n)) >> (64 - n) if x != rune { @@ -575,6 +588,7 @@ func (s *ss) scanInt(verb int, bitSize int) int64 { return s.scanRune(bitSize) } s.skipSpace(false) + s.notEOF() base, digits := s.getBase(verb) haveDigits := false if verb == 'U' { @@ -607,6 +621,7 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 { return uint64(s.scanRune(bitSize)) } s.skipSpace(false) + s.notEOF() base, digits := s.getBase(verb) haveDigits := false if verb == 'U' { @@ -727,6 +742,7 @@ func (s *ss) scanComplex(verb int, n int) complex128 { return 0 } s.skipSpace(false) + s.notEOF() sreal, simag := s.complexTokens() real := s.convertFloat(sreal, n/2) imag := s.convertFloat(simag, n/2) @@ -740,6 +756,7 @@ func (s *ss) convertString(verb int) (str string) { return "" } s.skipSpace(false) + s.notEOF() switch verb { case 'q': str = s.quotedString() @@ -748,16 +765,13 @@ func (s *ss) convertString(verb int) (str string) { default: str = string(s.token(true, notSpace)) // %s and %v just return the next word } - // Empty strings other than with %q are not OK. - if len(str) == 0 && verb != 'q' && s.maxWid > 0 { - s.errorString("Scan: no data for string") - } return } // quotedString returns the double- or back-quoted string represented by the next input characters. func (s *ss) quotedString() string { - quote := s.mustReadRune() + s.notEOF() + quote := s.getRune() switch quote { case '`': // Back-quoted: Anything goes until EOF or back quote. @@ -827,6 +841,7 @@ func (s *ss) hexByte() (b byte, ok bool) { // hexString returns the space-delimited hexpair-encoded string. func (s *ss) hexString() string { + s.notEOF() for { b, ok := s.hexByte() if !ok { @@ -860,6 +875,7 @@ func (s *ss) scanOne(verb int, field interface{}) { } return } + switch v := field.(type) { case *bool: *v = s.scanBool(verb) @@ -894,11 +910,13 @@ func (s *ss) scanOne(verb int, field interface{}) { case *float32: if s.okVerb(verb, floatVerbs, "float32") { s.skipSpace(false) + s.notEOF() *v = float32(s.convertFloat(s.floatToken(), 32)) } case *float64: if s.okVerb(verb, floatVerbs, "float64") { s.skipSpace(false) + s.notEOF() *v = s.convertFloat(s.floatToken(), 64) } case *string: @@ -936,6 +954,7 @@ func (s *ss) scanOne(verb int, field interface{}) { } case reflect.Float32, reflect.Float64: s.skipSpace(false) + s.notEOF() v.SetFloat(s.convertFloat(s.floatToken(), v.Type().Bits())) case reflect.Complex64, reflect.Complex128: v.SetComplex(s.scanComplex(verb, v.Type().Bits())) @@ -946,13 +965,13 @@ func (s *ss) scanOne(verb int, field interface{}) { } } -// errorHandler turns local panics into error returns. EOFs are benign. +// errorHandler turns local panics into error returns. func errorHandler(errp *os.Error) { if e := recover(); e != nil { if se, ok := e.(scanError); ok { // catch local error - if se.err != os.EOF { - *errp = se.err - } + *errp = se.err + } else if eof, ok := e.(os.Error); ok && eof == os.EOF { // out of input + *errp = eof } else { panic(e) } diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go index da13eb2d1..a4de8adb1 100644 --- a/src/pkg/fmt/scan_test.go +++ b/src/pkg/fmt/scan_test.go @@ -660,6 +660,68 @@ func TestEOF(t *testing.T) { } } +// Verify that we see an EOF error if we run out of input. +// This was a buglet: we used to get "expected integer". +func TestEOFAtEndOfInput(t *testing.T) { + var i, j int + n, err := Sscanf("23", "%d %d", &i, &j) + if n != 1 || i != 23 { + t.Errorf("Sscanf expected one value of 23; got %d %d", n, i) + } + if err != os.EOF { + t.Errorf("Sscanf expected EOF; got %q", err) + } + n, err = Sscan("234", &i, &j) + if n != 1 || i != 234 { + t.Errorf("Sscan expected one value of 234; got %d %d", n, i) + } + if err != os.EOF { + t.Errorf("Sscan expected EOF; got %q", err) + } + // Trailing space is tougher. + n, err = Sscan("234 ", &i, &j) + if n != 1 || i != 234 { + t.Errorf("Sscan expected one value of 234; got %d %d", n, i) + } + if err != os.EOF { + t.Errorf("Sscan expected EOF; got %q", err) + } +} + +var eofTests = []struct { + format string + v interface{} +}{ + {"%s", &stringVal}, + {"%q", &stringVal}, + {"%x", &stringVal}, + {"%v", &stringVal}, + {"%v", &bytesVal}, + {"%v", &intVal}, + {"%v", &uintVal}, + {"%v", &boolVal}, + {"%v", &float32Val}, + {"%v", &complex64Val}, + {"%v", &renamedStringVal}, + {"%v", &renamedBytesVal}, + {"%v", &renamedIntVal}, + {"%v", &renamedUintVal}, + {"%v", &renamedBoolVal}, + {"%v", &renamedFloat32Val}, + {"%v", &renamedComplex64Val}, +} + +func TestEOFAllTypes(t *testing.T) { + for i, test := range eofTests { + if _, err := Sscanf("", test.format, test.v); err != os.EOF { + t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err) + } + if _, err := Sscanf(" ", test.format, test.v); err != os.EOF { + t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err) + } + } +} + // Verify that, at least when using bufio, successive calls to Fscan do not lose runes. func TestUnreadRuneWithBufio(t *testing.T) { r := bufio.NewReader(strings.NewReader("123αb")) diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go index 07b7454c8..509abeca5 100644 --- a/src/pkg/go/scanner/scanner.go +++ b/src/pkg/go/scanner/scanner.go @@ -134,36 +134,6 @@ func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint } -func charString(ch int) string { - var s string - switch ch { - case -1: - return `EOF` - case '\a': - s = `\a` - case '\b': - s = `\b` - case '\f': - s = `\f` - case '\n': - s = `\n` - case '\r': - s = `\r` - case '\t': - s = `\t` - case '\v': - s = `\v` - case '\\': - s = `\\` - case '\'': - s = `\'` - default: - s = string(ch) - } - return "'" + s + "' (U+" + strconv.Itob(ch, 16) + ")" -} - - func (S *Scanner) error(offs int, msg string) { if S.err != nil { S.err.Error(S.file.Position(S.file.Pos(offs)), msg) @@ -327,6 +297,10 @@ func (S *Scanner) scanNumber(seenDecimalPoint bool) token.Token { // hexadecimal int S.next() S.scanMantissa(16) + if S.offset-offs <= 2 { + // only scanned "0x" or "0X" + S.error(offs, "illegal hexadecimal number") + } } else { // octal int or float seenDecimalDigit := false @@ -700,7 +674,7 @@ scanAgain: tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR) default: if S.mode&AllowIllegalChars == 0 { - S.error(offs, "illegal character "+charString(ch)) + S.error(offs, "illegal character "+strconv.QuoteRune(ch)) } insertSemi = S.insertSemi // preserve insertSemi info } diff --git a/src/pkg/go/scanner/scanner_test.go b/src/pkg/go/scanner/scanner_test.go index 2d56bfb25..8af972838 100644 --- a/src/pkg/go/scanner/scanner_test.go +++ b/src/pkg/go/scanner/scanner_test.go @@ -650,7 +650,9 @@ var errors = []struct { pos int err string }{ - {`#`, token.ILLEGAL, 0, "illegal character '#' (U+23)"}, + {"\a", token.ILLEGAL, 0, "illegal character '\\a'"}, + {`#`, token.ILLEGAL, 0, "illegal character '#'"}, + {`…`, token.ILLEGAL, 0, "illegal character '\\u2026'"}, {`' '`, token.CHAR, 0, ""}, {`''`, token.CHAR, 0, "illegal character literal"}, {`'\8'`, token.CHAR, 2, "unknown escape sequence"}, @@ -670,6 +672,8 @@ var errors = []struct { {"078e0", token.FLOAT, 0, ""}, {"078", token.INT, 0, "illegal octal number"}, {"07800000009", token.INT, 0, "illegal octal number"}, + {"0x", token.INT, 0, "illegal hexadecimal number"}, + {"0X", token.INT, 0, "illegal hexadecimal number"}, {"\"abc\x00def\"", token.STRING, 4, "illegal character NUL"}, {"\"abc\x80def\"", token.STRING, 4, "illegal UTF-8 encoding"}, } diff --git a/src/pkg/go/types/gcimporter_test.go b/src/pkg/go/types/gcimporter_test.go index 50e70f29c..10240add5 100644 --- a/src/pkg/go/types/gcimporter_test.go +++ b/src/pkg/go/types/gcimporter_test.go @@ -37,24 +37,14 @@ func init() { func compile(t *testing.T, dirname, filename string) { - cmd, err := exec.Run(gcPath, []string{gcPath, filename}, nil, dirname, exec.DevNull, exec.Pipe, exec.MergeWithStdout) + cmd := exec.Command(gcPath, filename) + cmd.Dir = dirname + out, err := cmd.CombinedOutput() if err != nil { t.Errorf("%s %s failed: %s", gcName, filename, err) return } - defer cmd.Close() - - msg, err := cmd.Wait(0) - if err != nil { - t.Errorf("%s %s failed: %s", gcName, filename, err) - return - } - - if !msg.Exited() || msg.ExitStatus() != 0 { - t.Errorf("%s %s failed: exit status = %d", gcName, filename, msg.ExitStatus()) - output, _ := ioutil.ReadAll(cmd.Stdout) - t.Log(string(output)) - } + t.Logf("%s", string(out)) } diff --git a/src/pkg/gob/decoder.go b/src/pkg/gob/decoder.go index ea2f62ec5..b83904a71 100644 --- a/src/pkg/gob/decoder.go +++ b/src/pkg/gob/decoder.go @@ -155,8 +155,8 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { // Decode reads the next value from the connection and stores // it in the data represented by the empty interface value. // If e is nil, the value will be discarded. Otherwise, -// the value underlying e must either be the correct type for the next -// data item received, and must be a pointer. +// the value underlying e must be a pointer to the +// correct type for the next data item received. func (dec *Decoder) Decode(e interface{}) os.Error { if e == nil { return dec.DecodeValue(reflect.Value{}) diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go index 7e4ccf881..7ab3f9247 100644 --- a/src/pkg/http/cgi/host.go +++ b/src/pkg/http/cgi/host.go @@ -156,34 +156,35 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { cwd = "." } - args := []string{h.Path} - args = append(args, h.Args...) - - cmd, err := exec.Run( - pathBase, - args, - env, - cwd, - exec.Pipe, // stdin - exec.Pipe, // stdout - exec.PassThrough, // stderr (for now) - ) - if err != nil { + internalError := func(err os.Error) { rw.WriteHeader(http.StatusInternalServerError) h.printf("CGI error: %v", err) - return } - defer func() { - cmd.Stdin.Close() - cmd.Stdout.Close() - cmd.Wait(0) // no zombies - }() + cmd := &exec.Cmd{ + Path: pathBase, + Args: append([]string{h.Path}, h.Args...), + Dir: cwd, + Env: env, + Stderr: os.Stderr, // for now + } if req.ContentLength != 0 { - go io.Copy(cmd.Stdin, req.Body) + cmd.Stdin = req.Body + } + stdoutRead, err := cmd.StdoutPipe() + if err != nil { + internalError(err) + return + } + + err = cmd.Start() + if err != nil { + internalError(err) + return } + defer cmd.Wait() - linebody, _ := bufio.NewReaderSize(cmd.Stdout, 1024) + linebody, _ := bufio.NewReaderSize(stdoutRead, 1024) headers := make(http.Header) statusCode := 0 for { diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go index 9ac085f2f..bbdb715cf 100644 --- a/src/pkg/http/cgi/host_test.go +++ b/src/pkg/http/cgi/host_test.go @@ -17,20 +17,6 @@ import ( "testing" ) -var cgiScriptWorks = canRun("./testdata/test.cgi") - -func canRun(s string) bool { - c, err := exec.Run(s, []string{s}, nil, ".", exec.DevNull, exec.DevNull, exec.DevNull) - if err != nil { - return false - } - w, err := c.Wait(0) - if err != nil { - return false - } - return w.Exited() && w.ExitStatus() == 0 -} - func newRequest(httpreq string) *http.Request { buf := bufio.NewReader(strings.NewReader(httpreq)) req, err := http.ReadRequest(buf) @@ -76,8 +62,15 @@ readlines: return rw } +var cgiTested = false +var cgiWorks bool + func skipTest(t *testing.T) bool { - if !cgiScriptWorks { + if !cgiTested { + cgiTested = true + cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil + } + if !cgiWorks { // No Perl on Windows, needed by test.cgi // TODO: make the child process be Go, not Perl. t.Logf("Skipping test: test.cgi failed.") diff --git a/src/pkg/http/client.go b/src/pkg/http/client.go index ac7ff1853..7e1d65df3 100644 --- a/src/pkg/http/client.go +++ b/src/pkg/http/client.go @@ -11,9 +11,7 @@ import ( "encoding/base64" "fmt" "io" - "io/ioutil" "os" - "strconv" "strings" ) @@ -100,13 +98,10 @@ func send(req *Request, t RoundTripper) (resp *Response, err os.Error) { info := req.URL.RawUserinfo if len(info) > 0 { - enc := base64.URLEncoding - encoded := make([]byte, enc.EncodedLen(len(info))) - enc.Encode(encoded, []byte(info)) if req.Header == nil { req.Header = make(Header) } - req.Header.Set("Authorization", "Basic "+string(encoded)) + req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(info))) } return t.RoundTrip(req) } @@ -231,23 +226,12 @@ func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Erro // // Caller should close r.Body when done reading from it. func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) { - var req Request - req.Method = "POST" - req.ProtoMajor = 1 - req.ProtoMinor = 1 - req.Close = true - req.Body = ioutil.NopCloser(body) - req.Header = Header{ - "Content-Type": {bodyType}, - } - req.TransferEncoding = []string{"chunked"} - - req.URL, err = ParseURL(url) + req, err := NewRequest("POST", url, body) if err != nil { return nil, err } - - return send(&req, c.Transport) + req.Header.Set("Content-Type", bodyType) + return send(req, c.Transport) } // PostForm issues a POST to the specified URL, @@ -265,25 +249,7 @@ func PostForm(url string, data map[string]string) (r *Response, err os.Error) { // // Caller should close r.Body when done reading from it. func (c *Client) PostForm(url string, data map[string]string) (r *Response, err os.Error) { - var req Request - req.Method = "POST" - req.ProtoMajor = 1 - req.ProtoMinor = 1 - req.Close = true - body := urlencode(data) - req.Body = ioutil.NopCloser(body) - req.Header = Header{ - "Content-Type": {"application/x-www-form-urlencoded"}, - "Content-Length": {strconv.Itoa(body.Len())}, - } - req.ContentLength = int64(body.Len()) - - req.URL, err = ParseURL(url) - if err != nil { - return nil, err - } - - return send(&req, c.Transport) + return c.Post(url, "application/x-www-form-urlencoded", urlencode(data)) } // TODO: remove this function when PostForm takes a multimap. diff --git a/src/pkg/http/client_test.go b/src/pkg/http/client_test.go index 0869015b3..822a8889c 100644 --- a/src/pkg/http/client_test.go +++ b/src/pkg/http/client_test.go @@ -10,6 +10,7 @@ import ( "fmt" . "http" "http/httptest" + "io" "io/ioutil" "os" "strconv" @@ -77,6 +78,61 @@ func TestGetRequestFormat(t *testing.T) { } } +func TestPostRequestFormat(t *testing.T) { + tr := &recordingTransport{} + client := &Client{Transport: tr} + + url := "http://dummy.faketld/" + json := `{"key":"value"}` + b := strings.NewReader(json) + client.Post(url, "application/json", b) // Note: doesn't hit network + + if tr.req.Method != "POST" { + t.Errorf("got method %q, want %q", tr.req.Method, "POST") + } + if tr.req.URL.String() != url { + t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) + } + if tr.req.Header == nil { + t.Fatalf("expected non-nil request Header") + } + if tr.req.Close { + t.Error("got Close true, want false") + } + if g, e := tr.req.ContentLength, int64(len(json)); g != e { + t.Errorf("got ContentLength %d, want %d", g, e) + } +} + +func TestPostFormRequestFormat(t *testing.T) { + tr := &recordingTransport{} + client := &Client{Transport: tr} + + url := "http://dummy.faketld/" + form := map[string]string{"foo": "bar"} + client.PostForm(url, form) // Note: doesn't hit network + + if tr.req.Method != "POST" { + t.Errorf("got method %q, want %q", tr.req.Method, "POST") + } + if tr.req.URL.String() != url { + t.Errorf("got URL %q, want %q", tr.req.URL.String(), url) + } + if tr.req.Header == nil { + t.Fatalf("expected non-nil request Header") + } + if g, e := tr.req.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; g != e { + t.Errorf("got Content-Type %q, want %q", g, e) + } + if tr.req.Close { + t.Error("got Close true, want false") + } + if g, e := tr.req.ContentLength, int64(len("foo=bar")); g != e { + t.Errorf("got ContentLength %d, want %d", g, e) + } + +} + func TestRedirects(t *testing.T) { var ts *httptest.Server ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { @@ -139,3 +195,41 @@ func TestRedirects(t *testing.T) { t.Errorf("with redirects forbidden, expected error %q, got %q", e, g) } } + +func TestStreamingGet(t *testing.T) { + say := make(chan string) + ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + w.(Flusher).Flush() + for str := range say { + w.Write([]byte(str)) + w.(Flusher).Flush() + } + })) + defer ts.Close() + + c := &Client{} + res, err := c.Get(ts.URL) + if err != nil { + t.Fatal(err) + } + var buf [10]byte + for _, str := range []string{"i", "am", "also", "known", "as", "comet"} { + say <- str + n, err := io.ReadFull(res.Body, buf[0:len(str)]) + if err != nil { + t.Fatalf("ReadFull on %q: %v", str, err) + } + if n != len(str) { + t.Fatalf("Receiving %q, only read %d bytes", str, n) + } + got := string(buf[0:n]) + if got != str { + t.Fatalf("Expected %q, got %q", str, got) + } + } + close(say) + _, err = io.ReadFull(res.Body, buf[0:1]) + if err != os.EOF { + t.Fatalf("at end expected EOF, got %v", err) + } +} diff --git a/src/pkg/http/cookie.go b/src/pkg/http/cookie.go index 5add1ccc2..eb61a7001 100644 --- a/src/pkg/http/cookie.go +++ b/src/pkg/http/cookie.go @@ -81,12 +81,17 @@ func readSetCookies(h Header) []*Cookie { if j := strings.Index(attr, "="); j >= 0 { attr, val = attr[:j], attr[j+1:] } - val, success = parseCookieValue(val) + lowerAttr := strings.ToLower(attr) + parseCookieValueFn := parseCookieValue + if lowerAttr == "expires" { + parseCookieValueFn = parseCookieExpiresValue + } + val, success = parseCookieValueFn(val) if !success { c.Unparsed = append(c.Unparsed, parts[i]) continue } - switch strings.ToLower(attr) { + switch lowerAttr { case "secure": c.Secure = true continue @@ -112,8 +117,11 @@ func readSetCookies(h Header) []*Cookie { c.RawExpires = val exptime, err := time.Parse(time.RFC1123, val) if err != nil { - c.Expires = time.Time{} - break + exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val) + if err != nil { + c.Expires = time.Time{} + break + } } c.Expires = *exptime continue @@ -272,7 +280,7 @@ func unquoteCookieValue(v string) string { } func isCookieByte(c byte) bool { - switch true { + switch { case c == 0x21, 0x23 <= c && c <= 0x2b, 0x2d <= c && c <= 0x3a, 0x3c <= c && c <= 0x5b, 0x5d <= c && c <= 0x7e: return true @@ -280,10 +288,22 @@ func isCookieByte(c byte) bool { return false } +func isCookieExpiresByte(c byte) (ok bool) { + return isCookieByte(c) || c == ',' || c == ' ' +} + func parseCookieValue(raw string) (string, bool) { + return parseCookieValueUsing(raw, isCookieByte) +} + +func parseCookieExpiresValue(raw string) (string, bool) { + return parseCookieValueUsing(raw, isCookieExpiresByte) +} + +func parseCookieValueUsing(raw string, validByte func(byte) bool) (string, bool) { raw = unquoteCookieValue(raw) for i := 0; i < len(raw); i++ { - if !isCookieByte(raw[i]) { + if !validByte(raw[i]) { return "", false } } diff --git a/src/pkg/http/cookie_test.go b/src/pkg/http/cookie_test.go index 13c9fff4a..02e42226b 100644 --- a/src/pkg/http/cookie_test.go +++ b/src/pkg/http/cookie_test.go @@ -11,9 +11,9 @@ import ( "os" "reflect" "testing" + "time" ) - var writeSetCookiesTests = []struct { Cookies []*Cookie Raw string @@ -115,6 +115,19 @@ var readSetCookiesTests = []struct { Header{"Set-Cookie": {"Cookie-1=v$1"}}, []*Cookie{&Cookie{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}}, }, + { + Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}}, + []*Cookie{&Cookie{ + Name: "NID", + Value: "99=YsDT5i3E-CXax-", + Path: "/", + Domain: ".google.ch", + HttpOnly: true, + Expires: time.Time{Year: 2011, Month: 11, Day: 23, Hour: 1, Minute: 5, Second: 3, Weekday: 3, ZoneOffset: 0, Zone: "GMT"}, + RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT", + Raw: "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly", + }}, + }, } func toJSON(v interface{}) string { diff --git a/src/pkg/http/fs.go b/src/pkg/http/fs.go index 17d5297b8..28a0c51ef 100644 --- a/src/pkg/http/fs.go +++ b/src/pkg/http/fs.go @@ -175,7 +175,9 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { } w.Header().Set("Accept-Ranges", "bytes") - w.Header().Set("Content-Length", strconv.Itoa64(size)) + if w.Header().Get("Content-Encoding") == "" { + w.Header().Set("Content-Length", strconv.Itoa64(size)) + } w.WriteHeader(code) diff --git a/src/pkg/http/fs_test.go b/src/pkg/http/fs_test.go index b94196258..554053449 100644 --- a/src/pkg/http/fs_test.go +++ b/src/pkg/http/fs_test.go @@ -101,7 +101,7 @@ func TestServeFileContentType(t *testing.T) { t.Fatal(err) } if h := resp.Header.Get("Content-Type"); h != want { - t.Errorf("Content-Type mismatch: got %q, want %q", h, want) + t.Errorf("Content-Type mismatch: got %d, want %d", h, want) } } get("text/plain; charset=utf-8") @@ -109,6 +109,21 @@ func TestServeFileContentType(t *testing.T) { get(ctype) } +func TestServeFileWithContentEncoding(t *testing.T) { + ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Content-Encoding", "foo") + ServeFile(w, r, "testdata/file") + })) + defer ts.Close() + resp, err := Get(ts.URL) + if err != nil { + t.Fatal(err) + } + if g, e := resp.ContentLength, int64(-1); g != e { + t.Errorf("Content-Length mismatch: got %q, want %q", g, e) + } +} + func getBody(t *testing.T, req Request) (*Response, []byte) { r, err := DefaultClient.Do(&req) if err != nil { diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go index 05d489211..2f6b651c3 100644 --- a/src/pkg/http/request.go +++ b/src/pkg/http/request.go @@ -10,6 +10,7 @@ package http import ( "bufio" + "bytes" "crypto/tls" "container/vector" "encoding/base64" @@ -231,7 +232,7 @@ const defaultUserAgent = "Go http package" // Method (defaults to "GET") // UserAgent (defaults to defaultUserAgent) // Referer -// Header +// Header (only keys not already in this list) // Cookie // ContentLength // TransferEncoding @@ -256,6 +257,9 @@ func (req *Request) WriteProxy(w io.Writer) os.Error { func (req *Request) write(w io.Writer, usingProxy bool) os.Error { host := req.Host if host == "" { + if req.URL == nil { + return os.NewError("http: Request.Write on Request with no Host or URL set") + } host = req.URL.Host } @@ -475,6 +479,17 @@ func NewRequest(method, url string, body io.Reader) (*Request, os.Error) { Body: rc, Host: u.Host, } + if body != nil { + switch v := body.(type) { + case *strings.Reader: + req.ContentLength = int64(v.Len()) + case *bytes.Buffer: + req.ContentLength = int64(v.Len()) + default: + req.ContentLength = -1 // chunked + } + } + return req, nil } @@ -485,9 +500,7 @@ func NewRequest(method, url string, body io.Reader) (*Request, os.Error) { // are not encrypted. func (r *Request) SetBasicAuth(username, password string) { s := username + ":" + password - buf := make([]byte, base64.StdEncoding.EncodedLen(len(s))) - base64.StdEncoding.Encode(buf, []byte(s)) - r.Header.Set("Authorization", "Basic "+string(buf)) + r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(s))) } // ReadRequest reads and parses a request from b. diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go index beb51fb8d..2889048a9 100644 --- a/src/pkg/http/requestwrite_test.go +++ b/src/pkg/http/requestwrite_test.go @@ -175,6 +175,35 @@ var reqWriteTests = []reqWriteTest{ "abcdef", }, + // HTTP/1.1 POST with Content-Length in headers + { + Request{ + Method: "POST", + RawURL: "http://example.com/", + Host: "example.com", + Header: Header{ + "Content-Length": []string{"10"}, // ignored + }, + ContentLength: 6, + }, + + []byte("abcdef"), + + "POST http://example.com/ HTTP/1.1\r\n" + + "Host: example.com\r\n" + + "User-Agent: Go http package\r\n" + + "Content-Length: 6\r\n" + + "\r\n" + + "abcdef", + + "POST http://example.com/ HTTP/1.1\r\n" + + "Host: example.com\r\n" + + "User-Agent: Go http package\r\n" + + "Content-Length: 6\r\n" + + "\r\n" + + "abcdef", + }, + // default to HTTP/1.1 { Request{ diff --git a/src/pkg/http/reverseproxy.go b/src/pkg/http/reverseproxy.go index e4ce1e34c..9a9e21599 100644 --- a/src/pkg/http/reverseproxy.go +++ b/src/pkg/http/reverseproxy.go @@ -92,6 +92,10 @@ func (p *ReverseProxy) ServeHTTP(rw ResponseWriter, req *Request) { } } + for _, cookie := range res.SetCookie { + SetCookie(rw, cookie) + } + rw.WriteHeader(res.StatusCode) if res.Body != nil { diff --git a/src/pkg/http/reverseproxy_test.go b/src/pkg/http/reverseproxy_test.go index 162000ece..d7bcde90d 100644 --- a/src/pkg/http/reverseproxy_test.go +++ b/src/pkg/http/reverseproxy_test.go @@ -20,7 +20,11 @@ func TestReverseProxy(t *testing.T) { if r.Header.Get("X-Forwarded-For") == "" { t.Errorf("didn't get X-Forwarded-For header") } + if g, e := r.Host, "some-name"; g != e { + t.Errorf("backend got Host header %q, want %q", g, e) + } w.Header().Set("X-Foo", "bar") + SetCookie(w, &Cookie{Name: "flavor", Value: "chocolateChip"}) w.WriteHeader(backendStatus) w.Write([]byte(backendResponse)) })) @@ -33,7 +37,9 @@ func TestReverseProxy(t *testing.T) { frontend := httptest.NewServer(proxyHandler) defer frontend.Close() - res, err := Get(frontend.URL) + getReq, _ := NewRequest("GET", frontend.URL, nil) + getReq.Host = "some-name" + res, err := DefaultClient.Do(getReq) if err != nil { t.Fatalf("Get: %v", err) } @@ -43,6 +49,12 @@ func TestReverseProxy(t *testing.T) { if g, e := res.Header.Get("X-Foo"), "bar"; g != e { t.Errorf("got X-Foo %q; expected %q", g, e) } + if g, e := len(res.SetCookie), 1; g != e { + t.Fatalf("got %d SetCookies, want %d", g, e) + } + if cookie := res.SetCookie[0]; cookie.Name != "flavor" { + t.Errorf("unexpected cookie %q", cookie.Name) + } bodyBytes, _ := ioutil.ReadAll(res.Body) if g, e := string(bodyBytes), backendResponse; g != e { t.Errorf("got body %q; expected %q", g, e) diff --git a/src/pkg/http/serve_test.go b/src/pkg/http/serve_test.go index 120a02605..c923c8a76 100644 --- a/src/pkg/http/serve_test.go +++ b/src/pkg/http/serve_test.go @@ -13,6 +13,7 @@ import ( . "http" "http/httptest" "io/ioutil" + "log" "os" "net" "reflect" @@ -432,6 +433,9 @@ func TestSetsRemoteAddr(t *testing.T) { } func TestChunkedResponseHeaders(t *testing.T) { + log.SetOutput(ioutil.Discard) // is noisy otherwise + defer log.SetOutput(os.Stderr) + ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted fmt.Fprintf(w, "I am a chunked response.") @@ -754,3 +758,43 @@ func TestZeroLengthPostAndResponse(t *testing.T) { } } } + +func TestHandlerPanic(t *testing.T) { + log.SetOutput(ioutil.Discard) // is noisy otherwise + defer log.SetOutput(os.Stderr) + + ts := httptest.NewServer(HandlerFunc(func(ResponseWriter, *Request) { + panic("intentional death for testing") + })) + defer ts.Close() + _, err := Get(ts.URL) + if err == nil { + t.Logf("expected an error") + } +} + +func BenchmarkClientServer(b *testing.B) { + b.StopTimer() + ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) { + fmt.Fprintf(rw, "Hello world.\n") + })) + defer ts.Close() + b.StartTimer() + + for i := 0; i < b.N; i++ { + res, err := Get(ts.URL) + if err != nil { + panic("Get: " + err.String()) + } + all, err := ioutil.ReadAll(res.Body) + if err != nil { + panic("ReadAll: " + err.String()) + } + body := string(all) + if body != "Hello world.\n" { + panic("Got body: " + body) + } + } + + b.StopTimer() +} diff --git a/src/pkg/http/server.go b/src/pkg/http/server.go index eb5a3a365..93d9d2ff4 100644 --- a/src/pkg/http/server.go +++ b/src/pkg/http/server.go @@ -6,12 +6,12 @@ // TODO(rsc): // logging -// post support package http import ( "bufio" + "bytes" "crypto/rand" "crypto/tls" "fmt" @@ -20,6 +20,7 @@ import ( "net" "os" "path" + "runtime" "strconv" "strings" "sync" @@ -119,6 +120,27 @@ type response struct { closeAfterReply bool } +type writerOnly struct { + io.Writer +} + +func (r *response) ReadFrom(src io.Reader) (n int64, err os.Error) { + // Flush before checking r.chunking, as Flush will call + // WriteHeader if it hasn't been called yet, and WriteHeader + // is what sets r.chunking. + r.Flush() + if !r.chunking { + if rf, ok := r.conn.rwc.(io.ReaderFrom); ok { + n, err = rf.ReadFrom(src) + r.written += n + return + } + } + // Fall back to default io.Copy implementation. + // Use wrapper to hide r.ReadFrom from io.Copy. + return io.Copy(writerOnly{r}, src) +} + // Create new connection from rwc. func newConn(rwc net.Conn, handler Handler) (c *conn, err os.Error) { c = new(conn) @@ -454,6 +476,33 @@ func (c *conn) close() { // Serve a new connection. func (c *conn) serve() { + defer func() { + err := recover() + if err == nil { + return + } + c.rwc.Close() + + // TODO(rsc,bradfitz): this is boilerplate. move it to runtime.Stack() + var buf bytes.Buffer + fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err) + for i := 1; i < 20; i++ { + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + var name string + f := runtime.FuncForPC(pc) + if f != nil { + name = f.Name() + } else { + name = fmt.Sprintf("%#x", pc) + } + fmt.Fprintf(&buf, " %s %s:%d\n", name, file, line) + } + log.Print(buf.String()) + }() + for { w, err := c.readRequest() if err != nil { diff --git a/src/pkg/http/spdy/Makefile b/src/pkg/http/spdy/Makefile index ff70d0437..3bec220c4 100644 --- a/src/pkg/http/spdy/Makefile +++ b/src/pkg/http/spdy/Makefile @@ -6,6 +6,8 @@ include ../../../Make.inc TARG=http/spdy GOFILES=\ - protocol.go\ + read.go\ + types.go\ + write.go\ include ../../../Make.pkg diff --git a/src/pkg/http/spdy/protocol.go b/src/pkg/http/spdy/protocol.go deleted file mode 100644 index ad9aa6333..000000000 --- a/src/pkg/http/spdy/protocol.go +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2011 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 spdy is an incomplete implementation of the SPDY protocol. -// -// The implementation follows draft 2 of the spec: -// https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft2 -package spdy - -import ( - "bytes" - "compress/zlib" - "encoding/binary" - "http" - "io" - "os" - "strconv" - "strings" - "sync" -) - -// Version is the protocol version number that this package implements. -const Version = 2 - -// ControlFrameType stores the type field in a control frame header. -type ControlFrameType uint16 - -// Control frame type constants -const ( - TypeSynStream ControlFrameType = 0x0001 - TypeSynReply = 0x0002 - TypeRstStream = 0x0003 - TypeSettings = 0x0004 - TypeNoop = 0x0005 - TypePing = 0x0006 - TypeGoaway = 0x0007 - TypeHeaders = 0x0008 - TypeWindowUpdate = 0x0009 -) - -func (t ControlFrameType) String() string { - switch t { - case TypeSynStream: - return "SYN_STREAM" - case TypeSynReply: - return "SYN_REPLY" - case TypeRstStream: - return "RST_STREAM" - case TypeSettings: - return "SETTINGS" - case TypeNoop: - return "NOOP" - case TypePing: - return "PING" - case TypeGoaway: - return "GOAWAY" - case TypeHeaders: - return "HEADERS" - case TypeWindowUpdate: - return "WINDOW_UPDATE" - } - return "Type(" + strconv.Itoa(int(t)) + ")" -} - -type FrameFlags uint8 - -// Stream frame flags -const ( - FlagFin FrameFlags = 0x01 - FlagUnidirectional = 0x02 -) - -// SETTINGS frame flags -const ( - FlagClearPreviouslyPersistedSettings FrameFlags = 0x01 -) - -// MaxDataLength is the maximum number of bytes that can be stored in one frame. -const MaxDataLength = 1<<24 - 1 - -// A Frame is a framed message as sent between clients and servers. -// There are two types of frames: control frames and data frames. -type Frame struct { - Header [4]byte - Flags FrameFlags - Data []byte -} - -// ControlFrame creates a control frame with the given information. -func ControlFrame(t ControlFrameType, f FrameFlags, data []byte) Frame { - return Frame{ - Header: [4]byte{ - (Version&0xff00)>>8 | 0x80, - (Version & 0x00ff), - byte((t & 0xff00) >> 8), - byte((t & 0x00ff) >> 0), - }, - Flags: f, - Data: data, - } -} - -// DataFrame creates a data frame with the given information. -func DataFrame(streamId uint32, f FrameFlags, data []byte) Frame { - return Frame{ - Header: [4]byte{ - byte(streamId & 0x7f000000 >> 24), - byte(streamId & 0x00ff0000 >> 16), - byte(streamId & 0x0000ff00 >> 8), - byte(streamId & 0x000000ff >> 0), - }, - Flags: f, - Data: data, - } -} - -// ReadFrame reads an entire frame into memory. -func ReadFrame(r io.Reader) (f Frame, err os.Error) { - _, err = io.ReadFull(r, f.Header[:]) - if err != nil { - return - } - err = binary.Read(r, binary.BigEndian, &f.Flags) - if err != nil { - return - } - var lengthField [3]byte - _, err = io.ReadFull(r, lengthField[:]) - if err != nil { - if err == os.EOF { - err = io.ErrUnexpectedEOF - } - return - } - var length uint32 - length |= uint32(lengthField[0]) << 16 - length |= uint32(lengthField[1]) << 8 - length |= uint32(lengthField[2]) << 0 - if length > 0 { - f.Data = make([]byte, int(length)) - _, err = io.ReadFull(r, f.Data) - if err == os.EOF { - err = io.ErrUnexpectedEOF - } - } else { - f.Data = []byte{} - } - return -} - -// IsControl returns whether the frame holds a control frame. -func (f Frame) IsControl() bool { - return f.Header[0]&0x80 != 0 -} - -// Type obtains the type field if the frame is a control frame, otherwise it returns zero. -func (f Frame) Type() ControlFrameType { - if !f.IsControl() { - return 0 - } - return (ControlFrameType(f.Header[2])<<8 | ControlFrameType(f.Header[3])) -} - -// StreamId returns the stream ID field if the frame is a data frame, otherwise it returns zero. -func (f Frame) StreamId() (id uint32) { - if f.IsControl() { - return 0 - } - id |= uint32(f.Header[0]) << 24 - id |= uint32(f.Header[1]) << 16 - id |= uint32(f.Header[2]) << 8 - id |= uint32(f.Header[3]) << 0 - return -} - -// WriteTo writes the frame in the SPDY format. -func (f Frame) WriteTo(w io.Writer) (n int64, err os.Error) { - var nn int - // Header - nn, err = w.Write(f.Header[:]) - n += int64(nn) - if err != nil { - return - } - // Flags - nn, err = w.Write([]byte{byte(f.Flags)}) - n += int64(nn) - if err != nil { - return - } - // Length - nn, err = w.Write([]byte{ - byte(len(f.Data) & 0x00ff0000 >> 16), - byte(len(f.Data) & 0x0000ff00 >> 8), - byte(len(f.Data) & 0x000000ff), - }) - n += int64(nn) - if err != nil { - return - } - // Data - if len(f.Data) > 0 { - nn, err = w.Write(f.Data) - n += int64(nn) - } - return -} - -// headerDictionary is the dictionary sent to the zlib compressor/decompressor. -// Even though the specification states there is no null byte at the end, Chrome sends it. -const headerDictionary = "optionsgetheadpostputdeletetrace" + - "acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" + - "if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" + - "max-forwardsproxy-authorizationrangerefererteuser-agent" + - "100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" + - "accept-rangesageetaglocationproxy-authenticatepublicretry-after" + - "servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" + - "connectiondatetrailertransfer-encodingupgradeviawarning" + - "content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" + - "MondayTuesdayWednesdayThursdayFridaySaturdaySunday" + - "JanFebMarAprMayJunJulAugSepOctNovDec" + - "chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" + - "charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00" - -// hrSource is a reader that passes through reads from another reader. -// When the underlying reader reaches EOF, Read will block until another reader is added via change. -type hrSource struct { - r io.Reader - m sync.RWMutex - c *sync.Cond -} - -func (src *hrSource) Read(p []byte) (n int, err os.Error) { - src.m.RLock() - for src.r == nil { - src.c.Wait() - } - n, err = src.r.Read(p) - src.m.RUnlock() - if err == os.EOF { - src.change(nil) - err = nil - } - return -} - -func (src *hrSource) change(r io.Reader) { - src.m.Lock() - defer src.m.Unlock() - src.r = r - src.c.Broadcast() -} - -// A HeaderReader reads zlib-compressed headers. -type HeaderReader struct { - source hrSource - decompressor io.ReadCloser -} - -// NewHeaderReader creates a HeaderReader with the initial dictionary. -func NewHeaderReader() (hr *HeaderReader) { - hr = new(HeaderReader) - hr.source.c = sync.NewCond(hr.source.m.RLocker()) - return -} - -// ReadHeader reads a set of headers from a reader. -func (hr *HeaderReader) ReadHeader(r io.Reader) (h http.Header, err os.Error) { - hr.source.change(r) - h, err = hr.read() - return -} - -// Decode reads a set of headers from a block of bytes. -func (hr *HeaderReader) Decode(data []byte) (h http.Header, err os.Error) { - hr.source.change(bytes.NewBuffer(data)) - h, err = hr.read() - return -} - -func (hr *HeaderReader) read() (h http.Header, err os.Error) { - var count uint16 - if hr.decompressor == nil { - hr.decompressor, err = zlib.NewReaderDict(&hr.source, []byte(headerDictionary)) - if err != nil { - return - } - } - err = binary.Read(hr.decompressor, binary.BigEndian, &count) - if err != nil { - return - } - h = make(http.Header, int(count)) - for i := 0; i < int(count); i++ { - var name, value string - name, err = readHeaderString(hr.decompressor) - if err != nil { - return - } - value, err = readHeaderString(hr.decompressor) - if err != nil { - return - } - valueList := strings.Split(string(value), "\x00", -1) - for _, v := range valueList { - h.Add(name, v) - } - } - return -} - -func readHeaderString(r io.Reader) (s string, err os.Error) { - var length uint16 - err = binary.Read(r, binary.BigEndian, &length) - if err != nil { - return - } - data := make([]byte, int(length)) - _, err = io.ReadFull(r, data) - if err != nil { - return - } - return string(data), nil -} - -// HeaderWriter will write zlib-compressed headers on different streams. -type HeaderWriter struct { - compressor *zlib.Writer - buffer *bytes.Buffer -} - -// NewHeaderWriter creates a HeaderWriter ready to compress headers. -func NewHeaderWriter(level int) (hw *HeaderWriter) { - hw = &HeaderWriter{buffer: new(bytes.Buffer)} - hw.compressor, _ = zlib.NewWriterDict(hw.buffer, level, []byte(headerDictionary)) - return -} - -// WriteHeader writes a header block directly to an output. -func (hw *HeaderWriter) WriteHeader(w io.Writer, h http.Header) (err os.Error) { - hw.write(h) - _, err = io.Copy(w, hw.buffer) - hw.buffer.Reset() - return -} - -// Encode returns a compressed header block. -func (hw *HeaderWriter) Encode(h http.Header) (data []byte) { - hw.write(h) - data = make([]byte, hw.buffer.Len()) - hw.buffer.Read(data) - return -} - -func (hw *HeaderWriter) write(h http.Header) { - binary.Write(hw.compressor, binary.BigEndian, uint16(len(h))) - for k, vals := range h { - k = strings.ToLower(k) - binary.Write(hw.compressor, binary.BigEndian, uint16(len(k))) - binary.Write(hw.compressor, binary.BigEndian, []byte(k)) - v := strings.Join(vals, "\x00") - binary.Write(hw.compressor, binary.BigEndian, uint16(len(v))) - binary.Write(hw.compressor, binary.BigEndian, []byte(v)) - } - hw.compressor.Flush() -} diff --git a/src/pkg/http/spdy/protocol_test.go b/src/pkg/http/spdy/protocol_test.go deleted file mode 100644 index 998ff998b..000000000 --- a/src/pkg/http/spdy/protocol_test.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2011 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 spdy - -import ( - "bytes" - "compress/zlib" - "http" - "os" - "testing" -) - -type frameIoTest struct { - desc string - data []byte - frame Frame - readError os.Error - readOnly bool -} - -var frameIoTests = []frameIoTest{ - { - "noop frame", - []byte{ - 0x80, 0x02, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x00, - }, - ControlFrame( - TypeNoop, - 0x00, - []byte{}, - ), - nil, - false, - }, - { - "ping frame", - []byte{ - 0x80, 0x02, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x01, - }, - ControlFrame( - TypePing, - 0x00, - []byte{0x00, 0x00, 0x00, 0x01}, - ), - nil, - false, - }, - { - "syn_stream frame", - []byte{ - 0x80, 0x02, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x53, - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xbb, - 0xdf, 0xa2, 0x51, 0xb2, - 0x62, 0x60, 0x66, 0x60, - 0xcb, 0x4d, 0x2d, 0xc9, - 0xc8, 0x4f, 0x61, 0x60, - 0x4e, 0x4f, 0x2d, 0x61, - 0x60, 0x2e, 0x2d, 0xca, - 0x61, 0x10, 0xcb, 0x28, - 0x29, 0x29, 0xb0, 0xd2, - 0xd7, 0x2f, 0x2f, 0x2f, - 0xd7, 0x4b, 0xcf, 0xcf, - 0x4f, 0xcf, 0x49, 0xd5, - 0x4b, 0xce, 0xcf, 0xd5, - 0x67, 0x60, 0x2f, 0x4b, - 0x2d, 0x2a, 0xce, 0xcc, - 0xcf, 0x63, 0xe0, 0x00, - 0x29, 0xd0, 0x37, 0xd4, - 0x33, 0x04, 0x00, 0x00, - 0x00, 0xff, 0xff, - }, - ControlFrame( - TypeSynStream, - 0x01, - []byte{ - 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xbb, - 0xdf, 0xa2, 0x51, 0xb2, - 0x62, 0x60, 0x66, 0x60, - 0xcb, 0x4d, 0x2d, 0xc9, - 0xc8, 0x4f, 0x61, 0x60, - 0x4e, 0x4f, 0x2d, 0x61, - 0x60, 0x2e, 0x2d, 0xca, - 0x61, 0x10, 0xcb, 0x28, - 0x29, 0x29, 0xb0, 0xd2, - 0xd7, 0x2f, 0x2f, 0x2f, - 0xd7, 0x4b, 0xcf, 0xcf, - 0x4f, 0xcf, 0x49, 0xd5, - 0x4b, 0xce, 0xcf, 0xd5, - 0x67, 0x60, 0x2f, 0x4b, - 0x2d, 0x2a, 0xce, 0xcc, - 0xcf, 0x63, 0xe0, 0x00, - 0x29, 0xd0, 0x37, 0xd4, - 0x33, 0x04, 0x00, 0x00, - 0x00, 0xff, 0xff, - }, - ), - nil, - false, - }, - { - "data frame", - []byte{ - 0x00, 0x00, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x04, - 0x01, 0x02, 0x03, 0x04, - }, - DataFrame( - 5, - 0x01, - []byte{0x01, 0x02, 0x03, 0x04}, - ), - nil, - false, - }, - { - "too much data", - []byte{ - 0x00, 0x00, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x04, - 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, - }, - DataFrame( - 5, - 0x01, - []byte{0x01, 0x02, 0x03, 0x04}, - ), - nil, - true, - }, - { - "not enough data", - []byte{ - 0x00, 0x00, 0x00, 0x05, - }, - Frame{}, - os.EOF, - true, - }, -} - -func TestReadFrame(t *testing.T) { - for _, tt := range frameIoTests { - f, err := ReadFrame(bytes.NewBuffer(tt.data)) - if err != tt.readError { - t.Errorf("%s: ReadFrame: %s", tt.desc, err) - continue - } - if err == nil { - if !bytes.Equal(f.Header[:], tt.frame.Header[:]) { - t.Errorf("%s: header %q != %q", tt.desc, string(f.Header[:]), string(tt.frame.Header[:])) - } - if f.Flags != tt.frame.Flags { - t.Errorf("%s: flags %#02x != %#02x", tt.desc, f.Flags, tt.frame.Flags) - } - if !bytes.Equal(f.Data, tt.frame.Data) { - t.Errorf("%s: data %q != %q", tt.desc, string(f.Data), string(tt.frame.Data)) - } - } - } -} - -func TestWriteTo(t *testing.T) { - for _, tt := range frameIoTests { - if tt.readOnly { - continue - } - b := new(bytes.Buffer) - _, err := tt.frame.WriteTo(b) - if err != nil { - t.Errorf("%s: WriteTo: %s", tt.desc, err) - } - if !bytes.Equal(b.Bytes(), tt.data) { - t.Errorf("%s: data %q != %q", tt.desc, string(b.Bytes()), string(tt.data)) - } - } -} - -var headerDataTest = []byte{ - 0x78, 0xbb, 0xdf, 0xa2, - 0x51, 0xb2, 0x62, 0x60, - 0x66, 0x60, 0xcb, 0x4d, - 0x2d, 0xc9, 0xc8, 0x4f, - 0x61, 0x60, 0x4e, 0x4f, - 0x2d, 0x61, 0x60, 0x2e, - 0x2d, 0xca, 0x61, 0x10, - 0xcb, 0x28, 0x29, 0x29, - 0xb0, 0xd2, 0xd7, 0x2f, - 0x2f, 0x2f, 0xd7, 0x4b, - 0xcf, 0xcf, 0x4f, 0xcf, - 0x49, 0xd5, 0x4b, 0xce, - 0xcf, 0xd5, 0x67, 0x60, - 0x2f, 0x4b, 0x2d, 0x2a, - 0xce, 0xcc, 0xcf, 0x63, - 0xe0, 0x00, 0x29, 0xd0, - 0x37, 0xd4, 0x33, 0x04, - 0x00, 0x00, 0x00, 0xff, - 0xff, -} - -func TestReadHeader(t *testing.T) { - r := NewHeaderReader() - h, err := r.Decode(headerDataTest) - if err != nil { - t.Fatalf("Error: %v", err) - return - } - if len(h) != 3 { - t.Errorf("Header count = %d (expected 3)", len(h)) - } - if h.Get("Url") != "http://www.google.com/" { - t.Errorf("Url: %q != %q", h.Get("Url"), "http://www.google.com/") - } - if h.Get("Method") != "get" { - t.Errorf("Method: %q != %q", h.Get("Method"), "get") - } - if h.Get("Version") != "http/1.1" { - t.Errorf("Version: %q != %q", h.Get("Version"), "http/1.1") - } -} - -func TestWriteHeader(t *testing.T) { - for level := zlib.NoCompression; level <= zlib.BestCompression; level++ { - r := NewHeaderReader() - w := NewHeaderWriter(level) - for i := 0; i < 100; i++ { - b := new(bytes.Buffer) - gold := http.Header{ - "Url": []string{"http://www.google.com/"}, - "Method": []string{"get"}, - "Version": []string{"http/1.1"}, - } - w.WriteHeader(b, gold) - h, err := r.Decode(b.Bytes()) - if err != nil { - t.Errorf("(level=%d i=%d) Error: %v", level, i, err) - return - } - if len(h) != len(gold) { - t.Errorf("(level=%d i=%d) Header count = %d (expected %d)", level, i, len(h), len(gold)) - } - for k, _ := range h { - if h.Get(k) != gold.Get(k) { - t.Errorf("(level=%d i=%d) %s: %q != %q", level, i, k, h.Get(k), gold.Get(k)) - } - } - } - } -} diff --git a/src/pkg/http/spdy/read.go b/src/pkg/http/spdy/read.go new file mode 100644 index 000000000..159dbc578 --- /dev/null +++ b/src/pkg/http/spdy/read.go @@ -0,0 +1,287 @@ +// Copyright 2011 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 spdy + +import ( + "compress/zlib" + "encoding/binary" + "http" + "io" + "os" + "strings" +) + +func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error { + return f.readSynStreamFrame(h, frame) +} + +func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) os.Error { + return f.readSynReplyFrame(h, frame) +} + +func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil { + return err + } + return nil +} + +func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) os.Error { + frame.CFHeader = h + var numSettings uint32 + if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil { + return err + } + frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings) + for i := uint32(0); i < numSettings; i++ { + if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil { + return err + } + frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24) + frame.FlagIdValues[i].Id &= 0xffffff + if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil { + return err + } + } + return nil +} + +func (frame *NoopFrame) read(h ControlFrameHeader, f *Framer) os.Error { + frame.CFHeader = h + return nil +} + +func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) os.Error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil { + return err + } + return nil +} + +func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) os.Error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil { + return err + } + return nil +} + +func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) os.Error { + return f.readHeadersFrame(h, frame) +} + +func newControlFrame(frameType ControlFrameType) (controlFrame, os.Error) { + ctor, ok := cframeCtor[frameType] + if !ok { + return nil, InvalidControlFrame + } + return ctor(), nil +} + +var cframeCtor = map[ControlFrameType]func() controlFrame{ + TypeSynStream: func() controlFrame { return new(SynStreamFrame) }, + TypeSynReply: func() controlFrame { return new(SynReplyFrame) }, + TypeRstStream: func() controlFrame { return new(RstStreamFrame) }, + TypeSettings: func() controlFrame { return new(SettingsFrame) }, + TypeNoop: func() controlFrame { return new(NoopFrame) }, + TypePing: func() controlFrame { return new(PingFrame) }, + TypeGoAway: func() controlFrame { return new(GoAwayFrame) }, + TypeHeaders: func() controlFrame { return new(HeadersFrame) }, + // TODO(willchan): Add TypeWindowUpdate +} + +type corkedReader struct { + r io.Reader + ch chan int + n int +} + +func (cr *corkedReader) Read(p []byte) (int, os.Error) { + if cr.n == 0 { + cr.n = <-cr.ch + } + if len(p) > cr.n { + p = p[:cr.n] + } + n, err := cr.r.Read(p) + cr.n -= n + return n, err +} + +func (f *Framer) uncorkHeaderDecompressor(payloadSize int) os.Error { + if f.headerDecompressor != nil { + f.headerReader.ch <- payloadSize + return nil + } + f.headerReader = corkedReader{r: f.r, ch: make(chan int, 1), n: payloadSize} + decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(HeaderDictionary)) + if err != nil { + return err + } + f.headerDecompressor = decompressor + return nil +} + +// ReadFrame reads SPDY encoded data and returns a decompressed Frame. +func (f *Framer) ReadFrame() (Frame, os.Error) { + var firstWord uint32 + if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil { + return nil, err + } + if (firstWord & 0x80000000) != 0 { + frameType := ControlFrameType(firstWord & 0xffff) + version := uint16(0x7fff & (firstWord >> 16)) + return f.parseControlFrame(version, frameType) + } + return f.parseDataFrame(firstWord & 0x7fffffff) +} + +func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, os.Error) { + var length uint32 + if err := binary.Read(f.r, binary.BigEndian, &length); err != nil { + return nil, err + } + flags := ControlFlags((length & 0xff000000) >> 24) + length &= 0xffffff + header := ControlFrameHeader{version, frameType, flags, length} + cframe, err := newControlFrame(frameType) + if err != nil { + return nil, err + } + if err = cframe.read(header, f); err != nil { + return nil, err + } + return cframe, nil +} + +func parseHeaderValueBlock(r io.Reader) (http.Header, os.Error) { + var numHeaders uint16 + if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil { + return nil, err + } + h := make(http.Header, int(numHeaders)) + for i := 0; i < int(numHeaders); i++ { + var length uint16 + if err := binary.Read(r, binary.BigEndian, &length); err != nil { + return nil, err + } + nameBytes := make([]byte, length) + if _, err := io.ReadFull(r, nameBytes); err != nil { + return nil, err + } + name := string(nameBytes) + if name != strings.ToLower(name) { + return nil, UnlowercasedHeaderName + } + if h[name] != nil { + return nil, DuplicateHeaders + } + if err := binary.Read(r, binary.BigEndian, &length); err != nil { + return nil, err + } + value := make([]byte, length) + if _, err := io.ReadFull(r, value); err != nil { + return nil, err + } + valueList := strings.Split(string(value), "\x00", -1) + for _, v := range valueList { + h.Add(name, v) + } + } + return h, nil +} + +func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) os.Error { + frame.CFHeader = h + var err os.Error + if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil { + return err + } + if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil { + return err + } + frame.Priority >>= 14 + + reader := f.r + if !f.headerCompressionDisabled { + f.uncorkHeaderDecompressor(int(h.length - 10)) + reader = f.headerDecompressor + } + + frame.Headers, err = parseHeaderValueBlock(reader) + if err != nil { + return err + } + return nil +} + +func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) os.Error { + frame.CFHeader = h + var err os.Error + if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + var unused uint16 + if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil { + return err + } + reader := f.r + if !f.headerCompressionDisabled { + f.uncorkHeaderDecompressor(int(h.length - 6)) + reader = f.headerDecompressor + } + frame.Headers, err = parseHeaderValueBlock(reader) + if err != nil { + return err + } + return nil +} + +func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) os.Error { + frame.CFHeader = h + var err os.Error + if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + var unused uint16 + if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil { + return err + } + reader := f.r + if !f.headerCompressionDisabled { + f.uncorkHeaderDecompressor(int(h.length - 6)) + reader = f.headerDecompressor + } + frame.Headers, err = parseHeaderValueBlock(reader) + if err != nil { + return err + } + return nil +} + +func (f *Framer) parseDataFrame(streamId uint32) (*DataFrame, os.Error) { + var length uint32 + if err := binary.Read(f.r, binary.BigEndian, &length); err != nil { + return nil, err + } + var frame DataFrame + frame.StreamId = streamId + frame.Flags = DataFlags(length >> 24) + length &= 0xffffff + frame.Data = make([]byte, length) + // TODO(willchan): Support compressed data frames. + if _, err := io.ReadFull(f.r, frame.Data); err != nil { + return nil, err + } + return &frame, nil +} diff --git a/src/pkg/http/spdy/spdy_test.go b/src/pkg/http/spdy/spdy_test.go new file mode 100644 index 000000000..9100e1ea8 --- /dev/null +++ b/src/pkg/http/spdy/spdy_test.go @@ -0,0 +1,496 @@ +// Copyright 2011 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 spdy + +import ( + "bytes" + "http" + "io" + "reflect" + "testing" +) + +func TestHeaderParsing(t *testing.T) { + headers := http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + } + var headerValueBlockBuf bytes.Buffer + writeHeaderValueBlock(&headerValueBlockBuf, headers) + + newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf) + if err != nil { + t.Fatal("parseHeaderValueBlock:", err) + } + + if !reflect.DeepEqual(headers, newHeaders) { + t.Fatal("got: ", newHeaders, "\nwant: ", headers) + } +} + +func TestCreateParseSynStreamFrame(t *testing.T) { + buffer := new(bytes.Buffer) + framer := &Framer{ + headerCompressionDisabled: true, + w: buffer, + headerBuf: new(bytes.Buffer), + r: buffer, + } + synStreamFrame := SynStreamFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeSynStream, + }, + Headers: http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + }, + } + if err := framer.WriteFrame(&synStreamFrame); err != nil { + t.Fatal("WriteFrame without compression:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame without compression:", err) + } + parsedSynStreamFrame, ok := frame.(*SynStreamFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) { + t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame) + } + + // Test again with compression + buffer.Reset() + framer, err = NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + if err := framer.WriteFrame(&synStreamFrame); err != nil { + t.Fatal("WriteFrame with compression:", err) + } + frame, err = framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame with compression:", err) + } + parsedSynStreamFrame, ok = frame.(*SynStreamFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) { + t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame) + } +} + +func TestCreateParseSynReplyFrame(t *testing.T) { + buffer := new(bytes.Buffer) + framer := &Framer{ + headerCompressionDisabled: true, + w: buffer, + headerBuf: new(bytes.Buffer), + r: buffer, + } + synReplyFrame := SynReplyFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeSynReply, + }, + Headers: http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + }, + } + if err := framer.WriteFrame(&synReplyFrame); err != nil { + t.Fatal("WriteFrame without compression:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame without compression:", err) + } + parsedSynReplyFrame, ok := frame.(*SynReplyFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) { + t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame) + } + + // Test again with compression + buffer.Reset() + framer, err = NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + if err := framer.WriteFrame(&synReplyFrame); err != nil { + t.Fatal("WriteFrame with compression:", err) + } + frame, err = framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame with compression:", err) + } + parsedSynReplyFrame, ok = frame.(*SynReplyFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) { + t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame) + } +} + +func TestCreateParseRstStream(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + rstStreamFrame := RstStreamFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeRstStream, + }, + StreamId: 1, + Status: InvalidStream, + } + if err := framer.WriteFrame(&rstStreamFrame); err != nil { + t.Fatal("WriteFrame:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame:", err) + } + parsedRstStreamFrame, ok := frame.(*RstStreamFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) { + t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame) + } +} + +func TestCreateParseSettings(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + settingsFrame := SettingsFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeSettings, + }, + FlagIdValues: []SettingsFlagIdValue{ + {FlagSettingsPersistValue, SettingsCurrentCwnd, 10}, + {FlagSettingsPersisted, SettingsUploadBandwidth, 1}, + }, + } + if err := framer.WriteFrame(&settingsFrame); err != nil { + t.Fatal("WriteFrame:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame:", err) + } + parsedSettingsFrame, ok := frame.(*SettingsFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) { + t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame) + } +} + +func TestCreateParseNoop(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + noopFrame := NoopFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeNoop, + }, + } + if err := framer.WriteFrame(&noopFrame); err != nil { + t.Fatal("WriteFrame:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame:", err) + } + parsedNoopFrame, ok := frame.(*NoopFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(noopFrame, *parsedNoopFrame) { + t.Fatal("got: ", *parsedNoopFrame, "\nwant: ", noopFrame) + } +} + +func TestCreateParsePing(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + pingFrame := PingFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypePing, + }, + Id: 31337, + } + if err := framer.WriteFrame(&pingFrame); err != nil { + t.Fatal("WriteFrame:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame:", err) + } + parsedPingFrame, ok := frame.(*PingFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(pingFrame, *parsedPingFrame) { + t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame) + } +} + +func TestCreateParseGoAway(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + goAwayFrame := GoAwayFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeGoAway, + }, + LastGoodStreamId: 31337, + } + if err := framer.WriteFrame(&goAwayFrame); err != nil { + t.Fatal("WriteFrame:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame:", err) + } + parsedGoAwayFrame, ok := frame.(*GoAwayFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) { + t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame) + } +} + +func TestCreateParseHeadersFrame(t *testing.T) { + buffer := new(bytes.Buffer) + framer := &Framer{ + headerCompressionDisabled: true, + w: buffer, + headerBuf: new(bytes.Buffer), + r: buffer, + } + headersFrame := HeadersFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeHeaders, + }, + } + headersFrame.Headers = http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + } + if err := framer.WriteFrame(&headersFrame); err != nil { + t.Fatal("WriteFrame without compression:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame without compression:", err) + } + parsedHeadersFrame, ok := frame.(*HeadersFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) { + t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame) + } + + // Test again with compression + buffer.Reset() + framer, err = NewFramer(buffer, buffer) + if err := framer.WriteFrame(&headersFrame); err != nil { + t.Fatal("WriteFrame with compression:", err) + } + frame, err = framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame with compression:", err) + } + parsedHeadersFrame, ok = frame.(*HeadersFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) { + t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame) + } +} + +func TestCreateParseDataFrame(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + dataFrame := DataFrame{ + StreamId: 1, + Data: []byte{'h', 'e', 'l', 'l', 'o'}, + } + if err := framer.WriteFrame(&dataFrame); err != nil { + t.Fatal("WriteFrame:", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame:", err) + } + parsedDataFrame, ok := frame.(*DataFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(dataFrame, *parsedDataFrame) { + t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame) + } +} + +func TestCompressionContextAcrossFrames(t *testing.T) { + buffer := new(bytes.Buffer) + framer, err := NewFramer(buffer, buffer) + if err != nil { + t.Fatal("Failed to create new framer:", err) + } + headersFrame := HeadersFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeHeaders, + }, + Headers: http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + }, + } + if err := framer.WriteFrame(&headersFrame); err != nil { + t.Fatal("WriteFrame (HEADERS):", err) + } + synStreamFrame := SynStreamFrame{ControlFrameHeader{Version, TypeSynStream, 0, 0}, 0, 0, 0, nil} + synStreamFrame.Headers = http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + } + if err := framer.WriteFrame(&synStreamFrame); err != nil { + t.Fatal("WriteFrame (SYN_STREAM):", err) + } + frame, err := framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes()) + } + parsedHeadersFrame, ok := frame.(*HeadersFrame) + if !ok { + t.Fatalf("expected HeadersFrame; got %T %v", frame, frame) + } + if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) { + t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame) + } + frame, err = framer.ReadFrame() + if err != nil { + t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes()) + } + parsedSynStreamFrame, ok := frame.(*SynStreamFrame) + if !ok { + t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame) + } + if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) { + t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame) + } +} + +func TestMultipleSPDYFrames(t *testing.T) { + // Initialize the framers. + pr1, pw1 := io.Pipe() + pr2, pw2 := io.Pipe() + writer, err := NewFramer(pw1, pr2) + if err != nil { + t.Fatal("Failed to create writer:", err) + } + reader, err := NewFramer(pw2, pr1) + if err != nil { + t.Fatal("Failed to create reader:", err) + } + + // Set up the frames we're actually transferring. + headersFrame := HeadersFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeHeaders, + }, + Headers: http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + }, + } + synStreamFrame := SynStreamFrame{ + CFHeader: ControlFrameHeader{ + version: Version, + frameType: TypeSynStream, + }, + Headers: http.Header{ + "Url": []string{"http://www.google.com/"}, + "Method": []string{"get"}, + "Version": []string{"http/1.1"}, + }, + } + + // Start the goroutines to write the frames. + go func() { + if err := writer.WriteFrame(&headersFrame); err != nil { + t.Fatal("WriteFrame (HEADERS): ", err) + } + if err := writer.WriteFrame(&synStreamFrame); err != nil { + t.Fatal("WriteFrame (SYN_STREAM): ", err) + } + }() + + // Read the frames and verify they look as expected. + frame, err := reader.ReadFrame() + if err != nil { + t.Fatal("ReadFrame (HEADERS): ", err) + } + parsedHeadersFrame, ok := frame.(*HeadersFrame) + if !ok { + t.Fatal("Parsed incorrect frame type:", frame) + } + if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) { + t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame) + } + frame, err = reader.ReadFrame() + if err != nil { + t.Fatal("ReadFrame (SYN_STREAM):", err) + } + parsedSynStreamFrame, ok := frame.(*SynStreamFrame) + if !ok { + t.Fatal("Parsed incorrect frame type.") + } + if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) { + t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame) + } +} diff --git a/src/pkg/http/spdy/types.go b/src/pkg/http/spdy/types.go new file mode 100644 index 000000000..5a665f04f --- /dev/null +++ b/src/pkg/http/spdy/types.go @@ -0,0 +1,363 @@ +// Copyright 2011 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 spdy + +import ( + "bytes" + "compress/zlib" + "http" + "io" + "os" + "strconv" +) + +// Data Frame Format +// +----------------------------------+ +// |0| Stream-ID (31bits) | +// +----------------------------------+ +// | flags (8) | Length (24 bits) | +// +----------------------------------+ +// | Data | +// +----------------------------------+ +// +// Control Frame Format +// +----------------------------------+ +// |1| Version(15bits) | Type(16bits) | +// +----------------------------------+ +// | flags (8) | Length (24 bits) | +// +----------------------------------+ +// | Data | +// +----------------------------------+ +// +// Control Frame: SYN_STREAM +// +----------------------------------+ +// |1|000000000000001|0000000000000001| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | >= 12 +// +----------------------------------+ +// |X| Stream-ID(31bits) | +// +----------------------------------+ +// |X|Associated-To-Stream-ID (31bits)| +// +----------------------------------+ +// |Pri| unused | Length (16bits)| +// +----------------------------------+ +// +// Control Frame: SYN_REPLY +// +----------------------------------+ +// |1|000000000000001|0000000000000010| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | >= 8 +// +----------------------------------+ +// |X| Stream-ID(31bits) | +// +----------------------------------+ +// | unused (16 bits)| Length (16bits)| +// +----------------------------------+ +// +// Control Frame: RST_STREAM +// +----------------------------------+ +// |1|000000000000001|0000000000000011| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | >= 4 +// +----------------------------------+ +// |X| Stream-ID(31bits) | +// +----------------------------------+ +// | Status code (32 bits) | +// +----------------------------------+ +// +// Control Frame: SETTINGS +// +----------------------------------+ +// |1|000000000000001|0000000000000100| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | +// +----------------------------------+ +// | # of entries (32) | +// +----------------------------------+ +// +// Control Frame: NOOP +// +----------------------------------+ +// |1|000000000000001|0000000000000101| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | = 0 +// +----------------------------------+ +// +// Control Frame: PING +// +----------------------------------+ +// |1|000000000000001|0000000000000110| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | = 4 +// +----------------------------------+ +// | Unique id (32 bits) | +// +----------------------------------+ +// +// Control Frame: GOAWAY +// +----------------------------------+ +// |1|000000000000001|0000000000000111| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | = 4 +// +----------------------------------+ +// |X| Last-accepted-stream-id | +// +----------------------------------+ +// +// Control Frame: HEADERS +// +----------------------------------+ +// |1|000000000000001|0000000000001000| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | >= 8 +// +----------------------------------+ +// |X| Stream-ID (31 bits) | +// +----------------------------------+ +// | unused (16 bits)| Length (16bits)| +// +----------------------------------+ +// +// Control Frame: WINDOW_UPDATE +// +----------------------------------+ +// |1|000000000000001|0000000000001001| +// +----------------------------------+ +// | flags (8) | Length (24 bits) | = 8 +// +----------------------------------+ +// |X| Stream-ID (31 bits) | +// +----------------------------------+ +// | Delta-Window-Size (32 bits) | +// +----------------------------------+ + +// Version is the protocol version number that this package implements. +const Version = 2 + +// ControlFrameType stores the type field in a control frame header. +type ControlFrameType uint16 + +// Control frame type constants +const ( + TypeSynStream ControlFrameType = 0x0001 + TypeSynReply = 0x0002 + TypeRstStream = 0x0003 + TypeSettings = 0x0004 + TypeNoop = 0x0005 + TypePing = 0x0006 + TypeGoAway = 0x0007 + TypeHeaders = 0x0008 + TypeWindowUpdate = 0x0009 +) + +// ControlFlags are the flags that can be set on a control frame. +type ControlFlags uint8 + +const ( + ControlFlagFin ControlFlags = 0x01 +) + +// DataFlags are the flags that can be set on a data frame. +type DataFlags uint8 + +const ( + DataFlagFin DataFlags = 0x01 + DataFlagCompressed = 0x02 +) + +// MaxDataLength is the maximum number of bytes that can be stored in one frame. +const MaxDataLength = 1<<24 - 1 + +// Frame is a single SPDY frame in its unpacked in-memory representation. Use +// Framer to read and write it. +type Frame interface { + write(f *Framer) os.Error +} + +// ControlFrameHeader contains all the fields in a control frame header, +// in its unpacked in-memory representation. +type ControlFrameHeader struct { + // Note, high bit is the "Control" bit. + version uint16 + frameType ControlFrameType + Flags ControlFlags + length uint32 +} + +type controlFrame interface { + Frame + read(h ControlFrameHeader, f *Framer) os.Error +} + +// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM +// frame. +type SynStreamFrame struct { + CFHeader ControlFrameHeader + StreamId uint32 + AssociatedToStreamId uint32 + // Note, only 2 highest bits currently used + // Rest of Priority is unused. + Priority uint16 + Headers http.Header +} + +// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame. +type SynReplyFrame struct { + CFHeader ControlFrameHeader + StreamId uint32 + Headers http.Header +} + +// StatusCode represents the status that led to a RST_STREAM +type StatusCode uint32 + +const ( + ProtocolError StatusCode = 1 + InvalidStream = 2 + RefusedStream = 3 + UnsupportedVersion = 4 + Cancel = 5 + InternalError = 6 + FlowControlError = 7 +) + +// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM +// frame. +type RstStreamFrame struct { + CFHeader ControlFrameHeader + StreamId uint32 + Status StatusCode +} + +// SettingsFlag represents a flag in a SETTINGS frame. +type SettingsFlag uint8 + +const ( + FlagSettingsPersistValue SettingsFlag = 0x1 + FlagSettingsPersisted = 0x2 +) + +// SettingsFlag represents the id of an id/value pair in a SETTINGS frame. +type SettingsId uint32 + +const ( + SettingsUploadBandwidth SettingsId = 1 + SettingsDownloadBandwidth = 2 + SettingsRoundTripTime = 3 + SettingsMaxConcurrentStreams = 4 + SettingsCurrentCwnd = 5 +) + +// SettingsFlagIdValue is the unpacked, in-memory representation of the +// combined flag/id/value for a setting in a SETTINGS frame. +type SettingsFlagIdValue struct { + Flag SettingsFlag + Id SettingsId + Value uint32 +} + +// SettingsFrame is the unpacked, in-memory representation of a SPDY +// SETTINGS frame. +type SettingsFrame struct { + CFHeader ControlFrameHeader + FlagIdValues []SettingsFlagIdValue +} + +// NoopFrame is the unpacked, in-memory representation of a NOOP frame. +type NoopFrame struct { + CFHeader ControlFrameHeader +} + +// PingFrame is the unpacked, in-memory representation of a PING frame. +type PingFrame struct { + CFHeader ControlFrameHeader + Id uint32 +} + +// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame. +type GoAwayFrame struct { + CFHeader ControlFrameHeader + LastGoodStreamId uint32 +} + +// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame. +type HeadersFrame struct { + CFHeader ControlFrameHeader + StreamId uint32 + Headers http.Header +} + +// DataFrame is the unpacked, in-memory representation of a DATA frame. +type DataFrame struct { + // Note, high bit is the "Control" bit. Should be 0 for data frames. + StreamId uint32 + Flags DataFlags + Data []byte +} + +// HeaderDictionary is the dictionary sent to the zlib compressor/decompressor. +// Even though the specification states there is no null byte at the end, Chrome sends it. +const HeaderDictionary = "optionsgetheadpostputdeletetrace" + + "acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" + + "if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" + + "max-forwardsproxy-authorizationrangerefererteuser-agent" + + "100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" + + "accept-rangesageetaglocationproxy-authenticatepublicretry-after" + + "servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" + + "connectiondatetrailertransfer-encodingupgradeviawarning" + + "content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" + + "MondayTuesdayWednesdayThursdayFridaySaturdaySunday" + + "JanFebMarAprMayJunJulAugSepOctNovDec" + + "chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" + + "charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00" + +type FramerError int + +const ( + Internal FramerError = iota + InvalidControlFrame + UnlowercasedHeaderName + DuplicateHeaders + UnknownFrameType + InvalidDataFrame +) + +func (e FramerError) String() string { + switch e { + case Internal: + return "Internal" + case InvalidControlFrame: + return "InvalidControlFrame" + case UnlowercasedHeaderName: + return "UnlowercasedHeaderName" + case DuplicateHeaders: + return "DuplicateHeaders" + case UnknownFrameType: + return "UnknownFrameType" + case InvalidDataFrame: + return "InvalidDataFrame" + } + return "Error(" + strconv.Itoa(int(e)) + ")" +} + +// Framer handles serializing/deserializing SPDY frames, including compressing/ +// decompressing payloads. +type Framer struct { + headerCompressionDisabled bool + w io.Writer + headerBuf *bytes.Buffer + headerCompressor *zlib.Writer + r io.Reader + headerReader corkedReader + headerDecompressor io.ReadCloser +} + +// NewFramer allocates a new Framer for a given SPDY connection, repesented by +// a io.Writer and io.Reader. Note that Framer will read and write individual fields +// from/to the Reader and Writer, so the caller should pass in an appropriately +// buffered implementation to optimize performance. +func NewFramer(w io.Writer, r io.Reader) (*Framer, os.Error) { + compressBuf := new(bytes.Buffer) + compressor, err := zlib.NewWriterDict(compressBuf, zlib.BestCompression, []byte(HeaderDictionary)) + if err != nil { + return nil, err + } + framer := &Framer{ + w: w, + headerBuf: compressBuf, + headerCompressor: compressor, + r: r, + } + return framer, nil +} diff --git a/src/pkg/http/spdy/write.go b/src/pkg/http/spdy/write.go new file mode 100644 index 000000000..aa1679f1b --- /dev/null +++ b/src/pkg/http/spdy/write.go @@ -0,0 +1,287 @@ +// Copyright 2011 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 spdy + +import ( + "encoding/binary" + "http" + "io" + "os" + "strings" +) + +func (frame *SynStreamFrame) write(f *Framer) os.Error { + return f.writeSynStreamFrame(frame) +} + +func (frame *SynReplyFrame) write(f *Framer) os.Error { + return f.writeSynReplyFrame(frame) +} + +func (frame *RstStreamFrame) write(f *Framer) (err os.Error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeRstStream + frame.CFHeader.length = 8 + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil { + return + } + return +} + +func (frame *SettingsFrame) write(f *Framer) (err os.Error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeSettings + frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4) + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil { + return + } + for _, flagIdValue := range frame.FlagIdValues { + flagId := (uint32(flagIdValue.Flag) << 24) | uint32(flagIdValue.Id) + if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil { + return + } + } + return +} + +func (frame *NoopFrame) write(f *Framer) os.Error { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeNoop + + // Serialize frame to Writer + return writeControlFrameHeader(f.w, frame.CFHeader) +} + +func (frame *PingFrame) write(f *Framer) (err os.Error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypePing + frame.CFHeader.length = 4 + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil { + return + } + return +} + +func (frame *GoAwayFrame) write(f *Framer) (err os.Error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeGoAway + frame.CFHeader.length = 4 + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil { + return + } + return nil +} + +func (frame *HeadersFrame) write(f *Framer) os.Error { + return f.writeHeadersFrame(frame) +} + +func (frame *DataFrame) write(f *Framer) os.Error { + return f.writeDataFrame(frame) +} + +// WriteFrame writes a frame. +func (f *Framer) WriteFrame(frame Frame) os.Error { + return frame.write(f) +} + +func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) os.Error { + if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil { + return err + } + if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil { + return err + } + flagsAndLength := (uint32(h.Flags) << 24) | h.length + if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil { + return err + } + return nil +} + +func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err os.Error) { + n = 0 + if err = binary.Write(w, binary.BigEndian, uint16(len(h))); err != nil { + return + } + n += 2 + for name, values := range h { + if err = binary.Write(w, binary.BigEndian, uint16(len(name))); err != nil { + return + } + n += 2 + name = strings.ToLower(name) + if _, err = io.WriteString(w, name); err != nil { + return + } + n += len(name) + v := strings.Join(values, "\x00") + if err = binary.Write(w, binary.BigEndian, uint16(len(v))); err != nil { + return + } + n += 2 + if _, err = io.WriteString(w, v); err != nil { + return + } + n += len(v) + } + return +} + +func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err os.Error) { + // Marshal the headers. + var writer io.Writer = f.headerBuf + if !f.headerCompressionDisabled { + writer = f.headerCompressor + } + if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil { + return + } + if !f.headerCompressionDisabled { + f.headerCompressor.Flush() + } + + // Set ControlFrameHeader + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeSynStream + frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10) + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<14); err != nil { + return err + } + if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil { + return err + } + f.headerBuf.Reset() + return nil +} + +func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err os.Error) { + // Marshal the headers. + var writer io.Writer = f.headerBuf + if !f.headerCompressionDisabled { + writer = f.headerCompressor + } + if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil { + return + } + if !f.headerCompressionDisabled { + f.headerCompressor.Flush() + } + + // Set ControlFrameHeader + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeSynReply + frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6) + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil { + return + } + if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil { + return + } + f.headerBuf.Reset() + return +} + +func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err os.Error) { + // Marshal the headers. + var writer io.Writer = f.headerBuf + if !f.headerCompressionDisabled { + writer = f.headerCompressor + } + if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil { + return + } + if !f.headerCompressionDisabled { + f.headerCompressor.Flush() + } + + // Set ControlFrameHeader + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeHeaders + frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6) + + // Serialize frame to Writer + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil { + return + } + if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil { + return + } + f.headerBuf.Reset() + return +} + +func (f *Framer) writeDataFrame(frame *DataFrame) (err os.Error) { + // Validate DataFrame + if frame.StreamId&0x80000000 != 0 || len(frame.Data) >= 0x0f000000 { + return InvalidDataFrame + } + + // TODO(willchan): Support data compression. + // Serialize frame to Writer + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + flagsAndLength := (uint32(frame.Flags) << 24) | uint32(len(frame.Data)) + if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil { + return + } + if _, err = f.w.Write(frame.Data); err != nil { + return + } + + return nil +} diff --git a/src/pkg/http/transport.go b/src/pkg/http/transport.go index 34bfbdd34..c907d85fd 100644 --- a/src/pkg/http/transport.go +++ b/src/pkg/http/transport.go @@ -36,17 +36,23 @@ const DefaultMaxIdleConnsPerHost = 2 type Transport struct { lk sync.Mutex idleConn map[string][]*persistConn + altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper // TODO: tunable on global max cached connections // TODO: tunable on timeout on cached connections // TODO: optional pipelining - // Proxy optionally specifies a function to return a proxy for - // a given Request. If the function returns a non-nil error, - // the request is aborted with the provided error. If Proxy is - // nil or returns a nil *URL, no proxy is used. + // Proxy specifies a function to return a proxy for a given + // Request. If the function returns a non-nil error, the + // request is aborted with the provided error. + // If Proxy is nil or returns a nil *URL, no proxy is used. Proxy func(*Request) (*URL, os.Error) + // Dial specifies the dial function for creating TCP + // connections. + // If Dial is nil, net.Dial is used. + Dial func(net, addr string) (c net.Conn, err os.Error) + DisableKeepAlives bool DisableCompression bool @@ -97,7 +103,16 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) { } } if req.URL.Scheme != "http" && req.URL.Scheme != "https" { - return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme} + t.lk.Lock() + var rt RoundTripper + if t.altProto != nil { + rt = t.altProto[req.URL.Scheme] + } + t.lk.Unlock() + if rt == nil { + return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme} + } + return rt.RoundTrip(req) } cm, err := t.connectMethodForRequest(req) @@ -117,6 +132,27 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) { return pconn.roundTrip(req) } +// RegisterProtocol registers a new protocol with scheme. +// The Transport will pass requests using the given scheme to rt. +// It is rt's responsibility to simulate HTTP request semantics. +// +// RegisterProtocol can be used by other packages to provide +// implementations of protocol schemes like "ftp" or "file". +func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) { + if scheme == "http" || scheme == "https" { + panic("protocol " + scheme + " already registered") + } + t.lk.Lock() + defer t.lk.Unlock() + if t.altProto == nil { + t.altProto = make(map[string]RoundTripper) + } + if _, exists := t.altProto[scheme]; exists { + panic("protocol " + scheme + " already registered") + } + t.altProto[scheme] = rt +} + // CloseIdleConnections closes any connections which were previously // connected from previous requests but are now sitting idle in // a "keep-alive" state. It does not interrupt any connections currently @@ -169,10 +205,7 @@ func (cm *connectMethod) proxyAuth() string { } proxyInfo := cm.proxyURL.RawUserinfo if proxyInfo != "" { - enc := base64.URLEncoding - encoded := make([]byte, enc.EncodedLen(len(proxyInfo))) - enc.Encode(encoded, []byte(proxyInfo)) - return "Basic " + string(encoded) + return "Basic " + base64.URLEncoding.EncodeToString([]byte(proxyInfo)) } return "" } @@ -227,6 +260,13 @@ func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) { return } +func (t *Transport) dial(network, addr string) (c net.Conn, err os.Error) { + if t.Dial != nil { + return t.Dial(network, addr) + } + return net.Dial(network, addr) +} + // getConn dials and creates a new persistConn to the target as // specified in the connectMethod. This includes doing a proxy CONNECT // and/or setting up TLS. If this doesn't return an error, the persistConn @@ -236,7 +276,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) { return pc, nil } - conn, err := net.Dial("tcp", cm.addr()) + conn, err := t.dial("tcp", cm.addr()) if err != nil { if cm.proxyURL != nil { err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err) diff --git a/src/pkg/http/transport_test.go b/src/pkg/http/transport_test.go index 9cd18ffec..76e97640e 100644 --- a/src/pkg/http/transport_test.go +++ b/src/pkg/http/transport_test.go @@ -17,6 +17,7 @@ import ( "io/ioutil" "os" "strconv" + "strings" "testing" "time" ) @@ -531,6 +532,36 @@ func TestTransportGzipRecursive(t *testing.T) { } } +type fooProto struct{} + +func (fooProto) RoundTrip(req *Request) (*Response, os.Error) { + res := &Response{ + Status: "200 OK", + StatusCode: 200, + Header: make(Header), + Body: ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())), + } + return res, nil +} + +func TestTransportAltProto(t *testing.T) { + tr := &Transport{} + c := &Client{Transport: tr} + tr.RegisterProtocol("foo", fooProto{}) + res, err := c.Get("foo://bar.com/path") + if err != nil { + t.Fatal(err) + } + bodyb, err := ioutil.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + body := string(bodyb) + if e := "You wanted foo://bar.com/path"; body != e { + t.Errorf("got response %q, want %q", body, e) + } +} + // rgz is a gzip quine that uncompresses to itself. var rgz = []byte{ 0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, diff --git a/src/pkg/image/gif/reader.go b/src/pkg/image/gif/reader.go index 5dd404036..9f7296a98 100644 --- a/src/pkg/image/gif/reader.go +++ b/src/pkg/image/gif/reader.go @@ -94,28 +94,26 @@ type blockReader struct { tmp [256]byte } -func (b *blockReader) Read(p []byte) (n int, err os.Error) { +func (b *blockReader) Read(p []byte) (int, os.Error) { if len(p) == 0 { - return - } - if len(b.slice) > 0 { - n = copy(p, b.slice) - b.slice = b.slice[n:] - return - } - var blockLen uint8 - blockLen, err = b.r.ReadByte() - if err != nil { - return + return 0, nil } - if blockLen == 0 { - return 0, os.EOF - } - b.slice = b.tmp[0:blockLen] - if _, err = io.ReadFull(b.r, b.slice); err != nil { - return + if len(b.slice) == 0 { + blockLen, err := b.r.ReadByte() + if err != nil { + return 0, err + } + if blockLen == 0 { + return 0, os.EOF + } + b.slice = b.tmp[0:blockLen] + if _, err = io.ReadFull(b.r, b.slice); err != nil { + return 0, err + } } - return b.Read(p) + n := copy(p, b.slice) + b.slice = b.slice[n:] + return n, nil } // decode reads a GIF image from r and stores the result in d. @@ -364,7 +362,7 @@ func (d *decoder) uninterlace(m *image.Paletted) { dx := d.width dy := d.height nPix = make([]uint8, dx*dy) - offset := 0 // steps through the input by sequentical scan lines. + offset := 0 // steps through the input by sequential scan lines. for _, pass := range interlacing { nOffset := pass.start * dx // steps through the output as defined by pass. for y := pass.start; y < dy; y += pass.skip { diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go index 4350acc82..1bdac36f5 100644 --- a/src/pkg/image/image.go +++ b/src/pkg/image/image.go @@ -58,6 +58,16 @@ func (p *RGBA) SetRGBA(x, y int, c RGBAColor) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *RGBA) SubImage(r Rectangle) Image { + return &RGBA{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *RGBA) Opaque() bool { if p.Rect.Empty() { @@ -117,6 +127,16 @@ func (p *RGBA64) SetRGBA64(x, y int, c RGBA64Color) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *RGBA64) SubImage(r Rectangle) Image { + return &RGBA64{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *RGBA64) Opaque() bool { if p.Rect.Empty() { @@ -176,6 +196,16 @@ func (p *NRGBA) SetNRGBA(x, y int, c NRGBAColor) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *NRGBA) SubImage(r Rectangle) Image { + return &NRGBA{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *NRGBA) Opaque() bool { if p.Rect.Empty() { @@ -235,6 +265,16 @@ func (p *NRGBA64) SetNRGBA64(x, y int, c NRGBA64Color) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *NRGBA64) SubImage(r Rectangle) Image { + return &NRGBA64{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *NRGBA64) Opaque() bool { if p.Rect.Empty() { @@ -294,6 +334,16 @@ func (p *Alpha) SetAlpha(x, y int, c AlphaColor) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *Alpha) SubImage(r Rectangle) Image { + return &Alpha{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *Alpha) Opaque() bool { if p.Rect.Empty() { @@ -353,6 +403,16 @@ func (p *Alpha16) SetAlpha16(x, y int, c Alpha16Color) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *Alpha16) SubImage(r Rectangle) Image { + return &Alpha16{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *Alpha16) Opaque() bool { if p.Rect.Empty() { @@ -412,6 +472,16 @@ func (p *Gray) SetGray(x, y int, c GrayColor) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *Gray) SubImage(r Rectangle) Image { + return &Gray{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *Gray) Opaque() bool { return true @@ -457,6 +527,16 @@ func (p *Gray16) SetGray16(x, y int, c Gray16Color) { p.Pix[y*p.Stride+x] = c } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *Gray16) SubImage(r Rectangle) Image { + return &Gray16{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *Gray16) Opaque() bool { return true @@ -544,6 +624,17 @@ func (p *Paletted) SetColorIndex(x, y int, index uint8) { p.Pix[y*p.Stride+x] = index } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *Paletted) SubImage(r Rectangle) Image { + return &Paletted{ + Pix: p.Pix, + Stride: p.Stride, + Rect: p.Rect.Intersect(r), + Palette: p.Palette, + } +} + // Opaque scans the entire image and returns whether or not it is fully opaque. func (p *Paletted) Opaque() bool { for _, c := range p.Palette { diff --git a/src/pkg/image/png/writer.go b/src/pkg/image/png/writer.go index a27586f23..d770cfad5 100644 --- a/src/pkg/image/png/writer.go +++ b/src/pkg/image/png/writer.go @@ -174,7 +174,7 @@ func (e *encoder) Write(b []byte) (int, os.Error) { // Chooses the filter to use for encoding the current row, and applies it. // The return value is the index of the filter and also of the row in cr that has had it applied. -func filter(cr [][]byte, pr []byte, bpp int) int { +func filter(cr *[nFilter][]byte, pr []byte, bpp int) int { // We try all five filter types, and pick the one that minimizes the sum of absolute differences. // This is the same heuristic that libpng uses, although the filters are attempted in order of // estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than @@ -304,7 +304,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error { // The +1 is for the per-row filter type, which is at cr[*][0]. b := m.Bounds() var cr [nFilter][]uint8 - for i := 0; i < len(cr); i++ { + for i := range cr { cr[i] = make([]uint8, 1+bpp*b.Dx()) cr[i][0] = uint8(i) } @@ -312,78 +312,84 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error { for y := b.Min.Y; y < b.Max.Y; y++ { // Convert from colors to bytes. + i := 1 switch cb { case cbG8: for x := b.Min.X; x < b.Max.X; x++ { c := image.GrayColorModel.Convert(m.At(x, y)).(image.GrayColor) - cr[0][x+1] = c.Y + cr[0][i] = c.Y + i++ } case cbTC8: // We have previously verified that the alpha value is fully opaque. cr0 := cr[0] if rgba != nil { yoff := y * rgba.Stride - xoff := 3*b.Min.X + 1 for _, color := range rgba.Pix[yoff+b.Min.X : yoff+b.Max.X] { - cr0[xoff] = color.R - cr0[xoff+1] = color.G - cr0[xoff+2] = color.B - xoff += 3 + cr0[i+0] = color.R + cr0[i+1] = color.G + cr0[i+2] = color.B + i += 3 } } else { for x := b.Min.X; x < b.Max.X; x++ { r, g, b, _ := m.At(x, y).RGBA() - cr0[3*x+1] = uint8(r >> 8) - cr0[3*x+2] = uint8(g >> 8) - cr0[3*x+3] = uint8(b >> 8) + cr0[i+0] = uint8(r >> 8) + cr0[i+1] = uint8(g >> 8) + cr0[i+2] = uint8(b >> 8) + i += 3 } } case cbP8: rowOffset := y * paletted.Stride - copy(cr[0][b.Min.X+1:], paletted.Pix[rowOffset+b.Min.X:rowOffset+b.Max.X]) + copy(cr[0][1:], paletted.Pix[rowOffset+b.Min.X:rowOffset+b.Max.X]) case cbTCA8: // Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied. for x := b.Min.X; x < b.Max.X; x++ { c := image.NRGBAColorModel.Convert(m.At(x, y)).(image.NRGBAColor) - cr[0][4*x+1] = c.R - cr[0][4*x+2] = c.G - cr[0][4*x+3] = c.B - cr[0][4*x+4] = c.A + cr[0][i+0] = c.R + cr[0][i+1] = c.G + cr[0][i+2] = c.B + cr[0][i+3] = c.A + i += 4 } case cbG16: for x := b.Min.X; x < b.Max.X; x++ { c := image.Gray16ColorModel.Convert(m.At(x, y)).(image.Gray16Color) - cr[0][2*x+1] = uint8(c.Y >> 8) - cr[0][2*x+2] = uint8(c.Y) + cr[0][i+0] = uint8(c.Y >> 8) + cr[0][i+1] = uint8(c.Y) + i += 2 } case cbTC16: + // We have previously verified that the alpha value is fully opaque. for x := b.Min.X; x < b.Max.X; x++ { - // We have previously verified that the alpha value is fully opaque. r, g, b, _ := m.At(x, y).RGBA() - cr[0][6*x+1] = uint8(r >> 8) - cr[0][6*x+2] = uint8(r) - cr[0][6*x+3] = uint8(g >> 8) - cr[0][6*x+4] = uint8(g) - cr[0][6*x+5] = uint8(b >> 8) - cr[0][6*x+6] = uint8(b) + cr[0][i+0] = uint8(r >> 8) + cr[0][i+1] = uint8(r) + cr[0][i+2] = uint8(g >> 8) + cr[0][i+3] = uint8(g) + cr[0][i+4] = uint8(b >> 8) + cr[0][i+5] = uint8(b) + i += 6 } case cbTCA16: // Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied. for x := b.Min.X; x < b.Max.X; x++ { c := image.NRGBA64ColorModel.Convert(m.At(x, y)).(image.NRGBA64Color) - cr[0][8*x+1] = uint8(c.R >> 8) - cr[0][8*x+2] = uint8(c.R) - cr[0][8*x+3] = uint8(c.G >> 8) - cr[0][8*x+4] = uint8(c.G) - cr[0][8*x+5] = uint8(c.B >> 8) - cr[0][8*x+6] = uint8(c.B) - cr[0][8*x+7] = uint8(c.A >> 8) - cr[0][8*x+8] = uint8(c.A) + cr[0][i+0] = uint8(c.R >> 8) + cr[0][i+1] = uint8(c.R) + cr[0][i+2] = uint8(c.G >> 8) + cr[0][i+3] = uint8(c.G) + cr[0][i+4] = uint8(c.B >> 8) + cr[0][i+5] = uint8(c.B) + cr[0][i+6] = uint8(c.A >> 8) + cr[0][i+7] = uint8(c.A) + i += 8 } } // Apply the filter. - f := filter(cr[0:nFilter], pr, bpp) + f := filter(&cr, pr, bpp) // Write the compressed bytes. _, err = zw.Write(cr[f]) diff --git a/src/pkg/image/png/writer_test.go b/src/pkg/image/png/writer_test.go index 6b054aaa8..271519a11 100644 --- a/src/pkg/image/png/writer_test.go +++ b/src/pkg/image/png/writer_test.go @@ -5,9 +5,9 @@ package png import ( + "bytes" "fmt" "image" - "io" "io/ioutil" "os" "testing" @@ -15,21 +15,38 @@ import ( func diff(m0, m1 image.Image) os.Error { b0, b1 := m0.Bounds(), m1.Bounds() - if !b0.Eq(b1) { + if !b0.Size().Eq(b1.Size()) { return fmt.Errorf("dimensions differ: %v vs %v", b0, b1) } + dx := b1.Min.X - b0.Min.X + dy := b1.Min.Y - b0.Min.Y for y := b0.Min.Y; y < b0.Max.Y; y++ { for x := b0.Min.X; x < b0.Max.X; x++ { - r0, g0, b0, a0 := m0.At(x, y).RGBA() - r1, g1, b1, a1 := m1.At(x, y).RGBA() + c0 := m0.At(x, y) + c1 := m1.At(x+dx, y+dy) + r0, g0, b0, a0 := c0.RGBA() + r1, g1, b1, a1 := c1.RGBA() if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { - return fmt.Errorf("colors differ at (%d, %d): %v vs %v", x, y, m0.At(x, y), m1.At(x, y)) + return fmt.Errorf("colors differ at (%d, %d): %v vs %v", x, y, c0, c1) } } } return nil } +func encodeDecode(m image.Image) (image.Image, os.Error) { + b := bytes.NewBuffer(nil) + err := Encode(b, m) + if err != nil { + return nil, err + } + m, err = Decode(b) + if err != nil { + return nil, err + } + return m, nil +} + func TestWriter(t *testing.T) { // The filenames variable is declared in reader_test.go. names := filenames @@ -44,26 +61,16 @@ func TestWriter(t *testing.T) { t.Error(fn, err) continue } - // Read the image again, and push it through a pipe that encodes at the write end, and decodes at the read end. - pr, pw := io.Pipe() - defer pr.Close() - go func() { - defer pw.Close() - m1, err := readPng(qfn) - if err != nil { - t.Error(fn, err) - return - } - err = Encode(pw, m1) - if err != nil { - t.Error(fn, err) - return - } - }() - m2, err := Decode(pr) + // Read the image again, encode it, and decode it. + m1, err := readPng(qfn) if err != nil { t.Error(fn, err) - continue + return + } + m2, err := encodeDecode(m1) + if err != nil { + t.Error(fn, err) + return } // Compare the two. err = diff(m0, m2) @@ -74,6 +81,26 @@ func TestWriter(t *testing.T) { } } +func TestSubimage(t *testing.T) { + m0 := image.NewRGBA(256, 256) + for y := 0; y < 256; y++ { + for x := 0; x < 256; x++ { + m0.Set(x, y, image.RGBAColor{uint8(x), uint8(y), 0, 255}) + } + } + m0.Rect = image.Rect(50, 30, 250, 130) + m1, err := encodeDecode(m0) + if err != nil { + t.Error(err) + return + } + err = diff(m0, m1) + if err != nil { + t.Error(err) + return + } +} + func BenchmarkEncodePaletted(b *testing.B) { b.StopTimer() img := image.NewPaletted(640, 480, diff --git a/src/pkg/image/ycbcr/ycbcr.go b/src/pkg/image/ycbcr/ycbcr.go index cda45996d..c1c58b708 100644 --- a/src/pkg/image/ycbcr/ycbcr.go +++ b/src/pkg/image/ycbcr/ycbcr.go @@ -169,6 +169,15 @@ func (p *YCbCr) At(x, y int) image.Color { } } +// SubImage returns an image representing the portion of the image p visible +// through r. The returned value shares pixels with the original image. +func (p *YCbCr) SubImage(r image.Rectangle) image.Image { + q := new(YCbCr) + *q = *p + q.Rect = q.Rect.Intersect(r) + return q +} + func (p *YCbCr) Opaque() bool { return true } diff --git a/src/pkg/index/suffixarray/suffixarray_test.go b/src/pkg/index/suffixarray/suffixarray_test.go index e85267f17..b1499027a 100644 --- a/src/pkg/index/suffixarray/suffixarray_test.go +++ b/src/pkg/index/suffixarray/suffixarray_test.go @@ -108,7 +108,7 @@ var testCases = []testCase{ } -// find all occurrences of s in source; report at most n occurences +// find all occurrences of s in source; report at most n occurrences func find(src, s string, n int) []int { var res vector.IntVector if s != "" && n != 0 { diff --git a/src/pkg/io/io.go b/src/pkg/io/io.go index 0bc73d67d..846dcacb5 100644 --- a/src/pkg/io/io.go +++ b/src/pkg/io/io.go @@ -162,6 +162,18 @@ type ByteReader interface { ReadByte() (c byte, err os.Error) } +// ByteScanner is the interface that adds the UnreadByte method to the +// basic ReadByte method. +// +// UnreadByte causes the next call to ReadByte to return the same byte +// as the previous call to ReadByte. +// It may be an error to call UnreadByte twice without an intervening +// call to ReadByte. +type ByteScanner interface { + ByteReader + UnreadByte() os.Error +} + // RuneReader is the interface that wraps the ReadRune method. // // ReadRune reads a single UTF-8 encoded Unicode character @@ -171,6 +183,18 @@ type RuneReader interface { ReadRune() (rune int, size int, err os.Error) } +// RuneScanner is the interface that adds the UnreadRune method to the +// basic ReadRune method. +// +// UnreadRune causes the next call to ReadRune to return the same rune +// as the previous call to ReadRune. +// It may be an error to call UnreadRune twice without an intervening +// call to ReadRune. +type RuneScanner interface { + RuneReader + UnreadRune() os.Error +} + // WriteString writes the contents of the string s to w, which accepts an array of bytes. func WriteString(w Writer, s string) (n int, err os.Error) { return w.Write([]byte(s)) @@ -303,22 +327,26 @@ func Copy(dst Writer, src Reader) (written int64, err os.Error) { // LimitReader returns a Reader that reads from r // but stops with os.EOF after n bytes. -func LimitReader(r Reader, n int64) Reader { return &limitedReader{r, n} } - -type limitedReader struct { - r Reader - n int64 +// The underlying implementation is a *LimitedReader. +func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} } + +// A LimitedReader reads from R but limits the amount of +// data returned to just N bytes. Each call to Read +// updates N to reflect the new amount remaining. +type LimitedReader struct { + R Reader // underlying reader + N int64 // max bytes remaining } -func (l *limitedReader) Read(p []byte) (n int, err os.Error) { - if l.n <= 0 { +func (l *LimitedReader) Read(p []byte) (n int, err os.Error) { + if l.N <= 0 { return 0, os.EOF } - if int64(len(p)) > l.n { - p = p[0:l.n] + if int64(len(p)) > l.N { + p = p[0:l.N] } - n, err = l.r.Read(p) - l.n -= int64(n) + n, err = l.R.Read(p) + l.N -= int64(n) return } diff --git a/src/pkg/mail/Makefile b/src/pkg/mail/Makefile new file mode 100644 index 000000000..e4de5428e --- /dev/null +++ b/src/pkg/mail/Makefile @@ -0,0 +1,11 @@ +# Copyright 2011 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=mail +GOFILES=\ + message.go\ + +include ../../Make.pkg diff --git a/src/pkg/mail/message.go b/src/pkg/mail/message.go new file mode 100644 index 000000000..9723863fe --- /dev/null +++ b/src/pkg/mail/message.go @@ -0,0 +1,95 @@ +// Copyright 2011 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 mail implements parsing of mail messages according to RFC 5322. +package mail + +import ( + "bufio" + "io" + "net/textproto" + "os" + "time" +) + +// A Message represents a parsed mail message. +type Message struct { + Header Header + Body io.Reader +} + +// ReadMessage reads a message from r. +// The headers are parsed, and the body of the message will be reading from r. +func ReadMessage(r io.Reader) (msg *Message, err os.Error) { + tp := textproto.NewReader(bufio.NewReader(r)) + + hdr, err := tp.ReadMIMEHeader() + if err != nil { + return nil, err + } + + return &Message{ + Header: Header(hdr), + Body: tp.R, + }, nil +} + +// Layouts suitable for passing to time.Parse. +// These are tried in order. +var dateLayouts []string + +func init() { + // Generate layouts based on RFC 5322, section 3.3. + + dows := [...]string{"", "Mon, "} // day-of-week + days := [...]string{"2", "02"} // day = 1*2DIGIT + years := [...]string{"2006", "06"} // year = 4*DIGIT / 2*DIGIT + seconds := [...]string{":05", ""} // second + zones := [...]string{"-0700", "MST"} // zone = (("+" / "-") 4DIGIT) / "GMT" / ... + + for _, dow := range dows { + for _, day := range days { + for _, year := range years { + for _, second := range seconds { + for _, zone := range zones { + s := dow + day + " Jan " + year + " 15:04" + second + " " + zone + dateLayouts = append(dateLayouts, s) + } + } + } + } + } +} + +func parseDate(date string) (*time.Time, os.Error) { + for _, layout := range dateLayouts { + t, err := time.Parse(layout, date) + if err == nil { + return t, nil + } + } + return nil, os.ErrorString("mail: header could not be parsed") +} + +// TODO(dsymonds): Parsers for more specific headers such as To, From, etc. + +// A Header represents the key-value pairs in a mail message header. +type Header map[string][]string + +// Get gets the first value associated with the given key. +// If there are no values associated with the key, Get returns "". +func (h Header) Get(key string) string { + return textproto.MIMEHeader(h).Get(key) +} + +var ErrHeaderNotPresent = os.ErrorString("mail: header not in message") + +// Date parses the Date header field. +func (h Header) Date() (*time.Time, os.Error) { + hdr := h.Get("Date") + if hdr == "" { + return nil, ErrHeaderNotPresent + } + return parseDate(hdr) +} diff --git a/src/pkg/mail/message_test.go b/src/pkg/mail/message_test.go new file mode 100644 index 000000000..1d1c6352e --- /dev/null +++ b/src/pkg/mail/message_test.go @@ -0,0 +1,129 @@ +// Copyright 2011 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 mail + +import ( + "bytes" + "io/ioutil" + "reflect" + "testing" + "time" +) + +var parseTests = []struct { + in string + header Header + body string +}{ + { + // RFC 5322, Appendix A.1.1 + in: `From: John Doe <jdoe@machine.example> +To: Mary Smith <mary@example.net> +Subject: Saying Hello +Date: Fri, 21 Nov 1997 09:55:06 -0600 +Message-ID: <1234@local.machine.example> + +This is a message just to say hello. +So, "Hello". +`, + header: Header{ + "From": []string{"John Doe <jdoe@machine.example>"}, + "To": []string{"Mary Smith <mary@example.net>"}, + "Subject": []string{"Saying Hello"}, + "Date": []string{"Fri, 21 Nov 1997 09:55:06 -0600"}, + "Message-Id": []string{"<1234@local.machine.example>"}, + }, + body: "This is a message just to say hello.\nSo, \"Hello\".\n", + }, +} + +func TestParsing(t *testing.T) { + for i, test := range parseTests { + msg, err := ReadMessage(bytes.NewBuffer([]byte(test.in))) + if err != nil { + t.Errorf("test #%d: Failed parsing message: %v", i, err) + continue + } + if !headerEq(msg.Header, test.header) { + t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v", + i, msg.Header, test.header) + } + body, err := ioutil.ReadAll(msg.Body) + if err != nil { + t.Errorf("test #%d: Failed reading body: %v", i, err) + continue + } + bodyStr := string(body) + if bodyStr != test.body { + t.Errorf("test #%d: Incorrectly parsed message body.\nGot:\n%+v\nWant:\n%+v", + i, bodyStr, test.body) + } + } +} + +func headerEq(a, b Header) bool { + if len(a) != len(b) { + return false + } + for k, as := range a { + bs, ok := b[k] + if !ok { + return false + } + if !reflect.DeepEqual(as, bs) { + return false + } + } + return true +} + +func TestDateParsing(t *testing.T) { + tests := []struct { + dateStr string + exp *time.Time + }{ + // RFC 5322, Appendix A.1.1 + { + "Fri, 21 Nov 1997 09:55:06 -0600", + &time.Time{ + Year: 1997, + Month: 11, + Day: 21, + Hour: 9, + Minute: 55, + Second: 6, + Weekday: 5, // Fri + ZoneOffset: -6 * 60 * 60, + }, + }, + // RFC5322, Appendix A.6.2 + // Obsolete date. + { + "21 Nov 97 09:55:06 GMT", + &time.Time{ + Year: 1997, + Month: 11, + Day: 21, + Hour: 9, + Minute: 55, + Second: 6, + Zone: "GMT", + }, + }, + } + for _, test := range tests { + hdr := Header{ + "Date": []string{test.dateStr}, + } + date, err := hdr.Date() + if err != nil { + t.Errorf("Failed parsing %q: %v", test.dateStr, err) + continue + } + if !reflect.DeepEqual(date, test.exp) { + t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp) + } + } +} diff --git a/src/pkg/math/log.go b/src/pkg/math/log.go index 39d94512d..a786c8ce3 100644 --- a/src/pkg/math/log.go +++ b/src/pkg/math/log.go @@ -23,7 +23,7 @@ package math // ==================================================== // // __ieee754_log(x) -// Return the logrithm of x +// Return the logarithm of x // // Method : // 1. Argument Reduction: find k and f such that diff --git a/src/pkg/math/sqrt_port.go b/src/pkg/math/sqrt_port.go index 6f35a383d..83af255bf 100644 --- a/src/pkg/math/sqrt_port.go +++ b/src/pkg/math/sqrt_port.go @@ -50,7 +50,7 @@ package math // If (2) is false, then q = q ; otherwise q = q + 2 . // i+1 i i+1 i // -// With some algebric manipulation, it is not difficult to see +// With some algebraic manipulation, it is not difficult to see // that (2) is equivalent to // -(i+1) // s + 2 <= y (3) diff --git a/src/pkg/mime/multipart/multipart_test.go b/src/pkg/mime/multipart/multipart_test.go index ec564b1d9..4ec3d30bd 100644 --- a/src/pkg/mime/multipart/multipart_test.go +++ b/src/pkg/mime/multipart/multipart_test.go @@ -203,7 +203,7 @@ func testMultipart(t *testing.T, r io.Reader) { t.Error("Didn't expect a fifth part.") } if err != os.EOF { - t.Errorf("On fifth part expected os.EOF; got %v", err) + t.Errorf("On fifth part expected os.EOF; got %v", err) } } diff --git a/src/pkg/mime/multipart/writer.go b/src/pkg/mime/multipart/writer.go index 74aa7be1c..b436dd012 100644 --- a/src/pkg/mime/multipart/writer.go +++ b/src/pkg/mime/multipart/writer.go @@ -6,24 +6,18 @@ package multipart import ( "bytes" + "crypto/rand" "fmt" "io" "net/textproto" "os" - "rand" "strings" ) -// Writer is used to generate multipart messages. +// A Writer generates multipart messages. type Writer struct { - // Boundary is the random boundary string between - // parts. NewWriter will generate this but it must - // not be changed after a part has been created. - // Setting this to an invalid value will generate - // malformed messages. - Boundary string - w io.Writer + boundary string lastpart *part } @@ -32,38 +26,42 @@ type Writer struct { func NewWriter(w io.Writer) *Writer { return &Writer{ w: w, - Boundary: randomBoundary(), + boundary: randomBoundary(), } } +// Boundary returns the Writer's randomly selected boundary string. +func (w *Writer) Boundary() string { + return w.boundary +} + // FormDataContentType returns the Content-Type for an HTTP // multipart/form-data with this Writer's Boundary. func (w *Writer) FormDataContentType() string { - return "multipart/form-data; boundary=" + w.Boundary + return "multipart/form-data; boundary=" + w.boundary } -const randChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - func randomBoundary() string { - var buf [60]byte - for i := range buf { - buf[i] = randChars[rand.Intn(len(randChars))] + var buf [30]byte + _, err := io.ReadFull(rand.Reader, buf[:]) + if err != nil { + panic(err) } - return string(buf[:]) + return fmt.Sprintf("%x", buf[:]) } // CreatePart creates a new multipart section with the provided -// header. The previous part, if still open, is closed. The body of -// the part should be written to the returned WriteCloser. Closing the -// returned WriteCloser after writing is optional. -func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.WriteCloser, os.Error) { +// header. The body of the part should be written to the returned +// Writer. After calling CreatePart, any previous part may no longer +// be written to. +func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, os.Error) { if w.lastpart != nil { - if err := w.lastpart.Close(); err != nil { + if err := w.lastpart.close(); err != nil { return nil, err } } var b bytes.Buffer - fmt.Fprintf(&b, "\r\n--%s\r\n", w.Boundary) + fmt.Fprintf(&b, "\r\n--%s\r\n", w.boundary) // TODO(bradfitz): move this to textproto.MimeHeader.Write(w), have it sort // and clean, like http.Header.Write(w) does. for k, vv := range header { @@ -91,7 +89,7 @@ func escapeQuotes(s string) string { // CreateFormFile is a convenience wrapper around CreatePart. It creates // a new form-data header with the provided field name and file name. -func (w *Writer) CreateFormFile(fieldname, filename string) (io.WriteCloser, os.Error) { +func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, os.Error) { h := make(textproto.MIMEHeader) h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, @@ -100,40 +98,35 @@ func (w *Writer) CreateFormFile(fieldname, filename string) (io.WriteCloser, os. return w.CreatePart(h) } -// CreateFormField is a convenience wrapper around CreatePart. It creates -// a new form-data header with the provided field name. -func (w *Writer) CreateFormField(fieldname string) (io.WriteCloser, os.Error) { +// CreateFormField calls CreatePart with a header using the +// given field name. +func (w *Writer) CreateFormField(fieldname string) (io.Writer, os.Error) { h := make(textproto.MIMEHeader) h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"`, escapeQuotes(fieldname))) return w.CreatePart(h) } -// WriteField is a convenience wrapper around CreateFormField. It creates and -// writes a part with the provided name and value. +// WriteField calls CreateFormField and then writes the given value. func (w *Writer) WriteField(fieldname, value string) os.Error { p, err := w.CreateFormField(fieldname) if err != nil { return err } _, err = p.Write([]byte(value)) - if err != nil { - return err - } - return p.Close() + return err } -// Close finishes the multipart message. It closes the previous part, -// if still open, and writes the trailing boundary end line to the -// output. +// Close finishes the multipart message and writes the trailing +// boundary end line to the output. func (w *Writer) Close() os.Error { if w.lastpart != nil { - if err := w.lastpart.Close(); err != nil { + if err := w.lastpart.close(); err != nil { return err } w.lastpart = nil } - _, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.Boundary) + _, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.boundary) return err } @@ -143,14 +136,14 @@ type part struct { we os.Error // last error that occurred writing } -func (p *part) Close() os.Error { +func (p *part) close() os.Error { p.closed = true return p.we } func (p *part) Write(d []byte) (n int, err os.Error) { if p.closed { - return 0, os.NewError("multipart: Write after Close") + return 0, os.NewError("multipart: can't write to finished part") } n, err = p.mw.w.Write(d) if err != nil { diff --git a/src/pkg/mime/multipart/writer_test.go b/src/pkg/mime/multipart/writer_test.go index b85fbf877..e6a04c388 100644 --- a/src/pkg/mime/multipart/writer_test.go +++ b/src/pkg/mime/multipart/writer_test.go @@ -23,7 +23,7 @@ func TestWriter(t *testing.T) { part.Write(fileContents) err = w.WriteField("key", "val") if err != nil { - t.Fatalf("CreateFormFieldValue: %v", err) + t.Fatalf("WriteField: %v", err) } part.Write([]byte("val")) err = w.Close() @@ -32,7 +32,7 @@ func TestWriter(t *testing.T) { } } - r := NewReader(&b, w.Boundary) + r := NewReader(&b, w.Boundary()) part, err := r.NextPart() if err != nil { diff --git a/src/pkg/net/Makefile b/src/pkg/net/Makefile index 376e9c6dc..d4adbffc0 100644 --- a/src/pkg/net/Makefile +++ b/src/pkg/net/Makefile @@ -23,12 +23,13 @@ GOFILES=\ unixsock.go\ GOFILES_freebsd=\ - newpollserver.go\ + dnsclient.go\ + dnsconfig.go\ fd.go\ file.go\ - dnsconfig.go\ - dnsclient.go\ + newpollserver.go\ port.go\ + sendfile_stub.go\ sock_bsd.go\ CGOFILES_freebsd=\ @@ -36,27 +37,32 @@ CGOFILES_freebsd=\ cgo_unix.go\ GOFILES_darwin=\ - newpollserver.go\ + dnsclient.go\ + dnsconfig.go\ fd.go\ file.go\ - dnsconfig.go\ - dnsclient.go\ + newpollserver.go\ port.go\ + sendfile_stub.go\ sock_bsd.go\ CGOFILES_darwin=\ cgo_bsd.go\ cgo_unix.go\ - + GOFILES_linux=\ - newpollserver.go\ + dnsclient.go\ + dnsconfig.go\ fd.go\ file.go\ - dnsconfig.go\ - dnsclient.go\ + newpollserver.go\ port.go\ + sendfile_linux.go\ sock_linux.go\ +GOFILES_plan9=\ + sendfile_stub.go\ + ifeq ($(GOARCH),arm) # ARM has no cgo, so use the stubs. GOFILES_linux+=cgo_stub.go @@ -68,8 +74,9 @@ endif GOFILES_windows=\ cgo_stub.go\ - resolv_windows.go\ file_windows.go\ + resolv_windows.go\ + sendfile_stub.go\ sock_windows.go\ GOFILES+=$(GOFILES_$(GOOS)) diff --git a/src/pkg/net/fd_linux.go b/src/pkg/net/fd_linux.go index dcf65c014..70fc344b2 100644 --- a/src/pkg/net/fd_linux.go +++ b/src/pkg/net/fd_linux.go @@ -117,6 +117,17 @@ func (p *pollster) DelFD(fd int, mode int) { } else { p.StopWaiting(fd, writeFlags) } + + // Discard any queued up events. + i := 0 + for i < len(p.waitEvents) { + if fd == int(p.waitEvents[i].Fd) { + copy(p.waitEvents[i:], p.waitEvents[i+1:]) + p.waitEvents = p.waitEvents[:len(p.waitEvents)-1] + } else { + i++ + } + } } func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.Error) { diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go index c2f736cc1..9ed7801d2 100644 --- a/src/pkg/net/fd_windows.go +++ b/src/pkg/net/fd_windows.go @@ -84,7 +84,7 @@ func (o *bufOp) Init(fd *netFD, buf []byte) { } } -// resultSrv will retreive all io completion results from +// resultSrv will retrieve all io completion results from // iocp and send them to the correspondent waiting client // goroutine via channel supplied in the request. type resultSrv struct { @@ -513,7 +513,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os. return nfd, nil } -// Not implemeted functions. +// Unimplemented functions. func (fd *netFD) dup() (f *os.File, err os.Error) { // TODO: Implement this diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go index a3000af8a..b0e2c4205 100644 --- a/src/pkg/net/ip.go +++ b/src/pkg/net/ip.go @@ -113,7 +113,7 @@ func (ip IP) IsInterfaceLocalMulticast() bool { return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01 } -// IsLinkLinkLocalMulticast returns true if ip is a link-local +// IsLinkLocalMulticast returns true if ip is a link-local // multicast address. func (ip IP) IsLinkLocalMulticast() bool { if ip4 := ip.To4(); ip4 != nil && ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 { @@ -122,7 +122,7 @@ func (ip IP) IsLinkLocalMulticast() bool { return ip[0] == 0xff && ip[1]&0x0f == 0x02 } -// IsLinkLinkLocalUnicast returns true if ip is a link-local +// IsLinkLocalUnicast returns true if ip is a link-local // unicast address. func (ip IP) IsLinkLocalUnicast() bool { if ip4 := ip.To4(); ip4 != nil && ip4[0] == 169 && ip4[1] == 254 { diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go index b83284d36..0b8c388f1 100644 --- a/src/pkg/net/ipsock.go +++ b/src/pkg/net/ipsock.go @@ -62,7 +62,7 @@ var supportsIPv6, supportsIPv4map = probeIPv6Stack() // favoriteAddrFamily returns the appropriate address family to // the given net, raddr, laddr and mode. At first it figures // address family out from the net. If mode indicates "listen" -// and laddr.(type).IP is nil, it assuumes that the user wants to +// and laddr.(type).IP is nil, it assumes that the user wants to // make a passive connection with wildcard address family, both // INET and INET6, and wildcard address. Otherwise guess: if the // addresses are IPv4 then returns INET, or else returns INET6. @@ -145,7 +145,7 @@ func ipv6only(x IP) IP { return nil } -// TODO(rsc): if syscall.OS == "linux", we're supposd to read +// TODO(rsc): if syscall.OS == "linux", we're supposed to read // /proc/sys/net/core/somaxconn, // to take advantage of kernels that have raised the limit. func listenBacklog() int { return syscall.SOMAXCONN } diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go new file mode 100644 index 000000000..6a5a06c8c --- /dev/null +++ b/src/pkg/net/sendfile_linux.go @@ -0,0 +1,84 @@ +// Copyright 2011 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 ( + "io" + "os" + "syscall" +) + +// maxSendfileSize is the largest chunk size we ask the kernel to copy +// at a time. +const maxSendfileSize int = 4 << 20 + +// sendFile copies the contents of r to c using the sendfile +// system call to minimize copies. +// +// if handled == true, sendFile returns the number of bytes copied and any +// non-EOF error. +// +// if handled == false, sendFile performed no work. +func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool) { + var remain int64 = 1 << 62 // by default, copy until EOF + + lr, ok := r.(*io.LimitedReader) + if ok { + remain, r = lr.N, lr.R + if remain <= 0 { + return 0, nil, true + } + } + f, ok := r.(*os.File) + if !ok { + return 0, nil, false + } + + c.wio.Lock() + defer c.wio.Unlock() + c.incref() + defer c.decref() + if c.wdeadline_delta > 0 { + // This is a little odd that we're setting the timeout + // for the entire file but Write has the same issue + // (if one slurps the whole file into memory and + // do one large Write). At least they're consistent. + c.wdeadline = pollserver.Now() + c.wdeadline_delta + } else { + c.wdeadline = 0 + } + + dst := c.sysfd + src := f.Fd() + for remain > 0 { + n := maxSendfileSize + if int64(n) > remain { + n = int(remain) + } + n, errno := syscall.Sendfile(dst, src, nil, n) + if n > 0 { + written += int64(n) + remain -= int64(n) + } + if n == 0 && errno == 0 { + break + } + if errno == syscall.EAGAIN && c.wdeadline >= 0 { + pollserver.WaitWrite(c) + continue + } + if errno != 0 { + // This includes syscall.ENOSYS (no kernel + // support) and syscall.EINVAL (fd types which + // don't implement sendfile together) + err = &OpError{"sendfile", c.net, c.raddr, os.Errno(errno)} + break + } + } + if lr != nil { + lr.N = remain + } + return written, err, written > 0 +} diff --git a/src/pkg/net/sendfile_stub.go b/src/pkg/net/sendfile_stub.go new file mode 100644 index 000000000..43e8104e9 --- /dev/null +++ b/src/pkg/net/sendfile_stub.go @@ -0,0 +1,14 @@ +// Copyright 2011 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 ( + "io" + "os" +) + +func sendFile(c *netFD, r io.Reader) (n int64, err os.Error, handled bool) { + return 0, nil, false +} diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go index 107de3e1c..36780d789 100644 --- a/src/pkg/net/server_test.go +++ b/src/pkg/net/server_test.go @@ -92,10 +92,13 @@ func connect(t *testing.T, network, addr string, isEmpty bool) { } func doTest(t *testing.T, network, listenaddr, dialaddr string) { - if listenaddr == "" { - t.Logf("Test %s %s %s\n", network, "<nil>", dialaddr) - } else { - t.Logf("Test %s %s %s\n", network, listenaddr, dialaddr) + t.Logf("Test %q %q %q\n", network, listenaddr, dialaddr) + switch listenaddr { + case "", "0.0.0.0", "[::]", "[::ffff:0.0.0.0]": + if testing.Short() || avoidMacFirewall { + t.Logf("skip wildcard listen during short test") + return + } } listening := make(chan string) done := make(chan int) diff --git a/src/pkg/net/sock.go b/src/pkg/net/sock.go index 5c47e4f77..eae7f3711 100644 --- a/src/pkg/net/sock.go +++ b/src/pkg/net/sock.go @@ -7,6 +7,7 @@ package net import ( + "io" "os" "reflect" "syscall" @@ -153,3 +154,14 @@ type UnknownSocketError struct { func (e *UnknownSocketError) String() string { return "unknown socket address type " + reflect.TypeOf(e.sa).String() } + +type writerOnly struct { + io.Writer +} + +// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't +// applicable. +func genericReadFrom(w io.Writer, r io.Reader) (n int64, err os.Error) { + // Use wrapper to hide existing r.ReadFrom from io.Copy. + return io.Copy(writerOnly{w}, r) +} diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go index 8aeed4895..9ee6c14f7 100644 --- a/src/pkg/net/tcpsock.go +++ b/src/pkg/net/tcpsock.go @@ -7,6 +7,7 @@ package net import ( + "io" "os" "syscall" ) @@ -95,6 +96,14 @@ func (c *TCPConn) Read(b []byte) (n int, err os.Error) { return c.fd.Read(b) } +// ReadFrom implements the io.ReaderFrom ReadFrom method. +func (c *TCPConn) ReadFrom(r io.Reader) (int64, os.Error) { + if n, err, handled := sendFile(c.fd, r); handled { + return n, err + } + return genericReadFrom(c, r) +} + // Write implements the net.Conn Write method. func (c *TCPConn) Write(b []byte) (n int, err os.Error) { if !c.ok() { diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go index ac1278689..e65374903 100644 --- a/src/pkg/net/textproto/reader.go +++ b/src/pkg/net/textproto/reader.go @@ -237,7 +237,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os. // to a method on r. // // Dot encoding is a common framing used for data blocks -// in text protcols like SMTP. The data consists of a sequence +// in text protocols such as SMTP. The data consists of a sequence // of lines, each of which ends in "\r\n". The sequence itself // ends at a line containing just a dot: ".\r\n". Lines beginning // with a dot are escaped with an additional dot to avoid diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go index 409355667..5469acffa 100644 --- a/src/pkg/net/udpsock.go +++ b/src/pkg/net/udpsock.go @@ -293,10 +293,10 @@ func (c *UDPConn) JoinGroup(addr IP) os.Error { if ip == nil { return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast} } - mreq := &syscall.IpMreq{ + mreq := &syscall.IPMreq{ Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}, } - err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)) + err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)) if err != nil { return &OpError{"joingroup", "udp", &IPAddr{ip}, err} } @@ -312,10 +312,10 @@ func (c *UDPConn) LeaveGroup(addr IP) os.Error { if ip == nil { return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast} } - mreq := &syscall.IpMreq{ + mreq := &syscall.IPMreq{ Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}, } - err := os.NewSyscallError("setsockopt", syscall.SetsockoptIpMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)) + err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)) if err != nil { return &OpError{"leavegroup", "udp", &IPAddr{ip}, err} } diff --git a/src/pkg/os/Makefile b/src/pkg/os/Makefile index cd9284079..c781df7af 100644 --- a/src/pkg/os/Makefile +++ b/src/pkg/os/Makefile @@ -23,6 +23,7 @@ GOFILES_freebsd=\ env_unix.go\ file_posix.go\ file_unix.go\ + path_unix.go\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ @@ -33,6 +34,7 @@ GOFILES_darwin=\ env_unix.go\ file_posix.go\ file_unix.go\ + path_unix.go\ sys_bsd.go\ exec_posix.go\ exec_unix.go\ @@ -43,6 +45,7 @@ GOFILES_linux=\ env_unix.go\ file_posix.go\ file_unix.go\ + path_unix.go\ sys_linux.go\ exec_posix.go\ exec_unix.go\ @@ -53,6 +56,7 @@ GOFILES_windows=\ env_windows.go\ file_posix.go\ file_windows.go\ + path_windows.go\ sys_windows.go\ exec_posix.go\ exec_windows.go\ @@ -62,6 +66,7 @@ GOFILES_plan9=\ error_plan9.go\ env_plan9.go\ file_plan9.go\ + path_plan9.go\ sys_plan9.go\ exec_plan9.go\ diff --git a/src/pkg/os/dir_plan9.go b/src/pkg/os/dir_plan9.go index d9514191d..bbc2cb647 100644 --- a/src/pkg/os/dir_plan9.go +++ b/src/pkg/os/dir_plan9.go @@ -9,35 +9,46 @@ import ( ) // Readdir reads the contents of the directory associated with file and -// returns an array of up to count FileInfo structures, in directory order. -// Subsequent calls on the same file will yield further FileInfos. -// A negative count means to read until EOF. -// Readdir returns the array and an Error, if any. -func (file *File) Readdir(count int) (fi []FileInfo, err Error) { +// returns an array of up to n FileInfo structures, as would be returned +// by Lstat, in directory order. Subsequent calls on the same file will yield +// further FileInfos. +// +// If n > 0, Readdir returns at most n FileInfo structures. In this case, if +// Readdirnames returns an empty slice, it will return a non-nil error +// explaining why. At the end of a directory, the error is os.EOF. +// +// If n <= 0, Readdir returns all the FileInfo from the directory in +// a single slice. In this case, if Readdir succeeds (reads all +// the way to the end of the directory), it returns the slice and a +// nil os.Error. If it encounters an error before the end of the +// directory, Readdir returns the FileInfo read until that point +// and a non-nil error. +func (file *File) Readdir(n int) (fi []FileInfo, err Error) { // If this file has no dirinfo, create one. if file.dirinfo == nil { file.dirinfo = new(dirInfo) } d := file.dirinfo - size := count - if size < 0 { + size := n + if size <= 0 { size = 100 + n = -1 } result := make([]FileInfo, 0, size) // Empty with room to grow. - for count != 0 { + for n != 0 { // Refill the buffer if necessary if d.bufp >= d.nbuf { d.bufp = 0 var e Error d.nbuf, e = file.Read(d.buf[:]) if e != nil && e != EOF { - return nil, &PathError{"readdir", file.name, e} + return result, &PathError{"readdir", file.name, e} } if e == EOF { break } if d.nbuf < syscall.STATFIXLEN { - return nil, &PathError{"readdir", file.name, Eshortstat} + return result, &PathError{"readdir", file.name, Eshortstat} } } @@ -45,39 +56,44 @@ func (file *File) Readdir(count int) (fi []FileInfo, err Error) { m, _ := gbit16(d.buf[d.bufp:]) m += 2 if m < syscall.STATFIXLEN { - return nil, &PathError{"readdir", file.name, Eshortstat} + return result, &PathError{"readdir", file.name, Eshortstat} } dir, e := UnmarshalDir(d.buf[d.bufp : d.bufp+int(m)]) if e != nil { - return nil, &PathError{"readdir", file.name, e} + return result, &PathError{"readdir", file.name, e} } var f FileInfo fileInfoFromStat(&f, dir) result = append(result, f) d.bufp += int(m) - count-- + n-- } - return result, nil -} -// Readdirnames returns an array of up to count file names residing in the -// directory associated with file. A negative count will return all of them. -// Readdir returns the array and an Error, if any. -func (file *File) Readdirnames(count int) (names []string, err Error) { - fi, e := file.Readdir(count) - - if e != nil { - return []string{}, e + if n >= 0 && len(result) == 0 { + return result, EOF } + return result, nil +} +// Readdirnames reads and returns a slice of names from the directory f. +// +// If n > 0, Readdirnames returns at most n names. In this case, if +// Readdirnames returns an empty slice, it will return a non-nil error +// explaining why. At the end of a directory, the error is os.EOF. +// +// If n <= 0, Readdirnames returns all the names from the directory in +// a single slice. In this case, if Readdirnames succeeds (reads all +// the way to the end of the directory), it returns the slice and a +// nil os.Error. If it encounters an error before the end of the +// directory, Readdirnames returns the names read until that point and +// a non-nil error. +func (file *File) Readdirnames(n int) (names []string, err Error) { + fi, err := file.Readdir(n) names = make([]string, len(fi)) - err = nil - for i := range fi { names[i] = fi[i].Name } - return } @@ -142,7 +158,7 @@ func pdir(b []byte, d *Dir) []byte { return b } -// UnmarshalDir reads a 9P Stat message from a 9P protocol message strored in b, +// UnmarshalDir reads a 9P Stat message from a 9P protocol message stored in b, // returning the corresponding Dir struct. func UnmarshalDir(b []byte) (d *Dir, err Error) { n := uint16(0) @@ -172,7 +188,7 @@ func UnmarshalDir(b []byte) (d *Dir, err Error) { return d, nil } -// gqid reads the qid part of a 9P Stat message from a 9P protocol message strored in b, +// gqid reads the qid part of a 9P Stat message from a 9P protocol message stored in b, // returning the corresponding Qid struct and the remaining slice of b. func gqid(b []byte) (Qid, []byte) { var q Qid @@ -190,25 +206,25 @@ func pqid(b []byte, q Qid) []byte { return b } -// gbit8 reads a byte-sized numeric value from a 9P protocol message strored in b, +// gbit8 reads a byte-sized numeric value from a 9P protocol message stored in b, // returning the value and the remaining slice of b. func gbit8(b []byte) (uint8, []byte) { return uint8(b[0]), b[1:] } -// gbit16 reads a 16-bit numeric value from a 9P protocol message strored in b, +// gbit16 reads a 16-bit numeric value from a 9P protocol message stored in b, // returning the value and the remaining slice of b. func gbit16(b []byte) (uint16, []byte) { return uint16(b[0]) | uint16(b[1])<<8, b[2:] } -// gbit32 reads a 32-bit numeric value from a 9P protocol message strored in b, +// gbit32 reads a 32-bit numeric value from a 9P protocol message stored in b, // returning the value and the remaining slice of b. func gbit32(b []byte) (uint32, []byte) { return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:] } -// gbit64 reads a 64-bit numeric value from a 9P protocol message strored in b, +// gbit64 reads a 64-bit numeric value from a 9P protocol message stored in b, // returning the value and the remaining slice of b. func gbit64(b []byte) (uint64, []byte) { lo, b := gbit32(b) @@ -216,7 +232,7 @@ func gbit64(b []byte) (uint64, []byte) { return uint64(hi)<<32 | uint64(lo), b } -// gstring reads a string from a 9P protocol message strored in b, +// gstring reads a string from a 9P protocol message stored in b, // returning the value as a Go string and the remaining slice of b. func gstring(b []byte) (string, []byte) { n, b := gbit16(b) diff --git a/src/pkg/os/dir_unix.go b/src/pkg/os/dir_unix.go index 9c543838e..7835ed52b 100644 --- a/src/pkg/os/dir_unix.go +++ b/src/pkg/os/dir_unix.go @@ -32,11 +32,11 @@ func (f *File) Readdirnames(n int) (names []string, err Error) { f.dirinfo.buf = make([]byte, blockSize) } d := f.dirinfo - wantAll := n < 0 size := n - if size < 0 { + if size <= 0 { size = 100 + n = -1 } names = make([]string, 0, size) // Empty with room to grow. @@ -60,7 +60,7 @@ func (f *File) Readdirnames(n int) (names []string, err Error) { d.bufp += nb n -= nc } - if !wantAll && len(names) == 0 { + if n >= 0 && len(names) == 0 { return names, EOF } return names, nil diff --git a/src/pkg/os/dir_windows.go b/src/pkg/os/dir_windows.go index a4df9d3ea..d76e88fdb 100644 --- a/src/pkg/os/dir_windows.go +++ b/src/pkg/os/dir_windows.go @@ -6,11 +6,6 @@ package os func (file *File) Readdirnames(n int) (names []string, err Error) { fis, err := file.Readdir(n) - // If n > 0 and we get an error, we return now. - // If n < 0, we return whatever we got + any error. - if n > 0 && err != nil { - return nil, err - } names = make([]string, len(fis)) for i, fi := range fis { names[i] = fi.Name diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go index c65c5b3ff..def9b3bf0 100644 --- a/src/pkg/os/file_unix.go +++ b/src/pkg/os/file_unix.go @@ -69,12 +69,12 @@ func (file *File) Stat() (fi *FileInfo, err Error) { } // Readdir reads the contents of the directory associated with file and -// returns an array of up to count FileInfo structures, as would be returned +// returns an array of up to n FileInfo structures, as would be returned // by Lstat, in directory order. Subsequent calls on the same file will yield // further FileInfos. // -// If n > 0, Readdir returns at most n names. In this case, if -// Readdirnames returns an empty slice, it will return a non-nil error +// If n > 0, Readdir returns at most n FileInfo structures. In this case, if +// Readdir returns an empty slice, it will return a non-nil error // explaining why. At the end of a directory, the error is os.EOF. // // If n <= 0, Readdir returns all the FileInfo from the directory in @@ -89,11 +89,7 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) { dirname = "." } dirname += "/" - wantAll := n < 0 - names, namesErr := file.Readdirnames(n) - if namesErr != nil && !wantAll { - return nil, namesErr - } + names, err := file.Readdirnames(n) fi = make([]FileInfo, len(names)) for i, filename := range names { fip, err := Lstat(dirname + filename) @@ -103,9 +99,6 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) { fi[i] = *fip } } - if !wantAll && namesErr != EOF { - err = namesErr - } return } diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go index 74ff3eb88..80886f6f5 100644 --- a/src/pkg/os/file_windows.go +++ b/src/pkg/os/file_windows.go @@ -123,12 +123,12 @@ func (file *File) Stat() (fi *FileInfo, err Error) { } // Readdir reads the contents of the directory associated with file and -// returns an array of up to count FileInfo structures, as would be returned +// returns an array of up to n FileInfo structures, as would be returned // by Lstat, in directory order. Subsequent calls on the same file will yield // further FileInfos. // -// If n > 0, Readdir returns at most n names. In this case, if -// Readdirnames returns an empty slice, it will return a non-nil error +// If n > 0, Readdir returns at most n FileInfo structures. In this case, if +// Readdir returns an empty slice, it will return a non-nil error // explaining why. At the end of a directory, the error is os.EOF. // // If n <= 0, Readdir returns all the FileInfo from the directory in @@ -145,9 +145,10 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) { return nil, &PathError{"Readdir", file.name, ENOTDIR} } di := file.dirinfo - wantAll := n < 0 + wantAll := n <= 0 size := n - if size < 0 { + if wantAll { + n = -1 size = 100 } fi = make([]FileInfo, 0, size) // Empty with room to grow. diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go index b06d57b85..8eabdee6b 100644 --- a/src/pkg/os/os_test.go +++ b/src/pkg/os/os_test.go @@ -286,6 +286,78 @@ func TestReaddirnamesOneAtATime(t *testing.T) { } } +func TestReaddirNValues(t *testing.T) { + if testing.Short() { + t.Logf("test.short; skipping") + return + } + dir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatalf("TempDir: %v", err) + } + defer RemoveAll(dir) + for i := 1; i <= 105; i++ { + f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i))) + if err != nil { + t.Fatalf("Create: %v", err) + } + f.Write([]byte(strings.Repeat("X", i))) + f.Close() + } + + var d *File + openDir := func() { + var err Error + d, err = Open(dir) + if err != nil { + t.Fatalf("Open directory: %v", err) + } + } + + readDirExpect := func(n, want int, wantErr Error) { + fi, err := d.Readdir(n) + if err != wantErr { + t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr) + } + if g, e := len(fi), want; g != e { + t.Errorf("Readdir of %d got %d files, want %d", n, g, e) + } + } + + readDirNamesExpect := func(n, want int, wantErr Error) { + fi, err := d.Readdirnames(n) + if err != wantErr { + t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr) + } + if g, e := len(fi), want; g != e { + t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e) + } + } + + for _, fn := range []func(int, int, Error){readDirExpect, readDirNamesExpect} { + // Test the slurp case + openDir() + fn(0, 105, nil) + fn(0, 0, nil) + d.Close() + + // Slurp with -1 instead + openDir() + fn(-1, 105, nil) + fn(-2, 0, nil) + fn(0, 0, nil) + d.Close() + + // Test the bounded case + openDir() + fn(1, 1, nil) + fn(2, 2, nil) + fn(105, 102, nil) // and tests buffer >100 case + fn(3, 0, EOF) + d.Close() + } +} + func TestHardLink(t *testing.T) { // Hardlinks are not supported under windows. if syscall.OS == "windows" { @@ -442,7 +514,8 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) { var b bytes.Buffer io.Copy(&b, r) output := b.String() - if output != expect { + // Accept /usr prefix because Solaris /bin is symlinked to /usr/bin. + if output != expect && output != "/usr"+expect { t.Errorf("exec %q returned %q wanted %q", strings.Join(append([]string{cmd}, args...), " "), output, expect) } @@ -917,7 +990,15 @@ func TestAppend(t *testing.T) { } s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append") if s != "new&append" { - t.Fatalf("writeFile: have %q want %q", s, "new&append") + t.Fatalf("writeFile: after append have %q want %q", s, "new&append") + } + s = writeFile(t, f, O_CREATE|O_RDWR, "old") + if s != "old&append" { + t.Fatalf("writeFile: after create have %q want %q", s, "old&append") + } + s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new") + if s != "new" { + t.Fatalf("writeFile: after truncate have %q want %q", s, "new") } } diff --git a/src/pkg/os/path.go b/src/pkg/os/path.go index 5565aaa29..7b93036aa 100644 --- a/src/pkg/os/path.go +++ b/src/pkg/os/path.go @@ -24,12 +24,12 @@ func MkdirAll(path string, perm uint32) Error { // Doesn't already exist; make sure parent does. i := len(path) - for i > 0 && path[i-1] == '/' { // Skip trailing slashes. + for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator. i-- } j := i - for j > 0 && path[j-1] != '/' { // Scan backward over element. + for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element. j-- } @@ -90,7 +90,7 @@ func RemoveAll(path string) Error { for { names, err1 := fd.Readdirnames(100) for _, name := range names { - err1 := RemoveAll(path + "/" + name) + err1 := RemoveAll(path + string(PathSeparator) + name) if err == nil { err = err1 } diff --git a/src/pkg/os/path_plan9.go b/src/pkg/os/path_plan9.go new file mode 100644 index 000000000..3121b7bc7 --- /dev/null +++ b/src/pkg/os/path_plan9.go @@ -0,0 +1,15 @@ +// Copyright 2011 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 + +const ( + PathSeparator = '/' // OS-specific path separator + PathListSeparator = 0 // OS-specific path list separator +) + +// IsPathSeparator returns true if c is a directory separator character. +func IsPathSeparator(c uint8) bool { + return PathSeparator == c +} diff --git a/src/pkg/os/path_test.go b/src/pkg/os/path_test.go index 483bb6395..d58945aab 100644 --- a/src/pkg/os/path_test.go +++ b/src/pkg/os/path_test.go @@ -6,6 +6,7 @@ package os_test import ( . "os" + "path/filepath" "testing" "runtime" "syscall" @@ -29,10 +30,11 @@ func TestMkdirAll(t *testing.T) { // Make file. fpath := path + "/file" - _, err = Create(fpath) + f, err := Create(fpath) if err != nil { t.Fatalf("create %q: %s", fpath, err) } + defer f.Close() // Can't make directory named after file. err = MkdirAll(fpath, 0777) @@ -43,8 +45,8 @@ func TestMkdirAll(t *testing.T) { if !ok { t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err) } - if perr.Path != fpath { - t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath) + if filepath.Clean(perr.Path) != filepath.Clean(fpath) { + t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath)) } // Can't make subdirectory of file. @@ -57,8 +59,16 @@ func TestMkdirAll(t *testing.T) { if !ok { t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err) } - if perr.Path != fpath { - t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath) + if filepath.Clean(perr.Path) != filepath.Clean(fpath) { + t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath)) + } + + if syscall.OS == "windows" { + path := `_test\_TestMkdirAll_\dir\.\dir2\` + err := MkdirAll(path, 0777) + if err != nil { + t.Fatalf("MkdirAll %q: %s", path, err) + } } } diff --git a/src/pkg/os/path_unix.go b/src/pkg/os/path_unix.go new file mode 100644 index 000000000..0d327cddd --- /dev/null +++ b/src/pkg/os/path_unix.go @@ -0,0 +1,15 @@ +// Copyright 2011 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 + +const ( + PathSeparator = '/' // OS-specific path separator + PathListSeparator = ':' // OS-specific path list separator +) + +// IsPathSeparator returns true if c is a directory separator character. +func IsPathSeparator(c uint8) bool { + return PathSeparator == c +} diff --git a/src/pkg/os/path_windows.go b/src/pkg/os/path_windows.go new file mode 100644 index 000000000..8740a9e61 --- /dev/null +++ b/src/pkg/os/path_windows.go @@ -0,0 +1,16 @@ +// Copyright 2011 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 + +const ( + PathSeparator = '\\' // OS-specific path separator + PathListSeparator = ':' // OS-specific path list separator +) + +// IsPathSeparator returns true if c is a directory separator character. +func IsPathSeparator(c uint8) bool { + // NOTE: Windows accept / as path separator. + return c == '\\' || c == '/' +} diff --git a/src/pkg/path/filepath/match.go b/src/pkg/path/filepath/match.go index a05bb5f7e..9c344309d 100644 --- a/src/pkg/path/filepath/match.go +++ b/src/pkg/path/filepath/match.go @@ -124,9 +124,8 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) { s = s[n:] chunk = chunk[1:] // possibly negated - notNegated := true - if len(chunk) > 0 && chunk[0] == '^' { - notNegated = false + negated := chunk[0] == '^' + if negated { chunk = chunk[1:] } // parse all ranges @@ -152,7 +151,7 @@ func matchChunk(chunk, s string) (rest string, ok bool, err os.Error) { } nrange++ } - if match != notNegated { + if match == negated { return } diff --git a/src/pkg/path/filepath/match_test.go b/src/pkg/path/filepath/match_test.go index 43e1c1cc2..a1c8333f3 100644 --- a/src/pkg/path/filepath/match_test.go +++ b/src/pkg/path/filepath/match_test.go @@ -69,6 +69,13 @@ var matchTests = []MatchTest{ {"*x", "xxx", true, nil}, } +func errp(e os.Error) string { + if e == nil { + return "<nil>" + } + return e.String() +} + func TestMatch(t *testing.T) { if runtime.GOOS == "windows" { // XXX: Don't pass for windows. @@ -77,7 +84,7 @@ func TestMatch(t *testing.T) { for _, tt := range matchTests { ok, err := Match(tt.pattern, tt.s) if ok != tt.match || err != tt.err { - t.Errorf("Match(%#q, %#q) = %v, %v want %v, nil", tt.pattern, tt.s, ok, err, tt.match) + t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", tt.pattern, tt.s, ok, errp(err), tt.match, errp(tt.err)) } } } diff --git a/src/pkg/path/filepath/path.go b/src/pkg/path/filepath/path.go index 6917218db..dcd8017ad 100644 --- a/src/pkg/path/filepath/path.go +++ b/src/pkg/path/filepath/path.go @@ -15,8 +15,8 @@ import ( ) const ( - SeparatorString = string(Separator) - ListSeparatorString = string(ListSeparator) + Separator = os.PathSeparator + ListSeparator = os.PathListSeparator ) // Clean returns the shortest path name equivalent to path @@ -61,20 +61,20 @@ func Clean(path string) string { for r < n { switch { - case isSeparator(path[r]): + case os.IsPathSeparator(path[r]): // empty path element r++ - case path[r] == '.' && (r+1 == n || isSeparator(path[r+1])): + case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])): // . element r++ - case path[r] == '.' && path[r+1] == '.' && (r+2 == n || isSeparator(path[r+2])): + case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])): // .. element: remove to last separator r += 2 switch { case w > dotdot: // can backtrack w-- - for w > dotdot && !isSeparator(buf[w]) { + for w > dotdot && !os.IsPathSeparator(buf[w]) { w-- } case !rooted: @@ -97,7 +97,7 @@ func Clean(path string) string { w++ } // copy element - for ; r < n && !isSeparator(path[r]); r++ { + for ; r < n && !os.IsPathSeparator(path[r]); r++ { buf[w] = path[r] w++ } @@ -119,7 +119,7 @@ func ToSlash(path string) string { if Separator == '/' { return path } - return strings.Replace(path, SeparatorString, "/", -1) + return strings.Replace(path, string(Separator), "/", -1) } // FromSlash returns the result of replacing each slash ('/') character @@ -128,7 +128,7 @@ func FromSlash(path string) string { if Separator == '/' { return path } - return strings.Replace(path, "/", SeparatorString, -1) + return strings.Replace(path, "/", string(Separator), -1) } // SplitList splits a list of paths joined by the OS-specific ListSeparator. @@ -136,7 +136,7 @@ func SplitList(path string) []string { if path == "" { return []string{} } - return strings.Split(path, ListSeparatorString, -1) + return strings.Split(path, string(ListSeparator), -1) } // Split splits path immediately following the final Separator, @@ -145,7 +145,7 @@ func SplitList(path string) []string { // and file set to path. func Split(path string) (dir, file string) { i := len(path) - 1 - for i >= 0 && !isSeparator(path[i]) { + for i >= 0 && !os.IsPathSeparator(path[i]) { i-- } return path[:i+1], path[i+1:] @@ -156,7 +156,7 @@ func Split(path string) (dir, file string) { func Join(elem ...string) string { for i, e := range elem { if e != "" { - return Clean(strings.Join(elem[i:], SeparatorString)) + return Clean(strings.Join(elem[i:], string(Separator))) } } return "" @@ -167,7 +167,7 @@ func Join(elem ...string) string { // in the final element of path; it is empty if there is // no dot. func Ext(path string) string { - for i := len(path) - 1; i >= 0 && !isSeparator(path[i]); i-- { + for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- { if path[i] == '.' { return path[i:] } @@ -234,7 +234,7 @@ func EvalSymlinks(path string) (string, os.Error) { if IsAbs(dest) { b.Reset() } - path = dest + SeparatorString + path + path = dest + string(Separator) + path } return Clean(b.String()), nil } @@ -245,7 +245,7 @@ func EvalSymlinks(path string) (string, os.Error) { // path name for a given file is not guaranteed to be unique. func Abs(path string) (string, os.Error) { if IsAbs(path) { - return path, nil + return Clean(path), nil } wd, err := os.Getwd() if err != nil { @@ -339,12 +339,12 @@ func Base(path string) string { return "." } // Strip trailing slashes. - for len(path) > 0 && isSeparator(path[len(path)-1]) { + for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) { path = path[0 : len(path)-1] } // Find the last element i := len(path) - 1 - for i >= 0 && !isSeparator(path[i]) { + for i >= 0 && !os.IsPathSeparator(path[i]) { i-- } if i >= 0 { @@ -352,7 +352,7 @@ func Base(path string) string { } // If empty now, it had only slashes. if path == "" { - return SeparatorString + return string(Separator) } return path } diff --git a/src/pkg/path/filepath/path_plan9.go b/src/pkg/path/filepath/path_plan9.go index e40008364..47990e0fe 100644 --- a/src/pkg/path/filepath/path_plan9.go +++ b/src/pkg/path/filepath/path_plan9.go @@ -6,16 +6,6 @@ package filepath import "strings" -const ( - Separator = '/' // OS-specific path separator - ListSeparator = 0 // OS-specific path list separator -) - -// isSeparator returns true if c is a directory separator character. -func isSeparator(c uint8) bool { - return Separator == c -} - // IsAbs returns true if the path is absolute. func IsAbs(path string) bool { return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#") diff --git a/src/pkg/path/filepath/path_test.go b/src/pkg/path/filepath/path_test.go index b14734983..6a5dd5b00 100644 --- a/src/pkg/path/filepath/path_test.go +++ b/src/pkg/path/filepath/path_test.go @@ -315,7 +315,10 @@ func TestWalk(t *testing.T) { } checkMarks(t) - if os.Getuid() > 0 { + // Test permission errors. Only possible if we're not root + // and only on some file systems (AFS, FAT). To avoid errors during + // all.bash on those file systems, skip during gotest -short. + if os.Getuid() > 0 && !testing.Short() { // introduce 2 errors: chmod top-level directories to 0 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) @@ -509,6 +512,7 @@ var abstests = []string{ // Already absolute "$GOROOT/src/Make.pkg", + "$GOROOT/src/../src/Make.pkg", } func TestAbs(t *testing.T) { @@ -537,5 +541,8 @@ func TestAbs(t *testing.T) { if !filepath.IsAbs(abspath) { t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath) } + if filepath.IsAbs(path) && abspath != filepath.Clean(path) { + t.Errorf("Abs(%q)=%q, isn't clean", path, abspath) + } } } diff --git a/src/pkg/path/filepath/path_unix.go b/src/pkg/path/filepath/path_unix.go index f8ac248fb..ea555fc0e 100644 --- a/src/pkg/path/filepath/path_unix.go +++ b/src/pkg/path/filepath/path_unix.go @@ -6,16 +6,6 @@ package filepath import "strings" -const ( - Separator = '/' // OS-specific path separator - ListSeparator = ':' // OS-specific path list separator -) - -// isSeparator returns true if c is a directory separator character. -func isSeparator(c uint8) bool { - return Separator == c -} - // IsAbs returns true if the path is absolute. func IsAbs(path string) bool { return strings.HasPrefix(path, "/") diff --git a/src/pkg/path/filepath/path_windows.go b/src/pkg/path/filepath/path_windows.go index dbd1c1e40..35302eb1a 100644 --- a/src/pkg/path/filepath/path_windows.go +++ b/src/pkg/path/filepath/path_windows.go @@ -4,20 +4,11 @@ package filepath -const ( - Separator = '\\' // OS-specific path separator - ListSeparator = ':' // OS-specific path list separator -) - -// isSeparator returns true if c is a directory separator character. -func isSeparator(c uint8) bool { - // NOTE: Windows accept / as path separator. - return c == '\\' || c == '/' -} +import "os" // IsAbs returns true if the path is absolute. func IsAbs(path string) bool { - return path != "" && (volumeName(path) != "" || isSeparator(path[0])) + return path != "" && (volumeName(path) != "" || os.IsPathSeparator(path[0])) } // volumeName return leading volume name. @@ -28,7 +19,7 @@ func volumeName(path string) string { } // with drive letter c := path[0] - if len(path) > 2 && path[1] == ':' && isSeparator(path[2]) && + if len(path) > 2 && path[1] == ':' && os.IsPathSeparator(path[2]) && ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { return path[0:2] diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go index 2c2158a3c..3abe13e04 100644 --- a/src/pkg/reflect/value.go +++ b/src/pkg/reflect/value.go @@ -173,7 +173,7 @@ type nonEmptyInterface struct { // Regarding the implementation of Value: // // The Internal interface is a true interface value in the Go sense, -// but it also serves as a (type, address) pair in whcih one cannot +// but it also serves as a (type, address) pair in which one cannot // be changed separately from the other. That is, it serves as a way // to prevent unsafe mutations of the Internal state even though // we cannot (yet?) hide the field while preserving the ability for diff --git a/src/pkg/regexp/all_test.go b/src/pkg/regexp/all_test.go index c7ee4c879..71edc4d18 100644 --- a/src/pkg/regexp/all_test.go +++ b/src/pkg/regexp/all_test.go @@ -356,7 +356,7 @@ func BenchmarkMatchClass(b *testing.B) { func BenchmarkMatchClass_InRange(b *testing.B) { b.StopTimer() - // 'b' is betwen 'a' and 'c', so the charclass + // 'b' is between 'a' and 'c', so the charclass // range checking is no help here. x := strings.Repeat("bbbb", 20) + "c" re := MustCompile("[ac]") diff --git a/src/pkg/runtime/arm/vlop.s b/src/pkg/runtime/arm/vlop.s index 2c5d7ebe1..fc679f0ee 100644 --- a/src/pkg/runtime/arm/vlop.s +++ b/src/pkg/runtime/arm/vlop.s @@ -105,7 +105,7 @@ loop: /* * compare numerator to denominator - * if less, subtract and set quotent bit + * if less, subtract and set quotient bit */ CMP R(D), R(N) ORR.HS $1, R(Q) diff --git a/src/pkg/runtime/closure_test.go b/src/pkg/runtime/closure_test.go new file mode 100644 index 000000000..ea65fbd5f --- /dev/null +++ b/src/pkg/runtime/closure_test.go @@ -0,0 +1,53 @@ +// Copyright 2011 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 runtime_test + +import "testing" + +var s int + +func BenchmarkCallClosure(b *testing.B) { + for i := 0; i < b.N; i++ { + s += func(ii int) int { return 2 * ii }(i) + } +} + +func BenchmarkCallClosure1(b *testing.B) { + for i := 0; i < b.N; i++ { + j := i + s += func(ii int) int { return 2*ii + j }(i) + } +} + +var ss *int + +func BenchmarkCallClosure2(b *testing.B) { + for i := 0; i < b.N; i++ { + j := i + s += func() int { + ss = &j + return 2 + }() + } +} + +func addr1(x int) *int { + return func() *int { return &x }() +} + +func BenchmarkCallClosure3(b *testing.B) { + for i := 0; i < b.N; i++ { + ss = addr1(i) + } +} + +func addr2() (x int, p *int) { + return 0, func() *int { return &x }() +} + +func BenchmarkCallClosure4(b *testing.B) { + for i := 0; i < b.N; i++ { + _, ss = addr2() + } +} diff --git a/src/pkg/runtime/linux/mem.c b/src/pkg/runtime/linux/mem.c index ce1a8aa70..02f798732 100644 --- a/src/pkg/runtime/linux/mem.c +++ b/src/pkg/runtime/linux/mem.c @@ -39,13 +39,19 @@ runtime·SysFree(void *v, uintptr n) void* runtime·SysReserve(void *v, uintptr n) { + void *p; + // On 64-bit, people with ulimit -v set complain if we reserve too // much address space. Instead, assume that the reservation is okay // and check the assumption in SysMap. if(sizeof(void*) == 8) return v; - return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); + p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); + if(p < (void*)4096) { + return nil; + } + return p; } enum @@ -63,6 +69,8 @@ runtime·SysMap(void *v, uintptr n) // On 64-bit, we don't actually have v reserved, so tread carefully. if(sizeof(void*) == 8) { p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0); + if(p == (void*)ENOMEM) + runtime·throw("runtime: out of memory"); if(p != v) { runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p); runtime·throw("runtime: address space conflict"); @@ -71,7 +79,7 @@ runtime·SysMap(void *v, uintptr n) } p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0); - if(p == (void*)-ENOMEM) + if(p == (void*)ENOMEM) runtime·throw("runtime: out of memory"); if(p != v) runtime·throw("runtime: cannot map pages in arena address space"); diff --git a/src/pkg/runtime/linux/thread.c b/src/pkg/runtime/linux/thread.c index 6c506236f..7c7ca7b4e 100644 --- a/src/pkg/runtime/linux/thread.c +++ b/src/pkg/runtime/linux/thread.c @@ -116,7 +116,7 @@ again: // // We only really care that (v&1) == 1 (the lock is held), // and in fact there is a futex variant that could - // accomodate that check, but let's not get carried away.) + // accommodate that check, but let's not get carried away.) futexsleep(&l->key, v+2); // We're awake: remove ourselves from the count. diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc index aae3d183f..517f96a31 100644 --- a/src/pkg/runtime/mprof.goc +++ b/src/pkg/runtime/mprof.goc @@ -113,7 +113,7 @@ static uintptr addrmem; // hashMultiplier is the bottom 32 bits of int((sqrt(5)-1)/2 * (1<<32)). // This is a good multiplier as suggested in CLR, Knuth. The hash // value is taken to be the top AddrHashBits bits of the bottom 32 bits -// of the muliplied value. +// of the multiplied value. enum { HashMultiplier = 2654435769U }; diff --git a/src/pkg/runtime/proc_test.go b/src/pkg/runtime/proc_test.go index a15b2d80a..cac4f9eea 100644 --- a/src/pkg/runtime/proc_test.go +++ b/src/pkg/runtime/proc_test.go @@ -24,20 +24,23 @@ func TestStopTheWorldDeadlock(t *testing.T) { t.Logf("skipping during short test") return } - runtime.GOMAXPROCS(3) - compl := make(chan int, 1) + maxprocs := runtime.GOMAXPROCS(3) + compl := make(chan bool, 2) go func() { for i := 0; i != 1000; i += 1 { runtime.GC() } - compl <- 0 + compl <- true }() go func() { for i := 0; i != 1000; i += 1 { runtime.GOMAXPROCS(3) } + compl <- true }() go perpetuumMobile() <-compl + <-compl stop <- true + runtime.GOMAXPROCS(maxprocs) } diff --git a/src/pkg/runtime/runtime-gdb.py b/src/pkg/runtime/runtime-gdb.py index 3f767fbdd..a96f3f382 100644 --- a/src/pkg/runtime/runtime-gdb.py +++ b/src/pkg/runtime/runtime-gdb.py @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -"""GDB Pretty printers and convencience functions for Go's runtime structures. +"""GDB Pretty printers and convenience functions for Go's runtime structures. This script is loaded by GDB when it finds a .debug_gdb_scripts section in the compiled binary. The [68]l linkers emit this with a @@ -393,7 +393,7 @@ class GoIfaceCmd(gdb.Command): # so Itype will start with a commontype which has kind = interface # -# Register all convience functions and CLI commands +# Register all convenience functions and CLI commands # for k in vars().values(): if hasattr(k, 'invoke'): diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index f2f8dcd5b..2b2b34a3c 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -306,7 +306,7 @@ enum { /* * defined macros - * you need super-goru privilege + * you need super-gopher-guru privilege * to add this list. */ #define nelem(x) (sizeof(x)/sizeof((x)[0])) diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s index 15f7f95b8..d38405075 100644 --- a/src/pkg/runtime/windows/386/sys.s +++ b/src/pkg/runtime/windows/386/sys.s @@ -59,15 +59,21 @@ TEXT runtime·setlasterror(SB),7,$0 TEXT runtime·sigtramp(SB),7,$0 PUSHL BP // cdecl + PUSHL BX + PUSHL SI + PUSHL DI PUSHL 0(FS) CALL runtime·sigtramp1(SB) POPL 0(FS) + POPL DI + POPL SI + POPL BX POPL BP RET -TEXT runtime·sigtramp1(SB),0,$16-28 +TEXT runtime·sigtramp1(SB),0,$16-40 // unwinding? - MOVL info+12(FP), BX + MOVL info+24(FP), BX MOVL 4(BX), CX // exception flags ANDL $6, CX MOVL $1, AX @@ -75,15 +81,15 @@ TEXT runtime·sigtramp1(SB),0,$16-28 // place ourselves at the top of the SEH chain to // ensure SEH frames lie within thread stack bounds - MOVL frame+16(FP), CX // our SEH frame + MOVL frame+28(FP), CX // our SEH frame MOVL CX, 0(FS) // copy arguments for call to sighandler MOVL BX, 0(SP) MOVL CX, 4(SP) - MOVL context+20(FP), BX + MOVL context+32(FP), BX MOVL BX, 8(SP) - MOVL dispatcher+24(FP), BX + MOVL dispatcher+36(FP), BX MOVL BX, 12(SP) CALL runtime·sighandler(SB) diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c index 2ce92dcfb..2ce8fae15 100644 --- a/src/pkg/runtime/windows/thread.c +++ b/src/pkg/runtime/windows/thread.c @@ -324,13 +324,31 @@ runtime·ctrlhandler1(uint32 type) return 0; } +// Will keep all callbacks in a linked list, so they don't get garbage collected. +typedef struct Callback Callback; +struct Callback { + Callback* link; + void* gobody; + byte asmbody; +}; + +typedef struct Callbacks Callbacks; +struct Callbacks { + Lock; + Callback* link; + int32 n; +}; + +static Callbacks cbs; + // Call back from windows dll into go. byte * runtime·compilecallback(Eface fn, bool cleanstack) { Func *f; int32 argsize, n; - byte *ret, *p; + byte *p; + Callback *c; if(fn.type->kind != KindFunc) runtime·panicstring("not a function"); @@ -348,7 +366,23 @@ runtime·compilecallback(Eface fn, bool cleanstack) if(cleanstack) n += 2; // ... argsize - ret = p = runtime·mal(n); + runtime·lock(&cbs); + for(c = cbs.link; c != nil; c = c->link) { + if(c->gobody == fn.data) { + runtime·unlock(&cbs); + return &c->asmbody; + } + } + if(cbs.n >= 20) + runtime·throw("too many callback functions"); + c = runtime·mal(sizeof *c + n); + c->gobody = fn.data; + c->link = cbs.link; + cbs.link = c; + cbs.n++; + runtime·unlock(&cbs); + + p = &c->asmbody; // MOVL fn, AX *p++ = 0xb8; @@ -376,7 +410,7 @@ runtime·compilecallback(Eface fn, bool cleanstack) } else *p = 0xc3; - return ret; + return &c->asmbody; } void diff --git a/src/pkg/smtp/smtp.go b/src/pkg/smtp/smtp.go index 3f89af147..d716df56b 100644 --- a/src/pkg/smtp/smtp.go +++ b/src/pkg/smtp/smtp.go @@ -151,8 +151,7 @@ func (c *Client) Auth(a Auth) os.Error { var msg []byte switch code { case 334: - msg = make([]byte, encoding.DecodedLen(len(msg64))) - _, err = encoding.Decode(msg, []byte(msg64)) + msg, err = encoding.DecodeString(msg64) case 235: // the last message isn't base64 because it isn't a challenge msg = []byte(msg64) diff --git a/src/pkg/strconv/decimal.go b/src/pkg/strconv/decimal.go index 3a5cf1ba6..783065bfb 100644 --- a/src/pkg/strconv/decimal.go +++ b/src/pkg/strconv/decimal.go @@ -108,7 +108,7 @@ func newDecimal(i uint64) *decimal { } // Maximum shift that we can do in one pass without overflow. -// Signed int has 31 bits, and we have to be able to accomodate 9<<k. +// Signed int has 31 bits, and we have to be able to accommodate 9<<k. const maxShift = 27 // Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow. diff --git a/src/pkg/strconv/quote.go b/src/pkg/strconv/quote.go index ed5889723..bbc0b2658 100644 --- a/src/pkg/strconv/quote.go +++ b/src/pkg/strconv/quote.go @@ -14,17 +14,14 @@ import ( const lowerhex = "0123456789abcdef" -// Quote returns a double-quoted Go string literal -// representing s. The returned string s uses Go escape -// sequences (\t, \n, \xFF, \u0100) for control characters -// and non-ASCII characters. -func Quote(s string) string { +func quoteWith(s string, quote byte) string { var buf bytes.Buffer - buf.WriteByte('"') + buf.WriteByte(quote) for ; len(s) > 0; s = s[1:] { switch c := s[0]; { - case c == '"': - buf.WriteString(`\"`) + case c == quote: + buf.WriteByte('\\') + buf.WriteByte(quote) case c == '\\': buf.WriteString(`\\`) case ' ' <= c && c <= '~': @@ -69,8 +66,26 @@ func Quote(s string) string { buf.WriteByte(lowerhex[c&0xF]) } } - buf.WriteByte('"') + buf.WriteByte(quote) return buf.String() + +} + +// Quote returns a double-quoted Go string literal +// representing s. The returned string uses Go escape +// sequences (\t, \n, \xFF, \u0100) for control characters +// and non-ASCII characters. +func Quote(s string) string { + return quoteWith(s, '"') +} + +// QuoteRune returns a single-quoted Go character literal +// representing the rune. The returned string uses Go escape +// sequences (\t, \n, \xFF, \u0100) for control characters +// and non-ASCII characters. +func QuoteRune(rune int) string { + // TODO: avoid the allocation here. + return quoteWith(string(rune), '\'') } // CanBackquote returns whether the string s would be diff --git a/src/pkg/strconv/quote_test.go b/src/pkg/strconv/quote_test.go index 1235fcb9a..3232d611c 100644 --- a/src/pkg/strconv/quote_test.go +++ b/src/pkg/strconv/quote_test.go @@ -25,14 +25,37 @@ var quotetests = []quoteTest{ } func TestQuote(t *testing.T) { - for i := 0; i < len(quotetests); i++ { - tt := quotetests[i] + for _, tt := range quotetests { if out := Quote(tt.in); out != tt.out { t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out) } } } +type quoteRuneTest struct { + in int + out string +} + +var quoterunetests = []quoteRuneTest{ + {'a', `'a'`}, + {'\a', `'\a'`}, + {'\\', `'\\'`}, + {0xFF, `'\u00ff'`}, + {0x263a, `'\u263a'`}, + {0x0010ffff, `'\U0010ffff'`}, + {0x0010ffff + 1, `'\ufffd'`}, + {0x04, `'\x04'`}, +} + +func TestQuoteRune(t *testing.T) { + for _, tt := range quoterunetests { + if out := QuoteRune(tt.in); out != tt.out { + t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out) + } + } +} + type canBackquoteTest struct { in string out bool @@ -80,8 +103,7 @@ var canbackquotetests = []canBackquoteTest{ } func TestCanBackquote(t *testing.T) { - for i := 0; i < len(canbackquotetests); i++ { - tt := canbackquotetests[i] + for _, tt := range canbackquotetests { if out := CanBackquote(tt.in); out != tt.out { t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out) } @@ -146,23 +168,20 @@ var misquoted = []string{ } func TestUnquote(t *testing.T) { - for i := 0; i < len(unquotetests); i++ { - tt := unquotetests[i] + for _, tt := range unquotetests { if out, err := Unquote(tt.in); err != nil && out != tt.out { t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out) } } // run the quote tests too, backward - for i := 0; i < len(quotetests); i++ { - tt := quotetests[i] + for _, tt := range quotetests { if in, err := Unquote(tt.out); in != tt.in { t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in) } } - for i := 0; i < len(misquoted); i++ { - s := misquoted[i] + for _, s := range misquoted { if out, err := Unquote(s); out != "" || err != os.EINVAL { t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", os.EINVAL) } diff --git a/src/pkg/strings/reader.go b/src/pkg/strings/reader.go index 4eae90e73..10b0278e1 100644 --- a/src/pkg/strings/reader.go +++ b/src/pkg/strings/reader.go @@ -9,50 +9,84 @@ import ( "utf8" ) -// A Reader satisfies calls to Read, ReadByte, and ReadRune by -// reading from a string. -type Reader string +// A Reader implements the io.Reader, io.ByteScanner, and +// io.RuneScanner interfaces by reading from a string. +type Reader struct { + s string + i int // current reading index + prevRune int // index of previous rune; or < 0 +} + +// Len returns the number of bytes of the unread portion of the +// string. +func (r *Reader) Len() int { + return len(r.s) - r.i +} func (r *Reader) Read(b []byte) (n int, err os.Error) { - s := *r - if len(s) == 0 { + if r.i >= len(r.s) { return 0, os.EOF } - n = copy(b, s) - *r = s[n:] + n = copy(b, r.s[r.i:]) + r.i += n + r.prevRune = -1 return } func (r *Reader) ReadByte() (b byte, err os.Error) { - s := *r - if len(s) == 0 { + if r.i >= len(r.s) { return 0, os.EOF } - b = s[0] - *r = s[1:] + b = r.s[r.i] + r.i++ + r.prevRune = -1 return } + +// UnreadByte moves the reading position back by one byte. +// It is an error to call UnreadByte if nothing has been +// read yet. +func (r *Reader) UnreadByte() os.Error { + if r.i <= 0 { + return os.ErrorString("strings.Reader: at beginning of string") + } + r.i-- + r.prevRune = -1 + return nil +} + // ReadRune reads and returns the next UTF-8-encoded // Unicode code point from the buffer. // If no bytes are available, the error returned is os.EOF. // If the bytes are an erroneous UTF-8 encoding, it // consumes one byte and returns U+FFFD, 1. func (r *Reader) ReadRune() (rune int, size int, err os.Error) { - s := *r - if len(s) == 0 { + if r.i >= len(r.s) { return 0, 0, os.EOF } - c := s[0] - if c < utf8.RuneSelf { - *r = s[1:] + r.prevRune = r.i + if c := r.s[r.i]; c < utf8.RuneSelf { + r.i++ return int(c), 1, nil } - rune, size = utf8.DecodeRuneInString(string(s)) - *r = s[size:] + rune, size = utf8.DecodeRuneInString(r.s[r.i:]) + r.i += size return } +// UnreadRune causes the next call to ReadRune to return the same rune +// as the previous call to ReadRune. +// The last method called on r must have been ReadRune. +func (r *Reader) UnreadRune() os.Error { + if r.prevRune < 0 { + return os.ErrorString("strings.Reader: previous operation was not ReadRune") + } + r.i = r.prevRune + r.prevRune = -1 + return nil +} + // NewReader returns a new Reader reading from s. // It is similar to bytes.NewBufferString but more efficient and read-only. -func NewReader(s string) *Reader { return (*Reader)(&s) } +func NewReader(s string) *Reader { return &Reader{s, 0, -1} } diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go index c45b1485d..a1a635ddd 100644 --- a/src/pkg/strings/strings_test.go +++ b/src/pkg/strings/strings_test.go @@ -5,6 +5,7 @@ package strings_test import ( + "bytes" "os" "reflect" "strconv" @@ -751,13 +752,56 @@ func TestRunes(t *testing.T) { } } +func TestReadByte(t *testing.T) { + testStrings := []string{"", abcd, faces, commas} + for _, s := range testStrings { + reader := NewReader(s) + if e := reader.UnreadByte(); e == nil { + t.Errorf("Unreading %q at beginning: expected error", s) + } + var res bytes.Buffer + for { + b, e := reader.ReadByte() + if e == os.EOF { + break + } + if e != nil { + t.Errorf("Reading %q: %s", s, e) + break + } + res.WriteByte(b) + // unread and read again + e = reader.UnreadByte() + if e != nil { + t.Errorf("Unreading %q: %s", s, e) + break + } + b1, e := reader.ReadByte() + if e != nil { + t.Errorf("Reading %q after unreading: %s", s, e) + break + } + if b1 != b { + t.Errorf("Reading %q after unreading: want byte %q, got %q", s, b, b1) + break + } + } + if res.String() != s { + t.Errorf("Reader(%q).ReadByte() produced %q", s, res.String()) + } + } +} + func TestReadRune(t *testing.T) { testStrings := []string{"", abcd, faces, commas} for _, s := range testStrings { reader := NewReader(s) + if e := reader.UnreadRune(); e == nil { + t.Errorf("Unreading %q at beginning: expected error", s) + } res := "" for { - r, _, e := reader.ReadRune() + r, z, e := reader.ReadRune() if e == os.EOF { break } @@ -766,6 +810,25 @@ func TestReadRune(t *testing.T) { break } res += string(r) + // unread and read again + e = reader.UnreadRune() + if e != nil { + t.Errorf("Unreading %q: %s", s, e) + break + } + r1, z1, e := reader.ReadRune() + if e != nil { + t.Errorf("Reading %q after unreading: %s", s, e) + break + } + if r1 != r { + t.Errorf("Reading %q after unreading: want rune %q, got %q", s, r, r1) + break + } + if z1 != z { + t.Errorf("Reading %q after unreading: want size %d, got %d", s, z, z1) + break + } } if res != s { t.Errorf("Reader(%q).ReadRune() produced %q", s, res) diff --git a/src/pkg/sync/atomic/asm_arm.s b/src/pkg/sync/atomic/asm_arm.s index 3363bbcf1..448a98a01 100644 --- a/src/pkg/sync/atomic/asm_arm.s +++ b/src/pkg/sync/atomic/asm_arm.s @@ -87,11 +87,14 @@ add64loop: // which will make uses of the 64-bit atomic operations loop forever. // If things are working, set okLDREXD to avoid future checks. // https://bugs.launchpad.net/qemu/+bug/670883. -TEXT check64<>(SB),7,$8 +TEXT check64<>(SB),7,$16 MOVW $10, R1 + // 8-aligned stack address scratch space. + MOVW $8(SP), R3 + AND $~7, R3 loop: - LDREXD (SP), R2 - STREXD R2, (SP), R0 + LDREXD (R3), R2 + STREXD R2, (R3), R0 CMP $0, R0 BEQ ok SUB $1, R1 diff --git a/src/pkg/sync/cond.go b/src/pkg/sync/cond.go index ea48f2e7a..75494b535 100644 --- a/src/pkg/sync/cond.go +++ b/src/pkg/sync/cond.go @@ -14,10 +14,26 @@ import "runtime" // which must be held when changing the condition and // when calling the Wait method. type Cond struct { - L Locker // held while observing or changing the condition - m Mutex // held to avoid internal races - waiters int // number of goroutines blocked on Wait - sema *uint32 + L Locker // held while observing or changing the condition + m Mutex // held to avoid internal races + + // We must be careful to make sure that when Signal + // releases a semaphore, the corresponding acquire is + // executed by a goroutine that was already waiting at + // the time of the call to Signal, not one that arrived later. + // To ensure this, we segment waiting goroutines into + // generations punctuated by calls to Signal. Each call to + // Signal begins another generation if there are no goroutines + // left in older generations for it to wake. Because of this + // optimization (only begin another generation if there + // are no older goroutines left), we only need to keep track + // of the two most recent generations, which we call old + // and new. + oldWaiters int // number of waiters in old generation... + oldSema *uint32 // ... waiting on this semaphore + + newWaiters int // number of waiters in new generation... + newSema *uint32 // ... waiting on this semaphore } // NewCond returns a new Cond with Locker l. @@ -42,11 +58,11 @@ func NewCond(l Locker) *Cond { // func (c *Cond) Wait() { c.m.Lock() - if c.sema == nil { - c.sema = new(uint32) + if c.newSema == nil { + c.newSema = new(uint32) } - s := c.sema - c.waiters++ + s := c.newSema + c.newWaiters++ c.m.Unlock() c.L.Unlock() runtime.Semacquire(s) @@ -59,9 +75,16 @@ func (c *Cond) Wait() { // during the call. func (c *Cond) Signal() { c.m.Lock() - if c.waiters > 0 { - c.waiters-- - runtime.Semrelease(c.sema) + if c.oldWaiters == 0 && c.newWaiters > 0 { + // Retire old generation; rename new to old. + c.oldWaiters = c.newWaiters + c.oldSema = c.newSema + c.newWaiters = 0 + c.newSema = nil + } + if c.oldWaiters > 0 { + c.oldWaiters-- + runtime.Semrelease(c.oldSema) } c.m.Unlock() } @@ -72,19 +95,19 @@ func (c *Cond) Signal() { // during the call. func (c *Cond) Broadcast() { c.m.Lock() - if c.waiters > 0 { - s := c.sema - n := c.waiters - for i := 0; i < n; i++ { - runtime.Semrelease(s) + // Wake both generations. + if c.oldWaiters > 0 { + for i := 0; i < c.oldWaiters; i++ { + runtime.Semrelease(c.oldSema) + } + c.oldWaiters = 0 + } + if c.newWaiters > 0 { + for i := 0; i < c.newWaiters; i++ { + runtime.Semrelease(c.newSema) } - // We just issued n wakeups via the semaphore s. - // To ensure that they wake up the existing waiters - // and not waiters that arrive after Broadcast returns, - // clear c.sema. The next operation will allocate - // a new one. - c.sema = nil - c.waiters = 0 + c.newWaiters = 0 + c.newSema = nil } c.m.Unlock() } diff --git a/src/pkg/sync/cond_test.go b/src/pkg/sync/cond_test.go index 846f98bf3..cefacb184 100644 --- a/src/pkg/sync/cond_test.go +++ b/src/pkg/sync/cond_test.go @@ -46,6 +46,33 @@ func TestCondSignal(t *testing.T) { c.Signal() } +func TestCondSignalGenerations(t *testing.T) { + var m Mutex + c := NewCond(&m) + n := 100 + running := make(chan bool, n) + awake := make(chan int, n) + for i := 0; i < n; i++ { + go func(i int) { + m.Lock() + running <- true + c.Wait() + awake <- i + m.Unlock() + }(i) + if i > 0 { + a := <-awake + if a != i-1 { + t.Fatalf("wrong goroutine woke up: want %d, got %d", i-1, a) + } + } + <-running + m.Lock() + c.Signal() + m.Unlock() + } +} + func TestCondBroadcast(t *testing.T) { var m Mutex c := NewCond(&m) diff --git a/src/pkg/syscall/Makefile b/src/pkg/syscall/Makefile index 978bc94f8..9284fcc5d 100644 --- a/src/pkg/syscall/Makefile +++ b/src/pkg/syscall/Makefile @@ -17,24 +17,27 @@ GOFILES=\ ztypes_$(GOOS)_$(GOARCH).go\ GOFILES_freebsd=\ + exec_unix.go\ + route_bsd.go\ syscall_bsd.go\ syscall_unix.go\ - exec_unix.go\ GOFILES_darwin=\ + exec_unix.go\ + route_bsd.go\ syscall_bsd.go\ syscall_unix.go\ - exec_unix.go\ GOFILES_linux=\ - syscall_unix.go\ exec_unix.go\ + netlink_linux.go\ + syscall_unix.go\ GOFILES_windows=\ - exec_windows.go - + exec_windows.go\ + GOFILES_plan9=\ - exec_plan9.go + exec_plan9.go\ OFILES=\ asm_$(GOOS)_$(GOARCH).$O\ diff --git a/src/pkg/syscall/exec_windows.go b/src/pkg/syscall/exec_windows.go index 85b1c2eda..b25f4a650 100644 --- a/src/pkg/syscall/exec_windows.go +++ b/src/pkg/syscall/exec_windows.go @@ -14,7 +14,7 @@ import ( var ForkLock sync.RWMutex -// escape rewrites command line argument s as prescribed +// EscapeArg rewrites command line argument s as prescribed // in http://msdn.microsoft.com/en-us/library/ms880421. // This function returns "" (2 double quotes) if s is empty. // Alternatively, these transformations are done: @@ -23,7 +23,7 @@ var ForkLock sync.RWMutex // - every double quote (") is escaped by back slash (\); // - finally, s is wrapped with double quotes (arg -> "arg"), // but only if there is space or tab inside s. -func escape(s string) string { +func EscapeArg(s string) string { if len(s) == 0 { return "\"\"" } @@ -89,7 +89,7 @@ func makeCmdLine(args []string) string { if s != "" { s += " " } - s += escape(v) + s += EscapeArg(v) } return s } @@ -222,6 +222,7 @@ type ProcAttr struct { Env []string Files []int HideWindow bool + CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess } var zeroAttributes ProcAttr @@ -252,10 +253,19 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, } argv0p := StringToUTF16Ptr(argv0) + var cmdline string + // Windows CreateProcess takes the command line as a single string: + // use attr.CmdLine if set, else build the command line by escaping + // and joining each argument with spaces + if attr.CmdLine != "" { + cmdline = attr.CmdLine + } else { + cmdline = makeCmdLine(argv) + } + var argvp *uint16 - s := makeCmdLine(argv) - if len(s) != 0 { - argvp = StringToUTF16Ptr(s) + if len(cmdline) != 0 { + argvp = StringToUTF16Ptr(cmdline) } var dirp *uint16 diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh index 3916174aa..1949ebfad 100755 --- a/src/pkg/syscall/mkerrors.sh +++ b/src/pkg/syscall/mkerrors.sh @@ -37,6 +37,7 @@ includes_Linux=' #include <linux/ptrace.h> #include <linux/wait.h> #include <net/if.h> +#include <net/if_arp.h> #include <netpacket/packet.h> ' @@ -53,6 +54,7 @@ includes_Darwin=' #include <sys/wait.h> #include <net/bpf.h> #include <net/if.h> +#include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -68,6 +70,7 @@ includes_FreeBSD=' #include <sys/wait.h> #include <net/bpf.h> #include <net/if.h> +#include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -137,9 +140,9 @@ done $2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 !~ "NLA_TYPE_MASK" && - $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RTM)_/ || + $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RTM|RTN|RTPROT|RTA|RTAX|RTNH|ARPHRD)_/ || $2 ~ /^SIOC/ || - $2 ~ /^(IFF|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || + $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || $2 ~ /^BIOC/ || $2 !~ /^(BPF_TIMEVAL)$/ && $2 ~ /^(BPF|DLT)_/ || diff --git a/src/pkg/syscall/netlink_linux.go b/src/pkg/syscall/netlink_linux.go new file mode 100644 index 000000000..681027ab9 --- /dev/null +++ b/src/pkg/syscall/netlink_linux.go @@ -0,0 +1,227 @@ +// Copyright 2011 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. + +// Netlink sockets and messages + +package syscall + +import ( + "unsafe" +) + +// Round the length of a netlink message up to align it properly. +func nlmAlignOf(msglen int) int { + return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1) +} + +// Round the length of a netlink route attribute up to align it +// properly. +func rtaAlignOf(attrlen int) int { + return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1) +} + +// NetlinkRouteRequest represents the request message to receive +// routing and link states from the kernel. +type NetlinkRouteRequest struct { + Header NlMsghdr + Data RtGenmsg +} + +func (rr *NetlinkRouteRequest) toWireFormat() []byte { + b := make([]byte, rr.Header.Len) + b[0] = byte(rr.Header.Len) + b[1] = byte(rr.Header.Len >> 8) + b[2] = byte(rr.Header.Len >> 16) + b[3] = byte(rr.Header.Len >> 24) + b[4] = byte(rr.Header.Type) + b[5] = byte(rr.Header.Type >> 8) + b[6] = byte(rr.Header.Flags) + b[7] = byte(rr.Header.Flags >> 8) + b[8] = byte(rr.Header.Seq) + b[9] = byte(rr.Header.Seq >> 8) + b[10] = byte(rr.Header.Seq >> 16) + b[11] = byte(rr.Header.Seq >> 24) + b[12] = byte(rr.Header.Pid) + b[13] = byte(rr.Header.Pid >> 8) + b[14] = byte(rr.Header.Pid >> 16) + b[15] = byte(rr.Header.Pid >> 24) + b[16] = byte(rr.Data.Family) + return b +} + +func newNetlinkRouteRequest(proto, seq, family int) []byte { + rr := &NetlinkRouteRequest{} + rr.Header.Len = NLMSG_HDRLEN + SizeofRtGenmsg + rr.Header.Type = uint16(proto) + rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST + rr.Header.Seq = uint32(seq) + rr.Data.Family = uint8(family) + return rr.toWireFormat() +} + +// NetlinkRIB returns routing information base, as known as RIB, +// which consists of network facility information, states and +// parameters. +func NetlinkRIB(proto, family int) ([]byte, int) { + var ( + s int + e int + lsanl SockaddrNetlink + seq int + tab []byte + ) + + s, e = Socket(AF_NETLINK, SOCK_RAW, 0) + if e != 0 { + return nil, e + } + defer Close(s) + + lsanl.Family = AF_NETLINK + e = Bind(s, &lsanl) + if e != 0 { + return nil, e + } + + seq++ + wb := newNetlinkRouteRequest(proto, seq, family) + e = Sendto(s, wb, 0, &lsanl) + if e != 0 { + return nil, e + } + + for { + var ( + rb []byte + nr int + lsa Sockaddr + ) + + rb = make([]byte, Getpagesize()) + nr, _, e = Recvfrom(s, rb, 0) + if e != 0 { + return nil, e + } + if nr < NLMSG_HDRLEN { + return nil, EINVAL + } + rb = rb[:nr] + tab = append(tab, rb...) + + msgs, _ := ParseNetlinkMessage(rb) + for _, m := range msgs { + if lsa, e = Getsockname(s); e != 0 { + return nil, e + } + switch v := lsa.(type) { + case *SockaddrNetlink: + if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid { + return nil, EINVAL + } + default: + return nil, EINVAL + } + if m.Header.Type == NLMSG_DONE { + goto done + } + if m.Header.Type == NLMSG_ERROR { + return nil, EINVAL + } + } + } + +done: + return tab, 0 +} + +// NetlinkMessage represents the netlink message. +type NetlinkMessage struct { + Header NlMsghdr + Data []byte +} + +// ParseNetlinkMessage parses buf as netlink messages and returns +// the slice containing the NetlinkMessage structs. +func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) { + var ( + h *NlMsghdr + dbuf []byte + dlen int + e int + msgs []NetlinkMessage + ) + + for len(buf) >= NLMSG_HDRLEN { + h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf) + if e != 0 { + break + } + m := NetlinkMessage{} + m.Header = *h + m.Data = dbuf[:h.Len-NLMSG_HDRLEN] + msgs = append(msgs, m) + buf = buf[dlen:] + } + + return msgs, e +} + +func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) { + h := (*NlMsghdr)(unsafe.Pointer(&buf[0])) + if h.Len < NLMSG_HDRLEN || int(h.Len) > len(buf) { + return nil, nil, 0, EINVAL + } + return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), 0 +} + +// NetlinkRouteAttr represents the netlink route attribute. +type NetlinkRouteAttr struct { + Attr RtAttr + Value []byte +} + +// ParseNetlinkRouteAttr parses msg's payload as netlink route +// attributes and returns the slice containing the NetlinkRouteAttr +// structs. +func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) { + var ( + buf []byte + a *RtAttr + alen int + vbuf []byte + e int + attrs []NetlinkRouteAttr + ) + + switch msg.Header.Type { + case RTM_NEWLINK: + buf = msg.Data[SizeofIfInfomsg:] + case RTM_NEWADDR: + buf = msg.Data[SizeofIfAddrmsg:] + default: + return nil, EINVAL + } + + for len(buf) >= SizeofRtAttr { + a, vbuf, alen, e = netlinkRouteAttrAndValue(buf) + if e != 0 { + break + } + ra := NetlinkRouteAttr{} + ra.Attr = *a + ra.Value = vbuf[:a.Len-SizeofRtAttr] + attrs = append(attrs, ra) + buf = buf[alen:] + } + + return attrs, 0 +} + +func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) { + h := (*RtAttr)(unsafe.Pointer(&buf[0])) + if h.Len < SizeofRtAttr || int(h.Len) > len(buf) { + return nil, nil, 0, EINVAL + } + return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), 0 +} diff --git a/src/pkg/syscall/route_bsd.go b/src/pkg/syscall/route_bsd.go new file mode 100644 index 000000000..79a8793d5 --- /dev/null +++ b/src/pkg/syscall/route_bsd.go @@ -0,0 +1,180 @@ +// Copyright 2011 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. + +// Routing sockets and messages + +package syscall + +import ( + "unsafe" +) + +const darwinAMD64 = OS == "darwin" && ARCH == "amd64" + +// Round the length of a raw sockaddr up to align it properly. +func rsaAlignOf(salen int) int { + salign := sizeofPtr + // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit + // aligned access to BSD subsystem. + if darwinAMD64 { + salign = 4 + } + if salen == 0 { + return salign + } + return (salen + salign - 1) & ^(salign - 1) +} + +// RouteRIB returns routing information base, as known as RIB, +// which consists of network facility information, states and +// parameters. +func RouteRIB(facility, param int) ([]byte, int) { + var ( + tab []byte + e int + ) + + mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)} + + // Find size. + n := uintptr(0) + if e = sysctl(mib, nil, &n, nil, 0); e != 0 { + return nil, e + } + if n == 0 { + return nil, 0 + } + + tab = make([]byte, n) + if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 { + return nil, e + } + + return tab[:n], 0 +} + +// RoutingMessage represents a routing message. +type RoutingMessage interface { + sockaddr() []Sockaddr +} + +const anyMessageLen = unsafe.Sizeof(anyMessage{}) + +type anyMessage struct { + Msglen uint16 + Version uint8 + Type uint8 +} + +func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage { + switch any.Type { + case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE: + p := (*RouteMessage)(unsafe.Pointer(any)) + rtm := &RouteMessage{} + rtm.Header = p.Header + rtm.Data = buf[SizeofRtMsghdr:any.Msglen] + return rtm + case RTM_IFINFO: + p := (*InterfaceMessage)(unsafe.Pointer(any)) + ifm := &InterfaceMessage{} + ifm.Header = p.Header + ifm.Data = buf[SizeofIfMsghdr:any.Msglen] + return ifm + case RTM_NEWADDR, RTM_DELADDR: + p := (*InterfaceAddrMessage)(unsafe.Pointer(any)) + ifam := &InterfaceAddrMessage{} + ifam.Header = p.Header + ifam.Data = buf[SizeofIfaMsghdr:any.Msglen] + return ifam + case RTM_NEWMADDR, RTM_DELMADDR: + // TODO: implement this in the near future + } + return nil +} + +// RouteMessage represents a routing message containing routing +// entries. +type RouteMessage struct { + Header RtMsghdr + Data []byte +} + +func (m *RouteMessage) sockaddr() (sas []Sockaddr) { + // TODO: implement this in the near future + return nil +} + +// InterfaceMessage represents a routing message containing +// network interface entries. +type InterfaceMessage struct { + Header IfMsghdr + Data []byte +} + +func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) { + if m.Header.Addrs&RTA_IFP == 0 { + return nil + } + sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0]))) + if e != 0 { + return nil + } + return append(sas, sa) +} + +// InterfaceAddrMessage represents a routing message containing +// network interface address entries. +type InterfaceAddrMessage struct { + Header IfaMsghdr + Data []byte +} + +const rtaMask = RTA_IFA | RTA_NETMASK | RTA_BRD + +func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) { + if m.Header.Addrs&rtaMask == 0 { + return nil + } + + buf := m.Data[:] + for i := uint(0); i < RTAX_MAX; i++ { + if m.Header.Addrs&rtaMask&(1<<i) == 0 { + continue + } + rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0])) + switch i { + case RTAX_IFA: + sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa))) + if e != 0 { + return nil + } + sas = append(sas, sa) + case RTAX_NETMASK, RTAX_BRD: + // nothing to do + } + buf = buf[rsaAlignOf(int(rsa.Len)):] + } + + return sas +} + +// ParseRoutingMessage parses buf as routing messages and returns +// the slice containing the RoutingMessage interfaces. +func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) { + for len(buf) >= anyMessageLen { + any := (*anyMessage)(unsafe.Pointer(&buf[0])) + if any.Version != RTM_VERSION { + return nil, EINVAL + } + msgs = append(msgs, any.toRoutingMessage(buf)) + buf = buf[any.Msglen:] + } + return msgs, 0 +} + +// ParseRoutingMessage parses msg's payload as raw sockaddrs and +// returns the slice containing the Sockaddr interfaces. +func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, errno int) { + return append(sas, msg.sockaddr()...), 0 +} diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go index 766a56db5..89bcc7f0e 100644 --- a/src/pkg/syscall/syscall_bsd.go +++ b/src/pkg/syscall/syscall_bsd.go @@ -22,7 +22,6 @@ const ImplementsGetwd = false func Getwd() (string, int) { return "", ENOTSUP } - /* * Wrapped */ @@ -392,7 +391,11 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) { return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), unsafe.Sizeof(*l)) } -func SetsockoptIpMreq(fd, level, opt int, mreq *IpMreq) (errno int) { +func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) { + return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq)) +} + +func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) { return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq)) } @@ -519,27 +522,6 @@ func SysctlUint32(name string) (value uint32, errno int) { return *(*uint32)(unsafe.Pointer(&buf[0])), 0 } -func SysctlNetRoute(fourth, fifth, sixth int) (value []byte, errno int) { - mib := []_C_int{CTL_NET, AF_ROUTE, 0, _C_int(fourth), _C_int(fifth), _C_int(sixth)} - - // Find size. - n := uintptr(0) - if errno = sysctl(mib, nil, &n, nil, 0); errno != 0 { - return nil, errno - } - if n == 0 { - return nil, 0 - } - - // Read into buffer of that size. - b := make([]byte, n) - if errno = sysctl(mib, &b[0], &n, nil, 0); errno != 0 { - return nil, errno - } - - return b[0:n], 0 -} - //sys utimes(path string, timeval *[2]Timeval) (errno int) func Utimes(path string, tv []Timeval) (errno int) { if len(tv) != 2 { diff --git a/src/pkg/syscall/syscall_linux.go b/src/pkg/syscall/syscall_linux.go index 9e9037ea1..63682d23c 100644 --- a/src/pkg/syscall/syscall_linux.go +++ b/src/pkg/syscall/syscall_linux.go @@ -463,7 +463,11 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) { return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), unsafe.Sizeof(*l)) } -func SetsockoptIpMreq(fd, level, opt int, mreq *IpMreq) (errno int) { +func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) { + return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq)) +} + +func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) { return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq)) } diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go index 6ba031faf..bb93533bd 100644 --- a/src/pkg/syscall/syscall_windows.go +++ b/src/pkg/syscall/syscall_windows.go @@ -230,16 +230,13 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) { } var createmode uint32 switch { - case mode&O_CREAT != 0: - switch { - case mode&O_EXCL != 0: - createmode = CREATE_NEW - case mode&O_APPEND != 0: - createmode = OPEN_ALWAYS - default: - createmode = CREATE_ALWAYS - } - case mode&O_TRUNC != 0: + case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): + createmode = CREATE_NEW + case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): + createmode = CREATE_ALWAYS + case mode&O_CREAT == O_CREAT: + createmode = OPEN_ALWAYS + case mode&O_TRUNC == O_TRUNC: createmode = TRUNCATE_EXISTING default: createmode = OPEN_EXISTING @@ -683,14 +680,20 @@ const ( IP_DROP_MEMBERSHIP ) -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } -func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) { return EWINDOWS } -func SetsockoptIpMreq(fd, level, opt int, mreq *IpMreq) (errno int) { return EWINDOWS } -func BindToDevice(fd int, device string) (errno int) { return EWINDOWS } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) { return EWINDOWS } +func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) { return EWINDOWS } +func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) { return EWINDOWS } +func BindToDevice(fd int, device string) (errno int) { return EWINDOWS } // TODO(brainman): fix all needed for os diff --git a/src/pkg/syscall/types_darwin.c b/src/pkg/syscall/types_darwin.c index 666923a68..ecccd5bd9 100644 --- a/src/pkg/syscall/types_darwin.c +++ b/src/pkg/syscall/types_darwin.c @@ -39,8 +39,7 @@ Input to godefs. See also mkerrors.sh and mkall.sh // Machine characteristics; for internal use. -enum -{ +enum { $sizeofPtr = sizeof(void*), $sizeofShort = sizeof(short), $sizeofInt = sizeof(int), @@ -48,7 +47,6 @@ enum $sizeofLongLong = sizeof(long long), }; - // Basic types typedef short $_C_short; @@ -71,8 +69,7 @@ typedef gid_t $_Gid_t; // Files -enum -{ +enum { $O_CLOEXEC = 0, // not supported }; @@ -86,8 +83,6 @@ typedef struct log2phys $Log2phys_t; typedef struct dirent $Dirent; -// Wait status. - // Sockets union sockaddr_all { @@ -112,9 +107,11 @@ typedef struct sockaddr_any $RawSockaddrAny; typedef socklen_t $_Socklen; typedef struct linger $Linger; typedef struct iovec $Iovec; -typedef struct ip_mreq $IpMreq; +typedef struct ip_mreq $IPMreq; +typedef struct ipv6_mreq $IPv6Mreq; typedef struct msghdr $Msghdr; typedef struct cmsghdr $Cmsghdr; +typedef struct in6_pktinfo $Inet6Pktinfo; enum { $SizeofSockaddrInet4 = sizeof(struct sockaddr_in), @@ -123,19 +120,21 @@ enum { $SizeofSockaddrUnix = sizeof(struct sockaddr_un), $SizeofSockaddrDatalink = sizeof(struct sockaddr_dl), $SizeofLinger = sizeof(struct linger), - $SizeofIpMreq = sizeof(struct ip_mreq), + $SizeofIPMreq = sizeof(struct ip_mreq), + $SizeofIPv6Mreq = sizeof(struct ipv6_mreq), $SizeofMsghdr = sizeof(struct msghdr), $SizeofCmsghdr = sizeof(struct cmsghdr), + $SizeofInet6Pktinfo = sizeof(struct in6_pktinfo), }; // Ptrace requests + enum { $PTRACE_TRACEME = PT_TRACE_ME, $PTRACE_CONT = PT_CONTINUE, $PTRACE_KILL = PT_KILL, }; - // Events (kqueue, kevent) typedef struct kevent $Kevent_t; diff --git a/src/pkg/syscall/types_freebsd.c b/src/pkg/syscall/types_freebsd.c index 9d65683ef..97636550a 100644 --- a/src/pkg/syscall/types_freebsd.c +++ b/src/pkg/syscall/types_freebsd.c @@ -35,8 +35,7 @@ Input to godefs. See also mkerrors.sh and mkall.sh // Machine characteristics; for internal use. -enum -{ +enum { $sizeofPtr = sizeof(void*), $sizeofShort = sizeof(short), $sizeofInt = sizeof(int), @@ -44,7 +43,6 @@ enum $sizeofLongLong = sizeof(long long), }; - // Basic types typedef short $_C_short; @@ -66,13 +64,11 @@ typedef gid_t $_Gid_t; // Files -enum -{ +enum { $O_CLOEXEC = 0, // not supported }; -enum -{ // Directory mode bits +enum { // Directory mode bits $S_IFMT = S_IFMT, $S_IFIFO = S_IFIFO, $S_IFCHR = S_IFCHR, @@ -95,8 +91,6 @@ typedef struct flock $Flock_t; typedef struct dirent $Dirent; -// Wait status. - // Sockets union sockaddr_all { @@ -121,9 +115,11 @@ typedef struct sockaddr_any $RawSockaddrAny; typedef socklen_t $_Socklen; typedef struct linger $Linger; typedef struct iovec $Iovec; -typedef struct ip_mreq $IpMreq; +typedef struct ip_mreq $IPMreq; +typedef struct ipv6_mreq $IPv6Mreq; typedef struct msghdr $Msghdr; typedef struct cmsghdr $Cmsghdr; +typedef struct in6_pktinfo $Inet6Pktinfo; enum { $SizeofSockaddrInet4 = sizeof(struct sockaddr_in), @@ -132,19 +128,21 @@ enum { $SizeofSockaddrUnix = sizeof(struct sockaddr_un), $SizeofSockaddrDatalink = sizeof(struct sockaddr_dl), $SizeofLinger = sizeof(struct linger), - $SizeofIpMreq = sizeof(struct ip_mreq), + $SizeofIPMreq = sizeof(struct ip_mreq), + $SizeofIPv6Mreq = sizeof(struct ipv6_mreq), $SizeofMsghdr = sizeof(struct msghdr), $SizeofCmsghdr = sizeof(struct cmsghdr), + $SizeofInet6Pktinfo = sizeof(struct in6_pktinfo), }; // Ptrace requests + enum { $PTRACE_TRACEME = PT_TRACE_ME, $PTRACE_CONT = PT_CONTINUE, $PTRACE_KILL = PT_KILL, }; - // Events (kqueue, kevent) typedef struct kevent $Kevent_t; diff --git a/src/pkg/syscall/types_linux.c b/src/pkg/syscall/types_linux.c index 1eaa58255..ce7f96764 100644 --- a/src/pkg/syscall/types_linux.c +++ b/src/pkg/syscall/types_linux.c @@ -47,8 +47,7 @@ Input to godefs. See also mkerrors.sh and mkall.sh // Machine characteristics; for internal use. -enum -{ +enum { $sizeofPtr = sizeof(void*), $sizeofShort = sizeof(short), $sizeofInt = sizeof(int), @@ -113,9 +112,11 @@ typedef struct sockaddr_any $RawSockaddrAny; typedef socklen_t $_Socklen; typedef struct linger $Linger; typedef struct iovec $Iovec; -typedef struct ip_mreq $IpMreq; +typedef struct ip_mreq $IPMreq; +typedef struct ipv6_mreq $IPv6Mreq; typedef struct msghdr $Msghdr; typedef struct cmsghdr $Cmsghdr; +typedef struct in6_pktinfo $Inet6Pktinfo; typedef struct ucred $Ucred; enum { @@ -126,9 +127,11 @@ enum { $SizeofSockaddrLinklayer = sizeof(struct sockaddr_ll), $SizeofSockaddrNetlink = sizeof(struct sockaddr_nl), $SizeofLinger = sizeof(struct linger), - $SizeofIpMreq = sizeof(struct ip_mreq), + $SizeofIPMreq = sizeof(struct ip_mreq), + $SizeofIPv6Mreq = sizeof(struct ipv6_mreq), $SizeofMsghdr = sizeof(struct msghdr), $SizeofCmsghdr = sizeof(struct cmsghdr), + $SizeofInet6Pktinfo = sizeof(struct in6_pktinfo), $SizeofUcred = sizeof(struct ucred), }; @@ -165,6 +168,42 @@ enum { $IFLA_NET_NS_PID = IFLA_NET_NS_PID, $IFLA_IFALIAS = IFLA_IFALIAS, $IFLA_MAX = IFLA_MAX, + $RT_SCOPE_UNIVERSE = RT_SCOPE_UNIVERSE, + $RT_SCOPE_SITE = RT_SCOPE_SITE, + $RT_SCOPE_LINK = RT_SCOPE_LINK, + $RT_SCOPE_HOST = RT_SCOPE_HOST, + $RT_SCOPE_NOWHERE = RT_SCOPE_NOWHERE, + $RT_TABLE_UNSPEC = RT_TABLE_UNSPEC, + $RT_TABLE_COMPAT = RT_TABLE_COMPAT, + $RT_TABLE_DEFAULT = RT_TABLE_DEFAULT, + $RT_TABLE_MAIN = RT_TABLE_MAIN, + $RT_TABLE_LOCAL = RT_TABLE_LOCAL, + $RT_TABLE_MAX = RT_TABLE_MAX, + $RTA_UNSPEC = RTA_UNSPEC, + $RTA_DST = RTA_DST, + $RTA_SRC = RTA_SRC, + $RTA_IIF = RTA_IIF, + $RTA_OIF = RTA_OIF, + $RTA_GATEWAY = RTA_GATEWAY, + $RTA_PRIORITY = RTA_PRIORITY, + $RTA_PREFSRC = RTA_PREFSRC, + $RTA_METRICS = RTA_METRICS, + $RTA_MULTIPATH = RTA_MULTIPATH, + $RTA_FLOW = RTA_FLOW, + $RTA_CACHEINFO = RTA_CACHEINFO, + $RTA_TABLE = RTA_TABLE, + $RTN_UNSPEC = RTN_UNSPEC, + $RTN_UNICAST = RTN_UNICAST, + $RTN_LOCAL = RTN_LOCAL, + $RTN_BROADCAST = RTN_BROADCAST, + $RTN_ANYCAST = RTN_ANYCAST, + $RTN_MULTICAST = RTN_MULTICAST, + $RTN_BLACKHOLE = RTN_BLACKHOLE, + $RTN_UNREACHABLE = RTN_UNREACHABLE, + $RTN_PROHIBIT = RTN_PROHIBIT, + $RTN_THROW = RTN_THROW, + $RTN_NAT = RTN_NAT, + $RTN_XRESOLVE = RTN_XRESOLVE, $SizeofNlMsghdr = sizeof(struct nlmsghdr), $SizeofNlMsgerr = sizeof(struct nlmsgerr), $SizeofRtGenmsg = sizeof(struct rtgenmsg), @@ -173,6 +212,7 @@ enum { $SizeofIfInfomsg = sizeof(struct ifinfomsg), $SizeofIfAddrmsg = sizeof(struct ifaddrmsg), $SizeofRtmsg = sizeof(struct rtmsg), + $SizeofRtNexthop = sizeof(struct rtnexthop), }; typedef struct nlmsghdr $NlMsghdr; @@ -183,6 +223,7 @@ typedef struct rtattr $RtAttr; typedef struct ifinfomsg $IfInfomsg; typedef struct ifaddrmsg $IfAddrmsg; typedef struct rtmsg $RtMsg; +typedef struct rtnexthop $RtNexthop; // Inotify diff --git a/src/pkg/syscall/zerrors_darwin_386.go b/src/pkg/syscall/zerrors_darwin_386.go index 7bc1280d6..5ee64ee70 100644 --- a/src/pkg/syscall/zerrors_darwin_386.go +++ b/src/pkg/syscall/zerrors_darwin_386.go @@ -339,6 +339,72 @@ const ( IFF_SIMPLEX = 0x800 IFF_UP = 0x1 IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a IN_CLASSA_HOST = 0xffffff IN_CLASSA_MAX = 0x80 IN_CLASSA_NET = 0xff000000 diff --git a/src/pkg/syscall/zerrors_darwin_amd64.go b/src/pkg/syscall/zerrors_darwin_amd64.go index d76f09220..65a48d6e7 100644 --- a/src/pkg/syscall/zerrors_darwin_amd64.go +++ b/src/pkg/syscall/zerrors_darwin_amd64.go @@ -339,6 +339,72 @@ const ( IFF_SIMPLEX = 0x800 IFF_UP = 0x1 IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_AAL5 = 0x31 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ATM = 0x25 + IFT_BRIDGE = 0xd1 + IFT_CARP = 0xf8 + IFT_CEPT = 0x13 + IFT_DS3 = 0x1e + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_ETHER = 0x6 + IFT_FAITH = 0x38 + IFT_FDDI = 0xf + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_GIF = 0x37 + IFT_HDH1822 = 0x3 + IFT_HIPPI = 0x2f + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IEEE1394 = 0x90 + IFT_IEEE8023ADLAG = 0x88 + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88026 = 0xa + IFT_L2VLAN = 0x87 + IFT_LAPB = 0x10 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_NSIP = 0x1b + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PDP = 0xff + IFT_PFLOG = 0xf5 + IFT_PFSYNC = 0xf6 + IFT_PPP = 0x17 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PTPSERIAL = 0x16 + IFT_RS232 = 0x21 + IFT_SDLC = 0x11 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_STARLAN = 0xb + IFT_STF = 0x39 + IFT_T1 = 0x12 + IFT_ULTRA = 0x1d + IFT_V35 = 0x2d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a IN_CLASSA_HOST = 0xffffff IN_CLASSA_MAX = 0x80 IN_CLASSA_NET = 0xff000000 diff --git a/src/pkg/syscall/zerrors_freebsd_386.go b/src/pkg/syscall/zerrors_freebsd_386.go index 9c21c71eb..52e42487b 100644 --- a/src/pkg/syscall/zerrors_freebsd_386.go +++ b/src/pkg/syscall/zerrors_freebsd_386.go @@ -9,1013 +9,1228 @@ package syscall // Constants const ( - AF_APPLETALK = 0x10 - AF_ARP = 0x23 - AF_ATM = 0x1e - AF_BLUETOOTH = 0x24 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1a - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1c - AF_IPX = 0x17 - AF_ISDN = 0x1a - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x26 - AF_NATM = 0x1d - AF_NETBIOS = 0x6 - AF_NETGRAPH = 0x20 - AF_OSI = 0x7 - AF_PUP = 0x4 - AF_ROUTE = 0x11 - AF_SCLUSTER = 0x22 - AF_SIP = 0x18 - AF_SLOW = 0x21 - AF_SNA = 0xb - AF_UNIX = 0x1 - AF_UNSPEC = 0 - AF_VENDOR00 = 0x27 - AF_VENDOR01 = 0x29 - AF_VENDOR02 = 0x2b - AF_VENDOR03 = 0x2d - AF_VENDOR04 = 0x2f - AF_VENDOR05 = 0x31 - AF_VENDOR06 = 0x33 - AF_VENDOR07 = 0x35 - AF_VENDOR08 = 0x37 - AF_VENDOR09 = 0x39 - AF_VENDOR10 = 0x3b - AF_VENDOR11 = 0x3d - AF_VENDOR12 = 0x3f - AF_VENDOR13 = 0x41 - AF_VENDOR14 = 0x43 - AF_VENDOR15 = 0x45 - AF_VENDOR16 = 0x47 - AF_VENDOR17 = 0x49 - AF_VENDOR18 = 0x4b - AF_VENDOR19 = 0x4d - AF_VENDOR20 = 0x4f - AF_VENDOR21 = 0x51 - AF_VENDOR22 = 0x53 - AF_VENDOR23 = 0x55 - AF_VENDOR24 = 0x57 - AF_VENDOR25 = 0x59 - AF_VENDOR26 = 0x5b - AF_VENDOR27 = 0x5d - AF_VENDOR28 = 0x5f - AF_VENDOR29 = 0x61 - AF_VENDOR30 = 0x63 - AF_VENDOR31 = 0x65 - AF_VENDOR32 = 0x67 - AF_VENDOR33 = 0x69 - AF_VENDOR34 = 0x6b - AF_VENDOR35 = 0x6d - AF_VENDOR36 = 0x6f - AF_VENDOR37 = 0x71 - AF_VENDOR38 = 0x73 - AF_VENDOR39 = 0x75 - AF_VENDOR40 = 0x77 - AF_VENDOR41 = 0x79 - AF_VENDOR42 = 0x7b - AF_VENDOR43 = 0x7d - AF_VENDOR44 = 0x7f - AF_VENDOR45 = 0x81 - AF_VENDOR46 = 0x83 - AF_VENDOR47 = 0x85 - BIOCFEEDBACK = 0x8004427c - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDIRECTION = 0x40044276 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc0084279 - BIOCGETBUFMODE = 0x4004427d - BIOCGETIF = 0x4020426b - BIOCGETZMAX = 0x4004427f - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4008426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCLOCK = 0x2000427a - BIOCPROMISC = 0x20004269 - BIOCROTZBUF = 0x400c4280 - BIOCSBLEN = 0xc0044266 - BIOCSDIRECTION = 0x80044277 - BIOCSDLT = 0x80044278 - BIOCSETBUFMODE = 0x8004427e - BIOCSETF = 0x80084267 - BIOCSETFNR = 0x80084282 - BIOCSETIF = 0x8020426c - BIOCSETWF = 0x8008427b - BIOCSETZBUF = 0x800c4281 - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8008426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0 - BPF_ALIGNMENT = 0x4 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_BUFMODE_BUFFER = 0x1 - BPF_BUFMODE_ZBUF = 0x2 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0 - BPF_IND = 0x40 - BPF_JA = 0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0 - BPF_LD = 0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0 - BPF_TXA = 0x80 - BPF_W = 0 - BPF_X = 0x8 - CTL_MAXNAME = 0x18 - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DOCSIS = 0x8f - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_NULL = 0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x79 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_LINUX = 0xbd - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - E2BIG = 0x7 - EACCES = 0xd - EADDRINUSE = 0x30 - EADDRNOTAVAIL = 0x31 - EAFNOSUPPORT = 0x2f - EAGAIN = 0x23 - EALREADY = 0x25 - EAUTH = 0x50 - EBADF = 0x9 - EBADMSG = 0x59 - EBADRPC = 0x48 - EBUSY = 0x10 - ECANCELED = 0x55 - ECHILD = 0xa - ECONNABORTED = 0x35 - ECONNREFUSED = 0x3d - ECONNRESET = 0x36 - EDEADLK = 0xb - EDESTADDRREQ = 0x27 - EDOM = 0x21 - EDOOFUS = 0x58 - EDQUOT = 0x45 - EEXIST = 0x11 - EFAULT = 0xe - EFBIG = 0x1b - EFTYPE = 0x4f - EHOSTDOWN = 0x40 - EHOSTUNREACH = 0x41 - EIDRM = 0x52 - EILSEQ = 0x56 - EINPROGRESS = 0x24 - EINTR = 0x4 - EINVAL = 0x16 - EIO = 0x5 - EISCONN = 0x38 - EISDIR = 0x15 - ELAST = 0x5d - ELOOP = 0x3e - EMFILE = 0x18 - EMLINK = 0x1f - EMSGSIZE = 0x28 - EMULTIHOP = 0x5a - ENAMETOOLONG = 0x3f - ENEEDAUTH = 0x51 - ENETDOWN = 0x32 - ENETRESET = 0x34 - ENETUNREACH = 0x33 - ENFILE = 0x17 - ENOATTR = 0x57 - ENOBUFS = 0x37 - ENODEV = 0x13 - ENOENT = 0x2 - ENOEXEC = 0x8 - ENOLCK = 0x4d - ENOLINK = 0x5b - ENOMEM = 0xc - ENOMSG = 0x53 - ENOPROTOOPT = 0x2a - ENOSPC = 0x1c - ENOSYS = 0x4e - ENOTBLK = 0xf - ENOTCAPABLE = 0x5d - ENOTCONN = 0x39 - ENOTDIR = 0x14 - ENOTEMPTY = 0x42 - ENOTSOCK = 0x26 - ENOTSUP = 0x2d - ENOTTY = 0x19 - ENXIO = 0x6 - EOPNOTSUPP = 0x2d - EOVERFLOW = 0x54 - EPERM = 0x1 - EPFNOSUPPORT = 0x2e - EPIPE = 0x20 - EPROCLIM = 0x43 - EPROCUNAVAIL = 0x4c - EPROGMISMATCH = 0x4b - EPROGUNAVAIL = 0x4a - EPROTO = 0x5c - EPROTONOSUPPORT = 0x2b - EPROTOTYPE = 0x29 - ERANGE = 0x22 - EREMOTE = 0x47 - EROFS = 0x1e - ERPCMISMATCH = 0x49 - ESHUTDOWN = 0x3a - ESOCKTNOSUPPORT = 0x2c - ESPIPE = 0x1d - ESRCH = 0x3 - ESTALE = 0x46 - ETIMEDOUT = 0x3c - ETOOMANYREFS = 0x3b - ETXTBSY = 0x1a - EUSERS = 0x44 - EVFILT_AIO = -0x3 - EVFILT_FS = -0x9 - EVFILT_LIO = -0xa - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xb - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xb - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EWOULDBLOCK = 0x23 - EXDEV = 0x12 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - F_CANCEL = 0x5 - F_DUP2FD = 0xa - F_DUPFD = 0 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0xb - F_GETOWN = 0x5 - F_OGETLK = 0x7 - F_OSETLK = 0x8 - F_OSETLKW = 0x9 - F_RDAHEAD = 0x10 - F_RDLCK = 0x1 - F_READAHEAD = 0xf - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0xc - F_SETLKW = 0xd - F_SETLK_REMOTE = 0xe - F_SETOWN = 0x6 - F_UNLCK = 0x2 - F_UNLCKSYS = 0x4 - F_WRLCK = 0x3 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_CANTCHANGE = 0x208f72 - IFF_DEBUG = 0x4 - IFF_DRV_OACTIVE = 0x400 - IFF_DRV_RUNNING = 0x40 - IFF_DYING = 0x200000 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MONITOR = 0x40000 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PPROMISC = 0x20000 - IFF_PROMISC = 0x100 - IFF_RENAMING = 0x400000 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_SMART = 0x20 - IFF_STATICARP = 0x80000 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CARP = 0x70 - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0x102 - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MOBILE = 0x37 - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OLD_DIVERT = 0xfe - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PFSYNC = 0xf0 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SKIP = 0x39 - IPPROTO_SPACER = 0x7fff - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TLSP = 0x38 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_AUTOFLOWLABEL = 0x3b - IPV6_BINDANY = 0x40 - IPV6_BINDV6ONLY = 0x1b - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_DONTFRAG = 0x3e - IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FRAGTTL = 0x78 - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_HOPLIMIT = 0x2f - IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MSFILTER = 0x4a - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_NEXTHOP = 0x30 - IPV6_PATHMTU = 0x2c - IPV6_PKTINFO = 0x2e - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_PREFER_TEMPADDR = 0x3f - IPV6_RECVDSTOPTS = 0x28 - IPV6_RECVHOPLIMIT = 0x25 - IPV6_RECVHOPOPTS = 0x27 - IPV6_RECVPATHMTU = 0x2b - IPV6_RECVPKTINFO = 0x24 - IPV6_RECVRTHDR = 0x26 - IPV6_RECVTCLASS = 0x39 - IPV6_RTHDR = 0x33 - IPV6_RTHDRDSTOPTS = 0x23 - IPV6_RTHDR_LOOSE = 0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x3d - IPV6_UNICAST_HOPS = 0x4 - IPV6_USE_MIN_MTU = 0x2a - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BINDANY = 0x18 - IP_BLOCK_SOURCE = 0x48 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DONTFRAG = 0x43 - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET3 = 0x31 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW3 = 0x30 - IP_FW_ADD = 0x32 - IP_FW_DEL = 0x33 - IP_FW_FLUSH = 0x34 - IP_FW_GET = 0x36 - IP_FW_NAT_CFG = 0x38 - IP_FW_NAT_DEL = 0x39 - IP_FW_NAT_GET_CONFIG = 0x3a - IP_FW_NAT_GET_LOG = 0x3b - IP_FW_RESETLOG = 0x37 - IP_FW_TABLE_ADD = 0x28 - IP_FW_TABLE_DEL = 0x29 - IP_FW_TABLE_FLUSH = 0x2a - IP_FW_TABLE_GETSIZE = 0x2b - IP_FW_TABLE_LIST = 0x2c - IP_FW_ZERO = 0x35 - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MAX_SOURCE_FILTER = 0x400 - IP_MF = 0x2000 - IP_MINTTL = 0x42 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_OFFMASK = 0x1fff - IP_ONESBCAST = 0x17 - IP_OPTIONS = 0x1 - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVRETOPTS = 0x6 - IP_RECVTTL = 0x41 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_SENDSRCADDR = 0x7 - IP_TOS = 0x3 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - MSG_COMPAT = 0x8000 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_NBIO = 0x4000 - MSG_NOSIGNAL = 0x20000 - MSG_NOTIFICATION = 0x2000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - NET_RT_DUMP = 0x1 - NET_RT_FLAGS = 0x2 - NET_RT_IFLIST = 0x3 - NET_RT_IFMALIST = 0x4 - NET_RT_MAXID = 0x5 - O_ACCMODE = 0x3 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CREAT = 0x200 - O_DIRECT = 0x10000 - O_DIRECTORY = 0x20000 - O_EXCL = 0x800 - O_EXEC = 0x40000 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x8000 - O_NOFOLLOW = 0x100 - O_NONBLOCK = 0x4 - O_RDONLY = 0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_TTY_INIT = 0x80000 - O_WRONLY = 0x1 - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_FMASK = 0x1004d808 - RTF_GATEWAY = 0x2 - RTF_HOST = 0x4 - RTF_LLDATA = 0x400 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_REJECT = 0x8 - RTF_RNH_LOCKED = 0x40000000 - RTF_STATIC = 0x800 - RTF_STICKY = 0x10000000 - RTF_UP = 0x1 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_IEEE80211 = 0x12 - RTM_IFANNOUNCE = 0x11 - RTM_IFINFO = 0xe - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RTV_WEIGHT = 0x100 - SCM_BINTIME = 0x4 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SHUT_RD = 0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIGABRT = 0x6 - SIGALRM = 0xe - SIGBUS = 0xa - SIGCHLD = 0x14 - SIGCONT = 0x13 - SIGEMT = 0x7 - SIGFPE = 0x8 - SIGHUP = 0x1 - SIGILL = 0x4 - SIGINFO = 0x1d - SIGINT = 0x2 - SIGIO = 0x17 - SIGIOT = 0x6 - SIGKILL = 0x9 - SIGLWP = 0x20 - SIGPIPE = 0xd - SIGPROF = 0x1b - SIGQUIT = 0x3 - SIGSEGV = 0xb - SIGSTOP = 0x11 - SIGSYS = 0xc - SIGTERM = 0xf - SIGTHR = 0x20 - SIGTRAP = 0x5 - SIGTSTP = 0x12 - SIGTTIN = 0x15 - SIGTTOU = 0x16 - SIGURG = 0x10 - SIGUSR1 = 0x1e - SIGUSR2 = 0x1f - SIGVTALRM = 0x1a - SIGWINCH = 0x1c - SIGXCPU = 0x18 - SIGXFSZ = 0x19 - SIOCADDMULTI = 0x80206931 - SIOCADDRT = 0x8030720a - SIOCAIFADDR = 0x8040691a - SIOCAIFGROUP = 0x80246987 - SIOCALIFADDR = 0x8118691b - SIOCATMARK = 0x40047307 - SIOCDELMULTI = 0x80206932 - SIOCDELRT = 0x8030720b - SIOCDIFADDR = 0x80206919 - SIOCDIFGROUP = 0x80246989 - SIOCDIFPHYADDR = 0x80206949 - SIOCDLIFADDR = 0x8118691d - SIOCGDRVSPEC = 0xc01c697b - SIOCGETSGCNT = 0xc0147210 - SIOCGETVIFCNT = 0xc014720f - SIOCGHIWAT = 0x40047301 - SIOCGIFADDR = 0xc0206921 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020691f - SIOCGIFCONF = 0xc0086924 - SIOCGIFDESCR = 0xc020692a - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFGENERIC = 0xc020693a - SIOCGIFGMEMB = 0xc024698a - SIOCGIFGROUP = 0xc0246988 - SIOCGIFINDEX = 0xc0206920 - SIOCGIFMAC = 0xc0206926 - SIOCGIFMEDIA = 0xc0286938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206948 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc0206947 - SIOCGIFSTATUS = 0xc331693b - SIOCGLIFADDR = 0xc118691c - SIOCGLIFPHYADDR = 0xc118694b - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCGPRIVATE_0 = 0xc0206950 - SIOCGPRIVATE_1 = 0xc0206951 - SIOCIFCREATE = 0xc020697a - SIOCIFCREATE2 = 0xc020697c - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc00c6978 - SIOCSDRVSPEC = 0x801c697b - SIOCSHIWAT = 0x80047300 - SIOCSIFADDR = 0x8020690c - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020691e - SIOCSIFDESCR = 0x80206929 - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206927 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNAME = 0x80206928 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x80406946 - SIOCSIFPHYS = 0x80206936 - SIOCSIFRVNET = 0xc020695b - SIOCSIFVNET = 0xc020695a - SIOCSLIFPHYADDR = 0x8118694a - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_ACCEPTFILTER = 0x1000 - SO_BINTIME = 0x2000 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1009 - SO_LINGER = 0x80 - SO_LISTENINCQLEN = 0x1013 - SO_LISTENQLEN = 0x1012 - SO_LISTENQLIMIT = 0x1011 - SO_NOSIGPIPE = 0x800 - SO_NO_DDP = 0x8000 - SO_NO_OFFLOAD = 0x4000 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1010 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_SETFIB = 0x1014 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TYPE = 0x1008 - SO_USELOOPBACK = 0x40 - TCP_CA_NAME_MAX = 0x10 - TCP_CONGESTION = 0x40 - TCP_INFO = 0x20 - TCP_MAXBURST = 0x4 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MD5SIG = 0x10 - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - WCONTINUED = 0x4 - WCOREFLAG = 0x80 - WLINUXCLONE = 0x80000000 - WNOHANG = 0x1 - WNOWAIT = 0x8 - WSTOPPED = 0x2 - WUNTRACED = 0x2 + AF_APPLETALK = 0x10 + AF_ARP = 0x23 + AF_ATM = 0x1e + AF_BLUETOOTH = 0x24 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1a + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1c + AF_IPX = 0x17 + AF_ISDN = 0x1a + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x26 + AF_NATM = 0x1d + AF_NETBIOS = 0x6 + AF_NETGRAPH = 0x20 + AF_OSI = 0x7 + AF_PUP = 0x4 + AF_ROUTE = 0x11 + AF_SCLUSTER = 0x22 + AF_SIP = 0x18 + AF_SLOW = 0x21 + AF_SNA = 0xb + AF_UNIX = 0x1 + AF_UNSPEC = 0 + AF_VENDOR00 = 0x27 + AF_VENDOR01 = 0x29 + AF_VENDOR02 = 0x2b + AF_VENDOR03 = 0x2d + AF_VENDOR04 = 0x2f + AF_VENDOR05 = 0x31 + AF_VENDOR06 = 0x33 + AF_VENDOR07 = 0x35 + AF_VENDOR08 = 0x37 + AF_VENDOR09 = 0x39 + AF_VENDOR10 = 0x3b + AF_VENDOR11 = 0x3d + AF_VENDOR12 = 0x3f + AF_VENDOR13 = 0x41 + AF_VENDOR14 = 0x43 + AF_VENDOR15 = 0x45 + AF_VENDOR16 = 0x47 + AF_VENDOR17 = 0x49 + AF_VENDOR18 = 0x4b + AF_VENDOR19 = 0x4d + AF_VENDOR20 = 0x4f + AF_VENDOR21 = 0x51 + AF_VENDOR22 = 0x53 + AF_VENDOR23 = 0x55 + AF_VENDOR24 = 0x57 + AF_VENDOR25 = 0x59 + AF_VENDOR26 = 0x5b + AF_VENDOR27 = 0x5d + AF_VENDOR28 = 0x5f + AF_VENDOR29 = 0x61 + AF_VENDOR30 = 0x63 + AF_VENDOR31 = 0x65 + AF_VENDOR32 = 0x67 + AF_VENDOR33 = 0x69 + AF_VENDOR34 = 0x6b + AF_VENDOR35 = 0x6d + AF_VENDOR36 = 0x6f + AF_VENDOR37 = 0x71 + AF_VENDOR38 = 0x73 + AF_VENDOR39 = 0x75 + AF_VENDOR40 = 0x77 + AF_VENDOR41 = 0x79 + AF_VENDOR42 = 0x7b + AF_VENDOR43 = 0x7d + AF_VENDOR44 = 0x7f + AF_VENDOR45 = 0x81 + AF_VENDOR46 = 0x83 + AF_VENDOR47 = 0x85 + BIOCFEEDBACK = 0x8004427c + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDIRECTION = 0x40044276 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc0084279 + BIOCGETBUFMODE = 0x4004427d + BIOCGETIF = 0x4020426b + BIOCGETZMAX = 0x4004427f + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4008426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCLOCK = 0x2000427a + BIOCPROMISC = 0x20004269 + BIOCROTZBUF = 0x400c4280 + BIOCSBLEN = 0xc0044266 + BIOCSDIRECTION = 0x80044277 + BIOCSDLT = 0x80044278 + BIOCSETBUFMODE = 0x8004427e + BIOCSETF = 0x80084267 + BIOCSETFNR = 0x80084282 + BIOCSETIF = 0x8020426c + BIOCSETWF = 0x8008427b + BIOCSETZBUF = 0x800c4281 + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8008426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0 + BPF_ALIGNMENT = 0x4 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_BUFMODE_BUFFER = 0x1 + BPF_BUFMODE_ZBUF = 0x2 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0 + BPF_IND = 0x40 + BPF_JA = 0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0 + BPF_LD = 0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0 + BPF_TXA = 0x80 + BPF_W = 0 + BPF_X = 0x8 + CTL_MAXNAME = 0x18 + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DOCSIS = 0x8f + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_NULL = 0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x79 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_LINUX = 0xbd + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0 + DT_WHT = 0xe + E2BIG = 0x7 + EACCES = 0xd + EADDRINUSE = 0x30 + EADDRNOTAVAIL = 0x31 + EAFNOSUPPORT = 0x2f + EAGAIN = 0x23 + EALREADY = 0x25 + EAUTH = 0x50 + EBADF = 0x9 + EBADMSG = 0x59 + EBADRPC = 0x48 + EBUSY = 0x10 + ECANCELED = 0x55 + ECHILD = 0xa + ECONNABORTED = 0x35 + ECONNREFUSED = 0x3d + ECONNRESET = 0x36 + EDEADLK = 0xb + EDESTADDRREQ = 0x27 + EDOM = 0x21 + EDOOFUS = 0x58 + EDQUOT = 0x45 + EEXIST = 0x11 + EFAULT = 0xe + EFBIG = 0x1b + EFTYPE = 0x4f + EHOSTDOWN = 0x40 + EHOSTUNREACH = 0x41 + EIDRM = 0x52 + EILSEQ = 0x56 + EINPROGRESS = 0x24 + EINTR = 0x4 + EINVAL = 0x16 + EIO = 0x5 + EISCONN = 0x38 + EISDIR = 0x15 + ELAST = 0x5d + ELOOP = 0x3e + EMFILE = 0x18 + EMLINK = 0x1f + EMSGSIZE = 0x28 + EMULTIHOP = 0x5a + ENAMETOOLONG = 0x3f + ENEEDAUTH = 0x51 + ENETDOWN = 0x32 + ENETRESET = 0x34 + ENETUNREACH = 0x33 + ENFILE = 0x17 + ENOATTR = 0x57 + ENOBUFS = 0x37 + ENODEV = 0x13 + ENOENT = 0x2 + ENOEXEC = 0x8 + ENOLCK = 0x4d + ENOLINK = 0x5b + ENOMEM = 0xc + ENOMSG = 0x53 + ENOPROTOOPT = 0x2a + ENOSPC = 0x1c + ENOSYS = 0x4e + ENOTBLK = 0xf + ENOTCAPABLE = 0x5d + ENOTCONN = 0x39 + ENOTDIR = 0x14 + ENOTEMPTY = 0x42 + ENOTSOCK = 0x26 + ENOTSUP = 0x2d + ENOTTY = 0x19 + ENXIO = 0x6 + EOPNOTSUPP = 0x2d + EOVERFLOW = 0x54 + EPERM = 0x1 + EPFNOSUPPORT = 0x2e + EPIPE = 0x20 + EPROCLIM = 0x43 + EPROCUNAVAIL = 0x4c + EPROGMISMATCH = 0x4b + EPROGUNAVAIL = 0x4a + EPROTO = 0x5c + EPROTONOSUPPORT = 0x2b + EPROTOTYPE = 0x29 + ERANGE = 0x22 + EREMOTE = 0x47 + EROFS = 0x1e + ERPCMISMATCH = 0x49 + ESHUTDOWN = 0x3a + ESOCKTNOSUPPORT = 0x2c + ESPIPE = 0x1d + ESRCH = 0x3 + ESTALE = 0x46 + ETIMEDOUT = 0x3c + ETOOMANYREFS = 0x3b + ETXTBSY = 0x1a + EUSERS = 0x44 + EVFILT_AIO = -0x3 + EVFILT_FS = -0x9 + EVFILT_LIO = -0xa + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0xb + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xb + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EWOULDBLOCK = 0x23 + EXDEV = 0x12 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + F_CANCEL = 0x5 + F_DUP2FD = 0xa + F_DUPFD = 0 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0xb + F_GETOWN = 0x5 + F_OGETLK = 0x7 + F_OSETLK = 0x8 + F_OSETLKW = 0x9 + F_RDAHEAD = 0x10 + F_RDLCK = 0x1 + F_READAHEAD = 0xf + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0xc + F_SETLKW = 0xd + F_SETLK_REMOTE = 0xe + F_SETOWN = 0x6 + F_UNLCK = 0x2 + F_UNLCKSYS = 0x4 + F_WRLCK = 0x3 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_CANTCHANGE = 0x208f72 + IFF_DEBUG = 0x4 + IFF_DRV_OACTIVE = 0x400 + IFF_DRV_RUNNING = 0x40 + IFF_DYING = 0x200000 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MONITOR = 0x40000 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PPROMISC = 0x20000 + IFF_PROMISC = 0x100 + IFF_RENAMING = 0x400000 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_SMART = 0x20 + IFF_STATICARP = 0x80000 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_A12MPPSWITCH = 0x82 + IFT_AAL2 = 0xbb + IFT_AAL5 = 0x31 + IFT_ADSL = 0x5e + IFT_AFLANE8023 = 0x3b + IFT_AFLANE8025 = 0x3c + IFT_ARAP = 0x58 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ASYNC = 0x54 + IFT_ATM = 0x25 + IFT_ATMDXI = 0x69 + IFT_ATMFUNI = 0x6a + IFT_ATMIMA = 0x6b + IFT_ATMLOGICAL = 0x50 + IFT_ATMRADIO = 0xbd + IFT_ATMSUBINTERFACE = 0x86 + IFT_ATMVCIENDPT = 0xc2 + IFT_ATMVIRTUAL = 0x95 + IFT_BGPPOLICYACCOUNTING = 0xa2 + IFT_BRIDGE = 0xd1 + IFT_BSC = 0x53 + IFT_CARP = 0xf8 + IFT_CCTEMUL = 0x3d + IFT_CEPT = 0x13 + IFT_CES = 0x85 + IFT_CHANNEL = 0x46 + IFT_CNR = 0x55 + IFT_COFFEE = 0x84 + IFT_COMPOSITELINK = 0x9b + IFT_DCN = 0x8d + IFT_DIGITALPOWERLINE = 0x8a + IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba + IFT_DLSW = 0x4a + IFT_DOCSCABLEDOWNSTREAM = 0x80 + IFT_DOCSCABLEMACLAYER = 0x7f + IFT_DOCSCABLEUPSTREAM = 0x81 + IFT_DS0 = 0x51 + IFT_DS0BUNDLE = 0x52 + IFT_DS1FDL = 0xaa + IFT_DS3 = 0x1e + IFT_DTM = 0x8c + IFT_DVBASILN = 0xac + IFT_DVBASIOUT = 0xad + IFT_DVBRCCDOWNSTREAM = 0x93 + IFT_DVBRCCMACLAYER = 0x92 + IFT_DVBRCCUPSTREAM = 0x94 + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_EPLRS = 0x57 + IFT_ESCON = 0x49 + IFT_ETHER = 0x6 + IFT_FAITH = 0xf2 + IFT_FAST = 0x7d + IFT_FASTETHER = 0x3e + IFT_FASTETHERFX = 0x45 + IFT_FDDI = 0xf + IFT_FIBRECHANNEL = 0x38 + IFT_FRAMERELAYINTERCONNECT = 0x3a + IFT_FRAMERELAYMPI = 0x5c + IFT_FRDLCIENDPT = 0xc1 + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_FRF16MFRBUNDLE = 0xa3 + IFT_FRFORWARD = 0x9e + IFT_G703AT2MB = 0x43 + IFT_G703AT64K = 0x42 + IFT_GIF = 0xf0 + IFT_GIGABITETHERNET = 0x75 + IFT_GR303IDT = 0xb2 + IFT_GR303RDT = 0xb1 + IFT_H323GATEKEEPER = 0xa4 + IFT_H323PROXY = 0xa5 + IFT_HDH1822 = 0x3 + IFT_HDLC = 0x76 + IFT_HDSL2 = 0xa8 + IFT_HIPERLAN2 = 0xb7 + IFT_HIPPI = 0x2f + IFT_HIPPIINTERFACE = 0x39 + IFT_HOSTPAD = 0x5a + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IBM370PARCHAN = 0x48 + IFT_IDSL = 0x9a + IFT_IEEE1394 = 0x90 + IFT_IEEE80211 = 0x47 + IFT_IEEE80212 = 0x37 + IFT_IEEE8023ADLAG = 0xa1 + IFT_IFGSN = 0x91 + IFT_IMT = 0xbe + IFT_INTERLEAVE = 0x7c + IFT_IP = 0x7e + IFT_IPFORWARD = 0x8e + IFT_IPOVERATM = 0x72 + IFT_IPOVERCDLC = 0x6d + IFT_IPOVERCLAW = 0x6e + IFT_IPSWITCH = 0x4e + IFT_IPXIP = 0xf9 + IFT_ISDN = 0x3f + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISDNS = 0x4b + IFT_ISDNU = 0x4c + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88025CRFPINT = 0x62 + IFT_ISO88025DTR = 0x56 + IFT_ISO88025FIBER = 0x73 + IFT_ISO88026 = 0xa + IFT_ISUP = 0xb3 + IFT_L2VLAN = 0x87 + IFT_L3IPVLAN = 0x88 + IFT_L3IPXVLAN = 0x89 + IFT_LAPB = 0x10 + IFT_LAPD = 0x4d + IFT_LAPF = 0x77 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MEDIAMAILOVERIP = 0x8b + IFT_MFSIGLINK = 0xa7 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_MPC = 0x71 + IFT_MPLS = 0xa6 + IFT_MPLSTUNNEL = 0x96 + IFT_MSDSL = 0x8f + IFT_MVL = 0xbf + IFT_MYRINET = 0x63 + IFT_NFAS = 0xaf + IFT_NSIP = 0x1b + IFT_OPTICALCHANNEL = 0xc3 + IFT_OPTICALTRANSPORT = 0xc4 + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PFLOG = 0xf6 + IFT_PFSYNC = 0xf7 + IFT_PLC = 0xae + IFT_POS = 0xab + IFT_PPP = 0x17 + IFT_PPPMULTILINKBUNDLE = 0x6c + IFT_PROPBWAP2MP = 0xb8 + IFT_PROPCNLS = 0x59 + IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 + IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 + IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PROPWIRELESSP2P = 0x9d + IFT_PTPSERIAL = 0x16 + IFT_PVC = 0xf1 + IFT_QLLC = 0x44 + IFT_RADIOMAC = 0xbc + IFT_RADSL = 0x5f + IFT_REACHDSL = 0xc0 + IFT_RFC1483 = 0x9f + IFT_RS232 = 0x21 + IFT_RSRB = 0x4f + IFT_SDLC = 0x11 + IFT_SDSL = 0x60 + IFT_SHDSL = 0xa9 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETOVERHEADCHANNEL = 0xb9 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_SRP = 0x97 + IFT_SS7SIGLINK = 0x9c + IFT_STACKTOSTACK = 0x6f + IFT_STARLAN = 0xb + IFT_STF = 0xd7 + IFT_T1 = 0x12 + IFT_TDLC = 0x74 + IFT_TERMPAD = 0x5b + IFT_TR008 = 0xb0 + IFT_TRANSPHDLC = 0x7b + IFT_TUNNEL = 0x83 + IFT_ULTRA = 0x1d + IFT_USB = 0xa0 + IFT_V11 = 0x40 + IFT_V35 = 0x2d + IFT_V36 = 0x41 + IFT_V37 = 0x78 + IFT_VDSL = 0x61 + IFT_VIRTUALIPADDRESS = 0x70 + IFT_VOICEEM = 0x64 + IFT_VOICEENCAP = 0x67 + IFT_VOICEFXO = 0x65 + IFT_VOICEFXS = 0x66 + IFT_VOICEOVERATM = 0x98 + IFT_VOICEOVERFRAMERELAY = 0x99 + IFT_VOICEOVERIP = 0x68 + IFT_X213 = 0x5d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25HUNTGROUP = 0x7a + IFT_X25MLP = 0x79 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LOOPBACKNET = 0x7f + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CARP = 0x70 + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0x102 + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MOBILE = 0x37 + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OLD_DIVERT = 0xfe + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PFSYNC = 0xf0 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SKIP = 0x39 + IPPROTO_SPACER = 0x7fff + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TLSP = 0x38 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDANY = 0x40 + IPV6_BINDV6ONLY = 0x1b + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FRAGTTL = 0x78 + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x24 + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x39 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x23 + IPV6_RTHDR_LOOSE = 0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x3d + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BINDANY = 0x18 + IP_BLOCK_SOURCE = 0x48 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x43 + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET3 = 0x31 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW3 = 0x30 + IP_FW_ADD = 0x32 + IP_FW_DEL = 0x33 + IP_FW_FLUSH = 0x34 + IP_FW_GET = 0x36 + IP_FW_NAT_CFG = 0x38 + IP_FW_NAT_DEL = 0x39 + IP_FW_NAT_GET_CONFIG = 0x3a + IP_FW_NAT_GET_LOG = 0x3b + IP_FW_RESETLOG = 0x37 + IP_FW_TABLE_ADD = 0x28 + IP_FW_TABLE_DEL = 0x29 + IP_FW_TABLE_FLUSH = 0x2a + IP_FW_TABLE_GETSIZE = 0x2b + IP_FW_TABLE_LIST = 0x2c + IP_FW_ZERO = 0x35 + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MAX_SOURCE_FILTER = 0x400 + IP_MF = 0x2000 + IP_MINTTL = 0x42 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_OFFMASK = 0x1fff + IP_ONESBCAST = 0x17 + IP_OPTIONS = 0x1 + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVRETOPTS = 0x6 + IP_RECVTTL = 0x41 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_SENDSRCADDR = 0x7 + IP_TOS = 0x3 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + MSG_COMPAT = 0x8000 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_NBIO = 0x4000 + MSG_NOSIGNAL = 0x20000 + MSG_NOTIFICATION = 0x2000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + NET_RT_DUMP = 0x1 + NET_RT_FLAGS = 0x2 + NET_RT_IFLIST = 0x3 + NET_RT_IFMALIST = 0x4 + NET_RT_MAXID = 0x5 + O_ACCMODE = 0x3 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CREAT = 0x200 + O_DIRECT = 0x10000 + O_DIRECTORY = 0x20000 + O_EXCL = 0x800 + O_EXEC = 0x40000 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x8000 + O_NOFOLLOW = 0x100 + O_NONBLOCK = 0x4 + O_RDONLY = 0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_TTY_INIT = 0x80000 + O_WRONLY = 0x1 + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_FMASK = 0x1004d808 + RTF_GATEWAY = 0x2 + RTF_HOST = 0x4 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_REJECT = 0x8 + RTF_RNH_LOCKED = 0x40000000 + RTF_STATIC = 0x800 + RTF_STICKY = 0x10000000 + RTF_UP = 0x1 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_IEEE80211 = 0x12 + RTM_IFANNOUNCE = 0x11 + RTM_IFINFO = 0xe + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RTV_WEIGHT = 0x100 + SCM_BINTIME = 0x4 + SCM_CREDS = 0x3 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SHUT_RD = 0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIGABRT = 0x6 + SIGALRM = 0xe + SIGBUS = 0xa + SIGCHLD = 0x14 + SIGCONT = 0x13 + SIGEMT = 0x7 + SIGFPE = 0x8 + SIGHUP = 0x1 + SIGILL = 0x4 + SIGINFO = 0x1d + SIGINT = 0x2 + SIGIO = 0x17 + SIGIOT = 0x6 + SIGKILL = 0x9 + SIGLWP = 0x20 + SIGPIPE = 0xd + SIGPROF = 0x1b + SIGQUIT = 0x3 + SIGSEGV = 0xb + SIGSTOP = 0x11 + SIGSYS = 0xc + SIGTERM = 0xf + SIGTHR = 0x20 + SIGTRAP = 0x5 + SIGTSTP = 0x12 + SIGTTIN = 0x15 + SIGTTOU = 0x16 + SIGURG = 0x10 + SIGUSR1 = 0x1e + SIGUSR2 = 0x1f + SIGVTALRM = 0x1a + SIGWINCH = 0x1c + SIGXCPU = 0x18 + SIGXFSZ = 0x19 + SIOCADDMULTI = 0x80206931 + SIOCADDRT = 0x8030720a + SIOCAIFADDR = 0x8040691a + SIOCAIFGROUP = 0x80246987 + SIOCALIFADDR = 0x8118691b + SIOCATMARK = 0x40047307 + SIOCDELMULTI = 0x80206932 + SIOCDELRT = 0x8030720b + SIOCDIFADDR = 0x80206919 + SIOCDIFGROUP = 0x80246989 + SIOCDIFPHYADDR = 0x80206949 + SIOCDLIFADDR = 0x8118691d + SIOCGDRVSPEC = 0xc01c697b + SIOCGETSGCNT = 0xc0147210 + SIOCGETVIFCNT = 0xc014720f + SIOCGHIWAT = 0x40047301 + SIOCGIFADDR = 0xc0206921 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020691f + SIOCGIFCONF = 0xc0086924 + SIOCGIFDESCR = 0xc020692a + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFGENERIC = 0xc020693a + SIOCGIFGMEMB = 0xc024698a + SIOCGIFGROUP = 0xc0246988 + SIOCGIFINDEX = 0xc0206920 + SIOCGIFMAC = 0xc0206926 + SIOCGIFMEDIA = 0xc0286938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206948 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc0206947 + SIOCGIFSTATUS = 0xc331693b + SIOCGLIFADDR = 0xc118691c + SIOCGLIFPHYADDR = 0xc118694b + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCGPRIVATE_0 = 0xc0206950 + SIOCGPRIVATE_1 = 0xc0206951 + SIOCIFCREATE = 0xc020697a + SIOCIFCREATE2 = 0xc020697c + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc00c6978 + SIOCSDRVSPEC = 0x801c697b + SIOCSHIWAT = 0x80047300 + SIOCSIFADDR = 0x8020690c + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020691e + SIOCSIFDESCR = 0x80206929 + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206927 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNAME = 0x80206928 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x80406946 + SIOCSIFPHYS = 0x80206936 + SIOCSIFRVNET = 0xc020695b + SIOCSIFVNET = 0xc020695a + SIOCSLIFPHYADDR = 0x8118694a + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_ACCEPTFILTER = 0x1000 + SO_BINTIME = 0x2000 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1009 + SO_LINGER = 0x80 + SO_LISTENINCQLEN = 0x1013 + SO_LISTENQLEN = 0x1012 + SO_LISTENQLIMIT = 0x1011 + SO_NOSIGPIPE = 0x800 + SO_NO_DDP = 0x8000 + SO_NO_OFFLOAD = 0x4000 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1010 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_SETFIB = 0x1014 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TYPE = 0x1008 + SO_USELOOPBACK = 0x40 + TCP_CA_NAME_MAX = 0x10 + TCP_CONGESTION = 0x40 + TCP_INFO = 0x20 + TCP_MAXBURST = 0x4 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MD5SIG = 0x10 + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + WCONTINUED = 0x4 + WCOREFLAG = 0x80 + WLINUXCLONE = 0x80000000 + WNOHANG = 0x1 + WNOWAIT = 0x8 + WSTOPPED = 0x2 + WUNTRACED = 0x2 ) // Types diff --git a/src/pkg/syscall/zerrors_freebsd_amd64.go b/src/pkg/syscall/zerrors_freebsd_amd64.go index 33fd3de1f..9b632ba93 100644 --- a/src/pkg/syscall/zerrors_freebsd_amd64.go +++ b/src/pkg/syscall/zerrors_freebsd_amd64.go @@ -9,1013 +9,1228 @@ package syscall // Constants const ( - AF_APPLETALK = 0x10 - AF_ARP = 0x23 - AF_ATM = 0x1e - AF_BLUETOOTH = 0x24 - AF_CCITT = 0xa - AF_CHAOS = 0x5 - AF_CNT = 0x15 - AF_COIP = 0x14 - AF_DATAKIT = 0x9 - AF_DECnet = 0xc - AF_DLI = 0xd - AF_E164 = 0x1a - AF_ECMA = 0x8 - AF_HYLINK = 0xf - AF_IEEE80211 = 0x25 - AF_IMPLINK = 0x3 - AF_INET = 0x2 - AF_INET6 = 0x1c - AF_IPX = 0x17 - AF_ISDN = 0x1a - AF_ISO = 0x7 - AF_LAT = 0xe - AF_LINK = 0x12 - AF_LOCAL = 0x1 - AF_MAX = 0x26 - AF_NATM = 0x1d - AF_NETBIOS = 0x6 - AF_NETGRAPH = 0x20 - AF_OSI = 0x7 - AF_PUP = 0x4 - AF_ROUTE = 0x11 - AF_SCLUSTER = 0x22 - AF_SIP = 0x18 - AF_SLOW = 0x21 - AF_SNA = 0xb - AF_UNIX = 0x1 - AF_UNSPEC = 0 - AF_VENDOR00 = 0x27 - AF_VENDOR01 = 0x29 - AF_VENDOR02 = 0x2b - AF_VENDOR03 = 0x2d - AF_VENDOR04 = 0x2f - AF_VENDOR05 = 0x31 - AF_VENDOR06 = 0x33 - AF_VENDOR07 = 0x35 - AF_VENDOR08 = 0x37 - AF_VENDOR09 = 0x39 - AF_VENDOR10 = 0x3b - AF_VENDOR11 = 0x3d - AF_VENDOR12 = 0x3f - AF_VENDOR13 = 0x41 - AF_VENDOR14 = 0x43 - AF_VENDOR15 = 0x45 - AF_VENDOR16 = 0x47 - AF_VENDOR17 = 0x49 - AF_VENDOR18 = 0x4b - AF_VENDOR19 = 0x4d - AF_VENDOR20 = 0x4f - AF_VENDOR21 = 0x51 - AF_VENDOR22 = 0x53 - AF_VENDOR23 = 0x55 - AF_VENDOR24 = 0x57 - AF_VENDOR25 = 0x59 - AF_VENDOR26 = 0x5b - AF_VENDOR27 = 0x5d - AF_VENDOR28 = 0x5f - AF_VENDOR29 = 0x61 - AF_VENDOR30 = 0x63 - AF_VENDOR31 = 0x65 - AF_VENDOR32 = 0x67 - AF_VENDOR33 = 0x69 - AF_VENDOR34 = 0x6b - AF_VENDOR35 = 0x6d - AF_VENDOR36 = 0x6f - AF_VENDOR37 = 0x71 - AF_VENDOR38 = 0x73 - AF_VENDOR39 = 0x75 - AF_VENDOR40 = 0x77 - AF_VENDOR41 = 0x79 - AF_VENDOR42 = 0x7b - AF_VENDOR43 = 0x7d - AF_VENDOR44 = 0x7f - AF_VENDOR45 = 0x81 - AF_VENDOR46 = 0x83 - AF_VENDOR47 = 0x85 - BIOCFEEDBACK = 0x8004427c - BIOCFLUSH = 0x20004268 - BIOCGBLEN = 0x40044266 - BIOCGDIRECTION = 0x40044276 - BIOCGDLT = 0x4004426a - BIOCGDLTLIST = 0xc0104279 - BIOCGETBUFMODE = 0x4004427d - BIOCGETIF = 0x4020426b - BIOCGETZMAX = 0x4008427f - BIOCGHDRCMPLT = 0x40044274 - BIOCGRSIG = 0x40044272 - BIOCGRTIMEOUT = 0x4010426e - BIOCGSEESENT = 0x40044276 - BIOCGSTATS = 0x4008426f - BIOCIMMEDIATE = 0x80044270 - BIOCLOCK = 0x2000427a - BIOCPROMISC = 0x20004269 - BIOCROTZBUF = 0x40184280 - BIOCSBLEN = 0xc0044266 - BIOCSDIRECTION = 0x80044277 - BIOCSDLT = 0x80044278 - BIOCSETBUFMODE = 0x8004427e - BIOCSETF = 0x80104267 - BIOCSETFNR = 0x80104282 - BIOCSETIF = 0x8020426c - BIOCSETWF = 0x8010427b - BIOCSETZBUF = 0x80184281 - BIOCSHDRCMPLT = 0x80044275 - BIOCSRSIG = 0x80044273 - BIOCSRTIMEOUT = 0x8010426d - BIOCSSEESENT = 0x80044277 - BIOCVERSION = 0x40044271 - BPF_A = 0x10 - BPF_ABS = 0x20 - BPF_ADD = 0 - BPF_ALIGNMENT = 0x8 - BPF_ALU = 0x4 - BPF_AND = 0x50 - BPF_B = 0x10 - BPF_BUFMODE_BUFFER = 0x1 - BPF_BUFMODE_ZBUF = 0x2 - BPF_DIV = 0x30 - BPF_H = 0x8 - BPF_IMM = 0 - BPF_IND = 0x40 - BPF_JA = 0 - BPF_JEQ = 0x10 - BPF_JGE = 0x30 - BPF_JGT = 0x20 - BPF_JMP = 0x5 - BPF_JSET = 0x40 - BPF_K = 0 - BPF_LD = 0 - BPF_LDX = 0x1 - BPF_LEN = 0x80 - BPF_LSH = 0x60 - BPF_MAJOR_VERSION = 0x1 - BPF_MAXBUFSIZE = 0x80000 - BPF_MAXINSNS = 0x200 - BPF_MEM = 0x60 - BPF_MEMWORDS = 0x10 - BPF_MINBUFSIZE = 0x20 - BPF_MINOR_VERSION = 0x1 - BPF_MISC = 0x7 - BPF_MSH = 0xa0 - BPF_MUL = 0x20 - BPF_NEG = 0x80 - BPF_OR = 0x40 - BPF_RELEASE = 0x30bb6 - BPF_RET = 0x6 - BPF_RSH = 0x70 - BPF_ST = 0x2 - BPF_STX = 0x3 - BPF_SUB = 0x10 - BPF_TAX = 0 - BPF_TXA = 0x80 - BPF_W = 0 - BPF_X = 0x8 - CTL_MAXNAME = 0x18 - CTL_NET = 0x4 - DLT_A429 = 0xb8 - DLT_A653_ICM = 0xb9 - DLT_AIRONET_HEADER = 0x78 - DLT_APPLE_IP_OVER_IEEE1394 = 0x8a - DLT_ARCNET = 0x7 - DLT_ARCNET_LINUX = 0x81 - DLT_ATM_CLIP = 0x13 - DLT_ATM_RFC1483 = 0xb - DLT_AURORA = 0x7e - DLT_AX25 = 0x3 - DLT_AX25_KISS = 0xca - DLT_BACNET_MS_TP = 0xa5 - DLT_BLUETOOTH_HCI_H4 = 0xbb - DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 - DLT_CAN20B = 0xbe - DLT_CHAOS = 0x5 - DLT_CHDLC = 0x68 - DLT_CISCO_IOS = 0x76 - DLT_C_HDLC = 0x68 - DLT_C_HDLC_WITH_DIR = 0xcd - DLT_DOCSIS = 0x8f - DLT_ECONET = 0x73 - DLT_EN10MB = 0x1 - DLT_EN3MB = 0x2 - DLT_ENC = 0x6d - DLT_ERF = 0xc5 - DLT_ERF_ETH = 0xaf - DLT_ERF_POS = 0xb0 - DLT_FDDI = 0xa - DLT_FLEXRAY = 0xd2 - DLT_FRELAY = 0x6b - DLT_FRELAY_WITH_DIR = 0xce - DLT_GCOM_SERIAL = 0xad - DLT_GCOM_T1E1 = 0xac - DLT_GPF_F = 0xab - DLT_GPF_T = 0xaa - DLT_GPRS_LLC = 0xa9 - DLT_HHDLC = 0x79 - DLT_IBM_SN = 0x92 - DLT_IBM_SP = 0x91 - DLT_IEEE802 = 0x6 - DLT_IEEE802_11 = 0x69 - DLT_IEEE802_11_RADIO = 0x7f - DLT_IEEE802_11_RADIO_AVS = 0xa3 - DLT_IEEE802_15_4 = 0xc3 - DLT_IEEE802_15_4_LINUX = 0xbf - DLT_IEEE802_15_4_NONASK_PHY = 0xd7 - DLT_IEEE802_16_MAC_CPS = 0xbc - DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 - DLT_IPFILTER = 0x74 - DLT_IPMB = 0xc7 - DLT_IPMB_LINUX = 0xd1 - DLT_IP_OVER_FC = 0x7a - DLT_JUNIPER_ATM1 = 0x89 - DLT_JUNIPER_ATM2 = 0x87 - DLT_JUNIPER_CHDLC = 0xb5 - DLT_JUNIPER_ES = 0x84 - DLT_JUNIPER_ETHER = 0xb2 - DLT_JUNIPER_FRELAY = 0xb4 - DLT_JUNIPER_GGSN = 0x85 - DLT_JUNIPER_ISM = 0xc2 - DLT_JUNIPER_MFR = 0x86 - DLT_JUNIPER_MLFR = 0x83 - DLT_JUNIPER_MLPPP = 0x82 - DLT_JUNIPER_MONITOR = 0xa4 - DLT_JUNIPER_PIC_PEER = 0xae - DLT_JUNIPER_PPP = 0xb3 - DLT_JUNIPER_PPPOE = 0xa7 - DLT_JUNIPER_PPPOE_ATM = 0xa8 - DLT_JUNIPER_SERVICES = 0x88 - DLT_JUNIPER_ST = 0xc8 - DLT_JUNIPER_VP = 0xb7 - DLT_LAPB_WITH_DIR = 0xcf - DLT_LAPD = 0xcb - DLT_LIN = 0xd4 - DLT_LINUX_IRDA = 0x90 - DLT_LINUX_LAPD = 0xb1 - DLT_LINUX_PPP_WITHDIRECTION = 0xa6 - DLT_LINUX_SLL = 0x71 - DLT_LOOP = 0x6c - DLT_LTALK = 0x72 - DLT_MFR = 0xb6 - DLT_MOST = 0xd3 - DLT_MTP2 = 0x8c - DLT_MTP2_WITH_PHDR = 0x8b - DLT_MTP3 = 0x8d - DLT_NULL = 0 - DLT_PCI_EXP = 0x7d - DLT_PFLOG = 0x75 - DLT_PFSYNC = 0x79 - DLT_PPI = 0xc0 - DLT_PPP = 0x9 - DLT_PPP_BSDOS = 0x10 - DLT_PPP_ETHER = 0x33 - DLT_PPP_PPPD = 0xa6 - DLT_PPP_SERIAL = 0x32 - DLT_PPP_WITH_DIR = 0xcc - DLT_PPP_WITH_DIRECTION = 0xa6 - DLT_PRISM_HEADER = 0x77 - DLT_PRONET = 0x4 - DLT_RAIF1 = 0xc6 - DLT_RAW = 0xc - DLT_RIO = 0x7c - DLT_SCCP = 0x8e - DLT_SITA = 0xc4 - DLT_SLIP = 0x8 - DLT_SLIP_BSDOS = 0xf - DLT_SUNATM = 0x7b - DLT_SYMANTEC_FIREWALL = 0x63 - DLT_TZSP = 0x80 - DLT_USB = 0xba - DLT_USB_LINUX = 0xbd - DLT_USER0 = 0x93 - DLT_USER1 = 0x94 - DLT_USER10 = 0x9d - DLT_USER11 = 0x9e - DLT_USER12 = 0x9f - DLT_USER13 = 0xa0 - DLT_USER14 = 0xa1 - DLT_USER15 = 0xa2 - DLT_USER2 = 0x95 - DLT_USER3 = 0x96 - DLT_USER4 = 0x97 - DLT_USER5 = 0x98 - DLT_USER6 = 0x99 - DLT_USER7 = 0x9a - DLT_USER8 = 0x9b - DLT_USER9 = 0x9c - DLT_X2E_SERIAL = 0xd5 - DLT_X2E_XORAYA = 0xd6 - E2BIG = 0x7 - EACCES = 0xd - EADDRINUSE = 0x30 - EADDRNOTAVAIL = 0x31 - EAFNOSUPPORT = 0x2f - EAGAIN = 0x23 - EALREADY = 0x25 - EAUTH = 0x50 - EBADF = 0x9 - EBADMSG = 0x59 - EBADRPC = 0x48 - EBUSY = 0x10 - ECANCELED = 0x55 - ECHILD = 0xa - ECONNABORTED = 0x35 - ECONNREFUSED = 0x3d - ECONNRESET = 0x36 - EDEADLK = 0xb - EDESTADDRREQ = 0x27 - EDOM = 0x21 - EDOOFUS = 0x58 - EDQUOT = 0x45 - EEXIST = 0x11 - EFAULT = 0xe - EFBIG = 0x1b - EFTYPE = 0x4f - EHOSTDOWN = 0x40 - EHOSTUNREACH = 0x41 - EIDRM = 0x52 - EILSEQ = 0x56 - EINPROGRESS = 0x24 - EINTR = 0x4 - EINVAL = 0x16 - EIO = 0x5 - EISCONN = 0x38 - EISDIR = 0x15 - ELAST = 0x5d - ELOOP = 0x3e - EMFILE = 0x18 - EMLINK = 0x1f - EMSGSIZE = 0x28 - EMULTIHOP = 0x5a - ENAMETOOLONG = 0x3f - ENEEDAUTH = 0x51 - ENETDOWN = 0x32 - ENETRESET = 0x34 - ENETUNREACH = 0x33 - ENFILE = 0x17 - ENOATTR = 0x57 - ENOBUFS = 0x37 - ENODEV = 0x13 - ENOENT = 0x2 - ENOEXEC = 0x8 - ENOLCK = 0x4d - ENOLINK = 0x5b - ENOMEM = 0xc - ENOMSG = 0x53 - ENOPROTOOPT = 0x2a - ENOSPC = 0x1c - ENOSYS = 0x4e - ENOTBLK = 0xf - ENOTCAPABLE = 0x5d - ENOTCONN = 0x39 - ENOTDIR = 0x14 - ENOTEMPTY = 0x42 - ENOTSOCK = 0x26 - ENOTSUP = 0x2d - ENOTTY = 0x19 - ENXIO = 0x6 - EOPNOTSUPP = 0x2d - EOVERFLOW = 0x54 - EPERM = 0x1 - EPFNOSUPPORT = 0x2e - EPIPE = 0x20 - EPROCLIM = 0x43 - EPROCUNAVAIL = 0x4c - EPROGMISMATCH = 0x4b - EPROGUNAVAIL = 0x4a - EPROTO = 0x5c - EPROTONOSUPPORT = 0x2b - EPROTOTYPE = 0x29 - ERANGE = 0x22 - EREMOTE = 0x47 - EROFS = 0x1e - ERPCMISMATCH = 0x49 - ESHUTDOWN = 0x3a - ESOCKTNOSUPPORT = 0x2c - ESPIPE = 0x1d - ESRCH = 0x3 - ESTALE = 0x46 - ETIMEDOUT = 0x3c - ETOOMANYREFS = 0x3b - ETXTBSY = 0x1a - EUSERS = 0x44 - EVFILT_AIO = -0x3 - EVFILT_FS = -0x9 - EVFILT_LIO = -0xa - EVFILT_PROC = -0x5 - EVFILT_READ = -0x1 - EVFILT_SIGNAL = -0x6 - EVFILT_SYSCOUNT = 0xb - EVFILT_TIMER = -0x7 - EVFILT_USER = -0xb - EVFILT_VNODE = -0x4 - EVFILT_WRITE = -0x2 - EV_ADD = 0x1 - EV_CLEAR = 0x20 - EV_DELETE = 0x2 - EV_DISABLE = 0x8 - EV_DISPATCH = 0x80 - EV_ENABLE = 0x4 - EV_EOF = 0x8000 - EV_ERROR = 0x4000 - EV_FLAG1 = 0x2000 - EV_ONESHOT = 0x10 - EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 - EWOULDBLOCK = 0x23 - EXDEV = 0x12 - FD_CLOEXEC = 0x1 - FD_SETSIZE = 0x400 - F_CANCEL = 0x5 - F_DUP2FD = 0xa - F_DUPFD = 0 - F_GETFD = 0x1 - F_GETFL = 0x3 - F_GETLK = 0xb - F_GETOWN = 0x5 - F_OGETLK = 0x7 - F_OSETLK = 0x8 - F_OSETLKW = 0x9 - F_RDAHEAD = 0x10 - F_RDLCK = 0x1 - F_READAHEAD = 0xf - F_SETFD = 0x2 - F_SETFL = 0x4 - F_SETLK = 0xc - F_SETLKW = 0xd - F_SETLK_REMOTE = 0xe - F_SETOWN = 0x6 - F_UNLCK = 0x2 - F_UNLCKSYS = 0x4 - F_WRLCK = 0x3 - IFF_ALLMULTI = 0x200 - IFF_ALTPHYS = 0x4000 - IFF_BROADCAST = 0x2 - IFF_CANTCHANGE = 0x208f72 - IFF_DEBUG = 0x4 - IFF_DRV_OACTIVE = 0x400 - IFF_DRV_RUNNING = 0x40 - IFF_DYING = 0x200000 - IFF_LINK0 = 0x1000 - IFF_LINK1 = 0x2000 - IFF_LINK2 = 0x4000 - IFF_LOOPBACK = 0x8 - IFF_MONITOR = 0x40000 - IFF_MULTICAST = 0x8000 - IFF_NOARP = 0x80 - IFF_OACTIVE = 0x400 - IFF_POINTOPOINT = 0x10 - IFF_PPROMISC = 0x20000 - IFF_PROMISC = 0x100 - IFF_RENAMING = 0x400000 - IFF_RUNNING = 0x40 - IFF_SIMPLEX = 0x800 - IFF_SMART = 0x20 - IFF_STATICARP = 0x80000 - IFF_UP = 0x1 - IFNAMSIZ = 0x10 - IN_CLASSA_HOST = 0xffffff - IN_CLASSA_MAX = 0x80 - IN_CLASSA_NET = 0xff000000 - IN_CLASSA_NSHIFT = 0x18 - IN_CLASSB_HOST = 0xffff - IN_CLASSB_MAX = 0x10000 - IN_CLASSB_NET = 0xffff0000 - IN_CLASSB_NSHIFT = 0x10 - IN_CLASSC_HOST = 0xff - IN_CLASSC_NET = 0xffffff00 - IN_CLASSC_NSHIFT = 0x8 - IN_CLASSD_HOST = 0xfffffff - IN_CLASSD_NET = 0xf0000000 - IN_CLASSD_NSHIFT = 0x1c - IN_LOOPBACKNET = 0x7f - IPPROTO_3PC = 0x22 - IPPROTO_ADFS = 0x44 - IPPROTO_AH = 0x33 - IPPROTO_AHIP = 0x3d - IPPROTO_APES = 0x63 - IPPROTO_ARGUS = 0xd - IPPROTO_AX25 = 0x5d - IPPROTO_BHA = 0x31 - IPPROTO_BLT = 0x1e - IPPROTO_BRSATMON = 0x4c - IPPROTO_CARP = 0x70 - IPPROTO_CFTP = 0x3e - IPPROTO_CHAOS = 0x10 - IPPROTO_CMTP = 0x26 - IPPROTO_CPHB = 0x49 - IPPROTO_CPNX = 0x48 - IPPROTO_DDP = 0x25 - IPPROTO_DGP = 0x56 - IPPROTO_DIVERT = 0x102 - IPPROTO_DONE = 0x101 - IPPROTO_DSTOPTS = 0x3c - IPPROTO_EGP = 0x8 - IPPROTO_EMCON = 0xe - IPPROTO_ENCAP = 0x62 - IPPROTO_EON = 0x50 - IPPROTO_ESP = 0x32 - IPPROTO_ETHERIP = 0x61 - IPPROTO_FRAGMENT = 0x2c - IPPROTO_GGP = 0x3 - IPPROTO_GMTP = 0x64 - IPPROTO_GRE = 0x2f - IPPROTO_HELLO = 0x3f - IPPROTO_HMP = 0x14 - IPPROTO_HOPOPTS = 0 - IPPROTO_ICMP = 0x1 - IPPROTO_ICMPV6 = 0x3a - IPPROTO_IDP = 0x16 - IPPROTO_IDPR = 0x23 - IPPROTO_IDRP = 0x2d - IPPROTO_IGMP = 0x2 - IPPROTO_IGP = 0x55 - IPPROTO_IGRP = 0x58 - IPPROTO_IL = 0x28 - IPPROTO_INLSP = 0x34 - IPPROTO_INP = 0x20 - IPPROTO_IP = 0 - IPPROTO_IPCOMP = 0x6c - IPPROTO_IPCV = 0x47 - IPPROTO_IPEIP = 0x5e - IPPROTO_IPIP = 0x4 - IPPROTO_IPPC = 0x43 - IPPROTO_IPV4 = 0x4 - IPPROTO_IPV6 = 0x29 - IPPROTO_IRTP = 0x1c - IPPROTO_KRYPTOLAN = 0x41 - IPPROTO_LARP = 0x5b - IPPROTO_LEAF1 = 0x19 - IPPROTO_LEAF2 = 0x1a - IPPROTO_MAX = 0x100 - IPPROTO_MAXID = 0x34 - IPPROTO_MEAS = 0x13 - IPPROTO_MHRP = 0x30 - IPPROTO_MICP = 0x5f - IPPROTO_MOBILE = 0x37 - IPPROTO_MTP = 0x5c - IPPROTO_MUX = 0x12 - IPPROTO_ND = 0x4d - IPPROTO_NHRP = 0x36 - IPPROTO_NONE = 0x3b - IPPROTO_NSP = 0x1f - IPPROTO_NVPII = 0xb - IPPROTO_OLD_DIVERT = 0xfe - IPPROTO_OSPFIGP = 0x59 - IPPROTO_PFSYNC = 0xf0 - IPPROTO_PGM = 0x71 - IPPROTO_PIGP = 0x9 - IPPROTO_PIM = 0x67 - IPPROTO_PRM = 0x15 - IPPROTO_PUP = 0xc - IPPROTO_PVP = 0x4b - IPPROTO_RAW = 0xff - IPPROTO_RCCMON = 0xa - IPPROTO_RDP = 0x1b - IPPROTO_ROUTING = 0x2b - IPPROTO_RSVP = 0x2e - IPPROTO_RVD = 0x42 - IPPROTO_SATEXPAK = 0x40 - IPPROTO_SATMON = 0x45 - IPPROTO_SCCSP = 0x60 - IPPROTO_SCTP = 0x84 - IPPROTO_SDRP = 0x2a - IPPROTO_SEP = 0x21 - IPPROTO_SKIP = 0x39 - IPPROTO_SPACER = 0x7fff - IPPROTO_SRPC = 0x5a - IPPROTO_ST = 0x7 - IPPROTO_SVMTP = 0x52 - IPPROTO_SWIPE = 0x35 - IPPROTO_TCF = 0x57 - IPPROTO_TCP = 0x6 - IPPROTO_TLSP = 0x38 - IPPROTO_TP = 0x1d - IPPROTO_TPXX = 0x27 - IPPROTO_TRUNK1 = 0x17 - IPPROTO_TRUNK2 = 0x18 - IPPROTO_TTP = 0x54 - IPPROTO_UDP = 0x11 - IPPROTO_VINES = 0x53 - IPPROTO_VISA = 0x46 - IPPROTO_VMTP = 0x51 - IPPROTO_WBEXPAK = 0x4f - IPPROTO_WBMON = 0x4e - IPPROTO_WSN = 0x4a - IPPROTO_XNET = 0xf - IPPROTO_XTP = 0x24 - IPV6_AUTOFLOWLABEL = 0x3b - IPV6_BINDANY = 0x40 - IPV6_BINDV6ONLY = 0x1b - IPV6_CHECKSUM = 0x1a - IPV6_DEFAULT_MULTICAST_HOPS = 0x1 - IPV6_DEFAULT_MULTICAST_LOOP = 0x1 - IPV6_DEFHLIM = 0x40 - IPV6_DONTFRAG = 0x3e - IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - IPV6_FRAGTTL = 0x78 - IPV6_FW_ADD = 0x1e - IPV6_FW_DEL = 0x1f - IPV6_FW_FLUSH = 0x20 - IPV6_FW_GET = 0x22 - IPV6_FW_ZERO = 0x21 - IPV6_HLIMDEC = 0x1 - IPV6_HOPLIMIT = 0x2f - IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c - IPV6_JOIN_GROUP = 0xc - IPV6_LEAVE_GROUP = 0xd - IPV6_MAXHLIM = 0xff - IPV6_MAXOPTHDR = 0x800 - IPV6_MAXPACKET = 0xffff - IPV6_MAX_GROUP_SRC_FILTER = 0x200 - IPV6_MAX_MEMBERSHIPS = 0xfff - IPV6_MAX_SOCK_SRC_FILTER = 0x80 - IPV6_MIN_MEMBERSHIPS = 0x1f - IPV6_MMTU = 0x500 - IPV6_MSFILTER = 0x4a - IPV6_MULTICAST_HOPS = 0xa - IPV6_MULTICAST_IF = 0x9 - IPV6_MULTICAST_LOOP = 0xb - IPV6_NEXTHOP = 0x30 - IPV6_PATHMTU = 0x2c - IPV6_PKTINFO = 0x2e - IPV6_PORTRANGE = 0xe - IPV6_PORTRANGE_DEFAULT = 0 - IPV6_PORTRANGE_HIGH = 0x1 - IPV6_PORTRANGE_LOW = 0x2 - IPV6_PREFER_TEMPADDR = 0x3f - IPV6_RECVDSTOPTS = 0x28 - IPV6_RECVHOPLIMIT = 0x25 - IPV6_RECVHOPOPTS = 0x27 - IPV6_RECVPATHMTU = 0x2b - IPV6_RECVPKTINFO = 0x24 - IPV6_RECVRTHDR = 0x26 - IPV6_RECVTCLASS = 0x39 - IPV6_RTHDR = 0x33 - IPV6_RTHDRDSTOPTS = 0x23 - IPV6_RTHDR_LOOSE = 0 - IPV6_RTHDR_STRICT = 0x1 - IPV6_RTHDR_TYPE_0 = 0 - IPV6_SOCKOPT_RESERVED1 = 0x3 - IPV6_TCLASS = 0x3d - IPV6_UNICAST_HOPS = 0x4 - IPV6_USE_MIN_MTU = 0x2a - IPV6_V6ONLY = 0x1b - IPV6_VERSION = 0x60 - IPV6_VERSION_MASK = 0xf0 - IP_ADD_MEMBERSHIP = 0xc - IP_ADD_SOURCE_MEMBERSHIP = 0x46 - IP_BINDANY = 0x18 - IP_BLOCK_SOURCE = 0x48 - IP_DEFAULT_MULTICAST_LOOP = 0x1 - IP_DEFAULT_MULTICAST_TTL = 0x1 - IP_DF = 0x4000 - IP_DONTFRAG = 0x43 - IP_DROP_MEMBERSHIP = 0xd - IP_DROP_SOURCE_MEMBERSHIP = 0x47 - IP_DUMMYNET3 = 0x31 - IP_DUMMYNET_CONFIGURE = 0x3c - IP_DUMMYNET_DEL = 0x3d - IP_DUMMYNET_FLUSH = 0x3e - IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 - IP_FW3 = 0x30 - IP_FW_ADD = 0x32 - IP_FW_DEL = 0x33 - IP_FW_FLUSH = 0x34 - IP_FW_GET = 0x36 - IP_FW_NAT_CFG = 0x38 - IP_FW_NAT_DEL = 0x39 - IP_FW_NAT_GET_CONFIG = 0x3a - IP_FW_NAT_GET_LOG = 0x3b - IP_FW_RESETLOG = 0x37 - IP_FW_TABLE_ADD = 0x28 - IP_FW_TABLE_DEL = 0x29 - IP_FW_TABLE_FLUSH = 0x2a - IP_FW_TABLE_GETSIZE = 0x2b - IP_FW_TABLE_LIST = 0x2c - IP_FW_ZERO = 0x35 - IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 - IP_MAXPACKET = 0xffff - IP_MAX_GROUP_SRC_FILTER = 0x200 - IP_MAX_MEMBERSHIPS = 0xfff - IP_MAX_SOCK_MUTE_FILTER = 0x80 - IP_MAX_SOCK_SRC_FILTER = 0x80 - IP_MAX_SOURCE_FILTER = 0x400 - IP_MF = 0x2000 - IP_MINTTL = 0x42 - IP_MIN_MEMBERSHIPS = 0x1f - IP_MSFILTER = 0x4a - IP_MSS = 0x240 - IP_MULTICAST_IF = 0x9 - IP_MULTICAST_LOOP = 0xb - IP_MULTICAST_TTL = 0xa - IP_MULTICAST_VIF = 0xe - IP_OFFMASK = 0x1fff - IP_ONESBCAST = 0x17 - IP_OPTIONS = 0x1 - IP_PORTRANGE = 0x13 - IP_PORTRANGE_DEFAULT = 0 - IP_PORTRANGE_HIGH = 0x1 - IP_PORTRANGE_LOW = 0x2 - IP_RECVDSTADDR = 0x7 - IP_RECVIF = 0x14 - IP_RECVOPTS = 0x5 - IP_RECVRETOPTS = 0x6 - IP_RECVTTL = 0x41 - IP_RETOPTS = 0x8 - IP_RF = 0x8000 - IP_RSVP_OFF = 0x10 - IP_RSVP_ON = 0xf - IP_RSVP_VIF_OFF = 0x12 - IP_RSVP_VIF_ON = 0x11 - IP_SENDSRCADDR = 0x7 - IP_TOS = 0x3 - IP_TTL = 0x4 - IP_UNBLOCK_SOURCE = 0x49 - MSG_COMPAT = 0x8000 - MSG_CTRUNC = 0x20 - MSG_DONTROUTE = 0x4 - MSG_DONTWAIT = 0x80 - MSG_EOF = 0x100 - MSG_EOR = 0x8 - MSG_NBIO = 0x4000 - MSG_NOSIGNAL = 0x20000 - MSG_NOTIFICATION = 0x2000 - MSG_OOB = 0x1 - MSG_PEEK = 0x2 - MSG_TRUNC = 0x10 - MSG_WAITALL = 0x40 - NET_RT_DUMP = 0x1 - NET_RT_FLAGS = 0x2 - NET_RT_IFLIST = 0x3 - NET_RT_IFMALIST = 0x4 - NET_RT_MAXID = 0x5 - O_ACCMODE = 0x3 - O_APPEND = 0x8 - O_ASYNC = 0x40 - O_CREAT = 0x200 - O_DIRECT = 0x10000 - O_DIRECTORY = 0x20000 - O_EXCL = 0x800 - O_EXEC = 0x40000 - O_EXLOCK = 0x20 - O_FSYNC = 0x80 - O_NDELAY = 0x4 - O_NOCTTY = 0x8000 - O_NOFOLLOW = 0x100 - O_NONBLOCK = 0x4 - O_RDONLY = 0 - O_RDWR = 0x2 - O_SHLOCK = 0x10 - O_SYNC = 0x80 - O_TRUNC = 0x400 - O_TTY_INIT = 0x80000 - O_WRONLY = 0x1 - RTAX_AUTHOR = 0x6 - RTAX_BRD = 0x7 - RTAX_DST = 0 - RTAX_GATEWAY = 0x1 - RTAX_GENMASK = 0x3 - RTAX_IFA = 0x5 - RTAX_IFP = 0x4 - RTAX_MAX = 0x8 - RTAX_NETMASK = 0x2 - RTA_AUTHOR = 0x40 - RTA_BRD = 0x80 - RTA_DST = 0x1 - RTA_GATEWAY = 0x2 - RTA_GENMASK = 0x8 - RTA_IFA = 0x20 - RTA_IFP = 0x10 - RTA_NETMASK = 0x4 - RTF_BLACKHOLE = 0x1000 - RTF_BROADCAST = 0x400000 - RTF_DONE = 0x40 - RTF_DYNAMIC = 0x10 - RTF_FMASK = 0x1004d808 - RTF_GATEWAY = 0x2 - RTF_HOST = 0x4 - RTF_LLDATA = 0x400 - RTF_LLINFO = 0x400 - RTF_LOCAL = 0x200000 - RTF_MODIFIED = 0x20 - RTF_MULTICAST = 0x800000 - RTF_PINNED = 0x100000 - RTF_PRCLONING = 0x10000 - RTF_PROTO1 = 0x8000 - RTF_PROTO2 = 0x4000 - RTF_PROTO3 = 0x40000 - RTF_REJECT = 0x8 - RTF_RNH_LOCKED = 0x40000000 - RTF_STATIC = 0x800 - RTF_STICKY = 0x10000000 - RTF_UP = 0x1 - RTF_XRESOLVE = 0x200 - RTM_ADD = 0x1 - RTM_CHANGE = 0x3 - RTM_DELADDR = 0xd - RTM_DELETE = 0x2 - RTM_DELMADDR = 0x10 - RTM_GET = 0x4 - RTM_IEEE80211 = 0x12 - RTM_IFANNOUNCE = 0x11 - RTM_IFINFO = 0xe - RTM_LOCK = 0x8 - RTM_LOSING = 0x5 - RTM_MISS = 0x7 - RTM_NEWADDR = 0xc - RTM_NEWMADDR = 0xf - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa - RTM_REDIRECT = 0x6 - RTM_RESOLVE = 0xb - RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x5 - RTV_EXPIRE = 0x4 - RTV_HOPCOUNT = 0x2 - RTV_MTU = 0x1 - RTV_RPIPE = 0x8 - RTV_RTT = 0x40 - RTV_RTTVAR = 0x80 - RTV_SPIPE = 0x10 - RTV_SSTHRESH = 0x20 - RTV_WEIGHT = 0x100 - SCM_BINTIME = 0x4 - SCM_CREDS = 0x3 - SCM_RIGHTS = 0x1 - SCM_TIMESTAMP = 0x2 - SHUT_RD = 0 - SHUT_RDWR = 0x2 - SHUT_WR = 0x1 - SIGABRT = 0x6 - SIGALRM = 0xe - SIGBUS = 0xa - SIGCHLD = 0x14 - SIGCONT = 0x13 - SIGEMT = 0x7 - SIGFPE = 0x8 - SIGHUP = 0x1 - SIGILL = 0x4 - SIGINFO = 0x1d - SIGINT = 0x2 - SIGIO = 0x17 - SIGIOT = 0x6 - SIGKILL = 0x9 - SIGLWP = 0x20 - SIGPIPE = 0xd - SIGPROF = 0x1b - SIGQUIT = 0x3 - SIGSEGV = 0xb - SIGSTOP = 0x11 - SIGSYS = 0xc - SIGTERM = 0xf - SIGTHR = 0x20 - SIGTRAP = 0x5 - SIGTSTP = 0x12 - SIGTTIN = 0x15 - SIGTTOU = 0x16 - SIGURG = 0x10 - SIGUSR1 = 0x1e - SIGUSR2 = 0x1f - SIGVTALRM = 0x1a - SIGWINCH = 0x1c - SIGXCPU = 0x18 - SIGXFSZ = 0x19 - SIOCADDMULTI = 0x80206931 - SIOCADDRT = 0x8040720a - SIOCAIFADDR = 0x8040691a - SIOCAIFGROUP = 0x80286987 - SIOCALIFADDR = 0x8118691b - SIOCATMARK = 0x40047307 - SIOCDELMULTI = 0x80206932 - SIOCDELRT = 0x8040720b - SIOCDIFADDR = 0x80206919 - SIOCDIFGROUP = 0x80286989 - SIOCDIFPHYADDR = 0x80206949 - SIOCDLIFADDR = 0x8118691d - SIOCGDRVSPEC = 0xc028697b - SIOCGETSGCNT = 0xc0207210 - SIOCGETVIFCNT = 0xc028720f - SIOCGHIWAT = 0x40047301 - SIOCGIFADDR = 0xc0206921 - SIOCGIFBRDADDR = 0xc0206923 - SIOCGIFCAP = 0xc020691f - SIOCGIFCONF = 0xc0106924 - SIOCGIFDESCR = 0xc020692a - SIOCGIFDSTADDR = 0xc0206922 - SIOCGIFFLAGS = 0xc0206911 - SIOCGIFGENERIC = 0xc020693a - SIOCGIFGMEMB = 0xc028698a - SIOCGIFGROUP = 0xc0286988 - SIOCGIFINDEX = 0xc0206920 - SIOCGIFMAC = 0xc0206926 - SIOCGIFMEDIA = 0xc0306938 - SIOCGIFMETRIC = 0xc0206917 - SIOCGIFMTU = 0xc0206933 - SIOCGIFNETMASK = 0xc0206925 - SIOCGIFPDSTADDR = 0xc0206948 - SIOCGIFPHYS = 0xc0206935 - SIOCGIFPSRCADDR = 0xc0206947 - SIOCGIFSTATUS = 0xc331693b - SIOCGLIFADDR = 0xc118691c - SIOCGLIFPHYADDR = 0xc118694b - SIOCGLOWAT = 0x40047303 - SIOCGPGRP = 0x40047309 - SIOCGPRIVATE_0 = 0xc0206950 - SIOCGPRIVATE_1 = 0xc0206951 - SIOCIFCREATE = 0xc020697a - SIOCIFCREATE2 = 0xc020697c - SIOCIFDESTROY = 0x80206979 - SIOCIFGCLONERS = 0xc0106978 - SIOCSDRVSPEC = 0x8028697b - SIOCSHIWAT = 0x80047300 - SIOCSIFADDR = 0x8020690c - SIOCSIFBRDADDR = 0x80206913 - SIOCSIFCAP = 0x8020691e - SIOCSIFDESCR = 0x80206929 - SIOCSIFDSTADDR = 0x8020690e - SIOCSIFFLAGS = 0x80206910 - SIOCSIFGENERIC = 0x80206939 - SIOCSIFLLADDR = 0x8020693c - SIOCSIFMAC = 0x80206927 - SIOCSIFMEDIA = 0xc0206937 - SIOCSIFMETRIC = 0x80206918 - SIOCSIFMTU = 0x80206934 - SIOCSIFNAME = 0x80206928 - SIOCSIFNETMASK = 0x80206916 - SIOCSIFPHYADDR = 0x80406946 - SIOCSIFPHYS = 0x80206936 - SIOCSIFRVNET = 0xc020695b - SIOCSIFVNET = 0xc020695a - SIOCSLIFPHYADDR = 0x8118694a - SIOCSLOWAT = 0x80047302 - SIOCSPGRP = 0x80047308 - SOCK_DGRAM = 0x2 - SOCK_MAXADDRLEN = 0xff - SOCK_RAW = 0x3 - SOCK_RDM = 0x4 - SOCK_SEQPACKET = 0x5 - SOCK_STREAM = 0x1 - SOL_SOCKET = 0xffff - SOMAXCONN = 0x80 - SO_ACCEPTCONN = 0x2 - SO_ACCEPTFILTER = 0x1000 - SO_BINTIME = 0x2000 - SO_BROADCAST = 0x20 - SO_DEBUG = 0x1 - SO_DONTROUTE = 0x10 - SO_ERROR = 0x1007 - SO_KEEPALIVE = 0x8 - SO_LABEL = 0x1009 - SO_LINGER = 0x80 - SO_LISTENINCQLEN = 0x1013 - SO_LISTENQLEN = 0x1012 - SO_LISTENQLIMIT = 0x1011 - SO_NOSIGPIPE = 0x800 - SO_NO_DDP = 0x8000 - SO_NO_OFFLOAD = 0x4000 - SO_OOBINLINE = 0x100 - SO_PEERLABEL = 0x1010 - SO_RCVBUF = 0x1002 - SO_RCVLOWAT = 0x1004 - SO_RCVTIMEO = 0x1006 - SO_REUSEADDR = 0x4 - SO_REUSEPORT = 0x200 - SO_SETFIB = 0x1014 - SO_SNDBUF = 0x1001 - SO_SNDLOWAT = 0x1003 - SO_SNDTIMEO = 0x1005 - SO_TIMESTAMP = 0x400 - SO_TYPE = 0x1008 - SO_USELOOPBACK = 0x40 - TCP_CA_NAME_MAX = 0x10 - TCP_CONGESTION = 0x40 - TCP_INFO = 0x20 - TCP_MAXBURST = 0x4 - TCP_MAXHLEN = 0x3c - TCP_MAXOLEN = 0x28 - TCP_MAXSEG = 0x2 - TCP_MAXWIN = 0xffff - TCP_MAX_SACK = 0x4 - TCP_MAX_WINSHIFT = 0xe - TCP_MD5SIG = 0x10 - TCP_MINMSS = 0xd8 - TCP_MSS = 0x200 - TCP_NODELAY = 0x1 - TCP_NOOPT = 0x8 - TCP_NOPUSH = 0x4 - WCONTINUED = 0x4 - WCOREFLAG = 0x80 - WLINUXCLONE = 0x80000000 - WNOHANG = 0x1 - WNOWAIT = 0x8 - WSTOPPED = 0x2 - WUNTRACED = 0x2 + AF_APPLETALK = 0x10 + AF_ARP = 0x23 + AF_ATM = 0x1e + AF_BLUETOOTH = 0x24 + AF_CCITT = 0xa + AF_CHAOS = 0x5 + AF_CNT = 0x15 + AF_COIP = 0x14 + AF_DATAKIT = 0x9 + AF_DECnet = 0xc + AF_DLI = 0xd + AF_E164 = 0x1a + AF_ECMA = 0x8 + AF_HYLINK = 0xf + AF_IEEE80211 = 0x25 + AF_IMPLINK = 0x3 + AF_INET = 0x2 + AF_INET6 = 0x1c + AF_IPX = 0x17 + AF_ISDN = 0x1a + AF_ISO = 0x7 + AF_LAT = 0xe + AF_LINK = 0x12 + AF_LOCAL = 0x1 + AF_MAX = 0x26 + AF_NATM = 0x1d + AF_NETBIOS = 0x6 + AF_NETGRAPH = 0x20 + AF_OSI = 0x7 + AF_PUP = 0x4 + AF_ROUTE = 0x11 + AF_SCLUSTER = 0x22 + AF_SIP = 0x18 + AF_SLOW = 0x21 + AF_SNA = 0xb + AF_UNIX = 0x1 + AF_UNSPEC = 0 + AF_VENDOR00 = 0x27 + AF_VENDOR01 = 0x29 + AF_VENDOR02 = 0x2b + AF_VENDOR03 = 0x2d + AF_VENDOR04 = 0x2f + AF_VENDOR05 = 0x31 + AF_VENDOR06 = 0x33 + AF_VENDOR07 = 0x35 + AF_VENDOR08 = 0x37 + AF_VENDOR09 = 0x39 + AF_VENDOR10 = 0x3b + AF_VENDOR11 = 0x3d + AF_VENDOR12 = 0x3f + AF_VENDOR13 = 0x41 + AF_VENDOR14 = 0x43 + AF_VENDOR15 = 0x45 + AF_VENDOR16 = 0x47 + AF_VENDOR17 = 0x49 + AF_VENDOR18 = 0x4b + AF_VENDOR19 = 0x4d + AF_VENDOR20 = 0x4f + AF_VENDOR21 = 0x51 + AF_VENDOR22 = 0x53 + AF_VENDOR23 = 0x55 + AF_VENDOR24 = 0x57 + AF_VENDOR25 = 0x59 + AF_VENDOR26 = 0x5b + AF_VENDOR27 = 0x5d + AF_VENDOR28 = 0x5f + AF_VENDOR29 = 0x61 + AF_VENDOR30 = 0x63 + AF_VENDOR31 = 0x65 + AF_VENDOR32 = 0x67 + AF_VENDOR33 = 0x69 + AF_VENDOR34 = 0x6b + AF_VENDOR35 = 0x6d + AF_VENDOR36 = 0x6f + AF_VENDOR37 = 0x71 + AF_VENDOR38 = 0x73 + AF_VENDOR39 = 0x75 + AF_VENDOR40 = 0x77 + AF_VENDOR41 = 0x79 + AF_VENDOR42 = 0x7b + AF_VENDOR43 = 0x7d + AF_VENDOR44 = 0x7f + AF_VENDOR45 = 0x81 + AF_VENDOR46 = 0x83 + AF_VENDOR47 = 0x85 + BIOCFEEDBACK = 0x8004427c + BIOCFLUSH = 0x20004268 + BIOCGBLEN = 0x40044266 + BIOCGDIRECTION = 0x40044276 + BIOCGDLT = 0x4004426a + BIOCGDLTLIST = 0xc0104279 + BIOCGETBUFMODE = 0x4004427d + BIOCGETIF = 0x4020426b + BIOCGETZMAX = 0x4008427f + BIOCGHDRCMPLT = 0x40044274 + BIOCGRSIG = 0x40044272 + BIOCGRTIMEOUT = 0x4010426e + BIOCGSEESENT = 0x40044276 + BIOCGSTATS = 0x4008426f + BIOCIMMEDIATE = 0x80044270 + BIOCLOCK = 0x2000427a + BIOCPROMISC = 0x20004269 + BIOCROTZBUF = 0x40184280 + BIOCSBLEN = 0xc0044266 + BIOCSDIRECTION = 0x80044277 + BIOCSDLT = 0x80044278 + BIOCSETBUFMODE = 0x8004427e + BIOCSETF = 0x80104267 + BIOCSETFNR = 0x80104282 + BIOCSETIF = 0x8020426c + BIOCSETWF = 0x8010427b + BIOCSETZBUF = 0x80184281 + BIOCSHDRCMPLT = 0x80044275 + BIOCSRSIG = 0x80044273 + BIOCSRTIMEOUT = 0x8010426d + BIOCSSEESENT = 0x80044277 + BIOCVERSION = 0x40044271 + BPF_A = 0x10 + BPF_ABS = 0x20 + BPF_ADD = 0 + BPF_ALIGNMENT = 0x8 + BPF_ALU = 0x4 + BPF_AND = 0x50 + BPF_B = 0x10 + BPF_BUFMODE_BUFFER = 0x1 + BPF_BUFMODE_ZBUF = 0x2 + BPF_DIV = 0x30 + BPF_H = 0x8 + BPF_IMM = 0 + BPF_IND = 0x40 + BPF_JA = 0 + BPF_JEQ = 0x10 + BPF_JGE = 0x30 + BPF_JGT = 0x20 + BPF_JMP = 0x5 + BPF_JSET = 0x40 + BPF_K = 0 + BPF_LD = 0 + BPF_LDX = 0x1 + BPF_LEN = 0x80 + BPF_LSH = 0x60 + BPF_MAJOR_VERSION = 0x1 + BPF_MAXBUFSIZE = 0x80000 + BPF_MAXINSNS = 0x200 + BPF_MEM = 0x60 + BPF_MEMWORDS = 0x10 + BPF_MINBUFSIZE = 0x20 + BPF_MINOR_VERSION = 0x1 + BPF_MISC = 0x7 + BPF_MSH = 0xa0 + BPF_MUL = 0x20 + BPF_NEG = 0x80 + BPF_OR = 0x40 + BPF_RELEASE = 0x30bb6 + BPF_RET = 0x6 + BPF_RSH = 0x70 + BPF_ST = 0x2 + BPF_STX = 0x3 + BPF_SUB = 0x10 + BPF_TAX = 0 + BPF_TXA = 0x80 + BPF_W = 0 + BPF_X = 0x8 + CTL_MAXNAME = 0x18 + CTL_NET = 0x4 + DLT_A429 = 0xb8 + DLT_A653_ICM = 0xb9 + DLT_AIRONET_HEADER = 0x78 + DLT_APPLE_IP_OVER_IEEE1394 = 0x8a + DLT_ARCNET = 0x7 + DLT_ARCNET_LINUX = 0x81 + DLT_ATM_CLIP = 0x13 + DLT_ATM_RFC1483 = 0xb + DLT_AURORA = 0x7e + DLT_AX25 = 0x3 + DLT_AX25_KISS = 0xca + DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_HCI_H4 = 0xbb + DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_CAN20B = 0xbe + DLT_CHAOS = 0x5 + DLT_CHDLC = 0x68 + DLT_CISCO_IOS = 0x76 + DLT_C_HDLC = 0x68 + DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DOCSIS = 0x8f + DLT_ECONET = 0x73 + DLT_EN10MB = 0x1 + DLT_EN3MB = 0x2 + DLT_ENC = 0x6d + DLT_ERF = 0xc5 + DLT_ERF_ETH = 0xaf + DLT_ERF_POS = 0xb0 + DLT_FDDI = 0xa + DLT_FLEXRAY = 0xd2 + DLT_FRELAY = 0x6b + DLT_FRELAY_WITH_DIR = 0xce + DLT_GCOM_SERIAL = 0xad + DLT_GCOM_T1E1 = 0xac + DLT_GPF_F = 0xab + DLT_GPF_T = 0xaa + DLT_GPRS_LLC = 0xa9 + DLT_HHDLC = 0x79 + DLT_IBM_SN = 0x92 + DLT_IBM_SP = 0x91 + DLT_IEEE802 = 0x6 + DLT_IEEE802_11 = 0x69 + DLT_IEEE802_11_RADIO = 0x7f + DLT_IEEE802_11_RADIO_AVS = 0xa3 + DLT_IEEE802_15_4 = 0xc3 + DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NONASK_PHY = 0xd7 + DLT_IEEE802_16_MAC_CPS = 0xbc + DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_IPFILTER = 0x74 + DLT_IPMB = 0xc7 + DLT_IPMB_LINUX = 0xd1 + DLT_IP_OVER_FC = 0x7a + DLT_JUNIPER_ATM1 = 0x89 + DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_CHDLC = 0xb5 + DLT_JUNIPER_ES = 0x84 + DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FRELAY = 0xb4 + DLT_JUNIPER_GGSN = 0x85 + DLT_JUNIPER_ISM = 0xc2 + DLT_JUNIPER_MFR = 0x86 + DLT_JUNIPER_MLFR = 0x83 + DLT_JUNIPER_MLPPP = 0x82 + DLT_JUNIPER_MONITOR = 0xa4 + DLT_JUNIPER_PIC_PEER = 0xae + DLT_JUNIPER_PPP = 0xb3 + DLT_JUNIPER_PPPOE = 0xa7 + DLT_JUNIPER_PPPOE_ATM = 0xa8 + DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_ST = 0xc8 + DLT_JUNIPER_VP = 0xb7 + DLT_LAPB_WITH_DIR = 0xcf + DLT_LAPD = 0xcb + DLT_LIN = 0xd4 + DLT_LINUX_IRDA = 0x90 + DLT_LINUX_LAPD = 0xb1 + DLT_LINUX_PPP_WITHDIRECTION = 0xa6 + DLT_LINUX_SLL = 0x71 + DLT_LOOP = 0x6c + DLT_LTALK = 0x72 + DLT_MFR = 0xb6 + DLT_MOST = 0xd3 + DLT_MTP2 = 0x8c + DLT_MTP2_WITH_PHDR = 0x8b + DLT_MTP3 = 0x8d + DLT_NULL = 0 + DLT_PCI_EXP = 0x7d + DLT_PFLOG = 0x75 + DLT_PFSYNC = 0x79 + DLT_PPI = 0xc0 + DLT_PPP = 0x9 + DLT_PPP_BSDOS = 0x10 + DLT_PPP_ETHER = 0x33 + DLT_PPP_PPPD = 0xa6 + DLT_PPP_SERIAL = 0x32 + DLT_PPP_WITH_DIR = 0xcc + DLT_PPP_WITH_DIRECTION = 0xa6 + DLT_PRISM_HEADER = 0x77 + DLT_PRONET = 0x4 + DLT_RAIF1 = 0xc6 + DLT_RAW = 0xc + DLT_RIO = 0x7c + DLT_SCCP = 0x8e + DLT_SITA = 0xc4 + DLT_SLIP = 0x8 + DLT_SLIP_BSDOS = 0xf + DLT_SUNATM = 0x7b + DLT_SYMANTEC_FIREWALL = 0x63 + DLT_TZSP = 0x80 + DLT_USB = 0xba + DLT_USB_LINUX = 0xbd + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_X2E_SERIAL = 0xd5 + DLT_X2E_XORAYA = 0xd6 + DT_BLK = 0x6 + DT_CHR = 0x2 + DT_DIR = 0x4 + DT_FIFO = 0x1 + DT_LNK = 0xa + DT_REG = 0x8 + DT_SOCK = 0xc + DT_UNKNOWN = 0 + DT_WHT = 0xe + E2BIG = 0x7 + EACCES = 0xd + EADDRINUSE = 0x30 + EADDRNOTAVAIL = 0x31 + EAFNOSUPPORT = 0x2f + EAGAIN = 0x23 + EALREADY = 0x25 + EAUTH = 0x50 + EBADF = 0x9 + EBADMSG = 0x59 + EBADRPC = 0x48 + EBUSY = 0x10 + ECANCELED = 0x55 + ECHILD = 0xa + ECONNABORTED = 0x35 + ECONNREFUSED = 0x3d + ECONNRESET = 0x36 + EDEADLK = 0xb + EDESTADDRREQ = 0x27 + EDOM = 0x21 + EDOOFUS = 0x58 + EDQUOT = 0x45 + EEXIST = 0x11 + EFAULT = 0xe + EFBIG = 0x1b + EFTYPE = 0x4f + EHOSTDOWN = 0x40 + EHOSTUNREACH = 0x41 + EIDRM = 0x52 + EILSEQ = 0x56 + EINPROGRESS = 0x24 + EINTR = 0x4 + EINVAL = 0x16 + EIO = 0x5 + EISCONN = 0x38 + EISDIR = 0x15 + ELAST = 0x5d + ELOOP = 0x3e + EMFILE = 0x18 + EMLINK = 0x1f + EMSGSIZE = 0x28 + EMULTIHOP = 0x5a + ENAMETOOLONG = 0x3f + ENEEDAUTH = 0x51 + ENETDOWN = 0x32 + ENETRESET = 0x34 + ENETUNREACH = 0x33 + ENFILE = 0x17 + ENOATTR = 0x57 + ENOBUFS = 0x37 + ENODEV = 0x13 + ENOENT = 0x2 + ENOEXEC = 0x8 + ENOLCK = 0x4d + ENOLINK = 0x5b + ENOMEM = 0xc + ENOMSG = 0x53 + ENOPROTOOPT = 0x2a + ENOSPC = 0x1c + ENOSYS = 0x4e + ENOTBLK = 0xf + ENOTCAPABLE = 0x5d + ENOTCONN = 0x39 + ENOTDIR = 0x14 + ENOTEMPTY = 0x42 + ENOTSOCK = 0x26 + ENOTSUP = 0x2d + ENOTTY = 0x19 + ENXIO = 0x6 + EOPNOTSUPP = 0x2d + EOVERFLOW = 0x54 + EPERM = 0x1 + EPFNOSUPPORT = 0x2e + EPIPE = 0x20 + EPROCLIM = 0x43 + EPROCUNAVAIL = 0x4c + EPROGMISMATCH = 0x4b + EPROGUNAVAIL = 0x4a + EPROTO = 0x5c + EPROTONOSUPPORT = 0x2b + EPROTOTYPE = 0x29 + ERANGE = 0x22 + EREMOTE = 0x47 + EROFS = 0x1e + ERPCMISMATCH = 0x49 + ESHUTDOWN = 0x3a + ESOCKTNOSUPPORT = 0x2c + ESPIPE = 0x1d + ESRCH = 0x3 + ESTALE = 0x46 + ETIMEDOUT = 0x3c + ETOOMANYREFS = 0x3b + ETXTBSY = 0x1a + EUSERS = 0x44 + EVFILT_AIO = -0x3 + EVFILT_FS = -0x9 + EVFILT_LIO = -0xa + EVFILT_PROC = -0x5 + EVFILT_READ = -0x1 + EVFILT_SIGNAL = -0x6 + EVFILT_SYSCOUNT = 0xb + EVFILT_TIMER = -0x7 + EVFILT_USER = -0xb + EVFILT_VNODE = -0x4 + EVFILT_WRITE = -0x2 + EV_ADD = 0x1 + EV_CLEAR = 0x20 + EV_DELETE = 0x2 + EV_DISABLE = 0x8 + EV_DISPATCH = 0x80 + EV_ENABLE = 0x4 + EV_EOF = 0x8000 + EV_ERROR = 0x4000 + EV_FLAG1 = 0x2000 + EV_ONESHOT = 0x10 + EV_RECEIPT = 0x40 + EV_SYSFLAGS = 0xf000 + EWOULDBLOCK = 0x23 + EXDEV = 0x12 + FD_CLOEXEC = 0x1 + FD_SETSIZE = 0x400 + F_CANCEL = 0x5 + F_DUP2FD = 0xa + F_DUPFD = 0 + F_GETFD = 0x1 + F_GETFL = 0x3 + F_GETLK = 0xb + F_GETOWN = 0x5 + F_OGETLK = 0x7 + F_OSETLK = 0x8 + F_OSETLKW = 0x9 + F_RDAHEAD = 0x10 + F_RDLCK = 0x1 + F_READAHEAD = 0xf + F_SETFD = 0x2 + F_SETFL = 0x4 + F_SETLK = 0xc + F_SETLKW = 0xd + F_SETLK_REMOTE = 0xe + F_SETOWN = 0x6 + F_UNLCK = 0x2 + F_UNLCKSYS = 0x4 + F_WRLCK = 0x3 + IFF_ALLMULTI = 0x200 + IFF_ALTPHYS = 0x4000 + IFF_BROADCAST = 0x2 + IFF_CANTCHANGE = 0x208f72 + IFF_DEBUG = 0x4 + IFF_DRV_OACTIVE = 0x400 + IFF_DRV_RUNNING = 0x40 + IFF_DYING = 0x200000 + IFF_LINK0 = 0x1000 + IFF_LINK1 = 0x2000 + IFF_LINK2 = 0x4000 + IFF_LOOPBACK = 0x8 + IFF_MONITOR = 0x40000 + IFF_MULTICAST = 0x8000 + IFF_NOARP = 0x80 + IFF_OACTIVE = 0x400 + IFF_POINTOPOINT = 0x10 + IFF_PPROMISC = 0x20000 + IFF_PROMISC = 0x100 + IFF_RENAMING = 0x400000 + IFF_RUNNING = 0x40 + IFF_SIMPLEX = 0x800 + IFF_SMART = 0x20 + IFF_STATICARP = 0x80000 + IFF_UP = 0x1 + IFNAMSIZ = 0x10 + IFT_1822 = 0x2 + IFT_A12MPPSWITCH = 0x82 + IFT_AAL2 = 0xbb + IFT_AAL5 = 0x31 + IFT_ADSL = 0x5e + IFT_AFLANE8023 = 0x3b + IFT_AFLANE8025 = 0x3c + IFT_ARAP = 0x58 + IFT_ARCNET = 0x23 + IFT_ARCNETPLUS = 0x24 + IFT_ASYNC = 0x54 + IFT_ATM = 0x25 + IFT_ATMDXI = 0x69 + IFT_ATMFUNI = 0x6a + IFT_ATMIMA = 0x6b + IFT_ATMLOGICAL = 0x50 + IFT_ATMRADIO = 0xbd + IFT_ATMSUBINTERFACE = 0x86 + IFT_ATMVCIENDPT = 0xc2 + IFT_ATMVIRTUAL = 0x95 + IFT_BGPPOLICYACCOUNTING = 0xa2 + IFT_BRIDGE = 0xd1 + IFT_BSC = 0x53 + IFT_CARP = 0xf8 + IFT_CCTEMUL = 0x3d + IFT_CEPT = 0x13 + IFT_CES = 0x85 + IFT_CHANNEL = 0x46 + IFT_CNR = 0x55 + IFT_COFFEE = 0x84 + IFT_COMPOSITELINK = 0x9b + IFT_DCN = 0x8d + IFT_DIGITALPOWERLINE = 0x8a + IFT_DIGITALWRAPPEROVERHEADCHANNEL = 0xba + IFT_DLSW = 0x4a + IFT_DOCSCABLEDOWNSTREAM = 0x80 + IFT_DOCSCABLEMACLAYER = 0x7f + IFT_DOCSCABLEUPSTREAM = 0x81 + IFT_DS0 = 0x51 + IFT_DS0BUNDLE = 0x52 + IFT_DS1FDL = 0xaa + IFT_DS3 = 0x1e + IFT_DTM = 0x8c + IFT_DVBASILN = 0xac + IFT_DVBASIOUT = 0xad + IFT_DVBRCCDOWNSTREAM = 0x93 + IFT_DVBRCCMACLAYER = 0x92 + IFT_DVBRCCUPSTREAM = 0x94 + IFT_ENC = 0xf4 + IFT_EON = 0x19 + IFT_EPLRS = 0x57 + IFT_ESCON = 0x49 + IFT_ETHER = 0x6 + IFT_FAITH = 0xf2 + IFT_FAST = 0x7d + IFT_FASTETHER = 0x3e + IFT_FASTETHERFX = 0x45 + IFT_FDDI = 0xf + IFT_FIBRECHANNEL = 0x38 + IFT_FRAMERELAYINTERCONNECT = 0x3a + IFT_FRAMERELAYMPI = 0x5c + IFT_FRDLCIENDPT = 0xc1 + IFT_FRELAY = 0x20 + IFT_FRELAYDCE = 0x2c + IFT_FRF16MFRBUNDLE = 0xa3 + IFT_FRFORWARD = 0x9e + IFT_G703AT2MB = 0x43 + IFT_G703AT64K = 0x42 + IFT_GIF = 0xf0 + IFT_GIGABITETHERNET = 0x75 + IFT_GR303IDT = 0xb2 + IFT_GR303RDT = 0xb1 + IFT_H323GATEKEEPER = 0xa4 + IFT_H323PROXY = 0xa5 + IFT_HDH1822 = 0x3 + IFT_HDLC = 0x76 + IFT_HDSL2 = 0xa8 + IFT_HIPERLAN2 = 0xb7 + IFT_HIPPI = 0x2f + IFT_HIPPIINTERFACE = 0x39 + IFT_HOSTPAD = 0x5a + IFT_HSSI = 0x2e + IFT_HY = 0xe + IFT_IBM370PARCHAN = 0x48 + IFT_IDSL = 0x9a + IFT_IEEE1394 = 0x90 + IFT_IEEE80211 = 0x47 + IFT_IEEE80212 = 0x37 + IFT_IEEE8023ADLAG = 0xa1 + IFT_IFGSN = 0x91 + IFT_IMT = 0xbe + IFT_INTERLEAVE = 0x7c + IFT_IP = 0x7e + IFT_IPFORWARD = 0x8e + IFT_IPOVERATM = 0x72 + IFT_IPOVERCDLC = 0x6d + IFT_IPOVERCLAW = 0x6e + IFT_IPSWITCH = 0x4e + IFT_IPXIP = 0xf9 + IFT_ISDN = 0x3f + IFT_ISDNBASIC = 0x14 + IFT_ISDNPRIMARY = 0x15 + IFT_ISDNS = 0x4b + IFT_ISDNU = 0x4c + IFT_ISO88022LLC = 0x29 + IFT_ISO88023 = 0x7 + IFT_ISO88024 = 0x8 + IFT_ISO88025 = 0x9 + IFT_ISO88025CRFPINT = 0x62 + IFT_ISO88025DTR = 0x56 + IFT_ISO88025FIBER = 0x73 + IFT_ISO88026 = 0xa + IFT_ISUP = 0xb3 + IFT_L2VLAN = 0x87 + IFT_L3IPVLAN = 0x88 + IFT_L3IPXVLAN = 0x89 + IFT_LAPB = 0x10 + IFT_LAPD = 0x4d + IFT_LAPF = 0x77 + IFT_LOCALTALK = 0x2a + IFT_LOOP = 0x18 + IFT_MEDIAMAILOVERIP = 0x8b + IFT_MFSIGLINK = 0xa7 + IFT_MIOX25 = 0x26 + IFT_MODEM = 0x30 + IFT_MPC = 0x71 + IFT_MPLS = 0xa6 + IFT_MPLSTUNNEL = 0x96 + IFT_MSDSL = 0x8f + IFT_MVL = 0xbf + IFT_MYRINET = 0x63 + IFT_NFAS = 0xaf + IFT_NSIP = 0x1b + IFT_OPTICALCHANNEL = 0xc3 + IFT_OPTICALTRANSPORT = 0xc4 + IFT_OTHER = 0x1 + IFT_P10 = 0xc + IFT_P80 = 0xd + IFT_PARA = 0x22 + IFT_PFLOG = 0xf6 + IFT_PFSYNC = 0xf7 + IFT_PLC = 0xae + IFT_POS = 0xab + IFT_PPP = 0x17 + IFT_PPPMULTILINKBUNDLE = 0x6c + IFT_PROPBWAP2MP = 0xb8 + IFT_PROPCNLS = 0x59 + IFT_PROPDOCSWIRELESSDOWNSTREAM = 0xb5 + IFT_PROPDOCSWIRELESSMACLAYER = 0xb4 + IFT_PROPDOCSWIRELESSUPSTREAM = 0xb6 + IFT_PROPMUX = 0x36 + IFT_PROPVIRTUAL = 0x35 + IFT_PROPWIRELESSP2P = 0x9d + IFT_PTPSERIAL = 0x16 + IFT_PVC = 0xf1 + IFT_QLLC = 0x44 + IFT_RADIOMAC = 0xbc + IFT_RADSL = 0x5f + IFT_REACHDSL = 0xc0 + IFT_RFC1483 = 0x9f + IFT_RS232 = 0x21 + IFT_RSRB = 0x4f + IFT_SDLC = 0x11 + IFT_SDSL = 0x60 + IFT_SHDSL = 0xa9 + IFT_SIP = 0x1f + IFT_SLIP = 0x1c + IFT_SMDSDXI = 0x2b + IFT_SMDSICIP = 0x34 + IFT_SONET = 0x27 + IFT_SONETOVERHEADCHANNEL = 0xb9 + IFT_SONETPATH = 0x32 + IFT_SONETVT = 0x33 + IFT_SRP = 0x97 + IFT_SS7SIGLINK = 0x9c + IFT_STACKTOSTACK = 0x6f + IFT_STARLAN = 0xb + IFT_STF = 0xd7 + IFT_T1 = 0x12 + IFT_TDLC = 0x74 + IFT_TERMPAD = 0x5b + IFT_TR008 = 0xb0 + IFT_TRANSPHDLC = 0x7b + IFT_TUNNEL = 0x83 + IFT_ULTRA = 0x1d + IFT_USB = 0xa0 + IFT_V11 = 0x40 + IFT_V35 = 0x2d + IFT_V36 = 0x41 + IFT_V37 = 0x78 + IFT_VDSL = 0x61 + IFT_VIRTUALIPADDRESS = 0x70 + IFT_VOICEEM = 0x64 + IFT_VOICEENCAP = 0x67 + IFT_VOICEFXO = 0x65 + IFT_VOICEFXS = 0x66 + IFT_VOICEOVERATM = 0x98 + IFT_VOICEOVERFRAMERELAY = 0x99 + IFT_VOICEOVERIP = 0x68 + IFT_X213 = 0x5d + IFT_X25 = 0x5 + IFT_X25DDN = 0x4 + IFT_X25HUNTGROUP = 0x7a + IFT_X25MLP = 0x79 + IFT_X25PLE = 0x28 + IFT_XETHER = 0x1a + IN_CLASSA_HOST = 0xffffff + IN_CLASSA_MAX = 0x80 + IN_CLASSA_NET = 0xff000000 + IN_CLASSA_NSHIFT = 0x18 + IN_CLASSB_HOST = 0xffff + IN_CLASSB_MAX = 0x10000 + IN_CLASSB_NET = 0xffff0000 + IN_CLASSB_NSHIFT = 0x10 + IN_CLASSC_HOST = 0xff + IN_CLASSC_NET = 0xffffff00 + IN_CLASSC_NSHIFT = 0x8 + IN_CLASSD_HOST = 0xfffffff + IN_CLASSD_NET = 0xf0000000 + IN_CLASSD_NSHIFT = 0x1c + IN_LOOPBACKNET = 0x7f + IPPROTO_3PC = 0x22 + IPPROTO_ADFS = 0x44 + IPPROTO_AH = 0x33 + IPPROTO_AHIP = 0x3d + IPPROTO_APES = 0x63 + IPPROTO_ARGUS = 0xd + IPPROTO_AX25 = 0x5d + IPPROTO_BHA = 0x31 + IPPROTO_BLT = 0x1e + IPPROTO_BRSATMON = 0x4c + IPPROTO_CARP = 0x70 + IPPROTO_CFTP = 0x3e + IPPROTO_CHAOS = 0x10 + IPPROTO_CMTP = 0x26 + IPPROTO_CPHB = 0x49 + IPPROTO_CPNX = 0x48 + IPPROTO_DDP = 0x25 + IPPROTO_DGP = 0x56 + IPPROTO_DIVERT = 0x102 + IPPROTO_DONE = 0x101 + IPPROTO_DSTOPTS = 0x3c + IPPROTO_EGP = 0x8 + IPPROTO_EMCON = 0xe + IPPROTO_ENCAP = 0x62 + IPPROTO_EON = 0x50 + IPPROTO_ESP = 0x32 + IPPROTO_ETHERIP = 0x61 + IPPROTO_FRAGMENT = 0x2c + IPPROTO_GGP = 0x3 + IPPROTO_GMTP = 0x64 + IPPROTO_GRE = 0x2f + IPPROTO_HELLO = 0x3f + IPPROTO_HMP = 0x14 + IPPROTO_HOPOPTS = 0 + IPPROTO_ICMP = 0x1 + IPPROTO_ICMPV6 = 0x3a + IPPROTO_IDP = 0x16 + IPPROTO_IDPR = 0x23 + IPPROTO_IDRP = 0x2d + IPPROTO_IGMP = 0x2 + IPPROTO_IGP = 0x55 + IPPROTO_IGRP = 0x58 + IPPROTO_IL = 0x28 + IPPROTO_INLSP = 0x34 + IPPROTO_INP = 0x20 + IPPROTO_IP = 0 + IPPROTO_IPCOMP = 0x6c + IPPROTO_IPCV = 0x47 + IPPROTO_IPEIP = 0x5e + IPPROTO_IPIP = 0x4 + IPPROTO_IPPC = 0x43 + IPPROTO_IPV4 = 0x4 + IPPROTO_IPV6 = 0x29 + IPPROTO_IRTP = 0x1c + IPPROTO_KRYPTOLAN = 0x41 + IPPROTO_LARP = 0x5b + IPPROTO_LEAF1 = 0x19 + IPPROTO_LEAF2 = 0x1a + IPPROTO_MAX = 0x100 + IPPROTO_MAXID = 0x34 + IPPROTO_MEAS = 0x13 + IPPROTO_MHRP = 0x30 + IPPROTO_MICP = 0x5f + IPPROTO_MOBILE = 0x37 + IPPROTO_MTP = 0x5c + IPPROTO_MUX = 0x12 + IPPROTO_ND = 0x4d + IPPROTO_NHRP = 0x36 + IPPROTO_NONE = 0x3b + IPPROTO_NSP = 0x1f + IPPROTO_NVPII = 0xb + IPPROTO_OLD_DIVERT = 0xfe + IPPROTO_OSPFIGP = 0x59 + IPPROTO_PFSYNC = 0xf0 + IPPROTO_PGM = 0x71 + IPPROTO_PIGP = 0x9 + IPPROTO_PIM = 0x67 + IPPROTO_PRM = 0x15 + IPPROTO_PUP = 0xc + IPPROTO_PVP = 0x4b + IPPROTO_RAW = 0xff + IPPROTO_RCCMON = 0xa + IPPROTO_RDP = 0x1b + IPPROTO_ROUTING = 0x2b + IPPROTO_RSVP = 0x2e + IPPROTO_RVD = 0x42 + IPPROTO_SATEXPAK = 0x40 + IPPROTO_SATMON = 0x45 + IPPROTO_SCCSP = 0x60 + IPPROTO_SCTP = 0x84 + IPPROTO_SDRP = 0x2a + IPPROTO_SEP = 0x21 + IPPROTO_SKIP = 0x39 + IPPROTO_SPACER = 0x7fff + IPPROTO_SRPC = 0x5a + IPPROTO_ST = 0x7 + IPPROTO_SVMTP = 0x52 + IPPROTO_SWIPE = 0x35 + IPPROTO_TCF = 0x57 + IPPROTO_TCP = 0x6 + IPPROTO_TLSP = 0x38 + IPPROTO_TP = 0x1d + IPPROTO_TPXX = 0x27 + IPPROTO_TRUNK1 = 0x17 + IPPROTO_TRUNK2 = 0x18 + IPPROTO_TTP = 0x54 + IPPROTO_UDP = 0x11 + IPPROTO_VINES = 0x53 + IPPROTO_VISA = 0x46 + IPPROTO_VMTP = 0x51 + IPPROTO_WBEXPAK = 0x4f + IPPROTO_WBMON = 0x4e + IPPROTO_WSN = 0x4a + IPPROTO_XNET = 0xf + IPPROTO_XTP = 0x24 + IPV6_AUTOFLOWLABEL = 0x3b + IPV6_BINDANY = 0x40 + IPV6_BINDV6ONLY = 0x1b + IPV6_CHECKSUM = 0x1a + IPV6_DEFAULT_MULTICAST_HOPS = 0x1 + IPV6_DEFAULT_MULTICAST_LOOP = 0x1 + IPV6_DEFHLIM = 0x40 + IPV6_DONTFRAG = 0x3e + IPV6_DSTOPTS = 0x32 + IPV6_FAITH = 0x1d + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + IPV6_FRAGTTL = 0x78 + IPV6_FW_ADD = 0x1e + IPV6_FW_DEL = 0x1f + IPV6_FW_FLUSH = 0x20 + IPV6_FW_GET = 0x22 + IPV6_FW_ZERO = 0x21 + IPV6_HLIMDEC = 0x1 + IPV6_HOPLIMIT = 0x2f + IPV6_HOPOPTS = 0x31 + IPV6_IPSEC_POLICY = 0x1c + IPV6_JOIN_GROUP = 0xc + IPV6_LEAVE_GROUP = 0xd + IPV6_MAXHLIM = 0xff + IPV6_MAXOPTHDR = 0x800 + IPV6_MAXPACKET = 0xffff + IPV6_MAX_GROUP_SRC_FILTER = 0x200 + IPV6_MAX_MEMBERSHIPS = 0xfff + IPV6_MAX_SOCK_SRC_FILTER = 0x80 + IPV6_MIN_MEMBERSHIPS = 0x1f + IPV6_MMTU = 0x500 + IPV6_MSFILTER = 0x4a + IPV6_MULTICAST_HOPS = 0xa + IPV6_MULTICAST_IF = 0x9 + IPV6_MULTICAST_LOOP = 0xb + IPV6_NEXTHOP = 0x30 + IPV6_PATHMTU = 0x2c + IPV6_PKTINFO = 0x2e + IPV6_PORTRANGE = 0xe + IPV6_PORTRANGE_DEFAULT = 0 + IPV6_PORTRANGE_HIGH = 0x1 + IPV6_PORTRANGE_LOW = 0x2 + IPV6_PREFER_TEMPADDR = 0x3f + IPV6_RECVDSTOPTS = 0x28 + IPV6_RECVHOPLIMIT = 0x25 + IPV6_RECVHOPOPTS = 0x27 + IPV6_RECVPATHMTU = 0x2b + IPV6_RECVPKTINFO = 0x24 + IPV6_RECVRTHDR = 0x26 + IPV6_RECVTCLASS = 0x39 + IPV6_RTHDR = 0x33 + IPV6_RTHDRDSTOPTS = 0x23 + IPV6_RTHDR_LOOSE = 0 + IPV6_RTHDR_STRICT = 0x1 + IPV6_RTHDR_TYPE_0 = 0 + IPV6_SOCKOPT_RESERVED1 = 0x3 + IPV6_TCLASS = 0x3d + IPV6_UNICAST_HOPS = 0x4 + IPV6_USE_MIN_MTU = 0x2a + IPV6_V6ONLY = 0x1b + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 + IP_ADD_MEMBERSHIP = 0xc + IP_ADD_SOURCE_MEMBERSHIP = 0x46 + IP_BINDANY = 0x18 + IP_BLOCK_SOURCE = 0x48 + IP_DEFAULT_MULTICAST_LOOP = 0x1 + IP_DEFAULT_MULTICAST_TTL = 0x1 + IP_DF = 0x4000 + IP_DONTFRAG = 0x43 + IP_DROP_MEMBERSHIP = 0xd + IP_DROP_SOURCE_MEMBERSHIP = 0x47 + IP_DUMMYNET3 = 0x31 + IP_DUMMYNET_CONFIGURE = 0x3c + IP_DUMMYNET_DEL = 0x3d + IP_DUMMYNET_FLUSH = 0x3e + IP_DUMMYNET_GET = 0x40 + IP_FAITH = 0x16 + IP_FW3 = 0x30 + IP_FW_ADD = 0x32 + IP_FW_DEL = 0x33 + IP_FW_FLUSH = 0x34 + IP_FW_GET = 0x36 + IP_FW_NAT_CFG = 0x38 + IP_FW_NAT_DEL = 0x39 + IP_FW_NAT_GET_CONFIG = 0x3a + IP_FW_NAT_GET_LOG = 0x3b + IP_FW_RESETLOG = 0x37 + IP_FW_TABLE_ADD = 0x28 + IP_FW_TABLE_DEL = 0x29 + IP_FW_TABLE_FLUSH = 0x2a + IP_FW_TABLE_GETSIZE = 0x2b + IP_FW_TABLE_LIST = 0x2c + IP_FW_ZERO = 0x35 + IP_HDRINCL = 0x2 + IP_IPSEC_POLICY = 0x15 + IP_MAXPACKET = 0xffff + IP_MAX_GROUP_SRC_FILTER = 0x200 + IP_MAX_MEMBERSHIPS = 0xfff + IP_MAX_SOCK_MUTE_FILTER = 0x80 + IP_MAX_SOCK_SRC_FILTER = 0x80 + IP_MAX_SOURCE_FILTER = 0x400 + IP_MF = 0x2000 + IP_MINTTL = 0x42 + IP_MIN_MEMBERSHIPS = 0x1f + IP_MSFILTER = 0x4a + IP_MSS = 0x240 + IP_MULTICAST_IF = 0x9 + IP_MULTICAST_LOOP = 0xb + IP_MULTICAST_TTL = 0xa + IP_MULTICAST_VIF = 0xe + IP_OFFMASK = 0x1fff + IP_ONESBCAST = 0x17 + IP_OPTIONS = 0x1 + IP_PORTRANGE = 0x13 + IP_PORTRANGE_DEFAULT = 0 + IP_PORTRANGE_HIGH = 0x1 + IP_PORTRANGE_LOW = 0x2 + IP_RECVDSTADDR = 0x7 + IP_RECVIF = 0x14 + IP_RECVOPTS = 0x5 + IP_RECVRETOPTS = 0x6 + IP_RECVTTL = 0x41 + IP_RETOPTS = 0x8 + IP_RF = 0x8000 + IP_RSVP_OFF = 0x10 + IP_RSVP_ON = 0xf + IP_RSVP_VIF_OFF = 0x12 + IP_RSVP_VIF_ON = 0x11 + IP_SENDSRCADDR = 0x7 + IP_TOS = 0x3 + IP_TTL = 0x4 + IP_UNBLOCK_SOURCE = 0x49 + MSG_COMPAT = 0x8000 + MSG_CTRUNC = 0x20 + MSG_DONTROUTE = 0x4 + MSG_DONTWAIT = 0x80 + MSG_EOF = 0x100 + MSG_EOR = 0x8 + MSG_NBIO = 0x4000 + MSG_NOSIGNAL = 0x20000 + MSG_NOTIFICATION = 0x2000 + MSG_OOB = 0x1 + MSG_PEEK = 0x2 + MSG_TRUNC = 0x10 + MSG_WAITALL = 0x40 + NET_RT_DUMP = 0x1 + NET_RT_FLAGS = 0x2 + NET_RT_IFLIST = 0x3 + NET_RT_IFMALIST = 0x4 + NET_RT_MAXID = 0x5 + O_ACCMODE = 0x3 + O_APPEND = 0x8 + O_ASYNC = 0x40 + O_CREAT = 0x200 + O_DIRECT = 0x10000 + O_DIRECTORY = 0x20000 + O_EXCL = 0x800 + O_EXEC = 0x40000 + O_EXLOCK = 0x20 + O_FSYNC = 0x80 + O_NDELAY = 0x4 + O_NOCTTY = 0x8000 + O_NOFOLLOW = 0x100 + O_NONBLOCK = 0x4 + O_RDONLY = 0 + O_RDWR = 0x2 + O_SHLOCK = 0x10 + O_SYNC = 0x80 + O_TRUNC = 0x400 + O_TTY_INIT = 0x80000 + O_WRONLY = 0x1 + RTAX_AUTHOR = 0x6 + RTAX_BRD = 0x7 + RTAX_DST = 0 + RTAX_GATEWAY = 0x1 + RTAX_GENMASK = 0x3 + RTAX_IFA = 0x5 + RTAX_IFP = 0x4 + RTAX_MAX = 0x8 + RTAX_NETMASK = 0x2 + RTA_AUTHOR = 0x40 + RTA_BRD = 0x80 + RTA_DST = 0x1 + RTA_GATEWAY = 0x2 + RTA_GENMASK = 0x8 + RTA_IFA = 0x20 + RTA_IFP = 0x10 + RTA_NETMASK = 0x4 + RTF_BLACKHOLE = 0x1000 + RTF_BROADCAST = 0x400000 + RTF_DONE = 0x40 + RTF_DYNAMIC = 0x10 + RTF_FMASK = 0x1004d808 + RTF_GATEWAY = 0x2 + RTF_HOST = 0x4 + RTF_LLDATA = 0x400 + RTF_LLINFO = 0x400 + RTF_LOCAL = 0x200000 + RTF_MODIFIED = 0x20 + RTF_MULTICAST = 0x800000 + RTF_PINNED = 0x100000 + RTF_PRCLONING = 0x10000 + RTF_PROTO1 = 0x8000 + RTF_PROTO2 = 0x4000 + RTF_PROTO3 = 0x40000 + RTF_REJECT = 0x8 + RTF_RNH_LOCKED = 0x40000000 + RTF_STATIC = 0x800 + RTF_STICKY = 0x10000000 + RTF_UP = 0x1 + RTF_XRESOLVE = 0x200 + RTM_ADD = 0x1 + RTM_CHANGE = 0x3 + RTM_DELADDR = 0xd + RTM_DELETE = 0x2 + RTM_DELMADDR = 0x10 + RTM_GET = 0x4 + RTM_IEEE80211 = 0x12 + RTM_IFANNOUNCE = 0x11 + RTM_IFINFO = 0xe + RTM_LOCK = 0x8 + RTM_LOSING = 0x5 + RTM_MISS = 0x7 + RTM_NEWADDR = 0xc + RTM_NEWMADDR = 0xf + RTM_OLDADD = 0x9 + RTM_OLDDEL = 0xa + RTM_REDIRECT = 0x6 + RTM_RESOLVE = 0xb + RTM_RTTUNIT = 0xf4240 + RTM_VERSION = 0x5 + RTV_EXPIRE = 0x4 + RTV_HOPCOUNT = 0x2 + RTV_MTU = 0x1 + RTV_RPIPE = 0x8 + RTV_RTT = 0x40 + RTV_RTTVAR = 0x80 + RTV_SPIPE = 0x10 + RTV_SSTHRESH = 0x20 + RTV_WEIGHT = 0x100 + SCM_BINTIME = 0x4 + SCM_CREDS = 0x3 + SCM_RIGHTS = 0x1 + SCM_TIMESTAMP = 0x2 + SHUT_RD = 0 + SHUT_RDWR = 0x2 + SHUT_WR = 0x1 + SIGABRT = 0x6 + SIGALRM = 0xe + SIGBUS = 0xa + SIGCHLD = 0x14 + SIGCONT = 0x13 + SIGEMT = 0x7 + SIGFPE = 0x8 + SIGHUP = 0x1 + SIGILL = 0x4 + SIGINFO = 0x1d + SIGINT = 0x2 + SIGIO = 0x17 + SIGIOT = 0x6 + SIGKILL = 0x9 + SIGLWP = 0x20 + SIGPIPE = 0xd + SIGPROF = 0x1b + SIGQUIT = 0x3 + SIGSEGV = 0xb + SIGSTOP = 0x11 + SIGSYS = 0xc + SIGTERM = 0xf + SIGTHR = 0x20 + SIGTRAP = 0x5 + SIGTSTP = 0x12 + SIGTTIN = 0x15 + SIGTTOU = 0x16 + SIGURG = 0x10 + SIGUSR1 = 0x1e + SIGUSR2 = 0x1f + SIGVTALRM = 0x1a + SIGWINCH = 0x1c + SIGXCPU = 0x18 + SIGXFSZ = 0x19 + SIOCADDMULTI = 0x80206931 + SIOCADDRT = 0x8040720a + SIOCAIFADDR = 0x8040691a + SIOCAIFGROUP = 0x80286987 + SIOCALIFADDR = 0x8118691b + SIOCATMARK = 0x40047307 + SIOCDELMULTI = 0x80206932 + SIOCDELRT = 0x8040720b + SIOCDIFADDR = 0x80206919 + SIOCDIFGROUP = 0x80286989 + SIOCDIFPHYADDR = 0x80206949 + SIOCDLIFADDR = 0x8118691d + SIOCGDRVSPEC = 0xc028697b + SIOCGETSGCNT = 0xc0207210 + SIOCGETVIFCNT = 0xc028720f + SIOCGHIWAT = 0x40047301 + SIOCGIFADDR = 0xc0206921 + SIOCGIFBRDADDR = 0xc0206923 + SIOCGIFCAP = 0xc020691f + SIOCGIFCONF = 0xc0106924 + SIOCGIFDESCR = 0xc020692a + SIOCGIFDSTADDR = 0xc0206922 + SIOCGIFFLAGS = 0xc0206911 + SIOCGIFGENERIC = 0xc020693a + SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 + SIOCGIFINDEX = 0xc0206920 + SIOCGIFMAC = 0xc0206926 + SIOCGIFMEDIA = 0xc0306938 + SIOCGIFMETRIC = 0xc0206917 + SIOCGIFMTU = 0xc0206933 + SIOCGIFNETMASK = 0xc0206925 + SIOCGIFPDSTADDR = 0xc0206948 + SIOCGIFPHYS = 0xc0206935 + SIOCGIFPSRCADDR = 0xc0206947 + SIOCGIFSTATUS = 0xc331693b + SIOCGLIFADDR = 0xc118691c + SIOCGLIFPHYADDR = 0xc118694b + SIOCGLOWAT = 0x40047303 + SIOCGPGRP = 0x40047309 + SIOCGPRIVATE_0 = 0xc0206950 + SIOCGPRIVATE_1 = 0xc0206951 + SIOCIFCREATE = 0xc020697a + SIOCIFCREATE2 = 0xc020697c + SIOCIFDESTROY = 0x80206979 + SIOCIFGCLONERS = 0xc0106978 + SIOCSDRVSPEC = 0x8028697b + SIOCSHIWAT = 0x80047300 + SIOCSIFADDR = 0x8020690c + SIOCSIFBRDADDR = 0x80206913 + SIOCSIFCAP = 0x8020691e + SIOCSIFDESCR = 0x80206929 + SIOCSIFDSTADDR = 0x8020690e + SIOCSIFFLAGS = 0x80206910 + SIOCSIFGENERIC = 0x80206939 + SIOCSIFLLADDR = 0x8020693c + SIOCSIFMAC = 0x80206927 + SIOCSIFMEDIA = 0xc0206937 + SIOCSIFMETRIC = 0x80206918 + SIOCSIFMTU = 0x80206934 + SIOCSIFNAME = 0x80206928 + SIOCSIFNETMASK = 0x80206916 + SIOCSIFPHYADDR = 0x80406946 + SIOCSIFPHYS = 0x80206936 + SIOCSIFRVNET = 0xc020695b + SIOCSIFVNET = 0xc020695a + SIOCSLIFPHYADDR = 0x8118694a + SIOCSLOWAT = 0x80047302 + SIOCSPGRP = 0x80047308 + SOCK_DGRAM = 0x2 + SOCK_MAXADDRLEN = 0xff + SOCK_RAW = 0x3 + SOCK_RDM = 0x4 + SOCK_SEQPACKET = 0x5 + SOCK_STREAM = 0x1 + SOL_SOCKET = 0xffff + SOMAXCONN = 0x80 + SO_ACCEPTCONN = 0x2 + SO_ACCEPTFILTER = 0x1000 + SO_BINTIME = 0x2000 + SO_BROADCAST = 0x20 + SO_DEBUG = 0x1 + SO_DONTROUTE = 0x10 + SO_ERROR = 0x1007 + SO_KEEPALIVE = 0x8 + SO_LABEL = 0x1009 + SO_LINGER = 0x80 + SO_LISTENINCQLEN = 0x1013 + SO_LISTENQLEN = 0x1012 + SO_LISTENQLIMIT = 0x1011 + SO_NOSIGPIPE = 0x800 + SO_NO_DDP = 0x8000 + SO_NO_OFFLOAD = 0x4000 + SO_OOBINLINE = 0x100 + SO_PEERLABEL = 0x1010 + SO_RCVBUF = 0x1002 + SO_RCVLOWAT = 0x1004 + SO_RCVTIMEO = 0x1006 + SO_REUSEADDR = 0x4 + SO_REUSEPORT = 0x200 + SO_SETFIB = 0x1014 + SO_SNDBUF = 0x1001 + SO_SNDLOWAT = 0x1003 + SO_SNDTIMEO = 0x1005 + SO_TIMESTAMP = 0x400 + SO_TYPE = 0x1008 + SO_USELOOPBACK = 0x40 + TCP_CA_NAME_MAX = 0x10 + TCP_CONGESTION = 0x40 + TCP_INFO = 0x20 + TCP_MAXBURST = 0x4 + TCP_MAXHLEN = 0x3c + TCP_MAXOLEN = 0x28 + TCP_MAXSEG = 0x2 + TCP_MAXWIN = 0xffff + TCP_MAX_SACK = 0x4 + TCP_MAX_WINSHIFT = 0xe + TCP_MD5SIG = 0x10 + TCP_MINMSS = 0xd8 + TCP_MSS = 0x200 + TCP_NODELAY = 0x1 + TCP_NOOPT = 0x8 + TCP_NOPUSH = 0x4 + WCONTINUED = 0x4 + WCOREFLAG = 0x80 + WLINUXCLONE = 0x80000000 + WNOHANG = 0x1 + WNOWAIT = 0x8 + WSTOPPED = 0x2 + WUNTRACED = 0x2 ) // Types diff --git a/src/pkg/syscall/zerrors_linux_386.go b/src/pkg/syscall/zerrors_linux_386.go index 3fba3ae94..73caed44c 100644 --- a/src/pkg/syscall/zerrors_linux_386.go +++ b/src/pkg/syscall/zerrors_linux_386.go @@ -48,6 +48,64 @@ const ( AF_UNSPEC = 0 AF_WANPIPE = 0x19 AF_X25 = 0x9 + ARPHRD_ADAPT = 0x108 + ARPHRD_APPLETLK = 0x8 + ARPHRD_ARCNET = 0x7 + ARPHRD_ASH = 0x30d + ARPHRD_ATM = 0x13 + ARPHRD_AX25 = 0x3 + ARPHRD_BIF = 0x307 + ARPHRD_CHAOS = 0x5 + ARPHRD_CISCO = 0x201 + ARPHRD_CSLIP = 0x101 + ARPHRD_CSLIP6 = 0x103 + ARPHRD_DDCMP = 0x205 + ARPHRD_DLCI = 0xf + ARPHRD_ECONET = 0x30e + ARPHRD_EETHER = 0x2 + ARPHRD_ETHER = 0x1 + ARPHRD_EUI64 = 0x1b + ARPHRD_FCAL = 0x311 + ARPHRD_FCFABRIC = 0x313 + ARPHRD_FCPL = 0x312 + ARPHRD_FCPP = 0x310 + ARPHRD_FDDI = 0x306 + ARPHRD_FRAD = 0x302 + ARPHRD_HDLC = 0x201 + ARPHRD_HIPPI = 0x30c + ARPHRD_HWX25 = 0x110 + ARPHRD_IEEE1394 = 0x18 + ARPHRD_IEEE802 = 0x6 + ARPHRD_IEEE80211 = 0x321 + ARPHRD_IEEE80211_PRISM = 0x322 + ARPHRD_IEEE80211_RADIOTAP = 0x323 + ARPHRD_IEEE802154 = 0x324 + ARPHRD_IEEE802154_PHY = 0x325 + ARPHRD_IEEE802_TR = 0x320 + ARPHRD_INFINIBAND = 0x20 + ARPHRD_IPDDP = 0x309 + ARPHRD_IPGRE = 0x30a + ARPHRD_IRDA = 0x30f + ARPHRD_LAPB = 0x204 + ARPHRD_LOCALTLK = 0x305 + ARPHRD_LOOPBACK = 0x304 + ARPHRD_METRICOM = 0x17 + ARPHRD_NETROM = 0 + ARPHRD_NONE = 0xfffe + ARPHRD_PIMREG = 0x30b + ARPHRD_PPP = 0x200 + ARPHRD_PRONET = 0x4 + ARPHRD_RAWHDLC = 0x206 + ARPHRD_ROSE = 0x10e + ARPHRD_RSRVD = 0x104 + ARPHRD_SIT = 0x308 + ARPHRD_SKIP = 0x303 + ARPHRD_SLIP = 0x100 + ARPHRD_SLIP6 = 0x102 + ARPHRD_TUNNEL = 0x300 + ARPHRD_TUNNEL6 = 0x301 + ARPHRD_VOID = 0xffff + ARPHRD_X25 = 0x10f DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -716,6 +774,25 @@ const ( RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 + RTNH_ALIGNTO = 0x4 + RTNH_F_DEAD = 0x1 + RTNH_F_ONLINK = 0x4 + RTNH_F_PERVASIVE = 0x2 + RTN_MAX = 0xb + RTPROT_BIRD = 0xc + RTPROT_BOOT = 0x3 + RTPROT_DHCP = 0x10 + RTPROT_DNROUTED = 0xd + RTPROT_GATED = 0x8 + RTPROT_KERNEL = 0x2 + RTPROT_MRT = 0xa + RTPROT_NTK = 0xf + RTPROT_RA = 0x9 + RTPROT_REDIRECT = 0x1 + RTPROT_STATIC = 0x4 + RTPROT_UNSPEC = 0 + RTPROT_XORP = 0xe + RTPROT_ZEBRA = 0xb SCM_CREDENTIALS = 0x2 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x1d diff --git a/src/pkg/syscall/zerrors_linux_amd64.go b/src/pkg/syscall/zerrors_linux_amd64.go index 0e57b9333..89260740d 100644 --- a/src/pkg/syscall/zerrors_linux_amd64.go +++ b/src/pkg/syscall/zerrors_linux_amd64.go @@ -48,6 +48,64 @@ const ( AF_UNSPEC = 0 AF_WANPIPE = 0x19 AF_X25 = 0x9 + ARPHRD_ADAPT = 0x108 + ARPHRD_APPLETLK = 0x8 + ARPHRD_ARCNET = 0x7 + ARPHRD_ASH = 0x30d + ARPHRD_ATM = 0x13 + ARPHRD_AX25 = 0x3 + ARPHRD_BIF = 0x307 + ARPHRD_CHAOS = 0x5 + ARPHRD_CISCO = 0x201 + ARPHRD_CSLIP = 0x101 + ARPHRD_CSLIP6 = 0x103 + ARPHRD_DDCMP = 0x205 + ARPHRD_DLCI = 0xf + ARPHRD_ECONET = 0x30e + ARPHRD_EETHER = 0x2 + ARPHRD_ETHER = 0x1 + ARPHRD_EUI64 = 0x1b + ARPHRD_FCAL = 0x311 + ARPHRD_FCFABRIC = 0x313 + ARPHRD_FCPL = 0x312 + ARPHRD_FCPP = 0x310 + ARPHRD_FDDI = 0x306 + ARPHRD_FRAD = 0x302 + ARPHRD_HDLC = 0x201 + ARPHRD_HIPPI = 0x30c + ARPHRD_HWX25 = 0x110 + ARPHRD_IEEE1394 = 0x18 + ARPHRD_IEEE802 = 0x6 + ARPHRD_IEEE80211 = 0x321 + ARPHRD_IEEE80211_PRISM = 0x322 + ARPHRD_IEEE80211_RADIOTAP = 0x323 + ARPHRD_IEEE802154 = 0x324 + ARPHRD_IEEE802154_PHY = 0x325 + ARPHRD_IEEE802_TR = 0x320 + ARPHRD_INFINIBAND = 0x20 + ARPHRD_IPDDP = 0x309 + ARPHRD_IPGRE = 0x30a + ARPHRD_IRDA = 0x30f + ARPHRD_LAPB = 0x204 + ARPHRD_LOCALTLK = 0x305 + ARPHRD_LOOPBACK = 0x304 + ARPHRD_METRICOM = 0x17 + ARPHRD_NETROM = 0 + ARPHRD_NONE = 0xfffe + ARPHRD_PIMREG = 0x30b + ARPHRD_PPP = 0x200 + ARPHRD_PRONET = 0x4 + ARPHRD_RAWHDLC = 0x206 + ARPHRD_ROSE = 0x10e + ARPHRD_RSRVD = 0x104 + ARPHRD_SIT = 0x308 + ARPHRD_SKIP = 0x303 + ARPHRD_SLIP = 0x100 + ARPHRD_SLIP6 = 0x102 + ARPHRD_TUNNEL = 0x300 + ARPHRD_TUNNEL6 = 0x301 + ARPHRD_VOID = 0xffff + ARPHRD_X25 = 0x10f DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -717,6 +775,25 @@ const ( RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 + RTNH_ALIGNTO = 0x4 + RTNH_F_DEAD = 0x1 + RTNH_F_ONLINK = 0x4 + RTNH_F_PERVASIVE = 0x2 + RTN_MAX = 0xb + RTPROT_BIRD = 0xc + RTPROT_BOOT = 0x3 + RTPROT_DHCP = 0x10 + RTPROT_DNROUTED = 0xd + RTPROT_GATED = 0x8 + RTPROT_KERNEL = 0x2 + RTPROT_MRT = 0xa + RTPROT_NTK = 0xf + RTPROT_RA = 0x9 + RTPROT_REDIRECT = 0x1 + RTPROT_STATIC = 0x4 + RTPROT_UNSPEC = 0 + RTPROT_XORP = 0xe + RTPROT_ZEBRA = 0xb SCM_CREDENTIALS = 0x2 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x1d diff --git a/src/pkg/syscall/zerrors_linux_arm.go b/src/pkg/syscall/zerrors_linux_arm.go index 5be8bfa5c..50cdaf18a 100644 --- a/src/pkg/syscall/zerrors_linux_arm.go +++ b/src/pkg/syscall/zerrors_linux_arm.go @@ -48,6 +48,64 @@ const ( AF_UNSPEC = 0 AF_WANPIPE = 0x19 AF_X25 = 0x9 + ARPHRD_ADAPT = 0x108 + ARPHRD_APPLETLK = 0x8 + ARPHRD_ARCNET = 0x7 + ARPHRD_ASH = 0x30d + ARPHRD_ATM = 0x13 + ARPHRD_AX25 = 0x3 + ARPHRD_BIF = 0x307 + ARPHRD_CHAOS = 0x5 + ARPHRD_CISCO = 0x201 + ARPHRD_CSLIP = 0x101 + ARPHRD_CSLIP6 = 0x103 + ARPHRD_DDCMP = 0x205 + ARPHRD_DLCI = 0xf + ARPHRD_ECONET = 0x30e + ARPHRD_EETHER = 0x2 + ARPHRD_ETHER = 0x1 + ARPHRD_EUI64 = 0x1b + ARPHRD_FCAL = 0x311 + ARPHRD_FCFABRIC = 0x313 + ARPHRD_FCPL = 0x312 + ARPHRD_FCPP = 0x310 + ARPHRD_FDDI = 0x306 + ARPHRD_FRAD = 0x302 + ARPHRD_HDLC = 0x201 + ARPHRD_HIPPI = 0x30c + ARPHRD_HWX25 = 0x110 + ARPHRD_IEEE1394 = 0x18 + ARPHRD_IEEE802 = 0x6 + ARPHRD_IEEE80211 = 0x321 + ARPHRD_IEEE80211_PRISM = 0x322 + ARPHRD_IEEE80211_RADIOTAP = 0x323 + ARPHRD_IEEE802154 = 0x324 + ARPHRD_IEEE802154_PHY = 0x325 + ARPHRD_IEEE802_TR = 0x320 + ARPHRD_INFINIBAND = 0x20 + ARPHRD_IPDDP = 0x309 + ARPHRD_IPGRE = 0x30a + ARPHRD_IRDA = 0x30f + ARPHRD_LAPB = 0x204 + ARPHRD_LOCALTLK = 0x305 + ARPHRD_LOOPBACK = 0x304 + ARPHRD_METRICOM = 0x17 + ARPHRD_NETROM = 0 + ARPHRD_NONE = 0xfffe + ARPHRD_PIMREG = 0x30b + ARPHRD_PPP = 0x200 + ARPHRD_PRONET = 0x4 + ARPHRD_RAWHDLC = 0x206 + ARPHRD_ROSE = 0x10e + ARPHRD_RSRVD = 0x104 + ARPHRD_SIT = 0x308 + ARPHRD_SKIP = 0x303 + ARPHRD_SLIP = 0x100 + ARPHRD_SLIP6 = 0x102 + ARPHRD_TUNNEL = 0x300 + ARPHRD_TUNNEL6 = 0x301 + ARPHRD_VOID = 0xffff + ARPHRD_X25 = 0x10f DT_BLK = 0x6 DT_CHR = 0x2 DT_DIR = 0x4 @@ -707,6 +765,25 @@ const ( RTM_SETDCB = 0x4f RTM_SETLINK = 0x13 RTM_SETNEIGHTBL = 0x43 + RTNH_ALIGNTO = 0x4 + RTNH_F_DEAD = 0x1 + RTNH_F_ONLINK = 0x4 + RTNH_F_PERVASIVE = 0x2 + RTN_MAX = 0xb + RTPROT_BIRD = 0xc + RTPROT_BOOT = 0x3 + RTPROT_DHCP = 0x10 + RTPROT_DNROUTED = 0xd + RTPROT_GATED = 0x8 + RTPROT_KERNEL = 0x2 + RTPROT_MRT = 0xa + RTPROT_NTK = 0xf + RTPROT_RA = 0x9 + RTPROT_REDIRECT = 0x1 + RTPROT_STATIC = 0x4 + RTPROT_UNSPEC = 0 + RTPROT_XORP = 0xe + RTPROT_ZEBRA = 0xb SCM_CREDENTIALS = 0x2 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x1d diff --git a/src/pkg/syscall/ztypes_darwin_386.go b/src/pkg/syscall/ztypes_darwin_386.go index 1f378427f..2dec01787 100644 --- a/src/pkg/syscall/ztypes_darwin_386.go +++ b/src/pkg/syscall/ztypes_darwin_386.go @@ -22,9 +22,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 PTRACE_TRACEME = 0 PTRACE_CONT = 0x7 PTRACE_KILL = 0x8 @@ -226,11 +228,16 @@ type Iovec struct { Len uint32 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -247,6 +254,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Kevent_t struct { Ident uint32 Filter int16 diff --git a/src/pkg/syscall/ztypes_darwin_amd64.go b/src/pkg/syscall/ztypes_darwin_amd64.go index 5fa27bdd7..96500d732 100644 --- a/src/pkg/syscall/ztypes_darwin_amd64.go +++ b/src/pkg/syscall/ztypes_darwin_amd64.go @@ -22,9 +22,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 PTRACE_TRACEME = 0 PTRACE_CONT = 0x7 PTRACE_KILL = 0x8 @@ -234,11 +236,16 @@ type Iovec struct { Len uint64 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -257,6 +264,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Kevent_t struct { Ident uint64 Filter int16 diff --git a/src/pkg/syscall/ztypes_freebsd_386.go b/src/pkg/syscall/ztypes_freebsd_386.go index f4d256f4e..6304d3b81 100644 --- a/src/pkg/syscall/ztypes_freebsd_386.go +++ b/src/pkg/syscall/ztypes_freebsd_386.go @@ -32,9 +32,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 PTRACE_TRACEME = 0 PTRACE_CONT = 0x7 PTRACE_KILL = 0x8 @@ -219,11 +221,16 @@ type Iovec struct { Len uint32 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -240,6 +247,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Kevent_t struct { Ident uint32 Filter int16 diff --git a/src/pkg/syscall/ztypes_freebsd_amd64.go b/src/pkg/syscall/ztypes_freebsd_amd64.go index cf6355caf..ef5a51c4d 100644 --- a/src/pkg/syscall/ztypes_freebsd_amd64.go +++ b/src/pkg/syscall/ztypes_freebsd_amd64.go @@ -32,9 +32,11 @@ const ( SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x30 SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 PTRACE_TRACEME = 0 PTRACE_CONT = 0x7 PTRACE_KILL = 0x8 @@ -220,11 +222,16 @@ type Iovec struct { Len uint64 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -243,6 +250,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Kevent_t struct { Ident uint64 Filter int16 diff --git a/src/pkg/syscall/ztypes_linux_386.go b/src/pkg/syscall/ztypes_linux_386.go index 0409027de..65c8b87db 100644 --- a/src/pkg/syscall/ztypes_linux_386.go +++ b/src/pkg/syscall/ztypes_linux_386.go @@ -19,9 +19,11 @@ const ( SizeofSockaddrLinklayer = 0x14 SizeofSockaddrNetlink = 0xc SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 SizeofUcred = 0xc IFA_UNSPEC = 0 IFA_ADDRESS = 0x1 @@ -53,6 +55,42 @@ const ( IFLA_NET_NS_PID = 0x13 IFLA_IFALIAS = 0x14 IFLA_MAX = 0x14 + RT_SCOPE_UNIVERSE = 0 + RT_SCOPE_SITE = 0xc8 + RT_SCOPE_LINK = 0xfd + RT_SCOPE_HOST = 0xfe + RT_SCOPE_NOWHERE = 0xff + RT_TABLE_UNSPEC = 0 + RT_TABLE_COMPAT = 0xfc + RT_TABLE_DEFAULT = 0xfd + RT_TABLE_MAIN = 0xfe + RT_TABLE_LOCAL = 0xff + RT_TABLE_MAX = 0xffffffff + RTA_UNSPEC = 0 + RTA_DST = 0x1 + RTA_SRC = 0x2 + RTA_IIF = 0x3 + RTA_OIF = 0x4 + RTA_GATEWAY = 0x5 + RTA_PRIORITY = 0x6 + RTA_PREFSRC = 0x7 + RTA_METRICS = 0x8 + RTA_MULTIPATH = 0x9 + RTA_FLOW = 0xb + RTA_CACHEINFO = 0xc + RTA_TABLE = 0xf + RTN_UNSPEC = 0 + RTN_UNICAST = 0x1 + RTN_LOCAL = 0x2 + RTN_BROADCAST = 0x3 + RTN_ANYCAST = 0x4 + RTN_MULTICAST = 0x5 + RTN_BLACKHOLE = 0x6 + RTN_UNREACHABLE = 0x7 + RTN_PROHIBIT = 0x8 + RTN_THROW = 0x9 + RTN_NAT = 0xa + RTN_XRESOLVE = 0xb SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -61,6 +99,7 @@ const ( SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 SizeofRtmsg = 0xc + SizeofRtNexthop = 0x8 SizeofInotifyEvent = 0x10 ) @@ -261,11 +300,16 @@ type Iovec struct { Len uint32 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -282,6 +326,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Ucred struct { Pid int32 Uid uint32 @@ -344,6 +393,13 @@ type RtMsg struct { Flags uint32 } +type RtNexthop struct { + Len uint16 + Flags uint8 + Hops uint8 + Ifindex int32 +} + type InotifyEvent struct { Wd int32 Mask uint32 diff --git a/src/pkg/syscall/ztypes_linux_amd64.go b/src/pkg/syscall/ztypes_linux_amd64.go index 1d375e0d4..e26b6bfd2 100644 --- a/src/pkg/syscall/ztypes_linux_amd64.go +++ b/src/pkg/syscall/ztypes_linux_amd64.go @@ -19,9 +19,11 @@ const ( SizeofSockaddrLinklayer = 0x14 SizeofSockaddrNetlink = 0xc SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x38 SizeofCmsghdr = 0x10 + SizeofInet6Pktinfo = 0x14 SizeofUcred = 0xc IFA_UNSPEC = 0 IFA_ADDRESS = 0x1 @@ -53,6 +55,42 @@ const ( IFLA_NET_NS_PID = 0x13 IFLA_IFALIAS = 0x14 IFLA_MAX = 0x14 + RT_SCOPE_UNIVERSE = 0 + RT_SCOPE_SITE = 0xc8 + RT_SCOPE_LINK = 0xfd + RT_SCOPE_HOST = 0xfe + RT_SCOPE_NOWHERE = 0xff + RT_TABLE_UNSPEC = 0 + RT_TABLE_COMPAT = 0xfc + RT_TABLE_DEFAULT = 0xfd + RT_TABLE_MAIN = 0xfe + RT_TABLE_LOCAL = 0xff + RT_TABLE_MAX = 0xffffffff + RTA_UNSPEC = 0 + RTA_DST = 0x1 + RTA_SRC = 0x2 + RTA_IIF = 0x3 + RTA_OIF = 0x4 + RTA_GATEWAY = 0x5 + RTA_PRIORITY = 0x6 + RTA_PREFSRC = 0x7 + RTA_METRICS = 0x8 + RTA_MULTIPATH = 0x9 + RTA_FLOW = 0xb + RTA_CACHEINFO = 0xc + RTA_TABLE = 0xf + RTN_UNSPEC = 0 + RTN_UNICAST = 0x1 + RTN_LOCAL = 0x2 + RTN_BROADCAST = 0x3 + RTN_ANYCAST = 0x4 + RTN_MULTICAST = 0x5 + RTN_BLACKHOLE = 0x6 + RTN_UNREACHABLE = 0x7 + RTN_PROHIBIT = 0x8 + RTN_THROW = 0x9 + RTN_NAT = 0xa + RTN_XRESOLVE = 0xb SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -61,6 +99,7 @@ const ( SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 SizeofRtmsg = 0xc + SizeofRtNexthop = 0x8 SizeofInotifyEvent = 0x10 ) @@ -261,11 +300,16 @@ type Iovec struct { Len uint64 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -284,6 +328,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Ucred struct { Pid int32 Uid uint32 @@ -346,6 +395,13 @@ type RtMsg struct { Flags uint32 } +type RtNexthop struct { + Len uint16 + Flags uint8 + Hops uint8 + Ifindex int32 +} + type InotifyEvent struct { Wd int32 Mask uint32 diff --git a/src/pkg/syscall/ztypes_linux_arm.go b/src/pkg/syscall/ztypes_linux_arm.go index 5f2cde3cb..ebd5379cb 100644 --- a/src/pkg/syscall/ztypes_linux_arm.go +++ b/src/pkg/syscall/ztypes_linux_arm.go @@ -24,9 +24,11 @@ const ( SizeofSockaddrLinklayer = 0x14 SizeofSockaddrNetlink = 0xc SizeofLinger = 0x8 - SizeofIpMreq = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 SizeofMsghdr = 0x1c SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 SizeofUcred = 0xc IFA_UNSPEC = 0 IFA_ADDRESS = 0x1 @@ -58,6 +60,42 @@ const ( IFLA_NET_NS_PID = 0x13 IFLA_IFALIAS = 0x14 IFLA_MAX = 0x14 + RT_SCOPE_UNIVERSE = 0 + RT_SCOPE_SITE = 0xc8 + RT_SCOPE_LINK = 0xfd + RT_SCOPE_HOST = 0xfe + RT_SCOPE_NOWHERE = 0xff + RT_TABLE_UNSPEC = 0 + RT_TABLE_COMPAT = 0xfc + RT_TABLE_DEFAULT = 0xfd + RT_TABLE_MAIN = 0xfe + RT_TABLE_LOCAL = 0xff + RT_TABLE_MAX = 0xffffffff + RTA_UNSPEC = 0 + RTA_DST = 0x1 + RTA_SRC = 0x2 + RTA_IIF = 0x3 + RTA_OIF = 0x4 + RTA_GATEWAY = 0x5 + RTA_PRIORITY = 0x6 + RTA_PREFSRC = 0x7 + RTA_METRICS = 0x8 + RTA_MULTIPATH = 0x9 + RTA_FLOW = 0xb + RTA_CACHEINFO = 0xc + RTA_TABLE = 0xf + RTN_UNSPEC = 0 + RTN_UNICAST = 0x1 + RTN_LOCAL = 0x2 + RTN_BROADCAST = 0x3 + RTN_ANYCAST = 0x4 + RTN_MULTICAST = 0x5 + RTN_BLACKHOLE = 0x6 + RTN_UNREACHABLE = 0x7 + RTN_PROHIBIT = 0x8 + RTN_THROW = 0x9 + RTN_NAT = 0xa + RTN_XRESOLVE = 0xb SizeofNlMsghdr = 0x10 SizeofNlMsgerr = 0x14 SizeofRtGenmsg = 0x1 @@ -66,6 +104,7 @@ const ( SizeofIfInfomsg = 0x10 SizeofIfAddrmsg = 0x8 SizeofRtmsg = 0xc + SizeofRtNexthop = 0x8 SizeofInotifyEvent = 0x10 ) @@ -268,11 +307,16 @@ type Iovec struct { Len uint32 } -type IpMreq struct { +type IPMreq struct { Multiaddr [4]byte /* in_addr */ Interface [4]byte /* in_addr */ } +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + type Msghdr struct { Name *byte Namelen uint32 @@ -289,6 +333,11 @@ type Cmsghdr struct { Type int32 } +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + type Ucred struct { Pid int32 Uid uint32 @@ -351,6 +400,13 @@ type RtMsg struct { Flags uint32 } +type RtNexthop struct { + Len uint16 + Flags uint8 + Hops uint8 + Ifindex int32 +} + type InotifyEvent struct { Wd int32 Mask uint32 diff --git a/src/pkg/tabwriter/tabwriter.go b/src/pkg/tabwriter/tabwriter.go index d91a07db2..b84c6ec79 100644 --- a/src/pkg/tabwriter/tabwriter.go +++ b/src/pkg/tabwriter/tabwriter.go @@ -158,7 +158,7 @@ const ( TabIndent // Print a vertical bar ('|') between columns (after formatting). - // Discarded colums appear as zero-width columns ("||"). + // Discarded columns appear as zero-width columns ("||"). Debug ) diff --git a/src/pkg/template/template.go b/src/pkg/template/template.go index c00f72ac9..f481cbd1e 100644 --- a/src/pkg/template/template.go +++ b/src/pkg/template/template.go @@ -17,12 +17,15 @@ Data items may be values or pointers; the interface hides the indirection. - In the following, 'field' is one of several things, according to the data. + In the following, 'Field' is one of several things, according to the data. - - The name of a field of a struct (result = data.field), - - The value stored in a map under that key (result = data[field]), or + - The name of a field of a struct (result = data.Field), + - The value stored in a map under that key (result = data["Field"]), or - The result of invoking a niladic single-valued method with that name - (result = data.field()) + (result = data.Field()) + + If Field is a struct field or method name, it must be an exported + (capitalized) name. Major constructs ({} are the default delimiters for template actions; [] are the notation in this comment for optional elements): @@ -236,8 +239,8 @@ func isExported(name string) bool { // -- Lexical analysis -// Is c a white space character? -func white(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } +// Is c a space character? +func isSpace(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } // Safely, does s[n:n+len(t)] == t? func equal(s []byte, n int, t []byte) bool { @@ -292,9 +295,9 @@ func (t *Template) nextItem() []byte { t.linenum++ i++ } - // Leading white space up to but not including newline + // Leading space up to but not including newline for i = start; i < len(t.buf); i++ { - if t.buf[i] == '\n' || !white(t.buf[i]) { + if t.buf[i] == '\n' || !isSpace(t.buf[i]) { break } } @@ -339,7 +342,7 @@ func (t *Template) nextItem() []byte { firstChar := t.buf[left+len(t.ldelim)] if firstChar == '.' || firstChar == '#' { // It's special and the first thing on the line. Is it the last? - for j := right; j < len(t.buf) && white(t.buf[j]); j++ { + for j := right; j < len(t.buf) && isSpace(t.buf[j]); j++ { if t.buf[j] == '\n' { // Yes it is. Drop the surrounding space and return the {.foo} t.linenum++ @@ -351,7 +354,7 @@ func (t *Template) nextItem() []byte { } // No it's not. If there's leading space, return that. if leadingSpace { - // not trimming space: return leading white space if there is some. + // not trimming space: return leading space if there is some. t.p = left return t.buf[start:left] } @@ -374,13 +377,13 @@ func (t *Template) nextItem() []byte { return item } -// Turn a byte array into a white-space-split array of strings, +// Turn a byte array into a space-split array of strings, // taking into account quoted strings. func words(buf []byte) []string { s := make([]string, 0, 5) for i := 0; i < len(buf); { // One word per loop - for i < len(buf) && white(buf[i]) { + for i < len(buf) && isSpace(buf[i]) { i++ } if i == len(buf) { @@ -395,10 +398,11 @@ func words(buf []byte) []string { } else { i++ } - } else { - for i < len(buf) && !white(buf[i]) { - i++ - } + } + // Even with quotes, break on space only. This handles input + // such as {""|} and catches quoting mistakes. + for i < len(buf) && !isSpace(buf[i]) { + i++ } s = append(s, string(buf[start:i])) } @@ -490,20 +494,9 @@ func (t *Template) formatter(name string) func(io.Writer, string, ...interface{} // -- Parsing -// Allocate a new variable-evaluation element. +// newVariable allocates a new variable-evaluation element. func (t *Template) newVariable(words []string) *variableElement { - // After the final space-separated argument, formatters may be specified separated - // by pipe symbols, for example: {a b c|d|e} - - // Until we learn otherwise, formatters contains a single name: "", the default formatter. - formatters := []string{""} - lastWord := words[len(words)-1] - bar := strings.IndexRune(lastWord, '|') - if bar >= 0 { - words[len(words)-1] = lastWord[0:bar] - formatters = strings.Split(lastWord[bar+1:], "|", -1) - } - + formatters := extractFormatters(words) args := make([]interface{}, len(words)) // Build argument list, processing any literals @@ -549,6 +542,38 @@ func (t *Template) newVariable(words []string) *variableElement { return &variableElement{t.linenum, args, formatters} } +// extractFormatters extracts a list of formatters from words. +// After the final space-separated argument in a variable, formatters may be +// specified separated by pipe symbols. For example: {a b c|d|e} +// The words parameter still has the formatters joined by '|' in the last word. +// extractFormatters splits formatters, replaces the last word with the content +// found before the first '|' within it, and returns the formatters obtained. +// If no formatters are found in words, the default formatter is returned. +func extractFormatters(words []string) (formatters []string) { + // "" is the default formatter. + formatters = []string{""} + if len(words) == 0 { + return + } + var bar int + lastWord := words[len(words)-1] + if isQuote(lastWord[0]) { + end := endQuote([]byte(lastWord), 0) + if end < 0 || end+1 == len(lastWord) || lastWord[end+1] != '|' { + return + } + bar = end + 1 + } else { + bar = strings.IndexRune(lastWord, '|') + if bar < 0 { + return + } + } + words[len(words)-1] = lastWord[0:bar] + formatters = strings.Split(lastWord[bar+1:], "|", -1) + return +} + // Grab the next item. If it's simple, just append it to the template. // Otherwise return its details. func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) { @@ -1012,13 +1037,13 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) { } } -// A valid delimiter must contain no white space and be non-empty. +// A valid delimiter must contain no space and be non-empty. func validDelim(d []byte) bool { if len(d) == 0 { return false } for _, c := range d { - if white(c) { + if isSpace(c) { return false } } diff --git a/src/pkg/template/template_test.go b/src/pkg/template/template_test.go index a5e6a4ecc..99b23c288 100644 --- a/src/pkg/template/template_test.go +++ b/src/pkg/template/template_test.go @@ -144,21 +144,21 @@ var tests = []*Test{ }, &Test{ - in: `{"Strings" ":"} {""} {"\t\u0123 \x23\\"} {"\"}{\\"}`, + in: `{"Strings" ":"} {""} {"|"} {"\t\u0123 \x23\\"} {"\"}{\\"}`, - out: "Strings: \t\u0123 \x23\\ \"}{\\", + out: "Strings: | \t\u0123 \x23\\ \"}{\\", }, &Test{ - in: "{`Raw strings` `:`} {``} {`\\t\\u0123 \\x23\\`} {`}{\\`}", + in: "{`Raw strings` `:`} {``} {`|`} {`\\t\\u0123 \\x23\\`} {`}{\\`}", - out: "Raw strings: \\t\\u0123 \\x23\\ }{\\", + out: "Raw strings: | \\t\\u0123 \\x23\\ }{\\", }, &Test{ - in: "Characters: {'a'} {'\\u0123'} {' '} {'}'} {'{'}", + in: "Characters: {'a'} {'\\u0123'} {' '} {'{'} {'|'} {'}'}", - out: "Characters: 97 291 32 125 123", + out: "Characters: 97 291 32 123 124 125", }, &Test{ @@ -762,6 +762,10 @@ var formatterTests = []Test{ in: `{"%.02f 0x%02X" 1.1 10|printf}`, out: "1.10 0x0A", }, + { + in: `{""|}{""||}{""|printf}`, // Issue #1896. + out: "", + }, } func TestFormatters(t *testing.T) { diff --git a/src/pkg/testing/benchmark.go b/src/pkg/testing/benchmark.go index cf73e2b48..db4c65941 100644 --- a/src/pkg/testing/benchmark.go +++ b/src/pkg/testing/benchmark.go @@ -150,7 +150,7 @@ func (b *B) run() BenchmarkResult { type BenchmarkResult struct { N int // The number of iterations. Ns int64 // The total time taken. - Bytes int64 // The total number of bytes processed. + Bytes int64 // Bytes processed in one iteration. } func (r BenchmarkResult) NsPerOp() int64 { @@ -160,13 +160,20 @@ func (r BenchmarkResult) NsPerOp() int64 { return r.Ns / int64(r.N) } +func (r BenchmarkResult) mbPerSec() float64 { + if r.Bytes <= 0 || r.Ns <= 0 || r.N <= 0 { + return 0 + } + return float64(r.Bytes) * float64(r.N) / float64(r.Ns) * 1e3 +} + func (r BenchmarkResult) String() string { - ns := r.NsPerOp() + mbs := r.mbPerSec() mb := "" - if ns > 0 && r.Bytes > 0 { - mb = fmt.Sprintf("\t%7.2f MB/s", (float64(r.Bytes)/1e6)/(float64(ns)/1e9)) + if mbs != 0 { + mb = fmt.Sprintf("\t%7.2f MB/s", mbs) } - return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, ns, mb) + return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, r.NsPerOp(), mb) } // An internal function but exported because it is cross-package; part of the implementation diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go index 7b5a8f3b6..47d736342 100644 --- a/src/pkg/time/format.go +++ b/src/pkg/time/format.go @@ -272,9 +272,19 @@ func (t *Time) Format(layout string) string { case stdHour: p = zeroPad(t.Hour) case stdHour12: - p = strconv.Itoa(t.Hour % 12) + // Noon is 12PM, midnight is 12AM. + hr := t.Hour % 12 + if hr == 0 { + hr = 12 + } + p = strconv.Itoa(hr) case stdZeroHour12: - p = zeroPad(t.Hour % 12) + // Noon is 12PM, midnight is 12AM. + hr := t.Hour % 12 + if hr == 0 { + hr = 12 + } + p = zeroPad(hr) case stdMinute: p = strconv.Itoa(t.Minute) case stdZeroMinute: @@ -429,6 +439,7 @@ func skip(value, prefix string) (string, os.Error) { func Parse(alayout, avalue string) (*Time, os.Error) { var t Time rangeErrString := "" // set if a value is out of range + amSet := false // do we need to subtract 12 from the hour for midnight? pmSet := false // do we need to add 12 to the hour? layout, value := alayout, avalue // Each iteration processes one std value. @@ -558,9 +569,12 @@ func Parse(alayout, avalue string) (*Time, os.Error) { break } p, value = value[0:2], value[2:] - if p == "PM" { + switch p { + case "PM": pmSet = true - } else if p != "AM" { + case "AM": + amSet = true + default: err = errBad } case stdpm: @@ -569,9 +583,12 @@ func Parse(alayout, avalue string) (*Time, os.Error) { break } p, value = value[0:2], value[2:] - if p == "pm" { + switch p { + case "pm": pmSet = true - } else if p != "am" { + case "am": + amSet = true + default: err = errBad } case stdTZ: @@ -613,6 +630,8 @@ func Parse(alayout, avalue string) (*Time, os.Error) { } if pmSet && t.Hour < 12 { t.Hour += 12 + } else if amSet && t.Hour == 12 { + t.Hour = 0 } return &t, nil } diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go index 3bc253c94..314622d0d 100644 --- a/src/pkg/time/sleep.go +++ b/src/pkg/time/sleep.go @@ -91,7 +91,7 @@ func (e *Timer) Stop() (ok bool) { // It assumes that f will not block. func after(ns int64, f func(int64)) (e *Timer) { now := Nanoseconds() - t := Nanoseconds() + ns + t := now + ns if ns > 0 && t < now { panic("time: time overflow") } diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go index 6c21bf19b..dde18000d 100644 --- a/src/pkg/time/tick.go +++ b/src/pkg/time/tick.go @@ -88,7 +88,7 @@ func wakeLoop(wakeMeAt chan int64, wakeUp chan bool) { // A single tickerLoop serves all ticks to Tickers. It waits for two events: // either the creation of a new Ticker or a tick from the alarm, -// signalling a time to wake up one or more Tickers. +// signaling a time to wake up one or more Tickers. func tickerLoop() { // Represents the next alarm to be delivered. var alarm alarmer diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go index 1d83291c0..eb676bf64 100644 --- a/src/pkg/time/time_test.go +++ b/src/pkg/time/time_test.go @@ -302,6 +302,66 @@ func TestParseErrors(t *testing.T) { } } +func TestNoonIs12PM(t *testing.T) { + noon := Time{Hour: 12} + const expect = "12:00PM" + got := noon.Format("3:04PM") + if got != expect { + t.Errorf("got %q; expect %q", got, expect) + } + got = noon.Format("03:04PM") + if got != expect { + t.Errorf("got %q; expect %q", got, expect) + } +} + +func TestMidnightIs12AM(t *testing.T) { + midnight := Time{Hour: 0} + expect := "12:00AM" + got := midnight.Format("3:04PM") + if got != expect { + t.Errorf("got %q; expect %q", got, expect) + } + got = midnight.Format("03:04PM") + if got != expect { + t.Errorf("got %q; expect %q", got, expect) + } +} + +func Test12PMIsNoon(t *testing.T) { + noon, err := Parse("3:04PM", "12:00PM") + if err != nil { + t.Fatal("error parsing date:", err) + } + if noon.Hour != 12 { + t.Errorf("got %d; expect 12", noon.Hour) + } + noon, err = Parse("03:04PM", "12:00PM") + if err != nil { + t.Fatal("error parsing date:", err) + } + if noon.Hour != 12 { + t.Errorf("got %d; expect 12", noon.Hour) + } +} + +func Test12AMIsMidnight(t *testing.T) { + midnight, err := Parse("3:04PM", "12:00AM") + if err != nil { + t.Fatal("error parsing date:", err) + } + if midnight.Hour != 0 { + t.Errorf("got %d; expect 0", midnight.Hour) + } + midnight, err = Parse("03:04PM", "12:00AM") + if err != nil { + t.Fatal("error parsing date:", err) + } + if midnight.Hour != 0 { + t.Errorf("got %d; expect 0", midnight.Hour) + } +} + // Check that a time without a Zone still produces a (numeric) time zone // when formatted with MST as a requested zone. func TestMissingZone(t *testing.T) { diff --git a/src/pkg/time/zoneinfo_windows.go b/src/pkg/time/zoneinfo_windows.go index c357eec62..83afdfb02 100644 --- a/src/pkg/time/zoneinfo_windows.go +++ b/src/pkg/time/zoneinfo_windows.go @@ -14,7 +14,7 @@ import ( // this year's rules for daylight savings time apply to all previous // and future years as well. -// TODO(brainman): use GetDynamicTimeZoneInformation, whenever posible (Vista and up), +// TODO(brainman): use GetDynamicTimeZoneInformation, whenever possible (Vista and up), // to improve on situation described in the bug above. type zone struct { @@ -46,7 +46,7 @@ func (z *zone) populate(bias, biasdelta int32, d *syscall.Systemtime, name []uin return } -// Pre-calculte cutoff time in seconds since the Unix epoch, if data is supplied in "absolute" format. +// Pre-calculate cutoff time in seconds since the Unix epoch, if data is supplied in "absolute" format. func (z *zone) preCalculateAbsSec() { if z.year != 0 { z.abssec = (&Time{z.year, int(z.month), int(z.day), int(z.hour), int(z.minute), int(z.second), 0, 0, ""}).Seconds() @@ -55,7 +55,7 @@ func (z *zone) preCalculateAbsSec() { } } -// Convert zone cutoff time to sec in number of seconds since the Unix epoch, given particualar year. +// Convert zone cutoff time to sec in number of seconds since the Unix epoch, given particular year. func (z *zone) cutoffSeconds(year int64) int64 { // Windows specifies daylight savings information in "day in month" format: // z.month is month number (1-12) @@ -96,7 +96,7 @@ func (z *zone) isBeforeCutoff(t *Time) bool { } type zoneinfo struct { - disabled bool // daylight saving time is not used localy + disabled bool // daylight saving time is not used locally offsetIfDisabled int januaryIsStd bool // is january 1 standard time? std, dst zone diff --git a/src/pkg/unicode/letter.go b/src/pkg/unicode/letter.go index 382c6eb3f..047bef19b 100644 --- a/src/pkg/unicode/letter.go +++ b/src/pkg/unicode/letter.go @@ -11,13 +11,31 @@ const ( ReplacementChar = 0xFFFD // Represents invalid code points. ) +// RangeTable defines a set of Unicode code points by listing the ranges of +// code points within the set. The ranges are listed in two slices +// to save space: a slice of 16-bit ranges and a slice of 32-bit ranges. +// The two slices must be in sorted order and non-overlapping. +// Also, R32 should contain only values >= 0x10000 (1<<16). +type RangeTable struct { + R16 []Range16 + R32 []Range32 +} -// The representation of a range of Unicode code points. The range runs from Lo to Hi +// Range16 represents of a range of 16-bit Unicode code points. The range runs from Lo to Hi // inclusive and has the specified stride. -type Range struct { - Lo int - Hi int - Stride int +type Range16 struct { + Lo uint16 + Hi uint16 + Stride uint16 +} + +// Range32 represents of a range of Unicode code points and is used when one or +// more of the values will not fit in 16 bits. The range runs from Lo to Hi +// inclusive and has the specified stride. Lo and Hi must always be >= 1<<16. +type Range32 struct { + Lo uint32 + Hi uint32 + Stride uint32 } // CaseRange represents a range of Unicode code points for simple (one @@ -31,8 +49,8 @@ type Range struct { // {UpperLower, UpperLower, UpperLower} // The constant UpperLower has an otherwise impossible delta value. type CaseRange struct { - Lo int - Hi int + Lo uint32 + Hi uint32 Delta d } @@ -60,22 +78,28 @@ const ( UpperLower = MaxRune + 1 // (Cannot be a valid delta.) ) -// Is tests whether rune is in the specified table of ranges. -func Is(ranges []Range, rune int) bool { - // common case: rune is ASCII or Latin-1 - if rune < 0x100 { - for _, r := range ranges { - if rune > r.Hi { - continue - } - if rune < r.Lo { - return false - } +// is16 uses binary search to test whether rune is in the specified slice of 16-bit ranges. +func is16(ranges []Range16, rune uint16) bool { + // binary search over ranges + lo := 0 + hi := len(ranges) + for lo < hi { + m := lo + (hi-lo)/2 + r := ranges[m] + if r.Lo <= rune && rune <= r.Hi { return (rune-r.Lo)%r.Stride == 0 } - return false + if rune < r.Lo { + hi = m + } else { + lo = m + 1 + } } + return false +} +// is32 uses binary search to test whether rune is in the specified slice of 32-bit ranges. +func is32(ranges []Range32, rune uint32) bool { // binary search over ranges lo := 0 hi := len(ranges) @@ -94,6 +118,34 @@ func Is(ranges []Range, rune int) bool { return false } +// Is tests whether rune is in the specified table of ranges. +func Is(rangeTab *RangeTable, rune int) bool { + // common case: rune is ASCII or Latin-1. + if rune < 0x100 { + // Only need to check R16, since R32 is always >= 1<<16. + r16 := uint16(rune) + for _, r := range rangeTab.R16 { + if r16 > r.Hi { + continue + } + if r16 < r.Lo { + return false + } + return (r16-r.Lo)%r.Stride == 0 + } + return false + } + r16 := rangeTab.R16 + if len(r16) > 0 && rune <= int(r16[len(r16)-1].Hi) { + return is16(r16, uint16(rune)) + } + r32 := rangeTab.R32 + if len(r32) > 0 && rune >= int(r32[0].Lo) { + return is32(r32, uint32(rune)) + } + return false +} + // IsUpper reports whether the rune is an upper case letter. func IsUpper(rune int) bool { if rune < 0x80 { // quick ASCII check @@ -150,7 +202,7 @@ func to(_case int, rune int, caseRange []CaseRange) int { for lo < hi { m := lo + (hi-lo)/2 r := caseRange[m] - if r.Lo <= rune && rune <= r.Hi { + if int(r.Lo) <= rune && rune <= int(r.Hi) { delta := int(r.Delta[_case]) if delta > MaxRune { // In an Upper-Lower sequence, which always starts with @@ -163,11 +215,11 @@ func to(_case int, rune int, caseRange []CaseRange) int { // bit in the sequence offset. // The constants UpperCase and TitleCase are even while LowerCase // is odd so we take the low bit from _case. - return r.Lo + ((rune-r.Lo)&^1 | _case&1) + return int(r.Lo) + ((rune-int(r.Lo))&^1 | _case&1) } return rune + delta } - if rune < r.Lo { + if rune < int(r.Lo) { hi = m } else { lo = m + 1 diff --git a/src/pkg/unicode/maketables.go b/src/pkg/unicode/maketables.go index 33a826862..c3cf32b48 100644 --- a/src/pkg/unicode/maketables.go +++ b/src/pkg/unicode/maketables.go @@ -28,6 +28,7 @@ func main() { printScriptOrProperty(false) printScriptOrProperty(true) printCases() + printSizes() } var dataURL = flag.String("data", "", "full URL for UnicodeData.txt; defaults to --url/UnicodeData.txt") @@ -278,16 +279,16 @@ func loadChars() { switch parseCategory(line[0 : len(line)-1]) { case SNormal: if first != 0 { - logger.Fatalf("bad state normal at U+%04X", lastChar) + logger.Fatalf("bad state normal at %U", lastChar) } case SFirst: if first != 0 { - logger.Fatalf("bad state first at U+%04X", lastChar) + logger.Fatalf("bad state first at %U", lastChar) } first = lastChar case SLast: if first == 0 { - logger.Fatalf("bad state last at U+%04X", lastChar) + logger.Fatalf("bad state last at %U", lastChar) } for i := first + 1; i <= lastChar; i++ { chars[i] = chars[first] @@ -299,6 +300,15 @@ func loadChars() { resp.Body.Close() } +const progHeader = `// Generated by running +// maketables --tables=%s --data=%s +// DO NOT EDIT + +package unicode + +` + + func printCategories() { if *tablelist == "" { return @@ -312,20 +322,14 @@ func printCategories() { fullCategoryTest(list) return } - fmt.Printf( - "// Generated by running\n"+ - "// maketables --tables=%s --data=%s\n"+ - "// DO NOT EDIT\n\n"+ - "package unicode\n\n", - *tablelist, - *dataURL) + fmt.Printf(progHeader, *tablelist, *dataURL) fmt.Println("// Version is the Unicode edition from which the tables are derived.") fmt.Printf("const Version = %q\n\n", version()) if *tablelist == "all" { fmt.Println("// Categories is the set of Unicode data tables.") - fmt.Println("var Categories = map[string] []Range {") + fmt.Println("var Categories = map[string] *RangeTable {") for k := range category { fmt.Printf("\t%q: %s,\n", k, k) } @@ -364,12 +368,12 @@ func printCategories() { ndecl++ if name == "letter" { // special case dumpRange( - "var letter = []Range {\n", + "var letter = &RangeTable{\n", letterOp) continue } dumpRange( - fmt.Sprintf("var _%s = []Range {\n", name), + fmt.Sprintf("var _%s = &RangeTable{\n", name), func(code int) bool { return chars[code].category == name }) } decl.Sort() @@ -382,12 +386,15 @@ func printCategories() { type Op func(code int) bool -const format = "\t{0x%04x, 0x%04x, %d},\n" +const format = "\t\t{0x%04x, 0x%04x, %d},\n" func dumpRange(header string, inCategory Op) { fmt.Print(header) next := 0 + fmt.Print("\tR16: []Range16{\n") // one Range for each iteration + count := &range16Count + size := 16 for { // look for start of range for next < len(chars) && !inCategory(next) { @@ -427,13 +434,38 @@ func dumpRange(header string, inCategory Op) { break } } - fmt.Printf(format, lo, hi, stride) + size, count = printRange(uint32(lo), uint32(hi), uint32(stride), size, count) // next range: start looking where this range ends next = hi + 1 } + fmt.Print("\t},\n") fmt.Print("}\n\n") } +func printRange(lo, hi, stride uint32, size int, count *int) (int, *int) { + if size == 16 && hi >= 1<<16 { + if lo < 1<<16 { + if lo+stride != hi { + log.Fatalf("unexpected straddle: %U %U %d", lo, hi, stride) + } + // No range contains U+FFFF as an instance, so split + // the range into two entries. That way we can maintain + // the invariant that R32 contains only >= 1<<16. + fmt.Printf(format, lo, lo, 1) + lo = hi + stride = 1 + *count++ + } + fmt.Print("\t},\n") + fmt.Print("\tR32: []Range32{\n") + size = 32 + count = &range32Count + } + fmt.Printf(format, lo, hi, stride) + *count++ + return size, count +} + func fullCategoryTest(list []string) { for _, name := range list { if _, ok := category[name]; !ok { @@ -454,12 +486,12 @@ func fullCategoryTest(list []string) { } } -func verifyRange(name string, inCategory Op, table []unicode.Range) { +func verifyRange(name string, inCategory Op, table *unicode.RangeTable) { for i := range chars { web := inCategory(i) pkg := unicode.Is(table, i) if web != pkg { - fmt.Fprintf(os.Stderr, "%s: U+%04X: web=%t pkg=%t\n", name, i, web, pkg) + fmt.Fprintf(os.Stderr, "%s: %U: web=%t pkg=%t\n", name, i, web, pkg) } } } @@ -497,22 +529,22 @@ func parseScript(line string, scripts map[string][]Script) { } // The script tables have a lot of adjacent elements. Fold them together. -func foldAdjacent(r []Script) []unicode.Range { - s := make([]unicode.Range, 0, len(r)) +func foldAdjacent(r []Script) []unicode.Range32 { + s := make([]unicode.Range32, 0, len(r)) j := 0 for i := 0; i < len(r); i++ { - if j > 0 && int(r[i].lo) == s[j-1].Hi+1 { - s[j-1].Hi = int(r[i].hi) + if j > 0 && r[i].lo == s[j-1].Hi+1 { + s[j-1].Hi = r[i].hi } else { s = s[0 : j+1] - s[j] = unicode.Range{int(r[i].lo), int(r[i].hi), 1} + s[j] = unicode.Range32{uint32(r[i].lo), uint32(r[i].hi), 1} j++ } } return s } -func fullScriptTest(list []string, installed map[string][]unicode.Range, scripts map[string][]Script) { +func fullScriptTest(list []string, installed map[string]*unicode.RangeTable, scripts map[string][]Script) { for _, name := range list { if _, ok := scripts[name]; !ok { logger.Fatal("unknown script", name) @@ -524,7 +556,7 @@ func fullScriptTest(list []string, installed map[string][]unicode.Range, scripts for _, script := range scripts[name] { for r := script.lo; r <= script.hi; r++ { if !unicode.Is(installed[name], int(r)) { - fmt.Fprintf(os.Stderr, "U+%04X: not in script %s\n", r, name) + fmt.Fprintf(os.Stderr, "%U: not in script %s\n", r, name) } } } @@ -589,10 +621,10 @@ func printScriptOrProperty(doProps bool) { if flaglist == "all" { if doProps { fmt.Println("// Properties is the set of Unicode property tables.") - fmt.Println("var Properties = map[string] []Range {") + fmt.Println("var Properties = map[string] *RangeTable{") } else { fmt.Println("// Scripts is the set of Unicode script tables.") - fmt.Println("var Scripts = map[string] []Range {") + fmt.Println("var Scripts = map[string] *RangeTable{") } for k := range table { fmt.Printf("\t%q: %s,\n", k, k) @@ -613,11 +645,15 @@ func printScriptOrProperty(doProps bool) { name, name, name, name) } ndecl++ - fmt.Printf("var _%s = []Range {\n", name) + fmt.Printf("var _%s = &RangeTable {\n", name) + fmt.Print("\tR16: []Range16{\n") ranges := foldAdjacent(table[name]) + size := 16 + count := &range16Count for _, s := range ranges { - fmt.Printf(format, s.Lo, s.Hi, s.Stride) + size, count = printRange(s.Lo, s.Hi, s.Stride, size, count) } + fmt.Print("\t},\n") fmt.Print("}\n\n") } decl.Sort() @@ -808,7 +844,7 @@ func printCaseRange(lo, hi *caseState) { fmt.Printf("\t{0x%04X, 0x%04X, d{UpperLower, UpperLower, UpperLower}},\n", lo.point, hi.point) case hi.point > lo.point && lo.isLowerUpper(): - logger.Fatalf("LowerUpper sequence: should not happen: U+%04X. If it's real, need to fix To()", lo.point) + logger.Fatalf("LowerUpper sequence: should not happen: %U. If it's real, need to fix To()", lo.point) fmt.Printf("\t{0x%04X, 0x%04X, d{LowerUpper, LowerUpper, LowerUpper}},\n", lo.point, hi.point) default: @@ -831,17 +867,31 @@ func fullCaseTest() { lower := unicode.ToLower(i) want := caseIt(i, c.lowerCase) if lower != want { - fmt.Fprintf(os.Stderr, "lower U+%04X should be U+%04X is U+%04X\n", i, want, lower) + fmt.Fprintf(os.Stderr, "lower %U should be %U is %U\n", i, want, lower) } upper := unicode.ToUpper(i) want = caseIt(i, c.upperCase) if upper != want { - fmt.Fprintf(os.Stderr, "upper U+%04X should be U+%04X is U+%04X\n", i, want, upper) + fmt.Fprintf(os.Stderr, "upper %U should be %U is %U\n", i, want, upper) } title := unicode.ToTitle(i) want = caseIt(i, c.titleCase) if title != want { - fmt.Fprintf(os.Stderr, "title U+%04X should be U+%04X is U+%04X\n", i, want, title) + fmt.Fprintf(os.Stderr, "title %U should be %U is %U\n", i, want, title) } } } + +var range16Count = 0 // Number of entries in the 16-bit range tables. +var range32Count = 0 // Number of entries in the 32-bit range tables. + +func printSizes() { + if *test { + return + } + fmt.Println() + fmt.Printf("// Range entries: %d 16-bit, %d 32-bit, %d total.\n", range16Count, range32Count, range16Count+range32Count) + range16Bytes := range16Count * 3 * 2 + range32Bytes := range32Count * 3 * 4 + fmt.Printf("// Range bytes: %d 16-bit, %d 32-bit, %d total.\n", range16Bytes, range32Bytes, range16Bytes+range32Bytes) +} diff --git a/src/pkg/unicode/tables.go b/src/pkg/unicode/tables.go index 89fd99411..fc2bdd8d2 100644 --- a/src/pkg/unicode/tables.go +++ b/src/pkg/unicode/tables.go @@ -8,7 +8,7 @@ package unicode const Version = "6.0.0" // Categories is the set of Unicode data tables. -var Categories = map[string][]Range{ +var Categories = map[string]*RangeTable{ "Lm": Lm, "Ll": Ll, "Me": Me, @@ -41,1939 +41,2030 @@ var Categories = map[string][]Range{ "Lo": Lo, } -var _Lm = []Range{ - {0x02b0, 0x02c1, 1}, - {0x02c6, 0x02d1, 1}, - {0x02e0, 0x02e4, 1}, - {0x02ec, 0x02ee, 2}, - {0x0374, 0x037a, 6}, - {0x0559, 0x0640, 231}, - {0x06e5, 0x06e6, 1}, - {0x07f4, 0x07f5, 1}, - {0x07fa, 0x081a, 32}, - {0x0824, 0x0828, 4}, - {0x0971, 0x0e46, 1237}, - {0x0ec6, 0x10fc, 566}, - {0x17d7, 0x1843, 108}, - {0x1aa7, 0x1c78, 465}, - {0x1c79, 0x1c7d, 1}, - {0x1d2c, 0x1d61, 1}, - {0x1d78, 0x1d9b, 35}, - {0x1d9c, 0x1dbf, 1}, - {0x2071, 0x207f, 14}, - {0x2090, 0x209c, 1}, - {0x2c7d, 0x2d6f, 242}, - {0x2e2f, 0x3005, 470}, - {0x3031, 0x3035, 1}, - {0x303b, 0x309d, 98}, - {0x309e, 0x30fc, 94}, - {0x30fd, 0x30fe, 1}, - {0xa015, 0xa4f8, 1251}, - {0xa4f9, 0xa4fd, 1}, - {0xa60c, 0xa67f, 115}, - {0xa717, 0xa71f, 1}, - {0xa770, 0xa788, 24}, - {0xa9cf, 0xaa70, 161}, - {0xaadd, 0xff70, 21651}, - {0xff9e, 0xff9f, 1}, -} - -var _Ll = []Range{ - {0x0061, 0x007a, 1}, - {0x00aa, 0x00b5, 11}, - {0x00ba, 0x00df, 37}, - {0x00e0, 0x00f6, 1}, - {0x00f8, 0x00ff, 1}, - {0x0101, 0x0137, 2}, - {0x0138, 0x0148, 2}, - {0x0149, 0x0177, 2}, - {0x017a, 0x017e, 2}, - {0x017f, 0x0180, 1}, - {0x0183, 0x0185, 2}, - {0x0188, 0x018c, 4}, - {0x018d, 0x0192, 5}, - {0x0195, 0x0199, 4}, - {0x019a, 0x019b, 1}, - {0x019e, 0x01a1, 3}, - {0x01a3, 0x01a5, 2}, - {0x01a8, 0x01aa, 2}, - {0x01ab, 0x01ad, 2}, - {0x01b0, 0x01b4, 4}, - {0x01b6, 0x01b9, 3}, - {0x01ba, 0x01bd, 3}, - {0x01be, 0x01bf, 1}, - {0x01c6, 0x01cc, 3}, - {0x01ce, 0x01dc, 2}, - {0x01dd, 0x01ef, 2}, - {0x01f0, 0x01f3, 3}, - {0x01f5, 0x01f9, 4}, - {0x01fb, 0x0233, 2}, - {0x0234, 0x0239, 1}, - {0x023c, 0x023f, 3}, - {0x0240, 0x0242, 2}, - {0x0247, 0x024f, 2}, - {0x0250, 0x0293, 1}, - {0x0295, 0x02af, 1}, - {0x0371, 0x0373, 2}, - {0x0377, 0x037b, 4}, - {0x037c, 0x037d, 1}, - {0x0390, 0x03ac, 28}, - {0x03ad, 0x03ce, 1}, - {0x03d0, 0x03d1, 1}, - {0x03d5, 0x03d7, 1}, - {0x03d9, 0x03ef, 2}, - {0x03f0, 0x03f3, 1}, - {0x03f5, 0x03fb, 3}, - {0x03fc, 0x0430, 52}, - {0x0431, 0x045f, 1}, - {0x0461, 0x0481, 2}, - {0x048b, 0x04bf, 2}, - {0x04c2, 0x04ce, 2}, - {0x04cf, 0x0527, 2}, - {0x0561, 0x0587, 1}, - {0x1d00, 0x1d2b, 1}, - {0x1d62, 0x1d77, 1}, - {0x1d79, 0x1d9a, 1}, - {0x1e01, 0x1e95, 2}, - {0x1e96, 0x1e9d, 1}, - {0x1e9f, 0x1eff, 2}, - {0x1f00, 0x1f07, 1}, - {0x1f10, 0x1f15, 1}, - {0x1f20, 0x1f27, 1}, - {0x1f30, 0x1f37, 1}, - {0x1f40, 0x1f45, 1}, - {0x1f50, 0x1f57, 1}, - {0x1f60, 0x1f67, 1}, - {0x1f70, 0x1f7d, 1}, - {0x1f80, 0x1f87, 1}, - {0x1f90, 0x1f97, 1}, - {0x1fa0, 0x1fa7, 1}, - {0x1fb0, 0x1fb4, 1}, - {0x1fb6, 0x1fb7, 1}, - {0x1fbe, 0x1fc2, 4}, - {0x1fc3, 0x1fc4, 1}, - {0x1fc6, 0x1fc7, 1}, - {0x1fd0, 0x1fd3, 1}, - {0x1fd6, 0x1fd7, 1}, - {0x1fe0, 0x1fe7, 1}, - {0x1ff2, 0x1ff4, 1}, - {0x1ff6, 0x1ff7, 1}, - {0x210a, 0x210e, 4}, - {0x210f, 0x2113, 4}, - {0x212f, 0x2139, 5}, - {0x213c, 0x213d, 1}, - {0x2146, 0x2149, 1}, - {0x214e, 0x2184, 54}, - {0x2c30, 0x2c5e, 1}, - {0x2c61, 0x2c65, 4}, - {0x2c66, 0x2c6c, 2}, - {0x2c71, 0x2c73, 2}, - {0x2c74, 0x2c76, 2}, - {0x2c77, 0x2c7c, 1}, - {0x2c81, 0x2ce3, 2}, - {0x2ce4, 0x2cec, 8}, - {0x2cee, 0x2d00, 18}, - {0x2d01, 0x2d25, 1}, - {0xa641, 0xa66d, 2}, - {0xa681, 0xa697, 2}, - {0xa723, 0xa72f, 2}, - {0xa730, 0xa731, 1}, - {0xa733, 0xa771, 2}, - {0xa772, 0xa778, 1}, - {0xa77a, 0xa77c, 2}, - {0xa77f, 0xa787, 2}, - {0xa78c, 0xa78e, 2}, - {0xa791, 0xa7a1, 16}, - {0xa7a3, 0xa7a9, 2}, - {0xa7fa, 0xfb00, 21254}, - {0xfb01, 0xfb06, 1}, - {0xfb13, 0xfb17, 1}, - {0xff41, 0xff5a, 1}, - {0x10428, 0x1044f, 1}, - {0x1d41a, 0x1d433, 1}, - {0x1d44e, 0x1d454, 1}, - {0x1d456, 0x1d467, 1}, - {0x1d482, 0x1d49b, 1}, - {0x1d4b6, 0x1d4b9, 1}, - {0x1d4bb, 0x1d4bd, 2}, - {0x1d4be, 0x1d4c3, 1}, - {0x1d4c5, 0x1d4cf, 1}, - {0x1d4ea, 0x1d503, 1}, - {0x1d51e, 0x1d537, 1}, - {0x1d552, 0x1d56b, 1}, - {0x1d586, 0x1d59f, 1}, - {0x1d5ba, 0x1d5d3, 1}, - {0x1d5ee, 0x1d607, 1}, - {0x1d622, 0x1d63b, 1}, - {0x1d656, 0x1d66f, 1}, - {0x1d68a, 0x1d6a5, 1}, - {0x1d6c2, 0x1d6da, 1}, - {0x1d6dc, 0x1d6e1, 1}, - {0x1d6fc, 0x1d714, 1}, - {0x1d716, 0x1d71b, 1}, - {0x1d736, 0x1d74e, 1}, - {0x1d750, 0x1d755, 1}, - {0x1d770, 0x1d788, 1}, - {0x1d78a, 0x1d78f, 1}, - {0x1d7aa, 0x1d7c2, 1}, - {0x1d7c4, 0x1d7c9, 1}, - {0x1d7cb, 0x1d7cb, 1}, -} - -var _Me = []Range{ - {0x0488, 0x0489, 1}, - {0x20dd, 0x20e0, 1}, - {0x20e2, 0x20e4, 1}, - {0xa670, 0xa672, 1}, -} - -var _Mc = []Range{ - {0x0903, 0x093b, 56}, - {0x093e, 0x0940, 1}, - {0x0949, 0x094c, 1}, - {0x094e, 0x094f, 1}, - {0x0982, 0x0983, 1}, - {0x09be, 0x09c0, 1}, - {0x09c7, 0x09c8, 1}, - {0x09cb, 0x09cc, 1}, - {0x09d7, 0x0a03, 44}, - {0x0a3e, 0x0a40, 1}, - {0x0a83, 0x0abe, 59}, - {0x0abf, 0x0ac0, 1}, - {0x0ac9, 0x0acb, 2}, - {0x0acc, 0x0b02, 54}, - {0x0b03, 0x0b3e, 59}, - {0x0b40, 0x0b47, 7}, - {0x0b48, 0x0b4b, 3}, - {0x0b4c, 0x0b57, 11}, - {0x0bbe, 0x0bbf, 1}, - {0x0bc1, 0x0bc2, 1}, - {0x0bc6, 0x0bc8, 1}, - {0x0bca, 0x0bcc, 1}, - {0x0bd7, 0x0c01, 42}, - {0x0c02, 0x0c03, 1}, - {0x0c41, 0x0c44, 1}, - {0x0c82, 0x0c83, 1}, - {0x0cbe, 0x0cc0, 2}, - {0x0cc1, 0x0cc4, 1}, - {0x0cc7, 0x0cc8, 1}, - {0x0cca, 0x0ccb, 1}, - {0x0cd5, 0x0cd6, 1}, - {0x0d02, 0x0d03, 1}, - {0x0d3e, 0x0d40, 1}, - {0x0d46, 0x0d48, 1}, - {0x0d4a, 0x0d4c, 1}, - {0x0d57, 0x0d82, 43}, - {0x0d83, 0x0dcf, 76}, - {0x0dd0, 0x0dd1, 1}, - {0x0dd8, 0x0ddf, 1}, - {0x0df2, 0x0df3, 1}, - {0x0f3e, 0x0f3f, 1}, - {0x0f7f, 0x102b, 172}, - {0x102c, 0x1031, 5}, - {0x1038, 0x103b, 3}, - {0x103c, 0x1056, 26}, - {0x1057, 0x1062, 11}, - {0x1063, 0x1064, 1}, - {0x1067, 0x106d, 1}, - {0x1083, 0x1084, 1}, - {0x1087, 0x108c, 1}, - {0x108f, 0x109a, 11}, - {0x109b, 0x109c, 1}, - {0x17b6, 0x17be, 8}, - {0x17bf, 0x17c5, 1}, - {0x17c7, 0x17c8, 1}, - {0x1923, 0x1926, 1}, - {0x1929, 0x192b, 1}, - {0x1930, 0x1931, 1}, - {0x1933, 0x1938, 1}, - {0x19b0, 0x19c0, 1}, - {0x19c8, 0x19c9, 1}, - {0x1a19, 0x1a1b, 1}, - {0x1a55, 0x1a57, 2}, - {0x1a61, 0x1a63, 2}, - {0x1a64, 0x1a6d, 9}, - {0x1a6e, 0x1a72, 1}, - {0x1b04, 0x1b35, 49}, - {0x1b3b, 0x1b3d, 2}, - {0x1b3e, 0x1b41, 1}, - {0x1b43, 0x1b44, 1}, - {0x1b82, 0x1ba1, 31}, - {0x1ba6, 0x1ba7, 1}, - {0x1baa, 0x1be7, 61}, - {0x1bea, 0x1bec, 1}, - {0x1bee, 0x1bf2, 4}, - {0x1bf3, 0x1c24, 49}, - {0x1c25, 0x1c2b, 1}, - {0x1c34, 0x1c35, 1}, - {0x1ce1, 0x1cf2, 17}, - {0xa823, 0xa824, 1}, - {0xa827, 0xa880, 89}, - {0xa881, 0xa8b4, 51}, - {0xa8b5, 0xa8c3, 1}, - {0xa952, 0xa953, 1}, - {0xa983, 0xa9b4, 49}, - {0xa9b5, 0xa9ba, 5}, - {0xa9bb, 0xa9bd, 2}, - {0xa9be, 0xa9c0, 1}, - {0xaa2f, 0xaa30, 1}, - {0xaa33, 0xaa34, 1}, - {0xaa4d, 0xaa7b, 46}, - {0xabe3, 0xabe4, 1}, - {0xabe6, 0xabe7, 1}, - {0xabe9, 0xabea, 1}, - {0xabec, 0x11000, 25620}, - {0x11002, 0x11082, 128}, - {0x110b0, 0x110b2, 1}, - {0x110b7, 0x110b8, 1}, - {0x1d165, 0x1d166, 1}, - {0x1d16d, 0x1d172, 1}, -} - -var _Mn = []Range{ - {0x0300, 0x036f, 1}, - {0x0483, 0x0487, 1}, - {0x0591, 0x05bd, 1}, - {0x05bf, 0x05c1, 2}, - {0x05c2, 0x05c4, 2}, - {0x05c5, 0x05c7, 2}, - {0x0610, 0x061a, 1}, - {0x064b, 0x065f, 1}, - {0x0670, 0x06d6, 102}, - {0x06d7, 0x06dc, 1}, - {0x06df, 0x06e4, 1}, - {0x06e7, 0x06e8, 1}, - {0x06ea, 0x06ed, 1}, - {0x0711, 0x0730, 31}, - {0x0731, 0x074a, 1}, - {0x07a6, 0x07b0, 1}, - {0x07eb, 0x07f3, 1}, - {0x0816, 0x0819, 1}, - {0x081b, 0x0823, 1}, - {0x0825, 0x0827, 1}, - {0x0829, 0x082d, 1}, - {0x0859, 0x085b, 1}, - {0x0900, 0x0902, 1}, - {0x093a, 0x093c, 2}, - {0x0941, 0x0948, 1}, - {0x094d, 0x0951, 4}, - {0x0952, 0x0957, 1}, - {0x0962, 0x0963, 1}, - {0x0981, 0x09bc, 59}, - {0x09c1, 0x09c4, 1}, - {0x09cd, 0x09e2, 21}, - {0x09e3, 0x0a01, 30}, - {0x0a02, 0x0a3c, 58}, - {0x0a41, 0x0a42, 1}, - {0x0a47, 0x0a48, 1}, - {0x0a4b, 0x0a4d, 1}, - {0x0a51, 0x0a70, 31}, - {0x0a71, 0x0a75, 4}, - {0x0a81, 0x0a82, 1}, - {0x0abc, 0x0ac1, 5}, - {0x0ac2, 0x0ac5, 1}, - {0x0ac7, 0x0ac8, 1}, - {0x0acd, 0x0ae2, 21}, - {0x0ae3, 0x0b01, 30}, - {0x0b3c, 0x0b3f, 3}, - {0x0b41, 0x0b44, 1}, - {0x0b4d, 0x0b56, 9}, - {0x0b62, 0x0b63, 1}, - {0x0b82, 0x0bc0, 62}, - {0x0bcd, 0x0c3e, 113}, - {0x0c3f, 0x0c40, 1}, - {0x0c46, 0x0c48, 1}, - {0x0c4a, 0x0c4d, 1}, - {0x0c55, 0x0c56, 1}, - {0x0c62, 0x0c63, 1}, - {0x0cbc, 0x0cbf, 3}, - {0x0cc6, 0x0ccc, 6}, - {0x0ccd, 0x0ce2, 21}, - {0x0ce3, 0x0d41, 94}, - {0x0d42, 0x0d44, 1}, - {0x0d4d, 0x0d62, 21}, - {0x0d63, 0x0dca, 103}, - {0x0dd2, 0x0dd4, 1}, - {0x0dd6, 0x0e31, 91}, - {0x0e34, 0x0e3a, 1}, - {0x0e47, 0x0e4e, 1}, - {0x0eb1, 0x0eb4, 3}, - {0x0eb5, 0x0eb9, 1}, - {0x0ebb, 0x0ebc, 1}, - {0x0ec8, 0x0ecd, 1}, - {0x0f18, 0x0f19, 1}, - {0x0f35, 0x0f39, 2}, - {0x0f71, 0x0f7e, 1}, - {0x0f80, 0x0f84, 1}, - {0x0f86, 0x0f87, 1}, - {0x0f8d, 0x0f97, 1}, - {0x0f99, 0x0fbc, 1}, - {0x0fc6, 0x102d, 103}, - {0x102e, 0x1030, 1}, - {0x1032, 0x1037, 1}, - {0x1039, 0x103a, 1}, - {0x103d, 0x103e, 1}, - {0x1058, 0x1059, 1}, - {0x105e, 0x1060, 1}, - {0x1071, 0x1074, 1}, - {0x1082, 0x1085, 3}, - {0x1086, 0x108d, 7}, - {0x109d, 0x135d, 704}, - {0x135e, 0x135f, 1}, - {0x1712, 0x1714, 1}, - {0x1732, 0x1734, 1}, - {0x1752, 0x1753, 1}, - {0x1772, 0x1773, 1}, - {0x17b7, 0x17bd, 1}, - {0x17c6, 0x17c9, 3}, - {0x17ca, 0x17d3, 1}, - {0x17dd, 0x180b, 46}, - {0x180c, 0x180d, 1}, - {0x18a9, 0x1920, 119}, - {0x1921, 0x1922, 1}, - {0x1927, 0x1928, 1}, - {0x1932, 0x1939, 7}, - {0x193a, 0x193b, 1}, - {0x1a17, 0x1a18, 1}, - {0x1a56, 0x1a58, 2}, - {0x1a59, 0x1a5e, 1}, - {0x1a60, 0x1a62, 2}, - {0x1a65, 0x1a6c, 1}, - {0x1a73, 0x1a7c, 1}, - {0x1a7f, 0x1b00, 129}, - {0x1b01, 0x1b03, 1}, - {0x1b34, 0x1b36, 2}, - {0x1b37, 0x1b3a, 1}, - {0x1b3c, 0x1b42, 6}, - {0x1b6b, 0x1b73, 1}, - {0x1b80, 0x1b81, 1}, - {0x1ba2, 0x1ba5, 1}, - {0x1ba8, 0x1ba9, 1}, - {0x1be6, 0x1be8, 2}, - {0x1be9, 0x1bed, 4}, - {0x1bef, 0x1bf1, 1}, - {0x1c2c, 0x1c33, 1}, - {0x1c36, 0x1c37, 1}, - {0x1cd0, 0x1cd2, 1}, - {0x1cd4, 0x1ce0, 1}, - {0x1ce2, 0x1ce8, 1}, - {0x1ced, 0x1dc0, 211}, - {0x1dc1, 0x1de6, 1}, - {0x1dfc, 0x1dff, 1}, - {0x20d0, 0x20dc, 1}, - {0x20e1, 0x20e5, 4}, - {0x20e6, 0x20f0, 1}, - {0x2cef, 0x2cf1, 1}, - {0x2d7f, 0x2de0, 97}, - {0x2de1, 0x2dff, 1}, - {0x302a, 0x302f, 1}, - {0x3099, 0x309a, 1}, - {0xa66f, 0xa67c, 13}, - {0xa67d, 0xa6f0, 115}, - {0xa6f1, 0xa802, 273}, - {0xa806, 0xa80b, 5}, - {0xa825, 0xa826, 1}, - {0xa8c4, 0xa8e0, 28}, - {0xa8e1, 0xa8f1, 1}, - {0xa926, 0xa92d, 1}, - {0xa947, 0xa951, 1}, - {0xa980, 0xa982, 1}, - {0xa9b3, 0xa9b6, 3}, - {0xa9b7, 0xa9b9, 1}, - {0xa9bc, 0xaa29, 109}, - {0xaa2a, 0xaa2e, 1}, - {0xaa31, 0xaa32, 1}, - {0xaa35, 0xaa36, 1}, - {0xaa43, 0xaa4c, 9}, - {0xaab0, 0xaab2, 2}, - {0xaab3, 0xaab4, 1}, - {0xaab7, 0xaab8, 1}, - {0xaabe, 0xaabf, 1}, - {0xaac1, 0xabe5, 292}, - {0xabe8, 0xabed, 5}, - {0xfb1e, 0xfe00, 738}, - {0xfe01, 0xfe0f, 1}, - {0xfe20, 0xfe26, 1}, - {0x101fd, 0x10a01, 2052}, - {0x10a02, 0x10a03, 1}, - {0x10a05, 0x10a06, 1}, - {0x10a0c, 0x10a0f, 1}, - {0x10a38, 0x10a3a, 1}, - {0x10a3f, 0x11001, 1474}, - {0x11038, 0x11046, 1}, - {0x11080, 0x11081, 1}, - {0x110b3, 0x110b6, 1}, - {0x110b9, 0x110ba, 1}, - {0x1d167, 0x1d169, 1}, - {0x1d17b, 0x1d182, 1}, - {0x1d185, 0x1d18b, 1}, - {0x1d1aa, 0x1d1ad, 1}, - {0x1d242, 0x1d244, 1}, - {0xe0100, 0xe01ef, 1}, -} - -var _Zl = []Range{ - {0x2028, 0x2028, 1}, -} - -var letter = []Range{ - {0x0041, 0x005a, 1}, - {0x0061, 0x007a, 1}, - {0x00aa, 0x00b5, 11}, - {0x00ba, 0x00c0, 6}, - {0x00c1, 0x00d6, 1}, - {0x00d8, 0x00f6, 1}, - {0x00f8, 0x02c1, 1}, - {0x02c6, 0x02d1, 1}, - {0x02e0, 0x02e4, 1}, - {0x02ec, 0x02ee, 2}, - {0x0370, 0x0374, 1}, - {0x0376, 0x0377, 1}, - {0x037a, 0x037d, 1}, - {0x0386, 0x0388, 2}, - {0x0389, 0x038a, 1}, - {0x038c, 0x038e, 2}, - {0x038f, 0x03a1, 1}, - {0x03a3, 0x03f5, 1}, - {0x03f7, 0x0481, 1}, - {0x048a, 0x0527, 1}, - {0x0531, 0x0556, 1}, - {0x0559, 0x0561, 8}, - {0x0562, 0x0587, 1}, - {0x05d0, 0x05ea, 1}, - {0x05f0, 0x05f2, 1}, - {0x0620, 0x064a, 1}, - {0x066e, 0x066f, 1}, - {0x0671, 0x06d3, 1}, - {0x06d5, 0x06e5, 16}, - {0x06e6, 0x06ee, 8}, - {0x06ef, 0x06fa, 11}, - {0x06fb, 0x06fc, 1}, - {0x06ff, 0x0710, 17}, - {0x0712, 0x072f, 1}, - {0x074d, 0x07a5, 1}, - {0x07b1, 0x07ca, 25}, - {0x07cb, 0x07ea, 1}, - {0x07f4, 0x07f5, 1}, - {0x07fa, 0x0800, 6}, - {0x0801, 0x0815, 1}, - {0x081a, 0x0824, 10}, - {0x0828, 0x0840, 24}, - {0x0841, 0x0858, 1}, - {0x0904, 0x0939, 1}, - {0x093d, 0x0950, 19}, - {0x0958, 0x0961, 1}, - {0x0971, 0x0977, 1}, - {0x0979, 0x097f, 1}, - {0x0985, 0x098c, 1}, - {0x098f, 0x0990, 1}, - {0x0993, 0x09a8, 1}, - {0x09aa, 0x09b0, 1}, - {0x09b2, 0x09b6, 4}, - {0x09b7, 0x09b9, 1}, - {0x09bd, 0x09ce, 17}, - {0x09dc, 0x09dd, 1}, - {0x09df, 0x09e1, 1}, - {0x09f0, 0x09f1, 1}, - {0x0a05, 0x0a0a, 1}, - {0x0a0f, 0x0a10, 1}, - {0x0a13, 0x0a28, 1}, - {0x0a2a, 0x0a30, 1}, - {0x0a32, 0x0a33, 1}, - {0x0a35, 0x0a36, 1}, - {0x0a38, 0x0a39, 1}, - {0x0a59, 0x0a5c, 1}, - {0x0a5e, 0x0a72, 20}, - {0x0a73, 0x0a74, 1}, - {0x0a85, 0x0a8d, 1}, - {0x0a8f, 0x0a91, 1}, - {0x0a93, 0x0aa8, 1}, - {0x0aaa, 0x0ab0, 1}, - {0x0ab2, 0x0ab3, 1}, - {0x0ab5, 0x0ab9, 1}, - {0x0abd, 0x0ad0, 19}, - {0x0ae0, 0x0ae1, 1}, - {0x0b05, 0x0b0c, 1}, - {0x0b0f, 0x0b10, 1}, - {0x0b13, 0x0b28, 1}, - {0x0b2a, 0x0b30, 1}, - {0x0b32, 0x0b33, 1}, - {0x0b35, 0x0b39, 1}, - {0x0b3d, 0x0b5c, 31}, - {0x0b5d, 0x0b5f, 2}, - {0x0b60, 0x0b61, 1}, - {0x0b71, 0x0b83, 18}, - {0x0b85, 0x0b8a, 1}, - {0x0b8e, 0x0b90, 1}, - {0x0b92, 0x0b95, 1}, - {0x0b99, 0x0b9a, 1}, - {0x0b9c, 0x0b9e, 2}, - {0x0b9f, 0x0ba3, 4}, - {0x0ba4, 0x0ba8, 4}, - {0x0ba9, 0x0baa, 1}, - {0x0bae, 0x0bb9, 1}, - {0x0bd0, 0x0c05, 53}, - {0x0c06, 0x0c0c, 1}, - {0x0c0e, 0x0c10, 1}, - {0x0c12, 0x0c28, 1}, - {0x0c2a, 0x0c33, 1}, - {0x0c35, 0x0c39, 1}, - {0x0c3d, 0x0c58, 27}, - {0x0c59, 0x0c60, 7}, - {0x0c61, 0x0c85, 36}, - {0x0c86, 0x0c8c, 1}, - {0x0c8e, 0x0c90, 1}, - {0x0c92, 0x0ca8, 1}, - {0x0caa, 0x0cb3, 1}, - {0x0cb5, 0x0cb9, 1}, - {0x0cbd, 0x0cde, 33}, - {0x0ce0, 0x0ce1, 1}, - {0x0cf1, 0x0cf2, 1}, - {0x0d05, 0x0d0c, 1}, - {0x0d0e, 0x0d10, 1}, - {0x0d12, 0x0d3a, 1}, - {0x0d3d, 0x0d4e, 17}, - {0x0d60, 0x0d61, 1}, - {0x0d7a, 0x0d7f, 1}, - {0x0d85, 0x0d96, 1}, - {0x0d9a, 0x0db1, 1}, - {0x0db3, 0x0dbb, 1}, - {0x0dbd, 0x0dc0, 3}, - {0x0dc1, 0x0dc6, 1}, - {0x0e01, 0x0e30, 1}, - {0x0e32, 0x0e33, 1}, - {0x0e40, 0x0e46, 1}, - {0x0e81, 0x0e82, 1}, - {0x0e84, 0x0e87, 3}, - {0x0e88, 0x0e8a, 2}, - {0x0e8d, 0x0e94, 7}, - {0x0e95, 0x0e97, 1}, - {0x0e99, 0x0e9f, 1}, - {0x0ea1, 0x0ea3, 1}, - {0x0ea5, 0x0ea7, 2}, - {0x0eaa, 0x0eab, 1}, - {0x0ead, 0x0eb0, 1}, - {0x0eb2, 0x0eb3, 1}, - {0x0ebd, 0x0ec0, 3}, - {0x0ec1, 0x0ec4, 1}, - {0x0ec6, 0x0edc, 22}, - {0x0edd, 0x0f00, 35}, - {0x0f40, 0x0f47, 1}, - {0x0f49, 0x0f6c, 1}, - {0x0f88, 0x0f8c, 1}, - {0x1000, 0x102a, 1}, - {0x103f, 0x1050, 17}, - {0x1051, 0x1055, 1}, - {0x105a, 0x105d, 1}, - {0x1061, 0x1065, 4}, - {0x1066, 0x106e, 8}, - {0x106f, 0x1070, 1}, - {0x1075, 0x1081, 1}, - {0x108e, 0x10a0, 18}, - {0x10a1, 0x10c5, 1}, - {0x10d0, 0x10fa, 1}, - {0x10fc, 0x1100, 4}, - {0x1101, 0x1248, 1}, - {0x124a, 0x124d, 1}, - {0x1250, 0x1256, 1}, - {0x1258, 0x125a, 2}, - {0x125b, 0x125d, 1}, - {0x1260, 0x1288, 1}, - {0x128a, 0x128d, 1}, - {0x1290, 0x12b0, 1}, - {0x12b2, 0x12b5, 1}, - {0x12b8, 0x12be, 1}, - {0x12c0, 0x12c2, 2}, - {0x12c3, 0x12c5, 1}, - {0x12c8, 0x12d6, 1}, - {0x12d8, 0x1310, 1}, - {0x1312, 0x1315, 1}, - {0x1318, 0x135a, 1}, - {0x1380, 0x138f, 1}, - {0x13a0, 0x13f4, 1}, - {0x1401, 0x166c, 1}, - {0x166f, 0x167f, 1}, - {0x1681, 0x169a, 1}, - {0x16a0, 0x16ea, 1}, - {0x1700, 0x170c, 1}, - {0x170e, 0x1711, 1}, - {0x1720, 0x1731, 1}, - {0x1740, 0x1751, 1}, - {0x1760, 0x176c, 1}, - {0x176e, 0x1770, 1}, - {0x1780, 0x17b3, 1}, - {0x17d7, 0x17dc, 5}, - {0x1820, 0x1877, 1}, - {0x1880, 0x18a8, 1}, - {0x18aa, 0x18b0, 6}, - {0x18b1, 0x18f5, 1}, - {0x1900, 0x191c, 1}, - {0x1950, 0x196d, 1}, - {0x1970, 0x1974, 1}, - {0x1980, 0x19ab, 1}, - {0x19c1, 0x19c7, 1}, - {0x1a00, 0x1a16, 1}, - {0x1a20, 0x1a54, 1}, - {0x1aa7, 0x1b05, 94}, - {0x1b06, 0x1b33, 1}, - {0x1b45, 0x1b4b, 1}, - {0x1b83, 0x1ba0, 1}, - {0x1bae, 0x1baf, 1}, - {0x1bc0, 0x1be5, 1}, - {0x1c00, 0x1c23, 1}, - {0x1c4d, 0x1c4f, 1}, - {0x1c5a, 0x1c7d, 1}, - {0x1ce9, 0x1cec, 1}, - {0x1cee, 0x1cf1, 1}, - {0x1d00, 0x1dbf, 1}, - {0x1e00, 0x1f15, 1}, - {0x1f18, 0x1f1d, 1}, - {0x1f20, 0x1f45, 1}, - {0x1f48, 0x1f4d, 1}, - {0x1f50, 0x1f57, 1}, - {0x1f59, 0x1f5f, 2}, - {0x1f60, 0x1f7d, 1}, - {0x1f80, 0x1fb4, 1}, - {0x1fb6, 0x1fbc, 1}, - {0x1fbe, 0x1fc2, 4}, - {0x1fc3, 0x1fc4, 1}, - {0x1fc6, 0x1fcc, 1}, - {0x1fd0, 0x1fd3, 1}, - {0x1fd6, 0x1fdb, 1}, - {0x1fe0, 0x1fec, 1}, - {0x1ff2, 0x1ff4, 1}, - {0x1ff6, 0x1ffc, 1}, - {0x2071, 0x207f, 14}, - {0x2090, 0x209c, 1}, - {0x2102, 0x2107, 5}, - {0x210a, 0x2113, 1}, - {0x2115, 0x2119, 4}, - {0x211a, 0x211d, 1}, - {0x2124, 0x212a, 2}, - {0x212b, 0x212d, 1}, - {0x212f, 0x2139, 1}, - {0x213c, 0x213f, 1}, - {0x2145, 0x2149, 1}, - {0x214e, 0x2183, 53}, - {0x2184, 0x2c00, 2684}, - {0x2c01, 0x2c2e, 1}, - {0x2c30, 0x2c5e, 1}, - {0x2c60, 0x2ce4, 1}, - {0x2ceb, 0x2cee, 1}, - {0x2d00, 0x2d25, 1}, - {0x2d30, 0x2d65, 1}, - {0x2d6f, 0x2d80, 17}, - {0x2d81, 0x2d96, 1}, - {0x2da0, 0x2da6, 1}, - {0x2da8, 0x2dae, 1}, - {0x2db0, 0x2db6, 1}, - {0x2db8, 0x2dbe, 1}, - {0x2dc0, 0x2dc6, 1}, - {0x2dc8, 0x2dce, 1}, - {0x2dd0, 0x2dd6, 1}, - {0x2dd8, 0x2dde, 1}, - {0x2e2f, 0x3005, 470}, - {0x3006, 0x3031, 43}, - {0x3032, 0x3035, 1}, - {0x303b, 0x303c, 1}, - {0x3041, 0x3096, 1}, - {0x309d, 0x309f, 1}, - {0x30a1, 0x30fa, 1}, - {0x30fc, 0x30ff, 1}, - {0x3105, 0x312d, 1}, - {0x3131, 0x318e, 1}, - {0x31a0, 0x31ba, 1}, - {0x31f0, 0x31ff, 1}, - {0x3400, 0x4db5, 1}, - {0x4e00, 0x9fcb, 1}, - {0xa000, 0xa48c, 1}, - {0xa4d0, 0xa4fd, 1}, - {0xa500, 0xa60c, 1}, - {0xa610, 0xa61f, 1}, - {0xa62a, 0xa62b, 1}, - {0xa640, 0xa66e, 1}, - {0xa67f, 0xa697, 1}, - {0xa6a0, 0xa6e5, 1}, - {0xa717, 0xa71f, 1}, - {0xa722, 0xa788, 1}, - {0xa78b, 0xa78e, 1}, - {0xa790, 0xa791, 1}, - {0xa7a0, 0xa7a9, 1}, - {0xa7fa, 0xa801, 1}, - {0xa803, 0xa805, 1}, - {0xa807, 0xa80a, 1}, - {0xa80c, 0xa822, 1}, - {0xa840, 0xa873, 1}, - {0xa882, 0xa8b3, 1}, - {0xa8f2, 0xa8f7, 1}, - {0xa8fb, 0xa90a, 15}, - {0xa90b, 0xa925, 1}, - {0xa930, 0xa946, 1}, - {0xa960, 0xa97c, 1}, - {0xa984, 0xa9b2, 1}, - {0xa9cf, 0xaa00, 49}, - {0xaa01, 0xaa28, 1}, - {0xaa40, 0xaa42, 1}, - {0xaa44, 0xaa4b, 1}, - {0xaa60, 0xaa76, 1}, - {0xaa7a, 0xaa80, 6}, - {0xaa81, 0xaaaf, 1}, - {0xaab1, 0xaab5, 4}, - {0xaab6, 0xaab9, 3}, - {0xaaba, 0xaabd, 1}, - {0xaac0, 0xaac2, 2}, - {0xaadb, 0xaadd, 1}, - {0xab01, 0xab06, 1}, - {0xab09, 0xab0e, 1}, - {0xab11, 0xab16, 1}, - {0xab20, 0xab26, 1}, - {0xab28, 0xab2e, 1}, - {0xabc0, 0xabe2, 1}, - {0xac00, 0xd7a3, 1}, - {0xd7b0, 0xd7c6, 1}, - {0xd7cb, 0xd7fb, 1}, - {0xf900, 0xfa2d, 1}, - {0xfa30, 0xfa6d, 1}, - {0xfa70, 0xfad9, 1}, - {0xfb00, 0xfb06, 1}, - {0xfb13, 0xfb17, 1}, - {0xfb1d, 0xfb1f, 2}, - {0xfb20, 0xfb28, 1}, - {0xfb2a, 0xfb36, 1}, - {0xfb38, 0xfb3c, 1}, - {0xfb3e, 0xfb40, 2}, - {0xfb41, 0xfb43, 2}, - {0xfb44, 0xfb46, 2}, - {0xfb47, 0xfbb1, 1}, - {0xfbd3, 0xfd3d, 1}, - {0xfd50, 0xfd8f, 1}, - {0xfd92, 0xfdc7, 1}, - {0xfdf0, 0xfdfb, 1}, - {0xfe70, 0xfe74, 1}, - {0xfe76, 0xfefc, 1}, - {0xff21, 0xff3a, 1}, - {0xff41, 0xff5a, 1}, - {0xff66, 0xffbe, 1}, - {0xffc2, 0xffc7, 1}, - {0xffca, 0xffcf, 1}, - {0xffd2, 0xffd7, 1}, - {0xffda, 0xffdc, 1}, - {0x10000, 0x1000b, 1}, - {0x1000d, 0x10026, 1}, - {0x10028, 0x1003a, 1}, - {0x1003c, 0x1003d, 1}, - {0x1003f, 0x1004d, 1}, - {0x10050, 0x1005d, 1}, - {0x10080, 0x100fa, 1}, - {0x10280, 0x1029c, 1}, - {0x102a0, 0x102d0, 1}, - {0x10300, 0x1031e, 1}, - {0x10330, 0x10340, 1}, - {0x10342, 0x10349, 1}, - {0x10380, 0x1039d, 1}, - {0x103a0, 0x103c3, 1}, - {0x103c8, 0x103cf, 1}, - {0x10400, 0x1049d, 1}, - {0x10800, 0x10805, 1}, - {0x10808, 0x1080a, 2}, - {0x1080b, 0x10835, 1}, - {0x10837, 0x10838, 1}, - {0x1083c, 0x1083f, 3}, - {0x10840, 0x10855, 1}, - {0x10900, 0x10915, 1}, - {0x10920, 0x10939, 1}, - {0x10a00, 0x10a10, 16}, - {0x10a11, 0x10a13, 1}, - {0x10a15, 0x10a17, 1}, - {0x10a19, 0x10a33, 1}, - {0x10a60, 0x10a7c, 1}, - {0x10b00, 0x10b35, 1}, - {0x10b40, 0x10b55, 1}, - {0x10b60, 0x10b72, 1}, - {0x10c00, 0x10c48, 1}, - {0x11003, 0x11037, 1}, - {0x11083, 0x110af, 1}, - {0x12000, 0x1236e, 1}, - {0x13000, 0x1342e, 1}, - {0x16800, 0x16a38, 1}, - {0x1b000, 0x1b001, 1}, - {0x1d400, 0x1d454, 1}, - {0x1d456, 0x1d49c, 1}, - {0x1d49e, 0x1d49f, 1}, - {0x1d4a2, 0x1d4a5, 3}, - {0x1d4a6, 0x1d4a9, 3}, - {0x1d4aa, 0x1d4ac, 1}, - {0x1d4ae, 0x1d4b9, 1}, - {0x1d4bb, 0x1d4bd, 2}, - {0x1d4be, 0x1d4c3, 1}, - {0x1d4c5, 0x1d505, 1}, - {0x1d507, 0x1d50a, 1}, - {0x1d50d, 0x1d514, 1}, - {0x1d516, 0x1d51c, 1}, - {0x1d51e, 0x1d539, 1}, - {0x1d53b, 0x1d53e, 1}, - {0x1d540, 0x1d544, 1}, - {0x1d546, 0x1d54a, 4}, - {0x1d54b, 0x1d550, 1}, - {0x1d552, 0x1d6a5, 1}, - {0x1d6a8, 0x1d6c0, 1}, - {0x1d6c2, 0x1d6da, 1}, - {0x1d6dc, 0x1d6fa, 1}, - {0x1d6fc, 0x1d714, 1}, - {0x1d716, 0x1d734, 1}, - {0x1d736, 0x1d74e, 1}, - {0x1d750, 0x1d76e, 1}, - {0x1d770, 0x1d788, 1}, - {0x1d78a, 0x1d7a8, 1}, - {0x1d7aa, 0x1d7c2, 1}, - {0x1d7c4, 0x1d7cb, 1}, - {0x20000, 0x2a6d6, 1}, - {0x2a700, 0x2b734, 1}, - {0x2b740, 0x2b81d, 1}, - {0x2f800, 0x2fa1d, 1}, -} - -var _Zp = []Range{ - {0x2029, 0x2029, 1}, -} - -var _Zs = []Range{ - {0x0020, 0x00a0, 128}, - {0x1680, 0x180e, 398}, - {0x2000, 0x200a, 1}, - {0x202f, 0x205f, 48}, - {0x3000, 0x3000, 1}, -} - -var _Cs = []Range{ - {0xd800, 0xdfff, 1}, -} - -var _Co = []Range{ - {0xe000, 0xf8ff, 1}, - {0xf0000, 0xffffd, 1}, - {0x100000, 0x10fffd, 1}, -} - -var _Cf = []Range{ - {0x00ad, 0x0600, 1363}, - {0x0601, 0x0603, 1}, - {0x06dd, 0x070f, 50}, - {0x17b4, 0x17b5, 1}, - {0x200b, 0x200f, 1}, - {0x202a, 0x202e, 1}, - {0x2060, 0x2064, 1}, - {0x206a, 0x206f, 1}, - {0xfeff, 0xfff9, 250}, - {0xfffa, 0xfffb, 1}, - {0x110bd, 0x1d173, 49334}, - {0x1d174, 0x1d17a, 1}, - {0xe0001, 0xe0020, 31}, - {0xe0021, 0xe007f, 1}, -} - -var _Cc = []Range{ - {0x0001, 0x001f, 1}, - {0x007f, 0x009f, 1}, -} - -var _Po = []Range{ - {0x0021, 0x0023, 1}, - {0x0025, 0x0027, 1}, - {0x002a, 0x002e, 2}, - {0x002f, 0x003a, 11}, - {0x003b, 0x003f, 4}, - {0x0040, 0x005c, 28}, - {0x00a1, 0x00b7, 22}, - {0x00bf, 0x037e, 703}, - {0x0387, 0x055a, 467}, - {0x055b, 0x055f, 1}, - {0x0589, 0x05c0, 55}, - {0x05c3, 0x05c6, 3}, - {0x05f3, 0x05f4, 1}, - {0x0609, 0x060a, 1}, - {0x060c, 0x060d, 1}, - {0x061b, 0x061e, 3}, - {0x061f, 0x066a, 75}, - {0x066b, 0x066d, 1}, - {0x06d4, 0x0700, 44}, - {0x0701, 0x070d, 1}, - {0x07f7, 0x07f9, 1}, - {0x0830, 0x083e, 1}, - {0x085e, 0x0964, 262}, - {0x0965, 0x0970, 11}, - {0x0df4, 0x0e4f, 91}, - {0x0e5a, 0x0e5b, 1}, - {0x0f04, 0x0f12, 1}, - {0x0f85, 0x0fd0, 75}, - {0x0fd1, 0x0fd4, 1}, - {0x0fd9, 0x0fda, 1}, - {0x104a, 0x104f, 1}, - {0x10fb, 0x1361, 614}, - {0x1362, 0x1368, 1}, - {0x166d, 0x166e, 1}, - {0x16eb, 0x16ed, 1}, - {0x1735, 0x1736, 1}, - {0x17d4, 0x17d6, 1}, - {0x17d8, 0x17da, 1}, - {0x1800, 0x1805, 1}, - {0x1807, 0x180a, 1}, - {0x1944, 0x1945, 1}, - {0x1a1e, 0x1a1f, 1}, - {0x1aa0, 0x1aa6, 1}, - {0x1aa8, 0x1aad, 1}, - {0x1b5a, 0x1b60, 1}, - {0x1bfc, 0x1bff, 1}, - {0x1c3b, 0x1c3f, 1}, - {0x1c7e, 0x1c7f, 1}, - {0x1cd3, 0x2016, 835}, - {0x2017, 0x2020, 9}, - {0x2021, 0x2027, 1}, - {0x2030, 0x2038, 1}, - {0x203b, 0x203e, 1}, - {0x2041, 0x2043, 1}, - {0x2047, 0x2051, 1}, - {0x2053, 0x2055, 2}, - {0x2056, 0x205e, 1}, - {0x2cf9, 0x2cfc, 1}, - {0x2cfe, 0x2cff, 1}, - {0x2d70, 0x2e00, 144}, - {0x2e01, 0x2e06, 5}, - {0x2e07, 0x2e08, 1}, - {0x2e0b, 0x2e0e, 3}, - {0x2e0f, 0x2e16, 1}, - {0x2e18, 0x2e19, 1}, - {0x2e1b, 0x2e1e, 3}, - {0x2e1f, 0x2e2a, 11}, - {0x2e2b, 0x2e2e, 1}, - {0x2e30, 0x2e31, 1}, - {0x3001, 0x3003, 1}, - {0x303d, 0x30fb, 190}, - {0xa4fe, 0xa4ff, 1}, - {0xa60d, 0xa60f, 1}, - {0xa673, 0xa67e, 11}, - {0xa6f2, 0xa6f7, 1}, - {0xa874, 0xa877, 1}, - {0xa8ce, 0xa8cf, 1}, - {0xa8f8, 0xa8fa, 1}, - {0xa92e, 0xa92f, 1}, - {0xa95f, 0xa9c1, 98}, - {0xa9c2, 0xa9cd, 1}, - {0xa9de, 0xa9df, 1}, - {0xaa5c, 0xaa5f, 1}, - {0xaade, 0xaadf, 1}, - {0xabeb, 0xfe10, 21029}, - {0xfe11, 0xfe16, 1}, - {0xfe19, 0xfe30, 23}, - {0xfe45, 0xfe46, 1}, - {0xfe49, 0xfe4c, 1}, - {0xfe50, 0xfe52, 1}, - {0xfe54, 0xfe57, 1}, - {0xfe5f, 0xfe61, 1}, - {0xfe68, 0xfe6a, 2}, - {0xfe6b, 0xff01, 150}, - {0xff02, 0xff03, 1}, - {0xff05, 0xff07, 1}, - {0xff0a, 0xff0e, 2}, - {0xff0f, 0xff1a, 11}, - {0xff1b, 0xff1f, 4}, - {0xff20, 0xff3c, 28}, - {0xff61, 0xff64, 3}, - {0xff65, 0x10100, 411}, - {0x10101, 0x1039f, 670}, - {0x103d0, 0x10857, 1159}, - {0x1091f, 0x1093f, 32}, - {0x10a50, 0x10a58, 1}, - {0x10a7f, 0x10b39, 186}, - {0x10b3a, 0x10b3f, 1}, - {0x11047, 0x1104d, 1}, - {0x110bb, 0x110bc, 1}, - {0x110be, 0x110c1, 1}, - {0x12470, 0x12473, 1}, -} - -var _Pi = []Range{ - {0x00ab, 0x2018, 8045}, - {0x201b, 0x201c, 1}, - {0x201f, 0x2039, 26}, - {0x2e02, 0x2e04, 2}, - {0x2e09, 0x2e0c, 3}, - {0x2e1c, 0x2e20, 4}, -} - -var _Pf = []Range{ - {0x00bb, 0x2019, 8030}, - {0x201d, 0x203a, 29}, - {0x2e03, 0x2e05, 2}, - {0x2e0a, 0x2e0d, 3}, - {0x2e1d, 0x2e21, 4}, -} - -var _Pe = []Range{ - {0x0029, 0x005d, 52}, - {0x007d, 0x0f3b, 3774}, - {0x0f3d, 0x169c, 1887}, - {0x2046, 0x207e, 56}, - {0x208e, 0x232a, 668}, - {0x2769, 0x2775, 2}, - {0x27c6, 0x27e7, 33}, - {0x27e9, 0x27ef, 2}, - {0x2984, 0x2998, 2}, - {0x29d9, 0x29db, 2}, - {0x29fd, 0x2e23, 1062}, - {0x2e25, 0x2e29, 2}, - {0x3009, 0x3011, 2}, - {0x3015, 0x301b, 2}, - {0x301e, 0x301f, 1}, - {0xfd3f, 0xfe18, 217}, - {0xfe36, 0xfe44, 2}, - {0xfe48, 0xfe5a, 18}, - {0xfe5c, 0xfe5e, 2}, - {0xff09, 0xff3d, 52}, - {0xff5d, 0xff63, 3}, -} - -var _Pd = []Range{ - {0x002d, 0x058a, 1373}, - {0x05be, 0x1400, 3650}, - {0x1806, 0x2010, 2058}, - {0x2011, 0x2015, 1}, - {0x2e17, 0x2e1a, 3}, - {0x301c, 0x3030, 20}, - {0x30a0, 0xfe31, 52625}, - {0xfe32, 0xfe58, 38}, - {0xfe63, 0xff0d, 170}, -} - -var _Pc = []Range{ - {0x005f, 0x203f, 8160}, - {0x2040, 0x2054, 20}, - {0xfe33, 0xfe34, 1}, - {0xfe4d, 0xfe4f, 1}, - {0xff3f, 0xff3f, 1}, -} - -var _Ps = []Range{ - {0x0028, 0x005b, 51}, - {0x007b, 0x0f3a, 3775}, - {0x0f3c, 0x169b, 1887}, - {0x201a, 0x201e, 4}, - {0x2045, 0x207d, 56}, - {0x208d, 0x2329, 668}, - {0x2768, 0x2774, 2}, - {0x27c5, 0x27e6, 33}, - {0x27e8, 0x27ee, 2}, - {0x2983, 0x2997, 2}, - {0x29d8, 0x29da, 2}, - {0x29fc, 0x2e22, 1062}, - {0x2e24, 0x2e28, 2}, - {0x3008, 0x3010, 2}, - {0x3014, 0x301a, 2}, - {0x301d, 0xfd3e, 52513}, - {0xfe17, 0xfe35, 30}, - {0xfe37, 0xfe43, 2}, - {0xfe47, 0xfe59, 18}, - {0xfe5b, 0xfe5d, 2}, - {0xff08, 0xff3b, 51}, - {0xff5b, 0xff5f, 4}, - {0xff62, 0xff62, 1}, -} - -var _Nd = []Range{ - {0x0030, 0x0039, 1}, - {0x0660, 0x0669, 1}, - {0x06f0, 0x06f9, 1}, - {0x07c0, 0x07c9, 1}, - {0x0966, 0x096f, 1}, - {0x09e6, 0x09ef, 1}, - {0x0a66, 0x0a6f, 1}, - {0x0ae6, 0x0aef, 1}, - {0x0b66, 0x0b6f, 1}, - {0x0be6, 0x0bef, 1}, - {0x0c66, 0x0c6f, 1}, - {0x0ce6, 0x0cef, 1}, - {0x0d66, 0x0d6f, 1}, - {0x0e50, 0x0e59, 1}, - {0x0ed0, 0x0ed9, 1}, - {0x0f20, 0x0f29, 1}, - {0x1040, 0x1049, 1}, - {0x1090, 0x1099, 1}, - {0x17e0, 0x17e9, 1}, - {0x1810, 0x1819, 1}, - {0x1946, 0x194f, 1}, - {0x19d0, 0x19d9, 1}, - {0x1a80, 0x1a89, 1}, - {0x1a90, 0x1a99, 1}, - {0x1b50, 0x1b59, 1}, - {0x1bb0, 0x1bb9, 1}, - {0x1c40, 0x1c49, 1}, - {0x1c50, 0x1c59, 1}, - {0xa620, 0xa629, 1}, - {0xa8d0, 0xa8d9, 1}, - {0xa900, 0xa909, 1}, - {0xa9d0, 0xa9d9, 1}, - {0xaa50, 0xaa59, 1}, - {0xabf0, 0xabf9, 1}, - {0xff10, 0xff19, 1}, - {0x104a0, 0x104a9, 1}, - {0x11066, 0x1106f, 1}, - {0x1d7ce, 0x1d7ff, 1}, -} - -var _Nl = []Range{ - {0x16ee, 0x16f0, 1}, - {0x2160, 0x2182, 1}, - {0x2185, 0x2188, 1}, - {0x3007, 0x3021, 26}, - {0x3022, 0x3029, 1}, - {0x3038, 0x303a, 1}, - {0xa6e6, 0xa6ef, 1}, - {0x10140, 0x10174, 1}, - {0x10341, 0x1034a, 9}, - {0x103d1, 0x103d5, 1}, - {0x12400, 0x12462, 1}, -} - -var _No = []Range{ - {0x00b2, 0x00b3, 1}, - {0x00b9, 0x00bc, 3}, - {0x00bd, 0x00be, 1}, - {0x09f4, 0x09f9, 1}, - {0x0b72, 0x0b77, 1}, - {0x0bf0, 0x0bf2, 1}, - {0x0c78, 0x0c7e, 1}, - {0x0d70, 0x0d75, 1}, - {0x0f2a, 0x0f33, 1}, - {0x1369, 0x137c, 1}, - {0x17f0, 0x17f9, 1}, - {0x19da, 0x2070, 1686}, - {0x2074, 0x2079, 1}, - {0x2080, 0x2089, 1}, - {0x2150, 0x215f, 1}, - {0x2189, 0x2460, 727}, - {0x2461, 0x249b, 1}, - {0x24ea, 0x24ff, 1}, - {0x2776, 0x2793, 1}, - {0x2cfd, 0x3192, 1173}, - {0x3193, 0x3195, 1}, - {0x3220, 0x3229, 1}, - {0x3251, 0x325f, 1}, - {0x3280, 0x3289, 1}, - {0x32b1, 0x32bf, 1}, - {0xa830, 0xa835, 1}, - {0x10107, 0x10133, 1}, - {0x10175, 0x10178, 1}, - {0x1018a, 0x10320, 406}, - {0x10321, 0x10323, 1}, - {0x10858, 0x1085f, 1}, - {0x10916, 0x1091b, 1}, - {0x10a40, 0x10a47, 1}, - {0x10a7d, 0x10a7e, 1}, - {0x10b58, 0x10b5f, 1}, - {0x10b78, 0x10b7f, 1}, - {0x10e60, 0x10e7e, 1}, - {0x11052, 0x11065, 1}, - {0x1d360, 0x1d371, 1}, - {0x1f100, 0x1f10a, 1}, -} - -var _So = []Range{ - {0x00a6, 0x00a7, 1}, - {0x00a9, 0x00ae, 5}, - {0x00b0, 0x00b6, 6}, - {0x0482, 0x060e, 396}, - {0x060f, 0x06de, 207}, - {0x06e9, 0x06fd, 20}, - {0x06fe, 0x07f6, 248}, - {0x09fa, 0x0b70, 374}, - {0x0bf3, 0x0bf8, 1}, - {0x0bfa, 0x0c7f, 133}, - {0x0d79, 0x0f01, 392}, - {0x0f02, 0x0f03, 1}, - {0x0f13, 0x0f17, 1}, - {0x0f1a, 0x0f1f, 1}, - {0x0f34, 0x0f38, 2}, - {0x0fbe, 0x0fc5, 1}, - {0x0fc7, 0x0fcc, 1}, - {0x0fce, 0x0fcf, 1}, - {0x0fd5, 0x0fd8, 1}, - {0x109e, 0x109f, 1}, - {0x1360, 0x1390, 48}, - {0x1391, 0x1399, 1}, - {0x1940, 0x19de, 158}, - {0x19df, 0x19ff, 1}, - {0x1b61, 0x1b6a, 1}, - {0x1b74, 0x1b7c, 1}, - {0x2100, 0x2101, 1}, - {0x2103, 0x2106, 1}, - {0x2108, 0x2109, 1}, - {0x2114, 0x2116, 2}, - {0x2117, 0x211e, 7}, - {0x211f, 0x2123, 1}, - {0x2125, 0x2129, 2}, - {0x212e, 0x213a, 12}, - {0x213b, 0x214a, 15}, - {0x214c, 0x214d, 1}, - {0x214f, 0x2195, 70}, - {0x2196, 0x2199, 1}, - {0x219c, 0x219f, 1}, - {0x21a1, 0x21a2, 1}, - {0x21a4, 0x21a5, 1}, - {0x21a7, 0x21ad, 1}, - {0x21af, 0x21cd, 1}, - {0x21d0, 0x21d1, 1}, - {0x21d3, 0x21d5, 2}, - {0x21d6, 0x21f3, 1}, - {0x2300, 0x2307, 1}, - {0x230c, 0x231f, 1}, - {0x2322, 0x2328, 1}, - {0x232b, 0x237b, 1}, - {0x237d, 0x239a, 1}, - {0x23b4, 0x23db, 1}, - {0x23e2, 0x23f3, 1}, - {0x2400, 0x2426, 1}, - {0x2440, 0x244a, 1}, - {0x249c, 0x24e9, 1}, - {0x2500, 0x25b6, 1}, - {0x25b8, 0x25c0, 1}, - {0x25c2, 0x25f7, 1}, - {0x2600, 0x266e, 1}, - {0x2670, 0x26ff, 1}, - {0x2701, 0x2767, 1}, - {0x2794, 0x27bf, 1}, - {0x2800, 0x28ff, 1}, - {0x2b00, 0x2b2f, 1}, - {0x2b45, 0x2b46, 1}, - {0x2b50, 0x2b59, 1}, - {0x2ce5, 0x2cea, 1}, - {0x2e80, 0x2e99, 1}, - {0x2e9b, 0x2ef3, 1}, - {0x2f00, 0x2fd5, 1}, - {0x2ff0, 0x2ffb, 1}, - {0x3004, 0x3012, 14}, - {0x3013, 0x3020, 13}, - {0x3036, 0x3037, 1}, - {0x303e, 0x303f, 1}, - {0x3190, 0x3191, 1}, - {0x3196, 0x319f, 1}, - {0x31c0, 0x31e3, 1}, - {0x3200, 0x321e, 1}, - {0x322a, 0x3250, 1}, - {0x3260, 0x327f, 1}, - {0x328a, 0x32b0, 1}, - {0x32c0, 0x32fe, 1}, - {0x3300, 0x33ff, 1}, - {0x4dc0, 0x4dff, 1}, - {0xa490, 0xa4c6, 1}, - {0xa828, 0xa82b, 1}, - {0xa836, 0xa837, 1}, - {0xa839, 0xaa77, 574}, - {0xaa78, 0xaa79, 1}, - {0xfdfd, 0xffe4, 487}, - {0xffe8, 0xffed, 5}, - {0xffee, 0xfffc, 14}, - {0xfffd, 0x10102, 261}, - {0x10137, 0x1013f, 1}, - {0x10179, 0x10189, 1}, - {0x10190, 0x1019b, 1}, - {0x101d0, 0x101fc, 1}, - {0x1d000, 0x1d0f5, 1}, - {0x1d100, 0x1d126, 1}, - {0x1d129, 0x1d164, 1}, - {0x1d16a, 0x1d16c, 1}, - {0x1d183, 0x1d184, 1}, - {0x1d18c, 0x1d1a9, 1}, - {0x1d1ae, 0x1d1dd, 1}, - {0x1d200, 0x1d241, 1}, - {0x1d245, 0x1d300, 187}, - {0x1d301, 0x1d356, 1}, - {0x1f000, 0x1f02b, 1}, - {0x1f030, 0x1f093, 1}, - {0x1f0a0, 0x1f0ae, 1}, - {0x1f0b1, 0x1f0be, 1}, - {0x1f0c1, 0x1f0cf, 1}, - {0x1f0d1, 0x1f0df, 1}, - {0x1f110, 0x1f12e, 1}, - {0x1f130, 0x1f169, 1}, - {0x1f170, 0x1f19a, 1}, - {0x1f1e6, 0x1f202, 1}, - {0x1f210, 0x1f23a, 1}, - {0x1f240, 0x1f248, 1}, - {0x1f250, 0x1f251, 1}, - {0x1f300, 0x1f320, 1}, - {0x1f330, 0x1f335, 1}, - {0x1f337, 0x1f37c, 1}, - {0x1f380, 0x1f393, 1}, - {0x1f3a0, 0x1f3c4, 1}, - {0x1f3c6, 0x1f3ca, 1}, - {0x1f3e0, 0x1f3f0, 1}, - {0x1f400, 0x1f43e, 1}, - {0x1f440, 0x1f442, 2}, - {0x1f443, 0x1f4f7, 1}, - {0x1f4f9, 0x1f4fc, 1}, - {0x1f500, 0x1f53d, 1}, - {0x1f550, 0x1f567, 1}, - {0x1f5fb, 0x1f5ff, 1}, - {0x1f601, 0x1f610, 1}, - {0x1f612, 0x1f614, 1}, - {0x1f616, 0x1f61c, 2}, - {0x1f61d, 0x1f61e, 1}, - {0x1f620, 0x1f625, 1}, - {0x1f628, 0x1f62b, 1}, - {0x1f62d, 0x1f630, 3}, - {0x1f631, 0x1f633, 1}, - {0x1f635, 0x1f640, 1}, - {0x1f645, 0x1f64f, 1}, - {0x1f680, 0x1f6c5, 1}, - {0x1f700, 0x1f773, 1}, -} - -var _Sm = []Range{ - {0x002b, 0x003c, 17}, - {0x003d, 0x003e, 1}, - {0x007c, 0x007e, 2}, - {0x00ac, 0x00b1, 5}, - {0x00d7, 0x00f7, 32}, - {0x03f6, 0x0606, 528}, - {0x0607, 0x0608, 1}, - {0x2044, 0x2052, 14}, - {0x207a, 0x207c, 1}, - {0x208a, 0x208c, 1}, - {0x2118, 0x2140, 40}, - {0x2141, 0x2144, 1}, - {0x214b, 0x2190, 69}, - {0x2191, 0x2194, 1}, - {0x219a, 0x219b, 1}, - {0x21a0, 0x21a6, 3}, - {0x21ae, 0x21ce, 32}, - {0x21cf, 0x21d2, 3}, - {0x21d4, 0x21f4, 32}, - {0x21f5, 0x22ff, 1}, - {0x2308, 0x230b, 1}, - {0x2320, 0x2321, 1}, - {0x237c, 0x239b, 31}, - {0x239c, 0x23b3, 1}, - {0x23dc, 0x23e1, 1}, - {0x25b7, 0x25c1, 10}, - {0x25f8, 0x25ff, 1}, - {0x266f, 0x27c0, 337}, - {0x27c1, 0x27c4, 1}, - {0x27c7, 0x27ca, 1}, - {0x27cc, 0x27ce, 2}, - {0x27cf, 0x27e5, 1}, - {0x27f0, 0x27ff, 1}, - {0x2900, 0x2982, 1}, - {0x2999, 0x29d7, 1}, - {0x29dc, 0x29fb, 1}, - {0x29fe, 0x2aff, 1}, - {0x2b30, 0x2b44, 1}, - {0x2b47, 0x2b4c, 1}, - {0xfb29, 0xfe62, 825}, - {0xfe64, 0xfe66, 1}, - {0xff0b, 0xff1c, 17}, - {0xff1d, 0xff1e, 1}, - {0xff5c, 0xff5e, 2}, - {0xffe2, 0xffe9, 7}, - {0xffea, 0xffec, 1}, - {0x1d6c1, 0x1d6db, 26}, - {0x1d6fb, 0x1d715, 26}, - {0x1d735, 0x1d74f, 26}, - {0x1d76f, 0x1d789, 26}, - {0x1d7a9, 0x1d7c3, 26}, -} - -var _Sk = []Range{ - {0x005e, 0x0060, 2}, - {0x00a8, 0x00af, 7}, - {0x00b4, 0x00b8, 4}, - {0x02c2, 0x02c5, 1}, - {0x02d2, 0x02df, 1}, - {0x02e5, 0x02eb, 1}, - {0x02ed, 0x02ef, 2}, - {0x02f0, 0x02ff, 1}, - {0x0375, 0x0384, 15}, - {0x0385, 0x1fbd, 7224}, - {0x1fbf, 0x1fc1, 1}, - {0x1fcd, 0x1fcf, 1}, - {0x1fdd, 0x1fdf, 1}, - {0x1fed, 0x1fef, 1}, - {0x1ffd, 0x1ffe, 1}, - {0x309b, 0x309c, 1}, - {0xa700, 0xa716, 1}, - {0xa720, 0xa721, 1}, - {0xa789, 0xa78a, 1}, - {0xfbb2, 0xfbc1, 1}, - {0xff3e, 0xff40, 2}, - {0xffe3, 0xffe3, 1}, -} - -var _Sc = []Range{ - {0x0024, 0x00a2, 126}, - {0x00a3, 0x00a5, 1}, - {0x060b, 0x09f2, 999}, - {0x09f3, 0x09fb, 8}, - {0x0af1, 0x0bf9, 264}, - {0x0e3f, 0x17db, 2460}, - {0x20a0, 0x20b9, 1}, - {0xa838, 0xfdfc, 21956}, - {0xfe69, 0xff04, 155}, - {0xffe0, 0xffe1, 1}, - {0xffe5, 0xffe6, 1}, -} - -var _Lu = []Range{ - {0x0041, 0x005a, 1}, - {0x00c0, 0x00d6, 1}, - {0x00d8, 0x00de, 1}, - {0x0100, 0x0136, 2}, - {0x0139, 0x0147, 2}, - {0x014a, 0x0178, 2}, - {0x0179, 0x017d, 2}, - {0x0181, 0x0182, 1}, - {0x0184, 0x0186, 2}, - {0x0187, 0x0189, 2}, - {0x018a, 0x018b, 1}, - {0x018e, 0x0191, 1}, - {0x0193, 0x0194, 1}, - {0x0196, 0x0198, 1}, - {0x019c, 0x019d, 1}, - {0x019f, 0x01a0, 1}, - {0x01a2, 0x01a6, 2}, - {0x01a7, 0x01a9, 2}, - {0x01ac, 0x01ae, 2}, - {0x01af, 0x01b1, 2}, - {0x01b2, 0x01b3, 1}, - {0x01b5, 0x01b7, 2}, - {0x01b8, 0x01bc, 4}, - {0x01c4, 0x01cd, 3}, - {0x01cf, 0x01db, 2}, - {0x01de, 0x01ee, 2}, - {0x01f1, 0x01f4, 3}, - {0x01f6, 0x01f8, 1}, - {0x01fa, 0x0232, 2}, - {0x023a, 0x023b, 1}, - {0x023d, 0x023e, 1}, - {0x0241, 0x0243, 2}, - {0x0244, 0x0246, 1}, - {0x0248, 0x024e, 2}, - {0x0370, 0x0372, 2}, - {0x0376, 0x0386, 16}, - {0x0388, 0x038a, 1}, - {0x038c, 0x038e, 2}, - {0x038f, 0x0391, 2}, - {0x0392, 0x03a1, 1}, - {0x03a3, 0x03ab, 1}, - {0x03cf, 0x03d2, 3}, - {0x03d3, 0x03d4, 1}, - {0x03d8, 0x03ee, 2}, - {0x03f4, 0x03f7, 3}, - {0x03f9, 0x03fa, 1}, - {0x03fd, 0x042f, 1}, - {0x0460, 0x0480, 2}, - {0x048a, 0x04c0, 2}, - {0x04c1, 0x04cd, 2}, - {0x04d0, 0x0526, 2}, - {0x0531, 0x0556, 1}, - {0x10a0, 0x10c5, 1}, - {0x1e00, 0x1e94, 2}, - {0x1e9e, 0x1efe, 2}, - {0x1f08, 0x1f0f, 1}, - {0x1f18, 0x1f1d, 1}, - {0x1f28, 0x1f2f, 1}, - {0x1f38, 0x1f3f, 1}, - {0x1f48, 0x1f4d, 1}, - {0x1f59, 0x1f5f, 2}, - {0x1f68, 0x1f6f, 1}, - {0x1fb8, 0x1fbb, 1}, - {0x1fc8, 0x1fcb, 1}, - {0x1fd8, 0x1fdb, 1}, - {0x1fe8, 0x1fec, 1}, - {0x1ff8, 0x1ffb, 1}, - {0x2102, 0x2107, 5}, - {0x210b, 0x210d, 1}, - {0x2110, 0x2112, 1}, - {0x2115, 0x2119, 4}, - {0x211a, 0x211d, 1}, - {0x2124, 0x212a, 2}, - {0x212b, 0x212d, 1}, - {0x2130, 0x2133, 1}, - {0x213e, 0x213f, 1}, - {0x2145, 0x2183, 62}, - {0x2c00, 0x2c2e, 1}, - {0x2c60, 0x2c62, 2}, - {0x2c63, 0x2c64, 1}, - {0x2c67, 0x2c6d, 2}, - {0x2c6e, 0x2c70, 1}, - {0x2c72, 0x2c75, 3}, - {0x2c7e, 0x2c80, 1}, - {0x2c82, 0x2ce2, 2}, - {0x2ceb, 0x2ced, 2}, - {0xa640, 0xa66c, 2}, - {0xa680, 0xa696, 2}, - {0xa722, 0xa72e, 2}, - {0xa732, 0xa76e, 2}, - {0xa779, 0xa77d, 2}, - {0xa77e, 0xa786, 2}, - {0xa78b, 0xa78d, 2}, - {0xa790, 0xa7a0, 16}, - {0xa7a2, 0xa7a8, 2}, - {0xff21, 0xff3a, 1}, - {0x10400, 0x10427, 1}, - {0x1d400, 0x1d419, 1}, - {0x1d434, 0x1d44d, 1}, - {0x1d468, 0x1d481, 1}, - {0x1d49c, 0x1d49e, 2}, - {0x1d49f, 0x1d4a5, 3}, - {0x1d4a6, 0x1d4a9, 3}, - {0x1d4aa, 0x1d4ac, 1}, - {0x1d4ae, 0x1d4b5, 1}, - {0x1d4d0, 0x1d4e9, 1}, - {0x1d504, 0x1d505, 1}, - {0x1d507, 0x1d50a, 1}, - {0x1d50d, 0x1d514, 1}, - {0x1d516, 0x1d51c, 1}, - {0x1d538, 0x1d539, 1}, - {0x1d53b, 0x1d53e, 1}, - {0x1d540, 0x1d544, 1}, - {0x1d546, 0x1d54a, 4}, - {0x1d54b, 0x1d550, 1}, - {0x1d56c, 0x1d585, 1}, - {0x1d5a0, 0x1d5b9, 1}, - {0x1d5d4, 0x1d5ed, 1}, - {0x1d608, 0x1d621, 1}, - {0x1d63c, 0x1d655, 1}, - {0x1d670, 0x1d689, 1}, - {0x1d6a8, 0x1d6c0, 1}, - {0x1d6e2, 0x1d6fa, 1}, - {0x1d71c, 0x1d734, 1}, - {0x1d756, 0x1d76e, 1}, - {0x1d790, 0x1d7a8, 1}, - {0x1d7ca, 0x1d7ca, 1}, -} - -var _Lt = []Range{ - {0x01c5, 0x01cb, 3}, - {0x01f2, 0x1f88, 7574}, - {0x1f89, 0x1f8f, 1}, - {0x1f98, 0x1f9f, 1}, - {0x1fa8, 0x1faf, 1}, - {0x1fbc, 0x1fcc, 16}, - {0x1ffc, 0x1ffc, 1}, -} - -var _Lo = []Range{ - {0x01bb, 0x01c0, 5}, - {0x01c1, 0x01c3, 1}, - {0x0294, 0x05d0, 828}, - {0x05d1, 0x05ea, 1}, - {0x05f0, 0x05f2, 1}, - {0x0620, 0x063f, 1}, - {0x0641, 0x064a, 1}, - {0x066e, 0x066f, 1}, - {0x0671, 0x06d3, 1}, - {0x06d5, 0x06ee, 25}, - {0x06ef, 0x06fa, 11}, - {0x06fb, 0x06fc, 1}, - {0x06ff, 0x0710, 17}, - {0x0712, 0x072f, 1}, - {0x074d, 0x07a5, 1}, - {0x07b1, 0x07ca, 25}, - {0x07cb, 0x07ea, 1}, - {0x0800, 0x0815, 1}, - {0x0840, 0x0858, 1}, - {0x0904, 0x0939, 1}, - {0x093d, 0x0950, 19}, - {0x0958, 0x0961, 1}, - {0x0972, 0x0977, 1}, - {0x0979, 0x097f, 1}, - {0x0985, 0x098c, 1}, - {0x098f, 0x0990, 1}, - {0x0993, 0x09a8, 1}, - {0x09aa, 0x09b0, 1}, - {0x09b2, 0x09b6, 4}, - {0x09b7, 0x09b9, 1}, - {0x09bd, 0x09ce, 17}, - {0x09dc, 0x09dd, 1}, - {0x09df, 0x09e1, 1}, - {0x09f0, 0x09f1, 1}, - {0x0a05, 0x0a0a, 1}, - {0x0a0f, 0x0a10, 1}, - {0x0a13, 0x0a28, 1}, - {0x0a2a, 0x0a30, 1}, - {0x0a32, 0x0a33, 1}, - {0x0a35, 0x0a36, 1}, - {0x0a38, 0x0a39, 1}, - {0x0a59, 0x0a5c, 1}, - {0x0a5e, 0x0a72, 20}, - {0x0a73, 0x0a74, 1}, - {0x0a85, 0x0a8d, 1}, - {0x0a8f, 0x0a91, 1}, - {0x0a93, 0x0aa8, 1}, - {0x0aaa, 0x0ab0, 1}, - {0x0ab2, 0x0ab3, 1}, - {0x0ab5, 0x0ab9, 1}, - {0x0abd, 0x0ad0, 19}, - {0x0ae0, 0x0ae1, 1}, - {0x0b05, 0x0b0c, 1}, - {0x0b0f, 0x0b10, 1}, - {0x0b13, 0x0b28, 1}, - {0x0b2a, 0x0b30, 1}, - {0x0b32, 0x0b33, 1}, - {0x0b35, 0x0b39, 1}, - {0x0b3d, 0x0b5c, 31}, - {0x0b5d, 0x0b5f, 2}, - {0x0b60, 0x0b61, 1}, - {0x0b71, 0x0b83, 18}, - {0x0b85, 0x0b8a, 1}, - {0x0b8e, 0x0b90, 1}, - {0x0b92, 0x0b95, 1}, - {0x0b99, 0x0b9a, 1}, - {0x0b9c, 0x0b9e, 2}, - {0x0b9f, 0x0ba3, 4}, - {0x0ba4, 0x0ba8, 4}, - {0x0ba9, 0x0baa, 1}, - {0x0bae, 0x0bb9, 1}, - {0x0bd0, 0x0c05, 53}, - {0x0c06, 0x0c0c, 1}, - {0x0c0e, 0x0c10, 1}, - {0x0c12, 0x0c28, 1}, - {0x0c2a, 0x0c33, 1}, - {0x0c35, 0x0c39, 1}, - {0x0c3d, 0x0c58, 27}, - {0x0c59, 0x0c60, 7}, - {0x0c61, 0x0c85, 36}, - {0x0c86, 0x0c8c, 1}, - {0x0c8e, 0x0c90, 1}, - {0x0c92, 0x0ca8, 1}, - {0x0caa, 0x0cb3, 1}, - {0x0cb5, 0x0cb9, 1}, - {0x0cbd, 0x0cde, 33}, - {0x0ce0, 0x0ce1, 1}, - {0x0cf1, 0x0cf2, 1}, - {0x0d05, 0x0d0c, 1}, - {0x0d0e, 0x0d10, 1}, - {0x0d12, 0x0d3a, 1}, - {0x0d3d, 0x0d4e, 17}, - {0x0d60, 0x0d61, 1}, - {0x0d7a, 0x0d7f, 1}, - {0x0d85, 0x0d96, 1}, - {0x0d9a, 0x0db1, 1}, - {0x0db3, 0x0dbb, 1}, - {0x0dbd, 0x0dc0, 3}, - {0x0dc1, 0x0dc6, 1}, - {0x0e01, 0x0e30, 1}, - {0x0e32, 0x0e33, 1}, - {0x0e40, 0x0e45, 1}, - {0x0e81, 0x0e82, 1}, - {0x0e84, 0x0e87, 3}, - {0x0e88, 0x0e8a, 2}, - {0x0e8d, 0x0e94, 7}, - {0x0e95, 0x0e97, 1}, - {0x0e99, 0x0e9f, 1}, - {0x0ea1, 0x0ea3, 1}, - {0x0ea5, 0x0ea7, 2}, - {0x0eaa, 0x0eab, 1}, - {0x0ead, 0x0eb0, 1}, - {0x0eb2, 0x0eb3, 1}, - {0x0ebd, 0x0ec0, 3}, - {0x0ec1, 0x0ec4, 1}, - {0x0edc, 0x0edd, 1}, - {0x0f00, 0x0f40, 64}, - {0x0f41, 0x0f47, 1}, - {0x0f49, 0x0f6c, 1}, - {0x0f88, 0x0f8c, 1}, - {0x1000, 0x102a, 1}, - {0x103f, 0x1050, 17}, - {0x1051, 0x1055, 1}, - {0x105a, 0x105d, 1}, - {0x1061, 0x1065, 4}, - {0x1066, 0x106e, 8}, - {0x106f, 0x1070, 1}, - {0x1075, 0x1081, 1}, - {0x108e, 0x10d0, 66}, - {0x10d1, 0x10fa, 1}, - {0x1100, 0x1248, 1}, - {0x124a, 0x124d, 1}, - {0x1250, 0x1256, 1}, - {0x1258, 0x125a, 2}, - {0x125b, 0x125d, 1}, - {0x1260, 0x1288, 1}, - {0x128a, 0x128d, 1}, - {0x1290, 0x12b0, 1}, - {0x12b2, 0x12b5, 1}, - {0x12b8, 0x12be, 1}, - {0x12c0, 0x12c2, 2}, - {0x12c3, 0x12c5, 1}, - {0x12c8, 0x12d6, 1}, - {0x12d8, 0x1310, 1}, - {0x1312, 0x1315, 1}, - {0x1318, 0x135a, 1}, - {0x1380, 0x138f, 1}, - {0x13a0, 0x13f4, 1}, - {0x1401, 0x166c, 1}, - {0x166f, 0x167f, 1}, - {0x1681, 0x169a, 1}, - {0x16a0, 0x16ea, 1}, - {0x1700, 0x170c, 1}, - {0x170e, 0x1711, 1}, - {0x1720, 0x1731, 1}, - {0x1740, 0x1751, 1}, - {0x1760, 0x176c, 1}, - {0x176e, 0x1770, 1}, - {0x1780, 0x17b3, 1}, - {0x17dc, 0x1820, 68}, - {0x1821, 0x1842, 1}, - {0x1844, 0x1877, 1}, - {0x1880, 0x18a8, 1}, - {0x18aa, 0x18b0, 6}, - {0x18b1, 0x18f5, 1}, - {0x1900, 0x191c, 1}, - {0x1950, 0x196d, 1}, - {0x1970, 0x1974, 1}, - {0x1980, 0x19ab, 1}, - {0x19c1, 0x19c7, 1}, - {0x1a00, 0x1a16, 1}, - {0x1a20, 0x1a54, 1}, - {0x1b05, 0x1b33, 1}, - {0x1b45, 0x1b4b, 1}, - {0x1b83, 0x1ba0, 1}, - {0x1bae, 0x1baf, 1}, - {0x1bc0, 0x1be5, 1}, - {0x1c00, 0x1c23, 1}, - {0x1c4d, 0x1c4f, 1}, - {0x1c5a, 0x1c77, 1}, - {0x1ce9, 0x1cec, 1}, - {0x1cee, 0x1cf1, 1}, - {0x2135, 0x2138, 1}, - {0x2d30, 0x2d65, 1}, - {0x2d80, 0x2d96, 1}, - {0x2da0, 0x2da6, 1}, - {0x2da8, 0x2dae, 1}, - {0x2db0, 0x2db6, 1}, - {0x2db8, 0x2dbe, 1}, - {0x2dc0, 0x2dc6, 1}, - {0x2dc8, 0x2dce, 1}, - {0x2dd0, 0x2dd6, 1}, - {0x2dd8, 0x2dde, 1}, - {0x3006, 0x303c, 54}, - {0x3041, 0x3096, 1}, - {0x309f, 0x30a1, 2}, - {0x30a2, 0x30fa, 1}, - {0x30ff, 0x3105, 6}, - {0x3106, 0x312d, 1}, - {0x3131, 0x318e, 1}, - {0x31a0, 0x31ba, 1}, - {0x31f0, 0x31ff, 1}, - {0x3400, 0x4db5, 1}, - {0x4e00, 0x9fcb, 1}, - {0xa000, 0xa014, 1}, - {0xa016, 0xa48c, 1}, - {0xa4d0, 0xa4f7, 1}, - {0xa500, 0xa60b, 1}, - {0xa610, 0xa61f, 1}, - {0xa62a, 0xa62b, 1}, - {0xa66e, 0xa6a0, 50}, - {0xa6a1, 0xa6e5, 1}, - {0xa7fb, 0xa801, 1}, - {0xa803, 0xa805, 1}, - {0xa807, 0xa80a, 1}, - {0xa80c, 0xa822, 1}, - {0xa840, 0xa873, 1}, - {0xa882, 0xa8b3, 1}, - {0xa8f2, 0xa8f7, 1}, - {0xa8fb, 0xa90a, 15}, - {0xa90b, 0xa925, 1}, - {0xa930, 0xa946, 1}, - {0xa960, 0xa97c, 1}, - {0xa984, 0xa9b2, 1}, - {0xaa00, 0xaa28, 1}, - {0xaa40, 0xaa42, 1}, - {0xaa44, 0xaa4b, 1}, - {0xaa60, 0xaa6f, 1}, - {0xaa71, 0xaa76, 1}, - {0xaa7a, 0xaa80, 6}, - {0xaa81, 0xaaaf, 1}, - {0xaab1, 0xaab5, 4}, - {0xaab6, 0xaab9, 3}, - {0xaaba, 0xaabd, 1}, - {0xaac0, 0xaac2, 2}, - {0xaadb, 0xaadc, 1}, - {0xab01, 0xab06, 1}, - {0xab09, 0xab0e, 1}, - {0xab11, 0xab16, 1}, - {0xab20, 0xab26, 1}, - {0xab28, 0xab2e, 1}, - {0xabc0, 0xabe2, 1}, - {0xac00, 0xd7a3, 1}, - {0xd7b0, 0xd7c6, 1}, - {0xd7cb, 0xd7fb, 1}, - {0xf900, 0xfa2d, 1}, - {0xfa30, 0xfa6d, 1}, - {0xfa70, 0xfad9, 1}, - {0xfb1d, 0xfb1f, 2}, - {0xfb20, 0xfb28, 1}, - {0xfb2a, 0xfb36, 1}, - {0xfb38, 0xfb3c, 1}, - {0xfb3e, 0xfb40, 2}, - {0xfb41, 0xfb43, 2}, - {0xfb44, 0xfb46, 2}, - {0xfb47, 0xfbb1, 1}, - {0xfbd3, 0xfd3d, 1}, - {0xfd50, 0xfd8f, 1}, - {0xfd92, 0xfdc7, 1}, - {0xfdf0, 0xfdfb, 1}, - {0xfe70, 0xfe74, 1}, - {0xfe76, 0xfefc, 1}, - {0xff66, 0xff6f, 1}, - {0xff71, 0xff9d, 1}, - {0xffa0, 0xffbe, 1}, - {0xffc2, 0xffc7, 1}, - {0xffca, 0xffcf, 1}, - {0xffd2, 0xffd7, 1}, - {0xffda, 0xffdc, 1}, - {0x10000, 0x1000b, 1}, - {0x1000d, 0x10026, 1}, - {0x10028, 0x1003a, 1}, - {0x1003c, 0x1003d, 1}, - {0x1003f, 0x1004d, 1}, - {0x10050, 0x1005d, 1}, - {0x10080, 0x100fa, 1}, - {0x10280, 0x1029c, 1}, - {0x102a0, 0x102d0, 1}, - {0x10300, 0x1031e, 1}, - {0x10330, 0x10340, 1}, - {0x10342, 0x10349, 1}, - {0x10380, 0x1039d, 1}, - {0x103a0, 0x103c3, 1}, - {0x103c8, 0x103cf, 1}, - {0x10450, 0x1049d, 1}, - {0x10800, 0x10805, 1}, - {0x10808, 0x1080a, 2}, - {0x1080b, 0x10835, 1}, - {0x10837, 0x10838, 1}, - {0x1083c, 0x1083f, 3}, - {0x10840, 0x10855, 1}, - {0x10900, 0x10915, 1}, - {0x10920, 0x10939, 1}, - {0x10a00, 0x10a10, 16}, - {0x10a11, 0x10a13, 1}, - {0x10a15, 0x10a17, 1}, - {0x10a19, 0x10a33, 1}, - {0x10a60, 0x10a7c, 1}, - {0x10b00, 0x10b35, 1}, - {0x10b40, 0x10b55, 1}, - {0x10b60, 0x10b72, 1}, - {0x10c00, 0x10c48, 1}, - {0x11003, 0x11037, 1}, - {0x11083, 0x110af, 1}, - {0x12000, 0x1236e, 1}, - {0x13000, 0x1342e, 1}, - {0x16800, 0x16a38, 1}, - {0x1b000, 0x1b001, 1}, - {0x20000, 0x2a6d6, 1}, - {0x2a700, 0x2b734, 1}, - {0x2b740, 0x2b81d, 1}, - {0x2f800, 0x2fa1d, 1}, +var _Lm = &RangeTable{ + R16: []Range16{ + {0x02b0, 0x02c1, 1}, + {0x02c6, 0x02d1, 1}, + {0x02e0, 0x02e4, 1}, + {0x02ec, 0x02ee, 2}, + {0x0374, 0x037a, 6}, + {0x0559, 0x0640, 231}, + {0x06e5, 0x06e6, 1}, + {0x07f4, 0x07f5, 1}, + {0x07fa, 0x081a, 32}, + {0x0824, 0x0828, 4}, + {0x0971, 0x0e46, 1237}, + {0x0ec6, 0x10fc, 566}, + {0x17d7, 0x1843, 108}, + {0x1aa7, 0x1c78, 465}, + {0x1c79, 0x1c7d, 1}, + {0x1d2c, 0x1d61, 1}, + {0x1d78, 0x1d9b, 35}, + {0x1d9c, 0x1dbf, 1}, + {0x2071, 0x207f, 14}, + {0x2090, 0x209c, 1}, + {0x2c7d, 0x2d6f, 242}, + {0x2e2f, 0x3005, 470}, + {0x3031, 0x3035, 1}, + {0x303b, 0x309d, 98}, + {0x309e, 0x30fc, 94}, + {0x30fd, 0x30fe, 1}, + {0xa015, 0xa4f8, 1251}, + {0xa4f9, 0xa4fd, 1}, + {0xa60c, 0xa67f, 115}, + {0xa717, 0xa71f, 1}, + {0xa770, 0xa788, 24}, + {0xa9cf, 0xaa70, 161}, + {0xaadd, 0xff70, 21651}, + {0xff9e, 0xff9f, 1}, + }, +} + +var _Ll = &RangeTable{ + R16: []Range16{ + {0x0061, 0x007a, 1}, + {0x00aa, 0x00b5, 11}, + {0x00ba, 0x00df, 37}, + {0x00e0, 0x00f6, 1}, + {0x00f8, 0x00ff, 1}, + {0x0101, 0x0137, 2}, + {0x0138, 0x0148, 2}, + {0x0149, 0x0177, 2}, + {0x017a, 0x017e, 2}, + {0x017f, 0x0180, 1}, + {0x0183, 0x0185, 2}, + {0x0188, 0x018c, 4}, + {0x018d, 0x0192, 5}, + {0x0195, 0x0199, 4}, + {0x019a, 0x019b, 1}, + {0x019e, 0x01a1, 3}, + {0x01a3, 0x01a5, 2}, + {0x01a8, 0x01aa, 2}, + {0x01ab, 0x01ad, 2}, + {0x01b0, 0x01b4, 4}, + {0x01b6, 0x01b9, 3}, + {0x01ba, 0x01bd, 3}, + {0x01be, 0x01bf, 1}, + {0x01c6, 0x01cc, 3}, + {0x01ce, 0x01dc, 2}, + {0x01dd, 0x01ef, 2}, + {0x01f0, 0x01f3, 3}, + {0x01f5, 0x01f9, 4}, + {0x01fb, 0x0233, 2}, + {0x0234, 0x0239, 1}, + {0x023c, 0x023f, 3}, + {0x0240, 0x0242, 2}, + {0x0247, 0x024f, 2}, + {0x0250, 0x0293, 1}, + {0x0295, 0x02af, 1}, + {0x0371, 0x0373, 2}, + {0x0377, 0x037b, 4}, + {0x037c, 0x037d, 1}, + {0x0390, 0x03ac, 28}, + {0x03ad, 0x03ce, 1}, + {0x03d0, 0x03d1, 1}, + {0x03d5, 0x03d7, 1}, + {0x03d9, 0x03ef, 2}, + {0x03f0, 0x03f3, 1}, + {0x03f5, 0x03fb, 3}, + {0x03fc, 0x0430, 52}, + {0x0431, 0x045f, 1}, + {0x0461, 0x0481, 2}, + {0x048b, 0x04bf, 2}, + {0x04c2, 0x04ce, 2}, + {0x04cf, 0x0527, 2}, + {0x0561, 0x0587, 1}, + {0x1d00, 0x1d2b, 1}, + {0x1d62, 0x1d77, 1}, + {0x1d79, 0x1d9a, 1}, + {0x1e01, 0x1e95, 2}, + {0x1e96, 0x1e9d, 1}, + {0x1e9f, 0x1eff, 2}, + {0x1f00, 0x1f07, 1}, + {0x1f10, 0x1f15, 1}, + {0x1f20, 0x1f27, 1}, + {0x1f30, 0x1f37, 1}, + {0x1f40, 0x1f45, 1}, + {0x1f50, 0x1f57, 1}, + {0x1f60, 0x1f67, 1}, + {0x1f70, 0x1f7d, 1}, + {0x1f80, 0x1f87, 1}, + {0x1f90, 0x1f97, 1}, + {0x1fa0, 0x1fa7, 1}, + {0x1fb0, 0x1fb4, 1}, + {0x1fb6, 0x1fb7, 1}, + {0x1fbe, 0x1fc2, 4}, + {0x1fc3, 0x1fc4, 1}, + {0x1fc6, 0x1fc7, 1}, + {0x1fd0, 0x1fd3, 1}, + {0x1fd6, 0x1fd7, 1}, + {0x1fe0, 0x1fe7, 1}, + {0x1ff2, 0x1ff4, 1}, + {0x1ff6, 0x1ff7, 1}, + {0x210a, 0x210e, 4}, + {0x210f, 0x2113, 4}, + {0x212f, 0x2139, 5}, + {0x213c, 0x213d, 1}, + {0x2146, 0x2149, 1}, + {0x214e, 0x2184, 54}, + {0x2c30, 0x2c5e, 1}, + {0x2c61, 0x2c65, 4}, + {0x2c66, 0x2c6c, 2}, + {0x2c71, 0x2c73, 2}, + {0x2c74, 0x2c76, 2}, + {0x2c77, 0x2c7c, 1}, + {0x2c81, 0x2ce3, 2}, + {0x2ce4, 0x2cec, 8}, + {0x2cee, 0x2d00, 18}, + {0x2d01, 0x2d25, 1}, + {0xa641, 0xa66d, 2}, + {0xa681, 0xa697, 2}, + {0xa723, 0xa72f, 2}, + {0xa730, 0xa731, 1}, + {0xa733, 0xa771, 2}, + {0xa772, 0xa778, 1}, + {0xa77a, 0xa77c, 2}, + {0xa77f, 0xa787, 2}, + {0xa78c, 0xa78e, 2}, + {0xa791, 0xa7a1, 16}, + {0xa7a3, 0xa7a9, 2}, + {0xa7fa, 0xfb00, 21254}, + {0xfb01, 0xfb06, 1}, + {0xfb13, 0xfb17, 1}, + {0xff41, 0xff5a, 1}, + }, + R32: []Range32{ + {0x10428, 0x1044f, 1}, + {0x1d41a, 0x1d433, 1}, + {0x1d44e, 0x1d454, 1}, + {0x1d456, 0x1d467, 1}, + {0x1d482, 0x1d49b, 1}, + {0x1d4b6, 0x1d4b9, 1}, + {0x1d4bb, 0x1d4bd, 2}, + {0x1d4be, 0x1d4c3, 1}, + {0x1d4c5, 0x1d4cf, 1}, + {0x1d4ea, 0x1d503, 1}, + {0x1d51e, 0x1d537, 1}, + {0x1d552, 0x1d56b, 1}, + {0x1d586, 0x1d59f, 1}, + {0x1d5ba, 0x1d5d3, 1}, + {0x1d5ee, 0x1d607, 1}, + {0x1d622, 0x1d63b, 1}, + {0x1d656, 0x1d66f, 1}, + {0x1d68a, 0x1d6a5, 1}, + {0x1d6c2, 0x1d6da, 1}, + {0x1d6dc, 0x1d6e1, 1}, + {0x1d6fc, 0x1d714, 1}, + {0x1d716, 0x1d71b, 1}, + {0x1d736, 0x1d74e, 1}, + {0x1d750, 0x1d755, 1}, + {0x1d770, 0x1d788, 1}, + {0x1d78a, 0x1d78f, 1}, + {0x1d7aa, 0x1d7c2, 1}, + {0x1d7c4, 0x1d7c9, 1}, + {0x1d7cb, 0x1d7cb, 1}, + }, +} + +var _Me = &RangeTable{ + R16: []Range16{ + {0x0488, 0x0489, 1}, + {0x20dd, 0x20e0, 1}, + {0x20e2, 0x20e4, 1}, + {0xa670, 0xa672, 1}, + }, +} + +var _Mc = &RangeTable{ + R16: []Range16{ + {0x0903, 0x093b, 56}, + {0x093e, 0x0940, 1}, + {0x0949, 0x094c, 1}, + {0x094e, 0x094f, 1}, + {0x0982, 0x0983, 1}, + {0x09be, 0x09c0, 1}, + {0x09c7, 0x09c8, 1}, + {0x09cb, 0x09cc, 1}, + {0x09d7, 0x0a03, 44}, + {0x0a3e, 0x0a40, 1}, + {0x0a83, 0x0abe, 59}, + {0x0abf, 0x0ac0, 1}, + {0x0ac9, 0x0acb, 2}, + {0x0acc, 0x0b02, 54}, + {0x0b03, 0x0b3e, 59}, + {0x0b40, 0x0b47, 7}, + {0x0b48, 0x0b4b, 3}, + {0x0b4c, 0x0b57, 11}, + {0x0bbe, 0x0bbf, 1}, + {0x0bc1, 0x0bc2, 1}, + {0x0bc6, 0x0bc8, 1}, + {0x0bca, 0x0bcc, 1}, + {0x0bd7, 0x0c01, 42}, + {0x0c02, 0x0c03, 1}, + {0x0c41, 0x0c44, 1}, + {0x0c82, 0x0c83, 1}, + {0x0cbe, 0x0cc0, 2}, + {0x0cc1, 0x0cc4, 1}, + {0x0cc7, 0x0cc8, 1}, + {0x0cca, 0x0ccb, 1}, + {0x0cd5, 0x0cd6, 1}, + {0x0d02, 0x0d03, 1}, + {0x0d3e, 0x0d40, 1}, + {0x0d46, 0x0d48, 1}, + {0x0d4a, 0x0d4c, 1}, + {0x0d57, 0x0d82, 43}, + {0x0d83, 0x0dcf, 76}, + {0x0dd0, 0x0dd1, 1}, + {0x0dd8, 0x0ddf, 1}, + {0x0df2, 0x0df3, 1}, + {0x0f3e, 0x0f3f, 1}, + {0x0f7f, 0x102b, 172}, + {0x102c, 0x1031, 5}, + {0x1038, 0x103b, 3}, + {0x103c, 0x1056, 26}, + {0x1057, 0x1062, 11}, + {0x1063, 0x1064, 1}, + {0x1067, 0x106d, 1}, + {0x1083, 0x1084, 1}, + {0x1087, 0x108c, 1}, + {0x108f, 0x109a, 11}, + {0x109b, 0x109c, 1}, + {0x17b6, 0x17be, 8}, + {0x17bf, 0x17c5, 1}, + {0x17c7, 0x17c8, 1}, + {0x1923, 0x1926, 1}, + {0x1929, 0x192b, 1}, + {0x1930, 0x1931, 1}, + {0x1933, 0x1938, 1}, + {0x19b0, 0x19c0, 1}, + {0x19c8, 0x19c9, 1}, + {0x1a19, 0x1a1b, 1}, + {0x1a55, 0x1a57, 2}, + {0x1a61, 0x1a63, 2}, + {0x1a64, 0x1a6d, 9}, + {0x1a6e, 0x1a72, 1}, + {0x1b04, 0x1b35, 49}, + {0x1b3b, 0x1b3d, 2}, + {0x1b3e, 0x1b41, 1}, + {0x1b43, 0x1b44, 1}, + {0x1b82, 0x1ba1, 31}, + {0x1ba6, 0x1ba7, 1}, + {0x1baa, 0x1be7, 61}, + {0x1bea, 0x1bec, 1}, + {0x1bee, 0x1bf2, 4}, + {0x1bf3, 0x1c24, 49}, + {0x1c25, 0x1c2b, 1}, + {0x1c34, 0x1c35, 1}, + {0x1ce1, 0x1cf2, 17}, + {0xa823, 0xa824, 1}, + {0xa827, 0xa880, 89}, + {0xa881, 0xa8b4, 51}, + {0xa8b5, 0xa8c3, 1}, + {0xa952, 0xa953, 1}, + {0xa983, 0xa9b4, 49}, + {0xa9b5, 0xa9ba, 5}, + {0xa9bb, 0xa9bd, 2}, + {0xa9be, 0xa9c0, 1}, + {0xaa2f, 0xaa30, 1}, + {0xaa33, 0xaa34, 1}, + {0xaa4d, 0xaa7b, 46}, + {0xabe3, 0xabe4, 1}, + {0xabe6, 0xabe7, 1}, + {0xabe9, 0xabea, 1}, + {0xabec, 0xabec, 1}, + }, + R32: []Range32{ + {0x11000, 0x11000, 1}, + {0x11002, 0x11082, 128}, + {0x110b0, 0x110b2, 1}, + {0x110b7, 0x110b8, 1}, + {0x1d165, 0x1d166, 1}, + {0x1d16d, 0x1d172, 1}, + }, +} + +var _Mn = &RangeTable{ + R16: []Range16{ + {0x0300, 0x036f, 1}, + {0x0483, 0x0487, 1}, + {0x0591, 0x05bd, 1}, + {0x05bf, 0x05c1, 2}, + {0x05c2, 0x05c4, 2}, + {0x05c5, 0x05c7, 2}, + {0x0610, 0x061a, 1}, + {0x064b, 0x065f, 1}, + {0x0670, 0x06d6, 102}, + {0x06d7, 0x06dc, 1}, + {0x06df, 0x06e4, 1}, + {0x06e7, 0x06e8, 1}, + {0x06ea, 0x06ed, 1}, + {0x0711, 0x0730, 31}, + {0x0731, 0x074a, 1}, + {0x07a6, 0x07b0, 1}, + {0x07eb, 0x07f3, 1}, + {0x0816, 0x0819, 1}, + {0x081b, 0x0823, 1}, + {0x0825, 0x0827, 1}, + {0x0829, 0x082d, 1}, + {0x0859, 0x085b, 1}, + {0x0900, 0x0902, 1}, + {0x093a, 0x093c, 2}, + {0x0941, 0x0948, 1}, + {0x094d, 0x0951, 4}, + {0x0952, 0x0957, 1}, + {0x0962, 0x0963, 1}, + {0x0981, 0x09bc, 59}, + {0x09c1, 0x09c4, 1}, + {0x09cd, 0x09e2, 21}, + {0x09e3, 0x0a01, 30}, + {0x0a02, 0x0a3c, 58}, + {0x0a41, 0x0a42, 1}, + {0x0a47, 0x0a48, 1}, + {0x0a4b, 0x0a4d, 1}, + {0x0a51, 0x0a70, 31}, + {0x0a71, 0x0a75, 4}, + {0x0a81, 0x0a82, 1}, + {0x0abc, 0x0ac1, 5}, + {0x0ac2, 0x0ac5, 1}, + {0x0ac7, 0x0ac8, 1}, + {0x0acd, 0x0ae2, 21}, + {0x0ae3, 0x0b01, 30}, + {0x0b3c, 0x0b3f, 3}, + {0x0b41, 0x0b44, 1}, + {0x0b4d, 0x0b56, 9}, + {0x0b62, 0x0b63, 1}, + {0x0b82, 0x0bc0, 62}, + {0x0bcd, 0x0c3e, 113}, + {0x0c3f, 0x0c40, 1}, + {0x0c46, 0x0c48, 1}, + {0x0c4a, 0x0c4d, 1}, + {0x0c55, 0x0c56, 1}, + {0x0c62, 0x0c63, 1}, + {0x0cbc, 0x0cbf, 3}, + {0x0cc6, 0x0ccc, 6}, + {0x0ccd, 0x0ce2, 21}, + {0x0ce3, 0x0d41, 94}, + {0x0d42, 0x0d44, 1}, + {0x0d4d, 0x0d62, 21}, + {0x0d63, 0x0dca, 103}, + {0x0dd2, 0x0dd4, 1}, + {0x0dd6, 0x0e31, 91}, + {0x0e34, 0x0e3a, 1}, + {0x0e47, 0x0e4e, 1}, + {0x0eb1, 0x0eb4, 3}, + {0x0eb5, 0x0eb9, 1}, + {0x0ebb, 0x0ebc, 1}, + {0x0ec8, 0x0ecd, 1}, + {0x0f18, 0x0f19, 1}, + {0x0f35, 0x0f39, 2}, + {0x0f71, 0x0f7e, 1}, + {0x0f80, 0x0f84, 1}, + {0x0f86, 0x0f87, 1}, + {0x0f8d, 0x0f97, 1}, + {0x0f99, 0x0fbc, 1}, + {0x0fc6, 0x102d, 103}, + {0x102e, 0x1030, 1}, + {0x1032, 0x1037, 1}, + {0x1039, 0x103a, 1}, + {0x103d, 0x103e, 1}, + {0x1058, 0x1059, 1}, + {0x105e, 0x1060, 1}, + {0x1071, 0x1074, 1}, + {0x1082, 0x1085, 3}, + {0x1086, 0x108d, 7}, + {0x109d, 0x135d, 704}, + {0x135e, 0x135f, 1}, + {0x1712, 0x1714, 1}, + {0x1732, 0x1734, 1}, + {0x1752, 0x1753, 1}, + {0x1772, 0x1773, 1}, + {0x17b7, 0x17bd, 1}, + {0x17c6, 0x17c9, 3}, + {0x17ca, 0x17d3, 1}, + {0x17dd, 0x180b, 46}, + {0x180c, 0x180d, 1}, + {0x18a9, 0x1920, 119}, + {0x1921, 0x1922, 1}, + {0x1927, 0x1928, 1}, + {0x1932, 0x1939, 7}, + {0x193a, 0x193b, 1}, + {0x1a17, 0x1a18, 1}, + {0x1a56, 0x1a58, 2}, + {0x1a59, 0x1a5e, 1}, + {0x1a60, 0x1a62, 2}, + {0x1a65, 0x1a6c, 1}, + {0x1a73, 0x1a7c, 1}, + {0x1a7f, 0x1b00, 129}, + {0x1b01, 0x1b03, 1}, + {0x1b34, 0x1b36, 2}, + {0x1b37, 0x1b3a, 1}, + {0x1b3c, 0x1b42, 6}, + {0x1b6b, 0x1b73, 1}, + {0x1b80, 0x1b81, 1}, + {0x1ba2, 0x1ba5, 1}, + {0x1ba8, 0x1ba9, 1}, + {0x1be6, 0x1be8, 2}, + {0x1be9, 0x1bed, 4}, + {0x1bef, 0x1bf1, 1}, + {0x1c2c, 0x1c33, 1}, + {0x1c36, 0x1c37, 1}, + {0x1cd0, 0x1cd2, 1}, + {0x1cd4, 0x1ce0, 1}, + {0x1ce2, 0x1ce8, 1}, + {0x1ced, 0x1dc0, 211}, + {0x1dc1, 0x1de6, 1}, + {0x1dfc, 0x1dff, 1}, + {0x20d0, 0x20dc, 1}, + {0x20e1, 0x20e5, 4}, + {0x20e6, 0x20f0, 1}, + {0x2cef, 0x2cf1, 1}, + {0x2d7f, 0x2de0, 97}, + {0x2de1, 0x2dff, 1}, + {0x302a, 0x302f, 1}, + {0x3099, 0x309a, 1}, + {0xa66f, 0xa67c, 13}, + {0xa67d, 0xa6f0, 115}, + {0xa6f1, 0xa802, 273}, + {0xa806, 0xa80b, 5}, + {0xa825, 0xa826, 1}, + {0xa8c4, 0xa8e0, 28}, + {0xa8e1, 0xa8f1, 1}, + {0xa926, 0xa92d, 1}, + {0xa947, 0xa951, 1}, + {0xa980, 0xa982, 1}, + {0xa9b3, 0xa9b6, 3}, + {0xa9b7, 0xa9b9, 1}, + {0xa9bc, 0xaa29, 109}, + {0xaa2a, 0xaa2e, 1}, + {0xaa31, 0xaa32, 1}, + {0xaa35, 0xaa36, 1}, + {0xaa43, 0xaa4c, 9}, + {0xaab0, 0xaab2, 2}, + {0xaab3, 0xaab4, 1}, + {0xaab7, 0xaab8, 1}, + {0xaabe, 0xaabf, 1}, + {0xaac1, 0xabe5, 292}, + {0xabe8, 0xabed, 5}, + {0xfb1e, 0xfe00, 738}, + {0xfe01, 0xfe0f, 1}, + {0xfe20, 0xfe26, 1}, + }, + R32: []Range32{ + {0x101fd, 0x10a01, 2052}, + {0x10a02, 0x10a03, 1}, + {0x10a05, 0x10a06, 1}, + {0x10a0c, 0x10a0f, 1}, + {0x10a38, 0x10a3a, 1}, + {0x10a3f, 0x11001, 1474}, + {0x11038, 0x11046, 1}, + {0x11080, 0x11081, 1}, + {0x110b3, 0x110b6, 1}, + {0x110b9, 0x110ba, 1}, + {0x1d167, 0x1d169, 1}, + {0x1d17b, 0x1d182, 1}, + {0x1d185, 0x1d18b, 1}, + {0x1d1aa, 0x1d1ad, 1}, + {0x1d242, 0x1d244, 1}, + {0xe0100, 0xe01ef, 1}, + }, +} + +var _Zl = &RangeTable{ + R16: []Range16{ + {0x2028, 0x2028, 1}, + }, +} + +var letter = &RangeTable{ + R16: []Range16{ + {0x0041, 0x005a, 1}, + {0x0061, 0x007a, 1}, + {0x00aa, 0x00b5, 11}, + {0x00ba, 0x00c0, 6}, + {0x00c1, 0x00d6, 1}, + {0x00d8, 0x00f6, 1}, + {0x00f8, 0x02c1, 1}, + {0x02c6, 0x02d1, 1}, + {0x02e0, 0x02e4, 1}, + {0x02ec, 0x02ee, 2}, + {0x0370, 0x0374, 1}, + {0x0376, 0x0377, 1}, + {0x037a, 0x037d, 1}, + {0x0386, 0x0388, 2}, + {0x0389, 0x038a, 1}, + {0x038c, 0x038e, 2}, + {0x038f, 0x03a1, 1}, + {0x03a3, 0x03f5, 1}, + {0x03f7, 0x0481, 1}, + {0x048a, 0x0527, 1}, + {0x0531, 0x0556, 1}, + {0x0559, 0x0561, 8}, + {0x0562, 0x0587, 1}, + {0x05d0, 0x05ea, 1}, + {0x05f0, 0x05f2, 1}, + {0x0620, 0x064a, 1}, + {0x066e, 0x066f, 1}, + {0x0671, 0x06d3, 1}, + {0x06d5, 0x06e5, 16}, + {0x06e6, 0x06ee, 8}, + {0x06ef, 0x06fa, 11}, + {0x06fb, 0x06fc, 1}, + {0x06ff, 0x0710, 17}, + {0x0712, 0x072f, 1}, + {0x074d, 0x07a5, 1}, + {0x07b1, 0x07ca, 25}, + {0x07cb, 0x07ea, 1}, + {0x07f4, 0x07f5, 1}, + {0x07fa, 0x0800, 6}, + {0x0801, 0x0815, 1}, + {0x081a, 0x0824, 10}, + {0x0828, 0x0840, 24}, + {0x0841, 0x0858, 1}, + {0x0904, 0x0939, 1}, + {0x093d, 0x0950, 19}, + {0x0958, 0x0961, 1}, + {0x0971, 0x0977, 1}, + {0x0979, 0x097f, 1}, + {0x0985, 0x098c, 1}, + {0x098f, 0x0990, 1}, + {0x0993, 0x09a8, 1}, + {0x09aa, 0x09b0, 1}, + {0x09b2, 0x09b6, 4}, + {0x09b7, 0x09b9, 1}, + {0x09bd, 0x09ce, 17}, + {0x09dc, 0x09dd, 1}, + {0x09df, 0x09e1, 1}, + {0x09f0, 0x09f1, 1}, + {0x0a05, 0x0a0a, 1}, + {0x0a0f, 0x0a10, 1}, + {0x0a13, 0x0a28, 1}, + {0x0a2a, 0x0a30, 1}, + {0x0a32, 0x0a33, 1}, + {0x0a35, 0x0a36, 1}, + {0x0a38, 0x0a39, 1}, + {0x0a59, 0x0a5c, 1}, + {0x0a5e, 0x0a72, 20}, + {0x0a73, 0x0a74, 1}, + {0x0a85, 0x0a8d, 1}, + {0x0a8f, 0x0a91, 1}, + {0x0a93, 0x0aa8, 1}, + {0x0aaa, 0x0ab0, 1}, + {0x0ab2, 0x0ab3, 1}, + {0x0ab5, 0x0ab9, 1}, + {0x0abd, 0x0ad0, 19}, + {0x0ae0, 0x0ae1, 1}, + {0x0b05, 0x0b0c, 1}, + {0x0b0f, 0x0b10, 1}, + {0x0b13, 0x0b28, 1}, + {0x0b2a, 0x0b30, 1}, + {0x0b32, 0x0b33, 1}, + {0x0b35, 0x0b39, 1}, + {0x0b3d, 0x0b5c, 31}, + {0x0b5d, 0x0b5f, 2}, + {0x0b60, 0x0b61, 1}, + {0x0b71, 0x0b83, 18}, + {0x0b85, 0x0b8a, 1}, + {0x0b8e, 0x0b90, 1}, + {0x0b92, 0x0b95, 1}, + {0x0b99, 0x0b9a, 1}, + {0x0b9c, 0x0b9e, 2}, + {0x0b9f, 0x0ba3, 4}, + {0x0ba4, 0x0ba8, 4}, + {0x0ba9, 0x0baa, 1}, + {0x0bae, 0x0bb9, 1}, + {0x0bd0, 0x0c05, 53}, + {0x0c06, 0x0c0c, 1}, + {0x0c0e, 0x0c10, 1}, + {0x0c12, 0x0c28, 1}, + {0x0c2a, 0x0c33, 1}, + {0x0c35, 0x0c39, 1}, + {0x0c3d, 0x0c58, 27}, + {0x0c59, 0x0c60, 7}, + {0x0c61, 0x0c85, 36}, + {0x0c86, 0x0c8c, 1}, + {0x0c8e, 0x0c90, 1}, + {0x0c92, 0x0ca8, 1}, + {0x0caa, 0x0cb3, 1}, + {0x0cb5, 0x0cb9, 1}, + {0x0cbd, 0x0cde, 33}, + {0x0ce0, 0x0ce1, 1}, + {0x0cf1, 0x0cf2, 1}, + {0x0d05, 0x0d0c, 1}, + {0x0d0e, 0x0d10, 1}, + {0x0d12, 0x0d3a, 1}, + {0x0d3d, 0x0d4e, 17}, + {0x0d60, 0x0d61, 1}, + {0x0d7a, 0x0d7f, 1}, + {0x0d85, 0x0d96, 1}, + {0x0d9a, 0x0db1, 1}, + {0x0db3, 0x0dbb, 1}, + {0x0dbd, 0x0dc0, 3}, + {0x0dc1, 0x0dc6, 1}, + {0x0e01, 0x0e30, 1}, + {0x0e32, 0x0e33, 1}, + {0x0e40, 0x0e46, 1}, + {0x0e81, 0x0e82, 1}, + {0x0e84, 0x0e87, 3}, + {0x0e88, 0x0e8a, 2}, + {0x0e8d, 0x0e94, 7}, + {0x0e95, 0x0e97, 1}, + {0x0e99, 0x0e9f, 1}, + {0x0ea1, 0x0ea3, 1}, + {0x0ea5, 0x0ea7, 2}, + {0x0eaa, 0x0eab, 1}, + {0x0ead, 0x0eb0, 1}, + {0x0eb2, 0x0eb3, 1}, + {0x0ebd, 0x0ec0, 3}, + {0x0ec1, 0x0ec4, 1}, + {0x0ec6, 0x0edc, 22}, + {0x0edd, 0x0f00, 35}, + {0x0f40, 0x0f47, 1}, + {0x0f49, 0x0f6c, 1}, + {0x0f88, 0x0f8c, 1}, + {0x1000, 0x102a, 1}, + {0x103f, 0x1050, 17}, + {0x1051, 0x1055, 1}, + {0x105a, 0x105d, 1}, + {0x1061, 0x1065, 4}, + {0x1066, 0x106e, 8}, + {0x106f, 0x1070, 1}, + {0x1075, 0x1081, 1}, + {0x108e, 0x10a0, 18}, + {0x10a1, 0x10c5, 1}, + {0x10d0, 0x10fa, 1}, + {0x10fc, 0x1100, 4}, + {0x1101, 0x1248, 1}, + {0x124a, 0x124d, 1}, + {0x1250, 0x1256, 1}, + {0x1258, 0x125a, 2}, + {0x125b, 0x125d, 1}, + {0x1260, 0x1288, 1}, + {0x128a, 0x128d, 1}, + {0x1290, 0x12b0, 1}, + {0x12b2, 0x12b5, 1}, + {0x12b8, 0x12be, 1}, + {0x12c0, 0x12c2, 2}, + {0x12c3, 0x12c5, 1}, + {0x12c8, 0x12d6, 1}, + {0x12d8, 0x1310, 1}, + {0x1312, 0x1315, 1}, + {0x1318, 0x135a, 1}, + {0x1380, 0x138f, 1}, + {0x13a0, 0x13f4, 1}, + {0x1401, 0x166c, 1}, + {0x166f, 0x167f, 1}, + {0x1681, 0x169a, 1}, + {0x16a0, 0x16ea, 1}, + {0x1700, 0x170c, 1}, + {0x170e, 0x1711, 1}, + {0x1720, 0x1731, 1}, + {0x1740, 0x1751, 1}, + {0x1760, 0x176c, 1}, + {0x176e, 0x1770, 1}, + {0x1780, 0x17b3, 1}, + {0x17d7, 0x17dc, 5}, + {0x1820, 0x1877, 1}, + {0x1880, 0x18a8, 1}, + {0x18aa, 0x18b0, 6}, + {0x18b1, 0x18f5, 1}, + {0x1900, 0x191c, 1}, + {0x1950, 0x196d, 1}, + {0x1970, 0x1974, 1}, + {0x1980, 0x19ab, 1}, + {0x19c1, 0x19c7, 1}, + {0x1a00, 0x1a16, 1}, + {0x1a20, 0x1a54, 1}, + {0x1aa7, 0x1b05, 94}, + {0x1b06, 0x1b33, 1}, + {0x1b45, 0x1b4b, 1}, + {0x1b83, 0x1ba0, 1}, + {0x1bae, 0x1baf, 1}, + {0x1bc0, 0x1be5, 1}, + {0x1c00, 0x1c23, 1}, + {0x1c4d, 0x1c4f, 1}, + {0x1c5a, 0x1c7d, 1}, + {0x1ce9, 0x1cec, 1}, + {0x1cee, 0x1cf1, 1}, + {0x1d00, 0x1dbf, 1}, + {0x1e00, 0x1f15, 1}, + {0x1f18, 0x1f1d, 1}, + {0x1f20, 0x1f45, 1}, + {0x1f48, 0x1f4d, 1}, + {0x1f50, 0x1f57, 1}, + {0x1f59, 0x1f5f, 2}, + {0x1f60, 0x1f7d, 1}, + {0x1f80, 0x1fb4, 1}, + {0x1fb6, 0x1fbc, 1}, + {0x1fbe, 0x1fc2, 4}, + {0x1fc3, 0x1fc4, 1}, + {0x1fc6, 0x1fcc, 1}, + {0x1fd0, 0x1fd3, 1}, + {0x1fd6, 0x1fdb, 1}, + {0x1fe0, 0x1fec, 1}, + {0x1ff2, 0x1ff4, 1}, + {0x1ff6, 0x1ffc, 1}, + {0x2071, 0x207f, 14}, + {0x2090, 0x209c, 1}, + {0x2102, 0x2107, 5}, + {0x210a, 0x2113, 1}, + {0x2115, 0x2119, 4}, + {0x211a, 0x211d, 1}, + {0x2124, 0x212a, 2}, + {0x212b, 0x212d, 1}, + {0x212f, 0x2139, 1}, + {0x213c, 0x213f, 1}, + {0x2145, 0x2149, 1}, + {0x214e, 0x2183, 53}, + {0x2184, 0x2c00, 2684}, + {0x2c01, 0x2c2e, 1}, + {0x2c30, 0x2c5e, 1}, + {0x2c60, 0x2ce4, 1}, + {0x2ceb, 0x2cee, 1}, + {0x2d00, 0x2d25, 1}, + {0x2d30, 0x2d65, 1}, + {0x2d6f, 0x2d80, 17}, + {0x2d81, 0x2d96, 1}, + {0x2da0, 0x2da6, 1}, + {0x2da8, 0x2dae, 1}, + {0x2db0, 0x2db6, 1}, + {0x2db8, 0x2dbe, 1}, + {0x2dc0, 0x2dc6, 1}, + {0x2dc8, 0x2dce, 1}, + {0x2dd0, 0x2dd6, 1}, + {0x2dd8, 0x2dde, 1}, + {0x2e2f, 0x3005, 470}, + {0x3006, 0x3031, 43}, + {0x3032, 0x3035, 1}, + {0x303b, 0x303c, 1}, + {0x3041, 0x3096, 1}, + {0x309d, 0x309f, 1}, + {0x30a1, 0x30fa, 1}, + {0x30fc, 0x30ff, 1}, + {0x3105, 0x312d, 1}, + {0x3131, 0x318e, 1}, + {0x31a0, 0x31ba, 1}, + {0x31f0, 0x31ff, 1}, + {0x3400, 0x4db5, 1}, + {0x4e00, 0x9fcb, 1}, + {0xa000, 0xa48c, 1}, + {0xa4d0, 0xa4fd, 1}, + {0xa500, 0xa60c, 1}, + {0xa610, 0xa61f, 1}, + {0xa62a, 0xa62b, 1}, + {0xa640, 0xa66e, 1}, + {0xa67f, 0xa697, 1}, + {0xa6a0, 0xa6e5, 1}, + {0xa717, 0xa71f, 1}, + {0xa722, 0xa788, 1}, + {0xa78b, 0xa78e, 1}, + {0xa790, 0xa791, 1}, + {0xa7a0, 0xa7a9, 1}, + {0xa7fa, 0xa801, 1}, + {0xa803, 0xa805, 1}, + {0xa807, 0xa80a, 1}, + {0xa80c, 0xa822, 1}, + {0xa840, 0xa873, 1}, + {0xa882, 0xa8b3, 1}, + {0xa8f2, 0xa8f7, 1}, + {0xa8fb, 0xa90a, 15}, + {0xa90b, 0xa925, 1}, + {0xa930, 0xa946, 1}, + {0xa960, 0xa97c, 1}, + {0xa984, 0xa9b2, 1}, + {0xa9cf, 0xaa00, 49}, + {0xaa01, 0xaa28, 1}, + {0xaa40, 0xaa42, 1}, + {0xaa44, 0xaa4b, 1}, + {0xaa60, 0xaa76, 1}, + {0xaa7a, 0xaa80, 6}, + {0xaa81, 0xaaaf, 1}, + {0xaab1, 0xaab5, 4}, + {0xaab6, 0xaab9, 3}, + {0xaaba, 0xaabd, 1}, + {0xaac0, 0xaac2, 2}, + {0xaadb, 0xaadd, 1}, + {0xab01, 0xab06, 1}, + {0xab09, 0xab0e, 1}, + {0xab11, 0xab16, 1}, + {0xab20, 0xab26, 1}, + {0xab28, 0xab2e, 1}, + {0xabc0, 0xabe2, 1}, + {0xac00, 0xd7a3, 1}, + {0xd7b0, 0xd7c6, 1}, + {0xd7cb, 0xd7fb, 1}, + {0xf900, 0xfa2d, 1}, + {0xfa30, 0xfa6d, 1}, + {0xfa70, 0xfad9, 1}, + {0xfb00, 0xfb06, 1}, + {0xfb13, 0xfb17, 1}, + {0xfb1d, 0xfb1f, 2}, + {0xfb20, 0xfb28, 1}, + {0xfb2a, 0xfb36, 1}, + {0xfb38, 0xfb3c, 1}, + {0xfb3e, 0xfb40, 2}, + {0xfb41, 0xfb43, 2}, + {0xfb44, 0xfb46, 2}, + {0xfb47, 0xfbb1, 1}, + {0xfbd3, 0xfd3d, 1}, + {0xfd50, 0xfd8f, 1}, + {0xfd92, 0xfdc7, 1}, + {0xfdf0, 0xfdfb, 1}, + {0xfe70, 0xfe74, 1}, + {0xfe76, 0xfefc, 1}, + {0xff21, 0xff3a, 1}, + {0xff41, 0xff5a, 1}, + {0xff66, 0xffbe, 1}, + {0xffc2, 0xffc7, 1}, + {0xffca, 0xffcf, 1}, + {0xffd2, 0xffd7, 1}, + {0xffda, 0xffdc, 1}, + }, + R32: []Range32{ + {0x10000, 0x1000b, 1}, + {0x1000d, 0x10026, 1}, + {0x10028, 0x1003a, 1}, + {0x1003c, 0x1003d, 1}, + {0x1003f, 0x1004d, 1}, + {0x10050, 0x1005d, 1}, + {0x10080, 0x100fa, 1}, + {0x10280, 0x1029c, 1}, + {0x102a0, 0x102d0, 1}, + {0x10300, 0x1031e, 1}, + {0x10330, 0x10340, 1}, + {0x10342, 0x10349, 1}, + {0x10380, 0x1039d, 1}, + {0x103a0, 0x103c3, 1}, + {0x103c8, 0x103cf, 1}, + {0x10400, 0x1049d, 1}, + {0x10800, 0x10805, 1}, + {0x10808, 0x1080a, 2}, + {0x1080b, 0x10835, 1}, + {0x10837, 0x10838, 1}, + {0x1083c, 0x1083f, 3}, + {0x10840, 0x10855, 1}, + {0x10900, 0x10915, 1}, + {0x10920, 0x10939, 1}, + {0x10a00, 0x10a10, 16}, + {0x10a11, 0x10a13, 1}, + {0x10a15, 0x10a17, 1}, + {0x10a19, 0x10a33, 1}, + {0x10a60, 0x10a7c, 1}, + {0x10b00, 0x10b35, 1}, + {0x10b40, 0x10b55, 1}, + {0x10b60, 0x10b72, 1}, + {0x10c00, 0x10c48, 1}, + {0x11003, 0x11037, 1}, + {0x11083, 0x110af, 1}, + {0x12000, 0x1236e, 1}, + {0x13000, 0x1342e, 1}, + {0x16800, 0x16a38, 1}, + {0x1b000, 0x1b001, 1}, + {0x1d400, 0x1d454, 1}, + {0x1d456, 0x1d49c, 1}, + {0x1d49e, 0x1d49f, 1}, + {0x1d4a2, 0x1d4a5, 3}, + {0x1d4a6, 0x1d4a9, 3}, + {0x1d4aa, 0x1d4ac, 1}, + {0x1d4ae, 0x1d4b9, 1}, + {0x1d4bb, 0x1d4bd, 2}, + {0x1d4be, 0x1d4c3, 1}, + {0x1d4c5, 0x1d505, 1}, + {0x1d507, 0x1d50a, 1}, + {0x1d50d, 0x1d514, 1}, + {0x1d516, 0x1d51c, 1}, + {0x1d51e, 0x1d539, 1}, + {0x1d53b, 0x1d53e, 1}, + {0x1d540, 0x1d544, 1}, + {0x1d546, 0x1d54a, 4}, + {0x1d54b, 0x1d550, 1}, + {0x1d552, 0x1d6a5, 1}, + {0x1d6a8, 0x1d6c0, 1}, + {0x1d6c2, 0x1d6da, 1}, + {0x1d6dc, 0x1d6fa, 1}, + {0x1d6fc, 0x1d714, 1}, + {0x1d716, 0x1d734, 1}, + {0x1d736, 0x1d74e, 1}, + {0x1d750, 0x1d76e, 1}, + {0x1d770, 0x1d788, 1}, + {0x1d78a, 0x1d7a8, 1}, + {0x1d7aa, 0x1d7c2, 1}, + {0x1d7c4, 0x1d7cb, 1}, + {0x20000, 0x2a6d6, 1}, + {0x2a700, 0x2b734, 1}, + {0x2b740, 0x2b81d, 1}, + {0x2f800, 0x2fa1d, 1}, + }, +} + +var _Zp = &RangeTable{ + R16: []Range16{ + {0x2029, 0x2029, 1}, + }, +} + +var _Zs = &RangeTable{ + R16: []Range16{ + {0x0020, 0x00a0, 128}, + {0x1680, 0x180e, 398}, + {0x2000, 0x200a, 1}, + {0x202f, 0x205f, 48}, + {0x3000, 0x3000, 1}, + }, +} + +var _Cs = &RangeTable{ + R16: []Range16{ + {0xd800, 0xdfff, 1}, + }, +} + +var _Co = &RangeTable{ + R16: []Range16{ + {0xe000, 0xf8ff, 1}, + }, + R32: []Range32{ + {0xf0000, 0xffffd, 1}, + {0x100000, 0x10fffd, 1}, + }, +} + +var _Cf = &RangeTable{ + R16: []Range16{ + {0x00ad, 0x0600, 1363}, + {0x0601, 0x0603, 1}, + {0x06dd, 0x070f, 50}, + {0x17b4, 0x17b5, 1}, + {0x200b, 0x200f, 1}, + {0x202a, 0x202e, 1}, + {0x2060, 0x2064, 1}, + {0x206a, 0x206f, 1}, + {0xfeff, 0xfff9, 250}, + {0xfffa, 0xfffb, 1}, + }, + R32: []Range32{ + {0x110bd, 0x1d173, 49334}, + {0x1d174, 0x1d17a, 1}, + {0xe0001, 0xe0020, 31}, + {0xe0021, 0xe007f, 1}, + }, +} + +var _Cc = &RangeTable{ + R16: []Range16{ + {0x0001, 0x001f, 1}, + {0x007f, 0x009f, 1}, + }, +} + +var _Po = &RangeTable{ + R16: []Range16{ + {0x0021, 0x0023, 1}, + {0x0025, 0x0027, 1}, + {0x002a, 0x002e, 2}, + {0x002f, 0x003a, 11}, + {0x003b, 0x003f, 4}, + {0x0040, 0x005c, 28}, + {0x00a1, 0x00b7, 22}, + {0x00bf, 0x037e, 703}, + {0x0387, 0x055a, 467}, + {0x055b, 0x055f, 1}, + {0x0589, 0x05c0, 55}, + {0x05c3, 0x05c6, 3}, + {0x05f3, 0x05f4, 1}, + {0x0609, 0x060a, 1}, + {0x060c, 0x060d, 1}, + {0x061b, 0x061e, 3}, + {0x061f, 0x066a, 75}, + {0x066b, 0x066d, 1}, + {0x06d4, 0x0700, 44}, + {0x0701, 0x070d, 1}, + {0x07f7, 0x07f9, 1}, + {0x0830, 0x083e, 1}, + {0x085e, 0x0964, 262}, + {0x0965, 0x0970, 11}, + {0x0df4, 0x0e4f, 91}, + {0x0e5a, 0x0e5b, 1}, + {0x0f04, 0x0f12, 1}, + {0x0f85, 0x0fd0, 75}, + {0x0fd1, 0x0fd4, 1}, + {0x0fd9, 0x0fda, 1}, + {0x104a, 0x104f, 1}, + {0x10fb, 0x1361, 614}, + {0x1362, 0x1368, 1}, + {0x166d, 0x166e, 1}, + {0x16eb, 0x16ed, 1}, + {0x1735, 0x1736, 1}, + {0x17d4, 0x17d6, 1}, + {0x17d8, 0x17da, 1}, + {0x1800, 0x1805, 1}, + {0x1807, 0x180a, 1}, + {0x1944, 0x1945, 1}, + {0x1a1e, 0x1a1f, 1}, + {0x1aa0, 0x1aa6, 1}, + {0x1aa8, 0x1aad, 1}, + {0x1b5a, 0x1b60, 1}, + {0x1bfc, 0x1bff, 1}, + {0x1c3b, 0x1c3f, 1}, + {0x1c7e, 0x1c7f, 1}, + {0x1cd3, 0x2016, 835}, + {0x2017, 0x2020, 9}, + {0x2021, 0x2027, 1}, + {0x2030, 0x2038, 1}, + {0x203b, 0x203e, 1}, + {0x2041, 0x2043, 1}, + {0x2047, 0x2051, 1}, + {0x2053, 0x2055, 2}, + {0x2056, 0x205e, 1}, + {0x2cf9, 0x2cfc, 1}, + {0x2cfe, 0x2cff, 1}, + {0x2d70, 0x2e00, 144}, + {0x2e01, 0x2e06, 5}, + {0x2e07, 0x2e08, 1}, + {0x2e0b, 0x2e0e, 3}, + {0x2e0f, 0x2e16, 1}, + {0x2e18, 0x2e19, 1}, + {0x2e1b, 0x2e1e, 3}, + {0x2e1f, 0x2e2a, 11}, + {0x2e2b, 0x2e2e, 1}, + {0x2e30, 0x2e31, 1}, + {0x3001, 0x3003, 1}, + {0x303d, 0x30fb, 190}, + {0xa4fe, 0xa4ff, 1}, + {0xa60d, 0xa60f, 1}, + {0xa673, 0xa67e, 11}, + {0xa6f2, 0xa6f7, 1}, + {0xa874, 0xa877, 1}, + {0xa8ce, 0xa8cf, 1}, + {0xa8f8, 0xa8fa, 1}, + {0xa92e, 0xa92f, 1}, + {0xa95f, 0xa9c1, 98}, + {0xa9c2, 0xa9cd, 1}, + {0xa9de, 0xa9df, 1}, + {0xaa5c, 0xaa5f, 1}, + {0xaade, 0xaadf, 1}, + {0xabeb, 0xfe10, 21029}, + {0xfe11, 0xfe16, 1}, + {0xfe19, 0xfe30, 23}, + {0xfe45, 0xfe46, 1}, + {0xfe49, 0xfe4c, 1}, + {0xfe50, 0xfe52, 1}, + {0xfe54, 0xfe57, 1}, + {0xfe5f, 0xfe61, 1}, + {0xfe68, 0xfe6a, 2}, + {0xfe6b, 0xff01, 150}, + {0xff02, 0xff03, 1}, + {0xff05, 0xff07, 1}, + {0xff0a, 0xff0e, 2}, + {0xff0f, 0xff1a, 11}, + {0xff1b, 0xff1f, 4}, + {0xff20, 0xff3c, 28}, + {0xff61, 0xff64, 3}, + {0xff65, 0xff65, 1}, + }, + R32: []Range32{ + {0x10100, 0x10100, 1}, + {0x10101, 0x1039f, 670}, + {0x103d0, 0x10857, 1159}, + {0x1091f, 0x1093f, 32}, + {0x10a50, 0x10a58, 1}, + {0x10a7f, 0x10b39, 186}, + {0x10b3a, 0x10b3f, 1}, + {0x11047, 0x1104d, 1}, + {0x110bb, 0x110bc, 1}, + {0x110be, 0x110c1, 1}, + {0x12470, 0x12473, 1}, + }, +} + +var _Pi = &RangeTable{ + R16: []Range16{ + {0x00ab, 0x2018, 8045}, + {0x201b, 0x201c, 1}, + {0x201f, 0x2039, 26}, + {0x2e02, 0x2e04, 2}, + {0x2e09, 0x2e0c, 3}, + {0x2e1c, 0x2e20, 4}, + }, +} + +var _Pf = &RangeTable{ + R16: []Range16{ + {0x00bb, 0x2019, 8030}, + {0x201d, 0x203a, 29}, + {0x2e03, 0x2e05, 2}, + {0x2e0a, 0x2e0d, 3}, + {0x2e1d, 0x2e21, 4}, + }, +} + +var _Pe = &RangeTable{ + R16: []Range16{ + {0x0029, 0x005d, 52}, + {0x007d, 0x0f3b, 3774}, + {0x0f3d, 0x169c, 1887}, + {0x2046, 0x207e, 56}, + {0x208e, 0x232a, 668}, + {0x2769, 0x2775, 2}, + {0x27c6, 0x27e7, 33}, + {0x27e9, 0x27ef, 2}, + {0x2984, 0x2998, 2}, + {0x29d9, 0x29db, 2}, + {0x29fd, 0x2e23, 1062}, + {0x2e25, 0x2e29, 2}, + {0x3009, 0x3011, 2}, + {0x3015, 0x301b, 2}, + {0x301e, 0x301f, 1}, + {0xfd3f, 0xfe18, 217}, + {0xfe36, 0xfe44, 2}, + {0xfe48, 0xfe5a, 18}, + {0xfe5c, 0xfe5e, 2}, + {0xff09, 0xff3d, 52}, + {0xff5d, 0xff63, 3}, + }, +} + +var _Pd = &RangeTable{ + R16: []Range16{ + {0x002d, 0x058a, 1373}, + {0x05be, 0x1400, 3650}, + {0x1806, 0x2010, 2058}, + {0x2011, 0x2015, 1}, + {0x2e17, 0x2e1a, 3}, + {0x301c, 0x3030, 20}, + {0x30a0, 0xfe31, 52625}, + {0xfe32, 0xfe58, 38}, + {0xfe63, 0xff0d, 170}, + }, +} + +var _Pc = &RangeTable{ + R16: []Range16{ + {0x005f, 0x203f, 8160}, + {0x2040, 0x2054, 20}, + {0xfe33, 0xfe34, 1}, + {0xfe4d, 0xfe4f, 1}, + {0xff3f, 0xff3f, 1}, + }, +} + +var _Ps = &RangeTable{ + R16: []Range16{ + {0x0028, 0x005b, 51}, + {0x007b, 0x0f3a, 3775}, + {0x0f3c, 0x169b, 1887}, + {0x201a, 0x201e, 4}, + {0x2045, 0x207d, 56}, + {0x208d, 0x2329, 668}, + {0x2768, 0x2774, 2}, + {0x27c5, 0x27e6, 33}, + {0x27e8, 0x27ee, 2}, + {0x2983, 0x2997, 2}, + {0x29d8, 0x29da, 2}, + {0x29fc, 0x2e22, 1062}, + {0x2e24, 0x2e28, 2}, + {0x3008, 0x3010, 2}, + {0x3014, 0x301a, 2}, + {0x301d, 0xfd3e, 52513}, + {0xfe17, 0xfe35, 30}, + {0xfe37, 0xfe43, 2}, + {0xfe47, 0xfe59, 18}, + {0xfe5b, 0xfe5d, 2}, + {0xff08, 0xff3b, 51}, + {0xff5b, 0xff5f, 4}, + {0xff62, 0xff62, 1}, + }, +} + +var _Nd = &RangeTable{ + R16: []Range16{ + {0x0030, 0x0039, 1}, + {0x0660, 0x0669, 1}, + {0x06f0, 0x06f9, 1}, + {0x07c0, 0x07c9, 1}, + {0x0966, 0x096f, 1}, + {0x09e6, 0x09ef, 1}, + {0x0a66, 0x0a6f, 1}, + {0x0ae6, 0x0aef, 1}, + {0x0b66, 0x0b6f, 1}, + {0x0be6, 0x0bef, 1}, + {0x0c66, 0x0c6f, 1}, + {0x0ce6, 0x0cef, 1}, + {0x0d66, 0x0d6f, 1}, + {0x0e50, 0x0e59, 1}, + {0x0ed0, 0x0ed9, 1}, + {0x0f20, 0x0f29, 1}, + {0x1040, 0x1049, 1}, + {0x1090, 0x1099, 1}, + {0x17e0, 0x17e9, 1}, + {0x1810, 0x1819, 1}, + {0x1946, 0x194f, 1}, + {0x19d0, 0x19d9, 1}, + {0x1a80, 0x1a89, 1}, + {0x1a90, 0x1a99, 1}, + {0x1b50, 0x1b59, 1}, + {0x1bb0, 0x1bb9, 1}, + {0x1c40, 0x1c49, 1}, + {0x1c50, 0x1c59, 1}, + {0xa620, 0xa629, 1}, + {0xa8d0, 0xa8d9, 1}, + {0xa900, 0xa909, 1}, + {0xa9d0, 0xa9d9, 1}, + {0xaa50, 0xaa59, 1}, + {0xabf0, 0xabf9, 1}, + {0xff10, 0xff19, 1}, + }, + R32: []Range32{ + {0x104a0, 0x104a9, 1}, + {0x11066, 0x1106f, 1}, + {0x1d7ce, 0x1d7ff, 1}, + }, +} + +var _Nl = &RangeTable{ + R16: []Range16{ + {0x16ee, 0x16f0, 1}, + {0x2160, 0x2182, 1}, + {0x2185, 0x2188, 1}, + {0x3007, 0x3021, 26}, + {0x3022, 0x3029, 1}, + {0x3038, 0x303a, 1}, + {0xa6e6, 0xa6ef, 1}, + }, + R32: []Range32{ + {0x10140, 0x10174, 1}, + {0x10341, 0x1034a, 9}, + {0x103d1, 0x103d5, 1}, + {0x12400, 0x12462, 1}, + }, +} + +var _No = &RangeTable{ + R16: []Range16{ + {0x00b2, 0x00b3, 1}, + {0x00b9, 0x00bc, 3}, + {0x00bd, 0x00be, 1}, + {0x09f4, 0x09f9, 1}, + {0x0b72, 0x0b77, 1}, + {0x0bf0, 0x0bf2, 1}, + {0x0c78, 0x0c7e, 1}, + {0x0d70, 0x0d75, 1}, + {0x0f2a, 0x0f33, 1}, + {0x1369, 0x137c, 1}, + {0x17f0, 0x17f9, 1}, + {0x19da, 0x2070, 1686}, + {0x2074, 0x2079, 1}, + {0x2080, 0x2089, 1}, + {0x2150, 0x215f, 1}, + {0x2189, 0x2460, 727}, + {0x2461, 0x249b, 1}, + {0x24ea, 0x24ff, 1}, + {0x2776, 0x2793, 1}, + {0x2cfd, 0x3192, 1173}, + {0x3193, 0x3195, 1}, + {0x3220, 0x3229, 1}, + {0x3251, 0x325f, 1}, + {0x3280, 0x3289, 1}, + {0x32b1, 0x32bf, 1}, + {0xa830, 0xa835, 1}, + }, + R32: []Range32{ + {0x10107, 0x10133, 1}, + {0x10175, 0x10178, 1}, + {0x1018a, 0x10320, 406}, + {0x10321, 0x10323, 1}, + {0x10858, 0x1085f, 1}, + {0x10916, 0x1091b, 1}, + {0x10a40, 0x10a47, 1}, + {0x10a7d, 0x10a7e, 1}, + {0x10b58, 0x10b5f, 1}, + {0x10b78, 0x10b7f, 1}, + {0x10e60, 0x10e7e, 1}, + {0x11052, 0x11065, 1}, + {0x1d360, 0x1d371, 1}, + {0x1f100, 0x1f10a, 1}, + }, +} + +var _So = &RangeTable{ + R16: []Range16{ + {0x00a6, 0x00a7, 1}, + {0x00a9, 0x00ae, 5}, + {0x00b0, 0x00b6, 6}, + {0x0482, 0x060e, 396}, + {0x060f, 0x06de, 207}, + {0x06e9, 0x06fd, 20}, + {0x06fe, 0x07f6, 248}, + {0x09fa, 0x0b70, 374}, + {0x0bf3, 0x0bf8, 1}, + {0x0bfa, 0x0c7f, 133}, + {0x0d79, 0x0f01, 392}, + {0x0f02, 0x0f03, 1}, + {0x0f13, 0x0f17, 1}, + {0x0f1a, 0x0f1f, 1}, + {0x0f34, 0x0f38, 2}, + {0x0fbe, 0x0fc5, 1}, + {0x0fc7, 0x0fcc, 1}, + {0x0fce, 0x0fcf, 1}, + {0x0fd5, 0x0fd8, 1}, + {0x109e, 0x109f, 1}, + {0x1360, 0x1390, 48}, + {0x1391, 0x1399, 1}, + {0x1940, 0x19de, 158}, + {0x19df, 0x19ff, 1}, + {0x1b61, 0x1b6a, 1}, + {0x1b74, 0x1b7c, 1}, + {0x2100, 0x2101, 1}, + {0x2103, 0x2106, 1}, + {0x2108, 0x2109, 1}, + {0x2114, 0x2116, 2}, + {0x2117, 0x211e, 7}, + {0x211f, 0x2123, 1}, + {0x2125, 0x2129, 2}, + {0x212e, 0x213a, 12}, + {0x213b, 0x214a, 15}, + {0x214c, 0x214d, 1}, + {0x214f, 0x2195, 70}, + {0x2196, 0x2199, 1}, + {0x219c, 0x219f, 1}, + {0x21a1, 0x21a2, 1}, + {0x21a4, 0x21a5, 1}, + {0x21a7, 0x21ad, 1}, + {0x21af, 0x21cd, 1}, + {0x21d0, 0x21d1, 1}, + {0x21d3, 0x21d5, 2}, + {0x21d6, 0x21f3, 1}, + {0x2300, 0x2307, 1}, + {0x230c, 0x231f, 1}, + {0x2322, 0x2328, 1}, + {0x232b, 0x237b, 1}, + {0x237d, 0x239a, 1}, + {0x23b4, 0x23db, 1}, + {0x23e2, 0x23f3, 1}, + {0x2400, 0x2426, 1}, + {0x2440, 0x244a, 1}, + {0x249c, 0x24e9, 1}, + {0x2500, 0x25b6, 1}, + {0x25b8, 0x25c0, 1}, + {0x25c2, 0x25f7, 1}, + {0x2600, 0x266e, 1}, + {0x2670, 0x26ff, 1}, + {0x2701, 0x2767, 1}, + {0x2794, 0x27bf, 1}, + {0x2800, 0x28ff, 1}, + {0x2b00, 0x2b2f, 1}, + {0x2b45, 0x2b46, 1}, + {0x2b50, 0x2b59, 1}, + {0x2ce5, 0x2cea, 1}, + {0x2e80, 0x2e99, 1}, + {0x2e9b, 0x2ef3, 1}, + {0x2f00, 0x2fd5, 1}, + {0x2ff0, 0x2ffb, 1}, + {0x3004, 0x3012, 14}, + {0x3013, 0x3020, 13}, + {0x3036, 0x3037, 1}, + {0x303e, 0x303f, 1}, + {0x3190, 0x3191, 1}, + {0x3196, 0x319f, 1}, + {0x31c0, 0x31e3, 1}, + {0x3200, 0x321e, 1}, + {0x322a, 0x3250, 1}, + {0x3260, 0x327f, 1}, + {0x328a, 0x32b0, 1}, + {0x32c0, 0x32fe, 1}, + {0x3300, 0x33ff, 1}, + {0x4dc0, 0x4dff, 1}, + {0xa490, 0xa4c6, 1}, + {0xa828, 0xa82b, 1}, + {0xa836, 0xa837, 1}, + {0xa839, 0xaa77, 574}, + {0xaa78, 0xaa79, 1}, + {0xfdfd, 0xffe4, 487}, + {0xffe8, 0xffed, 5}, + {0xffee, 0xfffc, 14}, + {0xfffd, 0xfffd, 1}, + }, + R32: []Range32{ + {0x10102, 0x10102, 1}, + {0x10137, 0x1013f, 1}, + {0x10179, 0x10189, 1}, + {0x10190, 0x1019b, 1}, + {0x101d0, 0x101fc, 1}, + {0x1d000, 0x1d0f5, 1}, + {0x1d100, 0x1d126, 1}, + {0x1d129, 0x1d164, 1}, + {0x1d16a, 0x1d16c, 1}, + {0x1d183, 0x1d184, 1}, + {0x1d18c, 0x1d1a9, 1}, + {0x1d1ae, 0x1d1dd, 1}, + {0x1d200, 0x1d241, 1}, + {0x1d245, 0x1d300, 187}, + {0x1d301, 0x1d356, 1}, + {0x1f000, 0x1f02b, 1}, + {0x1f030, 0x1f093, 1}, + {0x1f0a0, 0x1f0ae, 1}, + {0x1f0b1, 0x1f0be, 1}, + {0x1f0c1, 0x1f0cf, 1}, + {0x1f0d1, 0x1f0df, 1}, + {0x1f110, 0x1f12e, 1}, + {0x1f130, 0x1f169, 1}, + {0x1f170, 0x1f19a, 1}, + {0x1f1e6, 0x1f202, 1}, + {0x1f210, 0x1f23a, 1}, + {0x1f240, 0x1f248, 1}, + {0x1f250, 0x1f251, 1}, + {0x1f300, 0x1f320, 1}, + {0x1f330, 0x1f335, 1}, + {0x1f337, 0x1f37c, 1}, + {0x1f380, 0x1f393, 1}, + {0x1f3a0, 0x1f3c4, 1}, + {0x1f3c6, 0x1f3ca, 1}, + {0x1f3e0, 0x1f3f0, 1}, + {0x1f400, 0x1f43e, 1}, + {0x1f440, 0x1f442, 2}, + {0x1f443, 0x1f4f7, 1}, + {0x1f4f9, 0x1f4fc, 1}, + {0x1f500, 0x1f53d, 1}, + {0x1f550, 0x1f567, 1}, + {0x1f5fb, 0x1f5ff, 1}, + {0x1f601, 0x1f610, 1}, + {0x1f612, 0x1f614, 1}, + {0x1f616, 0x1f61c, 2}, + {0x1f61d, 0x1f61e, 1}, + {0x1f620, 0x1f625, 1}, + {0x1f628, 0x1f62b, 1}, + {0x1f62d, 0x1f630, 3}, + {0x1f631, 0x1f633, 1}, + {0x1f635, 0x1f640, 1}, + {0x1f645, 0x1f64f, 1}, + {0x1f680, 0x1f6c5, 1}, + {0x1f700, 0x1f773, 1}, + }, +} + +var _Sm = &RangeTable{ + R16: []Range16{ + {0x002b, 0x003c, 17}, + {0x003d, 0x003e, 1}, + {0x007c, 0x007e, 2}, + {0x00ac, 0x00b1, 5}, + {0x00d7, 0x00f7, 32}, + {0x03f6, 0x0606, 528}, + {0x0607, 0x0608, 1}, + {0x2044, 0x2052, 14}, + {0x207a, 0x207c, 1}, + {0x208a, 0x208c, 1}, + {0x2118, 0x2140, 40}, + {0x2141, 0x2144, 1}, + {0x214b, 0x2190, 69}, + {0x2191, 0x2194, 1}, + {0x219a, 0x219b, 1}, + {0x21a0, 0x21a6, 3}, + {0x21ae, 0x21ce, 32}, + {0x21cf, 0x21d2, 3}, + {0x21d4, 0x21f4, 32}, + {0x21f5, 0x22ff, 1}, + {0x2308, 0x230b, 1}, + {0x2320, 0x2321, 1}, + {0x237c, 0x239b, 31}, + {0x239c, 0x23b3, 1}, + {0x23dc, 0x23e1, 1}, + {0x25b7, 0x25c1, 10}, + {0x25f8, 0x25ff, 1}, + {0x266f, 0x27c0, 337}, + {0x27c1, 0x27c4, 1}, + {0x27c7, 0x27ca, 1}, + {0x27cc, 0x27ce, 2}, + {0x27cf, 0x27e5, 1}, + {0x27f0, 0x27ff, 1}, + {0x2900, 0x2982, 1}, + {0x2999, 0x29d7, 1}, + {0x29dc, 0x29fb, 1}, + {0x29fe, 0x2aff, 1}, + {0x2b30, 0x2b44, 1}, + {0x2b47, 0x2b4c, 1}, + {0xfb29, 0xfe62, 825}, + {0xfe64, 0xfe66, 1}, + {0xff0b, 0xff1c, 17}, + {0xff1d, 0xff1e, 1}, + {0xff5c, 0xff5e, 2}, + {0xffe2, 0xffe9, 7}, + {0xffea, 0xffec, 1}, + }, + R32: []Range32{ + {0x1d6c1, 0x1d6db, 26}, + {0x1d6fb, 0x1d715, 26}, + {0x1d735, 0x1d74f, 26}, + {0x1d76f, 0x1d789, 26}, + {0x1d7a9, 0x1d7c3, 26}, + }, +} + +var _Sk = &RangeTable{ + R16: []Range16{ + {0x005e, 0x0060, 2}, + {0x00a8, 0x00af, 7}, + {0x00b4, 0x00b8, 4}, + {0x02c2, 0x02c5, 1}, + {0x02d2, 0x02df, 1}, + {0x02e5, 0x02eb, 1}, + {0x02ed, 0x02ef, 2}, + {0x02f0, 0x02ff, 1}, + {0x0375, 0x0384, 15}, + {0x0385, 0x1fbd, 7224}, + {0x1fbf, 0x1fc1, 1}, + {0x1fcd, 0x1fcf, 1}, + {0x1fdd, 0x1fdf, 1}, + {0x1fed, 0x1fef, 1}, + {0x1ffd, 0x1ffe, 1}, + {0x309b, 0x309c, 1}, + {0xa700, 0xa716, 1}, + {0xa720, 0xa721, 1}, + {0xa789, 0xa78a, 1}, + {0xfbb2, 0xfbc1, 1}, + {0xff3e, 0xff40, 2}, + {0xffe3, 0xffe3, 1}, + }, +} + +var _Sc = &RangeTable{ + R16: []Range16{ + {0x0024, 0x00a2, 126}, + {0x00a3, 0x00a5, 1}, + {0x060b, 0x09f2, 999}, + {0x09f3, 0x09fb, 8}, + {0x0af1, 0x0bf9, 264}, + {0x0e3f, 0x17db, 2460}, + {0x20a0, 0x20b9, 1}, + {0xa838, 0xfdfc, 21956}, + {0xfe69, 0xff04, 155}, + {0xffe0, 0xffe1, 1}, + {0xffe5, 0xffe6, 1}, + }, +} + +var _Lu = &RangeTable{ + R16: []Range16{ + {0x0041, 0x005a, 1}, + {0x00c0, 0x00d6, 1}, + {0x00d8, 0x00de, 1}, + {0x0100, 0x0136, 2}, + {0x0139, 0x0147, 2}, + {0x014a, 0x0178, 2}, + {0x0179, 0x017d, 2}, + {0x0181, 0x0182, 1}, + {0x0184, 0x0186, 2}, + {0x0187, 0x0189, 2}, + {0x018a, 0x018b, 1}, + {0x018e, 0x0191, 1}, + {0x0193, 0x0194, 1}, + {0x0196, 0x0198, 1}, + {0x019c, 0x019d, 1}, + {0x019f, 0x01a0, 1}, + {0x01a2, 0x01a6, 2}, + {0x01a7, 0x01a9, 2}, + {0x01ac, 0x01ae, 2}, + {0x01af, 0x01b1, 2}, + {0x01b2, 0x01b3, 1}, + {0x01b5, 0x01b7, 2}, + {0x01b8, 0x01bc, 4}, + {0x01c4, 0x01cd, 3}, + {0x01cf, 0x01db, 2}, + {0x01de, 0x01ee, 2}, + {0x01f1, 0x01f4, 3}, + {0x01f6, 0x01f8, 1}, + {0x01fa, 0x0232, 2}, + {0x023a, 0x023b, 1}, + {0x023d, 0x023e, 1}, + {0x0241, 0x0243, 2}, + {0x0244, 0x0246, 1}, + {0x0248, 0x024e, 2}, + {0x0370, 0x0372, 2}, + {0x0376, 0x0386, 16}, + {0x0388, 0x038a, 1}, + {0x038c, 0x038e, 2}, + {0x038f, 0x0391, 2}, + {0x0392, 0x03a1, 1}, + {0x03a3, 0x03ab, 1}, + {0x03cf, 0x03d2, 3}, + {0x03d3, 0x03d4, 1}, + {0x03d8, 0x03ee, 2}, + {0x03f4, 0x03f7, 3}, + {0x03f9, 0x03fa, 1}, + {0x03fd, 0x042f, 1}, + {0x0460, 0x0480, 2}, + {0x048a, 0x04c0, 2}, + {0x04c1, 0x04cd, 2}, + {0x04d0, 0x0526, 2}, + {0x0531, 0x0556, 1}, + {0x10a0, 0x10c5, 1}, + {0x1e00, 0x1e94, 2}, + {0x1e9e, 0x1efe, 2}, + {0x1f08, 0x1f0f, 1}, + {0x1f18, 0x1f1d, 1}, + {0x1f28, 0x1f2f, 1}, + {0x1f38, 0x1f3f, 1}, + {0x1f48, 0x1f4d, 1}, + {0x1f59, 0x1f5f, 2}, + {0x1f68, 0x1f6f, 1}, + {0x1fb8, 0x1fbb, 1}, + {0x1fc8, 0x1fcb, 1}, + {0x1fd8, 0x1fdb, 1}, + {0x1fe8, 0x1fec, 1}, + {0x1ff8, 0x1ffb, 1}, + {0x2102, 0x2107, 5}, + {0x210b, 0x210d, 1}, + {0x2110, 0x2112, 1}, + {0x2115, 0x2119, 4}, + {0x211a, 0x211d, 1}, + {0x2124, 0x212a, 2}, + {0x212b, 0x212d, 1}, + {0x2130, 0x2133, 1}, + {0x213e, 0x213f, 1}, + {0x2145, 0x2183, 62}, + {0x2c00, 0x2c2e, 1}, + {0x2c60, 0x2c62, 2}, + {0x2c63, 0x2c64, 1}, + {0x2c67, 0x2c6d, 2}, + {0x2c6e, 0x2c70, 1}, + {0x2c72, 0x2c75, 3}, + {0x2c7e, 0x2c80, 1}, + {0x2c82, 0x2ce2, 2}, + {0x2ceb, 0x2ced, 2}, + {0xa640, 0xa66c, 2}, + {0xa680, 0xa696, 2}, + {0xa722, 0xa72e, 2}, + {0xa732, 0xa76e, 2}, + {0xa779, 0xa77d, 2}, + {0xa77e, 0xa786, 2}, + {0xa78b, 0xa78d, 2}, + {0xa790, 0xa7a0, 16}, + {0xa7a2, 0xa7a8, 2}, + {0xff21, 0xff3a, 1}, + }, + R32: []Range32{ + {0x10400, 0x10427, 1}, + {0x1d400, 0x1d419, 1}, + {0x1d434, 0x1d44d, 1}, + {0x1d468, 0x1d481, 1}, + {0x1d49c, 0x1d49e, 2}, + {0x1d49f, 0x1d4a5, 3}, + {0x1d4a6, 0x1d4a9, 3}, + {0x1d4aa, 0x1d4ac, 1}, + {0x1d4ae, 0x1d4b5, 1}, + {0x1d4d0, 0x1d4e9, 1}, + {0x1d504, 0x1d505, 1}, + {0x1d507, 0x1d50a, 1}, + {0x1d50d, 0x1d514, 1}, + {0x1d516, 0x1d51c, 1}, + {0x1d538, 0x1d539, 1}, + {0x1d53b, 0x1d53e, 1}, + {0x1d540, 0x1d544, 1}, + {0x1d546, 0x1d54a, 4}, + {0x1d54b, 0x1d550, 1}, + {0x1d56c, 0x1d585, 1}, + {0x1d5a0, 0x1d5b9, 1}, + {0x1d5d4, 0x1d5ed, 1}, + {0x1d608, 0x1d621, 1}, + {0x1d63c, 0x1d655, 1}, + {0x1d670, 0x1d689, 1}, + {0x1d6a8, 0x1d6c0, 1}, + {0x1d6e2, 0x1d6fa, 1}, + {0x1d71c, 0x1d734, 1}, + {0x1d756, 0x1d76e, 1}, + {0x1d790, 0x1d7a8, 1}, + {0x1d7ca, 0x1d7ca, 1}, + }, +} + +var _Lt = &RangeTable{ + R16: []Range16{ + {0x01c5, 0x01cb, 3}, + {0x01f2, 0x1f88, 7574}, + {0x1f89, 0x1f8f, 1}, + {0x1f98, 0x1f9f, 1}, + {0x1fa8, 0x1faf, 1}, + {0x1fbc, 0x1fcc, 16}, + {0x1ffc, 0x1ffc, 1}, + }, +} + +var _Lo = &RangeTable{ + R16: []Range16{ + {0x01bb, 0x01c0, 5}, + {0x01c1, 0x01c3, 1}, + {0x0294, 0x05d0, 828}, + {0x05d1, 0x05ea, 1}, + {0x05f0, 0x05f2, 1}, + {0x0620, 0x063f, 1}, + {0x0641, 0x064a, 1}, + {0x066e, 0x066f, 1}, + {0x0671, 0x06d3, 1}, + {0x06d5, 0x06ee, 25}, + {0x06ef, 0x06fa, 11}, + {0x06fb, 0x06fc, 1}, + {0x06ff, 0x0710, 17}, + {0x0712, 0x072f, 1}, + {0x074d, 0x07a5, 1}, + {0x07b1, 0x07ca, 25}, + {0x07cb, 0x07ea, 1}, + {0x0800, 0x0815, 1}, + {0x0840, 0x0858, 1}, + {0x0904, 0x0939, 1}, + {0x093d, 0x0950, 19}, + {0x0958, 0x0961, 1}, + {0x0972, 0x0977, 1}, + {0x0979, 0x097f, 1}, + {0x0985, 0x098c, 1}, + {0x098f, 0x0990, 1}, + {0x0993, 0x09a8, 1}, + {0x09aa, 0x09b0, 1}, + {0x09b2, 0x09b6, 4}, + {0x09b7, 0x09b9, 1}, + {0x09bd, 0x09ce, 17}, + {0x09dc, 0x09dd, 1}, + {0x09df, 0x09e1, 1}, + {0x09f0, 0x09f1, 1}, + {0x0a05, 0x0a0a, 1}, + {0x0a0f, 0x0a10, 1}, + {0x0a13, 0x0a28, 1}, + {0x0a2a, 0x0a30, 1}, + {0x0a32, 0x0a33, 1}, + {0x0a35, 0x0a36, 1}, + {0x0a38, 0x0a39, 1}, + {0x0a59, 0x0a5c, 1}, + {0x0a5e, 0x0a72, 20}, + {0x0a73, 0x0a74, 1}, + {0x0a85, 0x0a8d, 1}, + {0x0a8f, 0x0a91, 1}, + {0x0a93, 0x0aa8, 1}, + {0x0aaa, 0x0ab0, 1}, + {0x0ab2, 0x0ab3, 1}, + {0x0ab5, 0x0ab9, 1}, + {0x0abd, 0x0ad0, 19}, + {0x0ae0, 0x0ae1, 1}, + {0x0b05, 0x0b0c, 1}, + {0x0b0f, 0x0b10, 1}, + {0x0b13, 0x0b28, 1}, + {0x0b2a, 0x0b30, 1}, + {0x0b32, 0x0b33, 1}, + {0x0b35, 0x0b39, 1}, + {0x0b3d, 0x0b5c, 31}, + {0x0b5d, 0x0b5f, 2}, + {0x0b60, 0x0b61, 1}, + {0x0b71, 0x0b83, 18}, + {0x0b85, 0x0b8a, 1}, + {0x0b8e, 0x0b90, 1}, + {0x0b92, 0x0b95, 1}, + {0x0b99, 0x0b9a, 1}, + {0x0b9c, 0x0b9e, 2}, + {0x0b9f, 0x0ba3, 4}, + {0x0ba4, 0x0ba8, 4}, + {0x0ba9, 0x0baa, 1}, + {0x0bae, 0x0bb9, 1}, + {0x0bd0, 0x0c05, 53}, + {0x0c06, 0x0c0c, 1}, + {0x0c0e, 0x0c10, 1}, + {0x0c12, 0x0c28, 1}, + {0x0c2a, 0x0c33, 1}, + {0x0c35, 0x0c39, 1}, + {0x0c3d, 0x0c58, 27}, + {0x0c59, 0x0c60, 7}, + {0x0c61, 0x0c85, 36}, + {0x0c86, 0x0c8c, 1}, + {0x0c8e, 0x0c90, 1}, + {0x0c92, 0x0ca8, 1}, + {0x0caa, 0x0cb3, 1}, + {0x0cb5, 0x0cb9, 1}, + {0x0cbd, 0x0cde, 33}, + {0x0ce0, 0x0ce1, 1}, + {0x0cf1, 0x0cf2, 1}, + {0x0d05, 0x0d0c, 1}, + {0x0d0e, 0x0d10, 1}, + {0x0d12, 0x0d3a, 1}, + {0x0d3d, 0x0d4e, 17}, + {0x0d60, 0x0d61, 1}, + {0x0d7a, 0x0d7f, 1}, + {0x0d85, 0x0d96, 1}, + {0x0d9a, 0x0db1, 1}, + {0x0db3, 0x0dbb, 1}, + {0x0dbd, 0x0dc0, 3}, + {0x0dc1, 0x0dc6, 1}, + {0x0e01, 0x0e30, 1}, + {0x0e32, 0x0e33, 1}, + {0x0e40, 0x0e45, 1}, + {0x0e81, 0x0e82, 1}, + {0x0e84, 0x0e87, 3}, + {0x0e88, 0x0e8a, 2}, + {0x0e8d, 0x0e94, 7}, + {0x0e95, 0x0e97, 1}, + {0x0e99, 0x0e9f, 1}, + {0x0ea1, 0x0ea3, 1}, + {0x0ea5, 0x0ea7, 2}, + {0x0eaa, 0x0eab, 1}, + {0x0ead, 0x0eb0, 1}, + {0x0eb2, 0x0eb3, 1}, + {0x0ebd, 0x0ec0, 3}, + {0x0ec1, 0x0ec4, 1}, + {0x0edc, 0x0edd, 1}, + {0x0f00, 0x0f40, 64}, + {0x0f41, 0x0f47, 1}, + {0x0f49, 0x0f6c, 1}, + {0x0f88, 0x0f8c, 1}, + {0x1000, 0x102a, 1}, + {0x103f, 0x1050, 17}, + {0x1051, 0x1055, 1}, + {0x105a, 0x105d, 1}, + {0x1061, 0x1065, 4}, + {0x1066, 0x106e, 8}, + {0x106f, 0x1070, 1}, + {0x1075, 0x1081, 1}, + {0x108e, 0x10d0, 66}, + {0x10d1, 0x10fa, 1}, + {0x1100, 0x1248, 1}, + {0x124a, 0x124d, 1}, + {0x1250, 0x1256, 1}, + {0x1258, 0x125a, 2}, + {0x125b, 0x125d, 1}, + {0x1260, 0x1288, 1}, + {0x128a, 0x128d, 1}, + {0x1290, 0x12b0, 1}, + {0x12b2, 0x12b5, 1}, + {0x12b8, 0x12be, 1}, + {0x12c0, 0x12c2, 2}, + {0x12c3, 0x12c5, 1}, + {0x12c8, 0x12d6, 1}, + {0x12d8, 0x1310, 1}, + {0x1312, 0x1315, 1}, + {0x1318, 0x135a, 1}, + {0x1380, 0x138f, 1}, + {0x13a0, 0x13f4, 1}, + {0x1401, 0x166c, 1}, + {0x166f, 0x167f, 1}, + {0x1681, 0x169a, 1}, + {0x16a0, 0x16ea, 1}, + {0x1700, 0x170c, 1}, + {0x170e, 0x1711, 1}, + {0x1720, 0x1731, 1}, + {0x1740, 0x1751, 1}, + {0x1760, 0x176c, 1}, + {0x176e, 0x1770, 1}, + {0x1780, 0x17b3, 1}, + {0x17dc, 0x1820, 68}, + {0x1821, 0x1842, 1}, + {0x1844, 0x1877, 1}, + {0x1880, 0x18a8, 1}, + {0x18aa, 0x18b0, 6}, + {0x18b1, 0x18f5, 1}, + {0x1900, 0x191c, 1}, + {0x1950, 0x196d, 1}, + {0x1970, 0x1974, 1}, + {0x1980, 0x19ab, 1}, + {0x19c1, 0x19c7, 1}, + {0x1a00, 0x1a16, 1}, + {0x1a20, 0x1a54, 1}, + {0x1b05, 0x1b33, 1}, + {0x1b45, 0x1b4b, 1}, + {0x1b83, 0x1ba0, 1}, + {0x1bae, 0x1baf, 1}, + {0x1bc0, 0x1be5, 1}, + {0x1c00, 0x1c23, 1}, + {0x1c4d, 0x1c4f, 1}, + {0x1c5a, 0x1c77, 1}, + {0x1ce9, 0x1cec, 1}, + {0x1cee, 0x1cf1, 1}, + {0x2135, 0x2138, 1}, + {0x2d30, 0x2d65, 1}, + {0x2d80, 0x2d96, 1}, + {0x2da0, 0x2da6, 1}, + {0x2da8, 0x2dae, 1}, + {0x2db0, 0x2db6, 1}, + {0x2db8, 0x2dbe, 1}, + {0x2dc0, 0x2dc6, 1}, + {0x2dc8, 0x2dce, 1}, + {0x2dd0, 0x2dd6, 1}, + {0x2dd8, 0x2dde, 1}, + {0x3006, 0x303c, 54}, + {0x3041, 0x3096, 1}, + {0x309f, 0x30a1, 2}, + {0x30a2, 0x30fa, 1}, + {0x30ff, 0x3105, 6}, + {0x3106, 0x312d, 1}, + {0x3131, 0x318e, 1}, + {0x31a0, 0x31ba, 1}, + {0x31f0, 0x31ff, 1}, + {0x3400, 0x4db5, 1}, + {0x4e00, 0x9fcb, 1}, + {0xa000, 0xa014, 1}, + {0xa016, 0xa48c, 1}, + {0xa4d0, 0xa4f7, 1}, + {0xa500, 0xa60b, 1}, + {0xa610, 0xa61f, 1}, + {0xa62a, 0xa62b, 1}, + {0xa66e, 0xa6a0, 50}, + {0xa6a1, 0xa6e5, 1}, + {0xa7fb, 0xa801, 1}, + {0xa803, 0xa805, 1}, + {0xa807, 0xa80a, 1}, + {0xa80c, 0xa822, 1}, + {0xa840, 0xa873, 1}, + {0xa882, 0xa8b3, 1}, + {0xa8f2, 0xa8f7, 1}, + {0xa8fb, 0xa90a, 15}, + {0xa90b, 0xa925, 1}, + {0xa930, 0xa946, 1}, + {0xa960, 0xa97c, 1}, + {0xa984, 0xa9b2, 1}, + {0xaa00, 0xaa28, 1}, + {0xaa40, 0xaa42, 1}, + {0xaa44, 0xaa4b, 1}, + {0xaa60, 0xaa6f, 1}, + {0xaa71, 0xaa76, 1}, + {0xaa7a, 0xaa80, 6}, + {0xaa81, 0xaaaf, 1}, + {0xaab1, 0xaab5, 4}, + {0xaab6, 0xaab9, 3}, + {0xaaba, 0xaabd, 1}, + {0xaac0, 0xaac2, 2}, + {0xaadb, 0xaadc, 1}, + {0xab01, 0xab06, 1}, + {0xab09, 0xab0e, 1}, + {0xab11, 0xab16, 1}, + {0xab20, 0xab26, 1}, + {0xab28, 0xab2e, 1}, + {0xabc0, 0xabe2, 1}, + {0xac00, 0xd7a3, 1}, + {0xd7b0, 0xd7c6, 1}, + {0xd7cb, 0xd7fb, 1}, + {0xf900, 0xfa2d, 1}, + {0xfa30, 0xfa6d, 1}, + {0xfa70, 0xfad9, 1}, + {0xfb1d, 0xfb1f, 2}, + {0xfb20, 0xfb28, 1}, + {0xfb2a, 0xfb36, 1}, + {0xfb38, 0xfb3c, 1}, + {0xfb3e, 0xfb40, 2}, + {0xfb41, 0xfb43, 2}, + {0xfb44, 0xfb46, 2}, + {0xfb47, 0xfbb1, 1}, + {0xfbd3, 0xfd3d, 1}, + {0xfd50, 0xfd8f, 1}, + {0xfd92, 0xfdc7, 1}, + {0xfdf0, 0xfdfb, 1}, + {0xfe70, 0xfe74, 1}, + {0xfe76, 0xfefc, 1}, + {0xff66, 0xff6f, 1}, + {0xff71, 0xff9d, 1}, + {0xffa0, 0xffbe, 1}, + {0xffc2, 0xffc7, 1}, + {0xffca, 0xffcf, 1}, + {0xffd2, 0xffd7, 1}, + {0xffda, 0xffdc, 1}, + }, + R32: []Range32{ + {0x10000, 0x1000b, 1}, + {0x1000d, 0x10026, 1}, + {0x10028, 0x1003a, 1}, + {0x1003c, 0x1003d, 1}, + {0x1003f, 0x1004d, 1}, + {0x10050, 0x1005d, 1}, + {0x10080, 0x100fa, 1}, + {0x10280, 0x1029c, 1}, + {0x102a0, 0x102d0, 1}, + {0x10300, 0x1031e, 1}, + {0x10330, 0x10340, 1}, + {0x10342, 0x10349, 1}, + {0x10380, 0x1039d, 1}, + {0x103a0, 0x103c3, 1}, + {0x103c8, 0x103cf, 1}, + {0x10450, 0x1049d, 1}, + {0x10800, 0x10805, 1}, + {0x10808, 0x1080a, 2}, + {0x1080b, 0x10835, 1}, + {0x10837, 0x10838, 1}, + {0x1083c, 0x1083f, 3}, + {0x10840, 0x10855, 1}, + {0x10900, 0x10915, 1}, + {0x10920, 0x10939, 1}, + {0x10a00, 0x10a10, 16}, + {0x10a11, 0x10a13, 1}, + {0x10a15, 0x10a17, 1}, + {0x10a19, 0x10a33, 1}, + {0x10a60, 0x10a7c, 1}, + {0x10b00, 0x10b35, 1}, + {0x10b40, 0x10b55, 1}, + {0x10b60, 0x10b72, 1}, + {0x10c00, 0x10c48, 1}, + {0x11003, 0x11037, 1}, + {0x11083, 0x110af, 1}, + {0x12000, 0x1236e, 1}, + {0x13000, 0x1342e, 1}, + {0x16800, 0x16a38, 1}, + {0x1b000, 0x1b001, 1}, + {0x20000, 0x2a6d6, 1}, + {0x2a700, 0x2b734, 1}, + {0x2b740, 0x2b81d, 1}, + {0x2f800, 0x2fa1d, 1}, + }, } var ( @@ -2018,7 +2109,7 @@ var ( // DO NOT EDIT // Scripts is the set of Unicode script tables. -var Scripts = map[string][]Range{ +var Scripts = map[string]*RangeTable{ "Katakana": Katakana, "Malayalam": Malayalam, "Phags_Pa": Phags_Pa, @@ -2116,973 +2207,1203 @@ var Scripts = map[string][]Range{ "Gothic": Gothic, } -var _Katakana = []Range{ - {0x30a1, 0x30fa, 1}, - {0x30fd, 0x30ff, 1}, - {0x31f0, 0x31ff, 1}, - {0x32d0, 0x32fe, 1}, - {0x3300, 0x3357, 1}, - {0xff66, 0xff6f, 1}, - {0xff71, 0xff9d, 1}, - {0x1b000, 0x1b000, 1}, -} - -var _Malayalam = []Range{ - {0x0d02, 0x0d03, 1}, - {0x0d05, 0x0d0c, 1}, - {0x0d0e, 0x0d10, 1}, - {0x0d12, 0x0d3a, 1}, - {0x0d3d, 0x0d44, 1}, - {0x0d46, 0x0d48, 1}, - {0x0d4a, 0x0d4e, 1}, - {0x0d57, 0x0d57, 1}, - {0x0d60, 0x0d63, 1}, - {0x0d66, 0x0d75, 1}, - {0x0d79, 0x0d7f, 1}, -} - -var _Phags_Pa = []Range{ - {0xa840, 0xa877, 1}, -} - -var _Inscriptional_Parthian = []Range{ - {0x10b40, 0x10b55, 1}, - {0x10b58, 0x10b5f, 1}, -} - -var _Latin = []Range{ - {0x0041, 0x005a, 1}, - {0x0061, 0x007a, 1}, - {0x00aa, 0x00aa, 1}, - {0x00ba, 0x00ba, 1}, - {0x00c0, 0x00d6, 1}, - {0x00d8, 0x00f6, 1}, - {0x00f8, 0x02b8, 1}, - {0x02e0, 0x02e4, 1}, - {0x1d00, 0x1d25, 1}, - {0x1d2c, 0x1d5c, 1}, - {0x1d62, 0x1d65, 1}, - {0x1d6b, 0x1d77, 1}, - {0x1d79, 0x1dbe, 1}, - {0x1e00, 0x1eff, 1}, - {0x2071, 0x2071, 1}, - {0x207f, 0x207f, 1}, - {0x2090, 0x209c, 1}, - {0x212a, 0x212b, 1}, - {0x2132, 0x2132, 1}, - {0x214e, 0x214e, 1}, - {0x2160, 0x2188, 1}, - {0x2c60, 0x2c7f, 1}, - {0xa722, 0xa787, 1}, - {0xa78b, 0xa78e, 1}, - {0xa790, 0xa791, 1}, - {0xa7a0, 0xa7a9, 1}, - {0xa7fa, 0xa7ff, 1}, - {0xfb00, 0xfb06, 1}, - {0xff21, 0xff3a, 1}, - {0xff41, 0xff5a, 1}, -} - -var _Inscriptional_Pahlavi = []Range{ - {0x10b60, 0x10b72, 1}, - {0x10b78, 0x10b7f, 1}, -} - -var _Osmanya = []Range{ - {0x10480, 0x1049d, 1}, - {0x104a0, 0x104a9, 1}, -} - -var _Khmer = []Range{ - {0x1780, 0x17dd, 1}, - {0x17e0, 0x17e9, 1}, - {0x17f0, 0x17f9, 1}, - {0x19e0, 0x19ff, 1}, -} - -var _Inherited = []Range{ - {0x0300, 0x036f, 1}, - {0x0485, 0x0486, 1}, - {0x064b, 0x0655, 1}, - {0x065f, 0x065f, 1}, - {0x0670, 0x0670, 1}, - {0x0951, 0x0952, 1}, - {0x1cd0, 0x1cd2, 1}, - {0x1cd4, 0x1ce0, 1}, - {0x1ce2, 0x1ce8, 1}, - {0x1ced, 0x1ced, 1}, - {0x1dc0, 0x1de6, 1}, - {0x1dfc, 0x1dff, 1}, - {0x200c, 0x200d, 1}, - {0x20d0, 0x20f0, 1}, - {0x302a, 0x302d, 1}, - {0x3099, 0x309a, 1}, - {0xfe00, 0xfe0f, 1}, - {0xfe20, 0xfe26, 1}, - {0x101fd, 0x101fd, 1}, - {0x1d167, 0x1d169, 1}, - {0x1d17b, 0x1d182, 1}, - {0x1d185, 0x1d18b, 1}, - {0x1d1aa, 0x1d1ad, 1}, - {0xe0100, 0xe01ef, 1}, -} - -var _Telugu = []Range{ - {0x0c01, 0x0c03, 1}, - {0x0c05, 0x0c0c, 1}, - {0x0c0e, 0x0c10, 1}, - {0x0c12, 0x0c28, 1}, - {0x0c2a, 0x0c33, 1}, - {0x0c35, 0x0c39, 1}, - {0x0c3d, 0x0c44, 1}, - {0x0c46, 0x0c48, 1}, - {0x0c4a, 0x0c4d, 1}, - {0x0c55, 0x0c56, 1}, - {0x0c58, 0x0c59, 1}, - {0x0c60, 0x0c63, 1}, - {0x0c66, 0x0c6f, 1}, - {0x0c78, 0x0c7f, 1}, -} - -var _Samaritan = []Range{ - {0x0800, 0x082d, 1}, - {0x0830, 0x083e, 1}, -} - -var _Bopomofo = []Range{ - {0x02ea, 0x02eb, 1}, - {0x3105, 0x312d, 1}, - {0x31a0, 0x31ba, 1}, -} - -var _Imperial_Aramaic = []Range{ - {0x10840, 0x10855, 1}, - {0x10857, 0x1085f, 1}, -} - -var _Kaithi = []Range{ - {0x11080, 0x110c1, 1}, -} - -var _Mandaic = []Range{ - {0x0840, 0x085b, 1}, - {0x085e, 0x085e, 1}, -} - -var _Old_South_Arabian = []Range{ - {0x10a60, 0x10a7f, 1}, -} - -var _Kayah_Li = []Range{ - {0xa900, 0xa92f, 1}, -} - -var _New_Tai_Lue = []Range{ - {0x1980, 0x19ab, 1}, - {0x19b0, 0x19c9, 1}, - {0x19d0, 0x19da, 1}, - {0x19de, 0x19df, 1}, -} - -var _Tai_Le = []Range{ - {0x1950, 0x196d, 1}, - {0x1970, 0x1974, 1}, -} - -var _Kharoshthi = []Range{ - {0x10a00, 0x10a03, 1}, - {0x10a05, 0x10a06, 1}, - {0x10a0c, 0x10a13, 1}, - {0x10a15, 0x10a17, 1}, - {0x10a19, 0x10a33, 1}, - {0x10a38, 0x10a3a, 1}, - {0x10a3f, 0x10a47, 1}, - {0x10a50, 0x10a58, 1}, -} - -var _Common = []Range{ - {0x0000, 0x0040, 1}, - {0x005b, 0x0060, 1}, - {0x007b, 0x00a9, 1}, - {0x00ab, 0x00b9, 1}, - {0x00bb, 0x00bf, 1}, - {0x00d7, 0x00d7, 1}, - {0x00f7, 0x00f7, 1}, - {0x02b9, 0x02df, 1}, - {0x02e5, 0x02e9, 1}, - {0x02ec, 0x02ff, 1}, - {0x0374, 0x0374, 1}, - {0x037e, 0x037e, 1}, - {0x0385, 0x0385, 1}, - {0x0387, 0x0387, 1}, - {0x0589, 0x0589, 1}, - {0x060c, 0x060c, 1}, - {0x061b, 0x061b, 1}, - {0x061f, 0x061f, 1}, - {0x0640, 0x0640, 1}, - {0x0660, 0x0669, 1}, - {0x06dd, 0x06dd, 1}, - {0x0964, 0x0965, 1}, - {0x0970, 0x0970, 1}, - {0x0e3f, 0x0e3f, 1}, - {0x0fd5, 0x0fd8, 1}, - {0x10fb, 0x10fb, 1}, - {0x16eb, 0x16ed, 1}, - {0x1735, 0x1736, 1}, - {0x1802, 0x1803, 1}, - {0x1805, 0x1805, 1}, - {0x1cd3, 0x1cd3, 1}, - {0x1ce1, 0x1ce1, 1}, - {0x1ce9, 0x1cec, 1}, - {0x1cee, 0x1cf2, 1}, - {0x2000, 0x200b, 1}, - {0x200e, 0x2064, 1}, - {0x206a, 0x2070, 1}, - {0x2074, 0x207e, 1}, - {0x2080, 0x208e, 1}, - {0x20a0, 0x20b9, 1}, - {0x2100, 0x2125, 1}, - {0x2127, 0x2129, 1}, - {0x212c, 0x2131, 1}, - {0x2133, 0x214d, 1}, - {0x214f, 0x215f, 1}, - {0x2189, 0x2189, 1}, - {0x2190, 0x23f3, 1}, - {0x2400, 0x2426, 1}, - {0x2440, 0x244a, 1}, - {0x2460, 0x26ff, 1}, - {0x2701, 0x27ca, 1}, - {0x27cc, 0x27cc, 1}, - {0x27ce, 0x27ff, 1}, - {0x2900, 0x2b4c, 1}, - {0x2b50, 0x2b59, 1}, - {0x2e00, 0x2e31, 1}, - {0x2ff0, 0x2ffb, 1}, - {0x3000, 0x3004, 1}, - {0x3006, 0x3006, 1}, - {0x3008, 0x3020, 1}, - {0x3030, 0x3037, 1}, - {0x303c, 0x303f, 1}, - {0x309b, 0x309c, 1}, - {0x30a0, 0x30a0, 1}, - {0x30fb, 0x30fc, 1}, - {0x3190, 0x319f, 1}, - {0x31c0, 0x31e3, 1}, - {0x3220, 0x325f, 1}, - {0x327f, 0x32cf, 1}, - {0x3358, 0x33ff, 1}, - {0x4dc0, 0x4dff, 1}, - {0xa700, 0xa721, 1}, - {0xa788, 0xa78a, 1}, - {0xa830, 0xa839, 1}, - {0xfd3e, 0xfd3f, 1}, - {0xfdfd, 0xfdfd, 1}, - {0xfe10, 0xfe19, 1}, - {0xfe30, 0xfe52, 1}, - {0xfe54, 0xfe66, 1}, - {0xfe68, 0xfe6b, 1}, - {0xfeff, 0xfeff, 1}, - {0xff01, 0xff20, 1}, - {0xff3b, 0xff40, 1}, - {0xff5b, 0xff65, 1}, - {0xff70, 0xff70, 1}, - {0xff9e, 0xff9f, 1}, - {0xffe0, 0xffe6, 1}, - {0xffe8, 0xffee, 1}, - {0xfff9, 0xfffd, 1}, - {0x10100, 0x10102, 1}, - {0x10107, 0x10133, 1}, - {0x10137, 0x1013f, 1}, - {0x10190, 0x1019b, 1}, - {0x101d0, 0x101fc, 1}, - {0x1d000, 0x1d0f5, 1}, - {0x1d100, 0x1d126, 1}, - {0x1d129, 0x1d166, 1}, - {0x1d16a, 0x1d17a, 1}, - {0x1d183, 0x1d184, 1}, - {0x1d18c, 0x1d1a9, 1}, - {0x1d1ae, 0x1d1dd, 1}, - {0x1d300, 0x1d356, 1}, - {0x1d360, 0x1d371, 1}, - {0x1d400, 0x1d454, 1}, - {0x1d456, 0x1d49c, 1}, - {0x1d49e, 0x1d49f, 1}, - {0x1d4a2, 0x1d4a2, 1}, - {0x1d4a5, 0x1d4a6, 1}, - {0x1d4a9, 0x1d4ac, 1}, - {0x1d4ae, 0x1d4b9, 1}, - {0x1d4bb, 0x1d4bb, 1}, - {0x1d4bd, 0x1d4c3, 1}, - {0x1d4c5, 0x1d505, 1}, - {0x1d507, 0x1d50a, 1}, - {0x1d50d, 0x1d514, 1}, - {0x1d516, 0x1d51c, 1}, - {0x1d51e, 0x1d539, 1}, - {0x1d53b, 0x1d53e, 1}, - {0x1d540, 0x1d544, 1}, - {0x1d546, 0x1d546, 1}, - {0x1d54a, 0x1d550, 1}, - {0x1d552, 0x1d6a5, 1}, - {0x1d6a8, 0x1d7cb, 1}, - {0x1d7ce, 0x1d7ff, 1}, - {0x1f000, 0x1f02b, 1}, - {0x1f030, 0x1f093, 1}, - {0x1f0a0, 0x1f0ae, 1}, - {0x1f0b1, 0x1f0be, 1}, - {0x1f0c1, 0x1f0cf, 1}, - {0x1f0d1, 0x1f0df, 1}, - {0x1f100, 0x1f10a, 1}, - {0x1f110, 0x1f12e, 1}, - {0x1f130, 0x1f169, 1}, - {0x1f170, 0x1f19a, 1}, - {0x1f1e6, 0x1f1ff, 1}, - {0x1f201, 0x1f202, 1}, - {0x1f210, 0x1f23a, 1}, - {0x1f240, 0x1f248, 1}, - {0x1f250, 0x1f251, 1}, - {0x1f300, 0x1f320, 1}, - {0x1f330, 0x1f335, 1}, - {0x1f337, 0x1f37c, 1}, - {0x1f380, 0x1f393, 1}, - {0x1f3a0, 0x1f3c4, 1}, - {0x1f3c6, 0x1f3ca, 1}, - {0x1f3e0, 0x1f3f0, 1}, - {0x1f400, 0x1f43e, 1}, - {0x1f440, 0x1f440, 1}, - {0x1f442, 0x1f4f7, 1}, - {0x1f4f9, 0x1f4fc, 1}, - {0x1f500, 0x1f53d, 1}, - {0x1f550, 0x1f567, 1}, - {0x1f5fb, 0x1f5ff, 1}, - {0x1f601, 0x1f610, 1}, - {0x1f612, 0x1f614, 1}, - {0x1f616, 0x1f616, 1}, - {0x1f618, 0x1f618, 1}, - {0x1f61a, 0x1f61a, 1}, - {0x1f61c, 0x1f61e, 1}, - {0x1f620, 0x1f625, 1}, - {0x1f628, 0x1f62b, 1}, - {0x1f62d, 0x1f62d, 1}, - {0x1f630, 0x1f633, 1}, - {0x1f635, 0x1f640, 1}, - {0x1f645, 0x1f64f, 1}, - {0x1f680, 0x1f6c5, 1}, - {0x1f700, 0x1f773, 1}, - {0xe0001, 0xe0001, 1}, - {0xe0020, 0xe007f, 1}, -} - -var _Kannada = []Range{ - {0x0c82, 0x0c83, 1}, - {0x0c85, 0x0c8c, 1}, - {0x0c8e, 0x0c90, 1}, - {0x0c92, 0x0ca8, 1}, - {0x0caa, 0x0cb3, 1}, - {0x0cb5, 0x0cb9, 1}, - {0x0cbc, 0x0cc4, 1}, - {0x0cc6, 0x0cc8, 1}, - {0x0cca, 0x0ccd, 1}, - {0x0cd5, 0x0cd6, 1}, - {0x0cde, 0x0cde, 1}, - {0x0ce0, 0x0ce3, 1}, - {0x0ce6, 0x0cef, 1}, - {0x0cf1, 0x0cf2, 1}, -} - -var _Old_Turkic = []Range{ - {0x10c00, 0x10c48, 1}, -} - -var _Tamil = []Range{ - {0x0b82, 0x0b83, 1}, - {0x0b85, 0x0b8a, 1}, - {0x0b8e, 0x0b90, 1}, - {0x0b92, 0x0b95, 1}, - {0x0b99, 0x0b9a, 1}, - {0x0b9c, 0x0b9c, 1}, - {0x0b9e, 0x0b9f, 1}, - {0x0ba3, 0x0ba4, 1}, - {0x0ba8, 0x0baa, 1}, - {0x0bae, 0x0bb9, 1}, - {0x0bbe, 0x0bc2, 1}, - {0x0bc6, 0x0bc8, 1}, - {0x0bca, 0x0bcd, 1}, - {0x0bd0, 0x0bd0, 1}, - {0x0bd7, 0x0bd7, 1}, - {0x0be6, 0x0bfa, 1}, -} - -var _Tagalog = []Range{ - {0x1700, 0x170c, 1}, - {0x170e, 0x1714, 1}, -} - -var _Brahmi = []Range{ - {0x11000, 0x1104d, 1}, - {0x11052, 0x1106f, 1}, -} - -var _Arabic = []Range{ - {0x0600, 0x0603, 1}, - {0x0606, 0x060b, 1}, - {0x060d, 0x061a, 1}, - {0x061e, 0x061e, 1}, - {0x0620, 0x063f, 1}, - {0x0641, 0x064a, 1}, - {0x0656, 0x065e, 1}, - {0x066a, 0x066f, 1}, - {0x0671, 0x06dc, 1}, - {0x06de, 0x06ff, 1}, - {0x0750, 0x077f, 1}, - {0xfb50, 0xfbc1, 1}, - {0xfbd3, 0xfd3d, 1}, - {0xfd50, 0xfd8f, 1}, - {0xfd92, 0xfdc7, 1}, - {0xfdf0, 0xfdfc, 1}, - {0xfe70, 0xfe74, 1}, - {0xfe76, 0xfefc, 1}, - {0x10e60, 0x10e7e, 1}, -} - -var _Tagbanwa = []Range{ - {0x1760, 0x176c, 1}, - {0x176e, 0x1770, 1}, - {0x1772, 0x1773, 1}, -} - -var _Canadian_Aboriginal = []Range{ - {0x1400, 0x167f, 1}, - {0x18b0, 0x18f5, 1}, -} - -var _Tibetan = []Range{ - {0x0f00, 0x0f47, 1}, - {0x0f49, 0x0f6c, 1}, - {0x0f71, 0x0f97, 1}, - {0x0f99, 0x0fbc, 1}, - {0x0fbe, 0x0fcc, 1}, - {0x0fce, 0x0fd4, 1}, - {0x0fd9, 0x0fda, 1}, -} - -var _Coptic = []Range{ - {0x03e2, 0x03ef, 1}, - {0x2c80, 0x2cf1, 1}, - {0x2cf9, 0x2cff, 1}, -} - -var _Hiragana = []Range{ - {0x3041, 0x3096, 1}, - {0x309d, 0x309f, 1}, - {0x1b001, 0x1b001, 1}, - {0x1f200, 0x1f200, 1}, -} - -var _Limbu = []Range{ - {0x1900, 0x191c, 1}, - {0x1920, 0x192b, 1}, - {0x1930, 0x193b, 1}, - {0x1940, 0x1940, 1}, - {0x1944, 0x194f, 1}, -} - -var _Egyptian_Hieroglyphs = []Range{ - {0x13000, 0x1342e, 1}, -} - -var _Avestan = []Range{ - {0x10b00, 0x10b35, 1}, - {0x10b39, 0x10b3f, 1}, -} - -var _Myanmar = []Range{ - {0x1000, 0x109f, 1}, - {0xaa60, 0xaa7b, 1}, -} - -var _Armenian = []Range{ - {0x0531, 0x0556, 1}, - {0x0559, 0x055f, 1}, - {0x0561, 0x0587, 1}, - {0x058a, 0x058a, 1}, - {0xfb13, 0xfb17, 1}, -} - -var _Sinhala = []Range{ - {0x0d82, 0x0d83, 1}, - {0x0d85, 0x0d96, 1}, - {0x0d9a, 0x0db1, 1}, - {0x0db3, 0x0dbb, 1}, - {0x0dbd, 0x0dbd, 1}, - {0x0dc0, 0x0dc6, 1}, - {0x0dca, 0x0dca, 1}, - {0x0dcf, 0x0dd4, 1}, - {0x0dd6, 0x0dd6, 1}, - {0x0dd8, 0x0ddf, 1}, - {0x0df2, 0x0df4, 1}, -} - -var _Bengali = []Range{ - {0x0981, 0x0983, 1}, - {0x0985, 0x098c, 1}, - {0x098f, 0x0990, 1}, - {0x0993, 0x09a8, 1}, - {0x09aa, 0x09b0, 1}, - {0x09b2, 0x09b2, 1}, - {0x09b6, 0x09b9, 1}, - {0x09bc, 0x09c4, 1}, - {0x09c7, 0x09c8, 1}, - {0x09cb, 0x09ce, 1}, - {0x09d7, 0x09d7, 1}, - {0x09dc, 0x09dd, 1}, - {0x09df, 0x09e3, 1}, - {0x09e6, 0x09fb, 1}, -} - -var _Greek = []Range{ - {0x0370, 0x0373, 1}, - {0x0375, 0x0377, 1}, - {0x037a, 0x037d, 1}, - {0x0384, 0x0384, 1}, - {0x0386, 0x0386, 1}, - {0x0388, 0x038a, 1}, - {0x038c, 0x038c, 1}, - {0x038e, 0x03a1, 1}, - {0x03a3, 0x03e1, 1}, - {0x03f0, 0x03ff, 1}, - {0x1d26, 0x1d2a, 1}, - {0x1d5d, 0x1d61, 1}, - {0x1d66, 0x1d6a, 1}, - {0x1dbf, 0x1dbf, 1}, - {0x1f00, 0x1f15, 1}, - {0x1f18, 0x1f1d, 1}, - {0x1f20, 0x1f45, 1}, - {0x1f48, 0x1f4d, 1}, - {0x1f50, 0x1f57, 1}, - {0x1f59, 0x1f59, 1}, - {0x1f5b, 0x1f5b, 1}, - {0x1f5d, 0x1f5d, 1}, - {0x1f5f, 0x1f7d, 1}, - {0x1f80, 0x1fb4, 1}, - {0x1fb6, 0x1fc4, 1}, - {0x1fc6, 0x1fd3, 1}, - {0x1fd6, 0x1fdb, 1}, - {0x1fdd, 0x1fef, 1}, - {0x1ff2, 0x1ff4, 1}, - {0x1ff6, 0x1ffe, 1}, - {0x2126, 0x2126, 1}, - {0x10140, 0x1018a, 1}, - {0x1d200, 0x1d245, 1}, -} - -var _Cham = []Range{ - {0xaa00, 0xaa36, 1}, - {0xaa40, 0xaa4d, 1}, - {0xaa50, 0xaa59, 1}, - {0xaa5c, 0xaa5f, 1}, -} - -var _Hebrew = []Range{ - {0x0591, 0x05c7, 1}, - {0x05d0, 0x05ea, 1}, - {0x05f0, 0x05f4, 1}, - {0xfb1d, 0xfb36, 1}, - {0xfb38, 0xfb3c, 1}, - {0xfb3e, 0xfb3e, 1}, - {0xfb40, 0xfb41, 1}, - {0xfb43, 0xfb44, 1}, - {0xfb46, 0xfb4f, 1}, -} - -var _Meetei_Mayek = []Range{ - {0xabc0, 0xabed, 1}, - {0xabf0, 0xabf9, 1}, -} - -var _Saurashtra = []Range{ - {0xa880, 0xa8c4, 1}, - {0xa8ce, 0xa8d9, 1}, -} - -var _Hangul = []Range{ - {0x1100, 0x11ff, 1}, - {0x302e, 0x302f, 1}, - {0x3131, 0x318e, 1}, - {0x3200, 0x321e, 1}, - {0x3260, 0x327e, 1}, - {0xa960, 0xa97c, 1}, - {0xac00, 0xd7a3, 1}, - {0xd7b0, 0xd7c6, 1}, - {0xd7cb, 0xd7fb, 1}, - {0xffa0, 0xffbe, 1}, - {0xffc2, 0xffc7, 1}, - {0xffca, 0xffcf, 1}, - {0xffd2, 0xffd7, 1}, - {0xffda, 0xffdc, 1}, -} - -var _Runic = []Range{ - {0x16a0, 0x16ea, 1}, - {0x16ee, 0x16f0, 1}, -} - -var _Deseret = []Range{ - {0x10400, 0x1044f, 1}, -} - -var _Lisu = []Range{ - {0xa4d0, 0xa4ff, 1}, -} - -var _Sundanese = []Range{ - {0x1b80, 0x1baa, 1}, - {0x1bae, 0x1bb9, 1}, -} - -var _Glagolitic = []Range{ - {0x2c00, 0x2c2e, 1}, - {0x2c30, 0x2c5e, 1}, -} - -var _Oriya = []Range{ - {0x0b01, 0x0b03, 1}, - {0x0b05, 0x0b0c, 1}, - {0x0b0f, 0x0b10, 1}, - {0x0b13, 0x0b28, 1}, - {0x0b2a, 0x0b30, 1}, - {0x0b32, 0x0b33, 1}, - {0x0b35, 0x0b39, 1}, - {0x0b3c, 0x0b44, 1}, - {0x0b47, 0x0b48, 1}, - {0x0b4b, 0x0b4d, 1}, - {0x0b56, 0x0b57, 1}, - {0x0b5c, 0x0b5d, 1}, - {0x0b5f, 0x0b63, 1}, - {0x0b66, 0x0b77, 1}, -} - -var _Buhid = []Range{ - {0x1740, 0x1753, 1}, -} - -var _Ethiopic = []Range{ - {0x1200, 0x1248, 1}, - {0x124a, 0x124d, 1}, - {0x1250, 0x1256, 1}, - {0x1258, 0x1258, 1}, - {0x125a, 0x125d, 1}, - {0x1260, 0x1288, 1}, - {0x128a, 0x128d, 1}, - {0x1290, 0x12b0, 1}, - {0x12b2, 0x12b5, 1}, - {0x12b8, 0x12be, 1}, - {0x12c0, 0x12c0, 1}, - {0x12c2, 0x12c5, 1}, - {0x12c8, 0x12d6, 1}, - {0x12d8, 0x1310, 1}, - {0x1312, 0x1315, 1}, - {0x1318, 0x135a, 1}, - {0x135d, 0x137c, 1}, - {0x1380, 0x1399, 1}, - {0x2d80, 0x2d96, 1}, - {0x2da0, 0x2da6, 1}, - {0x2da8, 0x2dae, 1}, - {0x2db0, 0x2db6, 1}, - {0x2db8, 0x2dbe, 1}, - {0x2dc0, 0x2dc6, 1}, - {0x2dc8, 0x2dce, 1}, - {0x2dd0, 0x2dd6, 1}, - {0x2dd8, 0x2dde, 1}, - {0xab01, 0xab06, 1}, - {0xab09, 0xab0e, 1}, - {0xab11, 0xab16, 1}, - {0xab20, 0xab26, 1}, - {0xab28, 0xab2e, 1}, -} - -var _Javanese = []Range{ - {0xa980, 0xa9cd, 1}, - {0xa9cf, 0xa9d9, 1}, - {0xa9de, 0xa9df, 1}, -} - -var _Syloti_Nagri = []Range{ - {0xa800, 0xa82b, 1}, -} - -var _Vai = []Range{ - {0xa500, 0xa62b, 1}, -} - -var _Cherokee = []Range{ - {0x13a0, 0x13f4, 1}, -} - -var _Ogham = []Range{ - {0x1680, 0x169c, 1}, -} - -var _Batak = []Range{ - {0x1bc0, 0x1bf3, 1}, - {0x1bfc, 0x1bff, 1}, -} - -var _Syriac = []Range{ - {0x0700, 0x070d, 1}, - {0x070f, 0x074a, 1}, - {0x074d, 0x074f, 1}, -} - -var _Gurmukhi = []Range{ - {0x0a01, 0x0a03, 1}, - {0x0a05, 0x0a0a, 1}, - {0x0a0f, 0x0a10, 1}, - {0x0a13, 0x0a28, 1}, - {0x0a2a, 0x0a30, 1}, - {0x0a32, 0x0a33, 1}, - {0x0a35, 0x0a36, 1}, - {0x0a38, 0x0a39, 1}, - {0x0a3c, 0x0a3c, 1}, - {0x0a3e, 0x0a42, 1}, - {0x0a47, 0x0a48, 1}, - {0x0a4b, 0x0a4d, 1}, - {0x0a51, 0x0a51, 1}, - {0x0a59, 0x0a5c, 1}, - {0x0a5e, 0x0a5e, 1}, - {0x0a66, 0x0a75, 1}, -} - -var _Tai_Tham = []Range{ - {0x1a20, 0x1a5e, 1}, - {0x1a60, 0x1a7c, 1}, - {0x1a7f, 0x1a89, 1}, - {0x1a90, 0x1a99, 1}, - {0x1aa0, 0x1aad, 1}, -} - -var _Ol_Chiki = []Range{ - {0x1c50, 0x1c7f, 1}, -} - -var _Mongolian = []Range{ - {0x1800, 0x1801, 1}, - {0x1804, 0x1804, 1}, - {0x1806, 0x180e, 1}, - {0x1810, 0x1819, 1}, - {0x1820, 0x1877, 1}, - {0x1880, 0x18aa, 1}, -} - -var _Hanunoo = []Range{ - {0x1720, 0x1734, 1}, -} - -var _Cypriot = []Range{ - {0x10800, 0x10805, 1}, - {0x10808, 0x10808, 1}, - {0x1080a, 0x10835, 1}, - {0x10837, 0x10838, 1}, - {0x1083c, 0x1083c, 1}, - {0x1083f, 0x1083f, 1}, -} - -var _Buginese = []Range{ - {0x1a00, 0x1a1b, 1}, - {0x1a1e, 0x1a1f, 1}, -} - -var _Bamum = []Range{ - {0xa6a0, 0xa6f7, 1}, - {0x16800, 0x16a38, 1}, -} - -var _Lepcha = []Range{ - {0x1c00, 0x1c37, 1}, - {0x1c3b, 0x1c49, 1}, - {0x1c4d, 0x1c4f, 1}, -} - -var _Thaana = []Range{ - {0x0780, 0x07b1, 1}, -} - -var _Old_Persian = []Range{ - {0x103a0, 0x103c3, 1}, - {0x103c8, 0x103d5, 1}, -} - -var _Cuneiform = []Range{ - {0x12000, 0x1236e, 1}, - {0x12400, 0x12462, 1}, - {0x12470, 0x12473, 1}, -} - -var _Rejang = []Range{ - {0xa930, 0xa953, 1}, - {0xa95f, 0xa95f, 1}, -} - -var _Georgian = []Range{ - {0x10a0, 0x10c5, 1}, - {0x10d0, 0x10fa, 1}, - {0x10fc, 0x10fc, 1}, - {0x2d00, 0x2d25, 1}, -} - -var _Shavian = []Range{ - {0x10450, 0x1047f, 1}, -} - -var _Lycian = []Range{ - {0x10280, 0x1029c, 1}, -} - -var _Nko = []Range{ - {0x07c0, 0x07fa, 1}, -} - -var _Yi = []Range{ - {0xa000, 0xa48c, 1}, - {0xa490, 0xa4c6, 1}, -} - -var _Lao = []Range{ - {0x0e81, 0x0e82, 1}, - {0x0e84, 0x0e84, 1}, - {0x0e87, 0x0e88, 1}, - {0x0e8a, 0x0e8a, 1}, - {0x0e8d, 0x0e8d, 1}, - {0x0e94, 0x0e97, 1}, - {0x0e99, 0x0e9f, 1}, - {0x0ea1, 0x0ea3, 1}, - {0x0ea5, 0x0ea5, 1}, - {0x0ea7, 0x0ea7, 1}, - {0x0eaa, 0x0eab, 1}, - {0x0ead, 0x0eb9, 1}, - {0x0ebb, 0x0ebd, 1}, - {0x0ec0, 0x0ec4, 1}, - {0x0ec6, 0x0ec6, 1}, - {0x0ec8, 0x0ecd, 1}, - {0x0ed0, 0x0ed9, 1}, - {0x0edc, 0x0edd, 1}, -} - -var _Linear_B = []Range{ - {0x10000, 0x1000b, 1}, - {0x1000d, 0x10026, 1}, - {0x10028, 0x1003a, 1}, - {0x1003c, 0x1003d, 1}, - {0x1003f, 0x1004d, 1}, - {0x10050, 0x1005d, 1}, - {0x10080, 0x100fa, 1}, -} - -var _Old_Italic = []Range{ - {0x10300, 0x1031e, 1}, - {0x10320, 0x10323, 1}, -} - -var _Tai_Viet = []Range{ - {0xaa80, 0xaac2, 1}, - {0xaadb, 0xaadf, 1}, -} - -var _Devanagari = []Range{ - {0x0900, 0x0950, 1}, - {0x0953, 0x0963, 1}, - {0x0966, 0x096f, 1}, - {0x0971, 0x0977, 1}, - {0x0979, 0x097f, 1}, - {0xa8e0, 0xa8fb, 1}, -} - -var _Lydian = []Range{ - {0x10920, 0x10939, 1}, - {0x1093f, 0x1093f, 1}, -} - -var _Tifinagh = []Range{ - {0x2d30, 0x2d65, 1}, - {0x2d6f, 0x2d70, 1}, - {0x2d7f, 0x2d7f, 1}, -} - -var _Ugaritic = []Range{ - {0x10380, 0x1039d, 1}, - {0x1039f, 0x1039f, 1}, -} - -var _Thai = []Range{ - {0x0e01, 0x0e3a, 1}, - {0x0e40, 0x0e5b, 1}, -} - -var _Cyrillic = []Range{ - {0x0400, 0x0484, 1}, - {0x0487, 0x0527, 1}, - {0x1d2b, 0x1d2b, 1}, - {0x1d78, 0x1d78, 1}, - {0x2de0, 0x2dff, 1}, - {0xa640, 0xa673, 1}, - {0xa67c, 0xa697, 1}, -} - -var _Gujarati = []Range{ - {0x0a81, 0x0a83, 1}, - {0x0a85, 0x0a8d, 1}, - {0x0a8f, 0x0a91, 1}, - {0x0a93, 0x0aa8, 1}, - {0x0aaa, 0x0ab0, 1}, - {0x0ab2, 0x0ab3, 1}, - {0x0ab5, 0x0ab9, 1}, - {0x0abc, 0x0ac5, 1}, - {0x0ac7, 0x0ac9, 1}, - {0x0acb, 0x0acd, 1}, - {0x0ad0, 0x0ad0, 1}, - {0x0ae0, 0x0ae3, 1}, - {0x0ae6, 0x0aef, 1}, - {0x0af1, 0x0af1, 1}, -} - -var _Carian = []Range{ - {0x102a0, 0x102d0, 1}, -} - -var _Phoenician = []Range{ - {0x10900, 0x1091b, 1}, - {0x1091f, 0x1091f, 1}, -} - -var _Balinese = []Range{ - {0x1b00, 0x1b4b, 1}, - {0x1b50, 0x1b7c, 1}, -} - -var _Braille = []Range{ - {0x2800, 0x28ff, 1}, -} - -var _Han = []Range{ - {0x2e80, 0x2e99, 1}, - {0x2e9b, 0x2ef3, 1}, - {0x2f00, 0x2fd5, 1}, - {0x3005, 0x3005, 1}, - {0x3007, 0x3007, 1}, - {0x3021, 0x3029, 1}, - {0x3038, 0x303b, 1}, - {0x3400, 0x4db5, 1}, - {0x4e00, 0x9fcb, 1}, - {0xf900, 0xfa2d, 1}, - {0xfa30, 0xfa6d, 1}, - {0xfa70, 0xfad9, 1}, - {0x20000, 0x2a6d6, 1}, - {0x2a700, 0x2b734, 1}, - {0x2b740, 0x2b81d, 1}, - {0x2f800, 0x2fa1d, 1}, -} - -var _Gothic = []Range{ - {0x10330, 0x1034a, 1}, +var _Katakana = &RangeTable{ + R16: []Range16{ + {0x30a1, 0x30fa, 1}, + {0x30fd, 0x30ff, 1}, + {0x31f0, 0x31ff, 1}, + {0x32d0, 0x32fe, 1}, + {0x3300, 0x3357, 1}, + {0xff66, 0xff6f, 1}, + {0xff71, 0xff9d, 1}, + }, + R32: []Range32{ + {0x1b000, 0x1b000, 1}, + }, +} + +var _Malayalam = &RangeTable{ + R16: []Range16{ + {0x0d02, 0x0d03, 1}, + {0x0d05, 0x0d0c, 1}, + {0x0d0e, 0x0d10, 1}, + {0x0d12, 0x0d3a, 1}, + {0x0d3d, 0x0d44, 1}, + {0x0d46, 0x0d48, 1}, + {0x0d4a, 0x0d4e, 1}, + {0x0d57, 0x0d57, 1}, + {0x0d60, 0x0d63, 1}, + {0x0d66, 0x0d75, 1}, + {0x0d79, 0x0d7f, 1}, + }, +} + +var _Phags_Pa = &RangeTable{ + R16: []Range16{ + {0xa840, 0xa877, 1}, + }, +} + +var _Inscriptional_Parthian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10b40, 0x10b55, 1}, + {0x10b58, 0x10b5f, 1}, + }, +} + +var _Latin = &RangeTable{ + R16: []Range16{ + {0x0041, 0x005a, 1}, + {0x0061, 0x007a, 1}, + {0x00aa, 0x00aa, 1}, + {0x00ba, 0x00ba, 1}, + {0x00c0, 0x00d6, 1}, + {0x00d8, 0x00f6, 1}, + {0x00f8, 0x02b8, 1}, + {0x02e0, 0x02e4, 1}, + {0x1d00, 0x1d25, 1}, + {0x1d2c, 0x1d5c, 1}, + {0x1d62, 0x1d65, 1}, + {0x1d6b, 0x1d77, 1}, + {0x1d79, 0x1dbe, 1}, + {0x1e00, 0x1eff, 1}, + {0x2071, 0x2071, 1}, + {0x207f, 0x207f, 1}, + {0x2090, 0x209c, 1}, + {0x212a, 0x212b, 1}, + {0x2132, 0x2132, 1}, + {0x214e, 0x214e, 1}, + {0x2160, 0x2188, 1}, + {0x2c60, 0x2c7f, 1}, + {0xa722, 0xa787, 1}, + {0xa78b, 0xa78e, 1}, + {0xa790, 0xa791, 1}, + {0xa7a0, 0xa7a9, 1}, + {0xa7fa, 0xa7ff, 1}, + {0xfb00, 0xfb06, 1}, + {0xff21, 0xff3a, 1}, + {0xff41, 0xff5a, 1}, + }, +} + +var _Inscriptional_Pahlavi = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10b60, 0x10b72, 1}, + {0x10b78, 0x10b7f, 1}, + }, +} + +var _Osmanya = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10480, 0x1049d, 1}, + {0x104a0, 0x104a9, 1}, + }, +} + +var _Khmer = &RangeTable{ + R16: []Range16{ + {0x1780, 0x17dd, 1}, + {0x17e0, 0x17e9, 1}, + {0x17f0, 0x17f9, 1}, + {0x19e0, 0x19ff, 1}, + }, +} + +var _Inherited = &RangeTable{ + R16: []Range16{ + {0x0300, 0x036f, 1}, + {0x0485, 0x0486, 1}, + {0x064b, 0x0655, 1}, + {0x065f, 0x065f, 1}, + {0x0670, 0x0670, 1}, + {0x0951, 0x0952, 1}, + {0x1cd0, 0x1cd2, 1}, + {0x1cd4, 0x1ce0, 1}, + {0x1ce2, 0x1ce8, 1}, + {0x1ced, 0x1ced, 1}, + {0x1dc0, 0x1de6, 1}, + {0x1dfc, 0x1dff, 1}, + {0x200c, 0x200d, 1}, + {0x20d0, 0x20f0, 1}, + {0x302a, 0x302d, 1}, + {0x3099, 0x309a, 1}, + {0xfe00, 0xfe0f, 1}, + {0xfe20, 0xfe26, 1}, + }, + R32: []Range32{ + {0x101fd, 0x101fd, 1}, + {0x1d167, 0x1d169, 1}, + {0x1d17b, 0x1d182, 1}, + {0x1d185, 0x1d18b, 1}, + {0x1d1aa, 0x1d1ad, 1}, + {0xe0100, 0xe01ef, 1}, + }, +} + +var _Telugu = &RangeTable{ + R16: []Range16{ + {0x0c01, 0x0c03, 1}, + {0x0c05, 0x0c0c, 1}, + {0x0c0e, 0x0c10, 1}, + {0x0c12, 0x0c28, 1}, + {0x0c2a, 0x0c33, 1}, + {0x0c35, 0x0c39, 1}, + {0x0c3d, 0x0c44, 1}, + {0x0c46, 0x0c48, 1}, + {0x0c4a, 0x0c4d, 1}, + {0x0c55, 0x0c56, 1}, + {0x0c58, 0x0c59, 1}, + {0x0c60, 0x0c63, 1}, + {0x0c66, 0x0c6f, 1}, + {0x0c78, 0x0c7f, 1}, + }, +} + +var _Samaritan = &RangeTable{ + R16: []Range16{ + {0x0800, 0x082d, 1}, + {0x0830, 0x083e, 1}, + }, +} + +var _Bopomofo = &RangeTable{ + R16: []Range16{ + {0x02ea, 0x02eb, 1}, + {0x3105, 0x312d, 1}, + {0x31a0, 0x31ba, 1}, + }, +} + +var _Imperial_Aramaic = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10840, 0x10855, 1}, + {0x10857, 0x1085f, 1}, + }, +} + +var _Kaithi = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x11080, 0x110c1, 1}, + }, +} + +var _Mandaic = &RangeTable{ + R16: []Range16{ + {0x0840, 0x085b, 1}, + {0x085e, 0x085e, 1}, + }, +} + +var _Old_South_Arabian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10a60, 0x10a7f, 1}, + }, +} + +var _Kayah_Li = &RangeTable{ + R16: []Range16{ + {0xa900, 0xa92f, 1}, + }, +} + +var _New_Tai_Lue = &RangeTable{ + R16: []Range16{ + {0x1980, 0x19ab, 1}, + {0x19b0, 0x19c9, 1}, + {0x19d0, 0x19da, 1}, + {0x19de, 0x19df, 1}, + }, +} + +var _Tai_Le = &RangeTable{ + R16: []Range16{ + {0x1950, 0x196d, 1}, + {0x1970, 0x1974, 1}, + }, +} + +var _Kharoshthi = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10a00, 0x10a03, 1}, + {0x10a05, 0x10a06, 1}, + {0x10a0c, 0x10a13, 1}, + {0x10a15, 0x10a17, 1}, + {0x10a19, 0x10a33, 1}, + {0x10a38, 0x10a3a, 1}, + {0x10a3f, 0x10a47, 1}, + {0x10a50, 0x10a58, 1}, + }, +} + +var _Common = &RangeTable{ + R16: []Range16{ + {0x0000, 0x0040, 1}, + {0x005b, 0x0060, 1}, + {0x007b, 0x00a9, 1}, + {0x00ab, 0x00b9, 1}, + {0x00bb, 0x00bf, 1}, + {0x00d7, 0x00d7, 1}, + {0x00f7, 0x00f7, 1}, + {0x02b9, 0x02df, 1}, + {0x02e5, 0x02e9, 1}, + {0x02ec, 0x02ff, 1}, + {0x0374, 0x0374, 1}, + {0x037e, 0x037e, 1}, + {0x0385, 0x0385, 1}, + {0x0387, 0x0387, 1}, + {0x0589, 0x0589, 1}, + {0x060c, 0x060c, 1}, + {0x061b, 0x061b, 1}, + {0x061f, 0x061f, 1}, + {0x0640, 0x0640, 1}, + {0x0660, 0x0669, 1}, + {0x06dd, 0x06dd, 1}, + {0x0964, 0x0965, 1}, + {0x0970, 0x0970, 1}, + {0x0e3f, 0x0e3f, 1}, + {0x0fd5, 0x0fd8, 1}, + {0x10fb, 0x10fb, 1}, + {0x16eb, 0x16ed, 1}, + {0x1735, 0x1736, 1}, + {0x1802, 0x1803, 1}, + {0x1805, 0x1805, 1}, + {0x1cd3, 0x1cd3, 1}, + {0x1ce1, 0x1ce1, 1}, + {0x1ce9, 0x1cec, 1}, + {0x1cee, 0x1cf2, 1}, + {0x2000, 0x200b, 1}, + {0x200e, 0x2064, 1}, + {0x206a, 0x2070, 1}, + {0x2074, 0x207e, 1}, + {0x2080, 0x208e, 1}, + {0x20a0, 0x20b9, 1}, + {0x2100, 0x2125, 1}, + {0x2127, 0x2129, 1}, + {0x212c, 0x2131, 1}, + {0x2133, 0x214d, 1}, + {0x214f, 0x215f, 1}, + {0x2189, 0x2189, 1}, + {0x2190, 0x23f3, 1}, + {0x2400, 0x2426, 1}, + {0x2440, 0x244a, 1}, + {0x2460, 0x26ff, 1}, + {0x2701, 0x27ca, 1}, + {0x27cc, 0x27cc, 1}, + {0x27ce, 0x27ff, 1}, + {0x2900, 0x2b4c, 1}, + {0x2b50, 0x2b59, 1}, + {0x2e00, 0x2e31, 1}, + {0x2ff0, 0x2ffb, 1}, + {0x3000, 0x3004, 1}, + {0x3006, 0x3006, 1}, + {0x3008, 0x3020, 1}, + {0x3030, 0x3037, 1}, + {0x303c, 0x303f, 1}, + {0x309b, 0x309c, 1}, + {0x30a0, 0x30a0, 1}, + {0x30fb, 0x30fc, 1}, + {0x3190, 0x319f, 1}, + {0x31c0, 0x31e3, 1}, + {0x3220, 0x325f, 1}, + {0x327f, 0x32cf, 1}, + {0x3358, 0x33ff, 1}, + {0x4dc0, 0x4dff, 1}, + {0xa700, 0xa721, 1}, + {0xa788, 0xa78a, 1}, + {0xa830, 0xa839, 1}, + {0xfd3e, 0xfd3f, 1}, + {0xfdfd, 0xfdfd, 1}, + {0xfe10, 0xfe19, 1}, + {0xfe30, 0xfe52, 1}, + {0xfe54, 0xfe66, 1}, + {0xfe68, 0xfe6b, 1}, + {0xfeff, 0xfeff, 1}, + {0xff01, 0xff20, 1}, + {0xff3b, 0xff40, 1}, + {0xff5b, 0xff65, 1}, + {0xff70, 0xff70, 1}, + {0xff9e, 0xff9f, 1}, + {0xffe0, 0xffe6, 1}, + {0xffe8, 0xffee, 1}, + {0xfff9, 0xfffd, 1}, + }, + R32: []Range32{ + {0x10100, 0x10102, 1}, + {0x10107, 0x10133, 1}, + {0x10137, 0x1013f, 1}, + {0x10190, 0x1019b, 1}, + {0x101d0, 0x101fc, 1}, + {0x1d000, 0x1d0f5, 1}, + {0x1d100, 0x1d126, 1}, + {0x1d129, 0x1d166, 1}, + {0x1d16a, 0x1d17a, 1}, + {0x1d183, 0x1d184, 1}, + {0x1d18c, 0x1d1a9, 1}, + {0x1d1ae, 0x1d1dd, 1}, + {0x1d300, 0x1d356, 1}, + {0x1d360, 0x1d371, 1}, + {0x1d400, 0x1d454, 1}, + {0x1d456, 0x1d49c, 1}, + {0x1d49e, 0x1d49f, 1}, + {0x1d4a2, 0x1d4a2, 1}, + {0x1d4a5, 0x1d4a6, 1}, + {0x1d4a9, 0x1d4ac, 1}, + {0x1d4ae, 0x1d4b9, 1}, + {0x1d4bb, 0x1d4bb, 1}, + {0x1d4bd, 0x1d4c3, 1}, + {0x1d4c5, 0x1d505, 1}, + {0x1d507, 0x1d50a, 1}, + {0x1d50d, 0x1d514, 1}, + {0x1d516, 0x1d51c, 1}, + {0x1d51e, 0x1d539, 1}, + {0x1d53b, 0x1d53e, 1}, + {0x1d540, 0x1d544, 1}, + {0x1d546, 0x1d546, 1}, + {0x1d54a, 0x1d550, 1}, + {0x1d552, 0x1d6a5, 1}, + {0x1d6a8, 0x1d7cb, 1}, + {0x1d7ce, 0x1d7ff, 1}, + {0x1f000, 0x1f02b, 1}, + {0x1f030, 0x1f093, 1}, + {0x1f0a0, 0x1f0ae, 1}, + {0x1f0b1, 0x1f0be, 1}, + {0x1f0c1, 0x1f0cf, 1}, + {0x1f0d1, 0x1f0df, 1}, + {0x1f100, 0x1f10a, 1}, + {0x1f110, 0x1f12e, 1}, + {0x1f130, 0x1f169, 1}, + {0x1f170, 0x1f19a, 1}, + {0x1f1e6, 0x1f1ff, 1}, + {0x1f201, 0x1f202, 1}, + {0x1f210, 0x1f23a, 1}, + {0x1f240, 0x1f248, 1}, + {0x1f250, 0x1f251, 1}, + {0x1f300, 0x1f320, 1}, + {0x1f330, 0x1f335, 1}, + {0x1f337, 0x1f37c, 1}, + {0x1f380, 0x1f393, 1}, + {0x1f3a0, 0x1f3c4, 1}, + {0x1f3c6, 0x1f3ca, 1}, + {0x1f3e0, 0x1f3f0, 1}, + {0x1f400, 0x1f43e, 1}, + {0x1f440, 0x1f440, 1}, + {0x1f442, 0x1f4f7, 1}, + {0x1f4f9, 0x1f4fc, 1}, + {0x1f500, 0x1f53d, 1}, + {0x1f550, 0x1f567, 1}, + {0x1f5fb, 0x1f5ff, 1}, + {0x1f601, 0x1f610, 1}, + {0x1f612, 0x1f614, 1}, + {0x1f616, 0x1f616, 1}, + {0x1f618, 0x1f618, 1}, + {0x1f61a, 0x1f61a, 1}, + {0x1f61c, 0x1f61e, 1}, + {0x1f620, 0x1f625, 1}, + {0x1f628, 0x1f62b, 1}, + {0x1f62d, 0x1f62d, 1}, + {0x1f630, 0x1f633, 1}, + {0x1f635, 0x1f640, 1}, + {0x1f645, 0x1f64f, 1}, + {0x1f680, 0x1f6c5, 1}, + {0x1f700, 0x1f773, 1}, + {0xe0001, 0xe0001, 1}, + {0xe0020, 0xe007f, 1}, + }, +} + +var _Kannada = &RangeTable{ + R16: []Range16{ + {0x0c82, 0x0c83, 1}, + {0x0c85, 0x0c8c, 1}, + {0x0c8e, 0x0c90, 1}, + {0x0c92, 0x0ca8, 1}, + {0x0caa, 0x0cb3, 1}, + {0x0cb5, 0x0cb9, 1}, + {0x0cbc, 0x0cc4, 1}, + {0x0cc6, 0x0cc8, 1}, + {0x0cca, 0x0ccd, 1}, + {0x0cd5, 0x0cd6, 1}, + {0x0cde, 0x0cde, 1}, + {0x0ce0, 0x0ce3, 1}, + {0x0ce6, 0x0cef, 1}, + {0x0cf1, 0x0cf2, 1}, + }, +} + +var _Old_Turkic = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10c00, 0x10c48, 1}, + }, +} + +var _Tamil = &RangeTable{ + R16: []Range16{ + {0x0b82, 0x0b83, 1}, + {0x0b85, 0x0b8a, 1}, + {0x0b8e, 0x0b90, 1}, + {0x0b92, 0x0b95, 1}, + {0x0b99, 0x0b9a, 1}, + {0x0b9c, 0x0b9c, 1}, + {0x0b9e, 0x0b9f, 1}, + {0x0ba3, 0x0ba4, 1}, + {0x0ba8, 0x0baa, 1}, + {0x0bae, 0x0bb9, 1}, + {0x0bbe, 0x0bc2, 1}, + {0x0bc6, 0x0bc8, 1}, + {0x0bca, 0x0bcd, 1}, + {0x0bd0, 0x0bd0, 1}, + {0x0bd7, 0x0bd7, 1}, + {0x0be6, 0x0bfa, 1}, + }, +} + +var _Tagalog = &RangeTable{ + R16: []Range16{ + {0x1700, 0x170c, 1}, + {0x170e, 0x1714, 1}, + }, +} + +var _Brahmi = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x11000, 0x1104d, 1}, + {0x11052, 0x1106f, 1}, + }, +} + +var _Arabic = &RangeTable{ + R16: []Range16{ + {0x0600, 0x0603, 1}, + {0x0606, 0x060b, 1}, + {0x060d, 0x061a, 1}, + {0x061e, 0x061e, 1}, + {0x0620, 0x063f, 1}, + {0x0641, 0x064a, 1}, + {0x0656, 0x065e, 1}, + {0x066a, 0x066f, 1}, + {0x0671, 0x06dc, 1}, + {0x06de, 0x06ff, 1}, + {0x0750, 0x077f, 1}, + {0xfb50, 0xfbc1, 1}, + {0xfbd3, 0xfd3d, 1}, + {0xfd50, 0xfd8f, 1}, + {0xfd92, 0xfdc7, 1}, + {0xfdf0, 0xfdfc, 1}, + {0xfe70, 0xfe74, 1}, + {0xfe76, 0xfefc, 1}, + }, + R32: []Range32{ + {0x10e60, 0x10e7e, 1}, + }, +} + +var _Tagbanwa = &RangeTable{ + R16: []Range16{ + {0x1760, 0x176c, 1}, + {0x176e, 0x1770, 1}, + {0x1772, 0x1773, 1}, + }, +} + +var _Canadian_Aboriginal = &RangeTable{ + R16: []Range16{ + {0x1400, 0x167f, 1}, + {0x18b0, 0x18f5, 1}, + }, +} + +var _Tibetan = &RangeTable{ + R16: []Range16{ + {0x0f00, 0x0f47, 1}, + {0x0f49, 0x0f6c, 1}, + {0x0f71, 0x0f97, 1}, + {0x0f99, 0x0fbc, 1}, + {0x0fbe, 0x0fcc, 1}, + {0x0fce, 0x0fd4, 1}, + {0x0fd9, 0x0fda, 1}, + }, +} + +var _Coptic = &RangeTable{ + R16: []Range16{ + {0x03e2, 0x03ef, 1}, + {0x2c80, 0x2cf1, 1}, + {0x2cf9, 0x2cff, 1}, + }, +} + +var _Hiragana = &RangeTable{ + R16: []Range16{ + {0x3041, 0x3096, 1}, + {0x309d, 0x309f, 1}, + }, + R32: []Range32{ + {0x1b001, 0x1b001, 1}, + {0x1f200, 0x1f200, 1}, + }, +} + +var _Limbu = &RangeTable{ + R16: []Range16{ + {0x1900, 0x191c, 1}, + {0x1920, 0x192b, 1}, + {0x1930, 0x193b, 1}, + {0x1940, 0x1940, 1}, + {0x1944, 0x194f, 1}, + }, +} + +var _Egyptian_Hieroglyphs = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x13000, 0x1342e, 1}, + }, +} + +var _Avestan = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10b00, 0x10b35, 1}, + {0x10b39, 0x10b3f, 1}, + }, +} + +var _Myanmar = &RangeTable{ + R16: []Range16{ + {0x1000, 0x109f, 1}, + {0xaa60, 0xaa7b, 1}, + }, +} + +var _Armenian = &RangeTable{ + R16: []Range16{ + {0x0531, 0x0556, 1}, + {0x0559, 0x055f, 1}, + {0x0561, 0x0587, 1}, + {0x058a, 0x058a, 1}, + {0xfb13, 0xfb17, 1}, + }, +} + +var _Sinhala = &RangeTable{ + R16: []Range16{ + {0x0d82, 0x0d83, 1}, + {0x0d85, 0x0d96, 1}, + {0x0d9a, 0x0db1, 1}, + {0x0db3, 0x0dbb, 1}, + {0x0dbd, 0x0dbd, 1}, + {0x0dc0, 0x0dc6, 1}, + {0x0dca, 0x0dca, 1}, + {0x0dcf, 0x0dd4, 1}, + {0x0dd6, 0x0dd6, 1}, + {0x0dd8, 0x0ddf, 1}, + {0x0df2, 0x0df4, 1}, + }, +} + +var _Bengali = &RangeTable{ + R16: []Range16{ + {0x0981, 0x0983, 1}, + {0x0985, 0x098c, 1}, + {0x098f, 0x0990, 1}, + {0x0993, 0x09a8, 1}, + {0x09aa, 0x09b0, 1}, + {0x09b2, 0x09b2, 1}, + {0x09b6, 0x09b9, 1}, + {0x09bc, 0x09c4, 1}, + {0x09c7, 0x09c8, 1}, + {0x09cb, 0x09ce, 1}, + {0x09d7, 0x09d7, 1}, + {0x09dc, 0x09dd, 1}, + {0x09df, 0x09e3, 1}, + {0x09e6, 0x09fb, 1}, + }, +} + +var _Greek = &RangeTable{ + R16: []Range16{ + {0x0370, 0x0373, 1}, + {0x0375, 0x0377, 1}, + {0x037a, 0x037d, 1}, + {0x0384, 0x0384, 1}, + {0x0386, 0x0386, 1}, + {0x0388, 0x038a, 1}, + {0x038c, 0x038c, 1}, + {0x038e, 0x03a1, 1}, + {0x03a3, 0x03e1, 1}, + {0x03f0, 0x03ff, 1}, + {0x1d26, 0x1d2a, 1}, + {0x1d5d, 0x1d61, 1}, + {0x1d66, 0x1d6a, 1}, + {0x1dbf, 0x1dbf, 1}, + {0x1f00, 0x1f15, 1}, + {0x1f18, 0x1f1d, 1}, + {0x1f20, 0x1f45, 1}, + {0x1f48, 0x1f4d, 1}, + {0x1f50, 0x1f57, 1}, + {0x1f59, 0x1f59, 1}, + {0x1f5b, 0x1f5b, 1}, + {0x1f5d, 0x1f5d, 1}, + {0x1f5f, 0x1f7d, 1}, + {0x1f80, 0x1fb4, 1}, + {0x1fb6, 0x1fc4, 1}, + {0x1fc6, 0x1fd3, 1}, + {0x1fd6, 0x1fdb, 1}, + {0x1fdd, 0x1fef, 1}, + {0x1ff2, 0x1ff4, 1}, + {0x1ff6, 0x1ffe, 1}, + {0x2126, 0x2126, 1}, + }, + R32: []Range32{ + {0x10140, 0x1018a, 1}, + {0x1d200, 0x1d245, 1}, + }, +} + +var _Cham = &RangeTable{ + R16: []Range16{ + {0xaa00, 0xaa36, 1}, + {0xaa40, 0xaa4d, 1}, + {0xaa50, 0xaa59, 1}, + {0xaa5c, 0xaa5f, 1}, + }, +} + +var _Hebrew = &RangeTable{ + R16: []Range16{ + {0x0591, 0x05c7, 1}, + {0x05d0, 0x05ea, 1}, + {0x05f0, 0x05f4, 1}, + {0xfb1d, 0xfb36, 1}, + {0xfb38, 0xfb3c, 1}, + {0xfb3e, 0xfb3e, 1}, + {0xfb40, 0xfb41, 1}, + {0xfb43, 0xfb44, 1}, + {0xfb46, 0xfb4f, 1}, + }, +} + +var _Meetei_Mayek = &RangeTable{ + R16: []Range16{ + {0xabc0, 0xabed, 1}, + {0xabf0, 0xabf9, 1}, + }, +} + +var _Saurashtra = &RangeTable{ + R16: []Range16{ + {0xa880, 0xa8c4, 1}, + {0xa8ce, 0xa8d9, 1}, + }, +} + +var _Hangul = &RangeTable{ + R16: []Range16{ + {0x1100, 0x11ff, 1}, + {0x302e, 0x302f, 1}, + {0x3131, 0x318e, 1}, + {0x3200, 0x321e, 1}, + {0x3260, 0x327e, 1}, + {0xa960, 0xa97c, 1}, + {0xac00, 0xd7a3, 1}, + {0xd7b0, 0xd7c6, 1}, + {0xd7cb, 0xd7fb, 1}, + {0xffa0, 0xffbe, 1}, + {0xffc2, 0xffc7, 1}, + {0xffca, 0xffcf, 1}, + {0xffd2, 0xffd7, 1}, + {0xffda, 0xffdc, 1}, + }, +} + +var _Runic = &RangeTable{ + R16: []Range16{ + {0x16a0, 0x16ea, 1}, + {0x16ee, 0x16f0, 1}, + }, +} + +var _Deseret = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10400, 0x1044f, 1}, + }, +} + +var _Lisu = &RangeTable{ + R16: []Range16{ + {0xa4d0, 0xa4ff, 1}, + }, +} + +var _Sundanese = &RangeTable{ + R16: []Range16{ + {0x1b80, 0x1baa, 1}, + {0x1bae, 0x1bb9, 1}, + }, +} + +var _Glagolitic = &RangeTable{ + R16: []Range16{ + {0x2c00, 0x2c2e, 1}, + {0x2c30, 0x2c5e, 1}, + }, +} + +var _Oriya = &RangeTable{ + R16: []Range16{ + {0x0b01, 0x0b03, 1}, + {0x0b05, 0x0b0c, 1}, + {0x0b0f, 0x0b10, 1}, + {0x0b13, 0x0b28, 1}, + {0x0b2a, 0x0b30, 1}, + {0x0b32, 0x0b33, 1}, + {0x0b35, 0x0b39, 1}, + {0x0b3c, 0x0b44, 1}, + {0x0b47, 0x0b48, 1}, + {0x0b4b, 0x0b4d, 1}, + {0x0b56, 0x0b57, 1}, + {0x0b5c, 0x0b5d, 1}, + {0x0b5f, 0x0b63, 1}, + {0x0b66, 0x0b77, 1}, + }, +} + +var _Buhid = &RangeTable{ + R16: []Range16{ + {0x1740, 0x1753, 1}, + }, +} + +var _Ethiopic = &RangeTable{ + R16: []Range16{ + {0x1200, 0x1248, 1}, + {0x124a, 0x124d, 1}, + {0x1250, 0x1256, 1}, + {0x1258, 0x1258, 1}, + {0x125a, 0x125d, 1}, + {0x1260, 0x1288, 1}, + {0x128a, 0x128d, 1}, + {0x1290, 0x12b0, 1}, + {0x12b2, 0x12b5, 1}, + {0x12b8, 0x12be, 1}, + {0x12c0, 0x12c0, 1}, + {0x12c2, 0x12c5, 1}, + {0x12c8, 0x12d6, 1}, + {0x12d8, 0x1310, 1}, + {0x1312, 0x1315, 1}, + {0x1318, 0x135a, 1}, + {0x135d, 0x137c, 1}, + {0x1380, 0x1399, 1}, + {0x2d80, 0x2d96, 1}, + {0x2da0, 0x2da6, 1}, + {0x2da8, 0x2dae, 1}, + {0x2db0, 0x2db6, 1}, + {0x2db8, 0x2dbe, 1}, + {0x2dc0, 0x2dc6, 1}, + {0x2dc8, 0x2dce, 1}, + {0x2dd0, 0x2dd6, 1}, + {0x2dd8, 0x2dde, 1}, + {0xab01, 0xab06, 1}, + {0xab09, 0xab0e, 1}, + {0xab11, 0xab16, 1}, + {0xab20, 0xab26, 1}, + {0xab28, 0xab2e, 1}, + }, +} + +var _Javanese = &RangeTable{ + R16: []Range16{ + {0xa980, 0xa9cd, 1}, + {0xa9cf, 0xa9d9, 1}, + {0xa9de, 0xa9df, 1}, + }, +} + +var _Syloti_Nagri = &RangeTable{ + R16: []Range16{ + {0xa800, 0xa82b, 1}, + }, +} + +var _Vai = &RangeTable{ + R16: []Range16{ + {0xa500, 0xa62b, 1}, + }, +} + +var _Cherokee = &RangeTable{ + R16: []Range16{ + {0x13a0, 0x13f4, 1}, + }, +} + +var _Ogham = &RangeTable{ + R16: []Range16{ + {0x1680, 0x169c, 1}, + }, +} + +var _Batak = &RangeTable{ + R16: []Range16{ + {0x1bc0, 0x1bf3, 1}, + {0x1bfc, 0x1bff, 1}, + }, +} + +var _Syriac = &RangeTable{ + R16: []Range16{ + {0x0700, 0x070d, 1}, + {0x070f, 0x074a, 1}, + {0x074d, 0x074f, 1}, + }, +} + +var _Gurmukhi = &RangeTable{ + R16: []Range16{ + {0x0a01, 0x0a03, 1}, + {0x0a05, 0x0a0a, 1}, + {0x0a0f, 0x0a10, 1}, + {0x0a13, 0x0a28, 1}, + {0x0a2a, 0x0a30, 1}, + {0x0a32, 0x0a33, 1}, + {0x0a35, 0x0a36, 1}, + {0x0a38, 0x0a39, 1}, + {0x0a3c, 0x0a3c, 1}, + {0x0a3e, 0x0a42, 1}, + {0x0a47, 0x0a48, 1}, + {0x0a4b, 0x0a4d, 1}, + {0x0a51, 0x0a51, 1}, + {0x0a59, 0x0a5c, 1}, + {0x0a5e, 0x0a5e, 1}, + {0x0a66, 0x0a75, 1}, + }, +} + +var _Tai_Tham = &RangeTable{ + R16: []Range16{ + {0x1a20, 0x1a5e, 1}, + {0x1a60, 0x1a7c, 1}, + {0x1a7f, 0x1a89, 1}, + {0x1a90, 0x1a99, 1}, + {0x1aa0, 0x1aad, 1}, + }, +} + +var _Ol_Chiki = &RangeTable{ + R16: []Range16{ + {0x1c50, 0x1c7f, 1}, + }, +} + +var _Mongolian = &RangeTable{ + R16: []Range16{ + {0x1800, 0x1801, 1}, + {0x1804, 0x1804, 1}, + {0x1806, 0x180e, 1}, + {0x1810, 0x1819, 1}, + {0x1820, 0x1877, 1}, + {0x1880, 0x18aa, 1}, + }, +} + +var _Hanunoo = &RangeTable{ + R16: []Range16{ + {0x1720, 0x1734, 1}, + }, +} + +var _Cypriot = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10800, 0x10805, 1}, + {0x10808, 0x10808, 1}, + {0x1080a, 0x10835, 1}, + {0x10837, 0x10838, 1}, + {0x1083c, 0x1083c, 1}, + {0x1083f, 0x1083f, 1}, + }, +} + +var _Buginese = &RangeTable{ + R16: []Range16{ + {0x1a00, 0x1a1b, 1}, + {0x1a1e, 0x1a1f, 1}, + }, +} + +var _Bamum = &RangeTable{ + R16: []Range16{ + {0xa6a0, 0xa6f7, 1}, + }, + R32: []Range32{ + {0x16800, 0x16a38, 1}, + }, +} + +var _Lepcha = &RangeTable{ + R16: []Range16{ + {0x1c00, 0x1c37, 1}, + {0x1c3b, 0x1c49, 1}, + {0x1c4d, 0x1c4f, 1}, + }, +} + +var _Thaana = &RangeTable{ + R16: []Range16{ + {0x0780, 0x07b1, 1}, + }, +} + +var _Old_Persian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x103a0, 0x103c3, 1}, + {0x103c8, 0x103d5, 1}, + }, +} + +var _Cuneiform = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x12000, 0x1236e, 1}, + {0x12400, 0x12462, 1}, + {0x12470, 0x12473, 1}, + }, +} + +var _Rejang = &RangeTable{ + R16: []Range16{ + {0xa930, 0xa953, 1}, + {0xa95f, 0xa95f, 1}, + }, +} + +var _Georgian = &RangeTable{ + R16: []Range16{ + {0x10a0, 0x10c5, 1}, + {0x10d0, 0x10fa, 1}, + {0x10fc, 0x10fc, 1}, + {0x2d00, 0x2d25, 1}, + }, +} + +var _Shavian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10450, 0x1047f, 1}, + }, +} + +var _Lycian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10280, 0x1029c, 1}, + }, +} + +var _Nko = &RangeTable{ + R16: []Range16{ + {0x07c0, 0x07fa, 1}, + }, +} + +var _Yi = &RangeTable{ + R16: []Range16{ + {0xa000, 0xa48c, 1}, + {0xa490, 0xa4c6, 1}, + }, +} + +var _Lao = &RangeTable{ + R16: []Range16{ + {0x0e81, 0x0e82, 1}, + {0x0e84, 0x0e84, 1}, + {0x0e87, 0x0e88, 1}, + {0x0e8a, 0x0e8a, 1}, + {0x0e8d, 0x0e8d, 1}, + {0x0e94, 0x0e97, 1}, + {0x0e99, 0x0e9f, 1}, + {0x0ea1, 0x0ea3, 1}, + {0x0ea5, 0x0ea5, 1}, + {0x0ea7, 0x0ea7, 1}, + {0x0eaa, 0x0eab, 1}, + {0x0ead, 0x0eb9, 1}, + {0x0ebb, 0x0ebd, 1}, + {0x0ec0, 0x0ec4, 1}, + {0x0ec6, 0x0ec6, 1}, + {0x0ec8, 0x0ecd, 1}, + {0x0ed0, 0x0ed9, 1}, + {0x0edc, 0x0edd, 1}, + }, +} + +var _Linear_B = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10000, 0x1000b, 1}, + {0x1000d, 0x10026, 1}, + {0x10028, 0x1003a, 1}, + {0x1003c, 0x1003d, 1}, + {0x1003f, 0x1004d, 1}, + {0x10050, 0x1005d, 1}, + {0x10080, 0x100fa, 1}, + }, +} + +var _Old_Italic = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10300, 0x1031e, 1}, + {0x10320, 0x10323, 1}, + }, +} + +var _Tai_Viet = &RangeTable{ + R16: []Range16{ + {0xaa80, 0xaac2, 1}, + {0xaadb, 0xaadf, 1}, + }, +} + +var _Devanagari = &RangeTable{ + R16: []Range16{ + {0x0900, 0x0950, 1}, + {0x0953, 0x0963, 1}, + {0x0966, 0x096f, 1}, + {0x0971, 0x0977, 1}, + {0x0979, 0x097f, 1}, + {0xa8e0, 0xa8fb, 1}, + }, +} + +var _Lydian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10920, 0x10939, 1}, + {0x1093f, 0x1093f, 1}, + }, +} + +var _Tifinagh = &RangeTable{ + R16: []Range16{ + {0x2d30, 0x2d65, 1}, + {0x2d6f, 0x2d70, 1}, + {0x2d7f, 0x2d7f, 1}, + }, +} + +var _Ugaritic = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10380, 0x1039d, 1}, + {0x1039f, 0x1039f, 1}, + }, +} + +var _Thai = &RangeTable{ + R16: []Range16{ + {0x0e01, 0x0e3a, 1}, + {0x0e40, 0x0e5b, 1}, + }, +} + +var _Cyrillic = &RangeTable{ + R16: []Range16{ + {0x0400, 0x0484, 1}, + {0x0487, 0x0527, 1}, + {0x1d2b, 0x1d2b, 1}, + {0x1d78, 0x1d78, 1}, + {0x2de0, 0x2dff, 1}, + {0xa640, 0xa673, 1}, + {0xa67c, 0xa697, 1}, + }, +} + +var _Gujarati = &RangeTable{ + R16: []Range16{ + {0x0a81, 0x0a83, 1}, + {0x0a85, 0x0a8d, 1}, + {0x0a8f, 0x0a91, 1}, + {0x0a93, 0x0aa8, 1}, + {0x0aaa, 0x0ab0, 1}, + {0x0ab2, 0x0ab3, 1}, + {0x0ab5, 0x0ab9, 1}, + {0x0abc, 0x0ac5, 1}, + {0x0ac7, 0x0ac9, 1}, + {0x0acb, 0x0acd, 1}, + {0x0ad0, 0x0ad0, 1}, + {0x0ae0, 0x0ae3, 1}, + {0x0ae6, 0x0aef, 1}, + {0x0af1, 0x0af1, 1}, + }, +} + +var _Carian = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x102a0, 0x102d0, 1}, + }, +} + +var _Phoenician = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10900, 0x1091b, 1}, + {0x1091f, 0x1091f, 1}, + }, +} + +var _Balinese = &RangeTable{ + R16: []Range16{ + {0x1b00, 0x1b4b, 1}, + {0x1b50, 0x1b7c, 1}, + }, +} + +var _Braille = &RangeTable{ + R16: []Range16{ + {0x2800, 0x28ff, 1}, + }, +} + +var _Han = &RangeTable{ + R16: []Range16{ + {0x2e80, 0x2e99, 1}, + {0x2e9b, 0x2ef3, 1}, + {0x2f00, 0x2fd5, 1}, + {0x3005, 0x3005, 1}, + {0x3007, 0x3007, 1}, + {0x3021, 0x3029, 1}, + {0x3038, 0x303b, 1}, + {0x3400, 0x4db5, 1}, + {0x4e00, 0x9fcb, 1}, + {0xf900, 0xfa2d, 1}, + {0xfa30, 0xfa6d, 1}, + {0xfa70, 0xfad9, 1}, + }, + R32: []Range32{ + {0x20000, 0x2a6d6, 1}, + {0x2a700, 0x2b734, 1}, + {0x2b740, 0x2b81d, 1}, + {0x2f800, 0x2fa1d, 1}, + }, +} + +var _Gothic = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10330, 0x1034a, 1}, + }, } var ( @@ -3188,7 +3509,7 @@ var ( // DO NOT EDIT // Properties is the set of Unicode property tables. -var Properties = map[string][]Range{ +var Properties = map[string]*RangeTable{ "Pattern_Syntax": Pattern_Syntax, "Other_ID_Start": Other_ID_Start, "Pattern_White_Space": Pattern_White_Space, @@ -3223,837 +3544,927 @@ var Properties = map[string][]Range{ "White_Space": White_Space, } -var _Pattern_Syntax = []Range{ - {0x0021, 0x002f, 1}, - {0x003a, 0x0040, 1}, - {0x005b, 0x005e, 1}, - {0x0060, 0x0060, 1}, - {0x007b, 0x007e, 1}, - {0x00a1, 0x00a7, 1}, - {0x00a9, 0x00a9, 1}, - {0x00ab, 0x00ac, 1}, - {0x00ae, 0x00ae, 1}, - {0x00b0, 0x00b1, 1}, - {0x00b6, 0x00b6, 1}, - {0x00bb, 0x00bb, 1}, - {0x00bf, 0x00bf, 1}, - {0x00d7, 0x00d7, 1}, - {0x00f7, 0x00f7, 1}, - {0x2010, 0x2027, 1}, - {0x2030, 0x203e, 1}, - {0x2041, 0x2053, 1}, - {0x2055, 0x205e, 1}, - {0x2190, 0x245f, 1}, - {0x2500, 0x2775, 1}, - {0x2794, 0x2bff, 1}, - {0x2e00, 0x2e7f, 1}, - {0x3001, 0x3003, 1}, - {0x3008, 0x3020, 1}, - {0x3030, 0x3030, 1}, - {0xfd3e, 0xfd3f, 1}, - {0xfe45, 0xfe46, 1}, -} - -var _Other_ID_Start = []Range{ - {0x2118, 0x2118, 1}, - {0x212e, 0x212e, 1}, - {0x309b, 0x309c, 1}, -} - -var _Pattern_White_Space = []Range{ - {0x0009, 0x000d, 1}, - {0x0020, 0x0020, 1}, - {0x0085, 0x0085, 1}, - {0x200e, 0x200f, 1}, - {0x2028, 0x2029, 1}, -} - -var _Other_Lowercase = []Range{ - {0x02b0, 0x02b8, 1}, - {0x02c0, 0x02c1, 1}, - {0x02e0, 0x02e4, 1}, - {0x0345, 0x0345, 1}, - {0x037a, 0x037a, 1}, - {0x1d2c, 0x1d61, 1}, - {0x1d78, 0x1d78, 1}, - {0x1d9b, 0x1dbf, 1}, - {0x2090, 0x2094, 1}, - {0x2170, 0x217f, 1}, - {0x24d0, 0x24e9, 1}, - {0x2c7d, 0x2c7d, 1}, - {0xa770, 0xa770, 1}, -} - -var _Soft_Dotted = []Range{ - {0x0069, 0x006a, 1}, - {0x012f, 0x012f, 1}, - {0x0249, 0x0249, 1}, - {0x0268, 0x0268, 1}, - {0x029d, 0x029d, 1}, - {0x02b2, 0x02b2, 1}, - {0x03f3, 0x03f3, 1}, - {0x0456, 0x0456, 1}, - {0x0458, 0x0458, 1}, - {0x1d62, 0x1d62, 1}, - {0x1d96, 0x1d96, 1}, - {0x1da4, 0x1da4, 1}, - {0x1da8, 0x1da8, 1}, - {0x1e2d, 0x1e2d, 1}, - {0x1ecb, 0x1ecb, 1}, - {0x2071, 0x2071, 1}, - {0x2148, 0x2149, 1}, - {0x2c7c, 0x2c7c, 1}, - {0x1d422, 0x1d423, 1}, - {0x1d456, 0x1d457, 1}, - {0x1d48a, 0x1d48b, 1}, - {0x1d4be, 0x1d4bf, 1}, - {0x1d4f2, 0x1d4f3, 1}, - {0x1d526, 0x1d527, 1}, - {0x1d55a, 0x1d55b, 1}, - {0x1d58e, 0x1d58f, 1}, - {0x1d5c2, 0x1d5c3, 1}, - {0x1d5f6, 0x1d5f7, 1}, - {0x1d62a, 0x1d62b, 1}, - {0x1d65e, 0x1d65f, 1}, - {0x1d692, 0x1d693, 1}, -} - -var _Hex_Digit = []Range{ - {0x0030, 0x0039, 1}, - {0x0041, 0x0046, 1}, - {0x0061, 0x0066, 1}, - {0xff10, 0xff19, 1}, - {0xff21, 0xff26, 1}, - {0xff41, 0xff46, 1}, -} - -var _ASCII_Hex_Digit = []Range{ - {0x0030, 0x0039, 1}, - {0x0041, 0x0046, 1}, - {0x0061, 0x0066, 1}, -} - -var _Deprecated = []Range{ - {0x0149, 0x0149, 1}, - {0x0673, 0x0673, 1}, - {0x0f77, 0x0f77, 1}, - {0x0f79, 0x0f79, 1}, - {0x17a3, 0x17a4, 1}, - {0x206a, 0x206f, 1}, - {0x2329, 0x232a, 1}, - {0xe0001, 0xe0001, 1}, - {0xe0020, 0xe007f, 1}, -} - -var _Terminal_Punctuation = []Range{ - {0x0021, 0x0021, 1}, - {0x002c, 0x002c, 1}, - {0x002e, 0x002e, 1}, - {0x003a, 0x003b, 1}, - {0x003f, 0x003f, 1}, - {0x037e, 0x037e, 1}, - {0x0387, 0x0387, 1}, - {0x0589, 0x0589, 1}, - {0x05c3, 0x05c3, 1}, - {0x060c, 0x060c, 1}, - {0x061b, 0x061b, 1}, - {0x061f, 0x061f, 1}, - {0x06d4, 0x06d4, 1}, - {0x0700, 0x070a, 1}, - {0x070c, 0x070c, 1}, - {0x07f8, 0x07f9, 1}, - {0x0830, 0x083e, 1}, - {0x085e, 0x085e, 1}, - {0x0964, 0x0965, 1}, - {0x0e5a, 0x0e5b, 1}, - {0x0f08, 0x0f08, 1}, - {0x0f0d, 0x0f12, 1}, - {0x104a, 0x104b, 1}, - {0x1361, 0x1368, 1}, - {0x166d, 0x166e, 1}, - {0x16eb, 0x16ed, 1}, - {0x17d4, 0x17d6, 1}, - {0x17da, 0x17da, 1}, - {0x1802, 0x1805, 1}, - {0x1808, 0x1809, 1}, - {0x1944, 0x1945, 1}, - {0x1aa8, 0x1aab, 1}, - {0x1b5a, 0x1b5b, 1}, - {0x1b5d, 0x1b5f, 1}, - {0x1c3b, 0x1c3f, 1}, - {0x1c7e, 0x1c7f, 1}, - {0x203c, 0x203d, 1}, - {0x2047, 0x2049, 1}, - {0x2e2e, 0x2e2e, 1}, - {0x3001, 0x3002, 1}, - {0xa4fe, 0xa4ff, 1}, - {0xa60d, 0xa60f, 1}, - {0xa6f3, 0xa6f7, 1}, - {0xa876, 0xa877, 1}, - {0xa8ce, 0xa8cf, 1}, - {0xa92f, 0xa92f, 1}, - {0xa9c7, 0xa9c9, 1}, - {0xaa5d, 0xaa5f, 1}, - {0xaadf, 0xaadf, 1}, - {0xabeb, 0xabeb, 1}, - {0xfe50, 0xfe52, 1}, - {0xfe54, 0xfe57, 1}, - {0xff01, 0xff01, 1}, - {0xff0c, 0xff0c, 1}, - {0xff0e, 0xff0e, 1}, - {0xff1a, 0xff1b, 1}, - {0xff1f, 0xff1f, 1}, - {0xff61, 0xff61, 1}, - {0xff64, 0xff64, 1}, - {0x1039f, 0x1039f, 1}, - {0x103d0, 0x103d0, 1}, - {0x10857, 0x10857, 1}, - {0x1091f, 0x1091f, 1}, - {0x10b3a, 0x10b3f, 1}, - {0x11047, 0x1104d, 1}, - {0x110be, 0x110c1, 1}, - {0x12470, 0x12473, 1}, -} - -var _Quotation_Mark = []Range{ - {0x0022, 0x0022, 1}, - {0x0027, 0x0027, 1}, - {0x00ab, 0x00ab, 1}, - {0x00bb, 0x00bb, 1}, - {0x2018, 0x201f, 1}, - {0x2039, 0x203a, 1}, - {0x300c, 0x300f, 1}, - {0x301d, 0x301f, 1}, - {0xfe41, 0xfe44, 1}, - {0xff02, 0xff02, 1}, - {0xff07, 0xff07, 1}, - {0xff62, 0xff63, 1}, -} - -var _Other_ID_Continue = []Range{ - {0x00b7, 0x00b7, 1}, - {0x0387, 0x0387, 1}, - {0x1369, 0x1371, 1}, - {0x19da, 0x19da, 1}, -} - -var _Bidi_Control = []Range{ - {0x200e, 0x200f, 1}, - {0x202a, 0x202e, 1}, -} - -var _Variation_Selector = []Range{ - {0x180b, 0x180d, 1}, - {0xfe00, 0xfe0f, 1}, - {0xe0100, 0xe01ef, 1}, -} - -var _Noncharacter_Code_Point = []Range{ - {0xfdd0, 0xfdef, 1}, - {0xfffe, 0xffff, 1}, - {0x1fffe, 0x1ffff, 1}, - {0x2fffe, 0x2ffff, 1}, - {0x3fffe, 0x3ffff, 1}, - {0x4fffe, 0x4ffff, 1}, - {0x5fffe, 0x5ffff, 1}, - {0x6fffe, 0x6ffff, 1}, - {0x7fffe, 0x7ffff, 1}, - {0x8fffe, 0x8ffff, 1}, - {0x9fffe, 0x9ffff, 1}, - {0xafffe, 0xaffff, 1}, - {0xbfffe, 0xbffff, 1}, - {0xcfffe, 0xcffff, 1}, - {0xdfffe, 0xdffff, 1}, - {0xefffe, 0xeffff, 1}, - {0xffffe, 0xfffff, 1}, - {0x10fffe, 0x10ffff, 1}, -} - -var _Other_Math = []Range{ - {0x005e, 0x005e, 1}, - {0x03d0, 0x03d2, 1}, - {0x03d5, 0x03d5, 1}, - {0x03f0, 0x03f1, 1}, - {0x03f4, 0x03f5, 1}, - {0x2016, 0x2016, 1}, - {0x2032, 0x2034, 1}, - {0x2040, 0x2040, 1}, - {0x2061, 0x2064, 1}, - {0x207d, 0x207e, 1}, - {0x208d, 0x208e, 1}, - {0x20d0, 0x20dc, 1}, - {0x20e1, 0x20e1, 1}, - {0x20e5, 0x20e6, 1}, - {0x20eb, 0x20ef, 1}, - {0x2102, 0x2102, 1}, - {0x2107, 0x2107, 1}, - {0x210a, 0x2113, 1}, - {0x2115, 0x2115, 1}, - {0x2119, 0x211d, 1}, - {0x2124, 0x2124, 1}, - {0x2128, 0x2129, 1}, - {0x212c, 0x212d, 1}, - {0x212f, 0x2131, 1}, - {0x2133, 0x2138, 1}, - {0x213c, 0x213f, 1}, - {0x2145, 0x2149, 1}, - {0x2195, 0x2199, 1}, - {0x219c, 0x219f, 1}, - {0x21a1, 0x21a2, 1}, - {0x21a4, 0x21a5, 1}, - {0x21a7, 0x21a7, 1}, - {0x21a9, 0x21ad, 1}, - {0x21b0, 0x21b1, 1}, - {0x21b6, 0x21b7, 1}, - {0x21bc, 0x21cd, 1}, - {0x21d0, 0x21d1, 1}, - {0x21d3, 0x21d3, 1}, - {0x21d5, 0x21db, 1}, - {0x21dd, 0x21dd, 1}, - {0x21e4, 0x21e5, 1}, - {0x23b4, 0x23b5, 1}, - {0x23b7, 0x23b7, 1}, - {0x23d0, 0x23d0, 1}, - {0x23e2, 0x23e2, 1}, - {0x25a0, 0x25a1, 1}, - {0x25ae, 0x25b6, 1}, - {0x25bc, 0x25c0, 1}, - {0x25c6, 0x25c7, 1}, - {0x25ca, 0x25cb, 1}, - {0x25cf, 0x25d3, 1}, - {0x25e2, 0x25e2, 1}, - {0x25e4, 0x25e4, 1}, - {0x25e7, 0x25ec, 1}, - {0x2605, 0x2606, 1}, - {0x2640, 0x2640, 1}, - {0x2642, 0x2642, 1}, - {0x2660, 0x2663, 1}, - {0x266d, 0x266e, 1}, - {0x27c5, 0x27c6, 1}, - {0x27e6, 0x27ef, 1}, - {0x2983, 0x2998, 1}, - {0x29d8, 0x29db, 1}, - {0x29fc, 0x29fd, 1}, - {0xfe61, 0xfe61, 1}, - {0xfe63, 0xfe63, 1}, - {0xfe68, 0xfe68, 1}, - {0xff3c, 0xff3c, 1}, - {0xff3e, 0xff3e, 1}, - {0x1d400, 0x1d454, 1}, - {0x1d456, 0x1d49c, 1}, - {0x1d49e, 0x1d49f, 1}, - {0x1d4a2, 0x1d4a2, 1}, - {0x1d4a5, 0x1d4a6, 1}, - {0x1d4a9, 0x1d4ac, 1}, - {0x1d4ae, 0x1d4b9, 1}, - {0x1d4bb, 0x1d4bb, 1}, - {0x1d4bd, 0x1d4c3, 1}, - {0x1d4c5, 0x1d505, 1}, - {0x1d507, 0x1d50a, 1}, - {0x1d50d, 0x1d514, 1}, - {0x1d516, 0x1d51c, 1}, - {0x1d51e, 0x1d539, 1}, - {0x1d53b, 0x1d53e, 1}, - {0x1d540, 0x1d544, 1}, - {0x1d546, 0x1d546, 1}, - {0x1d54a, 0x1d550, 1}, - {0x1d552, 0x1d6a5, 1}, - {0x1d6a8, 0x1d6c0, 1}, - {0x1d6c2, 0x1d6da, 1}, - {0x1d6dc, 0x1d6fa, 1}, - {0x1d6fc, 0x1d714, 1}, - {0x1d716, 0x1d734, 1}, - {0x1d736, 0x1d74e, 1}, - {0x1d750, 0x1d76e, 1}, - {0x1d770, 0x1d788, 1}, - {0x1d78a, 0x1d7a8, 1}, - {0x1d7aa, 0x1d7c2, 1}, - {0x1d7c4, 0x1d7cb, 1}, - {0x1d7ce, 0x1d7ff, 1}, -} - -var _Unified_Ideograph = []Range{ - {0x3400, 0x4db5, 1}, - {0x4e00, 0x9fcb, 1}, - {0xfa0e, 0xfa0f, 1}, - {0xfa11, 0xfa11, 1}, - {0xfa13, 0xfa14, 1}, - {0xfa1f, 0xfa1f, 1}, - {0xfa21, 0xfa21, 1}, - {0xfa23, 0xfa24, 1}, - {0xfa27, 0xfa29, 1}, - {0x20000, 0x2a6d6, 1}, - {0x2a700, 0x2b734, 1}, - {0x2b740, 0x2b81d, 1}, -} - -var _Hyphen = []Range{ - {0x002d, 0x002d, 1}, - {0x00ad, 0x00ad, 1}, - {0x058a, 0x058a, 1}, - {0x1806, 0x1806, 1}, - {0x2010, 0x2011, 1}, - {0x2e17, 0x2e17, 1}, - {0x30fb, 0x30fb, 1}, - {0xfe63, 0xfe63, 1}, - {0xff0d, 0xff0d, 1}, - {0xff65, 0xff65, 1}, -} - -var _IDS_Binary_Operator = []Range{ - {0x2ff0, 0x2ff1, 1}, - {0x2ff4, 0x2ffb, 1}, -} - -var _Logical_Order_Exception = []Range{ - {0x0e40, 0x0e44, 1}, - {0x0ec0, 0x0ec4, 1}, - {0xaab5, 0xaab6, 1}, - {0xaab9, 0xaab9, 1}, - {0xaabb, 0xaabc, 1}, -} - -var _Radical = []Range{ - {0x2e80, 0x2e99, 1}, - {0x2e9b, 0x2ef3, 1}, - {0x2f00, 0x2fd5, 1}, -} - -var _Other_Uppercase = []Range{ - {0x2160, 0x216f, 1}, - {0x24b6, 0x24cf, 1}, -} - -var _STerm = []Range{ - {0x0021, 0x0021, 1}, - {0x002e, 0x002e, 1}, - {0x003f, 0x003f, 1}, - {0x055c, 0x055c, 1}, - {0x055e, 0x055e, 1}, - {0x0589, 0x0589, 1}, - {0x061f, 0x061f, 1}, - {0x06d4, 0x06d4, 1}, - {0x0700, 0x0702, 1}, - {0x07f9, 0x07f9, 1}, - {0x0964, 0x0965, 1}, - {0x104a, 0x104b, 1}, - {0x1362, 0x1362, 1}, - {0x1367, 0x1368, 1}, - {0x166e, 0x166e, 1}, - {0x1735, 0x1736, 1}, - {0x1803, 0x1803, 1}, - {0x1809, 0x1809, 1}, - {0x1944, 0x1945, 1}, - {0x1aa8, 0x1aab, 1}, - {0x1b5a, 0x1b5b, 1}, - {0x1b5e, 0x1b5f, 1}, - {0x1c3b, 0x1c3c, 1}, - {0x1c7e, 0x1c7f, 1}, - {0x203c, 0x203d, 1}, - {0x2047, 0x2049, 1}, - {0x2e2e, 0x2e2e, 1}, - {0x3002, 0x3002, 1}, - {0xa4ff, 0xa4ff, 1}, - {0xa60e, 0xa60f, 1}, - {0xa6f3, 0xa6f3, 1}, - {0xa6f7, 0xa6f7, 1}, - {0xa876, 0xa877, 1}, - {0xa8ce, 0xa8cf, 1}, - {0xa92f, 0xa92f, 1}, - {0xa9c8, 0xa9c9, 1}, - {0xaa5d, 0xaa5f, 1}, - {0xabeb, 0xabeb, 1}, - {0xfe52, 0xfe52, 1}, - {0xfe56, 0xfe57, 1}, - {0xff01, 0xff01, 1}, - {0xff0e, 0xff0e, 1}, - {0xff1f, 0xff1f, 1}, - {0xff61, 0xff61, 1}, - {0x10a56, 0x10a57, 1}, - {0x11047, 0x11048, 1}, - {0x110be, 0x110c1, 1}, -} - -var _Other_Alphabetic = []Range{ - {0x0345, 0x0345, 1}, - {0x05b0, 0x05bd, 1}, - {0x05bf, 0x05bf, 1}, - {0x05c1, 0x05c2, 1}, - {0x05c4, 0x05c5, 1}, - {0x05c7, 0x05c7, 1}, - {0x0610, 0x061a, 1}, - {0x064b, 0x0657, 1}, - {0x0659, 0x065f, 1}, - {0x0670, 0x0670, 1}, - {0x06d6, 0x06dc, 1}, - {0x06e1, 0x06e4, 1}, - {0x06e7, 0x06e8, 1}, - {0x06ed, 0x06ed, 1}, - {0x0711, 0x0711, 1}, - {0x0730, 0x073f, 1}, - {0x07a6, 0x07b0, 1}, - {0x0816, 0x0817, 1}, - {0x081b, 0x0823, 1}, - {0x0825, 0x0827, 1}, - {0x0829, 0x082c, 1}, - {0x0900, 0x0903, 1}, - {0x093a, 0x093b, 1}, - {0x093e, 0x094c, 1}, - {0x094e, 0x094f, 1}, - {0x0955, 0x0957, 1}, - {0x0962, 0x0963, 1}, - {0x0981, 0x0983, 1}, - {0x09be, 0x09c4, 1}, - {0x09c7, 0x09c8, 1}, - {0x09cb, 0x09cc, 1}, - {0x09d7, 0x09d7, 1}, - {0x09e2, 0x09e3, 1}, - {0x0a01, 0x0a03, 1}, - {0x0a3e, 0x0a42, 1}, - {0x0a47, 0x0a48, 1}, - {0x0a4b, 0x0a4c, 1}, - {0x0a51, 0x0a51, 1}, - {0x0a70, 0x0a71, 1}, - {0x0a75, 0x0a75, 1}, - {0x0a81, 0x0a83, 1}, - {0x0abe, 0x0ac5, 1}, - {0x0ac7, 0x0ac9, 1}, - {0x0acb, 0x0acc, 1}, - {0x0ae2, 0x0ae3, 1}, - {0x0b01, 0x0b03, 1}, - {0x0b3e, 0x0b44, 1}, - {0x0b47, 0x0b48, 1}, - {0x0b4b, 0x0b4c, 1}, - {0x0b56, 0x0b57, 1}, - {0x0b62, 0x0b63, 1}, - {0x0b82, 0x0b82, 1}, - {0x0bbe, 0x0bc2, 1}, - {0x0bc6, 0x0bc8, 1}, - {0x0bca, 0x0bcc, 1}, - {0x0bd7, 0x0bd7, 1}, - {0x0c01, 0x0c03, 1}, - {0x0c3e, 0x0c44, 1}, - {0x0c46, 0x0c48, 1}, - {0x0c4a, 0x0c4c, 1}, - {0x0c55, 0x0c56, 1}, - {0x0c62, 0x0c63, 1}, - {0x0c82, 0x0c83, 1}, - {0x0cbe, 0x0cc4, 1}, - {0x0cc6, 0x0cc8, 1}, - {0x0cca, 0x0ccc, 1}, - {0x0cd5, 0x0cd6, 1}, - {0x0ce2, 0x0ce3, 1}, - {0x0d02, 0x0d03, 1}, - {0x0d3e, 0x0d44, 1}, - {0x0d46, 0x0d48, 1}, - {0x0d4a, 0x0d4c, 1}, - {0x0d57, 0x0d57, 1}, - {0x0d62, 0x0d63, 1}, - {0x0d82, 0x0d83, 1}, - {0x0dcf, 0x0dd4, 1}, - {0x0dd6, 0x0dd6, 1}, - {0x0dd8, 0x0ddf, 1}, - {0x0df2, 0x0df3, 1}, - {0x0e31, 0x0e31, 1}, - {0x0e34, 0x0e3a, 1}, - {0x0e4d, 0x0e4d, 1}, - {0x0eb1, 0x0eb1, 1}, - {0x0eb4, 0x0eb9, 1}, - {0x0ebb, 0x0ebc, 1}, - {0x0ecd, 0x0ecd, 1}, - {0x0f71, 0x0f81, 1}, - {0x0f8d, 0x0f97, 1}, - {0x0f99, 0x0fbc, 1}, - {0x102b, 0x1036, 1}, - {0x1038, 0x1038, 1}, - {0x103b, 0x103e, 1}, - {0x1056, 0x1059, 1}, - {0x105e, 0x1060, 1}, - {0x1062, 0x1062, 1}, - {0x1067, 0x1068, 1}, - {0x1071, 0x1074, 1}, - {0x1082, 0x1086, 1}, - {0x109c, 0x109d, 1}, - {0x135f, 0x135f, 1}, - {0x1712, 0x1713, 1}, - {0x1732, 0x1733, 1}, - {0x1752, 0x1753, 1}, - {0x1772, 0x1773, 1}, - {0x17b6, 0x17c8, 1}, - {0x18a9, 0x18a9, 1}, - {0x1920, 0x192b, 1}, - {0x1930, 0x1938, 1}, - {0x19b0, 0x19c0, 1}, - {0x19c8, 0x19c9, 1}, - {0x1a17, 0x1a1b, 1}, - {0x1a55, 0x1a5e, 1}, - {0x1a61, 0x1a74, 1}, - {0x1b00, 0x1b04, 1}, - {0x1b35, 0x1b43, 1}, - {0x1b80, 0x1b82, 1}, - {0x1ba1, 0x1ba9, 1}, - {0x1be7, 0x1bf1, 1}, - {0x1c24, 0x1c35, 1}, - {0x1cf2, 0x1cf2, 1}, - {0x24b6, 0x24e9, 1}, - {0x2de0, 0x2dff, 1}, - {0xa823, 0xa827, 1}, - {0xa880, 0xa881, 1}, - {0xa8b4, 0xa8c3, 1}, - {0xa926, 0xa92a, 1}, - {0xa947, 0xa952, 1}, - {0xa980, 0xa983, 1}, - {0xa9b4, 0xa9bf, 1}, - {0xaa29, 0xaa36, 1}, - {0xaa43, 0xaa43, 1}, - {0xaa4c, 0xaa4d, 1}, - {0xaab0, 0xaab0, 1}, - {0xaab2, 0xaab4, 1}, - {0xaab7, 0xaab8, 1}, - {0xaabe, 0xaabe, 1}, - {0xabe3, 0xabea, 1}, - {0xfb1e, 0xfb1e, 1}, - {0x10a01, 0x10a03, 1}, - {0x10a05, 0x10a06, 1}, - {0x10a0c, 0x10a0f, 1}, - {0x11000, 0x11002, 1}, - {0x11038, 0x11045, 1}, - {0x11082, 0x11082, 1}, - {0x110b0, 0x110b8, 1}, -} - -var _Diacritic = []Range{ - {0x005e, 0x005e, 1}, - {0x0060, 0x0060, 1}, - {0x00a8, 0x00a8, 1}, - {0x00af, 0x00af, 1}, - {0x00b4, 0x00b4, 1}, - {0x00b7, 0x00b8, 1}, - {0x02b0, 0x034e, 1}, - {0x0350, 0x0357, 1}, - {0x035d, 0x0362, 1}, - {0x0374, 0x0375, 1}, - {0x037a, 0x037a, 1}, - {0x0384, 0x0385, 1}, - {0x0483, 0x0487, 1}, - {0x0559, 0x0559, 1}, - {0x0591, 0x05a1, 1}, - {0x05a3, 0x05bd, 1}, - {0x05bf, 0x05bf, 1}, - {0x05c1, 0x05c2, 1}, - {0x05c4, 0x05c4, 1}, - {0x064b, 0x0652, 1}, - {0x0657, 0x0658, 1}, - {0x06df, 0x06e0, 1}, - {0x06e5, 0x06e6, 1}, - {0x06ea, 0x06ec, 1}, - {0x0730, 0x074a, 1}, - {0x07a6, 0x07b0, 1}, - {0x07eb, 0x07f5, 1}, - {0x0818, 0x0819, 1}, - {0x093c, 0x093c, 1}, - {0x094d, 0x094d, 1}, - {0x0951, 0x0954, 1}, - {0x0971, 0x0971, 1}, - {0x09bc, 0x09bc, 1}, - {0x09cd, 0x09cd, 1}, - {0x0a3c, 0x0a3c, 1}, - {0x0a4d, 0x0a4d, 1}, - {0x0abc, 0x0abc, 1}, - {0x0acd, 0x0acd, 1}, - {0x0b3c, 0x0b3c, 1}, - {0x0b4d, 0x0b4d, 1}, - {0x0bcd, 0x0bcd, 1}, - {0x0c4d, 0x0c4d, 1}, - {0x0cbc, 0x0cbc, 1}, - {0x0ccd, 0x0ccd, 1}, - {0x0d4d, 0x0d4d, 1}, - {0x0dca, 0x0dca, 1}, - {0x0e47, 0x0e4c, 1}, - {0x0e4e, 0x0e4e, 1}, - {0x0ec8, 0x0ecc, 1}, - {0x0f18, 0x0f19, 1}, - {0x0f35, 0x0f35, 1}, - {0x0f37, 0x0f37, 1}, - {0x0f39, 0x0f39, 1}, - {0x0f3e, 0x0f3f, 1}, - {0x0f82, 0x0f84, 1}, - {0x0f86, 0x0f87, 1}, - {0x0fc6, 0x0fc6, 1}, - {0x1037, 0x1037, 1}, - {0x1039, 0x103a, 1}, - {0x1087, 0x108d, 1}, - {0x108f, 0x108f, 1}, - {0x109a, 0x109b, 1}, - {0x17c9, 0x17d3, 1}, - {0x17dd, 0x17dd, 1}, - {0x1939, 0x193b, 1}, - {0x1a75, 0x1a7c, 1}, - {0x1a7f, 0x1a7f, 1}, - {0x1b34, 0x1b34, 1}, - {0x1b44, 0x1b44, 1}, - {0x1b6b, 0x1b73, 1}, - {0x1baa, 0x1baa, 1}, - {0x1c36, 0x1c37, 1}, - {0x1c78, 0x1c7d, 1}, - {0x1cd0, 0x1ce8, 1}, - {0x1ced, 0x1ced, 1}, - {0x1d2c, 0x1d6a, 1}, - {0x1dc4, 0x1dcf, 1}, - {0x1dfd, 0x1dff, 1}, - {0x1fbd, 0x1fbd, 1}, - {0x1fbf, 0x1fc1, 1}, - {0x1fcd, 0x1fcf, 1}, - {0x1fdd, 0x1fdf, 1}, - {0x1fed, 0x1fef, 1}, - {0x1ffd, 0x1ffe, 1}, - {0x2cef, 0x2cf1, 1}, - {0x2e2f, 0x2e2f, 1}, - {0x302a, 0x302f, 1}, - {0x3099, 0x309c, 1}, - {0x30fc, 0x30fc, 1}, - {0xa66f, 0xa66f, 1}, - {0xa67c, 0xa67d, 1}, - {0xa67f, 0xa67f, 1}, - {0xa6f0, 0xa6f1, 1}, - {0xa717, 0xa721, 1}, - {0xa788, 0xa788, 1}, - {0xa8c4, 0xa8c4, 1}, - {0xa8e0, 0xa8f1, 1}, - {0xa92b, 0xa92e, 1}, - {0xa953, 0xa953, 1}, - {0xa9b3, 0xa9b3, 1}, - {0xa9c0, 0xa9c0, 1}, - {0xaa7b, 0xaa7b, 1}, - {0xaabf, 0xaac2, 1}, - {0xabec, 0xabed, 1}, - {0xfb1e, 0xfb1e, 1}, - {0xfe20, 0xfe26, 1}, - {0xff3e, 0xff3e, 1}, - {0xff40, 0xff40, 1}, - {0xff70, 0xff70, 1}, - {0xff9e, 0xff9f, 1}, - {0xffe3, 0xffe3, 1}, - {0x110b9, 0x110ba, 1}, - {0x1d167, 0x1d169, 1}, - {0x1d16d, 0x1d172, 1}, - {0x1d17b, 0x1d182, 1}, - {0x1d185, 0x1d18b, 1}, - {0x1d1aa, 0x1d1ad, 1}, -} - -var _Extender = []Range{ - {0x00b7, 0x00b7, 1}, - {0x02d0, 0x02d1, 1}, - {0x0640, 0x0640, 1}, - {0x07fa, 0x07fa, 1}, - {0x0e46, 0x0e46, 1}, - {0x0ec6, 0x0ec6, 1}, - {0x1843, 0x1843, 1}, - {0x1aa7, 0x1aa7, 1}, - {0x1c36, 0x1c36, 1}, - {0x1c7b, 0x1c7b, 1}, - {0x3005, 0x3005, 1}, - {0x3031, 0x3035, 1}, - {0x309d, 0x309e, 1}, - {0x30fc, 0x30fe, 1}, - {0xa015, 0xa015, 1}, - {0xa60c, 0xa60c, 1}, - {0xa9cf, 0xa9cf, 1}, - {0xaa70, 0xaa70, 1}, - {0xaadd, 0xaadd, 1}, - {0xff70, 0xff70, 1}, -} - -var _Join_Control = []Range{ - {0x200c, 0x200d, 1}, -} - -var _Ideographic = []Range{ - {0x3006, 0x3007, 1}, - {0x3021, 0x3029, 1}, - {0x3038, 0x303a, 1}, - {0x3400, 0x4db5, 1}, - {0x4e00, 0x9fcb, 1}, - {0xf900, 0xfa2d, 1}, - {0xfa30, 0xfa6d, 1}, - {0xfa70, 0xfad9, 1}, - {0x20000, 0x2a6d6, 1}, - {0x2a700, 0x2b734, 1}, - {0x2b740, 0x2b81d, 1}, - {0x2f800, 0x2fa1d, 1}, -} - -var _Dash = []Range{ - {0x002d, 0x002d, 1}, - {0x058a, 0x058a, 1}, - {0x05be, 0x05be, 1}, - {0x1400, 0x1400, 1}, - {0x1806, 0x1806, 1}, - {0x2010, 0x2015, 1}, - {0x2053, 0x2053, 1}, - {0x207b, 0x207b, 1}, - {0x208b, 0x208b, 1}, - {0x2212, 0x2212, 1}, - {0x2e17, 0x2e17, 1}, - {0x2e1a, 0x2e1a, 1}, - {0x301c, 0x301c, 1}, - {0x3030, 0x3030, 1}, - {0x30a0, 0x30a0, 1}, - {0xfe31, 0xfe32, 1}, - {0xfe58, 0xfe58, 1}, - {0xfe63, 0xfe63, 1}, - {0xff0d, 0xff0d, 1}, -} - -var _IDS_Trinary_Operator = []Range{ - {0x2ff2, 0x2ff3, 1}, -} - -var _Other_Grapheme_Extend = []Range{ - {0x09be, 0x09be, 1}, - {0x09d7, 0x09d7, 1}, - {0x0b3e, 0x0b3e, 1}, - {0x0b57, 0x0b57, 1}, - {0x0bbe, 0x0bbe, 1}, - {0x0bd7, 0x0bd7, 1}, - {0x0cc2, 0x0cc2, 1}, - {0x0cd5, 0x0cd6, 1}, - {0x0d3e, 0x0d3e, 1}, - {0x0d57, 0x0d57, 1}, - {0x0dcf, 0x0dcf, 1}, - {0x0ddf, 0x0ddf, 1}, - {0x200c, 0x200d, 1}, - {0xff9e, 0xff9f, 1}, - {0x1d165, 0x1d165, 1}, - {0x1d16e, 0x1d172, 1}, -} - -var _Other_Default_Ignorable_Code_Point = []Range{ - {0x034f, 0x034f, 1}, - {0x115f, 0x1160, 1}, - {0x2065, 0x2069, 1}, - {0x3164, 0x3164, 1}, - {0xffa0, 0xffa0, 1}, - {0xfff0, 0xfff8, 1}, - {0xe0000, 0xe0000, 1}, - {0xe0002, 0xe001f, 1}, - {0xe0080, 0xe00ff, 1}, - {0xe01f0, 0xe0fff, 1}, -} - -var _White_Space = []Range{ - {0x0009, 0x000d, 1}, - {0x0020, 0x0020, 1}, - {0x0085, 0x0085, 1}, - {0x00a0, 0x00a0, 1}, - {0x1680, 0x1680, 1}, - {0x180e, 0x180e, 1}, - {0x2000, 0x200a, 1}, - {0x2028, 0x2029, 1}, - {0x202f, 0x202f, 1}, - {0x205f, 0x205f, 1}, - {0x3000, 0x3000, 1}, +var _Pattern_Syntax = &RangeTable{ + R16: []Range16{ + {0x0021, 0x002f, 1}, + {0x003a, 0x0040, 1}, + {0x005b, 0x005e, 1}, + {0x0060, 0x0060, 1}, + {0x007b, 0x007e, 1}, + {0x00a1, 0x00a7, 1}, + {0x00a9, 0x00a9, 1}, + {0x00ab, 0x00ac, 1}, + {0x00ae, 0x00ae, 1}, + {0x00b0, 0x00b1, 1}, + {0x00b6, 0x00b6, 1}, + {0x00bb, 0x00bb, 1}, + {0x00bf, 0x00bf, 1}, + {0x00d7, 0x00d7, 1}, + {0x00f7, 0x00f7, 1}, + {0x2010, 0x2027, 1}, + {0x2030, 0x203e, 1}, + {0x2041, 0x2053, 1}, + {0x2055, 0x205e, 1}, + {0x2190, 0x245f, 1}, + {0x2500, 0x2775, 1}, + {0x2794, 0x2bff, 1}, + {0x2e00, 0x2e7f, 1}, + {0x3001, 0x3003, 1}, + {0x3008, 0x3020, 1}, + {0x3030, 0x3030, 1}, + {0xfd3e, 0xfd3f, 1}, + {0xfe45, 0xfe46, 1}, + }, +} + +var _Other_ID_Start = &RangeTable{ + R16: []Range16{ + {0x2118, 0x2118, 1}, + {0x212e, 0x212e, 1}, + {0x309b, 0x309c, 1}, + }, +} + +var _Pattern_White_Space = &RangeTable{ + R16: []Range16{ + {0x0009, 0x000d, 1}, + {0x0020, 0x0020, 1}, + {0x0085, 0x0085, 1}, + {0x200e, 0x200f, 1}, + {0x2028, 0x2029, 1}, + }, +} + +var _Other_Lowercase = &RangeTable{ + R16: []Range16{ + {0x02b0, 0x02b8, 1}, + {0x02c0, 0x02c1, 1}, + {0x02e0, 0x02e4, 1}, + {0x0345, 0x0345, 1}, + {0x037a, 0x037a, 1}, + {0x1d2c, 0x1d61, 1}, + {0x1d78, 0x1d78, 1}, + {0x1d9b, 0x1dbf, 1}, + {0x2090, 0x2094, 1}, + {0x2170, 0x217f, 1}, + {0x24d0, 0x24e9, 1}, + {0x2c7d, 0x2c7d, 1}, + {0xa770, 0xa770, 1}, + }, +} + +var _Soft_Dotted = &RangeTable{ + R16: []Range16{ + {0x0069, 0x006a, 1}, + {0x012f, 0x012f, 1}, + {0x0249, 0x0249, 1}, + {0x0268, 0x0268, 1}, + {0x029d, 0x029d, 1}, + {0x02b2, 0x02b2, 1}, + {0x03f3, 0x03f3, 1}, + {0x0456, 0x0456, 1}, + {0x0458, 0x0458, 1}, + {0x1d62, 0x1d62, 1}, + {0x1d96, 0x1d96, 1}, + {0x1da4, 0x1da4, 1}, + {0x1da8, 0x1da8, 1}, + {0x1e2d, 0x1e2d, 1}, + {0x1ecb, 0x1ecb, 1}, + {0x2071, 0x2071, 1}, + {0x2148, 0x2149, 1}, + {0x2c7c, 0x2c7c, 1}, + }, + R32: []Range32{ + {0x1d422, 0x1d423, 1}, + {0x1d456, 0x1d457, 1}, + {0x1d48a, 0x1d48b, 1}, + {0x1d4be, 0x1d4bf, 1}, + {0x1d4f2, 0x1d4f3, 1}, + {0x1d526, 0x1d527, 1}, + {0x1d55a, 0x1d55b, 1}, + {0x1d58e, 0x1d58f, 1}, + {0x1d5c2, 0x1d5c3, 1}, + {0x1d5f6, 0x1d5f7, 1}, + {0x1d62a, 0x1d62b, 1}, + {0x1d65e, 0x1d65f, 1}, + {0x1d692, 0x1d693, 1}, + }, +} + +var _Hex_Digit = &RangeTable{ + R16: []Range16{ + {0x0030, 0x0039, 1}, + {0x0041, 0x0046, 1}, + {0x0061, 0x0066, 1}, + {0xff10, 0xff19, 1}, + {0xff21, 0xff26, 1}, + {0xff41, 0xff46, 1}, + }, +} + +var _ASCII_Hex_Digit = &RangeTable{ + R16: []Range16{ + {0x0030, 0x0039, 1}, + {0x0041, 0x0046, 1}, + {0x0061, 0x0066, 1}, + }, +} + +var _Deprecated = &RangeTable{ + R16: []Range16{ + {0x0149, 0x0149, 1}, + {0x0673, 0x0673, 1}, + {0x0f77, 0x0f77, 1}, + {0x0f79, 0x0f79, 1}, + {0x17a3, 0x17a4, 1}, + {0x206a, 0x206f, 1}, + {0x2329, 0x232a, 1}, + }, + R32: []Range32{ + {0xe0001, 0xe0001, 1}, + {0xe0020, 0xe007f, 1}, + }, +} + +var _Terminal_Punctuation = &RangeTable{ + R16: []Range16{ + {0x0021, 0x0021, 1}, + {0x002c, 0x002c, 1}, + {0x002e, 0x002e, 1}, + {0x003a, 0x003b, 1}, + {0x003f, 0x003f, 1}, + {0x037e, 0x037e, 1}, + {0x0387, 0x0387, 1}, + {0x0589, 0x0589, 1}, + {0x05c3, 0x05c3, 1}, + {0x060c, 0x060c, 1}, + {0x061b, 0x061b, 1}, + {0x061f, 0x061f, 1}, + {0x06d4, 0x06d4, 1}, + {0x0700, 0x070a, 1}, + {0x070c, 0x070c, 1}, + {0x07f8, 0x07f9, 1}, + {0x0830, 0x083e, 1}, + {0x085e, 0x085e, 1}, + {0x0964, 0x0965, 1}, + {0x0e5a, 0x0e5b, 1}, + {0x0f08, 0x0f08, 1}, + {0x0f0d, 0x0f12, 1}, + {0x104a, 0x104b, 1}, + {0x1361, 0x1368, 1}, + {0x166d, 0x166e, 1}, + {0x16eb, 0x16ed, 1}, + {0x17d4, 0x17d6, 1}, + {0x17da, 0x17da, 1}, + {0x1802, 0x1805, 1}, + {0x1808, 0x1809, 1}, + {0x1944, 0x1945, 1}, + {0x1aa8, 0x1aab, 1}, + {0x1b5a, 0x1b5b, 1}, + {0x1b5d, 0x1b5f, 1}, + {0x1c3b, 0x1c3f, 1}, + {0x1c7e, 0x1c7f, 1}, + {0x203c, 0x203d, 1}, + {0x2047, 0x2049, 1}, + {0x2e2e, 0x2e2e, 1}, + {0x3001, 0x3002, 1}, + {0xa4fe, 0xa4ff, 1}, + {0xa60d, 0xa60f, 1}, + {0xa6f3, 0xa6f7, 1}, + {0xa876, 0xa877, 1}, + {0xa8ce, 0xa8cf, 1}, + {0xa92f, 0xa92f, 1}, + {0xa9c7, 0xa9c9, 1}, + {0xaa5d, 0xaa5f, 1}, + {0xaadf, 0xaadf, 1}, + {0xabeb, 0xabeb, 1}, + {0xfe50, 0xfe52, 1}, + {0xfe54, 0xfe57, 1}, + {0xff01, 0xff01, 1}, + {0xff0c, 0xff0c, 1}, + {0xff0e, 0xff0e, 1}, + {0xff1a, 0xff1b, 1}, + {0xff1f, 0xff1f, 1}, + {0xff61, 0xff61, 1}, + {0xff64, 0xff64, 1}, + }, + R32: []Range32{ + {0x1039f, 0x1039f, 1}, + {0x103d0, 0x103d0, 1}, + {0x10857, 0x10857, 1}, + {0x1091f, 0x1091f, 1}, + {0x10b3a, 0x10b3f, 1}, + {0x11047, 0x1104d, 1}, + {0x110be, 0x110c1, 1}, + {0x12470, 0x12473, 1}, + }, +} + +var _Quotation_Mark = &RangeTable{ + R16: []Range16{ + {0x0022, 0x0022, 1}, + {0x0027, 0x0027, 1}, + {0x00ab, 0x00ab, 1}, + {0x00bb, 0x00bb, 1}, + {0x2018, 0x201f, 1}, + {0x2039, 0x203a, 1}, + {0x300c, 0x300f, 1}, + {0x301d, 0x301f, 1}, + {0xfe41, 0xfe44, 1}, + {0xff02, 0xff02, 1}, + {0xff07, 0xff07, 1}, + {0xff62, 0xff63, 1}, + }, +} + +var _Other_ID_Continue = &RangeTable{ + R16: []Range16{ + {0x00b7, 0x00b7, 1}, + {0x0387, 0x0387, 1}, + {0x1369, 0x1371, 1}, + {0x19da, 0x19da, 1}, + }, +} + +var _Bidi_Control = &RangeTable{ + R16: []Range16{ + {0x200e, 0x200f, 1}, + {0x202a, 0x202e, 1}, + }, +} + +var _Variation_Selector = &RangeTable{ + R16: []Range16{ + {0x180b, 0x180d, 1}, + {0xfe00, 0xfe0f, 1}, + }, + R32: []Range32{ + {0xe0100, 0xe01ef, 1}, + }, +} + +var _Noncharacter_Code_Point = &RangeTable{ + R16: []Range16{ + {0xfdd0, 0xfdef, 1}, + {0xfffe, 0xffff, 1}, + }, + R32: []Range32{ + {0x1fffe, 0x1ffff, 1}, + {0x2fffe, 0x2ffff, 1}, + {0x3fffe, 0x3ffff, 1}, + {0x4fffe, 0x4ffff, 1}, + {0x5fffe, 0x5ffff, 1}, + {0x6fffe, 0x6ffff, 1}, + {0x7fffe, 0x7ffff, 1}, + {0x8fffe, 0x8ffff, 1}, + {0x9fffe, 0x9ffff, 1}, + {0xafffe, 0xaffff, 1}, + {0xbfffe, 0xbffff, 1}, + {0xcfffe, 0xcffff, 1}, + {0xdfffe, 0xdffff, 1}, + {0xefffe, 0xeffff, 1}, + {0xffffe, 0xfffff, 1}, + {0x10fffe, 0x10ffff, 1}, + }, +} + +var _Other_Math = &RangeTable{ + R16: []Range16{ + {0x005e, 0x005e, 1}, + {0x03d0, 0x03d2, 1}, + {0x03d5, 0x03d5, 1}, + {0x03f0, 0x03f1, 1}, + {0x03f4, 0x03f5, 1}, + {0x2016, 0x2016, 1}, + {0x2032, 0x2034, 1}, + {0x2040, 0x2040, 1}, + {0x2061, 0x2064, 1}, + {0x207d, 0x207e, 1}, + {0x208d, 0x208e, 1}, + {0x20d0, 0x20dc, 1}, + {0x20e1, 0x20e1, 1}, + {0x20e5, 0x20e6, 1}, + {0x20eb, 0x20ef, 1}, + {0x2102, 0x2102, 1}, + {0x2107, 0x2107, 1}, + {0x210a, 0x2113, 1}, + {0x2115, 0x2115, 1}, + {0x2119, 0x211d, 1}, + {0x2124, 0x2124, 1}, + {0x2128, 0x2129, 1}, + {0x212c, 0x212d, 1}, + {0x212f, 0x2131, 1}, + {0x2133, 0x2138, 1}, + {0x213c, 0x213f, 1}, + {0x2145, 0x2149, 1}, + {0x2195, 0x2199, 1}, + {0x219c, 0x219f, 1}, + {0x21a1, 0x21a2, 1}, + {0x21a4, 0x21a5, 1}, + {0x21a7, 0x21a7, 1}, + {0x21a9, 0x21ad, 1}, + {0x21b0, 0x21b1, 1}, + {0x21b6, 0x21b7, 1}, + {0x21bc, 0x21cd, 1}, + {0x21d0, 0x21d1, 1}, + {0x21d3, 0x21d3, 1}, + {0x21d5, 0x21db, 1}, + {0x21dd, 0x21dd, 1}, + {0x21e4, 0x21e5, 1}, + {0x23b4, 0x23b5, 1}, + {0x23b7, 0x23b7, 1}, + {0x23d0, 0x23d0, 1}, + {0x23e2, 0x23e2, 1}, + {0x25a0, 0x25a1, 1}, + {0x25ae, 0x25b6, 1}, + {0x25bc, 0x25c0, 1}, + {0x25c6, 0x25c7, 1}, + {0x25ca, 0x25cb, 1}, + {0x25cf, 0x25d3, 1}, + {0x25e2, 0x25e2, 1}, + {0x25e4, 0x25e4, 1}, + {0x25e7, 0x25ec, 1}, + {0x2605, 0x2606, 1}, + {0x2640, 0x2640, 1}, + {0x2642, 0x2642, 1}, + {0x2660, 0x2663, 1}, + {0x266d, 0x266e, 1}, + {0x27c5, 0x27c6, 1}, + {0x27e6, 0x27ef, 1}, + {0x2983, 0x2998, 1}, + {0x29d8, 0x29db, 1}, + {0x29fc, 0x29fd, 1}, + {0xfe61, 0xfe61, 1}, + {0xfe63, 0xfe63, 1}, + {0xfe68, 0xfe68, 1}, + {0xff3c, 0xff3c, 1}, + {0xff3e, 0xff3e, 1}, + }, + R32: []Range32{ + {0x1d400, 0x1d454, 1}, + {0x1d456, 0x1d49c, 1}, + {0x1d49e, 0x1d49f, 1}, + {0x1d4a2, 0x1d4a2, 1}, + {0x1d4a5, 0x1d4a6, 1}, + {0x1d4a9, 0x1d4ac, 1}, + {0x1d4ae, 0x1d4b9, 1}, + {0x1d4bb, 0x1d4bb, 1}, + {0x1d4bd, 0x1d4c3, 1}, + {0x1d4c5, 0x1d505, 1}, + {0x1d507, 0x1d50a, 1}, + {0x1d50d, 0x1d514, 1}, + {0x1d516, 0x1d51c, 1}, + {0x1d51e, 0x1d539, 1}, + {0x1d53b, 0x1d53e, 1}, + {0x1d540, 0x1d544, 1}, + {0x1d546, 0x1d546, 1}, + {0x1d54a, 0x1d550, 1}, + {0x1d552, 0x1d6a5, 1}, + {0x1d6a8, 0x1d6c0, 1}, + {0x1d6c2, 0x1d6da, 1}, + {0x1d6dc, 0x1d6fa, 1}, + {0x1d6fc, 0x1d714, 1}, + {0x1d716, 0x1d734, 1}, + {0x1d736, 0x1d74e, 1}, + {0x1d750, 0x1d76e, 1}, + {0x1d770, 0x1d788, 1}, + {0x1d78a, 0x1d7a8, 1}, + {0x1d7aa, 0x1d7c2, 1}, + {0x1d7c4, 0x1d7cb, 1}, + {0x1d7ce, 0x1d7ff, 1}, + }, +} + +var _Unified_Ideograph = &RangeTable{ + R16: []Range16{ + {0x3400, 0x4db5, 1}, + {0x4e00, 0x9fcb, 1}, + {0xfa0e, 0xfa0f, 1}, + {0xfa11, 0xfa11, 1}, + {0xfa13, 0xfa14, 1}, + {0xfa1f, 0xfa1f, 1}, + {0xfa21, 0xfa21, 1}, + {0xfa23, 0xfa24, 1}, + {0xfa27, 0xfa29, 1}, + }, + R32: []Range32{ + {0x20000, 0x2a6d6, 1}, + {0x2a700, 0x2b734, 1}, + {0x2b740, 0x2b81d, 1}, + }, +} + +var _Hyphen = &RangeTable{ + R16: []Range16{ + {0x002d, 0x002d, 1}, + {0x00ad, 0x00ad, 1}, + {0x058a, 0x058a, 1}, + {0x1806, 0x1806, 1}, + {0x2010, 0x2011, 1}, + {0x2e17, 0x2e17, 1}, + {0x30fb, 0x30fb, 1}, + {0xfe63, 0xfe63, 1}, + {0xff0d, 0xff0d, 1}, + {0xff65, 0xff65, 1}, + }, +} + +var _IDS_Binary_Operator = &RangeTable{ + R16: []Range16{ + {0x2ff0, 0x2ff1, 1}, + {0x2ff4, 0x2ffb, 1}, + }, +} + +var _Logical_Order_Exception = &RangeTable{ + R16: []Range16{ + {0x0e40, 0x0e44, 1}, + {0x0ec0, 0x0ec4, 1}, + {0xaab5, 0xaab6, 1}, + {0xaab9, 0xaab9, 1}, + {0xaabb, 0xaabc, 1}, + }, +} + +var _Radical = &RangeTable{ + R16: []Range16{ + {0x2e80, 0x2e99, 1}, + {0x2e9b, 0x2ef3, 1}, + {0x2f00, 0x2fd5, 1}, + }, +} + +var _Other_Uppercase = &RangeTable{ + R16: []Range16{ + {0x2160, 0x216f, 1}, + {0x24b6, 0x24cf, 1}, + }, +} + +var _STerm = &RangeTable{ + R16: []Range16{ + {0x0021, 0x0021, 1}, + {0x002e, 0x002e, 1}, + {0x003f, 0x003f, 1}, + {0x055c, 0x055c, 1}, + {0x055e, 0x055e, 1}, + {0x0589, 0x0589, 1}, + {0x061f, 0x061f, 1}, + {0x06d4, 0x06d4, 1}, + {0x0700, 0x0702, 1}, + {0x07f9, 0x07f9, 1}, + {0x0964, 0x0965, 1}, + {0x104a, 0x104b, 1}, + {0x1362, 0x1362, 1}, + {0x1367, 0x1368, 1}, + {0x166e, 0x166e, 1}, + {0x1735, 0x1736, 1}, + {0x1803, 0x1803, 1}, + {0x1809, 0x1809, 1}, + {0x1944, 0x1945, 1}, + {0x1aa8, 0x1aab, 1}, + {0x1b5a, 0x1b5b, 1}, + {0x1b5e, 0x1b5f, 1}, + {0x1c3b, 0x1c3c, 1}, + {0x1c7e, 0x1c7f, 1}, + {0x203c, 0x203d, 1}, + {0x2047, 0x2049, 1}, + {0x2e2e, 0x2e2e, 1}, + {0x3002, 0x3002, 1}, + {0xa4ff, 0xa4ff, 1}, + {0xa60e, 0xa60f, 1}, + {0xa6f3, 0xa6f3, 1}, + {0xa6f7, 0xa6f7, 1}, + {0xa876, 0xa877, 1}, + {0xa8ce, 0xa8cf, 1}, + {0xa92f, 0xa92f, 1}, + {0xa9c8, 0xa9c9, 1}, + {0xaa5d, 0xaa5f, 1}, + {0xabeb, 0xabeb, 1}, + {0xfe52, 0xfe52, 1}, + {0xfe56, 0xfe57, 1}, + {0xff01, 0xff01, 1}, + {0xff0e, 0xff0e, 1}, + {0xff1f, 0xff1f, 1}, + {0xff61, 0xff61, 1}, + }, + R32: []Range32{ + {0x10a56, 0x10a57, 1}, + {0x11047, 0x11048, 1}, + {0x110be, 0x110c1, 1}, + }, +} + +var _Other_Alphabetic = &RangeTable{ + R16: []Range16{ + {0x0345, 0x0345, 1}, + {0x05b0, 0x05bd, 1}, + {0x05bf, 0x05bf, 1}, + {0x05c1, 0x05c2, 1}, + {0x05c4, 0x05c5, 1}, + {0x05c7, 0x05c7, 1}, + {0x0610, 0x061a, 1}, + {0x064b, 0x0657, 1}, + {0x0659, 0x065f, 1}, + {0x0670, 0x0670, 1}, + {0x06d6, 0x06dc, 1}, + {0x06e1, 0x06e4, 1}, + {0x06e7, 0x06e8, 1}, + {0x06ed, 0x06ed, 1}, + {0x0711, 0x0711, 1}, + {0x0730, 0x073f, 1}, + {0x07a6, 0x07b0, 1}, + {0x0816, 0x0817, 1}, + {0x081b, 0x0823, 1}, + {0x0825, 0x0827, 1}, + {0x0829, 0x082c, 1}, + {0x0900, 0x0903, 1}, + {0x093a, 0x093b, 1}, + {0x093e, 0x094c, 1}, + {0x094e, 0x094f, 1}, + {0x0955, 0x0957, 1}, + {0x0962, 0x0963, 1}, + {0x0981, 0x0983, 1}, + {0x09be, 0x09c4, 1}, + {0x09c7, 0x09c8, 1}, + {0x09cb, 0x09cc, 1}, + {0x09d7, 0x09d7, 1}, + {0x09e2, 0x09e3, 1}, + {0x0a01, 0x0a03, 1}, + {0x0a3e, 0x0a42, 1}, + {0x0a47, 0x0a48, 1}, + {0x0a4b, 0x0a4c, 1}, + {0x0a51, 0x0a51, 1}, + {0x0a70, 0x0a71, 1}, + {0x0a75, 0x0a75, 1}, + {0x0a81, 0x0a83, 1}, + {0x0abe, 0x0ac5, 1}, + {0x0ac7, 0x0ac9, 1}, + {0x0acb, 0x0acc, 1}, + {0x0ae2, 0x0ae3, 1}, + {0x0b01, 0x0b03, 1}, + {0x0b3e, 0x0b44, 1}, + {0x0b47, 0x0b48, 1}, + {0x0b4b, 0x0b4c, 1}, + {0x0b56, 0x0b57, 1}, + {0x0b62, 0x0b63, 1}, + {0x0b82, 0x0b82, 1}, + {0x0bbe, 0x0bc2, 1}, + {0x0bc6, 0x0bc8, 1}, + {0x0bca, 0x0bcc, 1}, + {0x0bd7, 0x0bd7, 1}, + {0x0c01, 0x0c03, 1}, + {0x0c3e, 0x0c44, 1}, + {0x0c46, 0x0c48, 1}, + {0x0c4a, 0x0c4c, 1}, + {0x0c55, 0x0c56, 1}, + {0x0c62, 0x0c63, 1}, + {0x0c82, 0x0c83, 1}, + {0x0cbe, 0x0cc4, 1}, + {0x0cc6, 0x0cc8, 1}, + {0x0cca, 0x0ccc, 1}, + {0x0cd5, 0x0cd6, 1}, + {0x0ce2, 0x0ce3, 1}, + {0x0d02, 0x0d03, 1}, + {0x0d3e, 0x0d44, 1}, + {0x0d46, 0x0d48, 1}, + {0x0d4a, 0x0d4c, 1}, + {0x0d57, 0x0d57, 1}, + {0x0d62, 0x0d63, 1}, + {0x0d82, 0x0d83, 1}, + {0x0dcf, 0x0dd4, 1}, + {0x0dd6, 0x0dd6, 1}, + {0x0dd8, 0x0ddf, 1}, + {0x0df2, 0x0df3, 1}, + {0x0e31, 0x0e31, 1}, + {0x0e34, 0x0e3a, 1}, + {0x0e4d, 0x0e4d, 1}, + {0x0eb1, 0x0eb1, 1}, + {0x0eb4, 0x0eb9, 1}, + {0x0ebb, 0x0ebc, 1}, + {0x0ecd, 0x0ecd, 1}, + {0x0f71, 0x0f81, 1}, + {0x0f8d, 0x0f97, 1}, + {0x0f99, 0x0fbc, 1}, + {0x102b, 0x1036, 1}, + {0x1038, 0x1038, 1}, + {0x103b, 0x103e, 1}, + {0x1056, 0x1059, 1}, + {0x105e, 0x1060, 1}, + {0x1062, 0x1062, 1}, + {0x1067, 0x1068, 1}, + {0x1071, 0x1074, 1}, + {0x1082, 0x1086, 1}, + {0x109c, 0x109d, 1}, + {0x135f, 0x135f, 1}, + {0x1712, 0x1713, 1}, + {0x1732, 0x1733, 1}, + {0x1752, 0x1753, 1}, + {0x1772, 0x1773, 1}, + {0x17b6, 0x17c8, 1}, + {0x18a9, 0x18a9, 1}, + {0x1920, 0x192b, 1}, + {0x1930, 0x1938, 1}, + {0x19b0, 0x19c0, 1}, + {0x19c8, 0x19c9, 1}, + {0x1a17, 0x1a1b, 1}, + {0x1a55, 0x1a5e, 1}, + {0x1a61, 0x1a74, 1}, + {0x1b00, 0x1b04, 1}, + {0x1b35, 0x1b43, 1}, + {0x1b80, 0x1b82, 1}, + {0x1ba1, 0x1ba9, 1}, + {0x1be7, 0x1bf1, 1}, + {0x1c24, 0x1c35, 1}, + {0x1cf2, 0x1cf2, 1}, + {0x24b6, 0x24e9, 1}, + {0x2de0, 0x2dff, 1}, + {0xa823, 0xa827, 1}, + {0xa880, 0xa881, 1}, + {0xa8b4, 0xa8c3, 1}, + {0xa926, 0xa92a, 1}, + {0xa947, 0xa952, 1}, + {0xa980, 0xa983, 1}, + {0xa9b4, 0xa9bf, 1}, + {0xaa29, 0xaa36, 1}, + {0xaa43, 0xaa43, 1}, + {0xaa4c, 0xaa4d, 1}, + {0xaab0, 0xaab0, 1}, + {0xaab2, 0xaab4, 1}, + {0xaab7, 0xaab8, 1}, + {0xaabe, 0xaabe, 1}, + {0xabe3, 0xabea, 1}, + {0xfb1e, 0xfb1e, 1}, + }, + R32: []Range32{ + {0x10a01, 0x10a03, 1}, + {0x10a05, 0x10a06, 1}, + {0x10a0c, 0x10a0f, 1}, + {0x11000, 0x11002, 1}, + {0x11038, 0x11045, 1}, + {0x11082, 0x11082, 1}, + {0x110b0, 0x110b8, 1}, + }, +} + +var _Diacritic = &RangeTable{ + R16: []Range16{ + {0x005e, 0x005e, 1}, + {0x0060, 0x0060, 1}, + {0x00a8, 0x00a8, 1}, + {0x00af, 0x00af, 1}, + {0x00b4, 0x00b4, 1}, + {0x00b7, 0x00b8, 1}, + {0x02b0, 0x034e, 1}, + {0x0350, 0x0357, 1}, + {0x035d, 0x0362, 1}, + {0x0374, 0x0375, 1}, + {0x037a, 0x037a, 1}, + {0x0384, 0x0385, 1}, + {0x0483, 0x0487, 1}, + {0x0559, 0x0559, 1}, + {0x0591, 0x05a1, 1}, + {0x05a3, 0x05bd, 1}, + {0x05bf, 0x05bf, 1}, + {0x05c1, 0x05c2, 1}, + {0x05c4, 0x05c4, 1}, + {0x064b, 0x0652, 1}, + {0x0657, 0x0658, 1}, + {0x06df, 0x06e0, 1}, + {0x06e5, 0x06e6, 1}, + {0x06ea, 0x06ec, 1}, + {0x0730, 0x074a, 1}, + {0x07a6, 0x07b0, 1}, + {0x07eb, 0x07f5, 1}, + {0x0818, 0x0819, 1}, + {0x093c, 0x093c, 1}, + {0x094d, 0x094d, 1}, + {0x0951, 0x0954, 1}, + {0x0971, 0x0971, 1}, + {0x09bc, 0x09bc, 1}, + {0x09cd, 0x09cd, 1}, + {0x0a3c, 0x0a3c, 1}, + {0x0a4d, 0x0a4d, 1}, + {0x0abc, 0x0abc, 1}, + {0x0acd, 0x0acd, 1}, + {0x0b3c, 0x0b3c, 1}, + {0x0b4d, 0x0b4d, 1}, + {0x0bcd, 0x0bcd, 1}, + {0x0c4d, 0x0c4d, 1}, + {0x0cbc, 0x0cbc, 1}, + {0x0ccd, 0x0ccd, 1}, + {0x0d4d, 0x0d4d, 1}, + {0x0dca, 0x0dca, 1}, + {0x0e47, 0x0e4c, 1}, + {0x0e4e, 0x0e4e, 1}, + {0x0ec8, 0x0ecc, 1}, + {0x0f18, 0x0f19, 1}, + {0x0f35, 0x0f35, 1}, + {0x0f37, 0x0f37, 1}, + {0x0f39, 0x0f39, 1}, + {0x0f3e, 0x0f3f, 1}, + {0x0f82, 0x0f84, 1}, + {0x0f86, 0x0f87, 1}, + {0x0fc6, 0x0fc6, 1}, + {0x1037, 0x1037, 1}, + {0x1039, 0x103a, 1}, + {0x1087, 0x108d, 1}, + {0x108f, 0x108f, 1}, + {0x109a, 0x109b, 1}, + {0x17c9, 0x17d3, 1}, + {0x17dd, 0x17dd, 1}, + {0x1939, 0x193b, 1}, + {0x1a75, 0x1a7c, 1}, + {0x1a7f, 0x1a7f, 1}, + {0x1b34, 0x1b34, 1}, + {0x1b44, 0x1b44, 1}, + {0x1b6b, 0x1b73, 1}, + {0x1baa, 0x1baa, 1}, + {0x1c36, 0x1c37, 1}, + {0x1c78, 0x1c7d, 1}, + {0x1cd0, 0x1ce8, 1}, + {0x1ced, 0x1ced, 1}, + {0x1d2c, 0x1d6a, 1}, + {0x1dc4, 0x1dcf, 1}, + {0x1dfd, 0x1dff, 1}, + {0x1fbd, 0x1fbd, 1}, + {0x1fbf, 0x1fc1, 1}, + {0x1fcd, 0x1fcf, 1}, + {0x1fdd, 0x1fdf, 1}, + {0x1fed, 0x1fef, 1}, + {0x1ffd, 0x1ffe, 1}, + {0x2cef, 0x2cf1, 1}, + {0x2e2f, 0x2e2f, 1}, + {0x302a, 0x302f, 1}, + {0x3099, 0x309c, 1}, + {0x30fc, 0x30fc, 1}, + {0xa66f, 0xa66f, 1}, + {0xa67c, 0xa67d, 1}, + {0xa67f, 0xa67f, 1}, + {0xa6f0, 0xa6f1, 1}, + {0xa717, 0xa721, 1}, + {0xa788, 0xa788, 1}, + {0xa8c4, 0xa8c4, 1}, + {0xa8e0, 0xa8f1, 1}, + {0xa92b, 0xa92e, 1}, + {0xa953, 0xa953, 1}, + {0xa9b3, 0xa9b3, 1}, + {0xa9c0, 0xa9c0, 1}, + {0xaa7b, 0xaa7b, 1}, + {0xaabf, 0xaac2, 1}, + {0xabec, 0xabed, 1}, + {0xfb1e, 0xfb1e, 1}, + {0xfe20, 0xfe26, 1}, + {0xff3e, 0xff3e, 1}, + {0xff40, 0xff40, 1}, + {0xff70, 0xff70, 1}, + {0xff9e, 0xff9f, 1}, + {0xffe3, 0xffe3, 1}, + }, + R32: []Range32{ + {0x110b9, 0x110ba, 1}, + {0x1d167, 0x1d169, 1}, + {0x1d16d, 0x1d172, 1}, + {0x1d17b, 0x1d182, 1}, + {0x1d185, 0x1d18b, 1}, + {0x1d1aa, 0x1d1ad, 1}, + }, +} + +var _Extender = &RangeTable{ + R16: []Range16{ + {0x00b7, 0x00b7, 1}, + {0x02d0, 0x02d1, 1}, + {0x0640, 0x0640, 1}, + {0x07fa, 0x07fa, 1}, + {0x0e46, 0x0e46, 1}, + {0x0ec6, 0x0ec6, 1}, + {0x1843, 0x1843, 1}, + {0x1aa7, 0x1aa7, 1}, + {0x1c36, 0x1c36, 1}, + {0x1c7b, 0x1c7b, 1}, + {0x3005, 0x3005, 1}, + {0x3031, 0x3035, 1}, + {0x309d, 0x309e, 1}, + {0x30fc, 0x30fe, 1}, + {0xa015, 0xa015, 1}, + {0xa60c, 0xa60c, 1}, + {0xa9cf, 0xa9cf, 1}, + {0xaa70, 0xaa70, 1}, + {0xaadd, 0xaadd, 1}, + {0xff70, 0xff70, 1}, + }, +} + +var _Join_Control = &RangeTable{ + R16: []Range16{ + {0x200c, 0x200d, 1}, + }, +} + +var _Ideographic = &RangeTable{ + R16: []Range16{ + {0x3006, 0x3007, 1}, + {0x3021, 0x3029, 1}, + {0x3038, 0x303a, 1}, + {0x3400, 0x4db5, 1}, + {0x4e00, 0x9fcb, 1}, + {0xf900, 0xfa2d, 1}, + {0xfa30, 0xfa6d, 1}, + {0xfa70, 0xfad9, 1}, + }, + R32: []Range32{ + {0x20000, 0x2a6d6, 1}, + {0x2a700, 0x2b734, 1}, + {0x2b740, 0x2b81d, 1}, + {0x2f800, 0x2fa1d, 1}, + }, +} + +var _Dash = &RangeTable{ + R16: []Range16{ + {0x002d, 0x002d, 1}, + {0x058a, 0x058a, 1}, + {0x05be, 0x05be, 1}, + {0x1400, 0x1400, 1}, + {0x1806, 0x1806, 1}, + {0x2010, 0x2015, 1}, + {0x2053, 0x2053, 1}, + {0x207b, 0x207b, 1}, + {0x208b, 0x208b, 1}, + {0x2212, 0x2212, 1}, + {0x2e17, 0x2e17, 1}, + {0x2e1a, 0x2e1a, 1}, + {0x301c, 0x301c, 1}, + {0x3030, 0x3030, 1}, + {0x30a0, 0x30a0, 1}, + {0xfe31, 0xfe32, 1}, + {0xfe58, 0xfe58, 1}, + {0xfe63, 0xfe63, 1}, + {0xff0d, 0xff0d, 1}, + }, +} + +var _IDS_Trinary_Operator = &RangeTable{ + R16: []Range16{ + {0x2ff2, 0x2ff3, 1}, + }, +} + +var _Other_Grapheme_Extend = &RangeTable{ + R16: []Range16{ + {0x09be, 0x09be, 1}, + {0x09d7, 0x09d7, 1}, + {0x0b3e, 0x0b3e, 1}, + {0x0b57, 0x0b57, 1}, + {0x0bbe, 0x0bbe, 1}, + {0x0bd7, 0x0bd7, 1}, + {0x0cc2, 0x0cc2, 1}, + {0x0cd5, 0x0cd6, 1}, + {0x0d3e, 0x0d3e, 1}, + {0x0d57, 0x0d57, 1}, + {0x0dcf, 0x0dcf, 1}, + {0x0ddf, 0x0ddf, 1}, + {0x200c, 0x200d, 1}, + {0xff9e, 0xff9f, 1}, + }, + R32: []Range32{ + {0x1d165, 0x1d165, 1}, + {0x1d16e, 0x1d172, 1}, + }, +} + +var _Other_Default_Ignorable_Code_Point = &RangeTable{ + R16: []Range16{ + {0x034f, 0x034f, 1}, + {0x115f, 0x1160, 1}, + {0x2065, 0x2069, 1}, + {0x3164, 0x3164, 1}, + {0xffa0, 0xffa0, 1}, + {0xfff0, 0xfff8, 1}, + }, + R32: []Range32{ + {0xe0000, 0xe0000, 1}, + {0xe0002, 0xe001f, 1}, + {0xe0080, 0xe00ff, 1}, + {0xe01f0, 0xe0fff, 1}, + }, +} + +var _White_Space = &RangeTable{ + R16: []Range16{ + {0x0009, 0x000d, 1}, + {0x0020, 0x0020, 1}, + {0x0085, 0x0085, 1}, + {0x00a0, 0x00a0, 1}, + {0x1680, 0x1680, 1}, + {0x180e, 0x180e, 1}, + {0x2000, 0x200a, 1}, + {0x2028, 0x2029, 1}, + {0x202f, 0x202f, 1}, + {0x205f, 0x205f, 1}, + {0x3000, 0x3000, 1}, + }, } var ( @@ -4353,3 +4764,6 @@ var _CaseRanges = []CaseRange{ {0x10400, 0x10427, d{0, 40, 0}}, {0x10428, 0x1044F, d{-40, 0, -40}}, } + +// Range entries: 2715 16-bit, 545 32-bit, 3260 total. +// Range bytes: 16290 16-bit, 6540 32-bit, 22830 total. diff --git a/src/pkg/websocket/client.go b/src/pkg/websocket/client.go index 3712c2d1b..e28382196 100644 --- a/src/pkg/websocket/client.go +++ b/src/pkg/websocket/client.go @@ -29,7 +29,7 @@ var ( ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"} ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"} ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"} - ErrChallengeResponse = &ProtocolError{"mismatch challange/response"} + ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"} secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte ) @@ -226,7 +226,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio. // Step 25. send CRLF. bw.WriteString("\r\n") - // Step 26. genearte 8 bytes random key. + // Step 26. generate 8 bytes random key. key3 := generateKey3() // Step 27. send it out. bw.Write(key3) @@ -262,7 +262,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio. return ErrBadWebSocketProtocol } - // Step 42-43. get expected data from challange data. + // Step 42-43. get expected data from challenge data. expected, err := getChallengeResponse(number1, number2, key3) if err != nil { return err @@ -283,7 +283,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio. } /* -Handhake described in (soon obsolete) +Handshake described in (soon obsolete) draft-hixie-thewebsocket-protocol-75. */ func draft75handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) { diff --git a/src/pkg/websocket/server.go b/src/pkg/websocket/server.go index 376265236..165cbffee 100644 --- a/src/pkg/websocket/server.go +++ b/src/pkg/websocket/server.go @@ -124,7 +124,7 @@ func (f Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { part1 := keyNumber1 / space1 part2 := keyNumber2 / space2 - // Step 8. let challenge to be concatination of part1, part2 and key3. + // Step 8. let challenge be concatenation of part1, part2 and key3. // Step 9. get MD5 fingerprint of challenge. response, err := getChallengeResponse(part1, part2, key3) if err != nil { diff --git a/src/pkg/websocket/websocket.go b/src/pkg/websocket/websocket.go index edde61b4a..7447cf852 100644 --- a/src/pkg/websocket/websocket.go +++ b/src/pkg/websocket/websocket.go @@ -158,7 +158,7 @@ func (ws *Conn) SetReadTimeout(nsec int64) os.Error { return os.EINVAL } -// SetWritetTimeout sets the connection's network write timeout in nanoseconds. +// SetWriteTimeout sets the connection's network write timeout in nanoseconds. func (ws *Conn) SetWriteTimeout(nsec int64) os.Error { if conn, ok := ws.rwc.(net.Conn); ok { return conn.SetWriteTimeout(nsec) diff --git a/src/pkg/xml/xml.go b/src/pkg/xml/xml.go index 42d8b986e..2cebbce75 100644 --- a/src/pkg/xml/xml.go +++ b/src/pkg/xml/xml.go @@ -1028,312 +1028,316 @@ func isNameByte(c byte) bool { // and then reformatting. First corresponds to (Letter | '_' | ':') // and second corresponds to NameChar. -var first = []unicode.Range{ - {0x003A, 0x003A, 1}, - {0x0041, 0x005A, 1}, - {0x005F, 0x005F, 1}, - {0x0061, 0x007A, 1}, - {0x00C0, 0x00D6, 1}, - {0x00D8, 0x00F6, 1}, - {0x00F8, 0x00FF, 1}, - {0x0100, 0x0131, 1}, - {0x0134, 0x013E, 1}, - {0x0141, 0x0148, 1}, - {0x014A, 0x017E, 1}, - {0x0180, 0x01C3, 1}, - {0x01CD, 0x01F0, 1}, - {0x01F4, 0x01F5, 1}, - {0x01FA, 0x0217, 1}, - {0x0250, 0x02A8, 1}, - {0x02BB, 0x02C1, 1}, - {0x0386, 0x0386, 1}, - {0x0388, 0x038A, 1}, - {0x038C, 0x038C, 1}, - {0x038E, 0x03A1, 1}, - {0x03A3, 0x03CE, 1}, - {0x03D0, 0x03D6, 1}, - {0x03DA, 0x03E0, 2}, - {0x03E2, 0x03F3, 1}, - {0x0401, 0x040C, 1}, - {0x040E, 0x044F, 1}, - {0x0451, 0x045C, 1}, - {0x045E, 0x0481, 1}, - {0x0490, 0x04C4, 1}, - {0x04C7, 0x04C8, 1}, - {0x04CB, 0x04CC, 1}, - {0x04D0, 0x04EB, 1}, - {0x04EE, 0x04F5, 1}, - {0x04F8, 0x04F9, 1}, - {0x0531, 0x0556, 1}, - {0x0559, 0x0559, 1}, - {0x0561, 0x0586, 1}, - {0x05D0, 0x05EA, 1}, - {0x05F0, 0x05F2, 1}, - {0x0621, 0x063A, 1}, - {0x0641, 0x064A, 1}, - {0x0671, 0x06B7, 1}, - {0x06BA, 0x06BE, 1}, - {0x06C0, 0x06CE, 1}, - {0x06D0, 0x06D3, 1}, - {0x06D5, 0x06D5, 1}, - {0x06E5, 0x06E6, 1}, - {0x0905, 0x0939, 1}, - {0x093D, 0x093D, 1}, - {0x0958, 0x0961, 1}, - {0x0985, 0x098C, 1}, - {0x098F, 0x0990, 1}, - {0x0993, 0x09A8, 1}, - {0x09AA, 0x09B0, 1}, - {0x09B2, 0x09B2, 1}, - {0x09B6, 0x09B9, 1}, - {0x09DC, 0x09DD, 1}, - {0x09DF, 0x09E1, 1}, - {0x09F0, 0x09F1, 1}, - {0x0A05, 0x0A0A, 1}, - {0x0A0F, 0x0A10, 1}, - {0x0A13, 0x0A28, 1}, - {0x0A2A, 0x0A30, 1}, - {0x0A32, 0x0A33, 1}, - {0x0A35, 0x0A36, 1}, - {0x0A38, 0x0A39, 1}, - {0x0A59, 0x0A5C, 1}, - {0x0A5E, 0x0A5E, 1}, - {0x0A72, 0x0A74, 1}, - {0x0A85, 0x0A8B, 1}, - {0x0A8D, 0x0A8D, 1}, - {0x0A8F, 0x0A91, 1}, - {0x0A93, 0x0AA8, 1}, - {0x0AAA, 0x0AB0, 1}, - {0x0AB2, 0x0AB3, 1}, - {0x0AB5, 0x0AB9, 1}, - {0x0ABD, 0x0AE0, 0x23}, - {0x0B05, 0x0B0C, 1}, - {0x0B0F, 0x0B10, 1}, - {0x0B13, 0x0B28, 1}, - {0x0B2A, 0x0B30, 1}, - {0x0B32, 0x0B33, 1}, - {0x0B36, 0x0B39, 1}, - {0x0B3D, 0x0B3D, 1}, - {0x0B5C, 0x0B5D, 1}, - {0x0B5F, 0x0B61, 1}, - {0x0B85, 0x0B8A, 1}, - {0x0B8E, 0x0B90, 1}, - {0x0B92, 0x0B95, 1}, - {0x0B99, 0x0B9A, 1}, - {0x0B9C, 0x0B9C, 1}, - {0x0B9E, 0x0B9F, 1}, - {0x0BA3, 0x0BA4, 1}, - {0x0BA8, 0x0BAA, 1}, - {0x0BAE, 0x0BB5, 1}, - {0x0BB7, 0x0BB9, 1}, - {0x0C05, 0x0C0C, 1}, - {0x0C0E, 0x0C10, 1}, - {0x0C12, 0x0C28, 1}, - {0x0C2A, 0x0C33, 1}, - {0x0C35, 0x0C39, 1}, - {0x0C60, 0x0C61, 1}, - {0x0C85, 0x0C8C, 1}, - {0x0C8E, 0x0C90, 1}, - {0x0C92, 0x0CA8, 1}, - {0x0CAA, 0x0CB3, 1}, - {0x0CB5, 0x0CB9, 1}, - {0x0CDE, 0x0CDE, 1}, - {0x0CE0, 0x0CE1, 1}, - {0x0D05, 0x0D0C, 1}, - {0x0D0E, 0x0D10, 1}, - {0x0D12, 0x0D28, 1}, - {0x0D2A, 0x0D39, 1}, - {0x0D60, 0x0D61, 1}, - {0x0E01, 0x0E2E, 1}, - {0x0E30, 0x0E30, 1}, - {0x0E32, 0x0E33, 1}, - {0x0E40, 0x0E45, 1}, - {0x0E81, 0x0E82, 1}, - {0x0E84, 0x0E84, 1}, - {0x0E87, 0x0E88, 1}, - {0x0E8A, 0x0E8D, 3}, - {0x0E94, 0x0E97, 1}, - {0x0E99, 0x0E9F, 1}, - {0x0EA1, 0x0EA3, 1}, - {0x0EA5, 0x0EA7, 2}, - {0x0EAA, 0x0EAB, 1}, - {0x0EAD, 0x0EAE, 1}, - {0x0EB0, 0x0EB0, 1}, - {0x0EB2, 0x0EB3, 1}, - {0x0EBD, 0x0EBD, 1}, - {0x0EC0, 0x0EC4, 1}, - {0x0F40, 0x0F47, 1}, - {0x0F49, 0x0F69, 1}, - {0x10A0, 0x10C5, 1}, - {0x10D0, 0x10F6, 1}, - {0x1100, 0x1100, 1}, - {0x1102, 0x1103, 1}, - {0x1105, 0x1107, 1}, - {0x1109, 0x1109, 1}, - {0x110B, 0x110C, 1}, - {0x110E, 0x1112, 1}, - {0x113C, 0x1140, 2}, - {0x114C, 0x1150, 2}, - {0x1154, 0x1155, 1}, - {0x1159, 0x1159, 1}, - {0x115F, 0x1161, 1}, - {0x1163, 0x1169, 2}, - {0x116D, 0x116E, 1}, - {0x1172, 0x1173, 1}, - {0x1175, 0x119E, 0x119E - 0x1175}, - {0x11A8, 0x11AB, 0x11AB - 0x11A8}, - {0x11AE, 0x11AF, 1}, - {0x11B7, 0x11B8, 1}, - {0x11BA, 0x11BA, 1}, - {0x11BC, 0x11C2, 1}, - {0x11EB, 0x11F0, 0x11F0 - 0x11EB}, - {0x11F9, 0x11F9, 1}, - {0x1E00, 0x1E9B, 1}, - {0x1EA0, 0x1EF9, 1}, - {0x1F00, 0x1F15, 1}, - {0x1F18, 0x1F1D, 1}, - {0x1F20, 0x1F45, 1}, - {0x1F48, 0x1F4D, 1}, - {0x1F50, 0x1F57, 1}, - {0x1F59, 0x1F5B, 0x1F5B - 0x1F59}, - {0x1F5D, 0x1F5D, 1}, - {0x1F5F, 0x1F7D, 1}, - {0x1F80, 0x1FB4, 1}, - {0x1FB6, 0x1FBC, 1}, - {0x1FBE, 0x1FBE, 1}, - {0x1FC2, 0x1FC4, 1}, - {0x1FC6, 0x1FCC, 1}, - {0x1FD0, 0x1FD3, 1}, - {0x1FD6, 0x1FDB, 1}, - {0x1FE0, 0x1FEC, 1}, - {0x1FF2, 0x1FF4, 1}, - {0x1FF6, 0x1FFC, 1}, - {0x2126, 0x2126, 1}, - {0x212A, 0x212B, 1}, - {0x212E, 0x212E, 1}, - {0x2180, 0x2182, 1}, - {0x3007, 0x3007, 1}, - {0x3021, 0x3029, 1}, - {0x3041, 0x3094, 1}, - {0x30A1, 0x30FA, 1}, - {0x3105, 0x312C, 1}, - {0x4E00, 0x9FA5, 1}, - {0xAC00, 0xD7A3, 1}, +var first = &unicode.RangeTable{ + R16: []unicode.Range16{ + {0x003A, 0x003A, 1}, + {0x0041, 0x005A, 1}, + {0x005F, 0x005F, 1}, + {0x0061, 0x007A, 1}, + {0x00C0, 0x00D6, 1}, + {0x00D8, 0x00F6, 1}, + {0x00F8, 0x00FF, 1}, + {0x0100, 0x0131, 1}, + {0x0134, 0x013E, 1}, + {0x0141, 0x0148, 1}, + {0x014A, 0x017E, 1}, + {0x0180, 0x01C3, 1}, + {0x01CD, 0x01F0, 1}, + {0x01F4, 0x01F5, 1}, + {0x01FA, 0x0217, 1}, + {0x0250, 0x02A8, 1}, + {0x02BB, 0x02C1, 1}, + {0x0386, 0x0386, 1}, + {0x0388, 0x038A, 1}, + {0x038C, 0x038C, 1}, + {0x038E, 0x03A1, 1}, + {0x03A3, 0x03CE, 1}, + {0x03D0, 0x03D6, 1}, + {0x03DA, 0x03E0, 2}, + {0x03E2, 0x03F3, 1}, + {0x0401, 0x040C, 1}, + {0x040E, 0x044F, 1}, + {0x0451, 0x045C, 1}, + {0x045E, 0x0481, 1}, + {0x0490, 0x04C4, 1}, + {0x04C7, 0x04C8, 1}, + {0x04CB, 0x04CC, 1}, + {0x04D0, 0x04EB, 1}, + {0x04EE, 0x04F5, 1}, + {0x04F8, 0x04F9, 1}, + {0x0531, 0x0556, 1}, + {0x0559, 0x0559, 1}, + {0x0561, 0x0586, 1}, + {0x05D0, 0x05EA, 1}, + {0x05F0, 0x05F2, 1}, + {0x0621, 0x063A, 1}, + {0x0641, 0x064A, 1}, + {0x0671, 0x06B7, 1}, + {0x06BA, 0x06BE, 1}, + {0x06C0, 0x06CE, 1}, + {0x06D0, 0x06D3, 1}, + {0x06D5, 0x06D5, 1}, + {0x06E5, 0x06E6, 1}, + {0x0905, 0x0939, 1}, + {0x093D, 0x093D, 1}, + {0x0958, 0x0961, 1}, + {0x0985, 0x098C, 1}, + {0x098F, 0x0990, 1}, + {0x0993, 0x09A8, 1}, + {0x09AA, 0x09B0, 1}, + {0x09B2, 0x09B2, 1}, + {0x09B6, 0x09B9, 1}, + {0x09DC, 0x09DD, 1}, + {0x09DF, 0x09E1, 1}, + {0x09F0, 0x09F1, 1}, + {0x0A05, 0x0A0A, 1}, + {0x0A0F, 0x0A10, 1}, + {0x0A13, 0x0A28, 1}, + {0x0A2A, 0x0A30, 1}, + {0x0A32, 0x0A33, 1}, + {0x0A35, 0x0A36, 1}, + {0x0A38, 0x0A39, 1}, + {0x0A59, 0x0A5C, 1}, + {0x0A5E, 0x0A5E, 1}, + {0x0A72, 0x0A74, 1}, + {0x0A85, 0x0A8B, 1}, + {0x0A8D, 0x0A8D, 1}, + {0x0A8F, 0x0A91, 1}, + {0x0A93, 0x0AA8, 1}, + {0x0AAA, 0x0AB0, 1}, + {0x0AB2, 0x0AB3, 1}, + {0x0AB5, 0x0AB9, 1}, + {0x0ABD, 0x0AE0, 0x23}, + {0x0B05, 0x0B0C, 1}, + {0x0B0F, 0x0B10, 1}, + {0x0B13, 0x0B28, 1}, + {0x0B2A, 0x0B30, 1}, + {0x0B32, 0x0B33, 1}, + {0x0B36, 0x0B39, 1}, + {0x0B3D, 0x0B3D, 1}, + {0x0B5C, 0x0B5D, 1}, + {0x0B5F, 0x0B61, 1}, + {0x0B85, 0x0B8A, 1}, + {0x0B8E, 0x0B90, 1}, + {0x0B92, 0x0B95, 1}, + {0x0B99, 0x0B9A, 1}, + {0x0B9C, 0x0B9C, 1}, + {0x0B9E, 0x0B9F, 1}, + {0x0BA3, 0x0BA4, 1}, + {0x0BA8, 0x0BAA, 1}, + {0x0BAE, 0x0BB5, 1}, + {0x0BB7, 0x0BB9, 1}, + {0x0C05, 0x0C0C, 1}, + {0x0C0E, 0x0C10, 1}, + {0x0C12, 0x0C28, 1}, + {0x0C2A, 0x0C33, 1}, + {0x0C35, 0x0C39, 1}, + {0x0C60, 0x0C61, 1}, + {0x0C85, 0x0C8C, 1}, + {0x0C8E, 0x0C90, 1}, + {0x0C92, 0x0CA8, 1}, + {0x0CAA, 0x0CB3, 1}, + {0x0CB5, 0x0CB9, 1}, + {0x0CDE, 0x0CDE, 1}, + {0x0CE0, 0x0CE1, 1}, + {0x0D05, 0x0D0C, 1}, + {0x0D0E, 0x0D10, 1}, + {0x0D12, 0x0D28, 1}, + {0x0D2A, 0x0D39, 1}, + {0x0D60, 0x0D61, 1}, + {0x0E01, 0x0E2E, 1}, + {0x0E30, 0x0E30, 1}, + {0x0E32, 0x0E33, 1}, + {0x0E40, 0x0E45, 1}, + {0x0E81, 0x0E82, 1}, + {0x0E84, 0x0E84, 1}, + {0x0E87, 0x0E88, 1}, + {0x0E8A, 0x0E8D, 3}, + {0x0E94, 0x0E97, 1}, + {0x0E99, 0x0E9F, 1}, + {0x0EA1, 0x0EA3, 1}, + {0x0EA5, 0x0EA7, 2}, + {0x0EAA, 0x0EAB, 1}, + {0x0EAD, 0x0EAE, 1}, + {0x0EB0, 0x0EB0, 1}, + {0x0EB2, 0x0EB3, 1}, + {0x0EBD, 0x0EBD, 1}, + {0x0EC0, 0x0EC4, 1}, + {0x0F40, 0x0F47, 1}, + {0x0F49, 0x0F69, 1}, + {0x10A0, 0x10C5, 1}, + {0x10D0, 0x10F6, 1}, + {0x1100, 0x1100, 1}, + {0x1102, 0x1103, 1}, + {0x1105, 0x1107, 1}, + {0x1109, 0x1109, 1}, + {0x110B, 0x110C, 1}, + {0x110E, 0x1112, 1}, + {0x113C, 0x1140, 2}, + {0x114C, 0x1150, 2}, + {0x1154, 0x1155, 1}, + {0x1159, 0x1159, 1}, + {0x115F, 0x1161, 1}, + {0x1163, 0x1169, 2}, + {0x116D, 0x116E, 1}, + {0x1172, 0x1173, 1}, + {0x1175, 0x119E, 0x119E - 0x1175}, + {0x11A8, 0x11AB, 0x11AB - 0x11A8}, + {0x11AE, 0x11AF, 1}, + {0x11B7, 0x11B8, 1}, + {0x11BA, 0x11BA, 1}, + {0x11BC, 0x11C2, 1}, + {0x11EB, 0x11F0, 0x11F0 - 0x11EB}, + {0x11F9, 0x11F9, 1}, + {0x1E00, 0x1E9B, 1}, + {0x1EA0, 0x1EF9, 1}, + {0x1F00, 0x1F15, 1}, + {0x1F18, 0x1F1D, 1}, + {0x1F20, 0x1F45, 1}, + {0x1F48, 0x1F4D, 1}, + {0x1F50, 0x1F57, 1}, + {0x1F59, 0x1F5B, 0x1F5B - 0x1F59}, + {0x1F5D, 0x1F5D, 1}, + {0x1F5F, 0x1F7D, 1}, + {0x1F80, 0x1FB4, 1}, + {0x1FB6, 0x1FBC, 1}, + {0x1FBE, 0x1FBE, 1}, + {0x1FC2, 0x1FC4, 1}, + {0x1FC6, 0x1FCC, 1}, + {0x1FD0, 0x1FD3, 1}, + {0x1FD6, 0x1FDB, 1}, + {0x1FE0, 0x1FEC, 1}, + {0x1FF2, 0x1FF4, 1}, + {0x1FF6, 0x1FFC, 1}, + {0x2126, 0x2126, 1}, + {0x212A, 0x212B, 1}, + {0x212E, 0x212E, 1}, + {0x2180, 0x2182, 1}, + {0x3007, 0x3007, 1}, + {0x3021, 0x3029, 1}, + {0x3041, 0x3094, 1}, + {0x30A1, 0x30FA, 1}, + {0x3105, 0x312C, 1}, + {0x4E00, 0x9FA5, 1}, + {0xAC00, 0xD7A3, 1}, + }, } -var second = []unicode.Range{ - {0x002D, 0x002E, 1}, - {0x0030, 0x0039, 1}, - {0x00B7, 0x00B7, 1}, - {0x02D0, 0x02D1, 1}, - {0x0300, 0x0345, 1}, - {0x0360, 0x0361, 1}, - {0x0387, 0x0387, 1}, - {0x0483, 0x0486, 1}, - {0x0591, 0x05A1, 1}, - {0x05A3, 0x05B9, 1}, - {0x05BB, 0x05BD, 1}, - {0x05BF, 0x05BF, 1}, - {0x05C1, 0x05C2, 1}, - {0x05C4, 0x0640, 0x0640 - 0x05C4}, - {0x064B, 0x0652, 1}, - {0x0660, 0x0669, 1}, - {0x0670, 0x0670, 1}, - {0x06D6, 0x06DC, 1}, - {0x06DD, 0x06DF, 1}, - {0x06E0, 0x06E4, 1}, - {0x06E7, 0x06E8, 1}, - {0x06EA, 0x06ED, 1}, - {0x06F0, 0x06F9, 1}, - {0x0901, 0x0903, 1}, - {0x093C, 0x093C, 1}, - {0x093E, 0x094C, 1}, - {0x094D, 0x094D, 1}, - {0x0951, 0x0954, 1}, - {0x0962, 0x0963, 1}, - {0x0966, 0x096F, 1}, - {0x0981, 0x0983, 1}, - {0x09BC, 0x09BC, 1}, - {0x09BE, 0x09BF, 1}, - {0x09C0, 0x09C4, 1}, - {0x09C7, 0x09C8, 1}, - {0x09CB, 0x09CD, 1}, - {0x09D7, 0x09D7, 1}, - {0x09E2, 0x09E3, 1}, - {0x09E6, 0x09EF, 1}, - {0x0A02, 0x0A3C, 0x3A}, - {0x0A3E, 0x0A3F, 1}, - {0x0A40, 0x0A42, 1}, - {0x0A47, 0x0A48, 1}, - {0x0A4B, 0x0A4D, 1}, - {0x0A66, 0x0A6F, 1}, - {0x0A70, 0x0A71, 1}, - {0x0A81, 0x0A83, 1}, - {0x0ABC, 0x0ABC, 1}, - {0x0ABE, 0x0AC5, 1}, - {0x0AC7, 0x0AC9, 1}, - {0x0ACB, 0x0ACD, 1}, - {0x0AE6, 0x0AEF, 1}, - {0x0B01, 0x0B03, 1}, - {0x0B3C, 0x0B3C, 1}, - {0x0B3E, 0x0B43, 1}, - {0x0B47, 0x0B48, 1}, - {0x0B4B, 0x0B4D, 1}, - {0x0B56, 0x0B57, 1}, - {0x0B66, 0x0B6F, 1}, - {0x0B82, 0x0B83, 1}, - {0x0BBE, 0x0BC2, 1}, - {0x0BC6, 0x0BC8, 1}, - {0x0BCA, 0x0BCD, 1}, - {0x0BD7, 0x0BD7, 1}, - {0x0BE7, 0x0BEF, 1}, - {0x0C01, 0x0C03, 1}, - {0x0C3E, 0x0C44, 1}, - {0x0C46, 0x0C48, 1}, - {0x0C4A, 0x0C4D, 1}, - {0x0C55, 0x0C56, 1}, - {0x0C66, 0x0C6F, 1}, - {0x0C82, 0x0C83, 1}, - {0x0CBE, 0x0CC4, 1}, - {0x0CC6, 0x0CC8, 1}, - {0x0CCA, 0x0CCD, 1}, - {0x0CD5, 0x0CD6, 1}, - {0x0CE6, 0x0CEF, 1}, - {0x0D02, 0x0D03, 1}, - {0x0D3E, 0x0D43, 1}, - {0x0D46, 0x0D48, 1}, - {0x0D4A, 0x0D4D, 1}, - {0x0D57, 0x0D57, 1}, - {0x0D66, 0x0D6F, 1}, - {0x0E31, 0x0E31, 1}, - {0x0E34, 0x0E3A, 1}, - {0x0E46, 0x0E46, 1}, - {0x0E47, 0x0E4E, 1}, - {0x0E50, 0x0E59, 1}, - {0x0EB1, 0x0EB1, 1}, - {0x0EB4, 0x0EB9, 1}, - {0x0EBB, 0x0EBC, 1}, - {0x0EC6, 0x0EC6, 1}, - {0x0EC8, 0x0ECD, 1}, - {0x0ED0, 0x0ED9, 1}, - {0x0F18, 0x0F19, 1}, - {0x0F20, 0x0F29, 1}, - {0x0F35, 0x0F39, 2}, - {0x0F3E, 0x0F3F, 1}, - {0x0F71, 0x0F84, 1}, - {0x0F86, 0x0F8B, 1}, - {0x0F90, 0x0F95, 1}, - {0x0F97, 0x0F97, 1}, - {0x0F99, 0x0FAD, 1}, - {0x0FB1, 0x0FB7, 1}, - {0x0FB9, 0x0FB9, 1}, - {0x20D0, 0x20DC, 1}, - {0x20E1, 0x3005, 0x3005 - 0x20E1}, - {0x302A, 0x302F, 1}, - {0x3031, 0x3035, 1}, - {0x3099, 0x309A, 1}, - {0x309D, 0x309E, 1}, - {0x30FC, 0x30FE, 1}, +var second = &unicode.RangeTable{ + R16: []unicode.Range16{ + {0x002D, 0x002E, 1}, + {0x0030, 0x0039, 1}, + {0x00B7, 0x00B7, 1}, + {0x02D0, 0x02D1, 1}, + {0x0300, 0x0345, 1}, + {0x0360, 0x0361, 1}, + {0x0387, 0x0387, 1}, + {0x0483, 0x0486, 1}, + {0x0591, 0x05A1, 1}, + {0x05A3, 0x05B9, 1}, + {0x05BB, 0x05BD, 1}, + {0x05BF, 0x05BF, 1}, + {0x05C1, 0x05C2, 1}, + {0x05C4, 0x0640, 0x0640 - 0x05C4}, + {0x064B, 0x0652, 1}, + {0x0660, 0x0669, 1}, + {0x0670, 0x0670, 1}, + {0x06D6, 0x06DC, 1}, + {0x06DD, 0x06DF, 1}, + {0x06E0, 0x06E4, 1}, + {0x06E7, 0x06E8, 1}, + {0x06EA, 0x06ED, 1}, + {0x06F0, 0x06F9, 1}, + {0x0901, 0x0903, 1}, + {0x093C, 0x093C, 1}, + {0x093E, 0x094C, 1}, + {0x094D, 0x094D, 1}, + {0x0951, 0x0954, 1}, + {0x0962, 0x0963, 1}, + {0x0966, 0x096F, 1}, + {0x0981, 0x0983, 1}, + {0x09BC, 0x09BC, 1}, + {0x09BE, 0x09BF, 1}, + {0x09C0, 0x09C4, 1}, + {0x09C7, 0x09C8, 1}, + {0x09CB, 0x09CD, 1}, + {0x09D7, 0x09D7, 1}, + {0x09E2, 0x09E3, 1}, + {0x09E6, 0x09EF, 1}, + {0x0A02, 0x0A3C, 0x3A}, + {0x0A3E, 0x0A3F, 1}, + {0x0A40, 0x0A42, 1}, + {0x0A47, 0x0A48, 1}, + {0x0A4B, 0x0A4D, 1}, + {0x0A66, 0x0A6F, 1}, + {0x0A70, 0x0A71, 1}, + {0x0A81, 0x0A83, 1}, + {0x0ABC, 0x0ABC, 1}, + {0x0ABE, 0x0AC5, 1}, + {0x0AC7, 0x0AC9, 1}, + {0x0ACB, 0x0ACD, 1}, + {0x0AE6, 0x0AEF, 1}, + {0x0B01, 0x0B03, 1}, + {0x0B3C, 0x0B3C, 1}, + {0x0B3E, 0x0B43, 1}, + {0x0B47, 0x0B48, 1}, + {0x0B4B, 0x0B4D, 1}, + {0x0B56, 0x0B57, 1}, + {0x0B66, 0x0B6F, 1}, + {0x0B82, 0x0B83, 1}, + {0x0BBE, 0x0BC2, 1}, + {0x0BC6, 0x0BC8, 1}, + {0x0BCA, 0x0BCD, 1}, + {0x0BD7, 0x0BD7, 1}, + {0x0BE7, 0x0BEF, 1}, + {0x0C01, 0x0C03, 1}, + {0x0C3E, 0x0C44, 1}, + {0x0C46, 0x0C48, 1}, + {0x0C4A, 0x0C4D, 1}, + {0x0C55, 0x0C56, 1}, + {0x0C66, 0x0C6F, 1}, + {0x0C82, 0x0C83, 1}, + {0x0CBE, 0x0CC4, 1}, + {0x0CC6, 0x0CC8, 1}, + {0x0CCA, 0x0CCD, 1}, + {0x0CD5, 0x0CD6, 1}, + {0x0CE6, 0x0CEF, 1}, + {0x0D02, 0x0D03, 1}, + {0x0D3E, 0x0D43, 1}, + {0x0D46, 0x0D48, 1}, + {0x0D4A, 0x0D4D, 1}, + {0x0D57, 0x0D57, 1}, + {0x0D66, 0x0D6F, 1}, + {0x0E31, 0x0E31, 1}, + {0x0E34, 0x0E3A, 1}, + {0x0E46, 0x0E46, 1}, + {0x0E47, 0x0E4E, 1}, + {0x0E50, 0x0E59, 1}, + {0x0EB1, 0x0EB1, 1}, + {0x0EB4, 0x0EB9, 1}, + {0x0EBB, 0x0EBC, 1}, + {0x0EC6, 0x0EC6, 1}, + {0x0EC8, 0x0ECD, 1}, + {0x0ED0, 0x0ED9, 1}, + {0x0F18, 0x0F19, 1}, + {0x0F20, 0x0F29, 1}, + {0x0F35, 0x0F39, 2}, + {0x0F3E, 0x0F3F, 1}, + {0x0F71, 0x0F84, 1}, + {0x0F86, 0x0F8B, 1}, + {0x0F90, 0x0F95, 1}, + {0x0F97, 0x0F97, 1}, + {0x0F99, 0x0FAD, 1}, + {0x0FB1, 0x0FB7, 1}, + {0x0FB9, 0x0FB9, 1}, + {0x20D0, 0x20DC, 1}, + {0x20E1, 0x3005, 0x3005 - 0x20E1}, + {0x302A, 0x302F, 1}, + {0x3031, 0x3035, 1}, + {0x3099, 0x309A, 1}, + {0x309D, 0x309E, 1}, + {0x30FC, 0x30FE, 1}, + }, } // HTMLEntity is an entity map containing translations for the diff --git a/src/quietgcc.bash b/src/quietgcc.bash index e29ee4f64..c99305eda 100755 --- a/src/quietgcc.bash +++ b/src/quietgcc.bash @@ -4,7 +4,7 @@ # license that can be found in the LICENSE file. # The master for this file is $GOROOT/src/quietgcc.bash -# Changes made to $GOBIN/quietgcc will be overridden. +# Changes made to $GOBIN/quietgcc will be overwritten. # Gcc output that we don't care to see. ignore=': error: .Each undeclared identifier' @@ -32,7 +32,7 @@ case "$(uname -m -p)-$GOHOSTARCH" in esac # Run gcc, save error status, redisplay output without noise, exit with gcc status. -tmp=/tmp/qcc.$$.$USER.out +tmp=${TMPDIR:-/tmp}/quietgcc.$$.$USER.out $gcc -Wall -Wno-sign-compare -Wno-missing-braces \ -Wno-parentheses -Wno-unknown-pragmas -Wno-switch -Wno-comment \ -Werror \ |