int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n) { unsigned int i; const char *cmd; int r; if (!n) return -EAGAIN; cmd = *args++; --n; for (i = 0; cmds[i].cmd; ++i) { if (strcmp(cmd, cmds[i].cmd)) continue; if (is_cli() && cmds[i].cli_cmp == CLI_N) continue; if (!is_cli() && cmds[i].cli_cmp == CLI_Y) continue; switch (cmds[i].argc_cmp) { case CLI_EQUAL: if (n != cmds[i].argc) { cli_printf("Invalid number of arguments\n"); return -EINVAL; } break; case CLI_MORE: if (n < cmds[i].argc) { cli_printf("too few arguments\n"); return -EINVAL; } break; case CLI_LESS: if (n > cmds[i].argc) { cli_printf("too many arguments\n"); return -EINVAL; } break; } if (cmds[i].fn) { r = cmds[i].fn(args, n); return (r == -EAGAIN) ? -EINVAL : r; } break; } if (!strcmp(cmd, "help")) return cli_help(cmds); return -EAGAIN; }
/** * Print available commands. */ static void print_commands (char *prog_name_p) /**< program name */ { cli_help (prog_name_p, NULL, main_opts); printf ("\nAvailable commands:\n" " generate\n" " merge\n" "\nPassing -h or --help after a command displays its help.\n"); } /* print_commands */
/* * NAME * cli_find_cmd * * SYNOPSIS * #include "cli.h" * static cli_record_t * *cli_find_cmd(char *name) * * DESCRIPTION * An internal function to scan the current directory for the * specified entry. * * INPUT PARAMETERS * name pointer to the string to look for (null terminated). * * RETURN VALUE * NULL string NOT found * ptr Pointer to entry record if a match was found * */ static cli_record_t *cli_find_cmd (cli_internal_data_t* data, char *name) { cli_record_t *cmd_rec; //DEBUG_PRINTF("\nAttempting to Find \"%s\" in directory [%s]\n", // name, current_directory->name ); /* * check for global command search */ if (*name == '!') { DEBUG_PRINTF(data, "\nGlobal command search! \r\n"); name++; cmd_rec = data->list; while (cmd_rec != 0) { DEBUG_PRINTF(data, "\nglobal comparing \"%s\" with entry \"%s\"\r\n", name, cmd_rec->name); if (str_exact(cmd_rec->name, name, CLI_ENTRY_LEN)) { DEBUG_PRINTF(data, "\nGlobal match found for -%s- \r\n", name); return (cmd_rec); } cmd_rec = cmd_rec->cmd_list; } cliprintf(data, "\n*Unknown entry \"%s\"\r\n", name); return (0); } /* * now compare to existing command and directory entries */ cmd_rec = data->current_directory->link2subdir; while (cmd_rec != NULL) { DEBUG_PRINTF(data, "\ncomparing \"%s\" with entry \"%s\"\r\n", name, cmd_rec->name); if (str_exact(cmd_rec->name, name, CLI_ENTRY_LEN)) { DEBUG_PRINTF(data, "\nMatch found for -%s- \r\n", name); return (cmd_rec); } cmd_rec = cmd_rec->next_entry; } /* * check to see if the user wants to go back one directory */ if (str_exact(name, CLI_UP_ONE, 2)) { DEBUG_PRINTF(data, "\nGo up one dir level \r\n"); data->current_directory = data->current_directory->parent_dir; return (0); } /* * check to see if user wants to go to the root directory */ if (str_exact(name, CLI_ROOT_DIR, 1)) { DEBUG_PRINTF(data, "\nGo to root \r\n"); data->current_directory = &data->cli_root_element; return (0); } /* * check to see if user wants to list entries */ if (str_exact(name, CLI_LIST_DIR, 2)) { DEBUG_PRINTF(data, "\nList directory \r\n"); list_directory(data); return (0); } if (str_exact(name, CLI_GLOBAL_LIST, 2)) { DEBUG_PRINTF(data, "\nGlobal List \r\n"); global_command_list(data); return (0); } if (str_exact(name, CLI_H, 1) || str_exact(name, CLI_HELP, 4) || str_exact(name, CLI_QUESTION, 1)) { cli_help(data); return (NULL); } /* did not find a match */ cliprintf(data, "\n*Unknown entry \"%s\"\r\n", name); return (0); }
/** * Process 'merge' command. * * @return error code (0 - no error) */ static int process_merge (cli_state_t *cli_state_p, /**< cli state */ int argc, /**< number of arguments */ char *prog_name_p) /**< program name */ { jerry_init (JERRY_INIT_EMPTY); uint8_t *input_pos_p = input_buffer; cli_change_opts (cli_state_p, merge_opts); const uint32_t *merge_buffers[argc]; size_t merge_buffer_sizes[argc]; uint32_t number_of_files = 0; for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p)) { switch (id) { case OPT_MERGE_HELP: { cli_help (prog_name_p, "merge", merge_opts); return JERRY_STANDALONE_EXIT_CODE_OK; } case OPT_MERGE_OUT: { output_file_name_p = cli_consume_string (cli_state_p); break; } case CLI_OPT_DEFAULT: { const char *file_name_p = cli_consume_string (cli_state_p); if (cli_state_p->error == NULL) { size_t size = read_file (input_pos_p, file_name_p); if (size == 0) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } merge_buffers[number_of_files] = (const uint32_t *) input_pos_p; merge_buffer_sizes[number_of_files] = size; number_of_files++; const uintptr_t mask = sizeof (uint32_t) - 1; input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask); } break; } default: { cli_state_p->error = "Internal error"; break; } } } if (check_cli_error (cli_state_p)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (number_of_files < 2) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least two input files must be passed.\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } const char *error_p; size_t size = jerry_merge_snapshots (merge_buffers, merge_buffer_sizes, number_of_files, output_buffer, JERRY_BUFFER_SIZE, &error_p); if (size == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p); return JERRY_STANDALONE_EXIT_CODE_FAIL; } FILE *file_p = fopen (output_file_name_p, "w"); if (file_p != NULL) { fwrite (output_buffer, 1u, size, file_p); fclose (file_p); } else { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", output_file_name_p); } return JERRY_STANDALONE_EXIT_CODE_OK; } /* process_merge */
/** * Process 'generate' command. * * @return error code (0 - no error) */ static int process_generate (cli_state_t *cli_state_p, /**< cli state */ int argc, /**< number of arguments */ char *prog_name_p) /**< program name */ { (void) argc; bool is_save_literals_mode_in_c_format = false; uint32_t snapshot_flags = 0; jerry_init_flag_t flags = JERRY_INIT_EMPTY; const char *file_name_p = NULL; uint8_t *source_p = input_buffer; size_t source_length = 0; const char *save_literals_file_name_p = NULL; cli_change_opts (cli_state_p, generate_opts); for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p)) { switch (id) { case OPT_GENERATE_HELP: { cli_help (prog_name_p, "generate", generate_opts); return JERRY_STANDALONE_EXIT_CODE_OK; } case OPT_GENERATE_STATIC: { snapshot_flags |= JERRY_SNAPSHOT_SAVE_STATIC; break; } case OPT_GENERATE_LITERAL_LIST: case OPT_GENERATE_LITERAL_C: { if (save_literals_file_name_p != NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C); save_literals_file_name_p = cli_consume_string (cli_state_p); break; } case OPT_GENERATE_SHOW_OP: { if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg)) { jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); flags |= JERRY_INIT_SHOW_OPCODES; } break; } case OPT_GENERATE_OUT: { output_file_name_p = cli_consume_string (cli_state_p); break; } case CLI_OPT_DEFAULT: { if (file_name_p != NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } file_name_p = cli_consume_string (cli_state_p); if (cli_state_p->error == NULL) { source_length = read_file (source_p, file_name_p); if (source_length == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } } break; } default: { cli_state_p->error = "Internal error"; break; } } } if (check_cli_error (cli_state_p)) { return JERRY_STANDALONE_EXIT_CODE_FAIL; } if (file_name_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_init (flags); if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_length)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } jerry_value_t snapshot_result; snapshot_result = jerry_generate_snapshot ((jerry_char_t *) file_name_p, (size_t) strlen (file_name_p), (jerry_char_t *) source_p, source_length, snapshot_flags, output_buffer, sizeof (output_buffer) / sizeof (uint32_t)); if (jerry_value_has_error_flag (snapshot_result)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n"); jerry_value_clear_error_flag (&snapshot_result); print_unhandled_exception (snapshot_result); jerry_release_value (snapshot_result); return JERRY_STANDALONE_EXIT_CODE_FAIL; } size_t snapshot_size = (size_t) jerry_get_number_value (snapshot_result); jerry_release_value (snapshot_result); FILE *snapshot_file_p = fopen (output_file_name_p, "w"); if (snapshot_file_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p); return JERRY_STANDALONE_EXIT_CODE_FAIL; } fwrite (output_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p); fclose (snapshot_file_p); printf ("Created snapshot file: '%s' (%lu bytes)\n", output_file_name_p, (unsigned long) snapshot_size); if (save_literals_file_name_p != NULL) { const size_t literal_buffer_size = jerry_parse_and_save_literals ((jerry_char_t *) source_p, source_length, false, output_buffer, sizeof (output_buffer) / sizeof (uint32_t), is_save_literals_mode_in_c_format); if (literal_buffer_size == 0) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Literal saving failed!\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } FILE *literal_file_p = fopen (save_literals_file_name_p, "w"); if (literal_file_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write literal file: '%s'\n", save_literals_file_name_p); return JERRY_STANDALONE_EXIT_CODE_FAIL; } fwrite (output_buffer, sizeof (uint8_t), literal_buffer_size, literal_file_p); fclose (literal_file_p); printf ("Created literal file: '%s' (%lu bytes)\n", save_literals_file_name_p, (unsigned long) literal_buffer_size); } return 0; } /* process_generate */