diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | bootstrap.am | 1 | ||||
-rwxr-xr-x | doc/grosciteco.tes | 2 | ||||
-rwxr-xr-x | doc/htbl.tes | 2 | ||||
-rw-r--r-- | doc/sciteco.1.in | 42 | ||||
-rw-r--r-- | src/Makefile.am | 21 | ||||
-rw-r--r-- | src/interface-curses/interface-curses.cpp | 10 | ||||
-rw-r--r-- | src/interface-curses/interface-curses.h | 4 | ||||
-rw-r--r-- | src/interface-gtk/interface-gtk.cpp | 10 | ||||
-rw-r--r-- | src/interface-gtk/interface-gtk.h | 4 | ||||
-rw-r--r-- | src/interface.h | 7 | ||||
-rw-r--r-- | src/main.cpp | 92 | ||||
-rwxr-xr-x | src/symbols-extract.tes | 2 |
13 files changed, 149 insertions, 49 deletions
@@ -31,6 +31,7 @@ testsuite.dir # Binaries /src/sciteco /src/sciteco-minimal +/src/sciteco-wrapper # Generated source files /src/interface-gtk/gtk-info-popup.[ch] diff --git a/bootstrap.am b/bootstrap.am index 7ff35d3..bc6f721 100644 --- a/bootstrap.am +++ b/bootstrap.am @@ -25,6 +25,7 @@ SUBST_MACRO = eb$<\e \ <fs@PACKAGE_URL^Q@\e@PACKAGE_URL@\e;>j \ <fs@PACKAGE_URL_DEV^Q@\e@PACKAGE_URL_DEV@\e;>j \ <fs@bindir^Q@\e$(bindir)\e;>j \ + <fs@libexecdir^Q@\e$(libexecdir)\e;>j \ <fs@pkgdatadir^Q@\e$(pkgdatadir)\e;>j \ <fs@scitecolibdir^Q@\e$(scitecolibdir)\e;>j \ <fs@TECO_INTEGER^Q@\e@TECO_INTEGER@\e;>j \ diff --git a/doc/grosciteco.tes b/doc/grosciteco.tes index d84c6ab..7be01fb 100755 --- a/doc/grosciteco.tes +++ b/doc/grosciteco.tes @@ -1,4 +1,4 @@ -#!/usr/bin/env sciteco -m +#!/usr/local/bin/sciteco -m !* grosciteco.tes <output-woman> <output-tec> <input> *! !* Process command-line options *! diff --git a/doc/htbl.tes b/doc/htbl.tes index 4118e55..fced7e7 100755 --- a/doc/htbl.tes +++ b/doc/htbl.tes @@ -1,4 +1,4 @@ -#!/usr/bin/env sciteco -m +#!/usr/local/bin/sciteco -m !* htbl.tes <input> <output> *! !* Troff tbl "drop-in" replacement *! diff --git a/doc/sciteco.1.in b/doc/sciteco.1.in index e6c4d8a..ed3892f 100644 --- a/doc/sciteco.1.in +++ b/doc/sciteco.1.in @@ -17,10 +17,11 @@ Scintilla-based \fBT\fPext \fBE\fPditor and \fBCO\fPrrector .SY @PACKAGE@ .OP "-h|--help" .OP "-e|--eval" macro -.OP "-m|--mung" file +.OP "-m|--mung" .OP "--no-profile" .RI [ "UI option .\|.\|." ] .OP "--" +.RI [ script ] .RI [ "argument .\|.\|." ] .YS . @@ -40,26 +41,46 @@ natively supports Microsoft Windows NT\*(Tm. .LP .SCITECO_TOPIC mung When executed, \*(ST mungs (executes) the TECO macro stored in the file -specified by the +specified in the \fIscript\fP argument if .B "--mung" -option or the macro specified via +is given or the macro specified via .B "--eval" respectively. Munged files and macros are executed in non-interactive (\fIbatch\fP) mode, allowing the user to write stand-alone TECO scripts. Only when munging files as opposed to other means of executing macros, -the first line is ignored if it begins with \(lq#!\(rq. +the first line is ignored if it begins with a \(lq#\(rq (hash sign). Therefore under UNIX-like operating systems, TECO macro files may be invoked as scripts by using a Hash-Bang line like .\" FIXME: We'd like to include #! as a topic, but ! character are currently .\" not allowed since they are not escaped correctly. .SCITECO_TOPIC scripting .RS -.SCITECO_TT .EX +.SCITECO_TT #!@bindir@/sciteco -m +.SCITECO_TT_END .EE +.RE +. +.LP +Note that UNIX Hash-Bang lines will only pass a \fBsingle\fP argument to the +interpreter before the script's file name, so all required \*(ST options must +be mangled into a single argument with their single-letter names. +Passing option-like arguments (beginning with a dash) to scripts may cause +problems because \*(ST might try to interpret these options. +Beginning with Glib 2.44, \*(ST thus stops parsing at the first non-option +argument (which will always be the munged file name in a script invocation). +For binaries linked against older versions of Glib, \*(ST works around this +issue by providing a wrapper script that can be used in place of the main +executable. +A portable Hash-Bang line should thus look like: +.RS +.EX +.SCITECO_TT +#!@libexecdir@/sciteco-wrapper -m .SCITECO_TT_END +.EE .RE . .LP @@ -69,6 +90,8 @@ All command line arguments after the \*(ST options are passed as .I arguments to the munged macro by placing each argument on its own line in the buffer. +The \fIscript\fP file name expected when \(lq--mung\(rq is given +is currently \fBnot\fP considered a macro argument. In any case the current buffer position (called .IR dot ) is left at the beginning of the buffer. @@ -137,6 +160,8 @@ option is absent, \*(ST will mung On UNIX/Linux, the default profile is at .I ~/.teco_ini (see \fBENVIRONMENT\fP). +It will consequently not expect a \fIscript\fP file name as +the first non-option argument. The profile will usually set up various Scintilla and \*(ST options, configure syntax highlighting, define commonly used macros and open files specified as arguments to \*(ST. @@ -160,9 +185,12 @@ Similar to munging but always exits afterwards. If the option is specified, the .B \-\-mung option has no effect. -.IP "\fB-m\fR, \fB--mung\fR \fIfile" +.IP "\fB-m\fR, \fB--mung\fR" .SCITECO_TOPIC "-m" "--mung" -Mung \fIfile\fP. +Mung \fIscript\fP. +The script file name is expected as the first non-option +argument, so it does not necessarily have to follow the +\fB--mung\fP option. Default is .IR $SCITECOCONFIG/.teco_ini . .IP "\fB--no-profile\fP" diff --git a/src/Makefile.am b/src/Makefile.am index 314faa4..72e9157 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,10 +76,27 @@ CLEANFILES = $(BUILT_SOURCES) \ symbols-scintilla.cpp : @SCINTILLA_PATH@/include/Scintilla.h \ symbols-extract.tes - $(SCITECO_MINIMAL) -m @srcdir@/symbols-extract.tes \ + $(SCITECO_MINIMAL) -m -- @srcdir@/symbols-extract.tes \ $< $@ "SCI_" scintilla symbols-scilexer.cpp : @SCINTILLA_PATH@/include/SciLexer.h \ symbols-extract.tes - $(SCITECO_MINIMAL) -m @srcdir@/symbols-extract.tes \ + $(SCITECO_MINIMAL) -m -- @srcdir@/symbols-extract.tes \ $< $@ "SCLEX_,SCE_" scilexer + +# This installs a wrapper script to libexecdir to be used as +# the SciTECO interpreter in Hash-Bang lines. +# It makes sure that option parsing is disabled for all +# script arguments which is necessary for builds against Glib < 2.44. +# NOTE: When we raise the Glib requirement to 2.44, the sciteco-wrapper +# workaround can be removed completely. +libexec_SCRIPTS = sciteco-wrapper +CLEANFILES += $(libexec_SCRIPTS) + +.PHONY: sciteco-wrapper +sciteco-wrapper: + echo '#!/bin/sh' >$@ + echo 'OPT=$$1;' \ + 'shift;' \ + "exec $(bindir)/`echo sciteco | @SED@ '$(transform)'`$(EXEEXT)" \ + '"$$OPT" -- $$@' >>$@ diff --git a/src/interface-curses/interface-curses.cpp b/src/interface-curses/interface-curses.cpp index d592b89..5e5b8d8 100644 --- a/src/interface-curses/interface-curses.cpp +++ b/src/interface-curses/interface-curses.cpp @@ -312,7 +312,7 @@ InterfaceCurses::InterfaceCurses() : stdout_orig(-1), stderr_orig(-1), } void -InterfaceCurses::main_impl(int &argc, char **&argv) +InterfaceCurses::init(void) { /* * We must register this handler to handle @@ -518,12 +518,16 @@ InterfaceCurses::init_screen(void) * This sets the program name to "SciTECO" * which may then also be used as the X11 class name * for overwriting X11 resources in .Xdefaults + * * FIXME: We could support passing in resource * overrides via the SciTECO command line. * But unfortunately, Xinitscr() is called too - * late to modify argc/argv for command-line parsing. + * late to modify argc/argv for command-line parsing + * (and GOption needs to know about the additional + * possible arguments since they are not passed through + * transparently). * Therefore this could only be supported by - * adding a special option like --resource. + * adding a special option like --resource KEY=VAL. */ Xinitscr(1, (char **)argv); } diff --git a/src/interface-curses/interface-curses.h b/src/interface-curses/interface-curses.h index d036d37..a0198cc 100644 --- a/src/interface-curses/interface-curses.h +++ b/src/interface-curses/interface-curses.h @@ -121,8 +121,8 @@ public: InterfaceCurses(); ~InterfaceCurses(); - /* implementation of Interface::main() */ - void main_impl(int &argc, char **&argv); + /* override of Interface::init() */ + void init(void); /* override of Interface::init_color() */ void init_color(guint color, guint32 rgb); diff --git a/src/interface-gtk/interface-gtk.cpp b/src/interface-gtk/interface-gtk.cpp index 4ef0b38..920f01b 100644 --- a/src/interface-gtk/interface-gtk.cpp +++ b/src/interface-gtk/interface-gtk.cpp @@ -183,7 +183,12 @@ InterfaceGtk::get_options(void) {NULL} }; - GOptionGroup *group = gtk_get_option_group(TRUE); + /* + * Parsing the option context with the Gtk option group + * will automatically initialize Gtk, so gtk_init() + * does not have to be called. + */ + GOptionGroup *group = gtk_get_option_group(FALSE); g_option_group_add_entries(group, entries); @@ -191,7 +196,7 @@ InterfaceGtk::get_options(void) } void -InterfaceGtk::main_impl(int &argc, char **&argv) +InterfaceGtk::init(void) { static const Cmdline empty_cmdline; @@ -208,7 +213,6 @@ InterfaceGtk::main_impl(int &argc, char **&argv) g_thread_init(NULL); #endif gdk_threads_init(); - gtk_init(&argc, &argv); /* * Register clipboard registers. diff --git a/src/interface-gtk/interface-gtk.h b/src/interface-gtk/interface-gtk.h index 0145ff4..a19d253 100644 --- a/src/interface-gtk/interface-gtk.h +++ b/src/interface-gtk/interface-gtk.h @@ -113,8 +113,8 @@ public: /* overrides Interface::get_options() */ GOptionGroup *get_options(void); - /* implementation of Interface::main() */ - void main_impl(int &argc, char **&argv); + /* override of Interface::init() */ + void init(void); /* implementation of Interface::vmsg() */ void vmsg_impl(MessageType type, const gchar *fmt, va_list ap); diff --git a/src/interface.h b/src/interface.h index 98254ac..e841680 100644 --- a/src/interface.h +++ b/src/interface.h @@ -194,11 +194,8 @@ public: return NULL; } - inline void - main(int &argc, char **&argv) - { - impl().main_impl(argc, argv); - } + /* default implementation */ + inline void init(void) {} /* makes sense only on Curses */ inline void init_color(guint color, guint32 rgb) {} diff --git a/src/main.cpp b/src/main.cpp index d14e2e5..e9be929 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -75,7 +75,7 @@ namespace Flags { } static gchar *eval_macro = NULL; -static gchar *mung_file = NULL; +static gboolean mung_file = FALSE; static gboolean mung_profile = TRUE; sig_atomic_t sigint_occurred = FALSE; @@ -165,29 +165,31 @@ get_default_config_path(const gchar *program) #endif -static inline void +static inline gchar * process_options(int &argc, char **&argv) { static const GOptionEntry option_entries[] = { {"eval", 'e', 0, G_OPTION_ARG_STRING, &eval_macro, "Evaluate macro", "macro"}, - {"mung", 'm', 0, G_OPTION_ARG_FILENAME, &mung_file, - "Mung file instead of " - "$SCITECOCONFIG" G_DIR_SEPARATOR_S INI_FILE, "file"}, + {"mung", 'm', 0, G_OPTION_ARG_NONE, &mung_file, + "Mung script file (first non-option argument) instead of " + "$SCITECOCONFIG" G_DIR_SEPARATOR_S INI_FILE}, {"no-profile", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &mung_profile, "Do not mung " - "$SCITECOCONFIG" G_DIR_SEPARATOR_S INI_FILE - " even if it exists"}, + "$SCITECOCONFIG" G_DIR_SEPARATOR_S INI_FILE " " + "even if it exists"}, {NULL} }; + gchar *mung_filename = NULL; + GError *gerror = NULL; GOptionContext *options; GOptionGroup *interface_group = interface.get_options(); - options = g_option_context_new("[--] [ARGUMENT...]"); + options = g_option_context_new("[--] [SCRIPT] [ARGUMENT...]"); g_option_context_set_summary( options, @@ -203,6 +205,21 @@ process_options(int &argc, char **&argv) if (interface_group) g_option_context_add_group(options, interface_group); +#if GLIB_CHECK_VERSION(2,44,0) + /* + * If possible we parse in POSIX mode, which means that + * the first non-option argument terminates option parsing. + * SciTECO considers all non-option arguments to be script + * arguments and it makes little sense to mix script arguments + * with SciTECO options, so this lets the user avoid "--" + * in many situations. + * It is also strictly required to make hash-bang lines like + * #!/usr/bin/sciteco -m + * work (see sciteco(1)). + */ + g_option_context_set_strict_posix(options, TRUE); +#endif + if (!g_option_context_parse(options, &argc, &argv, &gerror)) { g_fprintf(stderr, "Option parsing failed: %s\n", gerror->message); @@ -212,15 +229,41 @@ process_options(int &argc, char **&argv) g_option_context_free(options); + /* + * GOption will NOT remove "--" if followed by an + * option-argument, which may interfer with scripts + * doing their own option handling and interpreting "--". + * + * NOTE: This is still true if we're parsing in GNU-mode + * and "--" is not the first non-option argument as in + * sciteco foo -- -C bar. + */ + if (argc >= 2 && !strcmp(argv[1], "--")) { + argv[1] = argv[0]; + argv++; + argc--; + } + if (mung_file) { - if (!g_file_test(mung_file, G_FILE_TEST_IS_REGULAR)) { + if (argc < 2) { + g_fprintf(stderr, "Script to mung expected!\n"); + exit(EXIT_FAILURE); + } + + if (!g_file_test(argv[1], G_FILE_TEST_IS_REGULAR)) { g_fprintf(stderr, "Cannot mung \"%s\". File does not exist!\n", - mung_file); + argv[1]); exit(EXIT_FAILURE); } + + mung_filename = g_strdup(argv[1]); + + argv[1] = argv[0]; + argv++; + argc--; } - /* remaining arguments, are arguments to the interface */ + return mung_filename; } static inline void @@ -369,6 +412,8 @@ main(int argc, char **argv) realloc /* try_realloc */ }; + gchar *mung_filename; + #ifdef DEBUG_PAUSE /* Windows debugging hack (see above) */ system("pause"); @@ -379,9 +424,12 @@ main(int argc, char **argv) g_mem_set_vtable(&vtable); - process_options(argc, argv); - interface.main(argc, argv); - /* remaining arguments are arguments to the munged file */ + mung_filename = process_options(argc, argv); + /* + * All remaining arguments in argv are arguments + * to the macro or munged file. + */ + interface.init(); /* * QRegister view must be initialized only now @@ -405,7 +453,7 @@ main(int argc, char **argv) ring.edit((const gchar *)NULL); /* add remaining arguments to unnamed buffer */ - for (int i = 1; i < argc; i++) { + for (gint i = 1; i < argc; i++) { /* * FIXME: arguments may contain line-feeds. * Once SciTECO is 8-byte clear, we can add the @@ -435,15 +483,15 @@ main(int argc, char **argv) exit(EXIT_SUCCESS); } - if (!mung_file && mung_profile) + if (!mung_filename && mung_profile) /* NOTE: Still safe to use g_getenv() */ - mung_file = g_build_filename(g_getenv("SCITECOCONFIG"), - INI_FILE, NIL); + mung_filename = g_build_filename(g_getenv("SCITECOCONFIG"), + INI_FILE, NIL); - if (mung_file && - g_file_test(mung_file, G_FILE_TEST_IS_REGULAR)) { + if (mung_filename && + g_file_test(mung_filename, G_FILE_TEST_IS_REGULAR)) { try { - Execute::file(mung_file, false); + Execute::file(mung_filename, false); } catch (Quit) { /* * ^C invoked, quit hook should still @@ -456,7 +504,6 @@ main(int argc, char **argv) exit(EXIT_SUCCESS); } } - g_free(mung_file); } catch (Error &error) { error.display_full(); exit(EXIT_FAILURE); @@ -495,5 +542,6 @@ main(int argc, char **argv) exit(EXIT_FAILURE); } + g_free(mung_filename); return 0; } diff --git a/src/symbols-extract.tes b/src/symbols-extract.tes index 2a6664c..e81331a 100755 --- a/src/symbols-extract.tes +++ b/src/symbols-extract.tes @@ -1,4 +1,4 @@ -#!./sciteco-minimal -m +#!/usr/local/bin/sciteco -m ! ./symbols-extract.tes <input file> <output file> <prefix pattern list> <array name> ! EMQ[$SCITECOPATH]/string.tes |