/* * Decide what type of # directive this line is. */ int deftype (char *line, struct filepointer *filep, struct inclist *file_red, struct inclist *file, int parse_it) { register char *p; char *directive, savechar; register int ret; /* Parse the directive... */ directive = line + 1; while (*directive == ' ' || *directive == '\t') directive++; p = directive; while (*p >= 'a' && *p <= 'z') p++; savechar = *p; *p = '\0'; ret = match (directive, directives); *p = savechar; /* If we don't recognize this compiler directive or we happen to just be gobbling up text while waiting for an #endif or #elif or #else in the case of an #elif we must check the zero_value and return an ELIF or an ELIFFALSE. */ if (ret == ELIF && !parse_it) { while (*p == ' ' || *p == '\t') p++; /* parse an expression. */ debug (0, ("%s, line %d: #elif %s ", file->i_file, filep->f_line, p)); ret = zero_value (p, filep, file_red); if (ret != IF) { debug (0, ("false...\n")); if (ret == IFFALSE) return (ELIFFALSE); else return (ELIFGUESSFALSE); } else { debug (0, ("true...\n")); return (ELIF); } } if (ret < 0 || !parse_it) return (ret); /* now decide how to parse the directive, and do it. */ while (*p == ' ' || *p == '\t') p++; switch (ret) { case IF: /* parse an expression. */ ret = zero_value (p, filep, file_red); debug (0, ("%s, line %d: %s #if %s\n", file->i_file, filep->f_line, ret ? "false" : "true", p)); break; case IFDEF: case IFNDEF: debug (0, ("%s, line %d: #%s %s\n", file->i_file, filep->f_line, directives[ret], p)); case UNDEF: /* separate the name of a single symbol. */ while (isalnum (*p) || *p == '_') *line++ = *p++; *line = '\0'; break; case INCLUDE: debug (2, ("%s, line %d: #include %s\n", file->i_file, filep->f_line, p)); /* Support ANSI macro substitution */ { struct symtab **sym = isdefined (p, file_red, NULL); while (sym) { p = (char *)(*sym)->s_value; debug (3, ("%s : #includes SYMBOL %s = %s\n", file->i_incstring, (*sym)->s_name, (*sym)->s_value)); /* mark file as having included a 'soft include' */ file->i_flags |= INCLUDED_SYM; sym = isdefined (p, file_red, NULL); } } /* Separate the name of the include file. */ while (*p && *p != '"' && *p != '<') p++; if (!*p) return (-2); if (*p++ == '"') { ret = INCLUDEDOT; while (*p && *p != '"') *line++ = *p++; } else while (*p && *p != '>') *line++ = *p++; *line = '\0'; break; case DEFINE: /* copy the definition back to the beginning of the line. */ strcpy (line, p); break; case ELSE: case ENDIF: case ELIF: case PRAGMA: case ERROR: case IDENT: case SCCS: case EJECT: case WARNING: debug (0, ("%s, line %d: #%s\n", file->i_file, filep->f_line, directives[ret])); /* nothing to do. */ break; } return (ret); }
/* * Decide what type of # directive this line is. */ int deftype (char *line, struct filepointer *filep, struct inclist *file_red, struct inclist *file, int parse_it, struct symhash *symbols) { char *p; char *directive, savechar; int ret; /* * Parse the directive... */ directive=line+1; while (*directive == ' ' || *directive == '\t') directive++; p = directive; while (*p >= 'a' && *p <= 'z') p++; savechar = *p; *p = '\0'; ret = match(directive, directives); *p = savechar; /* If we don't recognize this compiler directive or we happen to just * be gobbling up text while waiting for an #endif or #elif or #else * in the case of an #elif we must check the zero_value and return an * ELIF or an ELIFFALSE. */ if (ret == ELIF && !parse_it) { while (*p == ' ' || *p == '\t') p++; /* * parse an expression. */ debug(0,("%s, line %d: #elif %s ", file->i_file, filep->f_line, p)); ret = zero_value(p, filep, file_red, symbols); if (ret != IF) { debug(0,("false...\n")); if (ret == IFFALSE) return ELIFFALSE; else return ELIFGUESSFALSE; } else { debug(0,("true...\n")); return ELIF; } } if (ret < 0 || ! parse_it) return ret; /* * now decide how to parse the directive, and do it. */ while (*p == ' ' || *p == '\t') p++; switch (ret) { case IF: /* * parse an expression. */ ret = zero_value(p, filep, file_red, symbols); debug(0,("%s, line %d: %s #if %s\n", file->i_file, filep->f_line, ret?"false":"true", p)); break; case IFDEF: case IFNDEF: debug(0,("%s, line %d: #%s %s\n", file->i_file, filep->f_line, directives[ret], p)); //fall-through case UNDEF: /* * separate the name of a single symbol. */ while (isalnum((unsigned char)*p) || *p == '_') *line++ = *p++; *line = '\0'; break; case INCLUDE: debug(2,("%s, line %d: #include %s\n", file->i_file, filep->f_line, p)); /* Support ANSI macro substitution */ { char *sym = hash_lookup(p, symbols); while (sym) { p = sym; debug(3,("%s : #includes SYMBOL %s\n", file->i_incstring, sym)); /* mark file as having included a 'soft include' */ file->i_included_sym = TRUE; sym = hash_lookup(p, symbols); } } /* * Separate the name of the include file. */ while (*p && *p != '"' && *p != '<') p++; if (! *p) return -2; if (*p++ == '"') { ret = INCLUDEDOT; while (*p && *p != '"') *line++ = *p++; } else while (*p && *p != '>') *line++ = *p++; *line = '\0'; break; case DEFINE: /* * copy the definition back to the beginning of the line. */ memmove (line, p, strlen(p)); break; case ELSE: case ENDIF: case ELIF: case PRAGMA: case ERROR: case IDENT: case SCCS: case EJECT: debug(0,("%s, line %d: #%s\n", file->i_file, filep->f_line, directives[ret])); /* * nothing to do. */ break; } return ret; }
bool handler__set(globals_t * vars, char **argv, unsigned argc) { unsigned block, seconds = 1; char *delay = NULL; char *end; bool cont = false; struct setting { char *matchids; char *value; unsigned seconds; } *settings = NULL; assert(argc != 0); assert(argv != NULL); assert(vars != NULL); if (argc < 2) { show_error("expected an argument, type `help set` for details.\n"); return false; } /* supporting `set` for bytearray will cause annoying syntax problems... */ if ((vars->options.scan_data_type == BYTEARRAY) ||(vars->options.scan_data_type == STRING)) { show_error("`set` is not supported for bytearray or string, use `write` instead.\n"); return false; } /* check if there are any matches */ if (vars->num_matches == 0) { show_error("no matches are known.\n"); return false; } /* --- parse arguments into settings structs --- */ settings = calloca(argc - 1, sizeof(struct setting)); /* parse every block into a settings struct */ for (block = 0; block < argc - 1; block++) { /* first seperate the block into matches and value, which are separated by '=' */ if ((settings[block].value = strchr(argv[block + 1], '=')) == NULL) { /* no '=' found, whole string must be the value */ settings[block].value = argv[block + 1]; } else { /* there is a '=', value+1 points to value string. */ /* use strndupa() to copy the matchids into a new buffer */ settings[block].matchids = strndupa(argv[block + 1], (size_t) (settings[block].value++ - argv[block + 1])); } /* value points to the value string, possibly with a delay suffix */ /* matchids points to the match-ids (possibly multiple) or NULL */ /* now check for a delay suffix (meaning continuous mode), eg 0xff/10 */ if ((delay = strchr(settings[block].value, '/')) != NULL) { char *end = NULL; /* parse delay count */ settings[block].seconds = strtoul(delay + 1, &end, 10); if (*(delay + 1) == '\0') { /* empty delay count, eg: 12=32/ */ show_error("you specified an empty delay count, `%s`, see `help set`.\n", settings[block].value); return false; } else if (*end != '\0') { /* parse failed before end, probably trailing garbage, eg 34=9/16foo */ show_error("trailing garbage after delay count, `%s`.\n", settings[block].value); return false; } else if (settings[block].seconds == 0) { /* 10=24/0 disables continous mode */ show_info("you specified a zero delay, disabling continuous mode.\n"); } else { /* valid delay count seen and understood */ show_info("setting %s every %u seconds until interrupted...\n", settings[block].matchids ? settings[block]. matchids : "all", settings[block].seconds); /* continuous mode on */ cont = true; } /* remove any delay suffix from the value */ settings[block].value = strndupa(settings[block].value, (size_t) (delay - settings[block].value)); } /* if (strchr('/')) */ } /* for(block...) */ /* --- setup a longjmp to handle interrupt --- */ if (INTERRUPTABLE()) { /* control returns here when interrupted */ // settings is allocated with alloca, do not free it // free(settings); detach(vars->target); ENDINTERRUPTABLE(); return true; } /* --- execute the parsed setting structs --- */ while (true) { uservalue_t userval; /* for every settings struct */ for (block = 0; block < argc - 1; block++) { /* check if this block has anything to do this iteration */ if (seconds != 1) { /* not the first iteration (all blocks get executed first iteration) */ /* if settings.seconds is zero, then this block is only executed once */ /* if seconds % settings.seconds is zero, then this block must be executed */ if (settings[block].seconds == 0 || (seconds % settings[block].seconds) != 0) continue; } /* convert value */ if (!parse_uservalue_number(settings[block].value, &userval)) { show_error("bad number `%s` provided\n", settings[block].value); goto fail; } /* check if specific match(s) were specified */ if (settings[block].matchids != NULL) { char *id, *lmatches = NULL; unsigned num = 0; /* create local copy of the matchids for strtok() to modify */ lmatches = strdupa(settings[block].matchids); /* now seperate each match, spearated by commas */ while ((id = strtok(lmatches, ",")) != NULL) { match_location loc; /* set to NULL for strtok() */ lmatches = NULL; /* parse this id */ num = strtoul(id, &end, 0x00); /* check that succeeded */ if (*id == '\0' || *end != '\0') { show_error("could not parse match id `%s`\n", id); goto fail; } /* check this is a valid match-id */ loc = nth_match(vars->matches, num); if (loc.swath) { value_t v; value_t old; void *address = remote_address_of_nth_element(loc.swath, loc.index /* ,MATCHES_AND_VALUES */); /* copy val onto v */ /* XXX: valcmp? make sure the sizes match */ old = data_to_val(loc.swath, loc.index /* ,MATCHES_AND_VALUES */); zero_value(&v); v.flags = old.flags = loc.swath->data[loc.index].match_info; uservalue2value(&v, &userval); show_info("setting *%p to %#"PRIx64"...\n", address, v.int64_value); /* set the value specified */ fix_endianness(vars, &v); if (setaddr(vars->target, address, &v) == false) { show_error("failed to set a value.\n"); goto fail; } } else { /* match-id > than number of matches */ show_error("found an invalid match-id `%s`\n", id); goto fail; } } } else { matches_and_old_values_swath *reading_swath_index = (matches_and_old_values_swath *)vars->matches->swaths; int reading_iterator = 0; /* user wants to set all matches */ while (reading_swath_index->first_byte_in_child) { /* Only actual matches are considered */ if (flags_to_max_width_in_bytes(reading_swath_index->data[reading_iterator].match_info) > 0) { void *address = remote_address_of_nth_element(reading_swath_index, reading_iterator /* ,MATCHES_AND_VALUES */); /* XXX: as above : make sure the sizes match */ value_t old = data_to_val(reading_swath_index, reading_iterator /* ,MATCHES_AND_VALUES */); value_t v; zero_value(&v); v.flags = old.flags = reading_swath_index->data[reading_iterator].match_info; uservalue2value(&v, &userval); show_info("setting *%p to %#"PRIx64"...\n", address, v.int64_value); fix_endianness(vars, &v); if (setaddr(vars->target, address, &v) == false) { show_error("failed to set a value.\n"); goto fail; } } /* Go on to the next one... */ ++reading_iterator; if (reading_iterator >= reading_swath_index->number_of_bytes) { reading_swath_index = local_address_beyond_last_element(reading_swath_index /* ,MATCHES_AND_VALUES */); reading_iterator = 0; } } } /* if (matchid != NULL) else ... */ } /* for(block) */ if (cont) { sleep(1); } else { break; } seconds++; } /* while(true) */ ENDINTERRUPTABLE(); return true; fail: ENDINTERRUPTABLE(); return false; }