// matchfield reports whether the field matches this build. static bool matchfield(char *f) { char *p; bool res; p = xstrrchr(f, ','); if(p == nil) return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1"); *p = 0; res = matchfield(f) && matchfield(p+1); *p = ','; return res; }
int markall(char buf[], int f) { char **np; int i; struct message *mp; char *namelist[NMLSIZE], *bufp; int tok, beg, mc, star, other, valdot, colmod, colresult; valdot = dot - &message[0] + 1; colmod = 0; for (i = 1; i <= msgCount; i++) unmark(i); bufp = buf; mc = 0; np = &namelist[0]; scaninit(); tok = scan(&bufp); star = 0; other = 0; beg = 0; while (tok != TEOL) { switch (tok) { case TNUMBER: number: if (star) { printf("No numbers mixed with *\n"); return (-1); } mc++; other++; if (beg != 0) { if (check(lexnumber, f)) return (-1); for (i = beg; i <= lexnumber; i++) if (f == MDELETED || (message[i - 1].m_flag & MDELETED) == 0) mark(i); beg = 0; break; } beg = lexnumber; if (check(beg, f)) return (-1); tok = scan(&bufp); regret(tok); if (tok != TDASH) { mark(beg); beg = 0; } break; case TPLUS: if (beg != 0) { printf("Non-numeric second argument\n"); return (-1); } i = valdot; do { i++; if (i > msgCount) { printf("Referencing beyond EOF\n"); return (-1); } } while ((message[i - 1].m_flag & MDELETED) != f); mark(i); break; case TDASH: if (beg == 0) { i = valdot; do { i--; if (i <= 0) { printf("Referencing before 1\n"); return (-1); } } while ((message[i - 1].m_flag & MDELETED) != f); mark(i); } break; case TSTRING: if (beg != 0) { printf("Non-numeric second argument\n"); return (-1); } other++; if (lexstring[0] == ':') { colresult = evalcol(lexstring[1]); if (colresult == 0) { printf("Unknown colon modifier \"%s\"\n", lexstring); return (-1); } colmod |= colresult; } else *np++ = savestr(lexstring); break; case TDOLLAR: case TUP: case TDOT: lexnumber = metamess(lexstring[0], f); if (lexnumber == -1) return (-1); goto number; case TSTAR: if (other) { printf("Can't mix \"*\" with anything\n"); return (-1); } star++; break; case TERROR: return (-1); } tok = scan(&bufp); } lastcolmod = colmod; *np = NULL; mc = 0; if (star) { for (i = 0; i < msgCount; i++) if ((message[i].m_flag & MDELETED) == f) { mark(i+1); mc++; } if (mc == 0) { printf("No applicable messages.\n"); return (-1); } return (0); } /* * If no numbers were given, mark all of the messages, * so that we can unmark any whose sender was not selected * if any user names were given. */ if ((np > namelist || colmod != 0) && mc == 0) for (i = 1; i <= msgCount; i++) if ((message[i-1].m_flag & MDELETED) == f) mark(i); /* * If any names were given, go through and eliminate any * messages whose senders were not requested. */ if (np > namelist) { for (i = 1; i <= msgCount; i++) { for (mc = 0, np = &namelist[0]; *np != NULL; np++) if (**np == '/') { if (matchfield(*np, i)) { mc++; break; } } else { if (matchsender(*np, i)) { mc++; break; } } if (mc == 0) unmark(i); } /* * Make sure we got some decent messages. */ mc = 0; for (i = 1; i <= msgCount; i++) if (message[i-1].m_flag & MMARK) { mc++; break; } if (mc == 0) { printf("No applicable messages from {%s", namelist[0]); for (np = &namelist[1]; *np != NULL; np++) printf(", %s", *np); printf("}\n"); return (-1); } } /* * If any colon modifiers were given, go through and * unmark any messages which do not satisfy the modifiers. */ if (colmod != 0) { for (i = 1; i <= msgCount; i++) { struct coltab *colp; mp = &message[i - 1]; for (colp = &coltab[0]; colp->co_char != '\0'; colp++) if (colp->co_bit & colmod) if ((mp->m_flag & colp->co_mask) != colp->co_equal) unmark(i); } for (mp = &message[0]; mp < &message[msgCount]; mp++) if (mp->m_flag & MMARK) break; if (mp >= &message[msgCount]) { struct coltab *colp; printf("No messages satisfy"); for (colp = &coltab[0]; colp->co_char != '\0'; colp++) if (colp->co_bit & colmod) printf(" :%c", colp->co_char); printf("\n"); return (-1); } } return (0); }
// shouldbuild reports whether we should build this file. // It applies the same rules that are used with context tags // in package go/build, except that the GOOS and GOARCH // can appear anywhere in the file name, not just after _. // In particular, they can be the entire file name (like windows.c). // We also allow the special tag cmd_go_bootstrap. // See ../go/bootstrap.go and package go/build. static bool shouldbuild(char *file, char *dir) { char *name, *p; int i, j, ret; Buf b; Vec lines, fields; // Check file name for GOOS or GOARCH. name = lastelem(file); for(i=0; i<nelem(okgoos); i++) if(contains(name, okgoos[i]) && !streq(okgoos[i], goos)) return 0; for(i=0; i<nelem(okgoarch); i++) if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch)) return 0; // Omit test files. if(contains(name, "_test")) return 0; // cmd/go/doc.go has a giant /* */ comment before // it gets to the important detail that it is not part of // package main. We don't parse those comments, // so special case that file. if(hassuffix(file, "cmd/go/doc.go") || hassuffix(file, "cmd\\go\\doc.go")) return 0; if(hassuffix(file, "cmd/cgo/doc.go") || hassuffix(file, "cmd\\cgo\\doc.go")) return 0; // Check file contents for // +build lines. binit(&b); vinit(&lines); vinit(&fields); ret = 1; readfile(&b, file); splitlines(&lines, bstr(&b)); for(i=0; i<lines.len; i++) { p = lines.p[i]; while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') p++; if(*p == '\0') continue; if(contains(p, "package documentation")) { ret = 0; goto out; } if(contains(p, "package main") && !streq(dir, "cmd/go") && !streq(dir, "cmd/cgo")) { ret = 0; goto out; } if(!hasprefix(p, "//")) break; if(!contains(p, "+build")) continue; splitfields(&fields, lines.p[i]); if(fields.len < 2 || !streq(fields.p[1], "+build")) continue; for(j=2; j<fields.len; j++) { p = fields.p[j]; if((*p == '!' && !matchfield(p+1)) || matchfield(p)) goto fieldmatch; } ret = 0; goto out; fieldmatch:; } out: bfree(&b); vfree(&lines); vfree(&fields); return ret; }