Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(40)

Delta Between Two Patch Sets: src/cmd/dist/plan9.c

Issue 5608059: code review 5608059: build: dist-based build for Plan 9 (Closed)
Left Patch Set: diff -r f01e8edddf01 https://code.google.com/p/go/ Created 13 years, 2 months ago
Right Patch Set: diff -r cb5c48bccd5a https://code.google.com/p/go/ Created 12 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/dist/goc2c.c ('k') | src/make.rc » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // These #ifdefs are being used as a substitute for 5 // These #ifdefs are being used as a substitute for
6 // build configuration, so that on any system, this 6 // build configuration, so that on any system, this
7 // tool can be built with the local equivalent of 7 // tool can be built with the local equivalent of
8 // cc *.c 8 // cc *.c
9 // 9 //
10 #ifdef PLAN9 10 #ifdef PLAN9
11 11
12 #include <u.h>
13 #include <libc.h>
14 #include <stdio.h>
15 #undef nil
16 #undef nelem
12 #include "a.h" 17 #include "a.h"
13 18
14 // bprintf replaces the buffer with the result of the printf formatting 19 // bprintf replaces the buffer with the result of the printf formatting
15 // and returns a pointer to the NUL-terminated buffer contents. 20 // and returns a pointer to the NUL-terminated buffer contents.
16 char* 21 char*
17 bprintf(Buf *b, char *fmt, ...) 22 bprintf(Buf *b, char *fmt, ...)
18 { 23 {
19 va_list arg; 24 va_list arg;
20 char buf[4096]; 25 char buf[4096];
21 ········ 26 ········
22 breset(b); 27 breset(b);
23 va_start(arg, fmt); 28 va_start(arg, fmt);
24 » vsnprint(buf, sizeof buf, fmt, arg); 29 » vsnprintf(buf, sizeof buf, fmt, arg);
25 va_end(arg); 30 va_end(arg);
26 bwritestr(b, buf); 31 bwritestr(b, buf);
27 return bstr(b); 32 return bstr(b);
28 } 33 }
29 34
30 // bpathf is the same as bprintf (on windows it turns / into \ after the printf) . 35 // bpathf is the same as bprintf (on windows it turns / into \ after the printf) .
31 // It returns a pointer to the NUL-terminated buffer contents. 36 // It returns a pointer to the NUL-terminated buffer contents.
32 char* 37 char*
33 bpathf(Buf *b, char *fmt, ...) 38 bpathf(Buf *b, char *fmt, ...)
34 { 39 {
35 va_list arg; 40 va_list arg;
36 char buf[4096]; 41 char buf[4096];
37 ········ 42 ········
38 breset(b); 43 breset(b);
39 va_start(arg, fmt); 44 va_start(arg, fmt);
40 » vsnprint(buf, sizeof buf, fmt, arg); 45 » vsnprintf(buf, sizeof buf, fmt, arg);
41 va_end(arg); 46 va_end(arg);
42 bwritestr(b, buf); 47 bwritestr(b, buf);
43 return bstr(b); 48 return bstr(b);
44 } 49 }
45 50
46 // bwritef is like bprintf but does not reset the buffer 51 // bwritef is like bprintf but does not reset the buffer
47 // and does not return the NUL-terminated string. 52 // and does not return the NUL-terminated string.
48 void 53 void
49 bwritef(Buf *b, char *fmt, ...) 54 bwritef(Buf *b, char *fmt, ...)
50 { 55 {
51 va_list arg; 56 va_list arg;
52 char buf[4096]; 57 char buf[4096];
53 ········ 58 ········
54 va_start(arg, fmt); 59 va_start(arg, fmt);
55 » vsnprint(buf, sizeof buf, fmt, arg); 60 » vsnprintf(buf, sizeof buf, fmt, arg);
56 va_end(arg); 61 va_end(arg);
57 bwritestr(b, buf); 62 bwritestr(b, buf);
58 } 63 }
59 64
60 // breadfrom appends to b all the data that can be read from fd. 65 // breadfrom appends to b all the data that can be read from fd.
61 static void 66 static void
62 breadfrom(Buf *b, int fd) 67 breadfrom(Buf *b, int fd)
63 { 68 {
64 int n; 69 int n;
65 70
66 for(;;) { 71 for(;;) {
67 bgrow(b, 4096); 72 bgrow(b, 4096);
68 n = read(fd, b->p+b->len, 4096); 73 n = read(fd, b->p+b->len, 4096);
69 if(n < 0) 74 if(n < 0)
70 » » » fatal("read: %r"); 75 » » » fatal("read");
71 if(n == 0) 76 if(n == 0)
72 break; 77 break;
73 b->len += n; 78 b->len += n;
74 } 79 }
75 } 80 }
76 81
77 // xgetenv replaces b with the value of the named environment variable. 82 // xgetenv replaces b with the value of the named environment variable.
78 void 83 void
79 xgetenv(Buf *b, char *name) 84 xgetenv(Buf *b, char *name)
80 { 85 {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 { 130 {
126 genrun(nil, dir, mode, argv, 0); 131 genrun(nil, dir, mode, argv, 0);
127 } 132 }
128 133
129 #define MAXBG 4 /* maximum number of jobs to run at once */ 134 #define MAXBG 4 /* maximum number of jobs to run at once */
130 135
131 static struct { 136 static struct {
132 int pid; 137 int pid;
133 int mode; 138 int mode;
134 char *cmd; 139 char *cmd;
140 Buf *b;
135 } bg[MAXBG]; 141 } bg[MAXBG];
136 static int nbg; 142 static int nbg;
143 static int maxnbg = nelem(bg);
137 144
138 static void bgwait1(void); 145 static void bgwait1(void);
139 146
140 // genrun is the generic run implementation. 147 // genrun is the generic run implementation.
141 static void 148 static void
142 genrun(Buf *b, char *dir, int mode, Vec *argv, int wait) 149 genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
143 { 150 {
144 int i, p[2], pid; 151 int i, p[2], pid;
145 Buf b1, cmd; 152 Buf b1, cmd;
146 char *q; 153 char *q;
147 154
148 » while(nbg >= nelem(bg)) 155 » while(nbg >= maxnbg)
149 bgwait1(); 156 bgwait1();
150 157
151 binit(&b1); 158 binit(&b1);
152 » if(isabs(argv->p[0])) 159 » binit(&cmd);
153 » » argv0 = argv->p[0]; 160
154 » else { 161 » if(!isabs(argv->p[0])) {
155 bpathf(&b1, "/bin/%s", argv->p[0]); 162 bpathf(&b1, "/bin/%s", argv->p[0]);
156 » » argv0 = btake(&b1); 163 » » free(argv->p[0]);
157 » } 164 » » argv->p[0] = xstrdup(bstr(&b1));
158 » bfree(&b1); 165 » }
159 166
160 // Generate a copy of the command to show in a log. 167 // Generate a copy of the command to show in a log.
161 // Substitute $WORK for the work directory. 168 // Substitute $WORK for the work directory.
162 binit(&cmd);
163 for(i=0; i<argv->len; i++) { 169 for(i=0; i<argv->len; i++) {
164 if(i > 0) 170 if(i > 0)
165 bwritestr(&cmd, " "); 171 bwritestr(&cmd, " ");
166 q = argv->p[i]; 172 q = argv->p[i];
167 if(workdir != nil && hasprefix(q, workdir)) { 173 if(workdir != nil && hasprefix(q, workdir)) {
168 bwritestr(&cmd, "$WORK"); 174 bwritestr(&cmd, "$WORK");
169 q += strlen(workdir); 175 q += strlen(workdir);
170 } 176 }
171 bwritestr(&cmd, q); 177 bwritestr(&cmd, q);
172 } 178 }
173 if(vflag > 1) 179 if(vflag > 1)
174 xprintf("%s\n", bstr(&cmd)); 180 xprintf("%s\n", bstr(&cmd));
175 181
176 if(b != nil) { 182 if(b != nil) {
177 breset(b); 183 breset(b);
178 if(pipe(p) < 0) 184 if(pipe(p) < 0)
179 » » » fatal("pipe: %r"); 185 » » » fatal("pipe");
180 } 186 }
181 187
182 switch(pid = fork()) { 188 switch(pid = fork()) {
183 case -1: 189 case -1:
184 » » fatal("fork: %r"); 190 » » fatal("fork");
185 case 0: 191 case 0:
186 if(b != nil) { 192 if(b != nil) {
187 close(0); 193 close(0);
188 close(p[0]); 194 close(p[0]);
189 dup(p[1], 1); 195 dup(p[1], 1);
190 dup(p[1], 2); 196 dup(p[1], 2);
191 if(p[1] > 2) 197 if(p[1] > 2)
192 close(p[1]); 198 close(p[1]);
193 } 199 }
194 if(dir != nil) { 200 if(dir != nil) {
195 if(chdir(dir) < 0) { 201 if(chdir(dir) < 0) {
196 » » » » fprint(2, "chdir %s: %r\n", dir); 202 » » » » fprint(2, "chdir: %r\n");
197 _exits("chdir"); 203 _exits("chdir");
198 } 204 }
199 } 205 }
200 vadd(argv, nil); 206 vadd(argv, nil);
201 exec(argv->p[0], argv->p); 207 exec(argv->p[0], argv->p);
202 fprint(2, "%s\n", bstr(&cmd)); 208 fprint(2, "%s\n", bstr(&cmd));
203 » » fprint(2, "exec %s: %r\n", argv0); 209 » » fprint(2, "exec: %r\n");
204 _exits("exec"); 210 _exits("exec");
205 } 211 }
206 if(b != nil) { 212 if(b != nil) {
207 close(p[1]); 213 close(p[1]);
208 breadfrom(b, p[0]); 214 breadfrom(b, p[0]);
209 close(p[0]); 215 close(p[0]);
210 } 216 }
211 217
212 if(nbg < 0) 218 if(nbg < 0)
213 fatal("bad bookkeeping"); 219 fatal("bad bookkeeping");
214 bg[nbg].pid = pid; 220 bg[nbg].pid = pid;
215 bg[nbg].mode = mode; 221 bg[nbg].mode = mode;
216 bg[nbg].cmd = btake(&cmd); 222 bg[nbg].cmd = btake(&cmd);
223 bg[nbg].b = b;
217 nbg++; 224 nbg++;
218 ········ 225 ········
219 if(wait) 226 if(wait)
220 bgwait(); 227 bgwait();
221 228
222 bfree(&cmd); 229 bfree(&cmd);
230 bfree(&b1);
223 } 231 }
224 232
225 // bgwait1 waits for a single background job. 233 // bgwait1 waits for a single background job.
226 static void 234 static void
227 bgwait1(void) 235 bgwait1(void)
228 { 236 {
229 Waitmsg *w; 237 Waitmsg *w;
230 int i, mode; 238 int i, mode;
231 char *cmd; 239 char *cmd;
240 Buf *b;
232 241
233 w = wait(); 242 w = wait();
234 if(w == nil) 243 if(w == nil)
235 » » fatal("wait: %r"); 244 » » fatal("wait");
236 ················ 245 ················
237 for(i=0; i<nbg; i++) 246 for(i=0; i<nbg; i++)
238 if(bg[i].pid == w->pid) 247 if(bg[i].pid == w->pid)
239 goto ok; 248 goto ok;
240 fatal("wait: unexpected pid"); 249 fatal("wait: unexpected pid");
241 250
242 ok: 251 ok:
243 cmd = bg[i].cmd; 252 cmd = bg[i].cmd;
244 mode = bg[i].mode; 253 mode = bg[i].mode;
245 bg[i].pid = 0; 254 bg[i].pid = 0;
255 b = bg[i].b;
256 bg[i].b = nil;
246 bg[i] = bg[--nbg]; 257 bg[i] = bg[--nbg];
247 ········ 258 ········
248 » if(mode == CheckExit && w->msg[0]) 259 » if(mode == CheckExit && w->msg[0]) {
260 » » if(b != nil)
261 » » » xprintf("%s\n", bstr(b));
249 fatal("FAILED: %s", cmd); 262 fatal("FAILED: %s", cmd);
263 }
250 xfree(cmd); 264 xfree(cmd);
251 } 265 }
252 266
253 // bgwait waits for all the background jobs. 267 // bgwait waits for all the background jobs.
254 void 268 void
255 bgwait(void) 269 bgwait(void)
256 { 270 {
257 while(nbg > 0) 271 while(nbg > 0)
258 bgwait1(); 272 bgwait1();
259 } 273 }
260 274
261 // xgetwd replaces b with the current directory. 275 // xgetwd replaces b with the current directory.
262 void 276 void
263 xgetwd(Buf *b) 277 xgetwd(Buf *b)
264 { 278 {
265 char buf[4096]; 279 char buf[4096];
266 ········ 280 ········
267 breset(b); 281 breset(b);
268 if(getwd(buf, sizeof buf) == nil) 282 if(getwd(buf, sizeof buf) == nil)
269 » » fatal("getcwd: %r"); 283 » » fatal("getwd");
270 bwritestr(b, buf); 284 bwritestr(b, buf);
271 } 285 }
272 286
273 // xrealwd replaces b with the 'real' name for the given path. 287 // xrealwd replaces b with the 'real' name for the given path.
274 // real is defined as what getcwd returns in that directory. 288 // real is defined as what getcwd returns in that directory.
275 void 289 void
276 xrealwd(Buf *b, char *path) 290 xrealwd(Buf *b, char *path)
277 { 291 {
278 char buf[4096]; 292 char buf[4096];
279 int fd; 293 int fd;
280 294
281 » fd = open(".", 0); 295 » fd = open(path, OREAD);
282 » if(fd < 0)
283 » » fatal("open .: %r");
284 » if(chdir(path) < 0)
285 » » fatal("chdir %s: %r", path);
286 » xgetwd(b);
287 if(fd2path(fd, buf, sizeof buf) < 0) 296 if(fd2path(fd, buf, sizeof buf) < 0)
288 » » fatal("fdpath: %r"); 297 » » fatal("fd2path");
289 » if(chdir(buf) < 0)
290 » » fatal("chdir %s: %r", buf);
291 close(fd); 298 close(fd);
299 breset(b);
300 bwritestr(b, buf);
292 } 301 }
293 302
294 // isdir reports whether p names an existing directory. 303 // isdir reports whether p names an existing directory.
295 bool 304 bool
296 isdir(char *p) 305 isdir(char *p)
297 { 306 {
298 Dir *d; 307 Dir *d;
299 ulong mode; 308 ulong mode;
300 309
301 d = dirstat(p); 310 d = dirstat(p);
(...skipping 24 matching lines...) Expand all
326 mtime(char *p) 335 mtime(char *p)
327 { 336 {
328 Dir *d; 337 Dir *d;
329 ulong t; 338 ulong t;
330 339
331 d = dirstat(p); 340 d = dirstat(p);
332 if(d == nil) 341 if(d == nil)
333 return 0; 342 return 0;
334 t = d->mtime; 343 t = d->mtime;
335 free(d); 344 free(d);
336 » return (Time)t*1000000000LL; 345 » return (Time)t;
337 } 346 }
338 347
339 // isabs reports whether p is an absolute path. 348 // isabs reports whether p is an absolute path.
340 bool 349 bool
341 isabs(char *p) 350 isabs(char *p)
342 { 351 {
343 return hasprefix(p, "/"); 352 return hasprefix(p, "/");
344 } 353 }
345 354
346 // readfile replaces b with the content of the named file. 355 // readfile replaces b with the content of the named file.
347 void 356 void
348 readfile(Buf *b, char *file) 357 readfile(Buf *b, char *file)
349 { 358 {
350 int fd; 359 int fd;
351 » 360
352 breset(b); 361 breset(b);
353 fd = open(file, OREAD); 362 fd = open(file, OREAD);
354 if(fd < 0) 363 if(fd < 0)
355 » » fatal("open %s: %r", file); 364 » » fatal("open %s", file);
356 breadfrom(b, fd); 365 breadfrom(b, fd);
357 close(fd); 366 close(fd);
358 } 367 }
359 368
360 // writefile writes b to the named file, creating it if needed. 369 // writefile writes b to the named file, creating it if needed.
361 void 370 void
362 writefile(Buf *b, char *file) 371 writefile(Buf *b, char *file, int exec)
363 { 372 {
364 int fd; 373 int fd;
374 Dir d;
365 ········ 375 ········
366 fd = create(file, ORDWR, 0666); 376 fd = create(file, ORDWR, 0666);
367 if(fd < 0) 377 if(fd < 0)
368 » » fatal("create %s: %r", file); 378 » » fatal("create %s", file);
369 if(write(fd, b->p, b->len) != b->len) 379 if(write(fd, b->p, b->len) != b->len)
370 » » fatal("short write: %r"); 380 » » fatal("short write");
381 » if(exec) {
382 » » nulldir(&d);
383 » » d.mode = 0755;
384 » » dirfwstat(fd, &d);
385 » }
371 close(fd); 386 close(fd);
372 } 387 }
373 » 388
374 // xmkdir creates the directory p. 389 // xmkdir creates the directory p.
375 void 390 void
376 xmkdir(char *p) 391 xmkdir(char *p)
377 { 392 {
378 Dir *d;
379 int fd; 393 int fd;
380 394
381 » fd = open(p, OREAD); 395 » if(isdir(p))
382 » if(fd < 0) {
383 » » fd = create(p, OREAD, 0777|DMDIR);
384 » » if(fd < 0)
385 » » » fatal("mkdir create %s: %r", p);
386 » » close(fd);
387 return; 396 return;
388 » } 397 » fd = create(p, OREAD, 0777|DMDIR);
389 » d = dirfstat(fd);
390 » if(d == nil)
391 » » fatal("mkdir %s: stat: %r", p);
392 » if((d->mode & DMDIR) == 0)
393 » » fatal("mkdir %s: not a directory", p);
394 » free(d);
395 close(fd); 398 close(fd);
399 if(fd < 0)
400 fatal("mkdir %s", p);
396 } 401 }
397 402
398 // xmkdirall creates the directory p and its parents, as needed. 403 // xmkdirall creates the directory p and its parents, as needed.
399 void 404 void
400 xmkdirall(char *p) 405 xmkdirall(char *p)
401 { 406 {
402 char *q; 407 char *q;
403 408
404 if(isdir(p)) 409 if(isdir(p))
405 return; 410 return;
406 q = strrchr(p, '/'); 411 q = strrchr(p, '/');
407 if(q != nil) { 412 if(q != nil) {
408 *q = '\0'; 413 *q = '\0';
409 xmkdirall(p); 414 xmkdirall(p);
410 *q = '/'; 415 *q = '/';
411 } 416 }
412 xmkdir(p); 417 xmkdir(p);
413 } 418 }
414 419
415 // xremove removes the file p. 420 // xremove removes the file p.
416 void 421 void
417 xremove(char *p) 422 xremove(char *p)
418 { 423 {
419 » if(vflag > 1) 424 » if(vflag > 2)
420 xprintf("rm %s\n", p); 425 xprintf("rm %s\n", p);
421 remove(p); 426 remove(p);
422 } 427 }
423 428
424 // xremoveall removes the file or directory tree rooted at p. 429 // xremoveall removes the file or directory tree rooted at p.
425 void 430 void
426 xremoveall(char *p) 431 xremoveall(char *p)
427 { 432 {
428 int i; 433 int i;
429 Buf b; 434 Buf b;
430 Vec dir; 435 Vec dir;
431 436
432 binit(&b); 437 binit(&b);
433 vinit(&dir); 438 vinit(&dir);
434 439
435 if(isdir(p)) { 440 if(isdir(p)) {
436 xreaddir(&dir, p); 441 xreaddir(&dir, p);
437 for(i=0; i<dir.len; i++) { 442 for(i=0; i<dir.len; i++) {
438 bprintf(&b, "%s/%s", p, dir.p[i]); 443 bprintf(&b, "%s/%s", p, dir.p[i]);
439 xremoveall(bstr(&b)); 444 xremoveall(bstr(&b));
440 } 445 }
441 } 446 }
442 » if(vflag > 1) 447 » if(vflag > 2)
443 xprintf("rm %s\n", p); 448 xprintf("rm %s\n", p);
444 remove(p); 449 remove(p);
445 ········ 450 ········
446 bfree(&b); 451 bfree(&b);
447 vfree(&dir);···· 452 vfree(&dir);····
448 } 453 }
449 454
450 // xreaddir replaces dst with a list of the names of the files in dir. 455 // xreaddir replaces dst with a list of the names of the files in dir.
451 // The names are relative to dir; they are not full paths. 456 // The names are relative to dir; they are not full paths.
452 void 457 void
453 xreaddir(Vec *dst, char *dir) 458 xreaddir(Vec *dst, char *dir)
454 { 459 {
455 Dir *d; 460 Dir *d;
456 int fd, i, n; 461 int fd, i, n;
457 462
458 vreset(dst); 463 vreset(dst);
459 464
460 fd = open(dir, OREAD); 465 fd = open(dir, OREAD);
461 if(fd < 0) 466 if(fd < 0)
462 » » fatal("open %s: %r", dir); 467 » » fatal("open %s", dir);
463 n = dirreadall(fd, &d); 468 n = dirreadall(fd, &d);
464 for(i=0; i<n; i++) 469 for(i=0; i<n; i++)
465 vadd(dst, d[i].name); 470 vadd(dst, d[i].name);
466 free(d); 471 free(d);
467 close(fd); 472 close(fd);
468 } 473 }
469 474
470 // xworkdir creates a new temporary directory to hold object files 475 // xworkdir creates a new temporary directory to hold object files
471 // and returns the name of that directory. 476 // and returns the name of that directory.
472 char* 477 char*
473 xworkdir(void) 478 xworkdir(void)
474 { 479 {
475 Buf b; 480 Buf b;
476 char *p; 481 char *p;
477 int fd, tries; 482 int fd, tries;
478 483
479 binit(&b); 484 binit(&b);
480 485
481 fd = 0; 486 fd = 0;
482 for(tries=0; tries<1000; tries++) { 487 for(tries=0; tries<1000; tries++) {
483 bprintf(&b, "/tmp/go-cbuild-%06x", nrand((1<<24)-1)); 488 bprintf(&b, "/tmp/go-cbuild-%06x", nrand((1<<24)-1));
484 » » fd = create(bstr(&b), OREAD, 0700|DMDIR); 489 » » fd = create(bstr(&b), OREAD|OEXCL, 0700|DMDIR);
485 if(fd >= 0) 490 if(fd >= 0)
486 goto done; 491 goto done;
487 } 492 }
488 » fatal("xworkdir create: %r"); 493 » fatal("xworkdir create");
489 494
490 done: 495 done:
491 close(fd); 496 close(fd);
492 p = btake(&b); 497 p = btake(&b);
493 498
494 bfree(&b); 499 bfree(&b);
495 return p; 500 return p;
496 } 501 }
497 502
498 // fatal prints an error message to standard error and exits. 503 // fatal prints an error message to standard error and exits.
499 void 504 void
500 fatal(char *msg, ...) 505 fatal(char *msg, ...)
501 { 506 {
507 char buf[ERRMAX];
502 va_list arg; 508 va_list arg;
503 ········ 509 ········
504 » fprint(2, "go tool dist: "); 510 » rerrstr(buf, sizeof buf);
511
512 » fflush(stdout);
513 » fprintf(stderr, "go tool dist: ");
505 va_start(arg, msg); 514 va_start(arg, msg);
506 » vfprint(2, msg, arg); 515 » vfprintf(stderr, msg, arg);
507 va_end(arg); 516 va_end(arg);
508 » fprint(2, "\n"); 517
518 » if(buf[0])
519 » » fprintf(stderr, ": %s", buf);
520 » fprintf(stderr, "\n");
521
522 » bgwait();
509 exits(msg); 523 exits(msg);
510 } 524 }
511 525
512 // xmalloc returns a newly allocated zeroed block of n bytes of memory. 526 // xmalloc returns a newly allocated zeroed block of n bytes of memory.
513 // It calls fatal if it runs out of memory. 527 // It calls fatal if it runs out of memory.
514 void* 528 void*
515 xmalloc(int n) 529 xmalloc(int n)
516 { 530 {
517 void *p; 531 void *p;
518 ········ 532 ········
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 { 632 {
619 return strlen(p); 633 return strlen(p);
620 } 634 }
621 635
622 // xexit exits the process with return code n. 636 // xexit exits the process with return code n.
623 void 637 void
624 xexit(int n) 638 xexit(int n)
625 { 639 {
626 char buf[32]; 640 char buf[32];
627 641
628 » snprint(buf, sizeof buf, "%d", n); 642 » snprintf(buf, sizeof buf, "%d", n);
629 exits(buf); 643 exits(buf);
630 } 644 }
631 645
632 // xatexit schedules the exit-handler f to be run when the program exits. 646 // xatexit schedules the exit-handler f to be run when the program exits.
633 void 647 void
634 xatexit(void (*f)(void)) 648 xatexit(void (*f)(void))
635 { 649 {
636 atexit(f); 650 atexit(f);
637 } 651 }
638 652
639 // xprintf prints a message to standard output. 653 // xprintf prints a message to standard output.
640 void 654 void
641 xprintf(char *fmt, ...) 655 xprintf(char *fmt, ...)
642 { 656 {
643 va_list arg; 657 va_list arg;
644 ········ 658 ········
645 va_start(arg, fmt); 659 va_start(arg, fmt);
646 » vfprint(1, fmt, arg); 660 » vprintf(fmt, arg);
647 va_end(arg); 661 va_end(arg);
648 } 662 }
649 663
650 // xsetenv sets the environment variable $name to the given value. 664 // xsetenv sets the environment variable $name to the given value.
651 void 665 void
652 xsetenv(char *name, char *value) 666 xsetenv(char *name, char *value)
653 { 667 {
654 putenv(name, value); 668 putenv(name, value);
655 } 669 }
656 670
657 // main takes care of OS-specific startup and dispatches to xmain. 671 // main takes care of OS-specific startup and dispatches to xmain.
658 int 672 void
659 main(int argc, char **argv) 673 main(int argc, char **argv)
660 { 674 {
661 » char *p; 675 » Buf b;
662 » Buf b, b1; 676
677 » setvbuf(stdout, nil, _IOLBF, BUFSIZ);
678 » setvbuf(stderr, nil, _IOLBF, BUFSIZ);
663 679
664 binit(&b); 680 binit(&b);
665 » binit(&b1); 681
666 682 » rfork(RFENVG);
667 » p = argv[0]; 683
668 » if(hassuffix(p, "bin/tool/dist")) {
669 » » default_goroot = xstrdup(p);
670 » » default_goroot[strlen(p)-strlen("bin/tool/dist")] = '\0';
671 » }
672 »·······
673 slash = "/"; 684 slash = "/";
674 gohostos = "plan9"; 685 gohostos = "plan9";
675 686
676 » xgetenv(&b1, "objtype"); 687 » xgetenv(&b, "objtype");
677 » if(b1.len == 0) 688 » if(b.len == 0)
678 fatal("$objtype is unset"); 689 fatal("$objtype is unset");
679 » gohostarch = btake(&b1); 690 » gohostarch = btake(&b);
691
692 » xgetenv(&b, "GOBIN");
693 » if(b.len == 0){
694 » » bpathf(&b, "/%s/bin", gohostarch);
695 » » xsetenv("GOBIN", bstr(&b));
696 » }
680 697
681 srand(time(0)+getpid()); 698 srand(time(0)+getpid());
682 rfork(RFENVG);
683 init(); 699 init();
684 xmain(argc, argv); 700 xmain(argc, argv);
685 701
686 bfree(&b1);
687 bfree(&b); 702 bfree(&b);
688 » return 0; 703 » exits(nil);
689 } 704 }
690 705
691 // xqsort is a wrapper for the C standard qsort. 706 // xqsort is a wrapper for the C standard qsort.
692 void 707 void
693 xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*)) 708 xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*))
694 { 709 {
695 qsort(data, n, elemsize, cmp); 710 qsort(data, n, elemsize, cmp);
696 } 711 }
697 712
698 // xstrcmp compares the NUL-terminated strings a and b. 713 // xstrcmp compares the NUL-terminated strings a and b.
(...skipping 10 matching lines...) Expand all
709 return strstr(a, b); 724 return strstr(a, b);
710 } 725 }
711 726
712 // xstrrchr returns a pointer to the final occurrence of c in p. 727 // xstrrchr returns a pointer to the final occurrence of c in p.
713 char* 728 char*
714 xstrrchr(char *p, int c) 729 xstrrchr(char *p, int c)
715 { 730 {
716 return strrchr(p, c); 731 return strrchr(p, c);
717 } 732 }
718 733
719 #endif // __WINDOWS__ 734 #endif // PLAN9
rsc 2012/02/04 06:52:56 PLAN9
ality 2012/02/04 07:23:13 Done.
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b