/* mkvar: adds s to the list l of the current pattern's variables */ List mkvar (Symbol s, List l) { var_t *var; if (debugp) fprintf(stderr, "/* mkvar: %s [l=%d,r=%d] */\n", s->name, s->l, s->r); foreach(stab, checksame, s, 0); NEW(var, 1, ARENA0); var->id = s->name[0]-'a'; var->sh = SZ-1-s->r; var->msk = ((2 << (s->r - s->l)) - 1) << var->sh; return l_append((void *)var, l, ARENA0); }
/* concatenate list src with list dst */ int l_concat(list_t *dst, list_t **src) { void *data; element_t *n; n = (*src)->head; while (n) { l_remove(*src, NULL, &data); if (l_append(dst, NULL, data) == -1) return -1; n = (*src)->head; } l_destroy(*src); *src = NULL; return 0; }
static int add_section_label(struct label *l, const char *name, const char *attribute, uint64_t value, struct label **length) { char label[255]; int errcode; errcode = create_section_label_name(label, sizeof(label), name, attribute); if (errcode < 0) return errcode; errcode = l_append(l, label, value); if (errcode < 0) return errcode; if (length) *length = l_find(l, label); return 0; }
/*lint -esym(818,handler) dont declare handler const */ bool registercommand(const char *command, void *handler, list_t * commands, char *shortdoc, char *longdoc) { command_t *data; assert(commands != NULL); if (command != NULL) { if ((data = malloc(sizeof(command_t) + strlen(command) + 1)) == NULL) { show_error("sorry, there was a memory allocation problem.\n"); return false; } data->command = (char *) data + sizeof(*data); /* command points to the extra space allocated after data */ strcpy(data->command, command); } else { if ((data = malloc(sizeof(command_t))) == NULL) { show_error("sorry, there was a memory allocation problem.\n"); return false; } data->command = NULL; } data->handler = handler; data->shortdoc = shortdoc; data->longdoc = longdoc; /* add new command to list */ if (l_append(commands, NULL, data) == -1) { free(data); return false; } return true; }
int parse_yasm_labels(struct label *l, const struct text *t) { int errcode, no_org_directive; size_t i; uint64_t base_addr; enum { linelen = 1024 }; char line[linelen]; if (bug_on(!t)) return -err_internal; base_addr = 0; no_org_directive = 1; /* determine base address from org directive, error out on * sections. */ for (i = 0; i < t->n; i++) { char *tmp; errcode = text_line(t, line, linelen, i); if (errcode < 0) return errcode; tmp = strstr(line, "[section"); if (tmp) return -err_section; tmp = strstr(line, "[org"); if (!tmp) continue; base_addr = strtol(tmp+strlen("[org"), NULL, 0); no_org_directive = 0; break; } if (no_org_directive) return -err_no_org_directive; for (i = 0; i < t->n; i++) { char *tmp, *name; uint64_t addr; errcode = text_line(t, line, linelen, i); if (errcode < 0) goto error; /* skip line number count. */ tmp = strtok(line, " "); if (!tmp) continue; /* the label can now be on the same line as the memory * address or on a line by its own. * we look at the next token and (1) if it looks like a * label, we search in the following lines for the * corresponding address; or (2) if it looks like an * address, we store it and see if the token after the * opcode looks like a token; or (3) none of the above, * we continue with the next line. */ /* second token after the line number count. it's * either an address; or a label. */ tmp = strtok(NULL, " "); if (!tmp) continue; if (!make_label(tmp)) { /* get address in case we find a label later. */ if (sscanf(tmp, "%" PRIx64, &addr) != 1) continue; /* skip the opcode token. */ tmp = strtok(NULL, " "); if (!tmp) continue; /* this might be a label now. */ tmp = strtok(NULL, " "); if (!make_label(tmp)) continue; errcode = l_append(l, tmp, addr + base_addr); if (errcode < 0) goto error; continue; } name = duplicate_str(tmp); if (!name) { errcode = -err_no_mem; goto error; } /* there was a label so now an address needs to * be found. */ errcode = -err_label_addr; for (i += 1; i < t->n; i++) { int errcode_text; errcode_text = text_line(t, line, linelen, i); if (errcode_text < 0) { errcode = errcode_text; break; } if (sscanf(line, "%*d %" PRIx64 " %*x %*s", &addr) == 1) { errcode = l_append(l, name, addr + base_addr); break; } } if (errcode == -err_label_addr) fprintf(stderr, "label '%s' has no address\n", name); free(name); if (errcode < 0) goto error; } return 0; error: l_free(l->next); free(l->name); l->next = NULL; l->name = NULL; return errcode; }
/* scan: parse the contents of fp, expecting the input side (phase) of a rule if ph=='i', or the output side if ph=='o' */ List scan (FILE *fp, int ph) { int c = 0; /* Current char on fp */ int nb = 0, nw = 0; /* Position in rule (bit/word) */ Symbol csym = 0L; /* Current variable being scanned */ T f_msk=(T)0, f_val=(T)0; /* Current constant mask and value */ List pats = 0L; /* All the patterns (words) for this phase */ List vars = 0L; /* All the vars for a given pattern */ while ((c=getc(fp)) != EOF) { if (debugp) fprintf(stdout, "/* bit: %c msk: 0x%x val: 0x%x */\n", c, (unsigned)f_msk, (unsigned)f_val); /* Inputs end with '=', outputs with '+' */ if ((c == '=' && ph == 'i') || (c == '+' && ph == 'o')) break; switch(c) { case ' ': case '\f': case '\n': case '\r': case '\t': case '\v': continue; case '#': /* Comment character */ while ((c=getc(fp)) != EOF && c != '\n'); if (c == EOF && (nb > 0 || (ph == 'i' && nw > 0))) error(stringf("Unexpected end of file reading patterns at " "rule %d, word %c%d, bit %d", nr,ph,nw,nb)); continue; case '-': /* Denotes body of a variable */ if (!csym) /* We must be defining a variable */ error(stringf("'-' appears with no leading symbol " "at rule %d, word %c%d, bit %d", nr, ph, nw, nb)); else { /* Extend the variable's right boundary */ ++csym->r; assert(csym->r == nb); } break; case '0': case '1': /* Constant characters */ if (csym) { /* End any variable definition */ vars = mkvar(csym, vars); csym = 0L; } f_msk |= 1; f_val |= (c-'0'); break; default: c = tolower(c); /* Variables named by a-z, case insensitive */ if (c >= 'a' && c <= 'z') { char *s = stringf("%c", c); if (csym) vars = mkvar(csym, vars); if (!lookup(s, stab) && ph == 'o') error(stringf("Symbol '%c' used with no prior " "definition at rule %d, word o%d", c, nr, nw)); csym = install(s, stab); csym->l = csym->r = nb; } else error(stringf("Illegal character in rule file at rule %d, " "word %c%d, bit %d", nr, ph, nw, nb)); } if (nb == SZ-1) { /* End of a pattern (word): append this info */ pat_t *pat; /* to list of patterns, and reset current */ if (csym) { /* pattern state (masks, vars, bit count) */ vars = mkvar(csym, vars); csym = 0L; } NEW(pat, 1, ARENA0); pat->f_msk = f_msk; f_msk = (T)0; pat->f_val = f_val; f_val = (T)0; pat->nv = l_length(vars); if (debugp) fprintf(stdout, "/* msk: 0x%x, val: 0x%x, nv: 0x%x */\n", (unsigned)pat->f_msk, (unsigned)pat->f_val, pat->nv); l_ltov(pat->v, var_t *, vars, ARENA0); pats = l_append(pat, pats, ARENA0); ++nw; nb = 0; vars = 0L; } else { /* Still more to go: move on to next bit */ ++nb; f_msk <<= 1; f_val <<= 1;
/* Processes the current directive. * If the encoder returns an error, a message including current file and * line number together with the pt error string is printed on stderr. * * Returns 0 on success; a negative enum errcode otherwise. * Returns -err_internal if @p or @e is the NULL pointer. * Returns -err_parse_missing_directive if there was a pt directive marker, * but no directive. * Returns -stop_process if the .exp directive was encountered. * Returns -err_pt_lib if the pt encoder returned an error. * Returns -err_parse if a general parsing error was encountered. * Returns -err_parse_unknown_directive if there was an unknown pt directive. */ static int p_process(struct parser *p, struct pt_encoder *e) { int bytes_written; int errcode; char *directive, *payload, *pt_label_name, *tmp; struct pt_directive *pd; struct pt_packet packet; if (bug_on(!p)) return -err_internal; if (bug_on(!e)) return -err_internal; pd = p->pd; if (!pd) return -err_internal; directive = pd->name; payload = pd->payload; pt_label_name = NULL; bytes_written = 0; errcode = 0; /* find a label name. */ tmp = strchr(directive, ':'); if (tmp) { uint64_t x; pt_label_name = directive; directive = tmp+1; *tmp = '\0'; /* ignore whitespace between label and directive. */ while (isspace(*directive)) directive += 1; /* if we can lookup a yasm label with the same name, the * current pt directive label is invalid. */ errcode = yasm_lookup_label(p->y, &x, pt_label_name); if (errcode == 0) errcode = -err_label_not_unique; if (errcode != -err_no_label) return yasm_print_err(p->y, "label lookup", errcode); /* if we can lookup a pt directive label with the same * name, the current pt directive label is invalid. */ errcode = l_lookup(p->pt_labels, &x, pt_label_name); if (errcode == 0) errcode = -err_label_not_unique; if (errcode != -err_no_label) return yasm_print_err(p->y, "label lookup", -err_label_not_unique); } /* now try to match the directive string and call the * corresponding function that parses the payload and emits an * according packet. */ if (strcmp(directive, "") == 0) return yasm_print_err(p->y, "invalid syntax", -err_parse_missing_directive); else if (strcmp(directive, ".exp") == 0) { /* this is the end of processing pt directives, so we * add a p_last label to the pt directive labels. */ errcode = l_append(p->pt_labels, "eos", p->pt_bytes_written); if (errcode < 0) return yasm_print_err(p->y, "append label", errcode); return -stop_process; } if (strcmp(directive, "psb") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "psb: parsing failed", errcode); goto error; } packet.type = ppt_psb; } else if (strcmp(directive, "psbend") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "psbend: parsing failed", errcode); goto error; } packet.type = ppt_psbend; } else if (strcmp(directive, "pad") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "pad: parsing failed", errcode); goto error; } packet.type = ppt_pad; } else if (strcmp(directive, "ovf") == 0) { errcode = parse_empty(payload); if (errcode < 0) { yasm_print_err(p->y, "ovf: parsing failed", errcode); goto error; } packet.type = ppt_ovf; } else if (strcmp(directive, "tnt") == 0) { errcode = parse_tnt(&packet.payload.tnt.payload, &packet.payload.tnt.bit_size, payload); if (errcode < 0) { yasm_print_err(p->y, "tnt: parsing failed", errcode); goto error; } packet.type = ppt_tnt_8; } else if (strcmp(directive, "tnt64") == 0) { errcode = parse_tnt(&packet.payload.tnt.payload, &packet.payload.tnt.bit_size, payload); if (errcode < 0) { yasm_print_err(p->y, "tnt64: parsing failed", errcode); goto error; } packet.type = ppt_tnt_64; } else if (strcmp(directive, "tip") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "tip: parsing failed", errcode); goto error; } packet.type = ppt_tip; } else if (strcmp(directive, "tip.pge") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "tip.pge: parsing failed", errcode); goto error; } packet.type = ppt_tip_pge; } else if (strcmp(directive, "tip.pgd") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "tip.pgd: parsing failed", errcode); goto error; } packet.type = ppt_tip_pgd; } else if (strcmp(directive, "fup") == 0) { errcode = parse_ip(p, &packet.payload.ip.ip, &packet.payload.ip.ipc, payload); if (errcode < 0) { yasm_print_err(p->y, "fup: parsing failed", errcode); goto error; } packet.type = ppt_fup; } else if (strcmp(directive, "mode.exec") == 0) { if (strcmp(payload, "16bit") == 0) { packet.payload.mode.bits.exec.csl = 0; packet.payload.mode.bits.exec.csd = 0; } else if (strcmp(payload, "64bit") == 0) { packet.payload.mode.bits.exec.csl = 1; packet.payload.mode.bits.exec.csd = 0; } else if (strcmp(payload, "32bit") == 0) { packet.payload.mode.bits.exec.csl = 0; packet.payload.mode.bits.exec.csd = 1; } else { errcode = yasm_print_err(p->y, "mode.exec: argument must be one of \"16bit\", \"64bit\" or \"32bit\"", -err_parse); goto error; } packet.payload.mode.leaf = pt_mol_exec; packet.type = ppt_mode; } else if (strcmp(directive, "mode.tsx") == 0) { if (strcmp(payload, "begin") == 0) { packet.payload.mode.bits.tsx.intx = 1; packet.payload.mode.bits.tsx.abrt = 0; } else if (strcmp(payload, "abort") == 0) { packet.payload.mode.bits.tsx.intx = 0; packet.payload.mode.bits.tsx.abrt = 1; } else if (strcmp(payload, "commit") == 0) { packet.payload.mode.bits.tsx.intx = 0; packet.payload.mode.bits.tsx.abrt = 0; } else { errcode = yasm_print_err(p->y, "mode.tsx: argument must be one of \"begin\", \"abort\" or \"commit\"", -err_parse); goto error; } packet.payload.mode.leaf = pt_mol_tsx; packet.type = ppt_mode; } else if (strcmp(directive, "pip") == 0) { errcode = parse_uint64(&packet.payload.pip.cr3, payload); if (errcode < 0) { yasm_print_err(p->y, "pip: parsing failed", errcode); goto error; } packet.type = ppt_pip; } else if (strcmp(directive, "tsc") == 0) { errcode = parse_uint64(&packet.payload.tsc.tsc, payload); if (errcode < 0) { yasm_print_err(p->y, "tsc: parsing failed", errcode); goto error; } packet.type = ppt_tsc; } else if (strcmp(directive, "cbr") == 0) { errcode = parse_uint8(&packet.payload.cbr.ratio, payload); if (errcode < 0) { yasm_print_err(p->y, "cbr: parsing cbr failed", errcode); goto error; } packet.type = ppt_cbr; } else { errcode = yasm_print_err(p->y, "invalid syntax", -err_parse_unknown_directive); goto error; } bytes_written = pt_enc_next(e, &packet); if (bytes_written < 0) { const char *errstr, *format; char *msg; size_t n; errstr = pt_errstr(pt_errcode(bytes_written)); format = "encoder error in directive %s (status %s)"; /* the length of format includes the "%s" (-2) * characters, we add errstr (+-0) and then we need * space for a terminating null-byte (+1). */ n = strlen(format)-4 + strlen(directive) + strlen(errstr) + 1; msg = malloc(n); if (!msg) errcode = yasm_print_err(p->y, "encoder error not enough memory to show error code", -err_pt_lib); else { sprintf(msg, format, directive, errstr); errcode = yasm_print_err(p->y, msg, -err_pt_lib); free(msg); } } else { if (pt_label_name) { errcode = l_append(p->pt_labels, pt_label_name, p->pt_bytes_written); if (errcode < 0) goto error; } p->pt_bytes_written += bytes_written; } error: if (errcode < 0) bytes_written = errcode; return bytes_written; }
int parse_yasm_labels(struct label *l, const struct text *t) { int errcode, no_org_directive; size_t i; uint64_t base_addr; enum { linelen = 1024 }; char line[linelen]; struct label *length; if (bug_on(!t)) return -err_internal; base_addr = 0; no_org_directive = 1; length = NULL; /* determine base address from org directive and insert special * section labels. */ for (i = 0; i < t->n; i++) { char *tmp; errcode = text_line(t, line, linelen, i); if (errcode < 0) return errcode; tmp = strstr(line, "[section"); if (tmp) { tmp += strlen("[section"); errcode = parse_section(tmp, l, &length); if (errcode < 0) return errcode; continue; } tmp = strstr(line, "[org"); if (tmp) { base_addr = strtol(tmp+strlen("[org"), NULL, 0); errcode = l_append(l, "org", base_addr); if (errcode < 0) return errcode; no_org_directive = 0; continue; } /* update the section_<name>_length label, if we have one. * * this must be last; it destroys @line. */ if (length) { uint64_t value, size; tmp = strtok(line, " "); if (!tmp) continue; /* we expect a line number. */ errcode = str_to_uint64(tmp, &value, 10); if (errcode < 0) continue; tmp = strtok(NULL, " "); if (!tmp) continue; /* we expect an address. */ errcode = str_to_uint64(tmp, &value, 16); if (errcode < 0) continue; tmp = strtok(NULL, " "); if (!tmp) continue; /* we expect an opcode. */ errcode = str_to_uint64(tmp, &value, 16); if (errcode < 0) continue; /* we got an opcode - let's compute it's size. */ for (size = 0; value != 0; value >>= 8) size += 1; /* update the section_<name>_length label. */ length->addr += size; } } if (no_org_directive) return -err_no_org_directive; for (i = 0; i < t->n; i++) { char *tmp, *name; uint64_t addr; errcode = text_line(t, line, linelen, i); if (errcode < 0) goto error; /* Change the base on section switches. */ tmp = strstr(line, "[section"); if (tmp) { tmp += strlen("[section"); errcode = lookup_section_vstart(l, tmp, &base_addr); if (errcode < 0) return errcode; continue; } /* skip line number count. */ tmp = strtok(line, " "); if (!tmp) continue; /* the label can now be on the same line as the memory * address or on a line by its own. * we look at the next token and (1) if it looks like a * label, we search in the following lines for the * corresponding address; or (2) if it looks like an * address, we store it and see if the token after the * opcode looks like a token; or (3) none of the above, * we continue with the next line. */ /* second token after the line number count. it's * either an address; or a label. */ tmp = strtok(NULL, " "); if (!tmp) continue; if (!make_label(tmp)) { /* get address in case we find a label later. */ if (sscanf(tmp, "%" PRIx64, &addr) != 1) continue; /* skip the opcode token. */ tmp = strtok(NULL, " "); if (!tmp) continue; /* this might be a label now. */ tmp = strtok(NULL, " "); if (!make_label(tmp)) continue; errcode = l_append(l, tmp, addr + base_addr); if (errcode < 0) goto error; continue; } name = duplicate_str(tmp); if (!name) { errcode = -err_no_mem; goto error; } /* there was a label so now an address needs to * be found. */ errcode = -err_label_addr; for (i += 1; i < t->n; i++) { int errcode_text; errcode_text = text_line(t, line, linelen, i); if (errcode_text < 0) { errcode = errcode_text; break; } if (sscanf(line, "%*d %" PRIx64 " %*x %*s", &addr) == 1) { errcode = l_append(l, name, addr + base_addr); break; } } if (errcode == -err_label_addr) fprintf(stderr, "label '%s' has no address\n", name); free(name); if (errcode < 0) goto error; } return 0; error: l_free(l->next); free(l->name); l->next = NULL; l->name = NULL; return errcode; }
/* convert: read the text rewrite rules on fp, generating bog rewrite rules (on fr) and C tables (on ft) for use with tpo */ static void convert (FILE *fp, FILE *fr, FILE *ft) { int phase = IN, lc = 0, id, vused[26], i; char c, l[LSZ], *lp, v[VSZ], *vp; List trul = 0, tlin = 0, brul = 0, blin = 0, patterns = 0; for (i = 0; i < 26; i++) vused[i] = 0; while (fgets(l, LSZ, fp)) { ++lc; if (*l == '#' || *l == '\n') continue; if (!strcmp(l, "=\n")) { /* End of input pattern */ if (phase != IN) error(stringf("Misplaced '=' at line %d", lc)); if (!blin) warning(stringf("Empty input pattern at line %d", lc)); trul = l_append((void *)tlin, trul, ARENA0); tlin = 0; brul = l_append((void *)blin, brul, ARENA0); blin = 0; phase = OUT; continue; } if (!strcmp(l, "+\n")) { /* End of output pattern */ if (phase != OUT) error(stringf("Misplaced '+' at line %d", lc)); brul = l_append((void *)blin, brul, ARENA0); blin = 0; for (i = 0; i < 26; i++) vused[i] = 0; phase = IN; continue; } /* Extend text line list */ for (lp = l; *lp; lp++) ; if (*--lp == '\n') *lp = '\0'; if (phase == IN) tlin = l_append((void*)string(l), tlin, ARENA0); vp = v; /* "Uniqueify" string */ for (lp = l; *lp; lp++) if (*lp == '%') if ((c = tolower(*++lp)) >= 'a' && c <= 'z') { int j = c-'a'; *vp++ = c; *lp = ' '; if (phase == IN) vused[j] = 1; else if (!vused[j]) error(stringf("Symbol '%%%c' used with no prior " "definition at line %d", c, lc)); } else if (c != '%') error(stringf("Illegal expression '%%%c' at line %d", c, lc)); *vp++ = 0; /* Extend list of uniq'd patterns */ if (uniq(l, &lp, &id)) patterns = l_append((void *)lp, patterns, ARENA0); PDEBUG(("convert: %s :: %d\n", lp, id)); /* Extend binary line list (for bog) */ blin = l_append((void *)id, blin, ARENA0); blin = l_append((void *)string(v), blin, ARENA0); } unparsebin(brul, fr); fprintf(ft, "#include \"tpo.h\"\n\n"); unparsepat(patterns, ft); unparsetxt(trul, ft); }
/* dregion [!][x][,x,...] */ bool handler__dregion(globals_t * vars, char **argv, unsigned argc) { unsigned id; bool invert = false; char *end = NULL, *idstr = NULL, *block = NULL; element_t *np, *pp; list_t *keep = NULL; region_t *save; /* need an argument */ if (argc < 2) { show_error("expected an argument, see `help dregion`.\n"); return false; } /* check that there is a process known */ if (vars->target == 0) { show_error("no target specified, see `help pid`\n"); return false; } /* check for an inverted match */ if (*argv[1] == '!') { invert = true; /* create a copy of the argument for strtok(), +1 to skip '!' */ block = strdupa(argv[1] + 1); /* check for lone '!' */ if (*block == '\0') { show_error("inverting an empty set, maybe try `reset` instead?\n"); return false; } /* create a list to keep the specified regions */ if ((keep = l_init()) == NULL) { show_error("memory allocation error.\n"); return false; } } else { invert = false; block = strdupa(argv[1]); } /* loop for every number specified, eg "1,2,3,4,5" */ while ((idstr = strtok(block, ",")) != NULL) { region_t *r = NULL; /* set block to NULL for strtok() */ block = NULL; /* attempt to parse as a regionid */ id = strtoul(idstr, &end, 0x00); /* check that worked, "1,abc,4,,5,6foo" */ if (*end != '\0' || *idstr == '\0') { show_error("could not parse argument %s.\n", idstr); if (invert) { if (l_concat(vars->regions, &keep) == -1) { show_error("there was a problem restoring saved regions.\n"); l_destroy(vars->regions); l_destroy(keep); return false; } } assert(keep == NULL); return false; } /* initialise list pointers */ np = vars->regions->head; pp = NULL; /* find the correct region node */ while (np) { r = np->data; /* compare the node id to the id the user specified */ if (r->id == id) break; pp = np; /* keep track of prev for l_remove() */ np = np->next; } /* check if a match was found */ if (np == NULL) { show_error("no region matching %u, or already moved.\n", id); if (invert) { if (l_concat(vars->regions, &keep) == -1) { show_error("there was a problem restoring saved regions.\n"); l_destroy(vars->regions); l_destroy(keep); return false; } } if (keep) l_destroy(keep); return false; } np = pp; /* save this region if the match is inverted */ if (invert) { assert(keep != NULL); l_remove(vars->regions, np, (void *) &save); if (l_append(keep, keep->tail, save) == -1) { show_error("sorry, there was an internal memory error.\n"); free(save); return false; } continue; } /* check for any affected matches before removing it */ if(vars->num_matches > 0) { region_t *s; /* determine the correct pointer we're supposed to be checking */ if (np) { assert(np->next); s = np->next->data; } else { /* head of list */ s = vars->regions->head->data; } if (!(vars->matches = delete_by_region(vars->matches, &vars->num_matches, s, false))) { show_error("memory allocation error while deleting matches\n"); } } l_remove(vars->regions, np, NULL); } if (invert) { region_t *s = keep->head->data; if (vars->num_matches > 0) { if (!(vars->matches = delete_by_region(vars->matches, &vars->num_matches, s, true))) { show_error("memory allocation error while deleting matches\n"); } } /* okay, done with the regions list */ l_destroy(vars->regions); /* and switch to the keep list */ vars->regions = keep; } return true; }