This CL makes the next one have nice cross-file diffs.
Change-Id: I9ce897dc505dea9923be4e823bae31f4f7fa2ee2
Reviewed-on: https://go-review.googlesource.com/2471
Reviewed-by: Ian Lance Taylor <iant@golang.org>
+++ /dev/null
-// Copyright 2012 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.
-
-typedef int bool;
-
-// The Time unit is unspecified; we just need to
-// be able to compare whether t1 is older than t2 with t1 < t2.
-typedef long long Time;
-
-#define nil ((void*)0)
-#define nelem(x) (sizeof(x)/sizeof((x)[0]))
-#ifndef PLAN9
-#define USED(x) ((void)(x))
-#endif
-
-// A Buf is a byte buffer, like Go's []byte.
-typedef struct Buf Buf;
-struct Buf
-{
- char *p;
- int len;
- int cap;
-};
-
-// A Vec is a string vector, like Go's []string.
-typedef struct Vec Vec;
-struct Vec
-{
- char **p;
- int len;
- int cap;
-};
-
-// Modes for run.
-enum {
- CheckExit = 1,
-};
-
-// buf.c
-bool bequal(Buf *s, Buf *t);
-void bsubst(Buf *b, char *x, char *y);
-void bfree(Buf *b);
-void bgrow(Buf *b, int n);
-void binit(Buf *b);
-char* bpathf(Buf *b, char *fmt, ...);
-char* bprintf(Buf *b, char *fmt, ...);
-void bwritef(Buf *b, char *fmt, ...);
-void breset(Buf *b);
-char* bstr(Buf *b);
-char* btake(Buf *b);
-void bwrite(Buf *b, void *v, int n);
-void bwriteb(Buf *dst, Buf *src);
-void bwritestr(Buf *b, char *p);
-void bswap(Buf *b, Buf *b1);
-void vadd(Vec *v, char *p);
-void vcopy(Vec *dst, char **src, int n);
-void vfree(Vec *v);
-void vgrow(Vec *v, int n);
-void vinit(Vec *v);
-void vreset(Vec *v);
-void vuniq(Vec *v);
-void splitlines(Vec*, char*);
-void splitfields(Vec*, char*);
-
-// build.c
-extern char *goarch;
-extern char *gobin;
-extern char *gochar;
-extern char *gohostarch;
-extern char *gohostos;
-extern char *goos;
-extern char *goroot;
-extern char *goroot_final;
-extern char *goextlinkenabled;
-extern char *goversion;
-extern char *defaultcc;
-extern char *defaultcxxtarget;
-extern char *defaultcctarget;
-extern char *workdir;
-extern char *tooldir;
-extern char *slash;
-extern bool rebuildall;
-extern bool defaultclang;
-
-int find(char*, char**, int);
-void init(void);
-void cmdbanner(int, char**);
-void cmdbootstrap(int, char**);
-void cmdclean(int, char**);
-void cmdenv(int, char**);
-void cmdinstall(int, char**);
-void cmdversion(int, char**);
-
-// buildgc.c
-void gcopnames(char*, char*);
-void mkanames(char*, char*);
-
-// buildruntime.c
-void mkzasm(char*, char*);
-void mkzsys(char*, char*);
-void mkzgoarch(char*, char*);
-void mkzgoos(char*, char*);
-void mkzruntimedefs(char*, char*);
-void mkzversion(char*, char*);
-void mkzexperiment(char*, char*);
-
-// buildgo.c
-void mkzdefaultcc(char*, char*);
-
-// main.c
-extern int vflag;
-extern int sflag;
-void usage(void);
-void xmain(int argc, char **argv);
-
-// portability layer (plan9.c, unix.c, windows.c)
-bool contains(char *p, char *sep);
-void errprintf(char*, ...);
-void fatal(char *msg, ...);
-bool hasprefix(char *p, char *prefix);
-bool hassuffix(char *p, char *suffix);
-bool isabs(char*);
-bool isdir(char *p);
-bool isfile(char *p);
-char* lastelem(char*);
-Time mtime(char*);
-void readfile(Buf*, char*);
-void copyfile(char*, char*, int);
-void run(Buf *b, char *dir, int mode, char *cmd, ...);
-void runv(Buf *b, char *dir, int mode, Vec *argv);
-void bgrunv(char *dir, int mode, Vec *argv);
-void bgwait(void);
-bool streq(char*, char*);
-bool cansse2(void);
-void writefile(Buf*, char*, int);
-void xatexit(void (*f)(void));
-void xexit(int);
-void xfree(void*);
-void xgetenv(Buf *b, char *name);
-void xgetwd(Buf *b);
-void* xmalloc(int n);
-void* xmalloc(int);
-int xmemcmp(void*, void*, int);
-void xmemmove(void*, void*, int);
-void xmkdir(char *p);
-void xmkdirall(char*);
-Time xmtime(char *p);
-void xprintf(char*, ...);
-void xqsort(void*, int, int, int(*)(const void*, const void*));
-void xreaddir(Vec *dst, char *dir);
-void* xrealloc(void*, int);
-void xrealwd(Buf *b, char *path);
-void xremove(char *p);
-void xremoveall(char *p);
-void xsetenv(char*, char*);
-int xstrcmp(char*, char*);
-char* xstrdup(char *p);
-int xstrlen(char*);
-char* xstrrchr(char*, int);
-char* xstrstr(char*, char*);
-char* xworkdir(void);
-int xsamefile(char*, char*);
-char* xgetgoarm(void);
-int xtryexecfunc(void (*)(void));
+++ /dev/null
-/*
-Derived from Inferno include/kern.h.
-
-http://code.google.com/p/inferno-os/source/browse/include/kern.h
-
- Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
- Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
- Portions Copyright © 2009 The Go Authors. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-/* command line */
-extern char *argv0;
-#define ARGBEGIN for((argv0=(argv0?argv0:*argv)),argv++,argc--;\
- argv[0] && argv[0][0]=='-' && argv[0][1];\
- argc--, argv++) {\
- char *_args, *_argt;\
- char _argc;\
- _args = &argv[0][1];\
- if(_args[0]=='-' && _args[1]==0){\
- argc--; argv++; break;\
- }\
- while((_argc = *_args++) != 0)\
- switch(_argc)
-#define ARGEND _argt=0;USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
-#define ARGF() (_argt=_args, _args="",\
- (*_argt? _argt: argv[1]? (argc--, *++argv): 0))
-#define EARGF(x) (_argt=_args, _args="",\
- (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), fatal("usage"), (char*)0)))
-
-#define ARGC() _argc
-
+++ /dev/null
-// Copyright 2012 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 "a.h"
-
-#ifndef __ARMEL__
-char *
-xgetgoarm(void)
-{
- return "6";
-}
-#else
-static void useVFPv3(void);
-static void useVFPv1(void);
-
-char *
-xgetgoarm(void)
-{
-#if defined(__FreeBSD__)
- // FreeBSD has broken VFP support
- return "5";
-#endif
- // NaCl always has VFP support.
- if(streq(goos, "nacl") || xtryexecfunc(useVFPv3))
- return "7";
- else if(xtryexecfunc(useVFPv1))
- return "6";
- return "5";
-}
-
-static void
-useVFPv3(void)
-{
- // try to run VFPv3-only "vmov.f64 d0, #112" instruction
- // we can't use that instruction directly, because we
- // might be compiling with a soft-float only toolchain.
- //
- // some newer toolchains are configured to use thumb
- // by default, so we need to do some mode changing magic
- // here.
- // We can use "bx pc; nop" here, but GNU as(1) insists
- // on warning us
- // "use of r15 in bx in ARM mode is not really useful"
- // so we workaround that by using "bx r0"
- __asm__ __volatile__ ("mov r0, pc");
- __asm__ __volatile__ ("bx r0");
- __asm__ __volatile__ (".word 0xeeb70b00"); // vmov.f64 d0, #112
- __asm__ __volatile__ (".word 0xe12fff1e"); // bx lr
-}
-
-static void
-useVFPv1(void)
-{
- // try to run "vmov.f64 d0, d0" instruction
- // we can't use that instruction directly, because we
- // might be compiling with a soft-float only toolchain
- //
- // some newer toolchains are configured to use thumb
- // by default, so we need to do some mode changing magic
- // here.
- // We can use "bx pc; nop" here, but GNU as(1) insists
- // on warning us
- // "use of r15 in bx in ARM mode is not really useful"
- // so we workaround that by using "bx r0"
- __asm__ __volatile__ ("mov r0, pc");
- __asm__ __volatile__ ("bx r0");
- __asm__ __volatile__ (".word 0xeeb00b40"); // vomv.f64 d0, d0
- __asm__ __volatile__ (".word 0xe12fff1e"); // bx lr
-}
-
-#endif
+++ /dev/null
-// Copyright 2012 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.
-
-// Byte buffers and string vectors.
-
-#include "a.h"
-
-// binit prepares an uninitialized buffer for use.
-void
-binit(Buf *b)
-{
- b->p = nil;
- b->len = 0;
- b->cap = 0;
-}
-
-// breset truncates the buffer back to zero length.
-void
-breset(Buf *b)
-{
- b->len = 0;
-}
-
-// bfree frees the storage associated with a buffer.
-void
-bfree(Buf *b)
-{
- xfree(b->p);
- binit(b);
-}
-
-// bgrow ensures that the buffer has at least n more bytes
-// between its len and cap.
-void
-bgrow(Buf *b, int n)
-{
- int want;
-
- want = b->len+n;
- if(want > b->cap) {
- b->cap = 2*want;
- if(b->cap < 64)
- b->cap = 64;
- b->p = xrealloc(b->p, b->cap);
- }
-}
-
-// bwrite appends the n bytes at v to the buffer.
-void
-bwrite(Buf *b, void *v, int n)
-{
- bgrow(b, n);
- xmemmove(b->p+b->len, v, n);
- b->len += n;
-}
-
-// bwritestr appends the string p to the buffer.
-void
-bwritestr(Buf *b, char *p)
-{
- bwrite(b, p, xstrlen(p));
-}
-
-// bstr returns a pointer to a NUL-terminated string of the
-// buffer contents. The pointer points into the buffer.
-char*
-bstr(Buf *b)
-{
- bgrow(b, 1);
- b->p[b->len] = '\0';
- return b->p;
-}
-
-// btake takes ownership of the string form of the buffer.
-// After this call, the buffer has zero length and does not
-// refer to the memory that btake returned.
-char*
-btake(Buf *b)
-{
- char *p;
-
- p = bstr(b);
- binit(b);
- return p;
-}
-
-// bwriteb appends the src buffer to the dst buffer.
-void
-bwriteb(Buf *dst, Buf *src)
-{
- bwrite(dst, src->p, src->len);
-}
-
-// bequal reports whether the buffers have the same content.
-bool
-bequal(Buf *s, Buf *t)
-{
- return s->len == t->len && xmemcmp(s->p, t->p, s->len) == 0;
-}
-
-// bsubst rewites b to replace all occurrences of x with y.
-void
-bsubst(Buf *b, char *x, char *y)
-{
- char *p;
- int nx, ny, pos;
-
- nx = xstrlen(x);
- ny = xstrlen(y);
-
- pos = 0;
- for(;;) {
- p = xstrstr(bstr(b)+pos, x);
- if(p == nil)
- break;
- if(nx != ny) {
- if(nx < ny) {
- pos = p - b->p;
- bgrow(b, ny-nx);
- p = b->p + pos;
- }
- xmemmove(p+ny, p+nx, (b->p+b->len)-(p+nx));
- }
- xmemmove(p, y, ny);
- pos = p+ny - b->p;
- b->len += ny - nx;
- }
-}
-
-// The invariant with the vectors is that v->p[0:v->len] is allocated
-// strings that are owned by the vector. The data beyond v->len may
-// be garbage.
-
-// vinit prepares an uninitialized vector for use.
-void
-vinit(Vec *v)
-{
- v->p = nil;
- v->len = 0;
- v->cap = 0;
-}
-
-// vreset truncates the vector back to zero length.
-void
-vreset(Vec *v)
-{
- int i;
-
- for(i=0; i<v->len; i++) {
- xfree(v->p[i]);
- v->p[i] = nil;
- }
- v->len = 0;
-}
-
-// vfree frees the storage associated with the vector.
-void
-vfree(Vec *v)
-{
- vreset(v);
- xfree(v->p);
- vinit(v);
-}
-
-
-// vgrow ensures that the vector has room for at least
-// n more entries between len and cap.
-void
-vgrow(Vec *v, int n)
-{
- int want;
-
- want = v->len+n;
- if(want > v->cap) {
- v->cap = 2*want;
- if(v->cap < 64)
- v->cap = 64;
- v->p = xrealloc(v->p, v->cap*sizeof v->p[0]);
- }
-}
-
-// vcopy copies the srclen strings at src into the vector.
-void
-vcopy(Vec *dst, char **src, int srclen)
-{
- int i;
-
- // use vadd, to make copies of strings
- for(i=0; i<srclen; i++)
- vadd(dst, src[i]);
-}
-
-// vadd adds a copy of the string p to the vector.
-void
-vadd(Vec *v, char *p)
-{
- vgrow(v, 1);
- if(p != nil)
- p = xstrdup(p);
- v->p[v->len++] = p;
-}
-
-// vaddn adds a string consisting of the n bytes at p to the vector.
-static void
-vaddn(Vec *v, char *p, int n)
-{
- char *q;
-
- vgrow(v, 1);
- q = xmalloc(n+1);
- xmemmove(q, p, n);
- q[n] = '\0';
- v->p[v->len++] = q;
-}
-
-static int
-strpcmp(const void *a, const void *b)
-{
- return xstrcmp(*(char**)a, *(char**)b);
-}
-
-// vuniq sorts the vector and then discards duplicates,
-// in the manner of sort | uniq.
-void
-vuniq(Vec *v)
-{
- int i, n;
-
- xqsort(v->p, v->len, sizeof(v->p[0]), strpcmp);
- n = 0;
- for(i=0; i<v->len; i++) {
- if(n>0 && streq(v->p[i], v->p[n-1]))
- xfree(v->p[i]);
- else
- v->p[n++] = v->p[i];
- }
- v->len = n;
-}
-
-// splitlines replaces the vector v with the result of splitting
-// the input p after each \n. If there is a \r immediately before
-// each \n, it will be removed.
-void
-splitlines(Vec *v, char *p)
-{
- int i;
- char *start;
-
- vreset(v);
- start = p;
- for(i=0; p[i]; i++) {
- if((p[i] == '\r' && p[i+1] == '\n') || p[i] == '\n') {
- vaddn(v, start, (p+i+1)-start);
- if(p[i] == '\r') {
- v->p[v->len-1][(p+i)-start] = '\n';
- i++;
- }
- start = p+i+1;
- }
- }
- if(*start != '\0')
- vadd(v, start);
-}
-
-// splitfields replaces the vector v with the result of splitting
-// the input p into non-empty fields containing no spaces.
-void
-splitfields(Vec *v, char *p)
-{
- char *start;
-
- vreset(v);
- for(;;) {
- while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
- p++;
- if(*p == '\0')
- break;
- start = p;
- while(*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != '\0')
- p++;
- vaddn(v, start, p-start);
- }
-}
+++ /dev/null
-// Copyright 2012 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.
-
-// These #ifdefs are being used as a substitute for
-// build configuration, so that on any system, this
-// tool can be built with the local equivalent of
-// cc *.c
-//
-#ifdef PLAN9
-
-#include <u.h>
-#include <libc.h>
-#include <stdio.h>
-#undef nil
-#undef nelem
-#include "a.h"
-
-// bprintf replaces the buffer with the result of the printf formatting
-// and returns a pointer to the NUL-terminated buffer contents.
-char*
-bprintf(Buf *b, char *fmt, ...)
-{
- va_list arg;
- char buf[4096];
-
- breset(b);
- va_start(arg, fmt);
- vsnprintf(buf, sizeof buf, fmt, arg);
- va_end(arg);
- bwritestr(b, buf);
- return bstr(b);
-}
-
-// bpathf is the same as bprintf (on windows it turns / into \ after the printf).
-// It returns a pointer to the NUL-terminated buffer contents.
-char*
-bpathf(Buf *b, char *fmt, ...)
-{
- va_list arg;
- char buf[4096];
-
- breset(b);
- va_start(arg, fmt);
- vsnprintf(buf, sizeof buf, fmt, arg);
- va_end(arg);
- bwritestr(b, buf);
- return bstr(b);
-}
-
-// bwritef is like bprintf but does not reset the buffer
-// and does not return the NUL-terminated string.
-void
-bwritef(Buf *b, char *fmt, ...)
-{
- va_list arg;
- char buf[4096];
-
- va_start(arg, fmt);
- vsnprintf(buf, sizeof buf, fmt, arg);
- va_end(arg);
- bwritestr(b, buf);
-}
-
-// breadfrom appends to b all the data that can be read from fd.
-static void
-breadfrom(Buf *b, int fd)
-{
- int n;
-
- for(;;) {
- bgrow(b, 4096);
- n = read(fd, b->p+b->len, 4096);
- if(n < 0)
- fatal("read");
- if(n == 0)
- break;
- b->len += n;
- }
-}
-
-// xgetenv replaces b with the value of the named environment variable.
-void
-xgetenv(Buf *b, char *name)
-{
- char *p;
-
- breset(b);
- p = getenv(name);
- if(p != nil)
- bwritestr(b, p);
-}
-
-static void genrun(Buf *b, char *dir, int mode, Vec *argv, int bg);
-
-// run runs the command named by cmd.
-// If b is not nil, run replaces b with the output of the command.
-// If dir is not nil, run runs the command in that directory.
-// If mode is CheckExit, run calls fatal if the command is not successful.
-void
-run(Buf *b, char *dir, int mode, char *cmd, ...)
-{
- va_list arg;
- Vec argv;
- char *p;
-
- vinit(&argv);
- vadd(&argv, cmd);
- va_start(arg, cmd);
- while((p = va_arg(arg, char*)) != nil)
- vadd(&argv, p);
- va_end(arg);
-
- runv(b, dir, mode, &argv);
-
- vfree(&argv);
-}
-
-// runv is like run but takes a vector.
-void
-runv(Buf *b, char *dir, int mode, Vec *argv)
-{
- genrun(b, dir, mode, argv, 1);
-}
-
-// bgrunv is like run but runs the command in the background.
-// bgwait waits for pending bgrunv to finish.
-void
-bgrunv(char *dir, int mode, Vec *argv)
-{
- genrun(nil, dir, mode, argv, 0);
-}
-
-#define MAXBG 4 /* maximum number of jobs to run at once */
-
-static struct {
- int pid;
- int mode;
- char *cmd;
- Buf *b;
-} bg[MAXBG];
-static int nbg;
-static int maxnbg = nelem(bg);
-
-static void bgwait1(void);
-
-// genrun is the generic run implementation.
-static void
-genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
-{
- int i, p[2], pid;
- Buf b1, cmd;
- char *q;
-
- while(nbg >= maxnbg)
- bgwait1();
-
- binit(&b1);
- binit(&cmd);
-
- if(!isabs(argv->p[0])) {
- bpathf(&b1, "/bin/%s", argv->p[0]);
- free(argv->p[0]);
- argv->p[0] = xstrdup(bstr(&b1));
- }
-
- // Generate a copy of the command to show in a log.
- // Substitute $WORK for the work directory.
- for(i=0; i<argv->len; i++) {
- if(i > 0)
- bwritestr(&cmd, " ");
- q = argv->p[i];
- if(workdir != nil && hasprefix(q, workdir)) {
- bwritestr(&cmd, "$WORK");
- q += strlen(workdir);
- }
- bwritestr(&cmd, q);
- }
- if(vflag > 1)
- errprintf("%s\n", bstr(&cmd));
-
- if(b != nil) {
- breset(b);
- if(pipe(p) < 0)
- fatal("pipe");
- }
-
- switch(pid = fork()) {
- case -1:
- fatal("fork");
- case 0:
- if(b != nil) {
- close(0);
- close(p[0]);
- dup(p[1], 1);
- dup(p[1], 2);
- if(p[1] > 2)
- close(p[1]);
- }
- if(dir != nil) {
- if(chdir(dir) < 0) {
- fprint(2, "chdir: %r\n");
- _exits("chdir");
- }
- }
- vadd(argv, nil);
- exec(argv->p[0], argv->p);
- fprint(2, "%s\n", bstr(&cmd));
- fprint(2, "exec: %r\n");
- _exits("exec");
- }
- if(b != nil) {
- close(p[1]);
- breadfrom(b, p[0]);
- close(p[0]);
- }
-
- if(nbg < 0)
- fatal("bad bookkeeping");
- bg[nbg].pid = pid;
- bg[nbg].mode = mode;
- bg[nbg].cmd = btake(&cmd);
- bg[nbg].b = b;
- nbg++;
-
- if(wait)
- bgwait();
-
- bfree(&cmd);
- bfree(&b1);
-}
-
-// bgwait1 waits for a single background job.
-static void
-bgwait1(void)
-{
- Waitmsg *w;
- int i, mode;
- char *cmd;
- Buf *b;
-
- w = wait();
- if(w == nil)
- fatal("wait");
-
- for(i=0; i<nbg; i++)
- if(bg[i].pid == w->pid)
- goto ok;
- fatal("wait: unexpected pid");
-
-ok:
- cmd = bg[i].cmd;
- mode = bg[i].mode;
- bg[i].pid = 0;
- b = bg[i].b;
- bg[i].b = nil;
- bg[i] = bg[--nbg];
-
- if(mode == CheckExit && w->msg[0]) {
- if(b != nil)
- xprintf("%s\n", bstr(b));
- fatal("FAILED: %s", cmd);
- }
- xfree(cmd);
-}
-
-// bgwait waits for all the background jobs.
-void
-bgwait(void)
-{
- while(nbg > 0)
- bgwait1();
-}
-
-// xgetwd replaces b with the current directory.
-void
-xgetwd(Buf *b)
-{
- char buf[4096];
-
- breset(b);
- if(getwd(buf, sizeof buf) == nil)
- fatal("getwd");
- bwritestr(b, buf);
-}
-
-// xrealwd replaces b with the 'real' name for the given path.
-// real is defined as what getcwd returns in that directory.
-void
-xrealwd(Buf *b, char *path)
-{
- char buf[4096];
- int fd;
-
- fd = open(path, OREAD);
- if(fd2path(fd, buf, sizeof buf) < 0)
- fatal("fd2path");
- close(fd);
- breset(b);
- bwritestr(b, buf);
-}
-
-// isdir reports whether p names an existing directory.
-bool
-isdir(char *p)
-{
- Dir *d;
- ulong mode;
-
- d = dirstat(p);
- if(d == nil)
- return 0;
- mode = d->mode;
- free(d);
- return (mode & DMDIR) == DMDIR;
-}
-
-// isfile reports whether p names an existing file.
-bool
-isfile(char *p)
-{
- Dir *d;
- ulong mode;
-
- d = dirstat(p);
- if(d == nil)
- return 0;
- mode = d->mode;
- free(d);
- return (mode & DMDIR) == 0;
-}
-
-// mtime returns the modification time of the file p.
-Time
-mtime(char *p)
-{
- Dir *d;
- ulong t;
-
- d = dirstat(p);
- if(d == nil)
- return 0;
- t = d->mtime;
- free(d);
- return (Time)t;
-}
-
-// isabs reports whether p is an absolute path.
-bool
-isabs(char *p)
-{
- return hasprefix(p, "/");
-}
-
-// readfile replaces b with the content of the named file.
-void
-readfile(Buf *b, char *file)
-{
- int fd;
-
- breset(b);
- fd = open(file, OREAD);
- if(fd < 0)
- fatal("open %s", file);
- breadfrom(b, fd);
- close(fd);
-}
-
-// writefile writes b to the named file, creating it if needed.
-void
-writefile(Buf *b, char *file, int exec)
-{
- int fd;
- Dir d;
-
- fd = create(file, ORDWR, 0666);
- if(fd < 0)
- fatal("create %s", file);
- if(write(fd, b->p, b->len) != b->len)
- fatal("short write");
- if(exec) {
- nulldir(&d);
- d.mode = 0755;
- dirfwstat(fd, &d);
- }
- close(fd);
-}
-
-// xmkdir creates the directory p.
-void
-xmkdir(char *p)
-{
- int fd;
-
- if(isdir(p))
- return;
- fd = create(p, OREAD, 0777|DMDIR);
- close(fd);
- if(fd < 0)
- fatal("mkdir %s", p);
-}
-
-// xmkdirall creates the directory p and its parents, as needed.
-void
-xmkdirall(char *p)
-{
- char *q;
-
- if(isdir(p))
- return;
- q = strrchr(p, '/');
- if(q != nil) {
- *q = '\0';
- xmkdirall(p);
- *q = '/';
- }
- xmkdir(p);
-}
-
-// xremove removes the file p.
-void
-xremove(char *p)
-{
- if(vflag > 2)
- errprintf("rm %s\n", p);
- remove(p);
-}
-
-// xremoveall removes the file or directory tree rooted at p.
-void
-xremoveall(char *p)
-{
- int i;
- Buf b;
- Vec dir;
-
- binit(&b);
- vinit(&dir);
-
- if(isdir(p)) {
- xreaddir(&dir, p);
- for(i=0; i<dir.len; i++) {
- bprintf(&b, "%s/%s", p, dir.p[i]);
- xremoveall(bstr(&b));
- }
- }
- if(vflag > 2)
- errprintf("rm %s\n", p);
- remove(p);
-
- bfree(&b);
- vfree(&dir);
-}
-
-// xreaddir replaces dst with a list of the names of the files in dir.
-// The names are relative to dir; they are not full paths.
-void
-xreaddir(Vec *dst, char *dir)
-{
- Dir *d;
- int fd, i, n;
-
- vreset(dst);
-
- fd = open(dir, OREAD);
- if(fd < 0)
- fatal("open %s", dir);
- n = dirreadall(fd, &d);
- for(i=0; i<n; i++)
- vadd(dst, d[i].name);
- free(d);
- close(fd);
-}
-
-// xworkdir creates a new temporary directory to hold object files
-// and returns the name of that directory.
-char*
-xworkdir(void)
-{
- Buf b;
- char *p;
- int fd, tries;
-
- binit(&b);
-
- fd = 0;
- for(tries=0; tries<1000; tries++) {
- bprintf(&b, "/tmp/go-cbuild-%06x", nrand((1<<24)-1));
- fd = create(bstr(&b), OREAD|OEXCL, 0700|DMDIR);
- if(fd >= 0)
- goto done;
- }
- fatal("xworkdir create");
-
-done:
- close(fd);
- p = btake(&b);
-
- bfree(&b);
- return p;
-}
-
-// fatal prints an error message to standard error and exits.
-void
-fatal(char *msg, ...)
-{
- va_list arg;
-
- fflush(stdout);
- fprintf(stderr, "go tool dist: ");
- va_start(arg, msg);
- vfprintf(stderr, msg, arg);
- va_end(arg);
- fprintf(stderr, "\n");
-
- bgwait();
- exits(msg);
-}
-
-// xmalloc returns a newly allocated zeroed block of n bytes of memory.
-// It calls fatal if it runs out of memory.
-void*
-xmalloc(int n)
-{
- void *p;
-
- p = malloc(n);
- if(p == nil)
- fatal("out of memory");
- memset(p, 0, n);
- return p;
-}
-
-// xstrdup returns a newly allocated copy of p.
-// It calls fatal if it runs out of memory.
-char*
-xstrdup(char *p)
-{
- p = strdup(p);
- if(p == nil)
- fatal("out of memory");
- return p;
-}
-
-// xrealloc grows the allocation p to n bytes and
-// returns the new (possibly moved) pointer.
-// It calls fatal if it runs out of memory.
-void*
-xrealloc(void *p, int n)
-{
- p = realloc(p, n);
- if(p == nil)
- fatal("out of memory");
- return p;
-}
-
-// xfree frees the result returned by xmalloc, xstrdup, or xrealloc.
-void
-xfree(void *p)
-{
- free(p);
-}
-
-// hassuffix reports whether p ends with suffix.
-bool
-hassuffix(char *p, char *suffix)
-{
- int np, ns;
-
- np = strlen(p);
- ns = strlen(suffix);
- return np >= ns && streq(p+np-ns, suffix);
-}
-
-// hasprefix reports whether p begins with prefix.
-bool
-hasprefix(char *p, char *prefix)
-{
- return strncmp(p, prefix, strlen(prefix)) == 0;
-}
-
-// contains reports whether sep appears in p.
-bool
-contains(char *p, char *sep)
-{
- return strstr(p, sep) != nil;
-}
-
-// streq reports whether p and q are the same string.
-bool
-streq(char *p, char *q)
-{
- return strcmp(p, q) == 0;
-}
-
-// lastelem returns the final path element in p.
-char*
-lastelem(char *p)
-{
- char *out;
-
- out = p;
- for(; *p; p++)
- if(*p == '/')
- out = p+1;
- return out;
-}
-
-// xmemmove copies n bytes from src to dst.
-void
-xmemmove(void *dst, void *src, int n)
-{
- memmove(dst, src, n);
-}
-
-// xmemcmp compares the n-byte regions starting at a and at b.
-int
-xmemcmp(void *a, void *b, int n)
-{
- return memcmp(a, b, n);
-}
-
-// xstrlen returns the length of the NUL-terminated string at p.
-int
-xstrlen(char *p)
-{
- return strlen(p);
-}
-
-// xexit exits the process with return code n.
-void
-xexit(int n)
-{
- char buf[32];
-
- snprintf(buf, sizeof buf, "%d", n);
- exits(buf);
-}
-
-// xatexit schedules the exit-handler f to be run when the program exits.
-void
-xatexit(void (*f)(void))
-{
- atexit(f);
-}
-
-// xprintf prints a message to standard output.
-void
-xprintf(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- vprintf(fmt, arg);
- va_end(arg);
-}
-
-// errprintf prints a message to standard output.
-void
-errprintf(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- vfprintf(stderr, fmt, arg);
- va_end(arg);
-}
-
-// xsetenv sets the environment variable $name to the given value.
-void
-xsetenv(char *name, char *value)
-{
- putenv(name, value);
-}
-
-// main takes care of OS-specific startup and dispatches to xmain.
-void
-main(int argc, char **argv)
-{
- Buf b;
-
- setvbuf(stdout, nil, _IOLBF, BUFSIZ);
- setvbuf(stderr, nil, _IOLBF, BUFSIZ);
-
- binit(&b);
-
- rfork(RFENVG);
-
- slash = "/";
- gohostos = "plan9";
-
- xgetenv(&b, "objtype");
- if(b.len == 0)
- fatal("$objtype is unset");
- gohostarch = btake(&b);
-
- srand(time(0)+getpid());
- init();
- xmain(argc, argv);
-
- bfree(&b);
- exits(nil);
-}
-
-// xqsort is a wrapper for the C standard qsort.
-void
-xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*))
-{
- qsort(data, n, elemsize, cmp);
-}
-
-// xstrcmp compares the NUL-terminated strings a and b.
-int
-xstrcmp(char *a, char *b)
-{
- return strcmp(a, b);
-}
-
-// xstrstr returns a pointer to the first occurrence of b in a.
-char*
-xstrstr(char *a, char *b)
-{
- return strstr(a, b);
-}
-
-// xstrrchr returns a pointer to the final occurrence of c in p.
-char*
-xstrrchr(char *p, int c)
-{
- return strrchr(p, c);
-}
-
-// xsamefile reports whether f1 and f2 are the same file (or dir)
-int
-xsamefile(char *f1, char *f2)
-{
- return streq(f1, f2); // suffice for now
-}
-
-// xtryexecfunc tries to execute function f, if any illegal instruction
-// signal received in the course of executing that function, it will
-// return 0, otherwise it will return 1.
-int
-xtryexecfunc(void (*f)(void))
-{
- USED(f);
- return 0; // suffice for now
-}
-
-bool
-cansse2(void)
-{
- // if we had access to cpuid, could answer this question
- // less conservatively.
- return 0;
-}
-
-#endif // PLAN9
+++ /dev/null
-// Copyright 2012 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.
-
-// These #ifdefs are being used as a substitute for
-// build configuration, so that on any system, this
-// tool can be built with the local equivalent of
-// cc *.c
-//
-#ifdef WIN32
-
-// Portability layer implemented for Windows.
-// See unix.c for doc comments about exported functions.
-
-#include "a.h"
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-/*
- * Windows uses 16-bit rune strings in the APIs.
- * Define conversions between Rune* and UTF-8 char*.
- */
-
-typedef unsigned char uchar;
-typedef unsigned short Rune; // same as Windows
-
-// encoderune encodes the rune r into buf and returns
-// the number of bytes used.
-static int
-encoderune(char *buf, Rune r)
-{
- if(r < 0x80) { // 7 bits
- buf[0] = r;
- return 1;
- }
- if(r < 0x800) { // 5+6 bits
- buf[0] = 0xc0 | (r>>6);
- buf[1] = 0x80 | (r&0x3f);
- return 2;
- }
- buf[0] = 0xe0 | (r>>12);
- buf[1] = 0x80 | ((r>>6)&0x3f);
- buf[2] = 0x80 | (r&0x3f);
- return 3;
-}
-
-// decoderune decodes the rune encoding at sbuf into r
-// and returns the number of bytes used.
-static int
-decoderune(Rune *r, char *sbuf)
-{
- uchar *buf;
-
- buf = (uchar*)sbuf;
- if(buf[0] < 0x80) {
- *r = buf[0];
- return 1;
- }
- if((buf[0]&0xe0) == 0xc0 && (buf[1]&0xc0) == 0x80) {
- *r = (buf[0]&~0xc0)<<6 | (buf[1]&~0x80);
- if(*r < 0x80)
- goto err;
- return 2;
- }
- if((buf[0]&0xf0) == 0xe0 && (buf[1]&0xc0) == 0x80 && (buf[2]&0xc0) == 0x80) {
- *r = (buf[0]&~0xc0)<<12 | (buf[1]&~0x80)<<6 | (buf[2]&~0x80);
- if(*r < 0x800)
- goto err;
- return 3;
- }
-err:
- *r = 0xfffd;
- return 1;
-}
-
-// toutf replaces b with the UTF-8 encoding of the rune string r.
-static void
-toutf(Buf *b, Rune *r)
-{
- int i, n;
- char buf[4];
-
- breset(b);
- for(i=0; r[i]; i++) {
- n = encoderune(buf, r[i]);
- bwrite(b, buf, n);
- }
-}
-
-// torune replaces *rp with a pointer to a newly allocated
-// rune string equivalent of the UTF-8 string p.
-static void
-torune(Rune **rp, char *p)
-{
- Rune *r, *w;
-
- r = xmalloc((strlen(p)+1) * sizeof r[0]);
- w = r;
- while(*p)
- p += decoderune(w++, p);
- *w = 0;
- *rp = r;
-}
-
-// errstr returns the most recent Windows error, in string form.
-static char*
-errstr(void)
-{
- DWORD code;
- Rune *r;
- Buf b;
-
- binit(&b);
- code = GetLastError();
- r = nil;
- FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
- nil, code, 0, (Rune*)&r, 0, nil);
- toutf(&b, r);
- return bstr(&b); // leak but we're dying anyway
-}
-
-void
-xgetenv(Buf *b, char *name)
-{
- Rune *buf;
- int n;
- Rune *r;
-
- breset(b);
- torune(&r, name);
- n = GetEnvironmentVariableW(r, NULL, 0);
- if(n > 0) {
- buf = xmalloc((n+1)*sizeof buf[0]);
- GetEnvironmentVariableW(r, buf, n+1);
- buf[n] = '\0';
- toutf(b, buf);
- xfree(buf);
- }
- xfree(r);
-}
-
-void
-xsetenv(char *name, char *value)
-{
- Rune *rname, *rvalue;
-
- torune(&rname, name);
- torune(&rvalue, value);
- SetEnvironmentVariableW(rname, rvalue);
- xfree(rname);
- xfree(rvalue);
-}
-
-char*
-bprintf(Buf *b, char *fmt, ...)
-{
- va_list arg;
- char buf[4096];
-
- breset(b);
- va_start(arg, fmt);
- vsnprintf(buf, sizeof buf, fmt, arg);
- va_end(arg);
- bwritestr(b, buf);
- return bstr(b);
-}
-
-void
-bwritef(Buf *b, char *fmt, ...)
-{
- va_list arg;
- char buf[4096];
-
- // no reset
- va_start(arg, fmt);
- vsnprintf(buf, sizeof buf, fmt, arg);
- va_end(arg);
- bwritestr(b, buf);
-}
-
-// bpathf is like bprintf but replaces / with \ in the result,
-// to make it a canonical windows file path.
-char*
-bpathf(Buf *b, char *fmt, ...)
-{
- int i;
- va_list arg;
- char buf[4096];
-
- breset(b);
- va_start(arg, fmt);
- vsnprintf(buf, sizeof buf, fmt, arg);
- va_end(arg);
- bwritestr(b, buf);
-
- for(i=0; i<b->len; i++)
- if(b->p[i] == '/')
- b->p[i] = '\\';
-
- return bstr(b);
-}
-
-
-static void
-breadfrom(Buf *b, HANDLE h)
-{
- DWORD n;
-
- for(;;) {
- if(b->len > 1<<22)
- fatal("unlikely file size in readfrom");
- bgrow(b, 4096);
- n = 0;
- if(!ReadFile(h, b->p+b->len, 4096, &n, nil)) {
- // Happens for pipe reads.
- break;
- }
- if(n == 0)
- break;
- b->len += n;
- }
-}
-
-void
-run(Buf *b, char *dir, int mode, char *cmd, ...)
-{
- va_list arg;
- Vec argv;
- char *p;
-
- vinit(&argv);
- vadd(&argv, cmd);
- va_start(arg, cmd);
- while((p = va_arg(arg, char*)) != nil)
- vadd(&argv, p);
- va_end(arg);
-
- runv(b, dir, mode, &argv);
-
- vfree(&argv);
-}
-
-static void genrun(Buf*, char*, int, Vec*, int);
-
-void
-runv(Buf *b, char *dir, int mode, Vec *argv)
-{
- genrun(b, dir, mode, argv, 1);
-}
-
-void
-bgrunv(char *dir, int mode, Vec *argv)
-{
- genrun(nil, dir, mode, argv, 0);
-}
-
-#define MAXBG 4 /* maximum number of jobs to run at once */
-
-static struct {
- PROCESS_INFORMATION pi;
- int mode;
- char *cmd;
-} bg[MAXBG];
-
-static int nbg;
-
-static void bgwait1(void);
-
-static void
-genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
-{
- // Another copy of this logic is in ../../lib9/run_windows.c.
- // If there's a bug here, fix the logic there too.
- int i, j, nslash;
- Buf cmd;
- char *q;
- Rune *rcmd, *rexe, *rdir;
- STARTUPINFOW si;
- PROCESS_INFORMATION pi;
- HANDLE p[2];
-
- while(nbg >= nelem(bg))
- bgwait1();
-
- binit(&cmd);
-
- for(i=0; i<argv->len; i++) {
- q = argv->p[i];
- if(i == 0 && streq(q, "hg"))
- bwritestr(&cmd, "cmd.exe /c ");
- if(i > 0)
- bwritestr(&cmd, " ");
- if(contains(q, " ") || contains(q, "\t") || contains(q, "\"") || contains(q, "\\\\") || hassuffix(q, "\\")) {
- bwritestr(&cmd, "\"");
- nslash = 0;
- for(; *q; q++) {
- if(*q == '\\') {
- nslash++;
- continue;
- }
- if(*q == '"') {
- for(j=0; j<2*nslash+1; j++)
- bwritestr(&cmd, "\\");
- nslash = 0;
- }
- for(j=0; j<nslash; j++)
- bwritestr(&cmd, "\\");
- nslash = 0;
- bwrite(&cmd, q, 1);
- }
- for(j=0; j<2*nslash; j++)
- bwritestr(&cmd, "\\");
- bwritestr(&cmd, "\"");
- } else {
- bwritestr(&cmd, q);
- }
- }
- if(vflag > 1)
- errprintf("%s\n", bstr(&cmd));
-
- torune(&rcmd, bstr(&cmd));
- rexe = nil;
- rdir = nil;
- if(dir != nil)
- torune(&rdir, dir);
-
- memset(&si, 0, sizeof si);
- si.cb = sizeof si;
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = INVALID_HANDLE_VALUE;
- if(b == nil) {
- si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- } else {
- SECURITY_ATTRIBUTES seci;
-
- memset(&seci, 0, sizeof seci);
- seci.nLength = sizeof seci;
- seci.bInheritHandle = 1;
- breset(b);
- if(!CreatePipe(&p[0], &p[1], &seci, 0))
- fatal("CreatePipe: %s", errstr());
- si.hStdOutput = p[1];
- si.hStdError = p[1];
- }
-
- if(!CreateProcessW(rexe, rcmd, nil, nil, TRUE, 0, nil, rdir, &si, &pi)) {
- if(mode!=CheckExit)
- return;
- fatal("%s: %s", argv->p[0], errstr());
- }
- if(rexe != nil)
- xfree(rexe);
- xfree(rcmd);
- if(rdir != nil)
- xfree(rdir);
- if(b != nil) {
- CloseHandle(p[1]);
- breadfrom(b, p[0]);
- CloseHandle(p[0]);
- }
-
- if(nbg < 0)
- fatal("bad bookkeeping");
- bg[nbg].pi = pi;
- bg[nbg].mode = mode;
- bg[nbg].cmd = btake(&cmd);
- nbg++;
-
- if(wait)
- bgwait();
-
- bfree(&cmd);
-}
-
-// closes the background job for bgwait1
-static void
-bgwaitclose(int i)
-{
- if(i < 0 || i >= nbg)
- return;
-
- CloseHandle(bg[i].pi.hProcess);
- CloseHandle(bg[i].pi.hThread);
-
- bg[i] = bg[--nbg];
-}
-
-// bgwait1 waits for a single background job
-static void
-bgwait1(void)
-{
- int i, mode;
- char *cmd;
- HANDLE bgh[MAXBG];
- DWORD code;
-
- if(nbg == 0)
- fatal("bgwait1: nothing left");
-
- for(i=0; i<nbg; i++)
- bgh[i] = bg[i].pi.hProcess;
- i = WaitForMultipleObjects(nbg, bgh, FALSE, INFINITE);
- if(i < 0 || i >= nbg)
- fatal("WaitForMultipleObjects: %s", errstr());
-
- cmd = bg[i].cmd;
- mode = bg[i].mode;
- if(!GetExitCodeProcess(bg[i].pi.hProcess, &code)) {
- bgwaitclose(i);
- fatal("GetExitCodeProcess: %s", errstr());
- return;
- }
-
- if(mode==CheckExit && code != 0) {
- bgwaitclose(i);
- fatal("FAILED: %s", cmd);
- return;
- }
-
- bgwaitclose(i);
-}
-
-void
-bgwait(void)
-{
- while(nbg > 0)
- bgwait1();
-}
-
-// rgetwd returns a rune string form of the current directory's path.
-static Rune*
-rgetwd(void)
-{
- int n;
- Rune *r;
-
- n = GetCurrentDirectoryW(0, nil);
- r = xmalloc((n+1)*sizeof r[0]);
- GetCurrentDirectoryW(n+1, r);
- r[n] = '\0';
- return r;
-}
-
-void
-xgetwd(Buf *b)
-{
- Rune *r;
-
- r = rgetwd();
- breset(b);
- toutf(b, r);
- xfree(r);
-}
-
-void
-xrealwd(Buf *b, char *path)
-{
- Rune *old;
- Rune *rnew;
-
- old = rgetwd();
- torune(&rnew, path);
- if(!SetCurrentDirectoryW(rnew))
- fatal("chdir %s: %s", path, errstr());
- xfree(rnew);
- xgetwd(b);
- if(!SetCurrentDirectoryW(old)) {
- breset(b);
- toutf(b, old);
- fatal("chdir %s: %s", bstr(b), errstr());
- }
-}
-
-bool
-isdir(char *p)
-{
- DWORD attr;
- Rune *r;
-
- torune(&r, p);
- attr = GetFileAttributesW(r);
- xfree(r);
- return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
-}
-
-bool
-isfile(char *p)
-{
- DWORD attr;
- Rune *r;
-
- torune(&r, p);
- attr = GetFileAttributesW(r);
- xfree(r);
- return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
-}
-
-Time
-mtime(char *p)
-{
- HANDLE h;
- WIN32_FIND_DATAW data;
- Rune *r;
- FILETIME *ft;
-
- torune(&r, p);
- h = FindFirstFileW(r, &data);
- xfree(r);
- if(h == INVALID_HANDLE_VALUE)
- return 0;
- FindClose(h);
- ft = &data.ftLastWriteTime;
- return (Time)ft->dwLowDateTime + ((Time)ft->dwHighDateTime<<32);
-}
-
-bool
-isabs(char *p)
-{
- // c:/ or c:\ at beginning
- if(('A' <= p[0] && p[0] <= 'Z') || ('a' <= p[0] && p[0] <= 'z'))
- return p[1] == ':' && (p[2] == '/' || p[2] == '\\');
- // / or \ at beginning
- return p[0] == '/' || p[0] == '\\';
-}
-
-void
-readfile(Buf *b, char *file)
-{
- HANDLE h;
- Rune *r;
-
- breset(b);
- if(vflag > 2)
- errprintf("read %s\n", file);
- torune(&r, file);
- h = CreateFileW(r, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
- if(h == INVALID_HANDLE_VALUE)
- fatal("open %s: %s", file, errstr());
- breadfrom(b, h);
- CloseHandle(h);
-}
-
-void
-writefile(Buf *b, char *file, int exec)
-{
- HANDLE h;
- Rune *r;
- DWORD n;
-
- USED(exec);
-
- if(vflag > 2)
- errprintf("write %s\n", file);
- torune(&r, file);
- h = CreateFileW(r, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
- if(h == INVALID_HANDLE_VALUE)
- fatal("create %s: %s", file, errstr());
- n = 0;
- if(!WriteFile(h, b->p, b->len, &n, 0))
- fatal("write %s: %s", file, errstr());
- CloseHandle(h);
-}
-
-
-void
-xmkdir(char *p)
-{
- Rune *r;
-
- torune(&r, p);
- if(!CreateDirectoryW(r, nil))
- fatal("mkdir %s: %s", p, errstr());
- xfree(r);
-}
-
-void
-xmkdirall(char *p)
-{
- int c;
- char *q, *q2;
-
- if(isdir(p))
- return;
- q = strrchr(p, '/');
- q2 = strrchr(p, '\\');
- if(q2 != nil && (q == nil || q < q2))
- q = q2;
- if(q != nil) {
- c = *q;
- *q = '\0';
- xmkdirall(p);
- *q = c;
- }
- xmkdir(p);
-}
-
-void
-xremove(char *p)
-{
- int attr;
- Rune *r;
-
- torune(&r, p);
- attr = GetFileAttributesW(r);
- if(attr >= 0) {
- if(attr & FILE_ATTRIBUTE_DIRECTORY)
- RemoveDirectoryW(r);
- else
- DeleteFileW(r);
- }
- xfree(r);
-}
-
-void
-xreaddir(Vec *dst, char *dir)
-{
- Rune *r;
- Buf b;
- HANDLE h;
- WIN32_FIND_DATAW data;
- char *p, *q;
-
- binit(&b);
- vreset(dst);
-
- bwritestr(&b, dir);
- bwritestr(&b, "\\*");
- torune(&r, bstr(&b));
-
- h = FindFirstFileW(r, &data);
- xfree(r);
- if(h == INVALID_HANDLE_VALUE)
- goto out;
- do{
- toutf(&b, data.cFileName);
- p = bstr(&b);
- q = xstrrchr(p, '\\');
- if(q != nil)
- p = q+1;
- if(!streq(p, ".") && !streq(p, ".."))
- vadd(dst, p);
- }while(FindNextFileW(h, &data));
- FindClose(h);
-
-out:
- bfree(&b);
-}
-
-char*
-xworkdir(void)
-{
- Rune buf[1024];
- Rune tmp[MAX_PATH];
- Rune go[3] = {'g', 'o', '\0'};
- int n;
- Buf b;
-
- n = GetTempPathW(nelem(buf), buf);
- if(n <= 0)
- fatal("GetTempPath: %s", errstr());
- buf[n] = '\0';
-
- if(GetTempFileNameW(buf, go, 0, tmp) == 0)
- fatal("GetTempFileName: %s", errstr());
- DeleteFileW(tmp);
- if(!CreateDirectoryW(tmp, nil))
- fatal("create tempdir: %s", errstr());
-
- binit(&b);
- toutf(&b, tmp);
- return btake(&b);
-}
-
-void
-xremoveall(char *p)
-{
- int i;
- Buf b;
- Vec dir;
- Rune *r;
-
- binit(&b);
- vinit(&dir);
-
- torune(&r, p);
- if(isdir(p)) {
- xreaddir(&dir, p);
- for(i=0; i<dir.len; i++) {
- bprintf(&b, "%s/%s", p, dir.p[i]);
- xremoveall(bstr(&b));
- }
- RemoveDirectoryW(r);
- } else {
- DeleteFileW(r);
- }
- xfree(r);
-
- bfree(&b);
- vfree(&dir);
-}
-
-void
-fatal(char *msg, ...)
-{
- static char buf1[1024];
- va_list arg;
-
- va_start(arg, msg);
- vsnprintf(buf1, sizeof buf1, msg, arg);
- va_end(arg);
-
- errprintf("go tool dist: %s\n", buf1);
-
- bgwait();
- ExitProcess(1);
-}
-
-// HEAP is the persistent handle to the default process heap.
-static HANDLE HEAP = INVALID_HANDLE_VALUE;
-
-void*
-xmalloc(int n)
-{
- void *p;
-
- if(HEAP == INVALID_HANDLE_VALUE)
- HEAP = GetProcessHeap();
- p = HeapAlloc(HEAP, 0, n);
- if(p == nil)
- fatal("out of memory allocating %d: %s", n, errstr());
- memset(p, 0, n);
- return p;
-}
-
-char*
-xstrdup(char *p)
-{
- char *q;
-
- q = xmalloc(strlen(p)+1);
- strcpy(q, p);
- return q;
-}
-
-void
-xfree(void *p)
-{
- if(HEAP == INVALID_HANDLE_VALUE)
- HEAP = GetProcessHeap();
- HeapFree(HEAP, 0, p);
-}
-
-void*
-xrealloc(void *p, int n)
-{
- if(p == nil)
- return xmalloc(n);
- if(HEAP == INVALID_HANDLE_VALUE)
- HEAP = GetProcessHeap();
- p = HeapReAlloc(HEAP, 0, p, n);
- if(p == nil)
- fatal("out of memory reallocating %d", n);
- return p;
-}
-
-bool
-hassuffix(char *p, char *suffix)
-{
- int np, ns;
-
- np = strlen(p);
- ns = strlen(suffix);
- return np >= ns && streq(p+np-ns, suffix);
-}
-
-bool
-hasprefix(char *p, char *prefix)
-{
- return strncmp(p, prefix, strlen(prefix)) == 0;
-}
-
-bool
-contains(char *p, char *sep)
-{
- return strstr(p, sep) != nil;
-}
-
-bool
-streq(char *p, char *q)
-{
- return strcmp(p, q) == 0;
-}
-
-char*
-lastelem(char *p)
-{
- char *out;
-
- out = p;
- for(; *p; p++)
- if(*p == '/' || *p == '\\')
- out = p+1;
- return out;
-}
-
-void
-xmemmove(void *dst, void *src, int n)
-{
- memmove(dst, src, n);
-}
-
-int
-xmemcmp(void *a, void *b, int n)
-{
- return memcmp(a, b, n);
-}
-
-int
-xstrlen(char *p)
-{
- return strlen(p);
-}
-
-void
-xexit(int n)
-{
- ExitProcess(n);
-}
-
-void
-xatexit(void (*f)(void))
-{
- atexit(f);
-}
-
-void
-xprintf(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- vprintf(fmt, arg);
- va_end(arg);
-}
-
-void
-errprintf(char *fmt, ...)
-{
- va_list arg;
-
- va_start(arg, fmt);
- vfprintf(stderr, fmt, arg);
- va_end(arg);
-}
-
-int
-main(int argc, char **argv)
-{
- SYSTEM_INFO si;
-
- setvbuf(stdout, nil, _IOLBF, 0);
- setvbuf(stderr, nil, _IOLBF, 0);
-
- slash = "\\";
- gohostos = "windows";
-
- GetSystemInfo(&si);
- switch(si.wProcessorArchitecture) {
- case PROCESSOR_ARCHITECTURE_AMD64:
- gohostarch = "amd64";
- break;
- case PROCESSOR_ARCHITECTURE_INTEL:
- gohostarch = "386";
- break;
- default:
- fatal("unknown processor architecture");
- }
-
- init();
-
- xmain(argc, argv);
- return 0;
-}
-
-void
-xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*))
-{
- qsort(data, n, elemsize, cmp);
-}
-
-int
-xstrcmp(char *a, char *b)
-{
- return strcmp(a, b);
-}
-
-char*
-xstrstr(char *a, char *b)
-{
- return strstr(a, b);
-}
-
-char*
-xstrrchr(char *p, int c)
-{
- char *ep;
-
- ep = p+strlen(p);
- for(ep=p+strlen(p); ep >= p; ep--)
- if(*ep == c)
- return ep;
- return nil;
-}
-
-// xsamefile reports whether f1 and f2 are the same file (or dir)
-int
-xsamefile(char *f1, char *f2)
-{
- Rune *ru;
- HANDLE fd1, fd2;
- BY_HANDLE_FILE_INFORMATION fi1, fi2;
- int r;
-
- // trivial case
- if(streq(f1, f2))
- return 1;
-
- torune(&ru, f1);
- // refer to ../../os/stat_windows.go:/sameFile
- fd1 = CreateFileW(ru, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- xfree(ru);
- if(fd1 == INVALID_HANDLE_VALUE)
- return 0;
- torune(&ru, f2);
- fd2 = CreateFileW(ru, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- xfree(ru);
- if(fd2 == INVALID_HANDLE_VALUE) {
- CloseHandle(fd1);
- return 0;
- }
- r = GetFileInformationByHandle(fd1, &fi1) != 0 && GetFileInformationByHandle(fd2, &fi2) != 0;
- CloseHandle(fd2);
- CloseHandle(fd1);
- if(r != 0 &&
- fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber &&
- fi1.nFileIndexHigh == fi2.nFileIndexHigh &&
- fi1.nFileIndexLow == fi2.nFileIndexLow)
- return 1;
- return 0;
-}
-
-// xtryexecfunc tries to execute function f, if any illegal instruction
-// signal received in the course of executing that function, it will
-// return 0, otherwise it will return 1.
-int
-xtryexecfunc(void (*f)(void))
-{
- return 0; // suffice for now
-}
-
-static void
-cpuid(int dst[4], int ax)
-{
- // NOTE: This asm statement is for mingw.
- // If we ever support MSVC, use __cpuid(dst, ax)
- // to use the built-in.
-#if defined(__i386__) || defined(__x86_64__)
- asm volatile("cpuid"
- : "=a" (dst[0]), "=b" (dst[1]), "=c" (dst[2]), "=d" (dst[3])
- : "0" (ax));
-#else
- dst[0] = dst[1] = dst[2] = dst[3] = 0;
-#endif
-}
-
-bool
-cansse2(void)
-{
- int info[4];
-
- cpuid(info, 1);
- return (info[3] & (1<<26)) != 0; // SSE2
-}
-
-
-#endif // __WINDOWS__