aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
AgeCommit message (Collapse)AuthorFilesLines
2021-06-08all SciTECO scripts used during the build process now always write files ↵Robin Haberkorn1-1/+1
with Unix linebreaks * when hosted on Windows, the default is DOS linebreaks * Unix linebreaks are in many cases more consistent as all other sources use Unix linebreaks * woman pages with Unix linebreaks are slightly faster to load due to EOL conversion * especially Groff input must not contain CR as it will otherwise log lots of warnings (affects htbl.tes and tedoc.tes).
2021-06-08get rid of the GObject Builder (GOB2): converted teco-gtk-info-popup.gob and ↵Robin Haberkorn9-716/+813
teco-gtk-label.gob to plain C * Using modern GObject idioms and macros greatly reduces the necessary boilerplate code. * The plain C versions of our GObject classes are now "final" (cannot be derived) This means we can hide the instance structures from the headers and avoid using explicit private fields. * Avoids some deprecation warnings when building the Gtk UI. * GOB2 is apparently no longer maintained, so this seems like a good idea in the long run. * The most important reason however is that there is no precompiled GOB2 for Windows which prevents compilation on native Windows hosts, eg. during nightly builds. This is even more important as Gtk+3 is distributed on Windows practically exclusively via MSYS. (ArchLinux contains MinGW gtk3 packages as well, so cross-compiling from ArchLinux would have been an alternative.)
2021-06-08try G_SPAWN_LEAVE_DESCRIPTORS_OPEN when spawning processes: promises an ↵Robin Haberkorn1-1/+6
"optimized" code-path on UNIX
2021-06-08added test suite cases for memory limiting and command executionRobin Haberkorn1-0/+5
* Turned out to be useful in debugging the "Memory limiting during spawning" test case on Windows. * Use UNIX shell emulation (0,128ED) in all test cases. Should be necessary in order to run the testsuite on Windows, but it is currently broken anyway. * avoid <EG> when preprocessing files - use GNU Make's $(shell) instead * Fixes builds on MinGW where there are still problems with <EC> and <EG> at least in the virtual build environment. * Results in a another automake warning about non-POSIX Make constructs. This is not critical since we depend on GNU Make anyway.
2021-06-08Windows: normalize $COMSPECRobin Haberkorn3-4/+18
* Environment variables are case insensitive on Windows while SciTECO variables are case sensitive. We must therefore make sure that we first unset any $COMSPEC or $ComSpec from the environment before resetting it, thereby fixing its case. * Fixes command execution via <EC> on systems where the variable was not called $ComSpec.
2021-06-05teco_memory_check() now checks for addition overflows and negative searches ↵Robin Haberkorn2-1/+18
(<S>) for multiplication overflows * Since the numbers come from "outside" (SciTECO scripts) this is easily possible, resulting either in missed checks or even memory corruption. * In particular, this fixes the "Searching with large counts" test case on 32-bit builds. Perhaps at least one CI build should be 32-bit?
2021-06-05don't add -rdynamic when not replacing mallocRobin Haberkorn1-1/+4
* this flag could negatively affect optimizations * fixes builds on MinGW
2021-06-05when not replacing malloc with dlmalloc (--disable-malloc-replacement), ↵Robin Haberkorn1-1/+3
don't build an empty libdlmalloc * on some platforms (eg. Darwin/mac OS) we cannot apparently build empty convenience libraries * instead, we use conditional subdirectories and a conditional library dependency
2021-06-05use memory polling (--disable-malloc-replacement) on Mac OS XRobin Haberkorn1-3/+11
* I could not get malloc replacement via dlmalloc to work. This does not work like on Linux by overwriting weak malloc() functions. It should theoretically be possible to overwrite the default malloc zone but I could not properly debug this since I can only build for Mac OS via CI. * memory polling seems to work though - test suite runs through and it includes memory limiting test cases.
2021-06-04guard against too low arguments to <S> by checking whether the memory limit ↵Robin Haberkorn5-14/+28
would be exceeded * Checking whether the allocation succeeded may not prevent exceeding the memory limit excessively. * Even if the memory limit is not exceeded, the allocation can fail theoretically and the program would terminate abnormally. This however is true for all allocations in SciTECO (via glib). * teco_memory_check() therefore now supports checking whether an allocation would exceed the memory limit which will be useful before very large or variable allocations in addition to the regular checking in teco_machine_main_step(). * As a sideeffect, this fixes the "Searching with large counts" test case on Mac OS where too large allocations were not detected as expected (apparently Mac OS happily gives out ridiculously large chunks of memory). Now, all platforms are guaranteed to have the same behaviour.
2021-06-02avoid aliased functions, as they are not supported on Darwin (macOS)Robin Haberkorn1-1/+5
NOTE: Aliases and weak symbols must not be used for portability reasons!
2021-06-02renamed scintilla.[ch] to symbols.[ch]: fixes builds on case-insensitive ↵Robin Haberkorn6-5/+5
file systems * There is a "Scintilla.h" as well. * should fix macOS and builds on native Windows hosts * It wasn't practical to refer to the Scintilla includes using paths since the Scintilla location is configurable (--with-scintilla). So we'd have to write something like #include <include/Scintilla.h>. For Scinterm we cannot avoid collisions neither as its path is also configurable (--with-scinterm). Effectively, we must prevent name clashes across SciTECO and all of Scintilla and Scinterm.
2021-05-30THE GREAT CEEIFICATION EVENTRobin Haberkorn93-21895/+18705
This is a total conversion of SciTECO to plain C (GNU C11). The chance was taken to improve a lot of internal datastructures, fix fundamental bugs and lay the foundations of future features. The GTK user interface is now in an useable state! All changes have been squashed together. The language itself has almost not changed at all, except for: * Detection of string terminators (usually Escape) now takes the string building characters into account. A string is only terminated outside of string building characters. In other words, you can now for instance write I^EQ[Hello$world]$ This removes one of the last bits of shellisms which is out of place in SciTECO where no tokenization/lexing is performed. Consequently, the current termination character can also be escaped using ^Q/^R. This is used by auto completions to make sure that strings are inserted verbatim and without unwanted sideeffects. * All strings can now safely contain null-characters (see also: 8-bit cleanliness). The null-character itself (^@) is not (yet) a valid SciTECO command, though. An incomplete list of changes: * We got rid of the BSD headers for RB trees and lists/queues. The problem with them was that they used a form of metaprogramming only to gain a bit of type safety. It also resulted in less readble code. This was a C++ desease. The new code avoids metaprogramming only to gain type safety. The BSD tree.h has been replaced by rb3ptr by Jens Stimpfle (https://github.com/jstimpfle/rb3ptr). This implementation is also more memory efficient than BSD's. The BSD list.h and queue.h has been replaced with a custom src/list.h. * Fixed crashes, performance issues and compatibility issues with the Gtk 3 User Interface. It is now more or less ready for general use. The GDK lock is no longer used to avoid using deprecated functions. On the downside, the new implementation (driving the Gtk event loop stepwise) is even slower than the old one. A few glitches remain (see TODO), but it is hoped that they will be resolved by the Scintilla update which will be performed soon. * A lot of program units have been split up, so they are shorter and easier to maintain: core-commands.c, qreg-commands.c, goto-commands.c, file-utils.h. * Parser states are simply structs of callbacks now. They still use a kind of polymorphy using a preprocessor trick. TECO_DEFINE_STATE() takes an initializer list that will be merged with the default list of field initializers. To "subclass" states, you can simply define new macros that add initializers to existing macros. * Parsers no longer have a "transitions" table but the input_cb() may use switch-case statements. There are also teco_machine_main_transition_t now which can be used to implement simple transitions. Additionally, you can specify functions to execute during transitions. This largely avoids long switch-case-statements. * Parsers are embeddable/reusable now, at least in parse-only mode. This does not currently bring any advantages but may later be used to write a Scintilla lexer for TECO syntax highlighting. Once parsers are fully embeddable, it will also be possible to run TECO macros in a kind of coroutine which would allow them to process string arguments in real time. * undo.[ch] still uses metaprogramming extensively but via the C preprocessor of course. On the downside, most undo token generators must be initiated explicitly (theoretically we could have used embedded functions / trampolines to instantiate automatically but this has turned out to be dangereous). There is a TECO_DEFINE_UNDO_CALL() to generate closures for arbitrary functions now (ie. to call an arbitrary function at undo-time). This simplified a lot of code and is much shorter than manually pushing undo tokens in many cases. * Instead of the ridiculous C++ Curiously Recurring Template Pattern to achieve static polymorphy for user interface implementations, we now simply declare all functions to implement in interface.h and link in the implementations. This is possible since we no longer hace to define interface subclasses (all state is static variables in the interface's *.c files). * Headers are now significantly shorter than in C++ since we can often hide more of our "class" implementations. * Memory counting is based on dlmalloc for most platforms now. Unfortunately, there is no malloc implementation that provides an efficient constant-time memory counter that is guaranteed to decrease when freeing memory. But since we use a defined malloc implementation now, malloc_usable_size() can be used safely for tracking memory use. malloc() replacement is very tricky on Windows, so we use a poll thread on Windows. This can also be enabled on other supported platforms using --disable-malloc-replacement. All in all, I'm still not pleased with the state of memory limiting. It is a mess. * Error handling uses GError now. This has the advantage that the GError codes can be reused once we support error catching in the SciTECO language. * Added a few more test suite cases. * Haiku is no longer supported as builds are instable and I did not manage to debug them - quite possibly Haiku bugs were responsible. * Glib v2.44 or later are now required. The GTK UI requires Gtk+ v3.12 or later now. The GtkFlowBox fallback and sciteco-wrapper workaround are no longer required. * We now extensively use the GCC/Clang-specific g_auto feature (automatic deallocations when leaving the current code block). * Updated copyright to 2021. SciTECO has been in continuous development, even though there have been no commits since 2018. * Since these changes are so significant, the target release has been set to v2.0. It is planned that beginning with v3.0, the language will be kept stable.
2018-06-11improved Emscripten support: fixed configure-checks, generate *.js and ↵Robin Haberkorn3-9/+18
detect EMCurses * Emscripten can be used (theoretically) to build a host-only platform-independant version of SciTECO (running under node.js instead of the browser). * I ported netbsd-curses with Emscripten for that purpose. Therefore, adaptions for running in the browser are restricted to EMcurses now.
2017-08-24fixed memory leaks and memory measurement leaks by removing -fsized-deallocationRobin Haberkorn1-40/+28
* Array allocations were not properly accounted since the compiler would call the replacement new() which assumes that it would always be called along with the replacement sized-deletion. This is not true for array new[] allocations resulting in a constant increase of memory_usage and unrecoverable situations. This problem however could be fixed in principle by avoiding memory counting for arrays or falling back to malloc_usable_size. * The bigger problem was that some STLs (new_allocator) are broken, calling the non-sized delete for regular new() calls which could in principle be matched by sized-delete. This is also the reason why I had to provide a non-sized delete replacement, which in reality intoduced memory leaks. * Since adding checks for the broken compiler versions or a configure-time check that tries to detect these broken systems seems tedious, I simply removed that optimization. * This means we always have to rely on malloc_usable_size() now for non-SciTECO-object memory measurement. * Perhaps in the future, there should be an option for allowing portable measurement at the cost of memory usage, by prefixing each memory chunk with the chunk size. Maintainers could then decide to optimize their build for "speed" at the cost of memory overhead. * Another solution to this non-ending odyssey might be to introduce our own allocator, replacing malloc(), and allowing our own precise measurements.
2017-04-30define non-sized deallocator and memory counting debuggingRobin Haberkorn2-13/+39
* it turned out to be possible to provoke memory_usage overflows or underruns, resulting in unrecoverable states * a possible reason can be that at least with G++ 5.4.0, the compiler would sometimes call the (default) non-sized delete followed by our custom sized delete/deallocator. * This was true even after compiling Scintilla with -fsized-deallocation. * therefore we provide an empty non-sized delete now. * memory_usage counting can now be debugged by uncommenting DEBUG_MAGIC in memory.cpp. This uses a magic value to detect instrumented allocations being mixed with non-instrumented allocations. * simplified the global sized-deallocation functions (they are identical to the Object-class allocators).
2017-04-30removed CLANG and HAVE_SIZED_DEALLOCATION conditionalsRobin Haberkorn3-21/+3
Automakefiles could be simplified by updating CXXFLAGS in configure.ac instead.
2017-03-25some minor Doxygen documentation improvementsRobin Haberkorn4-4/+5
* avoid warnings * make sure Doxygen finds RBEntryOwnString * it would be nice to strip the top level `SciTECO` namespace but this is not supported without some macro magic that ommit the namespace declaration when processing with Doxygen.
2017-03-250,8ED: Automatic case-folding of commandsRobin Haberkorn4-11/+44
* when enabled, it will automatically upper-case all one or two letter commands (which are case insensitive). * also affects the up-carret control commands, so they when inserted they look more like real control commands. * specifically does not affect case-insensitive Q-Register specifications * the result are command lines that are better readable and conform to the coding style used in SciTECO's standard library. This eases reusing command lines as well. * Consequently, string-building and pattern match characters should be case-folded as well, but they aren't currently since State::process_edit_cmd() does not have sufficient insight into the MicroStateMachines. Also, it could not be delegated to the MicroStateMachines. Perhaps they should be abandoned in favour of embeddedable regular state machines; or regular state machines with a stack of return states?
2017-03-23fixed checks for missing left and right operands to binary operatorsRobin Haberkorn1-2/+2
* this resulted in assertions (crashes!) for harmless typos like "+23=" * a test case has been added
2017-03-23fixed and optimized piping very large buffers via EC/EGRobin Haberkorn2-14/+17
* test case: HECcat$ on a large buffer (>= 64kb) truncates the buffer or repeats its beginning * it turns out that the incremental writing to the process' stdin was broken. We were always writing data from the beginning of the buffer which fails if the stdin watcher must be activated more than once. * Also, EOLWriter::convert() can validly return 0, even if bytes have been written on the data sink, so this value cannot be used to check whether the process has closed its stdin. We now make sure that the entire buffer range is written to stdin. * Piping large buffers no longer removes the buffer gap. This makes little difference when filtering via EC since it will change the buffer gap anyway. Can make a huge difference when not touching the buffer, though (e.g. HEGAcat$). * I did not add a test suite case since that requires a very large test file and it cannot be easily generated automatically.
2017-03-18fixed Q-Reg autocompletion for `Q` commandRobin Haberkorn4-34/+42
* StateQueryQReg is now derived from StateExpectQReg whose semantics have been changed slightly. * The alternative would have been another common base class for both StateQueryQReg and StateExpectQReg.
2017-03-14added ./configure --with-interface=netbsd-curses and improved NetBSD-curses ↵Robin Haberkorn1-13/+27
support * Since netbsd-curses can act as a drop-in replacement to ncurses, SciTECO builds with --with-interface=ncurses as well. However, it is unintuitive for users to build with ncurses support when actually linking against netbsd-curses; so another option has been added. * The UNIX/TTY specific code (which works with both ncurses and netbsd-curses) was selected when NCURSES was detected at build-time. This does not work for netbsd-curses, so we define a new symbol NETBSD_CURSES. At build-time, a CURSES_TTY macro may now be defined. * This effectively fixes the stdio in interactive mode, window titles and the XTerm clipboard support for netbsd-curses. Some minor features like the reduced ESCDELAY are still broken.
2017-03-08yet another revision of memory limiting: the glibc mallinfo() approach has ↵Robin Haberkorn4-75/+117
been shown to be unacceptably broken, so the fallback implementation has been improved * mallinfo() is not only broken on 64-bit systems but slows things down linearilly to the memory size of the process. E.g. after 500000<%A>, SciTECO will act sluggish! Shutting down afterwards can take minutes... mallinfo() was thus finally discarded as a memory measurement technique. * Evaluating /proc/self/statm? has also been evaluated and discarded because doing this frequently is even slower. * Instead, the fallback implementation has been drastically improved: * If possible use C++14 global sized deallocators, allowing memory measurements across the entire C++ code base with minimal runtime overhead. Since we only depend on C++11, a lengthy Autoconf check had to be introduced. * Use malloc_usable_size() with global non-sized deallocators to measure the approx. memory usage of the entire process (at least the ones done via C++). The cheaper C++11 sized deallocators implemented via SciTECO::Object still have precedence, so this affects Scintilla code only. * With both improvements the test case sciteco -e '<@EU[X^E\a]"^E\a"%a>' is handled sufficiently well now on glibc and performance is much better now. * The jemalloc-specific technique has been removed since it no longer brings any benefits compared to the improved fallback technique. Even the case of using malloc_usable_size() in strict C++ mode is up to 3 times faster. * The new fallback implementation might actually be good enough for Windows as well if some MSVCRT-specific support is added, like using _msize() instead of malloc_usable_size(). This must be tested and benchmarked, so we keep the Windows-specific implementation for the time being.
2017-03-08undo stack reorganized into a stack of undo token listsRobin Haberkorn2-38/+62
* in a flat list of undo tokens, we need to store the program counter (ie. command line position) that the undo token corresponds to. Since in general there is more than one undo token per input character, this stored PCs redundantly. * For input characters with no undo tokens (only applies to NOPs like space in the command line macro), this needs one more pointer than before. * In case of 1 undo token per input character, the new implementation uses approx. the same memory. * In the most common case of more than one undo token per input character, this saves at least 4 bytes per undo token. * In large macros and long loops the effect is especially pronounced. E.g. 500000<%A> will use 8MB less memory with the new implementation.
2017-03-08fixup to 89224899: fixed function key macros after $ and the rubout-command ↵Robin Haberkorn2-2/+21
editing key * StateEscape should return the same fnmacro mask as StateStart * When rubbing out a command, we should stop at StateEscape as well. Therefore we reintroduced States::is_start(). RTTI is still not used.
2017-03-07refactored commandline key processing: rewritten Cmdline::process_edit_cmd() ↵Robin Haberkorn7-383/+524
as State::process_edit_cmd() virtual methods * Cmdline::process_edit_cmd() was much too long and deeply nested. It used RTTI excessively to implement the state-specific behaviour. It became apparent that the behaviour is largely state-specific and could be modelled much more elegantly as virtual methods of State. * Basically, a state can now implement a method to customize its commandline behaviour. In the case that the state does not define custom behaviour for the key pressed, it can "chain" to the parent class' process_edit_cmd(). This can be optimized to tail calls by the compiler. * The State::process_edit_cmd() implementations are still isolated in cmdline.cpp. This is not strictly necessary but allows us keep the already large compilations units like parser.cpp small. Also, the edit command processing has little to do with the rest of a state's functionality and is only used in interactive mode. * As a result, we have many small functions now which are much easier to maintain. This makes adding new and more complex context sensitive editing behaviour easier. * State-specific function key masking has been refactored by introducing State::get_fnmacro_mask(). * This allowed us to remove the States::is_*() functions which have always been a crutch to support context-sensitive key handling. * RTTI is almost completely eradicated, except for exception handling and StdError(). Both remaining cases can probably be avoided in the future, allowing us to compile smaller binaries.
2017-03-06roll back to the old mallinfo() implementation of memory limiting on Linux ↵Robin Haberkorn3-64/+118
and added a FreeBSD/jemalloc-specific implementation * largely reverts 39cfc573, but leaves in minor and documentation changes. * further experimentation of memory limiting using malloc() wrapping has shown additional problems, like dlsym() calling malloc-functions, further reducing the implementation to glibc-specific means. This means there had been no implementation for FreeBSD and checks would have to rely on undocumented internal implementation details of different libcs, which is not a good thing. * Other problems have been identified, like having to wrap calloc(), guarding against underruns and multi-thread safety had been identified but could be worked around. * A technique by calculating the memory usage as sbrk(0) - &end has been shown to be effective enough, at least on glibc. However even on glibc it has shortcomings since malloc() will somtimes use mmap() for allocations and the technique relies on implementation details of the libc. Furthermore another malloc_trim(0) had to be added to the error recovery in interactive mode, since glibc does not adjust the program break automatically (to avoid syscalls I presume). * On FreeBSD/jemalloc, the sbrk(0) method totally fails because jemalloc exclusively allocates via mmap() -> that solution was discarded as well. * Since all evaluated techniques turn out to be highly platform specific, I reverted to the simple and stable platform-specific mallinfo() API on Linux. * On FreeBSD/jemalloc, it's possible to use mallctl("stats.allocated") for the same purpose - so it works there, too now. It's slower than the other techniques, though. * A lengthy discussion has been added to memory.cpp, so that we do not repeat the previous mistakes.
2017-03-05memory limiting: libc malloc() and realloc() can return NULLRobin Haberkorn1-2/+4
* shouldn't make much of a difference, since we're in deep trouble when they return NULL, but the wrappers should be transparent instead of crashing in malloc_usable_size().
2017-03-05replaced Linux-specific mallinfo()-based memory limiting with a more ↵Robin Haberkorn1-17/+90
portable and faster hack * Works by "hooking" into malloc() and friends and counting the usable heap object sizes with malloc_usable_size(). Thus, it has no memory-overhead. * Will work at least on Linux and (Free)BSD. Other UNIXoid systems may work as well - this is tested by ./configure. * Usually faster than even the fallback implementation since the memory limit is hit earlier. * A similar approach could be tried on Windows (TODO). * A proper memory-limiting counting all malloc()s in the system can make a huge difference as this test case shows: sciteco -e '<@EU[X^E\a]"^E\a"%a>' It will allocate gigabytes before hitting the 500MB memory limit... * Fixed the UNIX-function checks on BSDs.
2017-03-03updated copyright to 2017Robin Haberkorn53-53/+53
2017-03-03build system portability fixesRobin Haberkorn1-6/+3
* especially to improve building on FreeBSD 11 * We need GNU Make, yet alone because Scintilla/Scinterm needs it. We now document that dependency and added an Autoconf check from the autoconf-archive. We make sure that the build process is invoked with GNU make by generating only GNUmakefiles. The Makefile.am files have not been renamed, so this change can be rolled back easily. * Some GNU-Make-specific autoreconf warnings have still been resolved. But not all of them, as this would have been unelegant and we need GNU Make anyway. * Declare ACLOCAL_AMFLAGS to appease autoreconf * Added an explicit check for C++11 from the autoconf-archives. In general we should support building with every C++11 compiler that is sufficiently GNU-like. * Do not use `sed` for inplace editing, as different sed-implementations have mutually incompatible syntax for this. Instead of declaring and checking a dependency on GNU sed, we simply use SciTECO for the editing task. This improves code portability on BSDs. * Similarily, BSD/POSIX `cmp` is supported now. This fixes the test suite on BSD without declaring a dependency on the GNU coreutils. * Simplified sciteco-wrapper generation.
2016-11-30allow dollar sign as another variant of ^[ (discard all arguments or return)Robin Haberkorn2-23/+42
* some classic TECOs have this * just like ^[, dollar works as a command only, not as a string terminator * it improves the readability of macros using printable characters only * it closes a gap in the language by allowing $$ (double-dollar) and ^[$ as printable ways to write the return from macro command. ^[^[ was not and is not possible. * since command line termination is a regular interactive return-command in SciTECO, double-dollar will also terminate the command line now. This will be allowed unless it turns out to be a cause of trouble. * The handling of unterminated commands has been cleaned up by introducing State::end_of_macro(). Most commands (and thus states) except the start state cannot be valid at the end of a macro since this indicates an unterminated/incomplete command. All lookahead-commands (currently only ^[) will end implicitly at the end of a macro and so will need a way to perform their action. The virtual method allows these actions to be defined with the rest of the state's implementation.
2016-11-27fixed rubout of the first command after command line termination ($$)Robin Haberkorn2-6/+6
* The $$ would leave the current state pointing to the "escape" state which was manually fixed up in macro return handling but not in command line return (ie. termination) handling. Therefore the initial state at the start of the command line after $$ was the "escape" state. The rubout-last-command immediate editing command would consequently end up in an infinite loop trying to reach the start state. * This has been fixed by setting the state before throwing Return(). Some additional paranoia assertions have been added to prevent this bug in the future.
2016-11-22Gtk interface: make sure that the default display is openedRobin Haberkorn1-2/+10
* this has been broken since cb5e08b40d
2016-11-22save some bytes per Q-Register creation on the undo stackRobin Haberkorn2-21/+47
* a table reference was stored in the UndoToken. * since there are only two tables at a given moment, this can be avoided by having two different undo tokens, one for globals and one for locals. * Practically, undo tokens for locals are only created for the top-level local Q-Reg table since macro calls with locals with set must_undo to false since the local table is destroyed with the macro return.
2016-11-22avoid the non-standard \e escape sequenceRobin Haberkorn2-5/+8
* shouldn't really be an issue but since we already have CTL_KEY_ESC_STR as a character literal, we may as well use it.
2016-11-22fixed local Q-Register management on certain broken platformsRobin Haberkorn4-23/+42
* on MSVCRT/MinGW, space allocated with alloca()/g_newa() was apparently freed once the first exception was caught. This prevented the proper destruction of local Q-Reg tables and broke the Windows port. * Since all alternatives to alloca() like VLAs are not practical, the default Q-Register initialization has been moved out of the QRegisterTable constructor into QRegisterTable::insert_defaults(). * The remaining QRegisterTable initialization and destruction is very cheap, so we simply reserve an empty QRegisterTable for local registers on every Execute::macro() call. The default registers are only initialized when required, though. * All of this has to change anyway once we replace the C++ call-stack approach to macro calls with our own macro call frame memory management.
2016-11-22optimized QRegisterTable cleanupRobin Haberkorn5-5/+10
* we can use root() instead of min() which is faster
2016-11-22partially reversed/fixed-up b7ff56db631: avoid g_slice allocators and ↵Robin Haberkorn2-14/+24
performance issues with memory measurements * Fixed build problems on Windows * g_slice on Windows has been shown to be of little use either and it does not work well with the GetProcessMemoryInfo() measurements. Also, it brings the same problem as on Glibc: Not even command-line termination returns the memory to the OS. Therefore, we don't use g_slice at all and commented on it. * The custom Linux and Windows memory measurement approaches have been shown to be inefficient. As a workaround, scripts disable memory limiting. * A better approach -- but it will only work on Glibc -- might be to hook into malloc(), realloc() and free() globally and use the malloc_usable_size() of a heap object for memory measurements. This will be relatively precise and cheap. * We still need the "Object" base class in order to measure memory usage as a fallback approach.
2016-11-21fixed compilation of the PDCurses frontendRobin Haberkorn1-1/+1
* a simple cast was missing due to C++ aliasing rules
2016-11-20fixed glib warnings about using g_mem_set_vtable() and revised memory limitingRobin Haberkorn24-268/+352
* we were basing the glib allocators on throwing std::bad_alloc just like the C++ operators. However, this always was unsafe since we were throwing exceptions across plain-C frames (Glib). Also, the memory vtable has been deprecated in Glib, resulting in ugly warnings. * Instead, we now let the C++ new/delete operators work like Glib by basing them on g_malloc/g_slice. This means they will assert and the application will terminate abnormally in case of OOM. OOMs cannot be handled properly anyway, so it is more important to have a good memory limiting mechanism. * Memory limiting has been completely revised. Instead of approximating undo stack sizes using virtual methods (which is unprecise and comes with a performance penalty), we now use a common base class SciTECO::Object to count the memory required by all objects allocated within SciTECO. This is less precise than using global replacement new/deletes which would allow us to control allocations in all C++ code including Scintilla, but they are only supported as of C++14 (GCC 5) and adding compile-time checks would be cumbersome. In any case, we're missing Glib allocations (esp. strings). * As a platform-specific extension, on Linux/glibc we use mallinfo() to count the exact memory usage of the process. On Windows, we use GetProcessMemoryInfo() -- the latter implementation is currently UNTESTED. * We use g_malloc() for new/delete operators when there is malloc_trim() since g_slice does not free heap chunks properly (probably does its own mmap()ing), rendering malloc_trim() ineffective. We've also benchmarked g_slice on Linux/glib (malloc_trim() shouldn't be available elsewhere) and found that it brings no significant performance benefit. On all other platforms, we use g_slice since it is assumed that it at least does not hurt. The new g_slice based allocators should be tested on MSVCRT since I assume that they bring a significant performance benefit on Windows. * Memory limiting does now work in batch mode as well and is still enabled by default. * The old UndoTokenWithSize CRTP hack could be removed. UndoStack operations should be a bit faster now. But on the other hand, there will be an overhead due to repeated memory limit checking on every processed character.
2016-11-20fixup to 19675a1a4899: fixed crash after rubbing out creation of global registerRobin Haberkorn1-1/+1
* test case: rubout 1U[foo] * this probably also leaked memory if it didn't crash * a missing cast from RBTree::remove() was missing. This cast is necessary since QRegister uses multiple inheritance. The offset of RBEntryString might not be 0 in QRegister. Also, since the base class is no longer virtual, a cast to the virtual QRegister class is necessary to ensure that subclass destructors get called. This might have not caused problems before since RBEntry was virtual or the compiler just happened to reorder the instance structures.
2016-11-20optimized RBTree: avoid unnecessary virtual RBTree and RBEntry ↵Robin Haberkorn7-26/+42
implementation classes * whenever the implementation class was not exactly RBEntryType, it had to have a virtual destructor since RBTree cared about cleanup and had to delete its members. * Since it does not allocate them, it is consistent to remove RBTree::clear(). The destructor now only checks that subclasses have cleaned up. Implementing cleanup in the subclasses is trivial. * Consequently, RBEntryString no longer has to be virtual. HelpIndex and GotoTables are completely non-virtual now which saves memory (and a bit of cleanup speed). For QRegister, not much changes, though.
2016-11-20fixed interpretation of the Q-Register specification ".."Robin Haberkorn1-3/+6
* From what the documentation says, a dot may only be used once to introduce a local Q-Register specification. The parser was accepting arbitrarily many dots though. * Now, ".." will refer to the local register ".".
2016-11-20auto-completion of Q-Register names, goto labels and help topicsRobin Haberkorn8-11/+194
* Using a common implementation in RBTreeString::auto_complete(). This is very efficient even for very huge tables since only an O(log(n)) lookup is required and then all entries with a matching prefix are iterated. Worst-case complexity is still O(n), since all entries may be legitimate completions. If necessary, the number of matching entries could be restricted, though. * Auto completes short and long Q-Reg names. Short names are "case-insensitive" (since they are upper-cased). Long specs are terminated with a closing bracket. * Long spec completions may have problems with names containing funny characters since they may be misinterpreted as string building characters or contain braces. All the auto-completions suffered from this problem already (see TODO). * This greatly simplifies investigating the Q-Register name spaces interactively and e.g. calling macros with long names, inserting environment registers etc. * Goto labels are terminated with commas since they may be part of a computed goto. * Help topics are matched case insensitive (just like the topic lookup itself) and are terminated with the escape character. This greatly simplifies navigating womanpages and looking up topics with long names.
2016-11-20optimized red-black trees and common base class for string-keyed RB treesRobin Haberkorn8-121/+167
* the old implementation tried to avoid template programming by making the entry comparison function virtual. * The new RBTree implementation takes a template argument with the implementation of RBEntry. It is now partially conventional that the template argument must be actually derived from RBTree::RBEntry and must define a "compare" method. * As an advantage we now get static polymorphism (avoiding virtual calls and allowing for more compiler optimizations) and the the RBEntry implementation no longer has to be virtual. * The only RB-Trees actually used are string-keyed, though. Therefore there's a common base class RBTreeString now which defines two synonymous "key" and "name" attributes. * The entry base class RBEntryString is virtual again because we do not want to propagate the RBEntryType template parameter even further and the RBTree base class needs to destroy entries. This might be avoided by not defining a RBTree::clear() method, leaving this task to the implementations. At least QRegisters have to be virtual, though. * RBTreeString only depends on the strcmp() and strncmp() functions used now and only case-sensitive and case-insensitive versions are actually required, so we instantiate these templates statically in rbtree.cpp. This means there are still only two instantiations of the RBTree in the binary. * RBTreeString defines convenient wrappers for find() and nfind() to look up by string. This uses the RBEntryString base class, so no allocations whatsover are required for lookups and less space is wasted on the call stack. * A RBEntryOwnString base class is also provided which frees the implementations from memory managing the tree keys. * RBTreeString can now be used to add other common functionality like auto-completions for Q-Registers, goto labels and help topics. * some minor optimizations * updated TODO
2016-11-18the manual generator (generator-docs.tes) has been cleaned up and is now ↵Robin Haberkorn9-69/+69
called tedoc.tes * some code simplifications * it now supports command line arguments via getopt.tes. * the -C flag enabled C/C++ mode. By default tedoc parses SciTECO code which means it can be used to document macro packages as well. * Therefore it is installed as a separate tool now. It may be used as a Groff preprocessor for third-party macro authors to generate (wo)man pages. * there's a man page tedoc.tes(1) * The troff placeholder macro is now called ".TEDOC". * Help topics can now be specified after the starting comment /*$ or !*$. Topics have been defined for all built-in commands.
2016-11-18standard lib: added getopt.tes for parsing command line options in scriptsRobin Haberkorn2-17/+23
* this uses an optstring compatible with getopt(3). * It does not use repeated getopt calls to iterate options, though but places the results in registers beginning with "getopt.". E.g. option "C" will result in "getopt.C" being set after the call to setopt. String arguments are supported and are placed in the string part of the getopt registers. * The grosciteco.tes and symbols-extract.tes scripts make use of getopt now, to simplify and clean up their command line handling.
2016-11-18improved command line option handlingRobin Haberkorn8-40/+110
* it turns out that option-like arguments could not be reliably passed to SciTECO scripts for two reasons: a) "--" arguments are not removed from argv by GOption if it detects and following option-like argument. "--" would thus be passed as a script argument which will disable option parsing in scripts that interpret "--". b) A script run via the Hash-Bang line "#!...sciteco -m" would require an explicit "--" to turn of GOption parsing. However it is __impossible__ to insert after the script file name on UNIX. * Therefore, SciTECO now removes leading "--" arguments left over by GOption. * If possible (Glib >= 2.44), option parsing is performed in strict POSIX mode which inhibits parsing after the first non-option argument. This reduces the number of cases where an explicit "--" is required. * --mung no longer takes an argument. Instead, the first non-option argument is expected to be the script file name. This looks weird at first but is more consistent with how other interpeters work. Once we revise argument passing to scripts, the script name can also be passed to the script which is more consistent with it being the first non-option argument. Also, with strict POSIX parsing, this fixed Hash-Bang lines since the script file name constructed by the kernel will automatically switch off option parsing, passing all option-like script arguments uninterpreted to the script. * Since we're supporting Glib < 2.44, the Hash-Bang lines are still broken for certain builds. Therefore, a wrapper script is installed to libexecdir (it never has to be executed by users and Hash-Bang lines need absolute paths anyway) which transparently inserts "--" into the SciTECO command line and should be used as the interpreter in portable SciTECO scripts. The wrapper script is generated and points to the exact SciTECO binary installed. This is important when doing parallel installs of Curses and Gtk binaries since each one will get its own working wrapper script. The wrapper-script workaround can be removed once we depend on Glib >= 2.44 (some day...). * The default /usr/bin/env Hash-Bang lines are no longer used in the scripts since they are broken anyway (UNIX incl. Linux cannot pass multiple arguments to the interpreter!). Scripts that get installed will get a fixed-up Hash-Bang line referring to the installed SciTECO binary anyway. * Interface::main() has been renamed to Interface::init() and is optional now. The Interface::main() method was introduced because of the misconception that interfaces will find their options in the argv array and have to do their own parsing. This is wrong, since their option group already cares about parsing. Therefore, gtk_init() does not have to called explicitly, too.