Don't crash parsing file list
This commit is contained in:
parent
d9ef2046dd
commit
5a639af9d9
@ -35,36 +35,40 @@
|
|||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct MeditOpts {
|
struct MeditOpts
|
||||||
int use_session;
|
{
|
||||||
int pid;
|
int use_session = -1;
|
||||||
gboolean new_app;
|
int pid = -1;
|
||||||
const char *instance_name;
|
gboolean new_app = false;
|
||||||
gboolean new_window;
|
const char *instance_name = nullptr;
|
||||||
gboolean new_tab;
|
gboolean new_window = false;
|
||||||
gboolean reload;
|
gboolean new_tab = false;
|
||||||
const char *project;
|
gboolean reload = false;
|
||||||
gboolean project_mode;
|
const char *project = nullptr;
|
||||||
int line;
|
gboolean project_mode = false;
|
||||||
const char *encoding;
|
int line = 0;
|
||||||
const char *log_file;
|
const char *encoding = nullptr;
|
||||||
gboolean log_window;
|
const char *log_file = nullptr;
|
||||||
const char *exec_string;
|
gboolean log_window = false;
|
||||||
const char *exec_file;
|
const char *exec_string = nullptr;
|
||||||
std::vector<gstr> files;
|
const char *exec_file = nullptr;
|
||||||
const char *geometry;
|
gstrvec files;
|
||||||
gboolean show_version;
|
char **filesp = nullptr;
|
||||||
const char *debug;
|
const char *geometry = nullptr;
|
||||||
gboolean ut;
|
gboolean show_version = false;
|
||||||
gboolean ut_uninstalled;
|
const char *debug = nullptr;
|
||||||
gboolean ut_list;
|
gboolean ut = false;
|
||||||
char *ut_dir;
|
gboolean ut_uninstalled = false;
|
||||||
char *ut_coverage_file;
|
gboolean ut_list = false;
|
||||||
std::vector<gstr> ut_tests;
|
char *ut_dir = nullptr;
|
||||||
char **run_script;
|
char *ut_coverage_file = nullptr;
|
||||||
char **send_script;
|
gstrvec ut_tests;
|
||||||
gboolean portable;
|
char **run_script = nullptr;
|
||||||
} medit_opts = { -1, -1 };
|
char **send_script = nullptr;
|
||||||
|
gboolean portable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static MeditOpts medit_opts;
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
|
||||||
@ -114,81 +118,20 @@ parse_use_session (const char *option_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GOptionEntry medit_options[] = {
|
|
||||||
{ "new-app", 'n', 0, G_OPTION_ARG_NONE, &medit_opts.new_app,
|
|
||||||
/* help message for command line option --new-app */ N_("Run new instance of application"), NULL },
|
|
||||||
{ "use-session", 's', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, (void*) parse_use_session,
|
|
||||||
/* help message for command line option --use-session */ N_("Load and save session"), "yes|no" },
|
|
||||||
{ "pid", 0, 0, G_OPTION_ARG_INT, &medit_opts.pid,
|
|
||||||
/* help message for command line option --pid=PID */ N_("Use existing instance with process id PID"),
|
|
||||||
/* "PID" part in "--pid=PID" */ N_("PID") },
|
|
||||||
{ "app-name", 0, 0, G_OPTION_ARG_STRING, (gpointer) &medit_opts.instance_name,
|
|
||||||
/* help message for command line option --app-name=NAME */ N_("Set instance name to NAME if it's not already running"),
|
|
||||||
/* "NAME" part in "--app-name=NAME" */ N_("NAME") },
|
|
||||||
{ "new-window", 'w', 0, G_OPTION_ARG_NONE, &medit_opts.new_window,
|
|
||||||
/* help message for command line option --new-window */ N_("Open file(s) in a new window"), NULL },
|
|
||||||
{ "new-tab", 't', 0, G_OPTION_ARG_NONE, &medit_opts.new_tab,
|
|
||||||
/* help message for command line option --new-tab */ N_("Open file(s) in a new tab"), NULL },
|
|
||||||
{ "project", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, (gpointer) &medit_opts.project,
|
|
||||||
"Open project file FILE", "FILE" },
|
|
||||||
{ "project-mode", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.project_mode,
|
|
||||||
"IDE mode", NULL },
|
|
||||||
{ "line", 'l', 0, G_OPTION_ARG_INT, &medit_opts.line,
|
|
||||||
/* help message for command line option --line=LINE */ N_("Open file and position cursor on line LINE"),
|
|
||||||
/* "LINE" part in --line=LINE */ N_("LINE") },
|
|
||||||
{ "encoding", 'e', 0, G_OPTION_ARG_STRING, (gpointer) &medit_opts.encoding,
|
|
||||||
/* help message for command line option --encoding=ENCODING */ N_("Use character encoding ENCODING"),
|
|
||||||
/* "ENCODING" part in --encoding=ENCODING */ N_("ENCODING") },
|
|
||||||
{ "reload", 'r', 0, G_OPTION_ARG_NONE, &medit_opts.reload,
|
|
||||||
/* help message for command line option --reload */ N_("Automatically reload file if it was modified on disk"), NULL },
|
|
||||||
{ "run-script", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, (gpointer) &medit_opts.run_script,
|
|
||||||
"Run SCRIPT", "SCRIPT" },
|
|
||||||
{ "send-script", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, (gpointer) &medit_opts.send_script,
|
|
||||||
"Send SCRIPT to existing instance", "SCRIPT" },
|
|
||||||
{ "log-window", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.log_window,
|
|
||||||
"Show debug output", NULL },
|
|
||||||
{ "log-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, (gpointer) &medit_opts.log_file,
|
|
||||||
"Write debug output to FILE", "FILE" },
|
|
||||||
{ "debug", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, (gpointer) &medit_opts.debug,
|
|
||||||
"Run in debug mode", NULL },
|
|
||||||
{ "geometry", 0, 0, G_OPTION_ARG_STRING, (gpointer) &medit_opts.geometry,
|
|
||||||
/* help message for command line option --geometry=WIDTHxHEIGHT[+X+Y] */ N_("Default window size and position"),
|
|
||||||
/* "WIDTHxHEIGHT[+X+Y]" part in --geometry=WIDTHxHEIGHT[+X+Y] */ N_("WIDTHxHEIGHT[+X+Y]") },
|
|
||||||
{ "version", 0, 0, G_OPTION_ARG_NONE, &medit_opts.show_version,
|
|
||||||
/* help message for command line option --version */ N_("Show version information and exit"), NULL },
|
|
||||||
{ "ut", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.ut,
|
|
||||||
"Run unit tests", NULL },
|
|
||||||
{ "ut-uninstalled", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.ut_uninstalled,
|
|
||||||
"Run unit tests in uninstalled medit", NULL },
|
|
||||||
{ "ut-dir", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &medit_opts.ut_dir,
|
|
||||||
"Data dir for unit tests", NULL },
|
|
||||||
{ "ut-coverage", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &medit_opts.ut_coverage_file,
|
|
||||||
"File to write coverage data to", NULL },
|
|
||||||
{ "ut-list", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.ut_list,
|
|
||||||
"List unit tests", NULL },
|
|
||||||
#ifdef __WIN32__
|
|
||||||
{ "portable", 0, G_OPTION_ARG_NONE, G_OPTION_ARG_NONE, &medit_opts.portable,
|
|
||||||
"Run medit in portable mode", NULL },
|
|
||||||
#endif
|
|
||||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &medit_opts.files,
|
|
||||||
NULL, /* "FILES" part in "medit [OPTION...] [FILES]" */ N_("FILES") },
|
|
||||||
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Check if there is an argument of the form +<number>, and treat it as --line <number> */
|
/* Check if there is an argument of the form +<number>, and treat it as --line <number> */
|
||||||
static void
|
static void
|
||||||
check_plus_line_arg (void)
|
check_plus_line_arg (void)
|
||||||
{
|
{
|
||||||
std::shared_ptr<g::Regex> re = g::Regex::compile("^\\+(?P<line>\\d+)", g::Regex::OPTIMIZE | g::Regex::DUPNAMES);
|
g::Regex re = g::Regex::compile("^\\+(?P<line>\\d+)", g::Regex::OPTIMIZE | g::Regex::DUPNAMES);
|
||||||
g_return_if_fail (re != nullptr);
|
g_return_if_fail(re.is_valid());
|
||||||
|
|
||||||
for (size_t i = 0; i < medit_opts.files.size(); ++i)
|
for (size_t i = 0; i < medit_opts.files.size(); ++i)
|
||||||
{
|
{
|
||||||
const gstr& file = medit_opts.files[i];
|
const gstr& file = medit_opts.files[i];
|
||||||
if (std::unique_ptr<g::MatchInfo> match_info = re->match(file))
|
if (g::MatchInfo match_info = re.match(file))
|
||||||
{
|
{
|
||||||
int line = 0;
|
int line = 0;
|
||||||
gstr line_string = match_info->fetch_named("line");
|
gstr line_string = match_info.fetch_named("line");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
line = strtol(line_string.get(), NULL, 10);
|
line = strtol(line_string.get(), NULL, 10);
|
||||||
@ -212,6 +155,9 @@ check_plus_line_arg (void)
|
|||||||
static gboolean
|
static gboolean
|
||||||
post_parse_func (void)
|
post_parse_func (void)
|
||||||
{
|
{
|
||||||
|
medit_opts.files = gstr::take(medit_opts.filesp);
|
||||||
|
medit_opts.filesp = nullptr;
|
||||||
|
|
||||||
if (medit_opts.show_version)
|
if (medit_opts.show_version)
|
||||||
{
|
{
|
||||||
g_print ("medit " MOO_DISPLAY_VERSION "\n");
|
g_print ("medit " MOO_DISPLAY_VERSION "\n");
|
||||||
@ -251,7 +197,68 @@ parse_args (int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
GOptionContext *ctx;
|
GOptionContext *ctx;
|
||||||
GOptionGroup *grp;
|
GOptionGroup *grp;
|
||||||
GError *error = NULL;
|
GError *error = nullptr;
|
||||||
|
|
||||||
|
GOptionEntry medit_options[] = {
|
||||||
|
{ "new-app", 'n', 0, G_OPTION_ARG_NONE, &medit_opts.new_app,
|
||||||
|
/* help message for command line option --new-app */ N_("Run new instance of application"), NULL },
|
||||||
|
{ "use-session", 's', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, (void*) parse_use_session,
|
||||||
|
/* help message for command line option --use-session */ N_("Load and save session"), "yes|no" },
|
||||||
|
{ "pid", 0, 0, G_OPTION_ARG_INT, &medit_opts.pid,
|
||||||
|
/* help message for command line option --pid=PID */ N_("Use existing instance with process id PID"),
|
||||||
|
/* "PID" part in "--pid=PID" */ N_("PID") },
|
||||||
|
{ "app-name", 0, 0, G_OPTION_ARG_STRING, (gpointer) &medit_opts.instance_name,
|
||||||
|
/* help message for command line option --app-name=NAME */ N_("Set instance name to NAME if it's not already running"),
|
||||||
|
/* "NAME" part in "--app-name=NAME" */ N_("NAME") },
|
||||||
|
{ "new-window", 'w', 0, G_OPTION_ARG_NONE, &medit_opts.new_window,
|
||||||
|
/* help message for command line option --new-window */ N_("Open file(s) in a new window"), NULL },
|
||||||
|
{ "new-tab", 't', 0, G_OPTION_ARG_NONE, &medit_opts.new_tab,
|
||||||
|
/* help message for command line option --new-tab */ N_("Open file(s) in a new tab"), NULL },
|
||||||
|
{ "project", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, (gpointer) &medit_opts.project,
|
||||||
|
"Open project file FILE", "FILE" },
|
||||||
|
{ "project-mode", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.project_mode,
|
||||||
|
"IDE mode", NULL },
|
||||||
|
{ "line", 'l', 0, G_OPTION_ARG_INT, &medit_opts.line,
|
||||||
|
/* help message for command line option --line=LINE */ N_("Open file and position cursor on line LINE"),
|
||||||
|
/* "LINE" part in --line=LINE */ N_("LINE") },
|
||||||
|
{ "encoding", 'e', 0, G_OPTION_ARG_STRING, (gpointer) &medit_opts.encoding,
|
||||||
|
/* help message for command line option --encoding=ENCODING */ N_("Use character encoding ENCODING"),
|
||||||
|
/* "ENCODING" part in --encoding=ENCODING */ N_("ENCODING") },
|
||||||
|
{ "reload", 'r', 0, G_OPTION_ARG_NONE, &medit_opts.reload,
|
||||||
|
/* help message for command line option --reload */ N_("Automatically reload file if it was modified on disk"), NULL },
|
||||||
|
{ "run-script", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, (gpointer) &medit_opts.run_script,
|
||||||
|
"Run SCRIPT", "SCRIPT" },
|
||||||
|
{ "send-script", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, (gpointer) &medit_opts.send_script,
|
||||||
|
"Send SCRIPT to existing instance", "SCRIPT" },
|
||||||
|
{ "log-window", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.log_window,
|
||||||
|
"Show debug output", NULL },
|
||||||
|
{ "log-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, (gpointer) &medit_opts.log_file,
|
||||||
|
"Write debug output to FILE", "FILE" },
|
||||||
|
{ "debug", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, (gpointer) &medit_opts.debug,
|
||||||
|
"Run in debug mode", NULL },
|
||||||
|
{ "geometry", 0, 0, G_OPTION_ARG_STRING, (gpointer) &medit_opts.geometry,
|
||||||
|
/* help message for command line option --geometry=WIDTHxHEIGHT[+X+Y] */ N_("Default window size and position"),
|
||||||
|
/* "WIDTHxHEIGHT[+X+Y]" part in --geometry=WIDTHxHEIGHT[+X+Y] */ N_("WIDTHxHEIGHT[+X+Y]") },
|
||||||
|
{ "version", 0, 0, G_OPTION_ARG_NONE, &medit_opts.show_version,
|
||||||
|
/* help message for command line option --version */ N_("Show version information and exit"), NULL },
|
||||||
|
{ "ut", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.ut,
|
||||||
|
"Run unit tests", NULL },
|
||||||
|
{ "ut-uninstalled", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.ut_uninstalled,
|
||||||
|
"Run unit tests in uninstalled medit", NULL },
|
||||||
|
{ "ut-dir", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &medit_opts.ut_dir,
|
||||||
|
"Data dir for unit tests", NULL },
|
||||||
|
{ "ut-coverage", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &medit_opts.ut_coverage_file,
|
||||||
|
"File to write coverage data to", NULL },
|
||||||
|
{ "ut-list", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &medit_opts.ut_list,
|
||||||
|
"List unit tests", NULL },
|
||||||
|
#ifdef __WIN32__
|
||||||
|
{ "portable", 0, G_OPTION_ARG_NONE, G_OPTION_ARG_NONE, &medit_opts.portable,
|
||||||
|
"Run medit in portable mode", NULL },
|
||||||
|
#endif
|
||||||
|
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &medit_opts.filesp,
|
||||||
|
NULL, /* "FILES" part in "medit [OPTION...] [FILES]" */ N_("FILES") },
|
||||||
|
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
grp = g_option_group_new ("medit", "medit", "medit", NULL, NULL);
|
grp = g_option_group_new ("medit", "medit", "medit", NULL, NULL);
|
||||||
g_option_group_add_entries (grp, medit_options);
|
g_option_group_add_entries (grp, medit_options);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user