Lptr AppendLptr (Lptr list1, Lptr list2) { Lptr ptr; #ifdef DEBUG_APPEND { Lptr ptr1, ptr2; for (ptr1 = list1; ptr1; ptr1 = ptr1->next) { for (ptr2 = list2; ptr2; ptr2 = ptr2->next) { if (ptr1 == ptr2) Punt ("ptr1 == ptr2 found"); if (free_list == 0) { if (ptr1->ptr == ptr2->ptr) Punt ("ptr1->ptr == ptr2->ptr found"); } } } } #endif if (list1 == 0) return list2; for (ptr = list1; ptr->next != 0; ptr = ptr->next) ; ptr->next = list2; return list1; }
Lint AppendLint (Lint list1, Lint list2) { Lint ptr; #ifdef DEBUG_APPEND { Lint ptr1, ptr2; for (ptr1 = list1; ptr1; ptr1 = ptr1->next) { for (ptr2 = list2; ptr2; ptr2 = ptr2->next) { if (ptr1 == ptr2) Punt ("ptr1 == ptr2 found"); if (free_list == 0) { if (ptr1->id == ptr2->id) Punt ("ptr1->id == ptr2->id found"); } } } } #endif if (list1 == 0) return list2; for (ptr = list1; ptr->next != 0; ptr = ptr->next) ; ptr->next = list2; return list1; }
/* * Apple trace selection on a given graph. */ void TraceSelection (FGraph graph, int method, double min_prob) { if (graph == 0) Punt ("TraceSelection: nil graph"); if ((min_prob < 0.0) || (min_prob > 1.0)) Punt ("TraceSelection: min_prob must be within [0..1]"); #ifdef DEBUG printf ("### BEFORE\n"); WriteGraph ("stdout", graph); #endif /* * The old selection program. */ switch (method) { case SELECT_BY_NODE_WEIGHT: best_successor_of = best_successor_1; best_predecessor_of = best_predecessor_1; min_prob_requirement = 0; SelectTraces (graph); PlaceTraces (graph); break; case SELECT_BY_ARC_WEIGHT: best_successor_of = best_successor_2; best_predecessor_of = best_predecessor_2; min_prob_requirement = 0; SelectTraces (graph); PlaceTraces (graph); break; case SELECT_BY_MIN_PROB: best_successor_of = best_successor_3; best_predecessor_of = best_predecessor_3; min_prob_requirement = min_prob; SelectTraces (graph); PlaceTraces (graph); break; case SELECT_BY_MAX_ARC: SelectBySortArc (graph); PlaceTraces (graph); break; default: Punt ("TraceSelection: illegal selection method"); } #ifdef DEBUG printf ("### AFTER\n"); WriteGraph ("stdout", graph); #endif }
void DeleteFileAndCheck(char *name) { if (strcmp(name, "/dev/null") != 0 && unlink(name) == -1) { char str[500]; perror(progName); (void)sprintf(str, "DeleteFileAndCheck(%s) failed!", name); Punt(str); } }
FILEPTR FOpenAndCheck(char *name, char *mode) { FILEPTR result; result = myfopen(name, mode); if (result == NULL) { char str[500]; perror(progName); (void)sprintf(str, "Error in FOpenAndCheck(%s, %s)", name, mode); Punt(str); } return result; }
void RenameAndCheck(char *from, char *to) { if (rename(from, to) == -1) { if (errno != EXDEV) { char str[500]; perror(progName); (void)sprintf(str, "RenameAndCheck(%s->%s) failed!", from, to); Punt(str); } CopyFileAndCheck(from, to); DeleteFileAndCheck(from); } }
Lint NewLint (int id) { Lint new_lint; if (d_lint != 0) { new_lint = d_lint; d_lint = d_lint->next; } else { new_lint = (Lint) L_alloc (Lint_Pool); if (new_lint == 0) Punt ("NewLint: out of memory space"); } new_lint->next = 0; new_lint->id = id; return new_lint; }
void CopyFileAndCheck(char *from, char *to) { int fromfid, tofid, n; char buf[512]; fromfid = myopen(from, O_RDONLY, 0666); tofid = myopen(to, O_WRONLY | O_TRUNC | O_CREAT, 0666); if (fromfid < 0 || tofid < 0) { perror(progName); (void)sprintf(buf, "CopyFileAndCheck(%s->%s) failed!", from, to); Punt(buf); } do { n = read(fromfid, buf, 512); if (n) (void) write(tofid, buf, n); } while (n); myclose(fromfid); myclose(tofid); }
Lptr NewLptr (void * ptr) { Lptr new_ptr; if (d_lptr != 0) { new_ptr = d_lptr; d_lptr = d_lptr->next; } else { if (!Lptr_Pool) Init_NewLptr(); new_ptr = (Lptr) L_alloc (Lptr_Pool); if (new_ptr == 0) Punt ("NewLptr: out of memory space"); } new_ptr->next = 0; new_ptr->ptr = ptr; return new_ptr; }
void meta_compat_start(void) { #ifdef USE_FILEMON_ONCE /* * We need to re-open filemon for each cmd. */ BuildMon *pbm = &Mybm; if (pbm->mfp != NULL && useFilemon) { filemon_open(pbm); } else { pbm->mon_fd = pbm->filemon_fd = -1; } #endif if (pipe(childPipe) < 0) Punt("Cannot create pipe: %s", strerror(errno)); /* Set close-on-exec flag for both */ (void)fcntl(childPipe[0], F_SETFD, 1); (void)fcntl(childPipe[1], F_SETFD, 1); }
/* * Places traces in a particular linear order * to maximize sequential transition. * A good way to achieve this is to construct a * higher level graph, using traces as nodes. * An arc is added between traces whose head * and tail are connected by a transition. */ static void PlaceTraces (FGraph graph) { FGraph new_graph; Node node, current; Node node_order[MAX_GRAPH_SIZE]; int i, size; #ifndef SECOND_LEVEL_SELECT int min_trace_id, max_trace_id; #endif if (graph->nodes == 0) return; #ifdef SECOND_LEVEL_SELECT new_graph = NewGraph (); /* create a high level graph */ for (node = graph->nodes; node != 0; node = nextNode (node)) { int trace_id; Node temp; trace_id = nodeType (node); temp = FindNode (new_graph, trace_id); if (temp == 0) { temp = NewNode (); nodeId (temp) = trace_id; AddNode (new_graph, temp); } if (node == graph->root) new_graph->root = temp; } for (node = graph->nodes; node != 0; node = nextNode (node)) { Arc arc; if (!(nodeStatus (node) & TRACE_TAIL)) continue; /* * Find transitions to the head of other traces. * Inner loop back-edge is not considered. */ for (arc = destinationArcs (node); arc != 0; arc = nextArc (arc)) { Node dest; dest = destinationNode (arc); if ((nodeType (dest) != nodeType (node)) && (nodeStatus (dest) & TRACE_HEAD)) { /* * Add a link (trace[node]->trace[dest]) */ int src_trace_id, dest_trace_id; Node src_node, dest_node; Arc ar; src_trace_id = nodeType (node); dest_trace_id = nodeType (dest); src_node = FindNode (new_graph, src_trace_id); dest_node = FindNode (new_graph, dest_trace_id); ConnectNodes (src_node, dest_node, 0); ar = FindSrcArc (src_node, dest_node, 0); arcWeight (ar) = arcWeight (arc); ar = FindDestArc (src_node, dest_node, 0); arcWeight (ar) = arcWeight (arc); } } } /* * Simply assign the node weights to max(connecting arc) */ for (node = new_graph->nodes; node != 0; node = nextNode (node)) { Arc arc; double max = 1.0; for (arc = sourceArcs (node); arc != 0; arc = nextArc (arc)) if (arcWeight (arc) > max) max = arcWeight (arc); for (arc = destinationArcs (node); arc != 0; arc = nextArc (arc)) if (arcWeight (arc) > max) max = arcWeight (arc); nodeWeight (node) = max; } /* * Apply SelectTraces() on the new graph. * Use SELECT_BY_ARC_WEIGHT */ best_successor_of = best_successor_2; best_predecessor_of = best_predecessor_2; SelectTraces (new_graph); /* * Determine the best sequential order of the traces. * Essentially, we have the original problem again. * However, after the second level trace selection, * we expect most of the sequential transitions are * captured. A naive heuristic is sufficient here. * The sequential order must start with the ENTRY trace. */ #ifdef DEBUG_TRACE1 printf ("... second level graph = \n"); WriteGraph ("stdout", new_graph); #endif /* * Clear the valid bit of all nodes. */ for (node = new_graph->nodes; node != 0; node = nextNode (node)) { nodeStatus (node) &= ~VISITED; } /* * Start from the root node. */ size = 0; current = new_graph->root; while (current != 0) { Node ptr; Arc ar; int trace_id; if (nodeStatus (current) & VISITED) Punt ("PlaceTraces: reached a VISITed node"); nodeStatus (current) |= VISITED; trace_id = nodeId (current); /* * Layout the trace. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if ((nodeType (ptr) == trace_id) && (nodeStatus (ptr) & TRACE_HEAD)) break; /* find the starting node of the trace */ } if (ptr == 0) Punt ("PlaceTraces: internal error (1)"); while (ptr != 0) { Arc next; node_order[size++] = ptr; /* * Follow the in-trace transition. */ if (nodeStatus (ptr) & TRACE_TAIL) break; /* reached the end of trace */ for (next = destinationArcs (ptr); next != 0; next = nextArc (next)) { if (arcType (next) == nodeType (ptr)) break; /* find a in-trace transition */ } if (next == 0) break; ptr = destinationNode (next); } /* * Select the next trace to be visited next. * Follow an in-trace transition (of the higher level * graph) if possible. */ for (ar = destinationArcs (current); ar != 0; ar = nextArc (ar)) { if (arcType (ar) == nodeType (current)) break; /* find an in-trace transition */ } if (ar != 0) { /* transition is still in-trace */ current = destinationNode (ar); } else { /* must find another trace */ /* * Find the most important trace left. */ Node nn, best; best = 0; for (nn = new_graph->nodes; nn != 0; nn = nextNode (nn)) { if (nodeStatus (nn) & VISITED) continue; /* skip over VISITED nodes */ if (!(nodeStatus (nn) & TRACE_HEAD)) continue; /* skip over non-trace headers */ if (best == 0) { best = nn; } else { if (nodeWeight (nn) > nodeWeight (best)) best = nn; } } current = best; /* go out of trace if best=0 */ } } /* * Make sure that all traces have been layout. */ for (node = new_graph->nodes; node != 0; node = nextNode (node)) { if (!(nodeStatus (node) & VISITED)) { Punt ("PlaceTraces: missing some traces"); } } /* * No longer need the higher level graph. */ FreeGraph (&new_graph); /* destroy the high level graph */ #else min_trace_id = 0x1FFFFFFF; max_trace_id = -0x1FFFFFFF; for (node = graph->nodes; node != 0; node = nextNode (node)) { int trace_id; trace_id = nodeType (node); if (trace_id > max_trace_id) max_trace_id = trace_id; if (trace_id < min_trace_id) min_trace_id = trace_id; } for (node = graph->nodes; node != 0; node = nextNode (node)) { nodeStatus (node) &= ~VISITED; } size = 0; for (i = min_trace_id; i <= max_trace_id; i++) { Node ptr; /* * 1. find the trace header. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if ((nodeType (ptr) == i) & ((nodeStatus (ptr) & TRACE_HEAD) != 0)) break; } if (ptr == 0) continue; while (ptr != 0) { Arc next; if (nodeStatus (ptr) & VISITED) Punt ("PlaceTraces: visited a node twice"); nodeStatus (ptr) |= VISITED; node_order[size++] = ptr; if (nodeStatus (ptr) & TRACE_TAIL) break; for (next = destinationArcs (ptr); next != 0; next = nextArc (next)) { if (arcType (next) == nodeType (ptr)) break; } if (next == 0) break; ptr = destinationNode (next); } } /* * Make sure that all traces have been layout. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { if (!(nodeStatus (node) & VISITED)) { fprintf (stderr, "min trace id = %d\n", min_trace_id); fprintf (stderr, "max trace id = %d\n", max_trace_id); fprintf (stderr, "size = %d\n", size); WriteGraph ("stderr", graph); Punt ("PlaceTraces: missing some traces"); } } #endif /* * Rearrange the order of nodes, according to the * node_order[] order. */ node_order[size] = 0; for (i = 0; i < size; i++) { nextNode (node_order[i]) = node_order[i + 1]; } graph->nodes = node_order[0]; }
static void AddExtensionFields (FGraph graph) { Node ptr; Arc arc; struct Ext *ext; int change; Set all; FreeExtensionFields (); if (graph->nodes == 0) return; if (graph->root == 0) Punt ("no root node"); all = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { nodeExt (ptr) = (others + n_others); others[n_others].dominator = 0; others[n_others].level = -1; others[n_others].order = n_others; all = Set_add (all, n_others); n_others += 1; } ext = (struct Ext *) nodeExt (graph->root); ext->level = 0; ext->dominator = Set_add (0, ext->order); for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (ptr == graph->root) continue; ext = (struct Ext *) nodeExt (ptr); ext->dominator = Set_union (0, all); } /* * compute dominators. */ change = 1; while (change != 0) { change = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { Set dom, temp; if (ptr == graph->root) continue; arc = sourceArcs (ptr); if (arc == 0) { dom = 0; } else { dom = Set_union (all, 0); for (; arc != 0; arc = nextArc (arc)) { ext = (struct Ext *) nodeExt (sourceNode (arc)); temp = Set_intersect (dom, ext->dominator); Set_dispose (dom); dom = temp; temp = 0; } ext = (struct Ext *) nodeExt (ptr); dom = Set_add (dom, ext->order); if (Set_same (dom, ext->dominator)) { Set_dispose (dom); } else { Set_dispose (ext->dominator); ext->dominator = dom; change += 1; } } } } all = Set_dispose (all); /* * compute level. */ change = 1; while (change != 0) { change = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { int max; ext = (struct Ext *) nodeExt (ptr); if (ext->level >= 0) continue; max = -1; for (arc = sourceArcs (ptr); arc != 0; arc = arc->next) { Node src; struct Ext *ex; src = sourceNode (arc); ex = (struct Ext *) nodeExt (src); /* ignore back-edges */ if (ex->order >= ext->order) continue; if (ex->level < 0) break; if (ex->level > max) max = ex->level; } if (arc == 0) { /* all source have been visited */ ext->level = max + 1; change += 1; } } } #ifdef DEBUG printf ("--------------------------------------------------\n"); for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { ext = nodeExt (ptr); printf ("# id=%d, order=%d, level=%d, ", ptr->id, ext->order, ext->level); PrintSet (stdout, "dominator", ext->dominator); } #endif }
/* * Trace selection by sorting all arcs and * select from the most important to the least important. */ void SelectBySortArc (FGraph graph) { #define MAX_SIZE (MAX_GRAPH_SIZE*2) ST_Entry sorted_list[MAX_SIZE]; /* expected fan-out = 2 */ register int list_length; Node node_list[MAX_GRAPH_SIZE]; register int node_list_length; register Node ptr; register Arc arc; register int i; int next_trace_id; /* * Mark all nodes unvisited. * Also clear all status bits. */ node_list_length = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { node_list[node_list_length++] = ptr; if (node_list_length >= MAX_GRAPH_SIZE) Punt ("SelectBySortArc: graph is too large"); nodeType (ptr) = 0; /* trace id = 0 */ nodeStatus (ptr) = NOT_VISITED; for (arc = sourceArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; } /* * Place all outgoing arcs in the list. * Sort all arcs by weight. */ list_length = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) { sorted_list[list_length].weight = arcWeight (arc); sorted_list[list_length].ptr = arc; list_length += 1; if (list_length >= MAX_SIZE) Punt ("SelectBySortArc: graph is too large"); } } max_sort (sorted_list, list_length); /* library/sort.c */ /* * From the most important arc to the least important arc, * connect basic blocks into traces. */ next_trace_id = 1; for (i = 0; i < list_length; i++) { int trace_id; Node src, dest; arc = (Arc) sorted_list[i].ptr; src = sourceNode (arc); dest = destinationNode (arc); /* * Check if this arc can still be selected. * dest cannot be the root of the graph. * case1 : src = free node, dest = free node * case2 : src is a tail node, dest is a head node, * except when src and dest belong to the same trace. */ if (dest == graph->root) continue; if (! ((nodeStatus (src) == NOT_VISITED) || (nodeStatus (src) & TRACE_TAIL))) continue; if (! ((nodeStatus (dest) == NOT_VISITED) || (nodeStatus (dest) & TRACE_HEAD))) continue; /* * If both src and dest are defined (in some trace), * we do not allow this connection if src and dest * belong to the same trace. * This takes care of self-recursions. */ if ((nodeStatus (src) & TRACE_TAIL) && (nodeStatus (dest) & TRACE_HEAD)) if (nodeType (src) == nodeType (dest)) continue; /* * It is also not allow to connect, when src and dest * are the same node. */ if (src == dest) continue; /* * After connection, src will no longer be tail, and * dest will no longer be head. */ nodeStatus (src) &= ~TRACE_TAIL; nodeStatus (dest) &= ~TRACE_HEAD; /* * Now this arc can be selected. */ if (nodeStatus (src) & VISITED) { trace_id = nodeType (src); arcType (arc) = trace_id; /* * If the dest node is in another trace, need to * combine the two traces. */ if (nodeStatus (dest) & VISITED) { register int j; register int bad_id = nodeType (dest); /* * For all nodes of type (nodeType(dest)), change * to trace_id. */ for (j = 0; j < node_list_length; j++) if (nodeType (node_list[j]) == bad_id) nodeType (node_list[j]) = trace_id; /* * For all arcs of type (nodeType(dest)), change * to trace_id. */ for (j = 0; j < list_length; j++) { Arc ac; ac = (Arc) sorted_list[j].ptr; if (arcType (ac) == bad_id) arcType (ac) = trace_id; } } else { /* * If dest is still a free node, it becomes the * trace tail. */ nodeStatus (dest) |= (VISITED | TRACE_TAIL); nodeType (dest) = trace_id; } } else if (nodeStatus (dest) & VISITED) { trace_id = nodeType (dest); arcType (arc) = trace_id; /* * Since src is a free node, src becomes a trace head. */ nodeStatus (src) |= (VISITED | TRACE_HEAD); nodeType (src) = trace_id; } else { trace_id = next_trace_id++; arcType (arc) = trace_id; nodeStatus (src) |= (VISITED | TRACE_HEAD); nodeType (src) = trace_id; nodeStatus (dest) |= (VISITED | TRACE_TAIL); nodeType (dest) = trace_id; } } /* * The remaining NOT_VISITED nodes, each forms a trace. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (nodeStatus (ptr) & VISITED) continue; nodeStatus (ptr) |= (VISITED | TRACE_HEAD | TRACE_TAIL); nodeType (ptr) = next_trace_id++; } /* * Detect inner loops. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (!(nodeStatus (ptr) & TRACE_TAIL)) continue; for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) { Node dest; dest = destinationNode (arc); if ((nodeStatus (dest) & TRACE_HEAD) && (nodeType (dest) == nodeType (ptr))) { nodeStatus (dest) |= LOOP_HEAD; break; } } } }
/*- * MainParseArgs -- * Parse a given argument vector. Called from main() and from * Main_ParseArgLine() when the MAKEFLAGS target is used. * * XXX: Deal with command line overriding MAKEFLAGS in makefile * * Results: * None * * Side Effects: * Various global and local flags will be set depending on the flags * given */ static void MainParseArgs(int argc, char **argv) { int c; string_t argstr; optind = 1; /* since we're called more than once */ rearg: while((c = getopt(argc, argv, "D:I:L:NPSd:ef:ij:knqrstv")) != EOF) { switch(c) { case 'D': argstr = string_create(optarg); Var_Set(argstr, string_create("1"), VAR_GLOBAL); Var_Append(sMAKEFLAGS, string_create("-D"), VAR_GLOBAL); Var_Append(sMAKEFLAGS, argstr, VAR_GLOBAL); string_deref(argstr); break; case 'I': argstr = string_create(optarg); Parse_AddIncludeDir(argstr); Var_Append(sMAKEFLAGS, string_create("-I"), VAR_GLOBAL); Var_Append(sMAKEFLAGS, argstr, VAR_GLOBAL); string_deref(argstr); break; case 'L': maxLocal = atoi(optarg); Var_Append(sMAKEFLAGS, string_create("-L"), VAR_GLOBAL); argstr = string_create(optarg); Var_Append(sMAKEFLAGS, argstr, VAR_GLOBAL); string_deref(argstr); break; case 'N': noisy = TRUE; Var_Append(sMAKEFLAGS, string_create("-N"), VAR_GLOBAL); break; case 'S': keepgoing = FALSE; Var_Append(sMAKEFLAGS, string_create("-S"), VAR_GLOBAL); break; case 'd': { char *modules = optarg; for (; *modules; ++modules) switch (*modules) { case 'A': debug = ~0; break; case 'a': debug |= DEBUG_ARCH; break; case 'c': debug |= DEBUG_COND; break; case 'd': debug |= DEBUG_DIR; break; case 'g': if (modules[1] == '1') { debug |= DEBUG_GRAPH1; ++modules; } else if (modules[1] == '2') { debug |= DEBUG_GRAPH2; ++modules; } break; case 'j': debug |= DEBUG_JOB; break; case 'm': debug |= DEBUG_MAKE; break; case 's': debug |= DEBUG_SUFF; break; case 't': debug |= DEBUG_TARG; break; case 'v': debug |= DEBUG_VAR; break; } Var_Append(sMAKEFLAGS, string_create("-d"), VAR_GLOBAL); argstr = string_create(optarg); Var_Append(sMAKEFLAGS, argstr, VAR_GLOBAL); string_deref(argstr); break; } case 'e': checkEnvFirst = TRUE; Var_Append(sMAKEFLAGS, string_create("-e"), VAR_GLOBAL); break; case 'f': (void)Lst_AtEnd(makefiles, (ClientData)optarg); break; case 'i': ignoreErrors = TRUE; Var_Append(sMAKEFLAGS, string_create("-i"), VAR_GLOBAL); break; case 'j': maxJobs = atoi(optarg); Var_Append(sMAKEFLAGS, string_create("-j"), VAR_GLOBAL); argstr = string_create(optarg); Var_Append(sMAKEFLAGS, argstr, VAR_GLOBAL); string_deref(argstr); break; case 'k': keepgoing = TRUE; Var_Append(sMAKEFLAGS, string_create("-k"), VAR_GLOBAL); break; case 'n': noExecute = TRUE; Var_Append(sMAKEFLAGS, string_create("-n"), VAR_GLOBAL); break; case 'q': queryFlag = TRUE; /* Kind of nonsensical, wot? */ Var_Append(sMAKEFLAGS, string_create("-q"), VAR_GLOBAL); break; case 'r': noBuiltins = TRUE; Var_Append(sMAKEFLAGS, string_create("-r"), VAR_GLOBAL); break; case 's': beSilent = TRUE; Var_Append(sMAKEFLAGS, string_create("-s"), VAR_GLOBAL); break; case 't': touchFlag = TRUE; Var_Append(sMAKEFLAGS, string_create("-t"), VAR_GLOBAL); break; case 'v': ui_print_revision(); exit(2); default: case '?': usage(); } } oldVars = TRUE; /* * See if the rest of the arguments are variable assignments and * perform them if so. Else take them to be targets and stuff them * on the end of the "create" list. */ for (argv += optind, argc -= optind; *argv; ++argv, --argc) if (Parse_DoVar(*argv, VAR_CMD) != 0) { if (!**argv) Punt("illegal (null) argument."); if (**argv == '-') { optind = 0; goto rearg; } (void)Lst_AtEnd(create, (ClientData)string_create(*argv)); } }
static Job * prepare_job(GNode *gn, int flags) { bool cmdsOK; /* true if the nodes commands were all right */ bool noExec; /* Set true if we decide not to run the job */ /* * Check the commands now so any attributes from .DEFAULT have a chance * to migrate to the node */ cmdsOK = Job_CheckCommands(gn); expand_commands(gn); if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { /* * We're serious here, but if the commands were bogus, we're * also dead... */ if (!cmdsOK) job_failure(gn, Punt); if (Lst_IsEmpty(&gn->commands)) noExec = true; else noExec = false; } else if (noExecute) { if (!cmdsOK || Lst_IsEmpty(&gn->commands)) noExec = true; else noExec = false; } else { /* * Just touch the target and note that no shell should be * executed. Check * the commands, too, but don't die if they're no good -- it * does no harm to keep working up the graph. */ Job_Touch(gn); noExec = true; } /* * If we're not supposed to execute a shell, don't. */ if (noExec) { /* * We only want to work our way up the graph if we aren't here * because the commands for the job were no good. */ if (cmdsOK && !aborting) { gn->built_status = MADE; Make_Update(gn); } return NULL; } else { Job *job; /* new job descriptor */ job = emalloc(sizeof(Job)); if (job == NULL) Punt("JobStart out of memory"); job->node = gn; /* * Set the initial value of the flags for this job based on the * global ones and the node's attributes... Any flags supplied * by the caller are also added to the field. */ job->flags = flags; if (gn->type & OP_CHEAP) return job; if ((gn->type & OP_EXPENSIVE) || expensive_commands(&gn->expanded)) job->flags |= JOB_IS_EXPENSIVE; return job; } }
/*- *----------------------------------------------------------------------- * JobExec -- * Execute the shell for the given job. Called from JobStart * * Side Effects: * A shell is executed, outputs is altered and the Job structure added * to the job table. *----------------------------------------------------------------------- */ static void JobExec(Job *job) { pid_t cpid; /* ID of new child */ struct job_pid *p; int fds[4]; int *fdout = fds; int *fderr = fds+2; int i; banner(job, stdout); setup_engine(1); /* Create the pipe by which we'll get the shell's output. */ if (pipe(fdout) == -1) Punt("Cannot create pipe: %s", strerror(errno)); if (pipe(fderr) == -1) Punt("Cannot create pipe: %s", strerror(errno)); block_signals(); if ((cpid = fork()) == -1) { Punt("Cannot fork"); unblock_signals(); } else if (cpid == 0) { supervise_jobs = false; /* standard pipe code to route stdout and stderr */ close(fdout[0]); if (dup2(fdout[1], 1) == -1) Punt("Cannot dup2(outPipe): %s", strerror(errno)); if (fdout[1] != 1) close(fdout[1]); close(fderr[0]); if (dup2(fderr[1], 2) == -1) Punt("Cannot dup2(errPipe): %s", strerror(errno)); if (fderr[1] != 2) close(fderr[1]); /* * We want to switch the child into a different process family * so we can kill it and all its descendants in one fell swoop, * by killing its process family, but not commit suicide. */ (void)setpgid(0, getpid()); if (random_delay) if (!(nJobs == 1 && no_jobs_left())) usleep(random() % random_delay); setup_all_signals(SigHandler, SIG_DFL); unblock_signals(); /* this exits directly */ run_gnode_parallel(job->node); /*NOTREACHED*/ } else { supervise_jobs = true; job->pid = cpid; /* we set the current position in the buffers to the beginning * and mark another stream to watch in the outputs mask */ for (i = 0; i < 2; i++) prepare_pipe(&job->in[i], fds+2*i); } /* * Now the job is actually running, add it to the table. */ nJobs++; Lst_AtEnd(&runningJobs, job); if (job->flags & JOB_IS_EXPENSIVE) expensive_job = true; p = emalloc(sizeof(struct job_pid)); p->pid = cpid; Lst_AtEnd(&job_pids, p); job->p = Lst_Last(&job_pids); unblock_signals(); if (DEBUG(JOB)) { LstNode ln; (void)fprintf(stdout, "Running %ld (%s)\n", (long)cpid, job->node->name); for (ln = Lst_First(&job->node->commands); ln != NULL ; ln = Lst_Adv(ln)) fprintf(stdout, "\t%s\n", (char *)Lst_Datum(ln)); (void)fflush(stdout); } }
/*- * MainParseArgs -- * Parse a given argument vector. Called from main() and from * Main_ParseArgLine() when the .MAKEFLAGS target is used. * * XXX: Deal with command line overriding .MAKEFLAGS in makefile * * Results: * None * * Side Effects: * Various global and local flags will be set depending on the flags * given */ static void MainParseArgs(int argc, char **argv) { char *p; int c; int arginc; char *argvalue; const char *getopt_def; char *optscan; Boolean inOption, dashDash = FALSE; char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ #ifdef REMOTE # define OPTFLAGS "BD:I:J:L:NPST:V:WXd:ef:ij:km:nqrst" #else # define OPTFLAGS "BD:I:J:NPST:V:WXd:ef:ij:km:nqrst" #endif #undef optarg #define optarg argvalue /* Can't actually use getopt(3) because rescanning is not portable */ getopt_def = OPTFLAGS; rearg: inOption = FALSE; optscan = NULL; while(argc > 1) { char *getopt_spec; if(!inOption) optscan = argv[1]; c = *optscan++; arginc = 0; if(inOption) { if(c == '\0') { ++argv; --argc; inOption = FALSE; continue; } } else { if (c != '-' || dashDash) break; inOption = TRUE; c = *optscan++; } /* '-' found at some earlier point */ getopt_spec = strchr(getopt_def, c); if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') { /* -<something> found, and <something> should have an arg */ inOption = FALSE; arginc = 1; argvalue = optscan; if(*argvalue == '\0') { if (argc < 3) { (void)fprintf(stderr, "%s: option requires " "an argument -- %c\n", progname, c); usage(); } argvalue = argv[2]; arginc = 2; } } else { argvalue = NULL; } switch(c) { case '\0': arginc = 1; inOption = FALSE; break; case 'B': compatMake = TRUE; Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); break; case 'D': Var_Set(optarg, "1", VAR_GLOBAL, 0); Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; case 'I': Parse_AddIncludeDir(optarg); Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; case 'J': if (sscanf(optarg, "%d,%d", &job_pipe[0], &job_pipe[1]) != 2) { /* backslash to avoid trigraph ??) */ (void)fprintf(stderr, "%s: internal error -- J option malformed (%s?\?)\n", progname, optarg); usage(); } if ((fcntl(job_pipe[0], F_GETFD, 0) < 0) || (fcntl(job_pipe[1], F_GETFD, 0) < 0)) { #if 0 (void)fprintf(stderr, "%s: warning -- J descriptors were closed!\n", progname); #endif job_pipe[0] = -1; job_pipe[1] = -1; compatMake = TRUE; } else { Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); jobServer = TRUE; } break; #ifdef REMOTE case 'L': maxLocal = strtol(optarg, &p, 0); if (*p != '\0' || maxLocal < 1) { (void)fprintf(stderr, "%s: illegal argument to -L -- must be positive integer!\n", progname); exit(1); } Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; #endif case 'N': noExecute = TRUE; noRecursiveExecute = TRUE; Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); break; case 'P': usePipes = FALSE; Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); break; case 'S': keepgoing = FALSE; Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); break; case 'T': tracefile = estrdup(optarg); Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; case 'V': printVars = TRUE; (void)Lst_AtEnd(variables, (ClientData)optarg); Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; case 'W': parseWarnFatal = TRUE; break; case 'X': varNoExportEnv = TRUE; Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); break; case 'd': { char *modules = optarg; for (; *modules; ++modules) switch (*modules) { case 'A': debug = ~0; break; case 'a': debug |= DEBUG_ARCH; break; case 'c': debug |= DEBUG_COND; break; case 'd': debug |= DEBUG_DIR; break; case 'e': debug |= DEBUG_ERROR; break; case 'f': debug |= DEBUG_FOR; break; case 'g': if (modules[1] == '1') { debug |= DEBUG_GRAPH1; ++modules; } else if (modules[1] == '2') { debug |= DEBUG_GRAPH2; ++modules; } else if (modules[1] == '3') { debug |= DEBUG_GRAPH3; ++modules; } break; case 'j': debug |= DEBUG_JOB; break; case 'm': debug |= DEBUG_MAKE; break; case 'n': debug |= DEBUG_SCRIPT; break; case 's': debug |= DEBUG_SUFF; break; case 't': debug |= DEBUG_TARG; break; case 'v': debug |= DEBUG_VAR; break; case 'x': debug |= DEBUG_SHELL; break; default: (void)fprintf(stderr, "%s: illegal argument to d option -- %c\n", progname, *modules); usage(); } Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; } case 'e': checkEnvFirst = TRUE; Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); break; case 'f': (void)Lst_AtEnd(makefiles, (ClientData)optarg); break; case 'i': ignoreErrors = TRUE; Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); break; case 'j': forceJobs = TRUE; maxJobs = strtol(optarg, &p, 0); if (*p != '\0' || maxJobs < 1) { (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n", progname); exit(1); } #ifndef REMOTE maxLocal = maxJobs; #endif Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; case 'k': keepgoing = TRUE; Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); break; case 'm': /* look for magic parent directory search string */ if (strncmp(".../", optarg, 4) == 0) { if (!Dir_FindHereOrAbove(curdir, optarg+4, found_path, sizeof(found_path))) break; /* nothing doing */ (void)Dir_AddDir(sysIncPath, found_path); } else { (void)Dir_AddDir(sysIncPath, optarg); } Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); break; case 'n': noExecute = TRUE; Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); break; case 'q': queryFlag = TRUE; /* Kind of nonsensical, wot? */ Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); break; case 'r': noBuiltins = TRUE; Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); break; case 's': beSilent = TRUE; Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); break; case 't': touchFlag = TRUE; Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); break; case '-': dashDash = TRUE; break; default: case '?': #ifndef MAKE_NATIVE fprintf(stderr, "getopt(%s) -> %d (%c)\n", OPTFLAGS, c, c); #endif usage(); } argv += arginc; argc -= arginc; } oldVars = TRUE; /* * See if the rest of the arguments are variable assignments and * perform them if so. Else take them to be targets and stuff them * on the end of the "create" list. */ for (; argc > 1; ++argv, --argc) if (Parse_IsVar(argv[1])) { Parse_DoVar(argv[1], VAR_CMD); } else { if (!*argv[1]) Punt("illegal (null) argument."); if (*argv[1] == '-' && !dashDash) goto rearg; (void)Lst_AtEnd(create, (ClientData)estrdup(argv[1])); } }
/* * Heuristic solution to the trace selection problem. */ static void SelectTraces (FGraph graph) { ST_Entry sorted_list[MAX_GRAPH_SIZE]; int list_length; Node ptr; Arc arc; int n, trace_id; Node ENTRY; Node seed, current, last; struct Ext *extCurrent, *extNext; /* * Compute level information. */ AddExtensionFields (graph); /* * Mark all nodes unvisited. * Also clear all status bits. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { nodeType (ptr) = 0; /* trace id = 0 */ nodeStatus (ptr) = NOT_VISITED; for (arc = sourceArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; for (arc = destinationArcs (ptr); arc != 0; arc = nextArc (arc)) arcType (arc) = 0; } /* * Sort all nodes according to the node weight. * From the most important node to the least important node. */ list_length = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { sorted_list[list_length].weight = nodeWeight (ptr); sorted_list[list_length].ptr = ptr; sorted_list[list_length].index = list_length; list_length += 1; if (list_length >= MAX_GRAPH_SIZE) Punt ("SelectTrace: graph is too large"); } max_sort (sorted_list, list_length); /* library/sort.c */ #ifdef WEIGHT_BASED /* * Give higher priority to the execution weight. */ ENTRY = graph->root; trace_id = 1; for (n = 0; n < list_length; n++) { /* * Select the highest weight un-visited node. */ seed = sorted_list[n].ptr; if (nodeStatus (seed) & VISITED) /* if visited, try next */ continue; /* highest node */ /* * Start a new trace. * Mark seed visited. */ nodeType (seed) = trace_id++; nodeStatus (seed) |= VISITED; /* * Grow the trace forward. */ current = seed; for (;;) { Arc ln, arc; Node dest; ln = best_successor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Cannot include ENTRY node. */ dest = destinationNode (ln); if (dest == ENTRY) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Can not include a dominator. */ extCurrent = nodeExt (current); extNext = nodeExt (dest); if ((extCurrent == 0) | (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extCurrent->dominator, extNext->order)) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Mark the link selected. */ arc = FindSrcArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (dest) = nodeType (seed); nodeStatus (dest) |= VISITED; current = dest; } /* * Grow the trace backward. */ current = seed; for (;;) { Arc ln, arc; Node src; /* * Cannot grow from the ENTRY node. */ if (current == ENTRY) { nodeStatus (current) |= TRACE_HEAD; break; } ln = best_predecessor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_HEAD; break; } src = sourceNode (ln); /* * Can not include a dominee. */ extCurrent = nodeExt (current); extNext = nodeExt (src); if ((extCurrent == 0) | (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extNext->dominator, extCurrent->order)) { nodeStatus (current) |= TRACE_HEAD; break; } /* * Mark the link selected. */ arc = FindSrcArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (src) = nodeType (seed); nodeStatus (src) |= VISITED; current = src; } } #else /* * Give more attention to the natural flow of the * program. */ ENTRY = graph->root; trace_id = 1; current = ENTRY; /* start from the entry block */ last = 0; for (n = 0; n < list_length; n++) { if (!(nodeStatus (current) & VISITED)) { /* * 1) start from the start node first. */ seed = current; } else { /* * 2) select a fall_thru node if possible. * 3) select the most important node. */ Node best, dest; Arc pc; if (last == 0) Punt ("this should not happen"); best = 0; for (pc = destinationArcs (last); pc != 0; pc = nextArc (pc)) { dest = destinationNode (pc); if (nodeStatus (dest) & VISITED) continue; if (best == 0) { best = dest; } else if (successor_node_weight (last, dest) > successor_node_weight (last, best)) { best = dest; } } if (best == 0) { int k; for (k = 0; k < list_length; k++) { dest = (Node) sorted_list[k].ptr; if (nodeStatus (dest) & VISITED) continue; best = dest; break; } } if (best == 0) { break; } seed = best; } if (nodeStatus (seed) & VISITED) Punt ("incorrect seed selection"); /* * Start a new trace. * Mark seed visited. */ nodeType (seed) = trace_id++; nodeStatus (seed) |= VISITED; /* * Grow the trace forward. */ current = seed; for (;;) { Arc ln, arc; Node dest; ln = best_successor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Cannot include ENTRY node. */ dest = destinationNode (ln); if (dest == ENTRY) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Can not include a dominator. */ extCurrent = (struct Ext *) nodeExt (current); extNext = (struct Ext *) nodeExt (dest); if ((extCurrent == 0) || (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extCurrent->dominator, extNext->order)) { nodeStatus (current) |= TRACE_TAIL; break; } /* * Mark the link selected. */ arc = FindSrcArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (current, dest, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (dest) = nodeType (seed); nodeStatus (dest) |= VISITED; current = dest; } last = current; /* * Grow the trace backward. */ current = seed; for (;;) { Arc ln, arc; Node src; /* * Cannot grow from the ENTRY node. */ if (current == ENTRY) { nodeStatus (current) |= TRACE_HEAD; break; } ln = best_predecessor_of (current); if (ln == 0) { nodeStatus (current) |= TRACE_HEAD; break; } src = sourceNode (ln); /* * Can not include a dominee. */ extCurrent = (struct Ext *) nodeExt (current); extNext = (struct Ext *) nodeExt (src); if ((extCurrent == 0) || (extNext == 0)) { Punt ("corrupted extension field"); } if (Set_in (extNext->dominator, extCurrent->order)) { nodeStatus (current) |= TRACE_HEAD; break; } /* * Mark the link selected. */ arc = FindSrcArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted source link"); arc = FindDestArc (src, current, 0); if (arc != 0) { arcType (arc) = nodeType (seed); } else Punt ("SelectTraces: corrupted destination link"); /* * Add it to the trace. */ nodeType (src) = nodeType (seed); nodeStatus (src) |= VISITED; current = src; } } #endif /* * Make sure that all nodes have been visited. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (!(nodeStatus (ptr) & VISITED)) Punt ("SelectTraces: failed to select all nodes"); } /* * Detect inner loops. */ for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { Arc ln; if (!(nodeStatus (ptr) & TRACE_TAIL)) continue; for (ln = destinationArcs (ptr); ln != 0; ln = nextArc (ln)) { Node dest; dest = destinationNode (ln); if ((nodeStatus (dest) & TRACE_HEAD) && (nodeType (dest) == nodeType (ptr))) { nodeStatus (dest) |= LOOP_HEAD; break; } } } }
int RunPlay(){ Team *O, *D; //Pointers to offence and defense if(state == Aoff){ // if A is on offense O = A; D = B; } else { //if B is on offense O = B; D = A; } int yrds, thrw; cout << "SELECTING PLAY " << play << endl; switch(play){ case PUNT: cout << "Team punts" << endl; pos = pos + Punt(D->kr, O->p); punt++; //If the ball is kicked into the endzome then it is a touchback //and the other team gets it at the 20 yard line if(pos>99){ cout << "Touchback" << endl; pos=80; } pos = 100-pos; state = Boff; return 1; break; case FIELDGOAL: if(Fieldgoal(O->k, (100-pos+17))){ cout << "Fieldgoal is good!" << endl; state = Akick; *fg++; score[0] += 3; } else { cout << "Fieldgoal is no good!" << endl; pos = 100-pos; Turnover(); } return 1; break; case DEEPPASS: //determines how many yards the pass will gain IF completeld yrds = PassYards(play, O->qb, O->wr1, D->cb1); //the time_left will go down as plays happen, this was just a simple temporary fix, will put //a more detailed function in later time_left -= (yrds/TIME); //if this is true then the QB was sacked. Team A loses 5 yards and the down if(Blitz(O->rde, D->lt) || Blitz(O->rde, D->lt) || Blitz(O->rde, D->lt)){ *sack++; pos -= 5; }else{ //This determines the outcome of the pass, a 0 means the qb missed or the receiver //dropped the ball, and 1 means the defender swatted the pass away, a 2 means the //defender intercepted the pass which means team B is then on offence, and a 3 means //team A's receiver successfully caught the ball thrw=Pass(O->qb, O->wr1, D->cb1, yrds, time_left); *att++; //miss or dropped if(thrw==0){ *miss++; cout << "Incomplete!" << endl; } //pass swatted else if(thrw==1){ *swat++; cout << "Pass defended!" << endl; } //pass intercepted else if(thrw==2){ *pick++; down=0; tofirst=10; state = Boff; pos = 100-pos-yrds; if(pos<1){ //If the ball is intercepted in the endzome then it is a //touchback and the other team gets it at the 20 yard line cout << "Touchback" << endl; pos=20; } cout << "Interception!" << endl; } //pass caught else if(thrw==3){ *cth++; passyrds += yrds; cout << "Pass completed for " << yrds << " yards!" << endl; pos = pos + yrds; } } break; } return 1; }
/** * Replace the current process. */ void Proc_Exec(const ProcStuff *ps) { if (ps->in != STDIN_FILENO) { /* * Redirect the child's stdin to the input fd * and reset it to the beginning (again). */ if (dup2(ps->in, STDIN_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); lseek(STDIN_FILENO, (off_t)0, SEEK_SET); } if (ps->out != STDOUT_FILENO) { /* * Redirect the child's stdout to the output fd. */ if (dup2(ps->out, STDOUT_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); close(ps->out); } if (ps->err != STDERR_FILENO) { /* * Redirect the child's stderr to the err fd. */ if (dup2(ps->err, STDERR_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); close(ps->err); } if (ps->merge_errors) { /* * Send stderr to parent process too. */ if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) Punt("Cannot dup2: %s", strerror(errno)); } if (commandShell->unsetenv) { /* for the benfit of ksh */ unsetenv("ENV"); } /* * The file descriptors for stdin, stdout, or stderr might * have been marked close-on-exec. Clear the flag on all * of them. */ fcntl(STDIN_FILENO, F_SETFD, fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC)); fcntl(STDOUT_FILENO, F_SETFD, fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC)); fcntl(STDERR_FILENO, F_SETFD, fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC)); if (ps->pgroup) { #ifdef USE_PGRP /* * Become a process group leader, so we can kill it and all * its descendants in one fell swoop, by killing its process * family, but not commit suicide. */ #if defined(SYSV) setsid(); #else setpgid(0, getpid()); #endif #endif /* USE_PGRP */ } if (ps->searchpath) { execvp(ps->argv[0], ps->argv); write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0])); write(STDERR_FILENO, ": ", 2); write(STDERR_FILENO, strerror(errno), strlen(strerror(errno))); write(STDERR_FILENO, "\n", 1); } else { execv(commandShell->path, ps->argv); write(STDERR_FILENO, "Could not execute shell\n", sizeof("Could not execute shell")); } /* * Since we are the child process, exit without flushing buffers. */ _exit(1); }
/* * Measure the trace selection result. * Trace selection must have been applied. */ void ReportSelectionResult (FGraph graph, double *matrix) { int i; Node node; Arc arc; if (graph == 0) Punt ("ReportSelectionResult: nil graph"); if (matrix == 0) return; for (i = 0; i <= N_LEAF; i++) matrix[i] = 0.0; /* * Compute the sequential locality. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { Arc ptr; Node next_node; next_node = nextNode (node); if (next_node == 0) /* ignore the last node */ break; for (ptr = destinationArcs (node); ptr != 0; ptr = nextArc (ptr)) { if (destinationNode (ptr) == next_node) { matrix[W_SEQUENTIAL] += arcWeight (ptr); } } } /* * Measure various transition counts. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { for (arc = destinationArcs (node); arc != 0; arc = nextArc (arc)) { Node src, dest; int Sh, St, Dh, Dt; src = sourceNode (arc); dest = destinationNode (arc); Sh = nodeStatus (src) & TRACE_HEAD; St = nodeStatus (src) & TRACE_TAIL; Dh = nodeStatus (dest) & TRACE_HEAD; Dt = nodeStatus (dest) & TRACE_TAIL; if ((arcType (arc) != 0) && (arcType (arc) == nodeType (node))) { /* * In-trace. */ matrix[W_E] += arcWeight (arc); } else if (arcType (arc) != 0) { Punt ("ReportSelectionResult: illegal arc type"); } else { if (St && Dh) { /* terminal to head */ matrix[W_A] += arcWeight (arc); /* detect loop back-edge */ if (nodeType (src) == nodeType (dest)) { matrix[W_BACK_EDGE] += arcWeight (arc); } } else if (St && !Dh) { /* terminal to middle */ matrix[W_B] += arcWeight (arc); } else if (!St && Dh) { /* middle to head */ matrix[W_C] += arcWeight (arc); } else { /* middle to middle */ matrix[W_D] += arcWeight (arc); } } } } #ifdef DEBUG_TRACE2 if (matrix[W_E] > matrix[W_SEQUENTIAL]) { WriteGraph ("zzz.debug", graph); fprintf (stderr, "in-trace = %f\n", matrix[W_E]); fprintf (stderr, "sequential = %f\n", matrix[W_SEQUENTIAL]); Punt ("ReportSelection: incorrect in-trace"); } #endif /* * Measure several graph parameters. */ for (node = graph->nodes; node != 0; node = nextNode (node)) { nodeStatus (node) &= ~VISITED; /* borrow the valid bit */ matrix[N_NODES] += 1.0; matrix[W_NODES] += nodeWeight (node); if (destinationArcs (node) == 0) { matrix[N_LEAF] += 1.0; } if (sourceArcs (node) == 0) { matrix[N_ROOT] += 1.0; } for (arc = destinationArcs (node); arc != 0; arc = nextArc (arc)) { matrix[N_ARCS] += 1.0; matrix[W_ARCS] += arcWeight (arc); } } for (node = graph->nodes; node != 0; node = nextNode (node)) { Node ptr; int trace_id, loop, size; if (nodeStatus (node) & VISITED) continue; trace_id = nodeType (node); loop = 0; size = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (nodeType (ptr) == trace_id) { nodeStatus (ptr) |= VISITED; size++; loop |= (nodeStatus (node) & LOOP_HEAD); } } matrix[N_TRACE] += 1.0; matrix[L_TRACE] += size; if (loop) { matrix[N_LOOP] += 1.0; matrix[L_LOOP] += size; } } if (matrix[L_TRACE] != matrix[N_NODES]) Punt ("ReportSelectionResult: incorrect accounting"); if (matrix[N_TRACE] != 0.0) matrix[L_TRACE] /= matrix[N_TRACE]; if (matrix[N_LOOP] != 0.0) matrix[L_LOOP] /= matrix[N_LOOP]; }
void myclose(int fid) { if (close(fid) < 0) Punt("Error in myclose!"); DEBUG1( "# %d : <Closed>\n", fid) }
/*- *----------------------------------------------------------------------- * Make_Update -- * Perform update on the parents of a node. Used by JobFinish once * a node has been dealt with and by MakeStartJobs if it finds an * up-to-date node. * * Input: * cgn the child node * * Results: * Always returns 0 * * Side Effects: * The unmade field of pgn is decremented and pgn may be placed on * the toBeMade queue if this field becomes 0. * * If the child was made, the parent's flag CHILDMADE field will be * set true. * * If the child is not up-to-date and still does not exist, * set the FORCE flag on the parents. * * If the child wasn't made, the cmgn field of the parent will be * altered if the child's mtime is big enough. * * Finally, if the child is the implied source for the parent, the * parent's IMPSRC variable is set appropriately. * *----------------------------------------------------------------------- */ void Make_Update(GNode *cgn) { GNode *pgn; /* the parent node */ char *cname; /* the child's name */ LstNode ln; /* Element in parents and iParents lists */ time_t mtime = -1; char *p1; Lst parents; GNode *centurion; /* It is save to re-examine any nodes again */ checked++; cname = Var_Value(TARGET, cgn, &p1); free(p1); if (DEBUG(MAKE)) fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num); /* * If the child was actually made, see what its modification time is * now -- some rules won't actually update the file. If the file still * doesn't exist, make its mtime now. */ if (cgn->made != UPTODATE) { mtime = Make_Recheck(cgn); } /* * If this is a `::' node, we must consult its first instance * which is where all parents are linked. */ if ((centurion = cgn->centurion) != NULL) { if (!Lst_IsEmpty(cgn->parents)) Punt("%s%s: cohort has parents", cgn->name, cgn->cohort_num); centurion->unmade_cohorts -= 1; if (centurion->unmade_cohorts < 0) Error("Graph cycles through centurion %s", centurion->name); } else { centurion = cgn; } parents = centurion->parents; /* If this was a .ORDER node, schedule the RHS */ Lst_ForEach(centurion->order_succ, MakeBuildParent, Lst_First(toBeMade)); /* Now mark all the parents as having one less unmade child */ if (Lst_Open(parents) == SUCCESS) { while ((ln = Lst_Next(parents)) != NULL) { pgn = (GNode *)Lst_Datum(ln); if (DEBUG(MAKE)) fprintf(debug_file, "inspect parent %s%s: flags %x, " "type %x, made %d, unmade %d ", pgn->name, pgn->cohort_num, pgn->flags, pgn->type, pgn->made, pgn->unmade-1); if (!(pgn->flags & REMAKE)) { /* This parent isn't needed */ if (DEBUG(MAKE)) fprintf(debug_file, "- not needed\n"); continue; } if (mtime == 0 && !(cgn->type & OP_WAIT)) pgn->flags |= FORCE; /* * If the parent has the .MADE attribute, its timestamp got * updated to that of its newest child, and its unmake * child count got set to zero in Make_ExpandUse(). * However other things might cause us to build one of its * children - and so we mustn't do any processing here when * the child build finishes. */ if (pgn->type & OP_MADE) { if (DEBUG(MAKE)) fprintf(debug_file, "- .MADE\n"); continue; } if ( ! (cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE))) { if (cgn->made == MADE) pgn->flags |= CHILDMADE; (void)Make_TimeStamp(pgn, cgn); } /* * A parent must wait for the completion of all instances * of a `::' dependency. */ if (centurion->unmade_cohorts != 0 || centurion->made < MADE) { if (DEBUG(MAKE)) fprintf(debug_file, "- centurion made %d, %d unmade cohorts\n", centurion->made, centurion->unmade_cohorts); continue; } /* One more child of this parent is now made */ pgn->unmade -= 1; if (pgn->unmade < 0) { if (DEBUG(MAKE)) { fprintf(debug_file, "Graph cycles through %s%s\n", pgn->name, pgn->cohort_num); Targ_PrintGraph(2); } Error("Graph cycles through %s%s", pgn->name, pgn->cohort_num); } /* We must always rescan the parents of .WAIT and .ORDER nodes. */ if (pgn->unmade != 0 && !(centurion->type & OP_WAIT) && !(centurion->flags & DONE_ORDER)) { if (DEBUG(MAKE)) fprintf(debug_file, "- unmade children\n"); continue; } if (pgn->made != DEFERRED) { /* * Either this parent is on a different branch of the tree, * or it on the RHS of a .WAIT directive * or it is already on the toBeMade list. */ if (DEBUG(MAKE)) fprintf(debug_file, "- not deferred\n"); continue; } if (pgn->order_pred && Lst_ForEach(pgn->order_pred, MakeCheckOrder, 0)) { /* A .ORDER rule stops us building this */ continue; } if (DEBUG(MAKE)) { static int two = 2; fprintf(debug_file, "- %s%s made, schedule %s%s (made %d)\n", cgn->name, cgn->cohort_num, pgn->name, pgn->cohort_num, pgn->made); Targ_PrintNode(pgn, &two); } /* Ok, we can schedule the parent again */ pgn->made = REQUESTED; (void)Lst_EnQueue(toBeMade, pgn); } Lst_Close(parents); } /* * Set the .PREFIX and .IMPSRC variables for all the implied parents * of this node. */ if (Lst_Open(cgn->iParents) == SUCCESS) { char *cpref = Var_Value(PREFIX, cgn, &p1); while ((ln = Lst_Next(cgn->iParents)) != NULL) { pgn = (GNode *)Lst_Datum(ln); if (pgn->flags & REMAKE) { Var_Set(IMPSRC, cname, pgn, 0); if (cpref != NULL) Var_Set(PREFIX, cpref, pgn, 0); } } free(p1); Lst_Close(cgn->iParents); } }
void myfclose(FILE *file) { int fid = fileno(file); if (fclose(file) < 0) Punt("Error in myfclose!"); DEBUG1("# %d : <Closed>\n", fid) }
/*- * MainParseArgs -- * Parse a given argument vector. Called from main() and from * Main_ParseArgLine() when the .MAKEFLAGS target is used. * * XXX: Deal with command line overriding .MAKEFLAGS in makefile * * Results: * None * * Side Effects: * Various global and local flags will be set depending on the flags * given */ static void MainParseArgs(int argc, char **argv) { char *p; int c = '?'; int arginc; char *argvalue; const char *getopt_def; char *optscan; Boolean inOption, dashDash = FALSE; char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ #define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstw" /* Can't actually use getopt(3) because rescanning is not portable */ getopt_def = OPTFLAGS; rearg: inOption = FALSE; optscan = NULL; while(argc > 1) { char *getopt_spec; if(!inOption) optscan = argv[1]; c = *optscan++; arginc = 0; if(inOption) { if(c == '\0') { ++argv; --argc; inOption = FALSE; continue; } } else { if (c != '-' || dashDash) break; inOption = TRUE; c = *optscan++; } /* '-' found at some earlier point */ getopt_spec = strchr(getopt_def, c); if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') { /* -<something> found, and <something> should have an arg */ inOption = FALSE; arginc = 1; argvalue = optscan; if(*argvalue == '\0') { if (argc < 3) goto noarg; argvalue = argv[2]; arginc = 2; } } else { argvalue = NULL; } switch(c) { case '\0': arginc = 1; inOption = FALSE; break; case 'B': compatMake = TRUE; Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0); break; case 'C': if (chdir(argvalue) == -1) { (void)fprintf(stderr, "%s: chdir %s: %s\n", progname, argvalue, strerror(errno)); exit(1); } if (getcwd(curdir, MAXPATHLEN) == NULL) { (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno)); exit(2); } ignorePWD = TRUE; break; case 'D': if (argvalue == NULL || argvalue[0] == 0) goto noarg; Var_Set(argvalue, "1", VAR_GLOBAL, 0); Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); break; case 'I': if (argvalue == NULL) goto noarg; Parse_AddIncludeDir(argvalue); Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); break; case 'J': if (argvalue == NULL) goto noarg; if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) { (void)fprintf(stderr, "%s: internal error -- J option malformed (%s)\n", progname, argvalue); usage(); } if ((fcntl(jp_0, F_GETFD, 0) < 0) || (fcntl(jp_1, F_GETFD, 0) < 0)) { #if 0 (void)fprintf(stderr, "%s: ###### warning -- J descriptors were closed!\n", progname); exit(2); #endif jp_0 = -1; jp_1 = -1; compatMake = TRUE; } else { Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); jobServer = TRUE; } break; case 'N': noExecute = TRUE; noRecursiveExecute = TRUE; Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); break; case 'S': keepgoing = FALSE; Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); break; case 'T': if (argvalue == NULL) goto noarg; tracefile = bmake_strdup(argvalue); Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); break; case 'V': if (argvalue == NULL) goto noarg; printVars = TRUE; (void)Lst_AtEnd(variables, argvalue); Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); break; case 'W': parseWarnFatal = TRUE; break; case 'X': varNoExportEnv = TRUE; Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); break; case 'd': if (argvalue == NULL) goto noarg; /* If '-d-opts' don't pass to children */ if (argvalue[0] == '-') argvalue++; else { Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); } parse_debug_options(argvalue); break; case 'e': checkEnvFirst = TRUE; Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); break; case 'f': if (argvalue == NULL) goto noarg; (void)Lst_AtEnd(makefiles, argvalue); break; case 'i': ignoreErrors = TRUE; Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); break; case 'j': if (argvalue == NULL) goto noarg; forceJobs = TRUE; maxJobs = strtol(argvalue, &p, 0); if (*p != '\0' || maxJobs < 1) { (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n", progname); exit(1); } Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0); maxJobTokens = maxJobs; break; case 'k': keepgoing = TRUE; Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); break; case 'm': if (argvalue == NULL) goto noarg; /* look for magic parent directory search string */ if (strncmp(".../", argvalue, 4) == 0) { if (!Dir_FindHereOrAbove(curdir, argvalue+4, found_path, sizeof(found_path))) break; /* nothing doing */ (void)Dir_AddDir(sysIncPath, found_path); } else { (void)Dir_AddDir(sysIncPath, argvalue); } Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); break; case 'n': noExecute = TRUE; Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); break; case 'q': queryFlag = TRUE; /* Kind of nonsensical, wot? */ Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); break; case 'r': noBuiltins = TRUE; Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); break; case 's': beSilent = TRUE; Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); break; case 't': touchFlag = TRUE; Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); break; case 'w': enterFlag = TRUE; Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL); break; case '-': dashDash = TRUE; break; default: case '?': #ifndef MAKE_NATIVE fprintf(stderr, "getopt(%s) -> %d (%c)\n", OPTFLAGS, c, c); #endif usage(); } argv += arginc; argc -= arginc; } oldVars = TRUE; /* * See if the rest of the arguments are variable assignments and * perform them if so. Else take them to be targets and stuff them * on the end of the "create" list. */ for (; argc > 1; ++argv, --argc) if (Parse_IsVar(argv[1])) { Parse_DoVar(argv[1], VAR_CMD); } else { if (!*argv[1]) Punt("illegal (null) argument."); if (*argv[1] == '-' && !dashDash) goto rearg; (void)Lst_AtEnd(create, bmake_strdup(argv[1])); } return; noarg: (void)fprintf(stderr, "%s: option requires an argument -- %c\n", progname, c); usage(); }
/*- * MainParseArgs -- * Parse a given argument vector. Called from main() and from * Main_ParseArgLine() when the .MAKEFLAGS target is used. * * XXX: Deal with command line overriding .MAKEFLAGS in makefile * * Side Effects: * Various global and local flags will be set depending on the flags * given */ static void MainParseArgs(int argc, char **argv) { int c, optend; #define OPTFLAGS "BC:D:I:SV:d:ef:ij:km:npqrst" #define OPTLETTERS "BSiknpqrst" if (pledge("stdio rpath wpath cpath proc exec", NULL) == -1) err(2, "pledge"); optind = 1; /* since we're called more than once */ optreset = 1; optend = 0; while (optind < argc) { if (!optend && argv[optind][0] == '-') { if (argv[optind][1] == '\0') optind++; /* ignore "-" */ else if (argv[optind][1] == '-' && argv[optind][2] == '\0') { optind++; /* ignore "--" */ optend++; /* "--" denotes end of flags */ } } c = optend ? -1 : getopt(argc, argv, OPTFLAGS); switch (c) { case 'C': break; case 'D': Var_Set(optarg, "1"); record_option(c, optarg); break; case 'I': Parse_AddIncludeDir(optarg); record_option(c, optarg); break; case 'V': Lst_AtEnd(&varstoprint, optarg); record_option(c, optarg); break; case 'd': { char *modules = optarg; for (; *modules; ++modules) switch (*modules) { case 'A': debug = ~0; break; case 'a': debug |= DEBUG_ARCH; break; case 'c': debug |= DEBUG_COND; break; case 'd': debug |= DEBUG_DIR; break; case 'D': debug |= DEBUG_DOUBLE; break; case 'e': debug |= DEBUG_EXPENSIVE; break; case 'f': debug |= DEBUG_FOR; break; case 'g': if (modules[1] == '1') { debug |= DEBUG_GRAPH1; ++modules; } else if (modules[1] == '2') { debug |= DEBUG_GRAPH2; ++modules; } break; case 'h': debug |= DEBUG_HELDJOBS; break; case 'j': debug |= DEBUG_JOB | DEBUG_KILL; break; case 'J': /* ignore */ break; case 'k': debug |= DEBUG_KILL; break; case 'l': debug |= DEBUG_LOUD; break; case 'm': debug |= DEBUG_MAKE; break; case 'n': debug |= DEBUG_NAME_MATCHING; break; case 'p': debug |= DEBUG_PARALLEL; break; case 'q': debug |= DEBUG_QUICKDEATH; break; case 's': debug |= DEBUG_SUFF; break; case 't': debug |= DEBUG_TARG; break; case 'T': debug |= DEBUG_TARGGROUP; break; case 'v': debug |= DEBUG_VAR; break; default: (void)fprintf(stderr, "make: illegal argument to -d option -- %c\n", *modules); usage(); } record_option(c, optarg); break; } case 'f': Lst_AtEnd(&makefiles, optarg); break; case 'j': { char *endptr; forceJobs = true; maxJobs = strtol(optarg, &endptr, 0); if (endptr == optarg) { fprintf(stderr, "make: illegal argument to -j option -- %s -- not a number\n", optarg); usage(); } record_option(c, optarg); break; } case 'm': Dir_AddDir(systemIncludePath, optarg); record_option(c, optarg); break; case -1: /* Check for variable assignments and targets. */ if (argv[optind] != NULL && !Parse_CmdlineVar(argv[optind])) { if (!*argv[optind]) Punt("illegal (null) argument."); Lst_AtEnd(create, estrdup(argv[optind])); } optind++; /* skip over non-option */ break; default: posixParseOptLetter(c); } } }