void cmd_delete() { int m, n; get_int_opt(&m); next_arg(); get_int_opt(&n); if (m > n) notif_error("First argument cannot be greater than the second"); copy_lines(m - 1); if (m < ln) notif_error("Invalid line number"); goto_line(n + 1); }
void cmd_replace() { int m, n; get_int_opt(&m); next_arg(); get_int_opt(&n); if (m > n) notif_error("First argument cannot be greater than the second"); next_arg(); copy_lines(m - 1); if (m < ln) return; goto_line(n + 1); write_text(); }
void cmd_insert() { int m; size_t text_len; get_int_opt(&m); if (m < ln) notif_error("Invalid line number"); next_arg(); copy_lines(m); write_text(); ln = m + 1; }
static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) { struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t)); memset(sb, 0, sizeof(struct sb_file_t)); sb_build_default_image(sb); if(db_find_option_by_id(cmd_file->opt_list, "componentVersion") && !db_parse_sb_version(&sb->component_ver, get_str_opt(cmd_file->opt_list, "componentVersion", ""))) bug("Invalid 'componentVersion' format\n"); if(db_find_option_by_id(cmd_file->opt_list, "productVersion") && !db_parse_sb_version(&sb->product_ver, get_str_opt(cmd_file->opt_list, "productVersion", ""))) bug("Invalid 'productVersion' format\n"); if(db_find_option_by_id(cmd_file->opt_list, "sbMinorVersion")) sb->minor_version = get_int_opt(cmd_file->opt_list, "sbMinorVersion", 0); if(db_find_option_by_id(cmd_file->opt_list, "flags")) sb->flags = get_int_opt(cmd_file->opt_list, "flags", 0); if(db_find_option_by_id(cmd_file->opt_list, "driveTag")) sb->drive_tag = get_int_opt(cmd_file->opt_list, "driveTag", 0); if(db_find_option_by_id(cmd_file->opt_list, "timestampLow")) { if(!db_find_option_by_id(cmd_file->opt_list, "timestampHigh")) bug("Option 'timestampLow' and 'timestampHigh' must both specified\n"); sb->timestamp = (uint64_t)get_int_opt(cmd_file->opt_list, "timestampHigh", 0) << 32 | get_int_opt(cmd_file->opt_list, "timestampLow", 0); } if(g_debug) printf("Applying command file...\n"); /* count sections */ struct cmd_section_t *csec = cmd_file->section_list; while(csec) { sb->nr_sections++; csec = csec->next; } sb->sections = xmalloc(sb->nr_sections * sizeof(struct sb_section_t)); memset(sb->sections, 0, sb->nr_sections * sizeof(struct sb_section_t)); /* flatten sections */ csec = cmd_file->section_list; for(int i = 0; i < sb->nr_sections; i++, csec = csec->next) { struct sb_section_t *sec = &sb->sections[i]; sec->identifier = csec->identifier; /* options */ do { /* cleartext */ sec->is_cleartext = get_int_opt(csec->opt_list, "cleartext", false); /* alignment */ sec->alignment = get_int_opt(csec->opt_list, "alignment", BLOCK_SIZE); // alignement cannot be lower than block size if((sec->alignment & (sec->alignment - 1)) != 0) bug("Alignment section attribute must be a power of two\n"); if(sec->alignment < BLOCK_SIZE) sec->alignment = BLOCK_SIZE; /* other flags */ sec->other_flags = get_int_opt(csec->opt_list, "sectionFlags", 0) & ~SECTION_STD_MASK; }while(0); if(csec->is_data) { sec->is_data = true; sec->nr_insts = 1; sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t)); memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t)); load_bin_by_id(cmd_file, csec->source_id); struct bin_param_t *bin = &db_find_source_by_id(cmd_file, csec->source_id)->bin; sec->insts[0].inst = SB_INST_DATA; sec->insts[0].size = bin->size; sec->insts[0].data = memdup(bin->data, bin->size); } else { sec->is_data = false; /* count instructions and loads things */ struct cmd_inst_t *cinst = csec->inst_list; while(cinst) { if(cinst->type == CMD_LOAD) { load_elf_by_id(cmd_file, cinst->identifier); struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf; sec->nr_insts += elf_get_nr_sections(elf); } else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL) { load_elf_by_id(cmd_file, cinst->identifier); struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf; if(!elf_get_start_addr(elf, NULL)) bug("cannot jump/call '%s' because it has no starting point !\n", cinst->identifier); sec->nr_insts++; } else if(cinst->type == CMD_CALL_AT || cinst->type == CMD_JUMP_AT) { sec->nr_insts++; } else if(cinst->type == CMD_LOAD_AT) { load_bin_by_id(cmd_file, cinst->identifier); sec->nr_insts++; } else if(cinst->type == CMD_MODE) { sec->nr_insts++; } else bug("die\n"); cinst = cinst->next; } sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t)); memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t)); /* flatten */ int idx = 0; cinst = csec->inst_list; while(cinst) { if(cinst->type == CMD_LOAD) { struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf; struct elf_section_t *esec = elf->first_section; while(esec) { if(esec->type == EST_LOAD) { sec->insts[idx].inst = SB_INST_LOAD; sec->insts[idx].addr = esec->addr; sec->insts[idx].size = esec->size; sec->insts[idx++].data = memdup(esec->section, esec->size); } else if(esec->type == EST_FILL) { sec->insts[idx].inst = SB_INST_FILL; sec->insts[idx].addr = esec->addr; sec->insts[idx].size = esec->size; sec->insts[idx++].pattern = esec->pattern; } esec = esec->next; } } else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL) { struct elf_params_t *elf = &db_find_source_by_id(cmd_file, cinst->identifier)->elf; sec->insts[idx].argument = cinst->argument; sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL; sec->insts[idx++].addr = elf->start_addr; } else if(cinst->type == CMD_JUMP_AT || cinst->type == CMD_CALL_AT) { sec->insts[idx].argument = cinst->argument; sec->insts[idx].inst = (cinst->type == CMD_JUMP_AT) ? SB_INST_JUMP : SB_INST_CALL; sec->insts[idx++].addr = cinst->addr; } else if(cinst->type == CMD_LOAD_AT) { struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin; sec->insts[idx].inst = SB_INST_LOAD; sec->insts[idx].addr = cinst->addr; sec->insts[idx].data = memdup(bin->data, bin->size); sec->insts[idx++].size = bin->size; } else if(cinst->type == CMD_MODE) { sec->insts[idx].inst = SB_INST_MODE; sec->insts[idx++].addr = cinst->argument; } else bug("die\n"); cinst = cinst->next; } } } return sb; }