pax_global_header00006660000000000000000000000064140052326650014515gustar00rootroot0000000000000052 comment=03be44634fc2a5df4abb1d75a141d976f6a08428 smenu-0.9.17/000077500000000000000000000000001400523266500127425ustar00rootroot00000000000000smenu-0.9.17/.clang-format000066400000000000000000000025761400523266500153270ustar00rootroot00000000000000SortIncludes: 'false' BasedOnStyle: Mozilla AlignAfterOpenBracket: 'true' AlignConsecutiveAssignments: 'true' AlignConsecutiveDeclarations: 'true' AlignOperands: 'true' AlignEscapedNewlinesLeft: 'true' AlignOperands: 'true' AlignTrailingComments: 'true' ReflowComments: 'false' AllowAllParametersOfDeclarationOnNextLine: 'false' AllowShortBlocksOnASingleLine: 'false' AllowShortCaseLabelsOnASingleLine: 'false' AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: 'false' AllowShortLoopsOnASingleLine: 'false' AlwaysBreakBeforeMultilineStrings: 'false' BinPackArguments: 'true' BinPackParameters: 'true' BreakBeforeBraces: Allman BreakBeforeBinaryOperators: NonAssignment BreakBeforeTernaryOperators: 'true' BreakConstructorInitializersBeforeComma: 'false' ColumnLimit: '80' ContinuationIndentWidth: '2' DerivePointerAlignment: 'false' IndentCaseLabels: 'true' IndentWidth: '2' KeepEmptyLinesAtTheStartOfBlocks: 'true' Language: Cpp MaxEmptyLinesToKeep: '1' PointerAlignment: Middle SpaceAfterCStyleCast: 'false' SpaceBeforeAssignmentOperators: 'true' SpaceBeforeParens: Never SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: 'false' SpacesBeforeTrailingComments: '1' SpacesInCStyleCastParentheses: 'false' SpacesInParentheses: 'false' SpacesInSquareBrackets: 'false' TabWidth: '2' UseTab: Never PenaltyBreakBeforeFirstCallParameter: '100' PenaltyBreakAssignment: '150' smenu-0.9.17/COPYRIGHT000066400000000000000000000000731400523266500142350ustar00rootroot00000000000000(c) Pierre Gentile (p.gen.progs@gmail.com) License: GPLv2 smenu-0.9.17/ChangeLog000066400000000000000000000255721400523266500145270ustar00rootroot00000000000000- Version 0.9.17 * Fixes: * The method to get the cursor location has been fixed and improved. * A display problem when the title takes too many lines has been fixed. * A failure when reopening /dev/tty is now fatal. * Interesting signals are now trapped only when needed. * The refresh mechanism when resizing the terminal has been fixed and improved. * \U does not need too be escaped anymore. * Improvements: * The -Q|-ignore_quotes option has been added to provide a way to ignore quotes when splitting the input stream/file into words. * The -!|-int|-int_string option has been added to define a string to be displayed on stdout when ^C is entered during a smenu session. * The usage text is now displayed in case of an error on the command line. * The code to create include/exclude RE patterns has been simplified. * smenu now mimics the Unix shell signal processing. * Misc: * The availability of str(n)dup is now checked at compile time. * Tests for RE patterns/inv. character have bee added. * The obsolete autogen.sh script has been removed. * github's ctxopt commit f779fb8 is now used. * The code is now a little more readable. - Version 0.9.16 * Bug fixes: * The SIGINT handling has been fixed. * The lvm_menu example is fixed. * Some memory allocation issues have been corrected. * The last example in the man page now works correctly. * The manual has been cleaned and corrected. * Missing headers has been added. * The List management code has been corrected and improved. * Invalid UTF-8 sequences entered using \u are now handled correctly. * Unreachable code has been removed. * As xwcscasecmp is missing in C99, a local version is now used. * The search timeout now works correctly. * Improvements: * Option management has been completely rewritten to use a new, more flexible system called ctxopt (github.com/p-gen/ctxopt): - Both short and long options can now be used. - The validity of some option arguments can now be easily checked. - A better and more precise help system can now be used. - ... * The horizontal and vertical scrolling symbols are now visually consistent. * An updated version of autotools is now used. * Wide mode is now allowed in column mode. * Line delimiters can now be defined to break lines in tabulation mode. * A set of UTF-8 characters can now be ignored as input. * Substitution character for non-printable characters can now be changed. * -N and -U options can now have multiple arguments. * Fuzzy and substring searches now ignore leading and trailing blanks. * Unicode codepoints can now be entered using the new \U notation. * smenu has been optimized to support networks with high latency. * Misc: * A note in the README to thank the packagers has been added. * The code has been adjusted to conform to C99. * The code has been cleaned up in many places. - Version 0.9.15 * Bug fixes: * An ending pattern search was not correctly highlighted * An highlighting issue when hitting the HOME key during a search in numbered mode has been fixed * The PgUp/PgDn moves have been fixed and improved in the presence of excluded words * The height of the windows when a message is present is now correctly calculated * The SIGINT signal handling is working properly now * A vt100 terminal is assumed when the environment variable TERM is unset * Improvements: * The 'o' sub-option of the -D option has been enhanced * The documentation has been improved and enhanced * An example of a hierarchical menu interpreter has been added * The message (title) appearance can now be changed with the -a option * An empty line has been added after the message (title) for clarity * The .spec file has been updated to support older SUSE/RH versions * An issue opening /dev/tty is now clearly signaled * The argument of the -n option is now optional and defaults to 0 (full height) * It is now possible to directly move the cursor to the start/end of the current line * Misc: * The code has been split into several files * The pull request #15 from sumbach/patch-1 has been merged * The pull request #12 from jonnydubowsky/patch-1 has been merged * More tests for the automatic regressions checking have been added * UTF-8 string length processing has been optimized * Help and usage messages are now printed on stdout * A FAQ has been added * Compiler warnings have been silenced - Version 0.9.14 * Rework the search system (major change) * Add a substring and a fuzzy (fzf inspired) search mode * Enlighten the current search pattern in the matching words * Remove the search mode timeout * Introduce ENTER/ESC as a way to exit search mode * Add the prefix/suffix affinity when searching * Allow to tag/un-tag all the matching words * add a -/ option to affect a search method to the / command * Add 'T' and 'U' commands to tag/un-tag all the matching words * Improve the direct access mechanism * [-D] Add a 's' (start) sub-option * [-D] Add a 'h' (head) sub-option * Add a "full window" option value to -n * Improve the test system and add tests * Improve the documentation * Update the README.rst file and mention the wiki on GitHub * Fix an OpenBSD compatibility issue * Fix and improve the color mechanism * Fix the cursor display after an ESC hit * Fix the tag attribute display * Fix some compilation warnings * Fix a missing message when the terminal is too small * Fix a lot of other small and not-so-small bugs - Version 0.9.13 * Add the first roll of an automated testing system * Fix a FreeBSD compatibility issue * Update the .spec file to create a '-test' RPM sub-package * [-a] Add a missing setting for cursor_on_tag (ct) * [-b] Fix a bug about non-printable characters * [-V] Output the version tag on standard output * [-D] Add a 'decorate' directive * [-D] Handle multiple instances of the same directive * Fix a logic error in the direct access code * Fix an horizontal scrolling issue when going to the last word * Clean up the allocated gutter array before leaving in case of error * Understand some more terminfo sequences * Fix the right margin and add a degraded method to display it * Improve the manual * Various other small bug fixes Apr 08 18:32 UTC 2018 - p.gen.progs@gmail.com - Version 0.9.12 * Fix the cursor restoration * Fix a Solaris incompatibility * Fix italic handling * Fix the replacement of sub-expressions (-S,-I,-E) * Fix a bug in the columns inclusion logic * Fix the impossibility to use the letter 't' in search mode * Fix possible display errors when the terminal is resized * Make sure that the timers does not alter the redrawing of the window * Add word numbering to allow direct access through their number (-N,-U,-F,-D) * Improve The manual * Allow the \u notation for UTF-8 characters in more places * Improve the -T option and add the related -P option * Add the -p for use with the -P and -T options * The gutter option (-g) now accepts a parameter * Adopt the NO_COLOR standard (http://no-color.org) * Improve the navigation by understanding more keys and key combinations * Understand CTRL+L to redraws the window in case of corruption * Exit from search mode when a direction key is hit * Adjust some values of timers * Remove deprecated directives in -C and -L * Various other small fixes and improvements Jan 26 12:35 UTC 2018 - p.gen.progs@gmail.com - Version 0.9.11 * Introduce the new \u notation for UTF-8 hex sequences * Non-printable characters with an escape form are expanded * Keep non selectable blank words to allow special effects * Fix the wide option when in column or tabulation mode * The last word is always the last of its line (-g) * Improve message (-m) placement in centered mode * Manage substitutions leading to empty strings * Hopefully fix the placement of the scroll bar in all cases * The gutter can now be displayed in column mode * Various other small fixes Jul 29 16:30:00 UTC 2017 - p.gen.progs@gmail.com - Bump to version 0.9.10 * The words acquisition is rewritten and split in multiple phases * Add the capacity to (de)select rows an columns containing regexes * -i, -e, -C and -R can be used more than once and have a cumulative effect * Bugfix: -s is able to jump to non selectable words * Bugfix: The attributes are not overloaded when reading configuration files * Bugfix: the right bar is too far right in some cases. * Bugfix: the right shift indicator is omitted in some cases * Add a -x|-X option to set a timeout in seconds * Add a -f option to select an alternative configuration file * Add a -a option to set the attributes of the displayed elements * Add more controls in the selection parser * smenu can now read words directly from a file given as parameter * Rewrite the replace function used by -S/-I/-E with a more sed-like one * Searches should always consider the visual aspect of words (-S/-I/-E) Thu Dec 22 20:48:17 UTC 2016 - p.gen.progs@gmail.com - Version 0.9.9 * New UTF8 validation routine * Man page cleanup * Code cleanup and improvement * Improved configuration process * Add code to detect the host system at compile time * Compilation is now possible on BSD system derivatives * Bug fix: ignore EOF when a scancode contains an escape sequence. * Fix the cursor appearance on tagged words Sun Dec 11 20:00:20 UTC 2016 - p.gen.progs@gmail.com - Version 0.9.8 * Change the cursor aspect when the selected word is tagged * Add a small animated gif demo * Fix a potential infinite loop * Use custom fgetc/ungetc to be able to safely push back more than one byte * Add libtinfo in the searched libraries an regenerate configure * Manage conflicts between -C, -R, -c, -l, and -t * Improve and fix the help line display * Add a -T option to enable a tagging (multi-selections) mode * Add the -? option to only display the synopsis * Adjust the code so that it can be compiled with an ANSI compiler * Put the searched line in the middle of the displayed window if possible * Add a -k option to prevent trimming spaces * Fix the -s option * When not in search mode, any key except '?' should quit the help mode * Add a new example: yesno * Fix an off-by-one error when using -c and -w together * And many other minor changes and fixes ------------------------------------------------------------------- Sun Mar 13 09:28:52 UTC 2016 - p.gen.progs@gmail.com - Version 0.9.1 * Use the GNU autotools * Fix a lot of small and not so small bugs * Change the -s option semantic * Improve help and man page * Introduce some new options - see the man page for more * Also rework some options - see the man page for more * Add more configurable colors * Add the notion of non-selectable words * Add the notion of special words * Add a (de)selection by rows and/or columns * Interpret quotations in the input stream and ignore empty words * Add an option to center the output window * And many other minor changes ------------------------------------------------------------------- Sun Aug 9 23:00:59 UTC 2015 - p.gen.progs@gmail.com - Initial version - 0.9 smenu-0.9.17/FAQ000066400000000000000000000024221400523266500132740ustar00rootroot00000000000000Q: What is smenu? A: smenu is a selection tool which acts as a filter that takes words from the standard input or a file and presents them on the screen in various ways in a scrolling window. A cursor that you can easily move allows you to select one or more of them. The selected words are printed on the standard output. -------- Q: Why smenu tells me: "The length of a word has reached the limit of 512 characters." but there is no such word in my entry? A: There is a good chance you have an unbalanced quote, single or double, somewhere. smenu uses quotation marks to be able to have spaces in 'words', and these quotation marks that do not serve as delimiters must be protected. You can use something like: sed -e "s/'/\\\'/g" -e 's/"/\\"/g' to pre-process the input in such a case. -------- Q: Why does smenu -C... no longer work? A: smenu uses a new system of options based on the notion of contexts. The -C parameter is only valid in the "Columns" context as indicated in the error message. The string '[-c|-col|-col_mode|-column>Columns]' which is printed in the error message tells that to switch to "Columns" mode you have to use the -c parameter or its alternatives. So in this case the correct command line is: smenu -c -C... smenu-0.9.17/LICENSE.rst000066400000000000000000000432261400523266500145650ustar00rootroot00000000000000GNU General Public License ========================== *Version 2, June 1991* *Copyright © 1989, 1991 Free Software Foundation, Inc.* *51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA* Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble ~~~~~~~~ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: **(1)** copyright the software, and **(2)** offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **0.** This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. **1.** You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. **2.** You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: * **a)** You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. * **b)** You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. * **c)** If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. **3.** You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: * **a)** Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * **b)** Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * **c)** Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. **4.** You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. **5.** You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. **6.** Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. **7.** If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. **8.** If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. **9.** The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. **10.** If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY ~~~~~~~~~~~ **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *END OF TERMS AND CONDITIONS* How to Apply These Terms to Your New Programs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w`. This is free software, and you are welcome to redistribute it under certain conditions; type `show c` for details. The hypothetical commands `show w` and `show c` should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c`; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision` (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. smenu-0.9.17/Makefile.am000066400000000000000000000015511400523266500150000ustar00rootroot00000000000000bin_PROGRAMS = smenu smenu_SOURCES = smenu.c smenu.h list.c list.h xmalloc.c xmalloc.h \ index.c index.h utf8.c utf8.h fgetc.c fgetc.h \ utils.c utils.h usage.c usage.h ctxopt.h ctxopt.c dist_man_MANS = smenu.1 EXTRA_DIST = smenu.spec.in smenu.spec ChangeLog build.sh version \ COPYRIGHT LICENSE.rst README.rst examples build-aux tests \ FAQ dist-hook: @chmod u+rw $(distdir)/tests; \ cd $(distdir)/tests ; \ find * -name 'data*' -o \ -name '*.in' -o \ -name '*.tst' -o \ -name '*.bl' -o \ -name '*.good' \ | cpio -o > tests.cpio 2>/dev/null @gzip -f9 $(distdir)/tests/tests.cpio @find $(distdir)/tests/* -type d \ -exec rm -rf {} + smenu-0.9.17/Makefile.in000066400000000000000000000740011400523266500150110ustar00rootroot00000000000000# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = smenu$(EXEEXT) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = smenu.spec CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) am_smenu_OBJECTS = smenu.$(OBJEXT) list.$(OBJEXT) xmalloc.$(OBJEXT) \ index.$(OBJEXT) utf8.$(OBJEXT) fgetc.$(OBJEXT) utils.$(OBJEXT) \ usage.$(OBJEXT) ctxopt.$(OBJEXT) smenu_OBJECTS = $(am_smenu_OBJECTS) smenu_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/ctxopt.Po ./$(DEPDIR)/fgetc.Po \ ./$(DEPDIR)/index.Po ./$(DEPDIR)/list.Po ./$(DEPDIR)/smenu.Po \ ./$(DEPDIR)/usage.Po ./$(DEPDIR)/utf8.Po ./$(DEPDIR)/utils.Po \ ./$(DEPDIR)/xmalloc.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(smenu_SOURCES) DIST_SOURCES = $(smenu_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \ $(srcdir)/config.h.in $(srcdir)/smenu.spec.in \ $(top_srcdir)/build-aux/compile \ $(top_srcdir)/build-aux/config.guess \ $(top_srcdir)/build-aux/config.sub \ $(top_srcdir)/build-aux/depcomp \ $(top_srcdir)/build-aux/install-sh \ $(top_srcdir)/build-aux/missing ChangeLog TODO \ build-aux/compile build-aux/config.guess build-aux/config.sub \ build-aux/depcomp build-aux/install-sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) GZIP_ENV = --best DIST_ARCHIVES = $(distdir).tar.bz2 DIST_TARGETS = dist-bzip2 # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ smenu_SOURCES = smenu.c smenu.h list.c list.h xmalloc.c xmalloc.h \ index.c index.h utf8.c utf8.h fgetc.c fgetc.h \ utils.c utils.h usage.c usage.h ctxopt.h ctxopt.c dist_man_MANS = smenu.1 EXTRA_DIST = smenu.spec.in smenu.spec ChangeLog build.sh version \ COPYRIGHT LICENSE.rst README.rst examples build-aux tests \ FAQ all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 smenu.spec: $(top_builddir)/config.status $(srcdir)/smenu.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) smenu$(EXEEXT): $(smenu_OBJECTS) $(smenu_DEPENDENCIES) $(EXTRA_smenu_DEPENDENCIES) @rm -f smenu$(EXEEXT) $(AM_V_CCLD)$(LINK) $(smenu_OBJECTS) $(smenu_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctxopt.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fgetc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/index.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smenu.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usage.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmalloc.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) config.h installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f ./$(DEPDIR)/ctxopt.Po -rm -f ./$(DEPDIR)/fgetc.Po -rm -f ./$(DEPDIR)/index.Po -rm -f ./$(DEPDIR)/list.Po -rm -f ./$(DEPDIR)/smenu.Po -rm -f ./$(DEPDIR)/usage.Po -rm -f ./$(DEPDIR)/utf8.Po -rm -f ./$(DEPDIR)/utils.Po -rm -f ./$(DEPDIR)/xmalloc.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f ./$(DEPDIR)/ctxopt.Po -rm -f ./$(DEPDIR)/fgetc.Po -rm -f ./$(DEPDIR)/index.Po -rm -f ./$(DEPDIR)/list.Po -rm -f ./$(DEPDIR)/smenu.Po -rm -f ./$(DEPDIR)/usage.Po -rm -f ./$(DEPDIR)/utf8.Po -rm -f ./$(DEPDIR)/utils.Po -rm -f ./$(DEPDIR)/xmalloc.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man1 .MAKE: all install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \ check-am clean clean-binPROGRAMS clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip dist-zstd distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-man \ uninstall-man1 .PRECIOUS: Makefile dist-hook: @chmod u+rw $(distdir)/tests; \ cd $(distdir)/tests ; \ find * -name 'data*' -o \ -name '*.in' -o \ -name '*.tst' -o \ -name '*.bl' -o \ -name '*.good' \ | cpio -o > tests.cpio 2>/dev/null @gzip -f9 $(distdir)/tests/tests.cpio @find $(distdir)/tests/* -type d \ -exec rm -rf {} + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: smenu-0.9.17/README.rst000066400000000000000000000132311400523266500144310ustar00rootroot00000000000000.. image:: smenu.gif | .. image:: simple_menu.gif What is it? =========== **smenu** is a selection filter just like ``sed`` is an editing filter. This tool takes words from standard input or from a file and presents them on the screen in different layouts in a scrolling window. A cursor that you can easily move lets you select one or more of them. Note that the screen is not previously cleared when the scrolling window of **smenu** is displayed. I tried to make its use as simple as possible. It supports the ``UTF-8`` encoding and should work on all terminals managed by the ``terminfo`` database. Please use the included man page to learn more about this little program. The `wiki `_ contains screenshots and animations that detail some concepts and features of **smenu**. How to build it? ================ **smenu** can be built on any system on which a working ``terminfo`` development platform is available. This includes every Unix and Unix-like system I am aware of. Please use the provided ``build.sh`` script to build the executable. This script accepts the same arguments as the GNU ``configure`` script, type ``build.sh --help`` to see them. The script ``autogen.sh`` is also provided if you need to generate a new ``configure`` script from ``configure.ac`` and ``Makefile.am``. The GNU **autotools** will need to be installed for this script to work. How to install it? ================== Once the build process has finished, a simple ``make install`` with the appropriate privileges will do it. Issue vs Discussion. ==================== I have enabled `discussions `_ on this repository. I am aware there may be some confusion when deciding where you should communicate when reporting issues, asking questions or raising feature requests so this section aims to help us align on that. Please `raise an issue `_ if: - You have found a bug. - You have a feature request and can clearly describe your request. Please `open a discussion `_ if: - You have a question. - You're not sure how to achieve something with smenu. - You have an idea but don't quite know how you would like it to work. - You have achieved something cool with smenu and want to show it off. - Anything else! Some examples. ============== Linux example. -------------- This program should work on most Unix but if you are using Linux, try to type the following line at a shell prompt (here: ``"$ "`` ): :: $ R=$(grep Vm /proc/$$/status \ | smenu -n20 -W $':\t\n' -q -c -b -g -s /VmH) $ echo $R Something like this should now be displayed with the program waiting for commands: (numbers are mine, yours will be different) :: VmPeak¦ 23840 kB VmSize¦ 23836 kB VmLck ¦ 0 kB VmHWM ¦ 2936 kB VmRSS ¦ 2936 kB VmData¦ 1316 kB VmStk ¦ 136 kB VmExe ¦ 28 kB VmLib ¦ 3956 kB VmPTE ¦ 64 kB VmSwap¦ 0 kB A cursor should be under ``"VmHWM "``. After having moved the cursor to ``" 136 kB"`` and ended the program with ````, the shell variable R should contain: ``" 136 kB"``. Unix example. ------------- The following command, which is Unix brand agnostic, should give you a scrolling window if you have more than 10 accounts on your Unix with a UID lower than 100: :: $ R=$(awk -F: '$3 < 100 {print $1,$3,$4,$NF}' /etc/passwd \ | smenu -n10 -c) $ echo $R On mine (``LANG`` and ``LC_ALL`` set to ``POSIX``) it displays: :: at 25 25 /bin/bash \ sys 0 3 /usr/bin/ksh + bin 1 1 /bin/bash | daemon 2 2 /bin/bash | ftp 40 49 /bin/bash | games 12 100 /bin/bash | lp 4 7 /bin/bash | mail 8 12 /bin/false | named 44 44 /bin/false | ntp 74 108 /bin/false v Note the presence of a scrollbar. Warning for post v0.9.15 versions. ---------------------------------- These versions use a new options system called **ctxopt** which may contain bugs. Please report them so they can be fixed in the next release of **smenu** or **ctxopt** (https://github.com/p-gen/ctxopt). Command line arguments may also need to be rearranged in some cases because of this new option management system. Sorry for the extra work this might entail. Testing and reporting. ---------------------- The included testing system is relatively young, please be indulgent. **IMPORTANT** the testing system has some dependencies, please read the ``test/README.rst`` before going further. **NOTE** running all the tests by running ``./tests.sh`` in the ``tests`` directory will take some time (around 21 min for now). **NOTE** on some systems like \*BSD some tests may fail. This can be explained by differences in posix/libc/... implementations. This can notably occur when some specific regular expressions or uncommon ``UTF-8`` byte sequences are used. If a test fails for unknown reason, then please send me its directory name and the relevant ``.bad`` file. If you are hit by a bug that no test covers, then you can create a new test in the ``tests`` directory in an existing or new directory: read the ``tests/README.rst`` file, use an existing test as model, create an ``.in`` file and a ``.tst`` file and send them to me as well as the produced files. Contributions. -------------- Contributions are welcome but discuss your proposal in an issue first, or with the maintainer. Special thanks. --------------- I want to thank those who took the time to package **smenu** for their preferred operating system or distribution. You will find their names here: https://repology.org/project/smenu/packages smenu-0.9.17/SUMMARY000066400000000000000000000003021400523266500140150ustar00rootroot00000000000000Terminal utility that allows you to use words coming from the standard input to create a nice selection window just below the cursor. Once done, your selection will be sent to standard output. smenu-0.9.17/TODO000066400000000000000000000002471400523266500134350ustar00rootroot00000000000000# B: Bugs to fix, I: possible Improvements # ========================================. I: Improve configure.ac I: Improve the checking of system/library calls returns smenu-0.9.17/aclocal.m4000066400000000000000000001217001400523266500146030ustar00rootroot00000000000000# generated automatically by aclocal 1.16.3 -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR smenu-0.9.17/build-aux/000077500000000000000000000000001400523266500146345ustar00rootroot00000000000000smenu-0.9.17/build-aux/config.guess000077500000000000000000001410211400523266500171530ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2020 Free Software Foundation, Inc. timestamp='2020-11-07' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=$(echo "$0" | sed -e 's,.*/,,') usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039 { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$driver" break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else #include #ifdef __DEFINED_va_list LIBC=musl #else LIBC=gnu #endif #endif EOF eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" ;; esac case "${UNAME_MACHINE}" in i?86) test -z "$VENDOR" && VENDOR=pc ;; *) test -z "$VENDOR" && VENDOR=unknown ;; esac test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse test -f /etc/os-release && grep -q suse /etc/os-release && VENDOR=suse # Note: order is significant - the case branches are not exclusive. case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)) case "$UNAME_MACHINE_ARCH" in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') machine="${arch}${endian}"-unknown ;; *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') echo "$UNAME_MACHINE_ARCH"-${VENDOR}-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') echo "$UNAME_MACHINE_ARCH"-${VENDOR}-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') echo "$UNAME_MACHINE_ARCH"-${VENDOR}-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-${VENDOR}-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) echo "$UNAME_MACHINE"-${VENDOR}-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) echo "$UNAME_MACHINE"-${VENDOR}-solidbsd"$UNAME_RELEASE" exit ;; *:OS108:*:*) echo "$UNAME_MACHINE"-${VENDOR}-os108_"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) echo powerpc-${VENDOR}-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) echo "$UNAME_MACHINE"-${VENDOR}-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-${VENDOR}-sortix exit ;; *:Twizzler:*:*) echo "$UNAME_MACHINE"-${VENDOR}-twizzler exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-${VENDOR}-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') ;; *5.*) UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-${VENDOR}-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-${VENDOR}-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-${VENDOR}-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-${VENDOR}-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "$( (/bin/universe) 2>/dev/null)" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case $(/usr/bin/uname -p) in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-${VENDOR}-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo "$SUN_ARCH"-${VENDOR}-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; sun4*:SunOS:*:*) case "$(/usr/bin/arch -k)" in Series*|S4*) UNAME_RELEASE=$(uname -v) ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')" exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "$(/bin/arch)" in sun3) echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-${VENDOR}-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && SYSTEM_NAME=$("$dummy" "$dummyarg") && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=$(/usr/bin/uname -p) if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then echo m88k-dg-dgux"$UNAME_RELEASE" else echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=$(/usr/bin/oslevel) else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') case "$UNAME_MACHINE" in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then echo "$UNAME_MACHINE"-${VENDOR}-osf1mk else echo "$UNAME_MACHINE"-${VENDOR}-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo "$UNAME_MACHINE"-${VENDOR}-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) echo sparc-${VENDOR}-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) echo "$UNAME_MACHINE"-${VENDOR}-bsdi"$UNAME_RELEASE" exit ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=$(uname -p) set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "${UNAME_PROCESSOR}"-${VENDOR}-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi else echo "${UNAME_PROCESSOR}"-${VENDOR}-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf fi exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=$(/usr/bin/uname -p) case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo "$UNAME_PROCESSOR"-${VENDOR}-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" exit ;; i*:CYGWIN*:*) echo "$UNAME_MACHINE"-${VENDOR}-cygwin exit ;; *:MINGW64*:*) echo "$UNAME_MACHINE"-${VENDOR}-mingw64 exit ;; *:MINGW*:*) echo "$UNAME_MACHINE"-${VENDOR}-mingw32 exit ;; *:MSYS*:*) echo "$UNAME_MACHINE"-${VENDOR}-msys exit ;; i*:PW*:*) echo "$UNAME_MACHINE"-${VENDOR}-pw32 exit ;; *:Interix*:*) case "$UNAME_MACHINE" in x86) echo i586-${VENDOR}-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) echo x86_64-${VENDOR}-interix"$UNAME_RELEASE" exit ;; IA64) echo ia64-${VENDOR}-interix"$UNAME_RELEASE" exit ;; esac ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-${VENDOR}-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-${VENDOR}-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-${VENDOR}-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; *:GNU:*:*) # the GNU system echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-${VENDOR}-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo "$UNAME_MACHINE-${VENDOR}-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC" exit ;; *:Minix:*:*) echo "$UNAME_MACHINE"-${VENDOR}-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; alpha:Linux:*:*) case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC"eabi else echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; cris:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; hexagon:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; ia64:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; k1om:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; m32r*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; m68*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-${VENDOR}-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) echo or1k-${VENDOR}-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; padre:Linux:*:*) echo sparc-${VENDOR}-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-${VENDOR}-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in PA7*) echo hppa1.1-${VENDOR}-linux-"$LIBC" ;; PA8*) echo hppa2.0-${VENDOR}-linux-"$LIBC" ;; *) echo hppa-${VENDOR}-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-${VENDOR}-linux-"$LIBC" exit ;; ppc:Linux:*:*) echo powerpc-${VENDOR}-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) echo powerpc64le-${VENDOR}-linux-"$LIBC" exit ;; ppcle:Linux:*:*) echo powerpcle-${VENDOR}-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; sh*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; tile*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; vax:Linux:*:*) echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then LIBCABI="$LIBC"x32 fi fi echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBCABI" exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-${VENDOR}-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo "$UNAME_MACHINE"-${VENDOR}-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo "$UNAME_MACHINE"-${VENDOR}-os2-emx exit ;; i*86:XTS-300:*:STOP) echo "$UNAME_MACHINE"-${VENDOR}-stop exit ;; i*86:atheos:*:*) echo "$UNAME_MACHINE"-${VENDOR}-atheos exit ;; i*86:syllable:*:*) echo "$UNAME_MACHINE"-${VENDOR}-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-${VENDOR}-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) echo "$UNAME_MACHINE"-${VENDOR}-msdosdjgpp exit ;; i*86:*:4.*:*) UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else echo "$UNAME_MACHINE"-${VENDOR}-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case $(/bin/uname -X | grep "^Machine") in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo "$UNAME_MACHINE-${VENDOR}-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //')) (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo "$UNAME_MACHINE"-${VENDOR}-sco"$UNAME_REL" else echo "$UNAME_MACHINE"-${VENDOR}-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-${VENDOR}-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-${VENDOR}-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-${VENDOR}-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-${VENDOR}-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-${VENDOR}-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) echo rs6000-${VENDOR}-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-${VENDOR}-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=$( (uname -p) 2>/dev/null) echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then echo mips-nec-sysv"$UNAME_RELEASE" else echo mips-${VENDOR}-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-${VENDOR}-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-${VENDOR}-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-${VENDOR}-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; arm64:Darwin:*:*) echo aarch64-apple-darwin"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=$(uname -p) case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=$(uname -p) if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-${VENDOR}-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo "$UNAME_MACHINE"-${VENDOR}-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-${VENDOR}-tops10 exit ;; *:TENEX:*:*) echo pdp10-${VENDOR}-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-${VENDOR}-tops20 exit ;; *:ITS:*:*) echo pdp10-${VENDOR}-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) echo "$UNAME_MACHINE"-${VENDOR}-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" exit ;; *:*VMS:*:*) UNAME_MACHINE=$( (uname -p) 2>/dev/null) case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-${VENDOR}-xenix exit ;; i*86:skyos:*:*) echo "$UNAME_MACHINE"-${VENDOR}-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" exit ;; i*86:rdos:*:*) echo "$UNAME_MACHINE"-${VENDOR}-rdos exit ;; i*86:AROS:*:*) echo "$UNAME_MACHINE"-${VENDOR}-aros exit ;; x86_64:VMkernel:*:*) echo "$UNAME_MACHINE"-${VENDOR}-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-${VENDOR}-onefs exit ;; *:Unleashed:*:*) echo "$UNAME_MACHINE"-${VENDOR}-unleashed"$UNAME_RELEASE" exit ;; esac # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown) uname -r = $( (uname -r) 2>/dev/null || echo unknown) uname -s = $( (uname -s) 2>/dev/null || echo unknown) uname -v = $( (uname -v) 2>/dev/null || echo unknown) /usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) /bin/uname -X = $( (/bin/uname -X) 2>/dev/null) hostinfo = $( (hostinfo) 2>/dev/null) /bin/universe = $( (/bin/universe) 2>/dev/null) /usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) /bin/arch = $( (/bin/arch) 2>/dev/null) /usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) /usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: smenu-0.9.17/build-aux/config.sub000077500000000000000000001026441400523266500166260ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2020 Free Software Foundation, Inc. timestamp='2020-11-07' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=$(echo "$0" | sed -e 's,.*/,,') usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv4 ;; i*86v) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv ;; i*86sol2) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=$(echo "$basic_machine" | sed 's/-.*//') ;; *-*) # shellcheck disable=SC2162 IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc caes, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') ;; os2-emx) kernel=os2 os=$(echo $basic_os | sed -e 's|os2-emx|emx|') ;; nto-qnx*) kernel=nto os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') ;; *-*) # shellcheck disable=SC2162 IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; -dietlibc* | -newlib* | -musl* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: smenu-0.9.17/build-aux/depcomp000077500000000000000000000560201400523266500162140ustar00rootroot00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: smenu-0.9.17/build-aux/install-sh000077500000000000000000000357761400523266500166620ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: smenu-0.9.17/build-aux/missing000077500000000000000000000153361400523266500162430ustar00rootroot00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: smenu-0.9.17/build.sh000077500000000000000000000012111400523266500143730ustar00rootroot00000000000000#!/bin/sh # Manage --help option # """""""""""""""""""" if echo "$@" | grep -- "--help"; then ./configure --help | sed s/configure/build.sh/g exit 1 fi # Ensure that aclocal wont' be called # """"""""""""""""""""""""""""""""""" touch aclocal.m4 touch Makefile.in configure config.h.in # Create the Makefile # """"""""""""""""""" ./configure "$@" # Add the git version if this is a git clone # """""""""""""""""""""""""""""""""""""""""" [ -d .git ] && V=`git log -1 --pretty=format:-%h` || V="" sed "/VERSION/s/\$/ \"$V\"/" config.h > /tmp/config.h$$ mv /tmp/config.h$$ config.h # Create the executable # """"""""""""""""""""" make exit 0 smenu-0.9.17/config.h.in000066400000000000000000000102541400523266500147670ustar00rootroot00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LANGINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the `mblen' function. */ #undef HAVE_MBLEN /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `nl_langinfo' function. */ #undef HAVE_NL_LANGINFO /* Define to 1 if you have the `pathconf' function. */ #undef HAVE_PATHCONF /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #undef HAVE_REALLOC /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strspn' function. */ #undef HAVE_STRSPN /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc /* Define to `unsigned int' if does not define. */ #undef size_t smenu-0.9.17/configure000077500000000000000000005703661400523266500146720ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for smenu 0.9.17. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: p.gen.progs@gmail.com about your system, including any $0: error possibly output before this message. Then install $0: a modern shell, or manually run the script under such a $0: shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='smenu' PACKAGE_TARNAME='smenu' PACKAGE_VERSION='0.9.17' PACKAGE_STRING='smenu 0.9.17' PACKAGE_BUGREPORT='p.gen.progs@gmail.com' PACKAGE_URL='' ac_unique_file="smenu.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBOBJS LN_S EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures smenu 0.9.17 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/smenu] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of smenu 0.9.17:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF smenu configure 0.9.17 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------ ## ## Report this to p.gen.progs@gmail.com ## ## ------------------------------------ ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by smenu $as_me 0.9.17, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" ac_aux_dir= for ac_dir in build-aux "$srcdir"/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='smenu' VERSION='0.9.17' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' # Checks for programs. DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 $as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 $as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done case $ac_cv_prog_cc_stdc in #( no) : ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 else ac_cv_prog_cc_stdc=no fi fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 $as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } if ${ac_cv_prog_cc_stdc+:} false; then : $as_echo_n "(cached) " >&6 fi case $ac_cv_prog_cc_stdc in #( no) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; #( '') : { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 $as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5 $as_echo_n "checking for library containing tgetent... " >&6; } if ${ac_cv_search_tgetent+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char tgetent (); int main () { return tgetent (); ; return 0; } _ACEOF for ac_lib in '' tinfo curses ncursesw ncurses; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_tgetent=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_tgetent+:} false; then : break fi done if ${ac_cv_search_tgetent+:} false; then : else ac_cv_search_tgetent=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_tgetent" >&5 $as_echo "$ac_cv_search_tgetent" >&6; } ac_res=$ac_cv_search_tgetent if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" HAVE_CURSES=True fi # Checks for libraries. # Checks for header files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in fcntl.h limits.h langinfo.h locale.h stdint.h stdlib.h \ string.h sys/ioctl.h sys/time.h termios.h unistd.h wchar.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi # Checks for library functions. for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi for ac_func in mblen memset nl_langinfo pathconf regcomp setlocale do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strchr strrchr strspn strcasecmp strdup strndup do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # OS-specific tests case "${host_os}" in *freebsd*|*dragonfly*) CPPFLAGS="-D__BSD_VISIBLE $CPPFLAGS" ;; *darwin*) CPPFLAGS="-D_DARWIN_C_SOURCE $CPPFLAGS" ;; *netbsd*) CPPFLAGS="-D_NETBSD_SOURCE $CPPFLAGS" ;; *openbsd*|*bitrig*) CPPFLAGS="-D_BSD_SOURCE $CPPFLAGS" ;; esac ac_config_files="$ac_config_files Makefile" ac_config_files="$ac_config_files smenu.spec" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by smenu $as_me 0.9.17, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ smenu config.status 0.9.17 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "smenu.spec") CONFIG_FILES="$CONFIG_FILES smenu.spec" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi smenu-0.9.17/configure.ac000066400000000000000000000027401400523266500152330ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. m4_define(my_version, [m4_esyscmd([tr -d '\n' < version])]) AC_PREREQ([2.69]) AC_INIT([smenu], [my_version], [p.gen.progs@gmail.com]) AC_CONFIG_SRCDIR([smenu.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([no-dist-gzip dist-bzip2 foreign -Wall]) AM_SILENT_RULES([yes]) # Checks for programs. AC_USE_SYSTEM_EXTENSIONS AC_PROG_AWK AC_PROG_CC_STDC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_SEARCH_LIBS([tgetent], [tinfo curses ncursesw ncurses], [HAVE_CURSES=True]) # Checks for libraries. # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([fcntl.h limits.h langinfo.h locale.h stdint.h stdlib.h \ string.h sys/ioctl.h sys/time.h termios.h unistd.h wchar.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([mblen memset nl_langinfo pathconf regcomp setlocale]) AC_CHECK_FUNCS([strchr strrchr strspn strcasecmp strdup strndup]) AC_CANONICAL_HOST # OS-specific tests case "${host_os}" in *freebsd*|*dragonfly*) CPPFLAGS="-D__BSD_VISIBLE $CPPFLAGS" ;; *darwin*) CPPFLAGS="-D_DARWIN_C_SOURCE $CPPFLAGS" ;; *netbsd*) CPPFLAGS="-D_NETBSD_SOURCE $CPPFLAGS" ;; *openbsd*|*bitrig*) CPPFLAGS="-D_BSD_SOURCE $CPPFLAGS" ;; esac AC_CONFIG_FILES([Makefile]) AC_OUTPUT([smenu.spec]) smenu-0.9.17/ctxopt.c000066400000000000000000004467401400523266500144460ustar00rootroot00000000000000/* ################################################################### */ /* This Source Code Form is subject to the terms of the Mozilla Public */ /* License, v. 2.0. If a copy of the MPL was not distributed with this */ /* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* ################################################################### */ #include #include #include #include #include #include #include #include #include #include #include "ctxopt.h" /* ************************ */ /* Static global variables. */ /* ************************ */ static void * contexts_bst; static void * options_bst; state_t * cur_state; /* Prototypes */ /* ************************** */ /* Fatal messages prototypes. */ /* ************************** */ static void (**err_functions)(errors e, state_t * state); static void fatal_internal(const char * format, ...); static void fatal(errors e, char * errmsg); static int user_rc; /* Used by various callback functions. */ static int user_value; /* Used by various callback functions. */ static char * user_string; /* Used by various callback functions. */ static char * user_string2; /* Used by various callback functions. */ static void * user_object; /* Used by various callback functions. */ /* ************************************ */ /* Memory management static prototypes. */ /* ************************************ */ static void * xmalloc(size_t size); static void * xcalloc(size_t num, size_t size); static void * xrealloc(void * ptr, size_t size); static char * xstrdup(const char * p); static char * xstrndup(const char * str, size_t len); /* ********************** */ /* BST static prototypes. */ /* ********************** */ typedef struct bst_s bst_t; typedef enum { preorder, postorder, endorder, leaf } walk_order_e; #if 0 /* Unused yet. */ static void * bst_delete(const void * vkey, void ** vrootp, int (*compar)(const void *, const void *)); #endif static void bst_destroy(void * vrootp, void (*clean)(void *)); static void * bst_find(const void * vkey, void * const * vrootp, int (*compar)(const void *, const void *)); static void * bst_search(void * vkey, void ** vrootp, int (*compar)(const void *, const void *)); static void bst_walk_recurse(const bst_t * root, void (*action)(const void *, walk_order_e, int), int level); static void bst_walk(const void * vroot, void (*action)(const void *, walk_order_e, int)); /* ****************************** */ /* Linked list static prototypes. */ /* ****************************** */ typedef struct ll_node_s ll_node_t; typedef struct ll_s ll_t; static void ll_append(ll_t * const list, void * const data); static void ll_prepend(ll_t * const list, void * const data); static void ll_insert_after(ll_t * const list, ll_node_t * node, void * const data); static void ll_insert_before(ll_t * const list, ll_node_t * node, void * const data); static int ll_delete(ll_t * const list, ll_node_t * node); #if 0 /* Unused yet. */ static ll_node_t * ll_find(ll_t * const, void * const, int (*)(const void *, const void *)); #endif static void ll_init(ll_t * list); static ll_node_t * ll_new_node(void); static ll_t * ll_new(void); static void ll_free(ll_t * const list, void (*)(void *)); static void ll_destroy(ll_t * const list, void (*)(void *)); static int ll_strarray(ll_t * list, ll_node_t * start_node, int * count, char *** array); /* ************************** */ /* Various static prototypes. */ /* ************************** */ static void ltrim(char * str, const char * trim_str); static void rtrim(char * str, const char * trim_str, size_t min); static int strchrcount(char * str, char c); static int strpref(char * s1, char * s2); static int stricmp(const char * s1, const char * s2); static char * xstrtok_r(char * str, const char * delim, char ** end); static int eval_yes(char * value, int * invalid); static char * get_word(char * str, char * buf, size_t len); /* ************************* */ /* ctxopt static prototypes. */ /* ************************* */ typedef struct flags_s flags_t; typedef struct opt_s opt_t; typedef struct par_s par_t; typedef struct ctx_s ctx_t; typedef struct constraint_s constraint_t; typedef struct ctx_inst_s ctx_inst_t; typedef struct opt_inst_s opt_inst_t; typedef struct seen_opt_s seen_opt_t; typedef struct req_s req_t; static char * strtoken(char * s, char * token, size_t tok_len, char * pattern, int * pos); static int ctx_compare(const void * c1, const void * c2); static void ctx_free(void * o); static void ctx_inst_free(void * ci); static void opt_inst_free(void * oi); static int seen_opt_compare(const void * so1, const void * so2); static void incomp_bst_free(void * b); static void req_free(void * r); static void seen_opt_free(void * seen_opt); static int opt_compare(const void * o1, const void * o2); static void opt_free(void * o); static int par_compare(const void * a1, const void * a2); static void par_free(void * p); static void constraint_free(void * cstr); static ctx_t * locate_ctx(char * name); static opt_t * locate_opt(char * name); static par_t * locate_par(char * name, ctx_t * ctx); static void print_before_constraints(ll_t * list); static void print_options(ll_t * list, int * has_optional, int * has_ellipsis, int * has_rule, int * has_generic_arg, int * has_ctx_change, int * has_early_eval); static void print_explanations(int has_early_eval, int has_ctx_change, int has_generic_arg, int has_optional, int has_ellipsis, int has_rule); static void bst_seen_opt_cb(const void * node, walk_order_e kind, int level); static void bst_seen_opt_seen_cb(const void * node, walk_order_e kind, int level); static void bst_print_ctx_cb(const void * node, walk_order_e kind, int level); static void bst_check_opt_cb(const void * node, walk_order_e kind, int level); static void bst_match_par_cb(const void * node, walk_order_e kind, int level); static void match_prefix_cb(const void * node, walk_order_e kind, int level); static int has_unseen_mandatory_opt(ctx_inst_t * ctx_inst, char ** missing); static int opt_parse(char * s, opt_t ** opt); static int init_opts(char * spec, ctx_t * ctx); static int ctxopt_build_cmdline_list(int nb_words, char ** words); static int opt_set_parms(char * opt_name, char * par_str); static ctx_inst_t * new_ctx_inst(ctx_t * ctx, ctx_inst_t * prev_ctx_inst); static void evaluate_ctx_inst(ctx_inst_t * ctx_inst); /* ****************************** */ /* Fatal messages implementation. */ /* ****************************** */ /* =================================================================== */ /* Fatal error function used when a fatal condition is encountered. */ /* This function is reserved for the ctxopt internal usage. */ /* */ /* format : printf like format. */ /* ... : remaining arguments interpreted using the format argument. */ /* =================================================================== */ static void fatal_internal(const char * format, ...) { va_list args; fprintf(stderr, "CTXOPT: "); va_start(args, format); vfprintf(stderr, format, args); fprintf(stderr, "\n"); va_end(args); exit(EXIT_FAILURE); } /* ====================================================================== */ /* Generic fatal error function. This one uses the global status ctxopt */ /* stored in the cur_state structure and can call custom error functions. */ /* registered by the users for a given error identifier if any. */ /* */ /* e : Error identifier responsible of the fatal error. */ /* errmsg : Users's provided string specific to the error e. */ /* Note that errmsg is not used in all cases. */ /* */ /* CTXOPTMISPAR Missing parameter. */ /* CTXOPTREQPAR Option: all parameters in a required group are */ /* missing. */ /* CTXOPTMISARG Missing argument. */ /* CTXOPTUXPARG Unexpected argument. */ /* CTXOPTDUPOPT Duplicated option. */ /* CTXOPTUNKPAR Unknown parameter. */ /* CTXOPTINCOPT Incompatible option. */ /* CTXOPTCTEOPT Option: bad number of occurrences. */ /* CTXOPTCTLOPT Option: not enough occurrences. */ /* CTXOPTCTGOPT Option: too many occurrence of. */ /* CTXOPTCTEARG Arguments: bad number of occurrences. */ /* CTXOPTCTLARG Arguments: not enough occurrences. */ /* CTXOPTCTGARG Arguments: too many occurrences. */ /* ====================================================================== */ static void fatal(errors e, char * errmsg) { if (err_functions[e] != NULL) err_functions[e](e, cur_state); else { switch (e) { case CTXOPTNOERR: break; case CTXOPTMISPAR: if (cur_state->ctx_par_name != NULL) fprintf(stderr, "the mandatory parameter(s) %s are missing in the context " "introduced by %s.\n", errmsg, cur_state->ctx_par_name); else fprintf(stderr, "The mandatory parameter(s) %s are missing " "in the main context.\n", errmsg); free(errmsg); break; case CTXOPTREQPAR: fprintf(stderr, errmsg, cur_state->req_opt_par_needed, cur_state->req_opt_par); break; case CTXOPTUNXARG: if (cur_state->cur_opt_par_name != NULL) fprintf(stderr, "The parameter %s takes no arguments " "or has too many arguments.\n", cur_state->cur_opt_par_name); break; case CTXOPTMISARG: if (cur_state->pre_opt_par_name != NULL) fprintf(stderr, "%s requires argument(s).\n", cur_state->pre_opt_par_name); else fprintf(stderr, "%s requires argument(s).\n", cur_state->cur_opt_par_name); break; case CTXOPTDUPOPT: if (cur_state->pre_opt_par_name != NULL) fprintf(stderr, "The parameter %s can only appear once in the context " "introduced by %s.\n", cur_state->cur_opt_params, cur_state->ctx_par_name); else fprintf(stderr, "The parameter %s can only appear once " "in the main context.\n", cur_state->cur_opt_params); break; case CTXOPTUNKPAR: fprintf(stderr, "Unknown parameter %s.\n%s", cur_state->cur_opt_par_name, errmsg); break; case CTXOPTINCOPT: fprintf(stderr, "The parameter %s is incompatible with %s.\n", cur_state->cur_opt_par_name, errmsg); break; case CTXOPTCTEOPT: if (cur_state->ctx_par_name) fprintf(stderr, "The parameter %s must appear exactly %d times " "in the context introduced by %s.\n", cur_state->cur_opt_params, cur_state->opts_count, cur_state->ctx_par_name); else fprintf(stderr, "The parameter %s must appear exactly %d times " "in the main context.\n", cur_state->cur_opt_params, cur_state->opts_count); break; case CTXOPTCTLOPT: if (cur_state->ctx_par_name) fprintf(stderr, "The parameter %s must appear less than %d times " "in the context introduced by %s.\n", cur_state->cur_opt_params, cur_state->opts_count, cur_state->ctx_par_name); else fprintf(stderr, "The parameter %s must appear less than %d times " "in the main context.\n", cur_state->cur_opt_params, cur_state->opts_count); break; case CTXOPTCTGOPT: if (cur_state->ctx_par_name) fprintf(stderr, "The parameter %s must appear more than %d times " "in the context introduced by %s.\n", cur_state->cur_opt_params, cur_state->opts_count, cur_state->ctx_par_name); else fprintf(stderr, "The parameter %s must appear more than %d times " "in the main context.\n", cur_state->cur_opt_params, cur_state->opts_count); break; case CTXOPTCTEARG: fprintf(stderr, "The parameter %s must have exactly %d arguments.\n", cur_state->cur_opt_par_name, cur_state->opt_args_count); break; case CTXOPTCTLARG: fprintf(stderr, "The parameter %s must have less than %d arguments.\n", cur_state->cur_opt_par_name, cur_state->opt_args_count); break; case CTXOPTCTGARG: fprintf(stderr, "The parameter %s must have more than %d arguments.\n", cur_state->cur_opt_par_name, cur_state->opt_args_count); break; case CTXOPTERRSIZ: break; } } /* CTXOPTUNKPAR should display the full usage to help the user follow */ /* the chaining of contexts when several possible contexts have been */ /* identified. Otherwise, errmsg is the empty string and the display of */ /* the current usage is enough. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (e == CTXOPTUNKPAR && *errmsg != '\0') ctxopt_disp_usage(continue_after); else ctxopt_ctx_disp_usage(cur_state->ctx_name, continue_after); exit(e); /* Exit with the error id e as return code. */ } /* ********************************* */ /* Memory management implementation. */ /* ********************************* */ /* ================== */ /* Customized malloc. */ /* ================== */ static void * xmalloc(size_t size) { void * allocated; size_t real_size; real_size = (size > 0) ? size : 1; allocated = malloc(real_size); if (allocated == NULL) fatal_internal("Insufficient memory (attempt to malloc %lu bytes).\n", (unsigned long int)size); return allocated; } /* ================== */ /* Customized calloc. */ /* ================== */ static void * xcalloc(size_t n, size_t size) { void * allocated; n = (n > 0) ? n : 1; size = (size > 0) ? size : 1; allocated = calloc(n, size); if (allocated == NULL) fatal_internal("Insufficient memory (attempt to calloc %lu bytes).\n", (unsigned long int)size); return allocated; } /* =================== */ /* Customized realloc. */ /* =================== */ static void * xrealloc(void * p, size_t size) { void * allocated; allocated = realloc(p, size); if (allocated == NULL && size > 0) fatal_internal("Insufficient memory (attempt to xrealloc %lu bytes).\n", (unsigned long int)size); return allocated; } /* ==================================== */ /* strdup implementation using xmalloc. */ /* ==================================== */ static char * xstrdup(const char * p) { char * allocated; allocated = xmalloc(strlen(p) + 1); strcpy(allocated, p); return allocated; } /* =================================================== */ /* strndup implementation using xmalloc. */ /* This version guarantees that there is a final '\0'. */ /* =================================================== */ static char * xstrndup(const char * str, size_t len) { char * p; p = memchr(str, '\0', len); if (p) len = p - str; p = xmalloc(len + 1); memcpy(p, str, len); p[len] = '\0'; return p; } /* *************************** */ /* Linked list implementation. */ /* *************************** */ /* Linked list node structure. */ /* """"""""""""""""""""""""""" */ struct ll_node_s { void * data; struct ll_node_s * next; struct ll_node_s * prev; }; /* Linked List structure. */ /* """""""""""""""""""""" */ struct ll_s { ll_node_t * head; ll_node_t * tail; long len; }; /* ========================= */ /* Create a new linked list. */ /* ========================= */ static ll_t * ll_new(void) { ll_t * ret = xmalloc(sizeof(ll_t)); ll_init(ret); return ret; } /* =============================================== */ /* Free all the elements of a list (make it empty) */ /* NULL or a custom function may be used to free */ /* the sub components of the elements. */ /* =============================================== */ static void ll_free(ll_t * const list, void (*clean)(void *)) { if (list) while (list->head) { /* Apply a custom cleaner if not NULL. */ /* """"""""""""""""""""""""""""""""""" */ if (clean) clean(list->head->data); ll_delete(list, list->head); } } /* ==================================== */ /* Destroy a list and all its elements. */ /* ==================================== */ static void ll_destroy(ll_t * list, void (*clean)(void *)) { if (list) { ll_free(list, clean); free(list); } } /* ========================= */ /* Initialize a linked list. */ /* ========================= */ static void ll_init(ll_t * list) { list->head = NULL; list->tail = NULL; list->len = 0; } /* ===================================================== */ /* Allocate the space for a new node in the linked list. */ /* ===================================================== */ static ll_node_t * ll_new_node(void) { ll_node_t * ret = xmalloc(sizeof(ll_node_t)); return ret; } /* ==================================================================== */ /* Append a new node filled with its data at the end of the linked list */ /* The user is responsible for the memory management of the data. */ /* ==================================================================== */ static void ll_append(ll_t * const list, void * const data) { ll_node_t * node; node = ll_new_node(); /* ll_new_node cannot return NULL because it * | uses xmalloc which does not return if there * | is an allocation error. */ node->data = data; node->next = NULL; node->prev = list->tail; if (list->tail) list->tail->next = node; else list->head = node; list->tail = node; ++list->len; } /* ================================================================== */ /* Put a new node filled with its data at the beginning of the linked */ /* list. */ /* The user is responsible for the memory management of the data. */ /* ================================================================== */ static void ll_prepend(ll_t * const list, void * const data) { ll_node_t * node; node = ll_new_node(); /* ll_new_node cannot return NULL because it * | uses xmalloc which does not return if there * | is an allocation error. */ node->data = data; node->prev = NULL; node->next = list->head; if (list->head) list->head->prev = node; else list->tail = node; list->head = node; ++list->len; } /* ======================================================== */ /* Insert a new node before the specified node in the list. */ /* ======================================================== */ static void ll_insert_before(ll_t * const list, ll_node_t * node, void * const data) { ll_node_t * new_node; if (node->prev == NULL) ll_prepend(list, data); else { new_node = ll_new_node(); /* ll_new_node cannot return NULL because it * | uses xmalloc which does not return if there * | is an allocation error. */ new_node->data = data; new_node->next = node; new_node->prev = node->prev; node->prev->next = new_node; node->prev = new_node; ++list->len; } } /* ======================================================= */ /* Insert a new node after the specified node in the list. */ /* ======================================================= */ static void ll_insert_after(ll_t * const list, ll_node_t * node, void * const data) { ll_node_t * new_node; if (node->next == NULL) ll_append(list, data); else { new_node = ll_new_node(); /* ll_new_node cannot return NULL because it * | uses xmalloc which does not return if there * | is an allocation error. */ new_node->data = data; new_node->prev = node; new_node->next = node->next; node->next->prev = new_node; node->next = new_node; ++list->len; } } /* ================================================================= */ /* Remove a node from a linked list. */ /* The memory taken by the deleted node must be freed by the caller. */ /* ================================================================= */ static int ll_delete(ll_t * const list, ll_node_t * node) { if (list->head == list->tail) { if (list->head != NULL) list->head = list->tail = NULL; else return 0; } else if (node->prev == NULL) { list->head = node->next; list->head->prev = NULL; } else if (node->next == NULL) { list->tail = node->prev; list->tail->next = NULL; } else { node->next->prev = node->prev; node->prev->next = node->next; } --list->len; free(node); return 1; } #if 0 /* Unused yet */ /* ======================================================================== */ /* Find a node in the list containing data. Return the node pointer or NULL */ /* if not found. */ /* A comparison function must be provided to compare a and b (strcmp like). */ /* ======================================================================== */ static ll_node_t * ll_find(ll_t * const list, void * const data, int (*cmpfunc)(const void * a, const void * b)) { ll_node_t * node; if (NULL == (node = list->head)) return NULL; do { if (0 == cmpfunc(node->data, data)) return node; } while (NULL != (node = node->next)); return NULL; } #endif /* ==================================================================== */ /* Allocate and fill an array of strings from a list. */ /* WARNINGS: */ /* 1) The list node must contain strings (char *). */ /* 2) The strings in the resulting array MUST NOT be freed as the are */ /* NOT copied from the strings of the list. */ /* */ /* IN list : The list from which the array is generated. */ /* IN start_node : The node of the list which will be the first node to */ /* consider to create the array. */ /* OUT: count : The number of elements of the resulting array. */ /* OUT: array : The resulting array or NULL if the list is empty. */ /* RC : : The number of elements of the resulting array. */ /* ==================================================================== */ static int ll_strarray(ll_t * list, ll_node_t * start_node, int * count, char *** array) { int n = 0; ll_node_t * node; *count = 0; node = start_node; if (list == NULL || node == NULL) { *array = NULL; return 0; } *array = xmalloc((list->len + 1) * sizeof(char *)); while (node != NULL) { (*array)[n++] = (char *)(node->data); (*count)++; node = node->next; } (*array)[*count] = NULL; return *count; } /* ******************************************************************* */ /* BST (search.h compatible) implementation. */ /* */ /* Tree search generalized from Knuth (6.2.2) Algorithm T just like */ /* the AT&T man page says. */ /* */ /* Written by reading the System V Interface Definition, not the code. */ /* */ /* Totally public domain. */ /* ******************************************************************* */ struct bst_s { void * key; struct bst_s * llink; struct bst_s * rlink; }; #if 0 /* Unused yet. */ /* =========================== */ /* Delete node with given key. */ /* =========================== */ static void * bst_delete(const void * vkey, void ** vrootp, int (*compar)(const void *, const void *)) { bst_t ** rootp = (bst_t **)vrootp; bst_t * p, *q, *r; int cmp; if (rootp == NULL || (p = *rootp) == NULL) return NULL; while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) { p = *rootp; rootp = (cmp < 0) ? &(*rootp)->llink /* follow llink branch */ : &(*rootp)->rlink; /* follow rlink branch */ if (*rootp == NULL) return NULL; /* key not found */ } r = (*rootp)->rlink; /* D1: */ if ((q = (*rootp)->llink) == NULL) /* Left NULL? */ q = r; else if (r != NULL) { /* Right link is NULL? */ if (r->llink == NULL) { /* D2: Find successor */ r->llink = q; q = r; } else { /* D3: Find NULL link */ for (q = r->llink; q->llink != NULL; q = r->llink) r = q; r->llink = q->rlink; q->llink = (*rootp)->llink; q->rlink = (*rootp)->rlink; } } if (p != *rootp) free(*rootp); /* D4: Free node */ *rootp = q; /* link parent to new node */ return p; } #endif /* ===================================================================== */ /* Destroy a tree. */ /* The clean function pointer can be NULL, in this case the node content */ /* is not freed. */ /* ===================================================================== */ static void bst_destroy(void * vrootp, void (*clean)(void *)) { bst_t * root = (bst_t *)vrootp; if (root == NULL) return; bst_destroy(root->llink, clean); bst_destroy(root->rlink, clean); if (clean) clean((void *)root->key); free(root); } /* ========================= */ /* Find a node, or return 0. */ /* ========================= */ static void * bst_find(const void * vkey, void * const * vrootp, int (*compar)(const void *, const void *)) { bst_t * const * rootp = (bst_t * const *)vrootp; if (rootp == NULL) return NULL; while (*rootp != NULL) { /* T1: */ int r; if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ return *rootp; /* key found */ rootp = (r < 0) ? &(*rootp)->llink /* T3: follow left branch */ : &(*rootp)->rlink; /* T4: follow right branch */ } return NULL; } /* ======================================= */ /* Find or inserts datum into search tree. */ /* ======================================= */ static void * bst_search(void * vkey, void ** vrootp, int (*compar)(const void *, const void *)) { bst_t * q; bst_t ** rootp = (bst_t **)vrootp; if (rootp == NULL) return NULL; while (*rootp != NULL) { /* Knuth's T1: */ int r; if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ return *rootp; /* we found it! */ rootp = (r < 0) ? &(*rootp)->llink /* T3: follow left branch */ : &(*rootp)->rlink; /* T4: follow right branch */ } q = xmalloc(sizeof(bst_t)); /* T5: key not found */ if (q != 0) { /* make new node */ *rootp = q; /* link new node to old */ q->key = vkey; /* initialize new node */ q->llink = q->rlink = NULL; } return q; } /* ========================= */ /* Walk the nodes of a tree. */ /* ========================= */ static void bst_walk_recurse(const bst_t * root, void (*action)(const void *, walk_order_e, int), int level) { if (root->llink == NULL && root->rlink == NULL) (*action)(root, leaf, level); else { (*action)(root, preorder, level); if (root->llink != NULL) bst_walk_recurse(root->llink, action, level + 1); (*action)(root, postorder, level); if (root->rlink != NULL) bst_walk_recurse(root->rlink, action, level + 1); (*action)(root, endorder, level); } } static void bst_walk(const void * vroot, void (*action)(const void *, walk_order_e, int)) { if (vroot != NULL && action != NULL) bst_walk_recurse(vroot, action, 0); } /* ************************ */ /* Various implementations. */ /* ************************ */ /* ======================== */ /* Trim leading characters. */ /* ======================== */ static void ltrim(char * str, const char * trim_str) { size_t len = strlen(str); size_t begin = strspn(str, trim_str); size_t i; if (begin > 0) for (i = begin; i <= len; ++i) str[i - begin] = str[i]; } /* ================================================= */ /* Trim trailing characters. */ /* The resulting string will have at least min bytes */ /* even if trailing spaces remain. */ /* ================================================= */ static void rtrim(char * str, const char * trim_str, size_t min) { size_t len = strlen(str); while (len > min && strchr(trim_str, str[len - 1])) str[--len] = '\0'; } /* ================================================== */ /* Count the number of occurrences of the character c */ /* in the string str. */ /* The str pointer is assumed to be not NULL. */ /* ================================================== */ static int strchrcount(char * str, char c) { int count = 0; while (*str) if (*str++ == c) count++; return count; } /* =============================================== */ /* Is the string str2 a prefix of the string str1? */ /* =============================================== */ static int strpref(char * str1, char * str2) { while (*str1 != '\0' && *str1 == *str2) { str1++; str2++; } return *str2 == '\0'; } /* ========================== */ /* Like strcmp ignoring case. */ /* ========================== */ static int stricmp(const char * s1, const char * s2) { while (tolower((unsigned char)*s1) == tolower((unsigned char)*s2)) { if (*s1 == '\0') return 0; s1++; s2++; } return (int)tolower((unsigned char)*s1) - (int)tolower((unsigned char)*s2); } /* ====================================================================== */ /* Strings concatenation with dynamic memory allocation. */ /* IN : a variable number of char * arguments with NULL terminating */ /* the sequence. */ /* The first one must have been dynamically allocated and is */ /* mandatory. */ /* */ /* Returns a new allocated string containing the concatenation of all */ /* the arguments. It is the caller's responsibility to free the resulting */ /* string. */ /* ====================================================================== */ static char * strappend(char * str, ...) { size_t l; va_list args; char * s; l = 1 + strlen(str); va_start(args, str); s = va_arg(args, char *); while (s) { l += strlen(s); s = va_arg(args, char *); } va_end(args); str = xrealloc(str, l); va_start(args, str); s = va_arg(args, char *); while (s) { strcat(str, s); s = va_arg(args, char *); } va_end(args); return str; } /* ====================================================================== */ /* Public domain strtok_r() by Charlie Gordon. */ /* from comp.lang.c 9/14/2007 */ /* http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684 */ /* */ /* (Declaration that it's public domain): */ /* http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c */ /* */ /* Also, fixed by Fletcher T. Penney --- added the "return NULL" when */ /* *end == NULL. */ /* ====================================================================== */ static char * xstrtok_r(char * str, const char * delim, char ** end) { char * ret; if (str == NULL) str = *end; if (str == NULL) return NULL; str += strspn(str, delim); if (*str == '\0') return NULL; ret = str; str += strcspn(str, delim); if (*str) *str++ = '\0'; *end = str; return ret; } /* ===================================================================== */ /* Put the first word of str, truncated to len characters, in buf. */ /* Return a pointer in str pointing just after the word. */ /* buf must have been pre-allocated to accept at least len+1 characters. */ /* Note that buf can contains a sting full of spaces is str was not */ /* trimmed before the call. */ /* ===================================================================== */ char * get_word(char * str, char * buf, size_t len) { char * s = str; /* Skip spaces. */ /* """""""""""" */ while (*s && isspace(*s)) s++; /* Set the new string start. */ /* """"""""""""""""""""""""" */ str = s; /* Get the word. */ /*"""""""""""""" */ while (*s && !isspace(*s) && s - str < len) s++; strncpy(buf, str, s - str); buf[s - str] = 0; return s; } /* ==================================================================== */ /* Return 1 is value is "1" or "yes" (ignoring case). */ /* Return 0 is value is "0" or "no" (ignoring case). */ /* If value has another value, then set invalid to 1 and also return 0 */ /* invalid is set to 0 in all the other cases. */ /* ==================================================================== */ static int eval_yes(char * value, int * invalid) { *invalid = 0; if (strcmp(value, "1") == 0 || stricmp(value, "yes") == 0) return 1; else if (strcmp(value, "0") != 0 && stricmp(value, "no") != 0) *invalid = 1; return 0; } /* =========================================================== */ /* Fill an array of strings from the words composing a string. */ /* */ /* str: initial string which will be altered. */ /* args: array of pointers to the start of the words in str. */ /* max: maximum number of words used before giving up. */ /* return: the number of words (<=max). */ /* =========================================================== */ static int str2argv(char * str, char ** args, int max) { int nb_args = 0; while (*str) { if (nb_args >= max) return nb_args; while (*str == ' ' || *str == '\t') *(str++) = '\0'; if (!*str) return nb_args; args[nb_args] = str; nb_args++; while (*str && (*str != ' ') && (*str != '\t')) str++; } return nb_args; } /* ********************** */ /* ctxopt implementation. */ /* ********************** */ static int ctxopt_initialized = 0; /* cap_init has not yet been called. */ /* Flags structure initialized by ctxopt_init. */ /* """"""""""""""""""""""""""""""""""""""""""" */ struct flags_s { int stop_if_non_option; int allow_abbreviations; int display_usage_on_error; }; static flags_t flags = { 0, 1, 1 }; /* Context structure. */ /* """""""""""""""""" */ struct ctx_s { char * name; ll_t * opt_list; /* list of options allowed in this context. */ ll_t * incomp_list; /* list of strings containing incompatible names * | of options separated by spaces or tabs. */ ll_t * req_list; /* list of strings containing an option name and * | all the option names where at least one of * | them is required to be also present. */ int (*action)(char * name, int type, char * new_ctx, int ctx_nb_data, void ** ctx_data); void * par_bst; int nb_data; void ** data; }; /* https://textik.com/#488ce3649b6c60f5 */ /* */ /* +--------------+ */ /* |first_ctx_inst| */ /* +---+----------+ */ /* | */ /* +--v-----+ +--------+ +--------+ +-----+ */ /* +---+-->ctx_inst+------>opt_inst+----->opt_inst+------> ... | */ /* | | +-+------+ +----+---+ +----+---+ +-----+ */ /* | | | | | */ /* | | +-v------+ | | */ /* | +--+ctx_inst<-----------+ | */ /* | +-+------+ | */ /* | | | */ /* | +-v------+ | */ /* +------+ctx_inst<--------------------------+ */ /* +-+------+ */ /* | */ /* +-v---+ */ /* | ... | */ /* +-----+ */ /* Option structure. */ /* """"""""""""""""" */ struct opt_s { char * name; /* option name. */ char * next_ctx; /* new context this option may lead to */ ll_t * ctx_list; /* list of contexts allowing this option. */ char * params; /* string containing all the parameters of * | the option. */ void (*action)( /* The option associated action. */ char * ctx_name, /* context name. */ char * opt_name, /* option name. */ char * par, /* option parameter. */ int nb_args, /* number of arguments. */ char ** args, /* option arguments. */ int nb_opt_data, /* number of option data pointers. */ void ** opt_data, /* option data pointers. */ int nb_ctx_data, /* nb of current context data ptrs. */ void ** ctx_data /* current context data pointers. */ ); int nb_data; /* number of the data pointers passed as argument to action. */ void ** data; /* array of data pointers passed as argument to action. */ int args; /* 1 if this option takes arguments else 0. */ int optional; /* 1 if the option is optional, else 0. */ int multiple; /* 1 if the option can appear more than one time in a * | context, else 0. */ int opt_count_matter; /* 1 if we must restrict the count, else 0. */ int occurrences; /* Number of option occurrences in a context. */ char opt_count_oper; /* <, = or > */ int opt_count_mark; /* Value to be compared to with opt_count_oper. */ char * arg; /* symbolic text after # describing the option argument. */ int optional_args; /* 1 of option is optional else 0. */ int multiple_args; /* 1 is option can appear more than once in a context * | instance. */ int opt_args_count_matter; /* 1 if count is rescticted, else 0. */ char opt_args_count_oper; /* <, = or > */ int opt_args_count_mark; /* Value to be compared to with * | opt_count_oper. */ int eval_first; /* 1 if this option must be evaluated before the options * | without this mark. */ ll_t * eval_before_list; /* List of pointers on options which must be * | evaluated before this option. */ ll_t * constraints_list; /* List of constraint check functions pointers. */ }; /* Context instance structure. */ /* """"""""""""""""""""""""""" */ struct ctx_inst_s { ctx_t * ctx; /* the context whose this is an instance of */ ctx_inst_t * prev_ctx_inst; /* ctx_inst of the opt_inst which led to the * | creation of this ctx_inst structure. */ opt_inst_t * gen_opt_inst; /* opt_inst which led to the creation of a * | instance of this structure. */ ll_t * incomp_bst_list; /* list of seen_opt_t BST. */ void * seen_opt_bst; /* tree of seen_opt_t. */ ll_t * opt_req_list; /* list of req_t. */ ll_t * opt_inst_list; /* The list of option instances in this * | context instance. */ char * par_name; /* parameter which created this instance. */ }; /* Option instance structure. */ /* """""""""""""""""""""""""" */ struct opt_inst_s { opt_t * opt; /* The option this is an instance of. */ char * opt_name; /* The option which led to this creation. */ char * par; /* The parameter which led to this creation. */ ll_t * values_list; /* The list of arguments of this option. */ ctx_inst_t * next_ctx_inst; /* The new context instance this option. * | instance may create. */ }; /* Structure used to check if an option has bee seen or not */ /* in a context instance. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct seen_opt_s { opt_t * opt; /* The concerned option. */ char * par; /* Parameter which led to the making of this structure. */ int seen; /* 1 if seen in the context instances, else 0. */ }; /* Structure used to check if at least one instance of the options whose */ /* pointers are in or_opt_list has been seen in the ctx_inst where an */ /* instance or opt is also present. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct req_s { opt_t * opt; /* Option that asks for other options. */ ll_t * or_opt_list; /* Required options, at least one of them * | must be present. */ }; /* Parameter structure which links a parameter to the option it belongs to. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct par_s { char * name; /* Parameter name (with the leading -). */ opt_t * opt; /* Attached option. */ }; /* Constraint structure. */ /* """"""""""""""""""""" */ struct constraint_s { int (*constraint)(int nb_args, char ** args, char * value, char * parameter); int nb_args; char ** args; char * to_free; /* pointer to the original string in which the array in * | args points to. This poinnter is kept there to allow * | it to be freed. */ }; state_t * cur_state = NULL; /* Current analysis state. */ static ll_t * cmdline_list = NULL; /* List of interpreted CLI words * | serves as the basis for the * | analysis of the parameters. */ static ctx_t * main_ctx = NULL; /* initial context. */ static ctx_inst_t * first_ctx_inst = NULL; /* Pointer to the fist context * | instance which holds the * | options instances. */ static ll_t * ctx_inst_list = NULL; /* List of the context instances. */ /* ======================================================= */ /* Parse a string for the next matching token. */ /* */ /* s: string to parse. */ /* token: pre_allocated array of max tok_len characters. */ /* pattern: scanf type pattern token must match. */ /* pos: number of characters successfully parsed in s. */ /* */ /* Returns: a pointer to the first unread character or */ /* to he terminating \0. */ /* ======================================================= */ static char * strtoken(char * s, char * token, size_t tok_len, char * pattern, int * pos) { char * full_pattern; char len[3]; int n; *pos = 0; n = snprintf(len, 3, "%zu", tok_len); if (n < 0) return NULL; full_pattern = xmalloc(strlen(pattern) + n + 4); strcpy(full_pattern, "%"); strcat(full_pattern, len); strcat(full_pattern, pattern); strcat(full_pattern, "%n"); n = sscanf(s, full_pattern, token, pos); free(full_pattern); if (n != 1) return NULL; return s + *pos; } /* ****************************************** */ /* Various comparison and deletion functions. */ /* ****************************************** */ static int ctx_compare(const void * c1, const void * c2) { return strcmp(((ctx_t *)c1)->name, ((ctx_t *)c2)->name); } /* =========================== */ /* Free a context_bst element. */ /* =========================== */ static void ctx_free(void * c) { ctx_t * ctx = c; free(ctx->name); free(ctx->data); ll_destroy(ctx->opt_list, NULL); ll_destroy(ctx->incomp_list, free); ll_destroy(ctx->req_list, free); bst_destroy(ctx->par_bst, par_free); free(c); } /* ============================= */ /* Free a ctx_inst_list element. */ /* ============================= */ static void ctx_inst_free(void * ci) { ctx_inst_t * ctx_inst = ci; free(ctx_inst->par_name); ll_destroy(ctx_inst->incomp_bst_list, incomp_bst_free); bst_destroy(ctx_inst->seen_opt_bst, seen_opt_free); ll_destroy(ctx_inst->opt_inst_list, opt_inst_free); ll_destroy(ctx_inst->opt_req_list, req_free); free(ci); } /* ============================== */ /* Free an opt_inst_list element. */ /* ============================== */ static void opt_inst_free(void * oi) { opt_inst_t * opt_inst = oi; ll_destroy(opt_inst->values_list, NULL); free(oi); } /* ================================== */ /* Compare two seen_opt_bst elements. */ /* ================================== */ static int seen_opt_compare(const void * so1, const void * so2) { opt_t *o1, *o2; o1 = ((seen_opt_t *)so1)->opt; o2 = ((seen_opt_t *)so2)->opt; return strcmp(o1->name, o2->name); } /* ============================ */ /* Free a seen_opt_bst element. */ /* ============================ */ void seen_opt_free(void * so) { seen_opt_t * seen_opt = so; free(seen_opt->par); free(so); } /* =========================== */ /* Free an incomp_bst element. */ /* =========================== */ static void incomp_bst_free(void * b) { bst_t * bst = b; bst_destroy(bst, NULL); } /* ============================= */ /* Free an opt_req_list element. */ /* ============================= */ static void req_free(void * r) { req_t * req = r; ll_destroy(req->or_opt_list, NULL); free(req); } /* ================================= */ /* Compare two options_bst elements. */ /* ================================= */ static int opt_compare(const void * o1, const void * o2) { return strcmp(((opt_t *)o1)->name, ((opt_t *)o2)->name); } /* ============================= */ /* Free an options_bst elements. */ /* ============================= */ void opt_free(void * o) { opt_t * opt = o; free(opt->name); free(opt->next_ctx); free(opt->params); free(opt->arg); free(opt->data); ll_destroy(opt->ctx_list, NULL); ll_destroy(opt->constraints_list, constraint_free); ll_destroy(opt->eval_before_list, NULL); free(o); } /* ============================= */ /* Compare two par_bst elements. */ /* ============================= */ static int par_compare(const void * a1, const void * a2) { return strcmp(((par_t *)a1)->name, ((par_t *)a2)->name); } /* ======================= */ /* Free a par_bst element. */ /* ======================= */ static void par_free(void * p) { par_t * par = p; free(par->name); free(p); } /* ================================ */ /* Free a constraints_list element. */ /* ================================ */ static void constraint_free(void * c) { constraint_t * cstr = c; free(cstr->args); free(cstr->to_free); free(c); } /* ******************************************************************** */ /* Helper functions to locate contexts, options and parameters in a BST */ /* by their names. */ /* ******************************************************************** */ static ctx_t * locate_ctx(char * name) { bst_t * node; ctx_t ctx = { 0 }; ctx.name = name; if ((node = bst_find(&ctx, &contexts_bst, ctx_compare)) == NULL) return NULL; else return node->key; } static opt_t * locate_opt(char * name) { bst_t * node; opt_t opt = { 0 }; opt.name = name; if ((node = bst_find(&opt, &options_bst, opt_compare)) == NULL) return NULL; else return node->key; } static par_t * locate_par(char * name, ctx_t * ctx) { bst_t * node; par_t par = { 0 }; void * bst = ctx->par_bst; par.name = name; if ((node = bst_find(&par, &bst, par_compare)) == NULL) return NULL; else return node->key; } /* ====================================================================== */ /* Helper function to display the dependency constraints between options. */ /* These constraints are set with the ctxopt_add_opt_settings function */ /* using the 'before' and 'after' arguments. */ /* IN list : a list of options. */ /* ====================================================================== */ static void print_before_constraints(ll_t * list) { ll_node_t * node = list->head; ll_node_t * before_node; opt_t * opt, *before_opt; int msg = 0; while (node != NULL) { opt = node->data; if (opt->eval_before_list->len > 0) { if (!msg) { printf("\n If present in the command line,"); msg = 1; /* Display this message only once. */ } before_node = opt->eval_before_list->head; printf("\n "); while (before_node != NULL) { before_opt = before_node->data; printf("%s", before_opt->params); before_node = before_node->next; if (before_node != NULL) printf(" and\n "); } printf(" will be evaluated after %s\n", opt->params); } node = node->next; } } /* =================================================================== */ /* Utility function to format and print the options present in a list. */ /* */ /* IN list : a list of options. */ /* OUT has_* : a set of flags which will determine the content of the */ /* explanation given after the formatted printing of the */ /* options. */ /* =================================================================== */ static void print_options(ll_t * list, int * has_optional, int * has_ellipsis, int * has_rule, int * has_generic_arg, int * has_ctx_change, int * has_early_eval) { ll_node_t * node = list->head; opt_t * opt; char * line; char * option; line = xstrdup(" "); while (node != NULL) { option = xstrdup(""); opt = node->data; if (opt->optional) { option = strappend(option, "[", (char *)0); *has_optional = 1; } if (opt->eval_first) { option = strappend(option, "*", (char *)0); *has_early_eval = 1; } option = strappend(option, opt->params, (char *)0); if (opt->next_ctx != NULL) { option = strappend(option, ">", opt->next_ctx, (char *)0); *has_ctx_change = 1; } if (opt->multiple) { if (opt->opt_count_oper != '\0') { char m[4]; char o[2]; o[0] = opt->opt_count_oper; o[1] = '\0'; snprintf(m, 3, "%u", opt->opt_count_mark); option = strappend(option, "...", o, m, (char *)0); *has_rule = 1; } else option = strappend(option, "...", (char *)0); *has_ellipsis = 1; } if (opt->args) { if (*(opt->arg) == '#') *has_generic_arg = 1; option = strappend(option, " ", (char *)0); if (opt->optional_args) { option = strappend(option, "[", opt->arg, (char *)0); *has_optional = 1; } else option = strappend(option, opt->arg, (char *)0); if (opt->multiple_args) { if (opt->opt_args_count_oper != '\0') { char m[4]; char o[2]; o[0] = opt->opt_args_count_oper; o[1] = '\0'; snprintf(m, 3, "%u", opt->opt_args_count_mark); option = strappend(option, "...", o, m, (char *)0); *has_rule = 1; } else option = strappend(option, "...", (char *)0); *has_ellipsis = 1; } if (opt->optional_args) option = strappend(option, "]", (char *)0); } if (opt->optional) option = strappend(option, "]", (char *)0); if (strlen(line) + 1 + strlen(option) < 80) line = strappend(line, option, " ", (char *)0); else { printf("%s\n", line); line[2] = '\0'; line = strappend(line, option, " ", (char *)0); } free(option); node = node->next; } printf("%s\n", line); free(line); } /* ==================================================== */ /* Explain the special syntactic symbols present in the */ /* generated usage messages. */ /* ==================================================== */ static void print_explanations(int has_early_eval, int has_ctx_change, int has_generic_arg, int has_optional, int has_ellipsis, int has_rule) { if (has_early_eval || has_ctx_change || has_generic_arg || has_optional || has_ellipsis || has_rule) { printf("\nExplanation of the syntax used above:\n"); printf("Only the parameters (prefixed by -) and the arguments, if any, " "must be entered.\n"); printf("The following is just there to explain the other symbols " "displayed.\n\n"); if (has_early_eval) printf("* : the parameters defined for this option will " "be evaluated first.\n"); if (has_ctx_change) printf("> : the context after this symbol will be the new " "default context.\n"); if (has_generic_arg) printf("#tag : argument with a hint about its meaning.\n"); if (has_optional) printf("[...] : the object between square brackets is " "optional.\n"); if (has_ellipsis) printf("... : several occurrences of the previous object " "are possible.\n"); if (has_rule) printf("[<|=|>]number: rules constraining the number of " "parameters/arguments.\n"); } } /* ************************************************************ */ /* Various utilities and callback functions called when walking */ /* through a BST. */ /* ************************************************************ */ static void bst_seen_opt_cb(const void * node, walk_order_e kind, int level) { seen_opt_t * seen_opt = ((bst_t *)node)->key; if (kind == postorder || kind == leaf) { if ((!seen_opt->opt->optional) && seen_opt->seen == 0) { user_rc = 1; user_string = strappend(user_string, seen_opt->opt->params, " ", (char *)0); } } } static void bst_seen_opt_seen_cb(const void * node, walk_order_e kind, int level) { seen_opt_t * seen_opt = ((bst_t *)node)->key; if (kind == postorder || kind == leaf) if (seen_opt->seen == 1) { user_rc = 1; user_object = seen_opt->par; } } static void bst_print_ctx_cb(const void * node, walk_order_e kind, int level) { ctx_t * ctx = main_ctx; ctx_t * cur_ctx = ((bst_t *)node)->key; ll_t * list; int has_optional = 0; int has_ellipsis = 0; int has_rule = 0; int has_generic_arg = 0; int has_ctx_change = 0; int has_early_eval = 0; if (kind == postorder || kind == leaf) if (strcmp(ctx->name, cur_ctx->name) != 0) { list = cur_ctx->opt_list; printf("\nAllowed options in the context %s:\n", cur_ctx->name); print_options(list, &has_optional, &has_ellipsis, &has_rule, &has_generic_arg, &has_ctx_change, &has_early_eval); print_before_constraints(list); } } static void bst_check_opt_cb(const void * node, walk_order_e kind, int level) { opt_t * opt = ((bst_t *)node)->key; if (kind == postorder || kind == leaf) { if (opt->params == NULL) /* opt must have associated parameters. */ fatal_internal("Option %s has no registered parameter.\n", opt->name); if (opt->action == NULL) /* opt must have an action. */ fatal_internal("Option %s has no registered action.\n", opt->name); } } static void bst_match_par_cb(const void * node, walk_order_e kind, int level) { ctx_t * ctx = ((bst_t *)node)->key; if (kind == postorder || kind == leaf) { char * str = xstrdup(user_string); while (*str != '\0') { if (locate_par(str, ctx) != NULL) { if (*user_string2 == '\0') user_string2 = strappend(user_string2, "- ", ctx->name, (char *)0); else user_string2 = strappend(user_string2, "\n- ", ctx->name, (char *)0); break; } str[strlen(str) - 1] = '\0'; } free(str); } } static void match_prefix_cb(const void * node, walk_order_e kind, int level) { par_t * par = ((bst_t *)node)->key; if (kind == postorder || kind == leaf) if (strpref(par->name, (char *)user_object)) { user_rc++; user_string = strappend(user_string, par->name, " ", (char *)0); } } /* ====================================================================== */ /* A parameter may not be separated from its first option by spaces, in */ /* this case this function looks for a valid flag as a prefix and splits */ /* the command line queue (eg: "-pa1" -> "-pa" "1" if "-pa" is a valid */ /* option). */ /* */ /* IN word : the word to be checked. */ /* IN ctx : the context in which the flag indexed by the word is to be */ /* checked. */ /* OUT pos : the offset in word pointing just after the matching prefix. */ /* OUT opt : a pointer to the option associated with the new parameter */ /* or NULL if none is found. */ /* */ /* The returned pointer must be freed by the caller. */ /* ====================================================================== */ static char * look_for_valid_prefix_in_word(char * word, ctx_t * ctx, int * pos, opt_t ** opt) { char * new = NULL; int len; par_t * par; par_t tmp_par = { 0 }; len = strlen(word); if (len > 2) { new = xstrdup(word); do { new[--len] = '\0'; tmp_par.name = new; } while ((par = locate_par(tmp_par.name, ctx)) == NULL && len > 2); if (par != NULL) { *pos = len; *opt = par->opt; } else { free(new); new = NULL; } } else *pos = 0; return new; } /* ============================================================= */ /* If par_name is an unique abbreviation of an exiting parameter */ /* in the context ctx, then return this parameter. */ /* ============================================================= */ static char * abbrev_expand(char * par_name, ctx_t * ctx) { user_object = par_name; user_rc = 0; *user_string = '\0'; bst_walk(ctx->par_bst, match_prefix_cb); rtrim(user_string, " ", 0); /* The previous bst_walk has built a string of blank separated parameters */ /* all having par_name as prefix. This string is put in the user_string */ /* exchange zone. The number of these words in put in user_rc. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (user_rc == 1) /* The number of matching abbreviations. */ return xstrdup(user_string); else /* There is at least tho defined parameters starting with par_name. */ { char * s, *first_s; par_t * par; opt_t * opt; int opt_count = 0; void * tmp_opt_bst = NULL; /* Find all the options corresponding to these words and store them */ /* without duplication in a temporary BST. Only their resulting count */ /* matters. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ s = first_s = strtok(user_string, " "); /* first_s holds a copy of * | the first word. */ while (s != NULL) { par = locate_par(s, ctx); opt = par->opt; if (bst_find(opt, &tmp_opt_bst, opt_compare) == NULL) { /* This option as not already been seen */ /* store it and increase the seen counter. */ /* """"""""""""""""""""""""""""""""""""""" */ bst_search(opt, &tmp_opt_bst, opt_compare); opt_count++; } s = strtok(NULL, " "); } /* Clean the temporary BST without removing the pointer */ /* to the real options. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (tmp_opt_bst != NULL) bst_destroy(tmp_opt_bst, NULL); if (opt_count == 1) /* All the abbreviation are leading to only one option */ /* We can just continue as in the previous case. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ return xstrdup(first_s); else return NULL; } } /* ================================================================ */ /* Terminate the program if mandatory options required by a context */ /* are not present. */ /* ================================================================ */ static void check_for_missing_mandatory_opt(ctx_inst_t * ctx_inst, char * opt_par) { char * missing; if (has_unseen_mandatory_opt(ctx_inst, &missing)) fatal(CTXOPTMISPAR, missing); } /* ====================================================== */ /* Return 1 if at least one mandatory option was not seen */ /* when quitting a context, else 0. */ /* ====================================================== */ static int has_unseen_mandatory_opt(ctx_inst_t * ctx_inst, char ** missing) { user_rc = 0; *user_string = '\0'; bst_walk(ctx_inst->seen_opt_bst, bst_seen_opt_cb); rtrim(user_string, " ", 0); *missing = user_string; return user_rc ? 1 : 0; } /* ========================================================================= */ /* This function terminates the program if an option or its arguments do not */ /* conform to its occurrences constraint. */ /* There constraints can appear by trailing >, < or = in their definition */ /* given in ctxopt_new_ctx. */ /* ========================================================================= */ static void check_for_occurrence_issues(ctx_inst_t * ctx_inst) { ctx_t * ctx = ctx_inst->ctx; opt_t * opt; ll_node_t * node; opt_inst_t * opt_inst; char * cur_opt_params = cur_state->cur_opt_params; char * cur_opt_par_name = cur_state->cur_opt_par_name; /* Checks options. */ /* """"""""""""""" */ node = ctx->opt_list->head; while (node != NULL) { opt = node->data; /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->cur_opt_params = opt->params; cur_state->opts_count = opt->opt_count_mark; cur_state->opt_args_count = opt->opt_args_count_mark; if (opt->opt_count_matter) switch (opt->opt_count_oper) { case '=': if (opt->occurrences > 0 && opt->opt_count_mark != opt->occurrences) fatal(CTXOPTCTEOPT, ""); break; case '<': if (opt->occurrences > 0 && opt->opt_count_mark <= opt->occurrences) fatal(CTXOPTCTLOPT, ""); break; case '>': if (opt->occurrences > 0 && opt->opt_count_mark >= opt->occurrences) fatal(CTXOPTCTGOPT, ""); break; } node = node->next; } /* Checks arguments. */ /* """"""""""""""""" */ node = ctx_inst->opt_inst_list->head; while (node != NULL) { opt_inst = node->data; opt = opt_inst->opt; /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->cur_opt_par_name = opt_inst->par; cur_state->opts_count = opt->opt_count_mark; cur_state->opt_args_count = opt->opt_args_count_mark; int nb_values = opt_inst->values_list->len; /* Number of arguments of opt */ if (opt->opt_args_count_matter) switch (opt->opt_args_count_oper) { case '=': if (nb_values > 0 && opt->opt_args_count_mark != nb_values) fatal(CTXOPTCTEARG, ""); break; case '<': if (nb_values > 0 && opt->opt_args_count_mark <= nb_values) fatal(CTXOPTCTLARG, ""); break; case '>': if (nb_values > 0 && opt->opt_args_count_mark >= nb_values) fatal(CTXOPTCTGARG, ""); break; } node = node->next; } cur_state->cur_opt_params = cur_opt_params; cur_state->cur_opt_par_name = cur_opt_par_name; } /* ====================================================================== */ /* This function terminates the program if all the options which are part */ /* of a group of required options by some other option are missing. */ /* ====================================================================== */ static void check_for_requirement_issues(ctx_inst_t * ctx_inst) { ll_node_t * node; ll_node_t * req_node; req_t * req; opt_t * opt; opt_t * req_opt; bst_t * bst_node; seen_opt_t tmp_seen_opt; int found; char * needed_params = NULL; node = ctx_inst->opt_req_list->head; while (node != NULL) { req = node->data; opt = req->opt; tmp_seen_opt.opt = opt; bst_node = bst_find(&tmp_seen_opt, &(ctx_inst->seen_opt_bst), seen_opt_compare); if (((seen_opt_t *)(bst_node->key))->seen != 0) { found = 0; req_node = req->or_opt_list->head; /* needed_params accumulates the params of the options in the group. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ free(needed_params); /* free can applied to the NULL pointer. */ needed_params = xstrdup(""); /* Go through the list of the required group of options and */ /* succeed when one of them has been seen in the context. */ /* otherwise a fatal error is triggered and the program is */ /* terminated. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (req_node != NULL) { req_opt = req_node->data; tmp_seen_opt.opt = req_opt; needed_params = strappend(needed_params, req_opt->params, "\n ", (char *)0); bst_node = bst_find(&tmp_seen_opt, &(ctx_inst->seen_opt_bst), seen_opt_compare); if (((seen_opt_t *)(bst_node->key))->seen != 0) { found = 1; /* A required option has been seen, */ break; /* accept the group. */ } req_node = req_node->next; } rtrim(needed_params, "\n ", 0); /* This is a fatal error if none of the options in the required */ /* options group has been seen in the context. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!found) { char * errmsg; if (req->or_opt_list->len > 1) errmsg = xstrdup("At least one of the parameters among:\n %s\n" "requested by %s must be present.\n"); else errmsg = xstrdup("The parameter %s " "requested by %s must be present.\n"); cur_state->req_opt_par_needed = needed_params; cur_state->req_opt_par = opt->params; fatal(CTXOPTREQPAR, errmsg); } } node = node->next; } } /* ======================================================================== */ /* Parse a strings describing options and some of their characteristics */ /* The input string must have follow some rules like in the examples below: */ /* */ /* "opt_name1 opt_name2" */ /* "[opt_name1] opt_name2" */ /* "[opt_name1] opt_name2..." */ /* "[opt_name1 #...] opt_name2... [#]" */ /* "[opt_name1 [#...]] opt_name2... [#...]" */ /* */ /* Where [ ] encloses an optional part, # means: has parameters and ... */ /* means that there can be more than one occurrence of the previous thing. */ /* */ /* opt_name can be followed by a 'new context' change prefixed with the */ /* symbol >, as in opt1>c2 by eg. */ /* */ /* This function returns as soon as one (or no) option has been parsed and */ /* return the offset to the next option to parse. */ /* */ /* In case of successful parsing, an new option is allocated and its */ /* pointer returned. */ /* ======================================================================== */ static int opt_parse(char * s, opt_t ** opt) { int opt_optional = 0; int opt_multiple = 0; int opt_count_matter = 0; char opt_count_oper = '\0'; unsigned opt_count_mark = 0; int opt_args = 0; char opt_arg[33] = { 0 }; int opt_multiple_args = 0; int opt_args_count_matter = 0; char opt_args_count_oper = '\0'; unsigned opt_args_count_mark = 0; int opt_optional_args = 0; int opt_eval_first = 0; int n; int pos; int count = 0; char * s_orig = s; char * p; char * opt_name = NULL; char * next_ctx; char token[65]; *opt = NULL; memset(opt_arg, '\0', 33); /* Strip the leading blanks. */ /* """"""""""""""""""""""""" */ while (isblank(*s)) s++; if (*s == '[') /* Start of an optional option. */ { opt_optional = 1; s++; } s = strtoken(s, token, sizeof(token) - 1, "[^] \n\t.]", &pos); if (s == NULL) return -1; /* Empty string. */ /* Early EOS, only return success if the option is mandatory. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!*s) if (opt_optional == 1) return -(s - s_orig - 1); /* Validate the option name */ /* ALPHA+(ALPHANUM|_)* */ /* """""""""""""""""""""""" */ p = token; if (!isalpha(*p) && *p != '*') return -(s - s_orig - 1); /* opt_name must start with a letter. */ if (*p == '*') opt_eval_first = 1; p++; while (*p) { if (!isalnum(*p) && *p != '_' && *p != '>') return -(s - s_orig - 1); /* opt_name must contain a letter, * * a number or a _ */ p++; } if (opt_eval_first) opt_name = xstrdup(token + 1); /* Ignore the first '*' in token. */ else opt_name = xstrdup(token); if (*s == ']') { s++; while (isblank(*s)) s++; goto success; } /* Check if it can appear multiple times by looking for the dots. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ p = strtoken(s, token, 3, "[.]", &pos); if (p) { if (strcmp(token, "...") == 0) { opt_multiple = 1; s = p; if (*s == '<' || *s == '=' || *s == '>') { unsigned value; int offset; n = sscanf(s + 1, "%u%n", &value, &offset); if (n == 1) { opt_count_matter = 1; opt_count_oper = *s; opt_count_mark = value; } s += offset + 1; } } else { free(opt_name); return -(s - s_orig - 1); } } if (*s == ']') { /* Abort on extraneous ] if the option is mandatory. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if (!opt_optional) { free(opt_name); return -(s - s_orig - 1); } s++; /* skip the ] */ if (!*s || isblank(*s)) goto success; else { free(opt_name); return -(s - s_orig - 1); } } /* A blank separates the option name and the argument tag. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (isblank(*s)) { char dots[4]; while (isblank(*s)) s++; if (!*s) goto success; pos = 0; n = sscanf(s, "[%32[^] .\t]%n%3[.]", opt_arg, &pos, dots); if (pos > 1 && *opt_arg == '#') /* [# has been read. */ { opt_args = 1; opt_optional_args = 1; if (n == 2) opt_multiple_args = 1; /* There were dots. */ s += pos + !!(n == 2) * 3; /* Skips the dots. */ if (*s == '<' || *s == '=' || *s == '>') { unsigned value; int offset; n = sscanf(s + 1, "%u%n", &value, &offset); if (n == 1) { opt_args_count_matter = 1; opt_args_count_oper = *s; opt_args_count_mark = value; } s += offset + 1; } /* Optional arg tag must end with a ] */ /* """""""""""""""""""""""""""""""""" */ if (*s != ']') { free(opt_name); return -(s - s_orig - 1); } s++; /* Skip the ] */ } else { n = sscanf(s, "%32[^] .\t]%n%3[.]", opt_arg, &pos, dots); if (pos > 0 && *opt_arg == '#') /* # has been read. */ { opt_args = 1; if (n == 2) /* There were dots. */ opt_multiple_args = 1; s += pos + !!(n == 2) * 3; /* Skip the dots. */ if (*s == '<' || *s == '=' || *s == '>') { unsigned value; int offset; n = sscanf(s + 1, "%u%n", &value, &offset); if (n == 1) { opt_args_count_matter = 1; opt_args_count_oper = *s; opt_args_count_mark = value; } s += offset + 1; } } } if (*s == ']') { /* Abort on extraneous ] if the option is mandatory. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if (!opt_optional) { free(opt_name); return -(s - s_orig - 1); } s++; /* skip the ] */ /* Strip the following blanks. */ /* """"""""""""""""""""""""""" */ while (isblank(*s)) s++; goto success; } else if (opt_optional == 0 && (!*s || isblank(*s))) { /* Strip the following blanks. */ /* """"""""""""""""""""""""""" */ while (isblank(*s)) s++; goto success; } else if (opt_args == 0) /* # was not read it is possibly the start * * of another option. */ goto success; else { free(opt_name); return -(s - s_orig - 1); } } success: /* Strip the following blanks. */ /* """"""""""""""""""""""""""" */ while (isblank(*s)) s++; next_ctx = NULL; if (*opt_name == '>') fatal_internal("The option name is missing in %s.", opt_name); count = strchrcount(opt_name, '>'); if (count == 1) { char * tmp = strchr(opt_name, '>'); next_ctx = xstrdup(tmp + 1); *tmp = '\0'; } else if (count > 1) fatal_internal("Only one occurrence of '>' is allowed in %s.", opt_name); *opt = xmalloc(sizeof(opt_t)); (*opt)->name = opt_name; (*opt)->optional = opt_optional; (*opt)->multiple = opt_multiple; (*opt)->opt_count_matter = opt_count_matter; (*opt)->opt_count_oper = opt_count_oper; (*opt)->opt_count_mark = opt_count_mark; (*opt)->args = opt_args; (*opt)->arg = xstrdup(opt_arg); (*opt)->optional_args = opt_optional_args; (*opt)->multiple_args = opt_multiple_args; (*opt)->opt_args_count_matter = opt_args_count_matter; (*opt)->opt_args_count_oper = opt_args_count_oper; (*opt)->opt_args_count_mark = opt_args_count_mark; (*opt)->eval_first = opt_eval_first; (*opt)->next_ctx = next_ctx; (*opt)->ctx_list = ll_new(); (*opt)->constraints_list = ll_new(); (*opt)->eval_before_list = ll_new(); (*opt)->action = NULL; (*opt)->params = NULL; (*opt)->data = NULL; return s - s_orig; } /* ==================================================================== */ /* Try to initialize all the option in a given string. */ /* Each parsed option are put in a BST tree with its name as index. */ /* */ /* On collision, the arguments only the signature are required to be */ /* the same else this is considered as an error. Options can be used in */ /* more than one context and can be optional in one and mandatory in */ /* another. */ /* ==================================================================== */ static int init_opts(char * spec, ctx_t * ctx) { opt_t * opt, *bst_opt; bst_t * node; int offset; while (*spec) { if ((offset = opt_parse(spec, &opt)) > 0) { spec += offset; if ((node = bst_find(opt, &options_bst, opt_compare)) != NULL) { int same_next_ctx = 0; bst_opt = node->key; /* Node extracted from the BST. */ if (bst_opt->next_ctx == NULL && opt->next_ctx == NULL) same_next_ctx = 1; else if (bst_opt->next_ctx == NULL && opt->next_ctx != NULL) same_next_ctx = 0; else if (bst_opt->next_ctx != NULL && opt->next_ctx == NULL) same_next_ctx = 0; else same_next_ctx = strcmp(bst_opt->next_ctx, opt->next_ctx) == 0; if (bst_opt->optional_args != opt->optional_args || bst_opt->multiple_args != opt->multiple_args || bst_opt->args != opt->args || !same_next_ctx) { fatal_internal("The option %s already exists with " "a different arguments signature.\n", opt->name); } /* The newly created opt is already present in options_bst. */ /* We can remove it. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ opt_free(opt); /* The new occurrence of the option option is legal */ /* append the current context ptr in the list. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ ll_append(bst_opt->ctx_list, ctx); /* Append the new option to the context's options list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ ll_append(ctx->opt_list, bst_opt); } else { /* Initialize the option's context list with the current context. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ ll_append(opt->ctx_list, ctx); /* Append the new option to the context's options list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ ll_append(ctx->opt_list, opt); /* Insert the new option in the BST. */ /* """"""""""""""""""""""""""""""""" */ bst_search(opt, &options_bst, opt_compare); } } else { char * s = xstrndup(spec, -offset); printf("%s <---\nSyntax error at or before offset %d\n", s, -offset); free(s); exit(EXIT_FAILURE); } } return 1; } /* ===================================================== */ /* ctxopt initialization function, must be called first. */ /* ===================================================== */ void ctxopt_init(char * prog_name, char * init_flags) { int n; contexts_bst = NULL; options_bst = NULL; char * ptr; user_rc = 0; user_value = 0; user_string = xmalloc(8); user_string2 = xmalloc(8); user_object = NULL; char flag[33], fname[31], vname[31]; int invalid; ctxopt_initialized = 1; /* Initialize current_state.*/ /* """""""""""""""""""""""" */ cur_state = xcalloc(sizeof(state_t), 0); /* Initialize custom error function pointers to NULL. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ err_functions = xmalloc(CTXOPTERRSIZ * sizeof(void *)); for (n = 0; n < CTXOPTERRSIZ; n++) err_functions[n] = NULL; /* Parse init_flags if any. */ /* """""""""""""""""""""""" */ while (*init_flags && (init_flags = get_word(init_flags, flag, 32))) { if (*flag) { if (sscanf(flag, "%30[^=]=%30[^=]", fname, vname) != 2) fatal_internal("Invalid flag assignment: %s.", flag); if (strcmp(fname, "stop_if_non_option") == 0) { if (eval_yes(vname, &invalid)) flags.stop_if_non_option = 1; else if (!invalid) flags.stop_if_non_option = 0; else fatal_internal("Invalid flag value for %s: %s.", fname, vname); } else if (strcmp(fname, "allow_abbreviations") == 0) { if (eval_yes(vname, &invalid)) flags.allow_abbreviations = 1; else if (!invalid) flags.allow_abbreviations = 0; else fatal_internal("Invalid flag value for %s: %s.", fname, vname); } else if (strcmp(fname, "display_usage_on_error") == 0) { if (eval_yes(vname, &invalid)) flags.display_usage_on_error = 1; else if (!invalid) flags.display_usage_on_error = 0; else fatal_internal("Invalid flag value for %s: %s.", fname, vname); } else fatal_internal("Invalid flag name: %s.", fname); } } /* Update current_state. */ /* """"""""""""""""""""" */ if (prog_name) { if (*prog_name == '\0') cur_state->prog_name = xstrdup("program_name"); else if ((ptr = strrchr(prog_name, '/'))) cur_state->prog_name = xstrdup(ptr + 1); else cur_state->prog_name = xstrdup(prog_name); } else cur_state->prog_name = xstrdup("program_name"); } /* ========================================================================= */ /* Utility function which create and register a par_t object in a BST */ /* embedded in a context. */ /* This object will have a name and a pointer to the option it refers to. */ /* These object will be used to quickly find an option from a command */ /* line parameter during the analysis phase. */ /* */ /* IN : an option name. */ /* IN : a string of command line parameters to associate to the option. */ /* Returns : 1 is all was fine else 0. */ /* ========================================================================= */ static int opt_set_parms(char * opt_name, char * par_str) { char * par_name, *ctx_name; char * tmp_par_str, *end_tmp_par_str; ctx_t * ctx; opt_t * opt; bst_t * node; par_t * par, tmp_par; int rc = 1; /* Return code. */ ll_t * list; ll_node_t * lnode; /* Look if the given option is defined. */ /* """""""""""""""""""""""""""""""""""" */ opt = locate_opt(opt_name); if (opt == NULL) fatal_internal("Unknown option %s.", opt_name); /* For each context using this option. */ /* """"""""""""""""""""""""""""""""""" */ list = opt->ctx_list; lnode = list->head; while (lnode != NULL) { /* Locate the context in the contexts tree. */ /* """""""""""""""""""""""""""""""""""""""" */ ctx_name = ((ctx_t *)(lnode->data))->name; ctx = locate_ctx(ctx_name); if (ctx == NULL) fatal_internal("Unknown context %s.", ctx_name); else { void * par_bst = ctx->par_bst; tmp_par_str = xstrdup(par_str); ltrim(tmp_par_str, " \t"); rtrim(tmp_par_str, " \t", 0); par_name = xstrtok_r(tmp_par_str, " \t,", &end_tmp_par_str); if (par_name == NULL) fatal_internal("Parameters are missing for option %s.", opt_name); /* For each parameter given in par_str, creates a par_t object and */ /* insert it the in the parameters BST of the context. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (par_name != NULL) { tmp_par.name = par_name; node = bst_find(&tmp_par, &par_bst, par_compare); if (node != NULL) { fatal_internal("The parameter %s is already defined in context %s.", par_name, ctx->name); rc = 0; } else { par = xmalloc(sizeof(par_t)); par->name = xstrdup(par_name); par->opt = opt; /* Link the option to this parameter. */ bst_search(par, &par_bst, par_compare); } par_name = xstrtok_r(NULL, " \t,", &end_tmp_par_str); } /* Update the value of the root of ctx->par_bst as it may have */ /* been modified. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ ctx->par_bst = par_bst; free(tmp_par_str); } lnode = lnode->next; } return rc; } /* ==================================================================== */ /* Create a new context instance. */ /* IN ctx : a context pointer to allow this instance to */ /* access the context fields */ /* IN prev_ctx_inst : the context instance whose option leading to the */ /* creation of this new context instance is part of */ /* Returns : the new context. */ /* ==================================================================== */ static ctx_inst_t * new_ctx_inst(ctx_t * ctx, ctx_inst_t * prev_ctx_inst) { opt_t * opt; opt_inst_t * gen_opt_inst; ctx_inst_t * ctx_inst; seen_opt_t * seen_opt; char * str, *opt_name; void * bst; bst_t * bst_node; /* Keep a trace of the opt_inst which was at the origin of the creation */ /* of this context instance. */ /* This will serve during the evaluation of the option callbacks. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (prev_ctx_inst != NULL) { gen_opt_inst = (opt_inst_t *)(prev_ctx_inst->opt_inst_list->tail->data); /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->opt_name = gen_opt_inst->opt->name; } else gen_opt_inst = NULL; /* Create and initialize the new context instance. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ ctx_inst = xmalloc(sizeof(ctx_inst_t)); ctx_inst->ctx = ctx; ctx_inst->prev_ctx_inst = prev_ctx_inst; ctx_inst->gen_opt_inst = gen_opt_inst; ctx_inst->incomp_bst_list = ll_new(); ctx_inst->opt_inst_list = ll_new(); ctx_inst->opt_req_list = ll_new(); ctx_inst->seen_opt_bst = NULL; ll_node_t * node; if (prev_ctx_inst == NULL) first_ctx_inst = ctx_inst; /* Initialize the occurrence counters of each opt allowed in the context. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = ctx->opt_list->head; while (node != NULL) { opt = node->data; opt->occurrences = 0; node = node->next; } /* Initialize the BST containing the seen indicator for all the options */ /* allowed in this context instance. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = ctx->opt_list->head; while (node != NULL) { opt = node->data; seen_opt = xmalloc(sizeof(seen_opt_t)); seen_opt->opt = opt; seen_opt->par = NULL; seen_opt->seen = 0; bst_search(seen_opt, &(ctx_inst->seen_opt_bst), seen_opt_compare); node = node->next; } /* Initialize the BST containing the incompatibles options. */ /* Incompatibles option names are read from strings found in the list */ /* incomp_list present in each instance of ctx_t. */ /* These names are then used to search for the object of type seen_opt_t */ /* which is already present in the seen_opt_bst of the context instance. */ /* in the BST. */ /* Once found the seen_opt_t object in inserted in the new BST. */ /* At the end the new BST in added to the list incomp_bst_list. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = ctx->incomp_list->head; while (node != NULL) { bst = NULL; seen_opt_t tmp_seen_opt; str = xstrdup(node->data); ltrim(str, " \t"); rtrim(str, " \t", 0); opt_name = strtok(str, " \t"); /* Extract the first option name. */ while (opt_name != NULL) /* For each option name. */ { if ((opt = locate_opt(opt_name)) != NULL) { /* The option found is searched in the tree of potential */ /* seen options. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ tmp_seen_opt.opt = opt; bst_node = bst_find(&tmp_seen_opt, &(ctx_inst->seen_opt_bst), seen_opt_compare); if (bst_node != NULL) { /* If found then it is added into the new BST tree. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ seen_opt = bst_node->key; bst_search(seen_opt, &bst, seen_opt_compare); } else /* Not found! That means that the option is unknown in this */ /* context as all options has have a seen_opt structure in */ /* seen_opt_bst. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ fatal_internal("%s is not known in the context %s.", opt->name, ctx->name); } else fatal_internal("Unknown option %s.", opt_name); opt_name = strtok(NULL, " \t"); } free(str); ll_append(ctx_inst->incomp_bst_list, bst); node = node->next; } /* Initialize the list of res_t structures according to the */ /* list set in the context by ctxopt_add_ctx_settings/required. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = ctx->req_list->head; while (node != NULL) { req_t * req = xmalloc(sizeof(req_t)); str = xstrdup(node->data); ltrim(str, " \t"); rtrim(str, " \t", 0); opt_name = strtok(str, " \t"); /* Extract the first option name. */ if ((opt = locate_opt(opt_name)) != NULL) { req->opt = opt; req->or_opt_list = ll_new(); while ((opt_name = strtok(NULL, " \t")) != NULL) { if ((opt = locate_opt(opt_name)) != NULL) ll_append(req->or_opt_list, opt); else fatal_internal("Unknown option %s.", opt_name); } ll_append(ctx_inst->opt_req_list, req); } else fatal_internal("Unknown option %s.", opt_name); free(str); node = node->next; } return ctx_inst; } /* ====================================================================== */ /* Create a list formed by all the significant command line words */ /* Words beginning or ending with { or } are split. Each of these */ /* symbols will get their own place in the list. */ /* */ /* the {...} part delimits a context, the { will not appear in the list */ /* and the } will be replaced by a | in the resulting list (cmdline_list) */ /* to facilitate the parsing phase. | must not be used by the end user. */ /* */ /* IN nb_word : number of word to parse, this is typically argc-1 as the */ /* program name is not considered. */ /* IN words : is the array of strings constituting the command line to */ /* parse. */ /* Returns : 1 on success, 0 if a { or } is missing. */ /* ====================================================================== */ static int ctxopt_build_cmdline_list(int nb_words, char ** words) { int i; char * prev_word = NULL; char * word; char * ptr; int level = 0; ll_node_t *node, *start_node; /* The analysis is divided into three passes, this is not optimal but */ /* must be done only one time. Doing that we privilege readability. */ /* */ /* In the following, SG is the ascii character 1d (dec 29) */ /* */ /* The first pass creates the list, extract the leading an trailing */ /* SG '{' and '}' of each word and give them their own place in the */ /* list */ /* */ /* The second pass transform the '{...}' blocks by a trailing SG */ /* ({...} -> ...|) */ /* */ /* The last pass remove the duplicated SG, check for SG, '{' or '}' in */ /* the middle in the remaining list elements and recreate the pseudo */ /* argument: {} */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ /* If the option list is not empty, clear it before going further. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (cmdline_list != NULL) ll_destroy(cmdline_list, free); cmdline_list = ll_new(); start_node = cmdline_list->head; /* In the following loop start_node will * * contain a pointer to the current * * word stripped from its leading * * sequence of {, }. */ for (i = 0; i < nb_words; i++) { size_t len = strlen(words[i]); size_t start, end; char * str; str = words[i]; /* Replace each occurrence of the legal word {} by the characters */ /* 0x02 and 0x03 to hide them from the following process. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while ((ptr = strstr(str, "{}")) != NULL) { *ptr = 0x02; /* Arbitrary values unlikely */ *(ptr + 1) = 0x03; /* present in a word. */ } if (len > 1) /* The word contains at least 2 characters. */ { start = 0; /* Interpret its beginning and look for the start of the real word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (start <= len - 1 && (str[start] == '{' || str[start] == '}')) { ll_append(cmdline_list, xstrndup(str + start, 1)); start++; start_node = cmdline_list->tail; } end = len - 1; if (str[end] == '{' || str[end] == '}') { if (end > 0 && str[end - 1] != '\\') { ll_append(cmdline_list, xstrndup(str + end, 1)); end--; node = cmdline_list->tail; while (str[end] == '{' || str[end] == '}') { if (end > start && str[end - 1] == '\\') break; ll_insert_before(cmdline_list, node, xstrndup(str + end, 1)); end--; node = node->prev; } } } if (start <= end) { if (start_node != NULL) ll_insert_after(cmdline_list, start_node, xstrndup(str + start, end - start + 1)); else ll_append(cmdline_list, xstrndup(str + start, end - start + 1)); start_node = cmdline_list->tail; } } else if (len == 1) { ll_append(cmdline_list, xstrdup(str)); start_node = cmdline_list->tail; } } /* 2nd pass. */ /* """"""""" */ node = cmdline_list->head; level = 0; while (node != NULL) { word = node->data; if (strcmp(word, "{") == 0) { ll_node_t * old_node = node; level++; node = node->next; free(word); ll_delete(cmdline_list, old_node); } else if (strcmp(word, "}") == 0) { level--; if (level < 0) return 0; else *word = 0x1d; } else node = node->next; } if (level != 0) return 0; /* 3rd pass. */ /* """"""""" */ node = cmdline_list->head; while (node != NULL) { word = node->data; /* Restore the original { and } characters forming the legal word {}. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while ((ptr = strchr(word, 0x02)) != NULL) *ptr = '{'; while ((ptr = strchr(word, 0x03)) != NULL) *ptr = '}'; /* Remove a SG if the previous element is SG. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (strcmp(word, "\x1d") == 0) { if (prev_word != NULL && (strcmp(prev_word, "\x1d") == 0)) { ll_node_t * old_node = node; node = node->prev; free(old_node->data); ll_delete(cmdline_list, old_node); } } else if (strcmp(word, "-") == 0) /* A single - is a legal argument, not * * a parameter. Protect it. */ { free(node->data); node->data = xstrdup("\\-"); } prev_word = node->data; node = node->next; } /* Clean useless and SG at the beginning and end of list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = cmdline_list->head; if (node == NULL) return 1; word = node->data; if (strcmp(word, "\x1d") == 0) { free(word); ll_delete(cmdline_list, node); } node = cmdline_list->tail; if (node == NULL) return 1; word = node->data; if (strcmp(word, "\x1d") == 0) { free(word); ll_delete(cmdline_list, node); } return 1; } /* ===================================================================== */ /* Build and analyze the command line list and create the linked data */ /* structures whose data will be evaluated later by ctxopt_evaluate. */ /* This function identifies the following errors and creates an array of */ /* The remaining unanalyzed arguments. */ /* - detect missing arguments */ /* - detect too many arguments */ /* - detect unknown parameters in a context */ /* - detect too many occurrences of a parameters in a context */ /* - detect missing required arguments in a context */ /* */ /* IN nb_word : number of word to parse, this is typically argc-1 as the */ /* program name is not considered */ /* IN words : is the array of strings constituting the command line to */ /* parse. */ /* OUT nb_rem_args : nb of remaining command line arguments if a -- */ /* is present in the list. */ /* OUT rem_args : array of remaining command line arguments if a -- */ /* is present in the list. This array must be free by */ /* The caller as it is allocated here. */ /* ===================================================================== */ void ctxopt_analyze(int nb_words, char ** words, int * nb_rem_args, char *** rem_args) { char * ctxopt_debug_env; /* Environment variable CTXOPT_DEBUG content. */ int ctxopt_debug; /* 1 if ctxopt_debug_env is set and not empty. * | 0 if ctxopt_debug_env is unset or empty. */ ctx_t * ctx; opt_t * opt; par_t * par; ctx_inst_t * ctx_inst; opt_inst_t * opt_inst; int expect_par = 0; int expect_arg = 0; int expect_par_or_arg = 0; ll_node_t * cli_node; bst_t * bst_node; seen_opt_t * bst_seen_opt; char * par_name; void * bst; ll_node_t * node; if (!ctxopt_build_cmdline_list(nb_words, words)) fatal_internal("The command line could not be parsed: " "missing '{' or '}' detected."); if (main_ctx == NULL) fatal_internal("At least one context must have been created."); /* Check that all options has an action and at least one parameter. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ bst_walk(options_bst, bst_check_opt_cb); /* CTXOPT debug setting. */ /* """"""""""""""""""""" */ ctxopt_debug_env = getenv("CTXOPT_DEBUG"); if (ctxopt_debug_env != NULL && *ctxopt_debug_env != '\0') ctxopt_debug = 1; else ctxopt_debug = 0; /* Create the first ctx_inst record. */ /* """"""""""""""""""""""""""""""""" */ ctx = main_ctx; ctx_inst_list = ll_new(); ctx_inst = new_ctx_inst(ctx, NULL); ctx_inst->par_name = NULL; /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->ctx_name = ctx->name; ll_append(ctx_inst_list, ctx_inst); /* For each node in the command line. */ /* """""""""""""""""""""""""""""""""" */ cli_node = cmdline_list->head; expect_par = 1; par_name = NULL; while (cli_node != NULL) { if (strcmp(cli_node->data, "--") == 0) break; /* No new parameter will be analyzed after this point. */ par_name = cli_node->data; /* Replace a leading -- by a single - */ /* """""""""""""""""""""""""""""""""" */ if (strncmp(par_name, "--", 2) == 0) par_name += 1; /* Ignore the first dash. */ if (strcmp(par_name, "\x1d") == 0) { check_for_missing_mandatory_opt(ctx_inst, (char *)(cli_node->prev->data)); check_for_occurrence_issues(ctx_inst); check_for_requirement_issues(ctx_inst); /* Forced backtracking to the previous context instance. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ctx_inst->prev_ctx_inst != NULL) { ctx_inst = ctx_inst->prev_ctx_inst; ctx = ctx_inst->ctx; /* Update current_states. */ /* """"""""""""""""""""" */ cur_state->ctx_name = ctx->name; cur_state->ctx_par_name = ctx_inst->par_name; if (ctxopt_debug) fprintf(stderr, "CTXOPT_DEBUG: Context forced backtrack, " "new current context: %s.\n", ctx->name); } else { /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->ctx_par_name = NULL; } } else if (expect_par && *par_name == '-') { int pos = 0; char * prefix; /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->cur_opt_par_name = par_name; cur_state->ctx_name = ctx->name; cur_state->ctx_par_name = ctx_inst->par_name; if (ctxopt_debug) fprintf(stderr, "CTXOPT_DEBUG: Parameter: %s. Current context: %s.\n", par_name, cur_state->ctx_name); /* An expected parameter has been seen. */ /* """""""""""""""""""""""""""""""""""" */ if ((par = locate_par(par_name, ctx)) == NULL) { opt_t * popt; char * word; /* Look if this parameter is an unique abbreviation of a longer */ /* parameter. If this is the case then just replace it with its */ /* full length version and try again. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (flags.allow_abbreviations) if ((word = abbrev_expand(par_name, ctx)) != NULL) { cli_node->data = word; continue; } /* Try to find a prefix which is a valid parameter in this context */ /* If found, split the cli_node in two to build a new parameter */ /* node and followed by a node containing the remaining string */ /* If the new parameter corresponds to an option not taking */ /* argument then prefix the remaining string whit a dash as it may */ /* contain a new parameter. */ /* The new parameter will be re-evaluated in the next iteration of */ /* the loop. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""*/ prefix = look_for_valid_prefix_in_word(par_name, ctx, &pos, &popt); if (prefix != NULL && pos != 0) { if (ctxopt_debug) fprintf(stderr, "CTXOPT_DEBUG: Found a valid parameter " "as a prefix of %s: %s.\n", par_name, prefix); cli_node->data = prefix; /* prefix contains le name of a valid * | parameter in this context. */ if (popt->args) { /* The parameter may be followed by arguments. */ /* ''''''''''''''''''''''''''''''''''''''''''' */ if (*(par_name + pos) == '-') { word = xstrdup("\\"); /* Protect the '-' */ word = strappend(word, par_name + pos, (char *)0); } else word = xstrdup(par_name + pos); } else { /* The parameter does not take arguments, the */ /* following word must be a parameter or nothing */ /* hence prefix it with a dash. */ /* ''''''''''''''''''''''''''''''''''''''''''''' */ word = xstrdup("-"); word = strappend(word, par_name + pos, (char *)0); } /* Insert it after the current node in the list. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ ll_insert_after(cmdline_list, cli_node, word); continue; /* loop. */ } else { check_for_missing_mandatory_opt(ctx_inst, par_name); check_for_occurrence_issues(ctx_inst); check_for_requirement_issues(ctx_inst); if (ctx_inst->prev_ctx_inst == NULL) { char * errmsg = xstrdup(""); /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->ctx_par_name = NULL; *user_string = '\0'; *user_string2 = '\0'; user_string = strappend(user_string, par_name, (char *)0); bst_walk(contexts_bst, bst_match_par_cb); if (*user_string2 != '\0') { char * help_msg; int count = 0; count = strchrcount(user_string2, '\n'); if (flags.display_usage_on_error) help_msg = ", see below"; else help_msg = ""; if (count == 0) /* Only one context involved. */ errmsg = strappend( errmsg, "\nThis parameter is only valid in the following " "context:\n", user_string2, "\n\nFirst switch to this context using the appropriate " "parameter", help_msg, ".\n", (char *)0); else errmsg = strappend( errmsg, "\nThis parameter is only valid in one of the following " "contexts:\n", user_string2, "\n\nFirst switch to one of them using the appropriate " "parameter", help_msg, ".\n", (char *)0); } fatal(CTXOPTUNKPAR, errmsg); } else { /* Tries to backtrack and analyse the same parameter in the */ /* previous context. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ ctx_inst = ctx_inst->prev_ctx_inst; ctx = ctx_inst->ctx; if (ctxopt_debug) fprintf(stderr, "CTXOPT_DEBUG: Context backtrack, " "new current context: %s.\n", ctx->name); /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->ctx_name = ctx->name; cur_state->ctx_par_name = ctx_inst->par_name; cli_node = cli_node->prev; } } } else { seen_opt_t seen_opt; /* The parameter is valid in the context, create a opt_inst and */ /* append it to the ctx_inst list options list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ opt = par->opt; opt->occurrences++; opt_inst = xmalloc(sizeof(opt_inst_t)); opt_inst->opt = opt; opt_inst->par = par_name; opt_inst->values_list = ll_new(); opt_inst->next_ctx_inst = NULL; /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->cur_opt_params = opt->params; /* Priority option are inserted at the start of the opt_inst list */ /* but their order of appearance in the context definition must */ /* be preserver so each new priority option will be placed after */ /* the previous ones at the start of the opt_inst list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!opt->eval_first) { /* Look if we have a registered dependency in the order of the */ /* evaluation of two options. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (opt->eval_before_list->len > 0) { ll_t * list = ctx_inst->opt_inst_list; ll_node_t * opt_inst_node; ll_t * before_list = opt->eval_before_list; ll_node_t * before_node = before_list->head; ll_node_t * target_node = NULL; /* If not NULL, the new node * | will be inserted before it. */ /* For each entry in eval_before_list, try to find if it */ /* refers to an option already entered in the context. If this */ /* is the case, insert it just before it instead of putting it */ /* at the end. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (before_node != NULL) { opt_inst_node = list->head; while (opt_inst_node != target_node) { opt_t * tmp_opt = (((opt_inst_t *)opt_inst_node->data))->opt; /* We have found an option mentioned if the before_list */ /* of the option we want to add. We can stop searching. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (strcmp(tmp_opt->name, ((opt_t *)before_node->data)->name)) opt_inst_node = opt_inst_node->next; else target_node = opt_inst_node; /* Set the target node. */ } before_node = before_node->next; } /* Insert or append ? */ /* """""""""""""""""" */ if (target_node != NULL) ll_insert_before(ctx_inst->opt_inst_list, target_node, opt_inst); else ll_append(ctx_inst->opt_inst_list, opt_inst); } else ll_append(ctx_inst->opt_inst_list, opt_inst); } else { ll_node_t * opt_inst_node = ctx_inst->opt_inst_list->head; opt_inst_t * tmp_opt_inst; while (opt_inst_node != NULL) { tmp_opt_inst = opt_inst_node->data; if (!tmp_opt_inst->opt->eval_first) { ll_insert_before(ctx_inst->opt_inst_list, opt_inst_node, opt_inst); break; } else opt_inst_node = opt_inst_node->next; } if (opt_inst_node == NULL) ll_append(ctx_inst->opt_inst_list, opt_inst); } /* Check if an option was already seen in the */ /* current context instance. */ /* """""""""""""""""""""""""""""""""""""""""" */ seen_opt.opt = opt; bst_node = bst_find(&seen_opt, &(ctx_inst->seen_opt_bst), seen_opt_compare); /* bst_node cannot be NULL here. */ bst_seen_opt = (seen_opt_t *)(bst_node->key); if (!opt->multiple && bst_seen_opt->seen == 1) fatal(CTXOPTDUPOPT, ""); /* Check if this option is compatible with the options already */ /* seen in this context instance. */ /* Look if the option is present in one on the BST present in */ /* the incomp_bst_list of the context instance. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = ctx_inst->incomp_bst_list->head; while (node != NULL) { bst = node->data; user_object = NULL; /* There can only have one seen_opt object in the BST tree was */ /* already seen, try to locate it, the result will be put in */ /* user_object by the bst_seen_opt_seen_cb function. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ bst_walk(bst, bst_seen_opt_seen_cb); /* If it is the case, look if the current option is also */ /* in this BST. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (user_object != NULL) { bst_node = bst_find(bst_seen_opt, &bst, seen_opt_compare); if (bst_node != NULL) { bst_seen_opt = (seen_opt_t *)(bst_node->key); if (bst_seen_opt->seen == 0) fatal(CTXOPTINCOPT, (char *)user_object); } } node = node->next; } /* Mark this option as seen in the current context instance. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ bst_seen_opt->seen = 1; free(bst_seen_opt->par); bst_seen_opt->par = xstrdup(par_name); /* If this option leads to a next context, create a new ctx_inst */ /* and switch to it for the analyse of the future parameter. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (opt->next_ctx != NULL) { ctx = locate_ctx(opt->next_ctx); if (ctx == NULL) fatal_internal("Unknown context %s.", opt->next_ctx); opt_inst->next_ctx_inst = ctx_inst = new_ctx_inst(ctx, ctx_inst); ctx_inst->par_name = xstrdup(par_name); ll_append(ctx_inst_list, ctx_inst); if (ctxopt_debug) fprintf(stderr, "CTXOPT_DEBUG: Context change, " "new current context: %s.\n", ctx->name); } /* Look is we must expect some arguments. */ /* """""""""""""""""""""""""""""""""""""" */ expect_par_or_arg = 0; expect_par = 0; expect_arg = 0; if (!opt->args) expect_par = 1; /* Parameter doesn't accept any argument. */ else { if (!opt->optional_args) expect_arg = 1; /* Parameter has mandatory arguments. */ else expect_par_or_arg = 1; /* Parameter has optional arguments. */ } } } else if (expect_par && *par_name != '-') { ll_node_t * n = cli_node->next; if (!flags.stop_if_non_option) /* Look if potential arguments must still be analyzed until the */ /* end of the context/command line part to analyze/command line. */ /* If this is the case we have met an extra argument. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (n != NULL) { if (strcmp(n->data, "--") == 0 || strcmp(n->data, "\x1d") == 0) fatal(CTXOPTUNXARG, ""); if (*(char *)(n->data) == '-') fatal(CTXOPTUNXARG, ""); n = n->next; } break; /* An unexpected non parameter was seen, if no Potential * | arguments remain in the command line or * | flags.stop_if_non_option is set, assume that it is is * | the first of the non arguments and stop the command * | line analysis. */ } else if (expect_arg && *par_name != '-') { ll_node_t * cstr_node; constraint_t * cstr; if (ctxopt_debug) fprintf(stderr, "CTXOPT_DEBUG: Argument: %s.\n", par_name); /* Check if the arguments of the option respects */ /* the attached constraints if any. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ cstr_node = opt->constraints_list->head; while (cstr_node != NULL) { cstr = cstr_node->data; if (!cstr->constraint(cstr->nb_args, cstr->args, par_name, cur_state->cur_opt_par_name)) { fputs("\n", stderr); ctxopt_ctx_disp_usage(cur_state->ctx_name, exit_after); } cstr_node = cstr_node->next; } /* If the argument is valid, store it. */ /* """"""""""""""""""""""""""""""""""" */ if (*par_name == '\\' && *(par_name + 1) == '-') ll_append(opt_inst->values_list, par_name + 1); else ll_append(opt_inst->values_list, par_name); expect_arg = 0; expect_par = 0; expect_par_or_arg = 0; if (opt->multiple_args) expect_par_or_arg = 1; else expect_par = 1; /* Parameter takes only one argument. */ } else if (expect_arg && *par_name == '-') fatal(CTXOPTMISARG, ""); else if (expect_par_or_arg) { expect_arg = 0; expect_par = 0; expect_par_or_arg = 0; if (*par_name != '-') expect_arg = 1; /* Consider this word as an argument and retry. */ else expect_par = 1; /* Consider this word as a parameter and retry. */ cli_node = cli_node->prev; } cli_node = cli_node->next; } if (cmdline_list->len > 0 && par_name && *par_name == '-') { if (expect_arg && opt && !opt->optional_args) fatal(CTXOPTMISARG, ""); } /* Look if a context_instance has unseen mandatory options. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = ctx_inst_list->head; while (node != NULL) { ctx_inst = node->data; /* Update current_state. */ /* """"""""""""""""""""" */ cur_state->ctx_name = ctx_inst->ctx->name; cur_state->ctx_par_name = ctx_inst->par_name; check_for_missing_mandatory_opt(ctx_inst, par_name); check_for_occurrence_issues(ctx_inst); check_for_requirement_issues(ctx_inst); node = node->next; } /* Allocate the array containing the remaining not analyzed */ /* command line arguments. */ /* NOTE: The strings in the array are just pointer to the */ /* data of the generating list and must not be freed. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (cli_node != NULL) { if (strcmp((char *)cli_node->data, "--") == 0) /* The special parameter -- was encountered, the -- argument is not */ /* put in the remaining arguments. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ ll_strarray(cmdline_list, cli_node->next, nb_rem_args, rem_args); else /* A non parameter was encountered when a parameter was expected. We */ /* assume that the evaluation of the remaining command line argument */ /* are not the responsibility of the users code. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ ll_strarray(cmdline_list, cli_node, nb_rem_args, rem_args); } else { *nb_rem_args = 0; *rem_args = xmalloc(sizeof(char *)); (*rem_args)[0] = NULL; } } /* ==================================================== */ /* Free ctxopt memory used for its internal structures. */ /* ==================================================== */ void ctxopt_free_memory(void) { ll_destroy(cmdline_list, free); ll_destroy(ctx_inst_list, ctx_inst_free); bst_destroy(options_bst, opt_free); bst_destroy(contexts_bst, ctx_free); } /* ==================================================================== */ /* Parse the options data structures and launches the callback function */ /* attached to each options instances. */ /* This calls a recursive function which proceeds context per context. */ /* ==================================================================== */ void ctxopt_evaluate(void) { evaluate_ctx_inst(first_ctx_inst); } /* =================================================================== */ /* Recursive function called by ctxopt_evaluate to process the list of */ /* the opt_inst present in a ctx_inst and attempt to evaluate the */ /* action attached to the context and its option instances. */ /* =================================================================== */ static void evaluate_ctx_inst(ctx_inst_t * ctx_inst) { opt_inst_t * opt_inst; ctx_t * ctx; opt_t * opt; ll_node_t * opt_inst_node; char ** args; int nb_args; if (ctx_inst == NULL) return; ctx = ctx_inst->ctx; /* Do not evaluate the action attached to this context is there is no */ /* option to evaluate. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ opt_inst_node = ctx_inst->opt_inst_list->head; if (opt_inst_node == NULL) return; /* Call the entering action attached to this context if any. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ctx->action != NULL) { if (ctx_inst->prev_ctx_inst != NULL) ctx->action(ctx->name, entering, ctx_inst->prev_ctx_inst->ctx->name, ctx->nb_data, ctx->data); else ctx->action(ctx->name, entering, NULL, ctx->nb_data, ctx->data); } /* For each instance of options. */ /* """"""""""""""""""""""""""""" */ while (opt_inst_node != NULL) { opt_inst = (opt_inst_t *)(opt_inst_node->data); ll_strarray(opt_inst->values_list, opt_inst->values_list->head, &nb_args, &args); opt = opt_inst->opt; /* Launch the attached action if any. */ /* """""""""""""""""""""""""""""""""" */ if (opt->action != NULL) opt->action(ctx->name, opt->name, opt_inst->par, nb_args, args, opt->nb_data, opt->data, ctx->nb_data, ctx->data); if (opt_inst->next_ctx_inst != NULL) evaluate_ctx_inst(opt_inst->next_ctx_inst); if (args != NULL) free(args); opt_inst_node = opt_inst_node->next; } /* Call the exiting action attached to this context if any. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ctx->action != NULL) { if (ctx_inst->prev_ctx_inst != NULL) ctx->action(ctx->name, exiting, ctx_inst->prev_ctx_inst->ctx->name, ctx->nb_data, ctx->data); else ctx->action(ctx->name, exiting, NULL, ctx->nb_data, ctx->data); } } /* ============================================================ */ /* Create and initializes a new context. */ /* - allocate space. */ /* - name it. */ /* - initialize its option with a few of their characteristics. */ /* ============================================================ */ void ctxopt_new_ctx(char * name, char * opts_specs) { ctx_t * ctx; char * p; if (!ctxopt_initialized) fatal_internal("Please call ctxopt_init first."); ctx = xmalloc(sizeof(ctx_t)); /* Validates the context name: */ /* ALPHA+(ALPHANUM|_)* */ /* """"""""""""""""""""""""""" */ p = name; if (!isalpha(*p)) fatal_internal("A context name must start with a letter: %s.", name); p++; while (*p) { if (!isalnum(*p) && *p != '_') fatal_internal("A context name must only contain letters, " "numbers or '_': %s.", name); p++; } ctx->name = xstrdup(name); ctx->opt_list = ll_new(); /* List of options legit in this context. */ ctx->incomp_list = ll_new(); /* List of incompatible options strings. */ ctx->req_list = ll_new(); /* List of opts/required opts tuples (str). */ ctx->par_bst = NULL; ctx->data = NULL; ctx->action = NULL; /* The first created context is the main one. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (contexts_bst == NULL) { main_ctx = ctx; cur_state->ctx_name = ctx->name; } if (init_opts(opts_specs, ctx) == 0) exit(EXIT_FAILURE); if (bst_find(ctx, &contexts_bst, ctx_compare) != NULL) fatal_internal("The context %s already exists.", name); else bst_search(ctx, &contexts_bst, ctx_compare); } /* ==================================================== */ /* Display a usage screen limited to a specific context */ /* IN: the context name. */ /* IN: what to do after (continue or exit the program) */ /* possible values: continue_after, exit_after. */ /* ==================================================== */ void ctxopt_ctx_disp_usage(char * ctx_name, usage_behaviour action) { ctx_t * ctx; ll_t * list; int has_optional = 0; int has_ellipsis = 0; int has_rule = 0; int has_generic_arg = 0; int has_ctx_change = 0; int has_early_eval = 0; if (!flags.display_usage_on_error) return; ctx = locate_ctx(ctx_name); if (ctx == NULL) fatal_internal("Unknown context %s.", ctx_name); if (cur_state->ctx_par_name == NULL) printf("\nSynopsis:\n%s \\\n", cur_state->prog_name); else printf("\nSynopsis for the context introduced by %s:\n", cur_state->ctx_par_name); list = ctx->opt_list; print_options(list, &has_optional, &has_ellipsis, &has_rule, &has_generic_arg, &has_ctx_change, &has_early_eval); print_before_constraints(list); print_explanations(has_early_eval, has_ctx_change, has_generic_arg, has_optional, has_ellipsis, has_rule); if (action == exit_after) exit(EXIT_FAILURE); } /* =================================================== */ /* Display a full usage screen about all contexts. */ /* IN: what to do after (continue or exit the program) */ /* possible values: continue_after, exit_after. */ /* =================================================== */ void ctxopt_disp_usage(usage_behaviour action) { ll_t * list; int has_optional = 0; int has_ellipsis = 0; int has_rule = 0; int has_generic_arg = 0; int has_ctx_change = 0; int has_early_eval = 0; if (!flags.display_usage_on_error) return; if (main_ctx == NULL) fatal_internal("At least one context must have been created."); /* Usage for the first context. */ /* """""""""""""""""""""""""""" */ printf("\nAllowed options in the base context:\n"); list = main_ctx->opt_list; print_options(list, &has_optional, &has_ellipsis, &has_rule, &has_generic_arg, &has_ctx_change, &has_early_eval); /* Dependency constraints between options. */ /* """"""""""""""""""""""""""""""""""""""" */ print_before_constraints(list); /* Usage for the other contexts. */ /* """"""""""""""""""""""""""""" */ bst_walk(contexts_bst, bst_print_ctx_cb); /* Contextual syntactic explanations. */ /* """""""""""""""""""""""""""""""""" */ print_explanations(has_early_eval, has_ctx_change, has_generic_arg, has_optional, has_ellipsis, has_rule); if (action == exit_after) exit(EXIT_FAILURE); } /* ************************************ */ /* Built-in constraint check functions. */ /* ************************************ */ /* ============================================================= */ /* This constraint checks if each arguments respects a format as */ /* defined for the scanf function. */ /* return 1 if yes and 0 if no. */ /* ============================================================= */ int ctxopt_format_constraint(int nb_args, char ** args, char * value, char * par) { int rc = 0; char x[256]; char y; char * format; if (nb_args != 1) fatal_internal("Format constraint, invalid number of parameters."); if (strlen(value) > 255) value[255] = '\0'; format = xstrdup(args[0]); format = strappend(format, "%c", (char *)0); rc = sscanf(value, format, x, &y); if (rc != 1) fprintf(stderr, "The argument %s of %s does not respect the imposed format %s.", value, par, args[0]); free(format); return rc == 1; } /* ================================================================== */ /* This constraint checks if each arguments of the option instance is */ /* between a minimum and a maximum (inclusive). */ /* return 1 if yes and 0 if no. */ /* ================================================================== */ int ctxopt_re_constraint(int nb_args, char ** args, char * value, char * par) { regex_t re; if (nb_args != 1) fatal_internal( "Regular expression constraint, invalid number of parameters."); if (regcomp(&re, args[0], REG_EXTENDED) != 0) fatal_internal("Invalid regular expression %s.", args[0]); if (regexec(&re, value, (size_t)0, NULL, 0) != 0) { fprintf(stderr, "The argument %s of %s doesn't match the constraining " "regular expression %s.", value, par, args[0]); return 0; } regfree(&re); return 1; } /* ================================================================== */ /* This constraint checks if each arguments of the option instance is */ /* between a minimum and a maximum (inclusive). */ /* return 1 if yes and 0 if no. */ /* ================================================================== */ int ctxopt_range_constraint(int nb_args, char ** args, char * value, char * par) { long min, max; char c; char * ptr; int n; long v; int min_only = 0; int max_only = 0; if (nb_args != 2) fatal_internal("Range constraint, invalid number of parameters."); if (strcmp(args[0], ".") == 0) max_only = 1; else n = sscanf(args[0], "%ld%c", &min, &c); if (!max_only && n != 1) fatal_internal("Range constraint, min: invalid parameters."); if (strcmp(args[1], ".") == 0) min_only = 1; else n = sscanf(args[1], "%ld%c", &max, &c); if (!min_only && n != 1) fatal_internal("Range constraint, max: invalid parameters."); if (min_only && max_only) fatal_internal("Range constraint, invalid parameters."); errno = 0; v = strtol(value, &ptr, 10); if (errno || ptr == value) return 0; if (min_only) { if (v < min) { fprintf(stderr, "The argument %ld of %s is not greater than or equal to %ld.", v, par, min); return 0; } else return 1; } else if (max_only) { if (v > max) { fprintf(stderr, "The argument %ld of %s is not less than or equal to %ld.", v, par, max); return 0; } else return 1; } else if (v < min || v > max) { fprintf(stderr, "The argument %ld of %s is not between %ld and %ld.", v, par, min, max); return 0; } return 1; /* Check passed. */ } /* =============================================================== */ /* This function provides a way to set the behaviour of a context. */ /* =============================================================== */ void ctxopt_add_global_settings(settings s, ...) { va_list(args); va_start(args, s); switch (s) { case error_functions: { typedef void fn(errors e, state_t * state); void (*function)(errors e, state_t * state); errors e; e = va_arg(args, errors); function = va_arg(args, fn *); err_functions[e] = function; break; } default: break; } va_end(args); } /* ================================================================ */ /* This function provides a way to set the behaviour of an option. */ /* It can take a variable number of arguments according to its */ /* first argument: */ /* - parameter: */ /* o a string containing an option name and all its possible */ /* parameters separates by spaces, tabs or commas (char *) */ /* (e.g: "help -h -help"). */ /* - actions: */ /* o a string containing an option name. */ /* o a pointer to a function which will be called at evaluation */ /* time. */ /* - constraints: */ /* o a string containing an option name. */ /* o a pointer to a function to check if an argument is valid. */ /* o a strings containing the arguments to this function. */ /* ================================================================ */ void ctxopt_add_opt_settings(settings s, ...) { opt_t * opt; void * ptr = NULL; va_list(args); va_start(args, s); switch (s) { /* This part associates some command line parameters to an option. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case parameters: { char * opt_name; char * params; /* The second argument must be a string containing: */ /* - The name of an existing option. */ /* - a list of parameters with a leading dash (-). */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ ptr = va_arg(args, char *); opt_name = ptr; if (opt_name != NULL) { if ((opt = locate_opt(opt_name)) != NULL) { ptr = va_arg(args, char *); params = ptr; if (!opt_set_parms(opt_name, params)) fatal_internal( "Duplicated parameters or bad settings for the option %s.", params); } else fatal_internal("Unknown option %s.", opt_name); } else fatal_internal( "ctxopt_opt_add_settings: parameters: not enough arguments."); /* Here opt is a known option. */ /* """"""""""""""""""""""""""" */ if (opt->params != NULL) fatal_internal("Parameters are already set for %s.", opt_name); else { size_t n; size_t l = strlen(params); opt->params = xstrdup(params); while ((n = strcspn(opt->params, " \t")) < l) opt->params[n] = '|'; } break; } /* This part associates a callback function to an option. */ /* This function will be called when an instance of an option */ /* is evaluated. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case actions: { void * data; void (*function)(); int nb_data = 0; /* The second argument must be the name of an existing option. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ ptr = va_arg(args, char *); if ((opt = locate_opt(ptr)) != NULL) { typedef void fn(char *, char *, char *, int, char **, int, void *, int, void **); /* The third argument must be the callback function. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ function = va_arg(args, fn *); opt->action = function; /* The fourth argument must be a pointer to an user's defined */ /* variable or structure that the previous function can manage. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while ((data = va_arg(args, void *)) != NULL) { nb_data++; opt->data = xrealloc(opt->data, nb_data * sizeof(void *)); opt->data[nb_data - 1] = data; } opt->nb_data = nb_data; } else fatal_internal("Unknown option %s.", ptr); break; } /* This part associates a list of functions to control some */ /* characteristics of the arguments of an option. */ /* Each function will be called in order and must return 1 */ /* to validate the arguments. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case constraints: { char * value; constraint_t * cstr; int (*function)(); /* The second argument must be a string. */ /* """"""""""""""""""""""""""""""""""""" */ ptr = va_arg(args, char *); if ((opt = locate_opt(ptr)) != NULL) { typedef int fn(int, char **, char *); /* The third argument must be a function. */ /* """""""""""""""""""""""""""""""""""""" */ function = va_arg(args, fn *); cstr = xmalloc(sizeof(constraint_t)); cstr->constraint = function; /* The fourth argument must be a string containing the argument of */ /* The previous function separated by spaces or tabs. */ /* Theses arguments will be passed to the previous function */ /* max: 32 argument! */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ value = xstrdup(va_arg(args, char *)); cstr->to_free = value; cstr->args = xcalloc(sizeof(char *), 32); cstr->nb_args = str2argv(value, cstr->args, 32); ll_append(opt->constraints_list, cstr); } else fatal_internal("Unknown option %s.", ptr); break; } /* This part allows to indicate that an option must be evaluated */ /* after a list of other options. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case after: { char * str; /* The second argument must be a string. */ /* """"""""""""""""""""""""""""""""""""" */ ptr = va_arg(args, char *); if ((opt = locate_opt(ptr)) != NULL) { char * end_str; char * opt_name; opt_t * opt_before; ptr = va_arg(args, char *); str = xstrdup(ptr); ltrim(str, " \t"); rtrim(str, " \t", 0); /* Feed the list of options to be evaluated after the given option. */ /* This list will contain pointers to options. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ opt_name = xstrtok_r(str, " \t,", &end_str); if (opt_name != NULL) { if ((opt_before = locate_opt(opt_name)) != NULL) { ll_append(opt->eval_before_list, opt_before); while ((opt_name = xstrtok_r(NULL, " \t,", &end_str)) != NULL) { if ((opt_before = locate_opt(opt_name)) != NULL) ll_append(opt->eval_before_list, opt_before); else fatal_internal("Unknown option %s.", opt_name); } } else fatal_internal("Unknown option %s.", opt_name); } else fatal_internal("Not enough options to be evaluated after %s.", opt->name); free(str); } else fatal_internal("Unknown option %s.", ptr); break; } /* This part allows to indicate that an option must be evaluated */ /* before a list of other options. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case before: { char * str; /* The second argument must be a string. */ /* """"""""""""""""""""""""""""""""""""" */ ptr = va_arg(args, char *); if ((opt = locate_opt(ptr)) != NULL) { char * end_str; char * opt_name; opt_t * opt_before; ptr = va_arg(args, char *); str = xstrdup(ptr); ltrim(str, " \t"); rtrim(str, " \t", 0); /* Feed the list of options to be evaluated before the given option. */ /* This list will contain pointers to options. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ opt_name = xstrtok_r(str, " \t,", &end_str); if (opt_name != NULL) { if ((opt_before = locate_opt(opt_name)) != NULL) { ll_append(opt_before->eval_before_list, opt); while ((opt_name = xstrtok_r(NULL, " \t,", &end_str)) != NULL) { if ((opt_before = locate_opt(opt_name)) != NULL) ll_append(opt_before->eval_before_list, opt); else fatal_internal("Unknown option %s.", opt_name); } } else fatal_internal("Unknown option %s.", opt_name); } else fatal_internal("Not enough options to be evaluated before %s.", opt->name); free(str); } else fatal_internal("Unknown option %s.", ptr); break; } default: break; } va_end(args); } /* =============================================================== */ /* This function provides a way to set the behaviour of a context. */ /* =============================================================== */ void ctxopt_add_ctx_settings(settings s, ...) { ctx_t * ctx; va_list(args); va_start(args, s); switch (s) { /* Add a set of mutually incompatible options in a context. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case incompatibilities: { void * ptr; ll_t * list; size_t n; char * str; ptr = va_arg(args, char *); if ((ctx = locate_ctx(ptr)) != NULL) { ptr = va_arg(args, char *); list = ctx->incomp_list; str = xstrdup(ptr); ltrim(str, " \t"); rtrim(str, " \t", 0); n = strcspn(str, " \t"); if (n > 0 && n < strlen(str)) ll_append(list, str); else fatal_internal( "Not enough incompatible options in the string: \"%s\".", str); } else fatal_internal("Unknown context %s.", ptr); break; } case requirements: { void * ptr; ll_t * list; size_t n; char * str; ptr = va_arg(args, char *); if ((ctx = locate_ctx(ptr)) != NULL) { ptr = va_arg(args, char *); list = ctx->req_list; str = xstrdup(ptr); ltrim(str, " \t"); rtrim(str, " \t", 0); n = strcspn(str, " \t"); if (n > 0 && n < strlen(str)) ll_append(list, str); else fatal_internal("Not enough required options in the string: \"%s\".", str); } else fatal_internal("Unknown context %s.", ptr); break; } /* Add functions which will be called when */ /* entering and exiting a context. */ /* """"""""""""""""""""""""""""""""""""""" */ case actions: { void * ptr; void * data; int (*function)(); int nb_data = 0; ptr = va_arg(args, char *); if ((ctx = locate_ctx(ptr)) != NULL) { typedef int fn(char *, direction, char *, int, void **); function = va_arg(args, fn *); ctx->action = function; while ((data = va_arg(args, void *)) != NULL) { nb_data++; ctx->data = xrealloc(ctx->data, nb_data * sizeof(void *)); ctx->data[nb_data - 1] = data; } ctx->nb_data = nb_data; } else fatal_internal("Unknown context %s.", ptr); break; } default: break; } va_end(args); } smenu-0.9.17/ctxopt.h000066400000000000000000000056431400523266500144440ustar00rootroot00000000000000/* ################################################################### */ /* This Source Code Form is subject to the terms of the Mozilla Public */ /* License, v. 2.0. If a copy of the MPL was not distributed with this */ /* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* ################################################################### */ #ifndef CTXOPT_H #define CTXOPT_H typedef enum { parameters, constraints, actions, incompatibilities, requirements, error_functions, before, after, } settings; typedef enum { entering, exiting } direction; typedef enum { CTXOPTNOERR = 0, CTXOPTMISPAR, CTXOPTREQPAR, CTXOPTMISARG, CTXOPTDUPOPT, CTXOPTUNKPAR, CTXOPTINCOPT, CTXOPTCTEOPT, CTXOPTCTLOPT, CTXOPTCTGOPT, CTXOPTCTEARG, CTXOPTCTLARG, CTXOPTCTGARG, CTXOPTUNXARG, CTXOPTERRSIZ } errors; typedef enum { continue_after, exit_after } usage_behaviour; typedef struct state_s { char * prog_name; /* base name of the program name. */ char * ctx_name; /* current context name. */ char * ctx_par_name; /* parameter which led to this context. */ char * opt_name; /* current option name. */ int opts_count; /* limit of the number of occurrences of * | the current option. */ int opt_args_count; /* limit of the number of parameters of * | the current option. */ char * pre_opt_par_name; /* parameter before the current one. */ char * cur_opt_par_name; /* current parameter. */ char * cur_opt_params; /* All the option's parameters. */ char * req_opt_par_needed; /* Option's params in the missing * | required group of optrions. */ char * req_opt_par; /* Option's params of the option which * | required one of the parameter in * | req_opt_par_needed to also be present * | in the current context. */ } state_t; void ctxopt_init(char * prog_name, char * flags); void ctxopt_analyze(int nb_words, char ** words, int * rem_count, char *** rem_args); void ctxopt_evaluate(void); void ctxopt_new_ctx(char * name, char * opts_specs); void ctxopt_ctx_disp_usage(char * ctx_name, usage_behaviour action); void ctxopt_disp_usage(usage_behaviour action); void ctxopt_add_global_settings(settings s, ...); void ctxopt_add_ctx_settings(settings s, ...); void ctxopt_add_opt_settings(settings s, ...); int ctxopt_format_constraint(int nb_args, char ** args, char * value, char * par); int ctxopt_re_constraint(int nb_args, char ** args, char * value, char * par); int ctxopt_range_constraint(int nb_args, char ** args, char * value, char * par); void ctxopt_free_memory(void); #endif smenu-0.9.17/examples/000077500000000000000000000000001400523266500145605ustar00rootroot00000000000000smenu-0.9.17/examples/lvm_menu/000077500000000000000000000000001400523266500164025ustar00rootroot00000000000000smenu-0.9.17/examples/lvm_menu/README000066400000000000000000000006701400523266500172650ustar00rootroot00000000000000This is an example of bash tool to build a customized LVM management menu. First, make sure to make menu.sh and lvm_menu.sh executable: (chmod +x menu.sh lvm_menu.sh). menu.sh is used to create a generic menu with smenu lvm_menu.sh uses menu.sh to create a specialized menu to manage LVM objects Running lvm_menu.sh -i should display something similar to the screenshot provided. In this screenshot the user is about to delete a LV. smenu-0.9.17/examples/lvm_menu/lvm_menu.sh000066400000000000000000000022001400523266500205520ustar00rootroot00000000000000#!/usr/bin/env bash # ==================== # # Fatal error function # # ==================== # function error { echo $* >&2 exit 1 } # Check for the presence of smenu # """"""""""""""""""""""""""""""" SMENU=$(which smenu 2>/dev/null) [[ -x "$SMENU" ]] || error "smenu is not in the PATH or not executable." MENU+="\ 'Create' 'Delete' 'Extend' 'Shrink' 'VGC VG' 'VGD VG' 'VGE VG' 'VGS VG' 'LVC LV' 'LVD LV' 'LVE LV' 'LVS LV' 'PVC PV' 'PVD PV' # 'L List' # 'Quit Exit menu'" trap "exit 1" INT while true do clear echo "Executing ${0##*/}" echo MESSAGE="LVM management" read REP <<< $(echo "$MENU" | ./menu.sh -p $SMENU -i "$MESSAGE" "-Re1") case $REP in ABORT) exit 1 ;; QUIT) exit 0 ;; L) echo List ;; VGC) echo VG create ;; VGD) echo VG delete ;; VGE) echo VG expand ;; VGS) echo VG shrink ;; LVC) echo LV create ;; LVD) echo LV delete ;; LVE) echo LV expand ;; LVS) echo LV shrink ;; PVC) echo PV create ;; PVD) echo PV delete ;; esac echo echo -n "Press to continue" read done exit 0 smenu-0.9.17/examples/lvm_menu/menu.sh000066400000000000000000000042211400523266500177010ustar00rootroot00000000000000#!/usr/bin/env bash # ################################################################ # # Frontend to smenu to display a nice menu # # # # FLAGS: -p The path of the smenu program # # -i (optional) add some help in the title # # # # ARGS: $1 (required) must contain a string which will become # # the menu title # # $2... (optional) adds more options passed to smenu # # # # RC: 0 OK # # 1 KO # # ################################################################ # # ============== # # usage function # # ============== # function usage { echo "menu.sh [-i] title [smenu options]" exit 1 } declare integer INFO=0 # Option processing # """"""""""""""""" while getopts p:ih OPT 2>/dev/null do case ${OPT} in p) SMENU=${OPTARG} ;; i) INFO=1 ;; h|*) usage exit 1 ;; esac done shift $((${OPTIND} - 1)) # Menu title generation # """"""""""""""""""""" if [[ $1 ]]; then MESSAGE="$1" (( INFO )) && MESSAGE+=$'\n'"[ q=quit arrows=move ?=help ]" TITLE="-m" TITLE+=$MESSAGE$'\n' shift else TITLE="-m " fi # Menu display # """""""""""" REP=$($SMENU "$TITLE" \ -s /Exit \ -q -d -M -n 30 \ -U "Exit menu" \ -a da:3,b \ -e '^#' -E '/(^#)+(.*)$/ \2/v' \ -1 'Exit' 2,r \ -I '/([^ ]+) (.*)/\2/v' -c -w \ $1 \ || echo Abort) read KEY DUMMY <<< $REP # Action processing # """"""""""""""""" case $KEY in Abort) echo ABORT ;; ""|Quit) echo QUIT ;; *) echo $KEY ;; esac # Normal exit # """"""""""" exit 0 smenu-0.9.17/examples/lvm_menu/screenshot.png000066400000000000000000000210121400523266500212610ustar00rootroot00000000000000PNG  IHDR>V\zTXtRaw profile type exifxYv$ E /#@.xw"2.UUe]j)S$P?oH9Ԧ]H_uɓ_3|}`co}i}='zn,~e~]$x {=ۥRsY=|9T4.TrJg.[T[y+-З"< Wg?;w|?_H >WpGJf**oD=Nፋc—x7-?qNܐj:iyiĚ-ӓ9ȻxrJ;[(s-xS'֜8Y#_ n/Qbyjźex'!֞|P)sg3)VKa<}.O@vc1Ё(?ID; <H"s-Erܳ_hzޛ[&ъ0[MUk?Z;VmICmJ*MDTTTKu{}< ؆ }1g M5yʫڒ>e{y)8r3δCZjԺ rmW~ǝ]{ww_еZ~:Ϯq4~"945q==՚s޳82C2lޛpwVKٻ:S} T:uZA׎~:Bi,L-g@В9\[jMKα]żƢi^B] .eͥgކh9yƦźx'(NxΖ&k6~:j.A}r:U660 H{C%pji-iG\0- Iya3q>ecF x꩖GR6 ZjP<(;cU؜tڎ-Xt;UnNvS$ ۲)1Kזּ vS"_ FW1V5SX!N8i}Kp2dN13pL[r}_M%/4f2\,Ev! xThcJ*fiOv} WVV|idioG HfĴX[biڦ1M9w`,VeuT"ϵ&^QJZEdrSo8:ky5n|6PE=[|cݯ\]cʙ - De$5qQoGD JGs}qt<שPXCS.CwP#M`_3GR*fPxVeUՊ+cy3f8 ma|3ږo/|acZͯ{3cNP\+"t*+D%BOnEM!aբM  lvA7l]7Fj\J> HV[LұS~!i?y.ԹU&Lu27lQ7Ǥq6gtյI3ancZ +Zb[Ɇ*k\Zcin= $Tg;$2`~JAV?$syWwO9cAb3ڨ\VivBk Xo?gbzGdoK2-l@ \p? a}jkZCF}]ΞZF\:OYneL6-3H,;"<6d0uLLB>Ǔ]H5js2uQ0Dc3Amxa]a>4$3+a CZ9FFt@AJ^GY*}:/lO\{T9ݾ1KZl"'/Ēf` v"Ȱ#X:rh d kGxd*﮽b<%@ ApD[^"πt^ S42#>x<9m1 h p䕁vÒ 7ve.$9 _r~aneѥ*[?jGz6ey'o|F>_|`i7,0Ƞ4h 쎝:z;`wFiEvV9w`H!rszELxK`e;4Q;@G%DKx,lޕp28s,P 1& SS]xY S°ײW=sሊIe=ԭ08;O#~ paVa8"C`cZVQc28,chsJ1xm/"Čxߡ@zqBǽpq G ^/D2U[y'H6Drć&,,RM43db`䉜5HT/Ӫde\bD\$J y^4& cЅ[a܃>`73d/m3؋_NڲqT hV 9;)Y#V939g[1o#BwGj3mX& g^׏/f{~ |a΍os`T,IkBb,“g6;^]8I$t`Y!&JHppM\qRǢB/Hk:V&fuCdo?\{=z!džl'-Q40n@(QUS 1T=I!uٳ{*(R(HSݟƅT1#56H+<U P@%/?fj`HPu~QI3'WL#HTG+Eh60F~GJ_dOo.f#eP4o2̡JkwyVba9 w-3cDSc0h~_/,8djw"CmŖpcY E@8ˆ?VIsx@/w'y"~bs~ϪsHyo\w Jƥ5N@P2 a |?ƜU_w:y>7'Do'Bψ19>5iCCPICC profilex}=H@_S"-*vqP,_8jP! :\MGbYWWAqrtRtZxp܏wwVb1hm&11Y!LWf1'I x{zY!5k1'2ô77m>qdxԤ ?r]i bKGDH pHYs  tIME 67" hIDATxAOIǫQK+a胃1Xh|4/(,GCvFB"1ܐ"zchG9΅,:com$kl?MR`y_^U=z!Lr~+Y!dÑ+r+1alXyӞ8rL3k󹆰e1fC?3ys_b W^tt={TO1YY6k.,ʻ!.W$5|+K˙v'ot!#%mn~T둟O?GV*3*t;h1홭RyKB?fӑOdC Z~f.˲)?bycp*? 8?tVC𥉉3v2W~(?1?a&3eGэ 4~x~'#rcߑGO#hGwU*݆}X˶ޖW~N ڮd?eojDy,7\~Q/fcǬfU3iV375ߵ_+ZnIݔKͻ<;z1R;(mJUߒj5cH/x!9ȏ,jB)֏eYF~j-H)3?':X=񊔟7^N͇䊿l*)|v"]8I W p}ko)Wmuaܭ(#gIa?\lj8~57"oU~5Z~h+j>H-۪>̣&W, oБ¢4k?X#Gŏ?|Q(39X>aGMkEizȨ(*i ZM+쇛c ~Gԛla6 cejJC#W+fLm4$/^Wsy~FCX9^#U1yi2S;g7^LйFL>'%؁݁(|Ѕtٺg J64ϹWhjʛ벤뇯YMӶtGr>vT.?`FJ gFXZiy@o&{t]~f3EL%˖fEVwv(q{Ck?ɗ>AZu˞ {?j]kКD͖h97b4?jY" W$ewve85?֋ ?V_rC ۇ{ZMO@b׼Ɂ$2,79c}jn՟sDѴd:~z xGN U*>Z]u?Pisw׀Zzw p }[^-kau^@1_cWuןcƮ|nmɣ7Vnm]?g」S. '}w(eaʲQ_mm9ݖ,"'SS,ͽc?G빯R)!HJRb.JPEwI͑'RsI?sO|Z',}>K'?; ?Y'5{a|%&gv.sO9!+?w'sb~he1_|d` IENDB`smenu-0.9.17/examples/simple_menu/000077500000000000000000000000001400523266500170755ustar00rootroot00000000000000smenu-0.9.17/examples/simple_menu/README000066400000000000000000000030021400523266500177500ustar00rootroot00000000000000This example presents a simple hierarchical menu interpreter. Each menu and submenu are in a file suffixed by .mnu and is constituted by directives and menu entries/preudo-entries. Each of them are in its proper line. Comment lines are allowed and are introduced by a '#' in the first column The directives are: .columns: Set the number of columns in the menu .centered: Tell if the menu must be centered .eraseafter: Tell if the menu window must be destroyed after the selection and the old cursor location restored. .title: Set the menu tittle. The item lines has at least two fields: a tag and a menu item which will be displayed. The tag is normally the returned value when an item is selected but may also be part of a pseudo-entry. These special tags are: >xxx : Loads the submenu file xxx.mnu and interprets it. < : Reload the previous menu file and interprets it --- : Inserts an empty item in the menu === : Inserts an empty line in the menu (useful when there is more than 1 column) EXIT : Exits the menu without outputting anything. As usual, 'ENTER' triggers the selection and 'q' quits the menu without outputting anything. To launch the demo, first, make sure to make simple_menu.sh executable (chmod +x simple_menu.sh actions.sh) and enter: ./simple_menu.sh main.mnu ./actions.sh The first argument is the main menu file and the second one is the path of the program which will be called each time a selection is made. This program will be given the selected tag as argument. smenu-0.9.17/examples/simple_menu/actions.sh000066400000000000000000000002151400523266500210670ustar00rootroot00000000000000#!/usr/bin/env bash (( $# != 1 )) && exit 0 ACTION=$1 case $ACTION in *) echo "Tag $ACTION selected." sleep 1 ;; esac exit 0 smenu-0.9.17/examples/simple_menu/main.mnu000066400000000000000000000007321400523266500205440ustar00rootroot00000000000000# Directives # .columns: Number of columns in the menu # .centered: The menu will be centered # .eraseafter: The menu window will be destroyed after the selection # .title: The menu tittle .columns 2 .title Simple menu ITEM1 First item >sub1 First submenu ITEM3 Third item >sub2 Second submenu === ITEM5 Fifth item ITEM6 Sixth item ITEM7 Seventh item ITEM8 Eighth item ITEM9 Ninth item ITEM10 Tenth item === EXIT Exit without selection smenu-0.9.17/examples/simple_menu/screenshot.png000066400000000000000000000106321400523266500217620ustar00rootroot00000000000000PNG  IHDR9/0PLTE|*R14Ii6Qd~橇Aڮh@%IDATx흿oX8bvRB<k{\֨ߤ #? '&mlqZS7yJtc[`56 IiD?@yA;Ko6Z^2g$bx#d&tZeV#Xrւ?О/QkϼR`R,EЄN.\Wq&'+;}ʸ\gZ3ӨЦ Z唝:X %f!eZce`C̽g5Cv\cg~6DrnZrMxv쨸rآYnWt^ig~;\ӊ.>vsb*ʎX3ʕTsY ʑ%:bj-yK=a͖B0BLGL3h!d:ʎX34bT,}Z^j@#+X =V;p~֙}tי=X/؁؁33SNga'l0\Hu "u#=+؉;>5!"Uuot;:QĠ߹IAعvIpqoW}E}yW˵oUzzQ =''ZPkI\u|;yn-$Nwj|sڹ[1X;ZV;?o۱Ҋ1?tkA>n9(dN|Y}w3/wœQ;kzԳSLSeWhLK{];0~lToeui\vQɰ7^?G;zU`Lظ~wۊiɶ2][OD%;E}wOiCӫպQOҔ=+(F4mKFcf=9_rsF^{ڥs{bT>J0!v-Gߝ[KqL>yTW;Es35'%~osqqeYeW> kx%qjןZqe-R-hS K;̃?;i;bqele󟝨?|sѫl D}#Ֆf۪:0UMٓicc;׼I9VJg񳫖%wηc[_ؚqb+gɎ+LǾۛ\ܠ3Eto~MͦU,v~Wءoa"9ʴBvKIo2`Z!/OoG}Z>+:2+iR;+[KpU.Y"ũo8`tZr~h^þ=^iTNzV`;7K;1+-\kUkzuimydf$;kF|徴 쀾+%ƕzVxe dA?O_>9JKx9w]9U_RBp۳T^6~ ;T;VJaUT'l:H}eS y.hfF'TE<_iÏ\˛rwn~^Q/LdhSU"D"תEG~.[?Iv:U 6d iJ$rRE n6avR1Y( /#3pd$RR*U%xdǍD ߎs3lǹIͮ%DTԳgJ̓jyYKpvs46ZRE=OxTse\Z~WvMz3zƝOPcBᲯ\z 󸂨Wĕ4gٱgA}ڈ-_9eE+8b͈0c{[E};vrYV];W~{ Zqpv:Y};|bj5TI5֐e;o\r݈-Yܠs!Kwv\9ͧ6Ǧb (v^v α/~Ϊ+{Vq *8N.m|e+8YnֱW~rΊ5d}:&;Xlee'8r!KwުlbMqԷ[@Y =.|A}e\E}e`9T^±ӯω*aВWd&*ajgS0;AfVh"v w۴rָsU^Z&~zE.蕪n1v:\"jÚS887Zjg:\&WLܞ,ri2 \¨ToGeoU.cU ŀdݦ=cQ=kmeCvrO8ŘLcYNGq48vH}初eGrz4T;9ӳF8-&+dXkOg97 ܅e0OusiT^kj<*MQ?"c'T_ΕJ5q&ʨgJZNgtڊ>׳(WǎĸF ?d0|[IENDB`smenu-0.9.17/examples/simple_menu/simple_menu.sh000066400000000000000000000155661400523266500217630ustar00rootroot00000000000000#!/usr/bin/env bash # Variables # """"""""" PROG=${0#*/} typeset -a MENU_STACK # A stack of MENUS to store the previously visited menus # Array of menu characteristics for caching purpose # ''''''''''''''''''''''''''''''''''''''''''''''''' typeset -A MENU_ARRAY typeset -A COL_ARRAY typeset -A CENTERING_ARRAY typeset -A TITLE_ARRAY typeset -A ERASE_ARRAY SEL= # The selection SMENU= # The smenu path will be stored here # ============================ # # Usage function, always fails # # ============================ # function usage { echo "Usage: $PROG menu_file[.mnu] user_program," >&2 echo " read the README for an example" >&2 exit 1 } # ==================== # # Fatal error function # # ==================== # function error { echo $* >&2 exit 1 } # The script expects exactly one argument (the filename of the root menu). # """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" (( $# != 2 )) && usage USER_PROGRAM=$2 # ======================================================================= # # Parse a level in the menu hierarchy and call process with the selection # # (possibly empty). # # ======================================================================= # function process_menu { TITLE=$'\n'"[ENTER: select, q: abort]" # Untitled by default CENTERING="-M" # Is the menu centered in the screen ?, defaults to yes ERASE="-d" # Destroy the selection window after use. Defaults to yes MENU_FILE=$1 MENU= # Make sure the working area is empty # If the menu has already been seen, read its characteristics from the cache # else construct them. # """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" if [[ -z ${MENU_ARRAY[$MENU_FILE]} ]]; then COL=1 # Parse the directives embedded in the menu file # """""""""""""""""""""""""""""""""""""""""""""" MENU_DIRECIVES=$(grep '^\.' $MENU_FILE) while read DIRECTIVE VALUE; do case $DIRECTIVE in .columns) # Number of columns of the menu COL=$VALUE (( COL < 1 || COL > 15 )) && error "$DIRECTIVE, bad value" ;; .centered) # Is the menu centered? [[ $VALUE == no ]] && CENTERING="" ;; .eraseafter) # Will the space used by the menu be reclaimed? [[ $VALUE == no ]] && ERASE="" ;; .title) # The menu title TITLE="$VALUE"$'\n'$TITLE ;; *) error "bad directive $DIRECTIVE" ;; esac done <<< "$MENU_DIRECIVES" # Build the menu entries in the working area # """""""""""""""""""""""""""""""""""""""""" MENU_LINES=$(grep -v -e '^\.' -e '^#' -e '^[ \t]*$' $MENU_FILE) # The special tag "---" creates an empty entry (a hole in a column) # The special tag "===" create an empty line # The special tag "EXIT" permit to exit the menu # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' while read TAG VALUE; do ITEMS_TO_ADD=1 # By default, only one iteration of the tag is taken # into account (( ${#TAG} > 30 )) \ && error "Menu tag \"${TAG}\" too long (max 30 characters)." [[ $TAG == --- ]] && VALUE=@@@ [[ $TAG == === ]] && VALUE=@@@ && ITEMS_TO_ADD=COL [[ -z $VALUE ]] && error "Empty menu entry for $TAG" [[ $TAG == EXIT ]] && TAG="@EXIT@xxxxxxxxxxxxxxxxxxxxxxxx00" [[ $TAG == "<"* ]] && TAG=" 0 )); do MENU+="'$TAG $FINAL_VALUE'"$'\n' done done <<< "$MENU_LINES" # Feed the cache # """""""""""""" MENU_ARRAY[$MENU_FILE]="$MENU" COL_ARRAY[$MENU_FILE]=$COL CENTERING_ARRAY[$MENU_FILE]=$CENTERING TITLE_ARRAY[$MENU_FILE]=$TITLE ERASE_ARRAY[$MENU_FILE]=$ERASE else # Read from the cache # """"""""""""""""""" MENU="${MENU_ARRAY[$MENU_FILE]}" COL=${COL_ARRAY[$MENU_FILE]} CENTERING=${CENTERING_ARRAY[$MENU_FILE]} TITLE=${TITLE_ARRAY[$MENU_FILE]} ERASE=${ERASE_ARRAY[$MENU_FILE]} fi # Display the menu and get the selection # """""""""""""""""""""""""""""""""""""" SEL=$(echo "$MENU" | $SMENU \ $CENTERING \ $ERASE \ -N \ -F -D o:30 i:0 n:2 \ -n \ -a m:0/6 \ -m "$TITLE" \ -t $COL \ -S'/@@@/ /' \ -S'/^[^ ]+ //v' \ -e @@@) SEL=${SEL%% *} } # Check for the presence of smenu # """"""""""""""""""""""""""""""" SMENU=$(which smenu 2>/dev/null) [[ -x "$SMENU" ]] || error "smenu is not in the PATH or not executable." # Initialize the menu stack with the argument # """"""""""""""""""""""""""""""""""""""""""" MENU_STACK+=(${1%.mnu}.mnu) # And process the main menu # """"""""""""""""""""""""" process_menu ${1%.mnu}.mnu # According to the selection, navigate in the submenus or return # the tag associated with the selected menu entry. # """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" while true; do if [[ $SEL == "<"* ]]; then # Back to the previous menu # ''''''''''''''''''''''''' if (( ${#MENU_STACK[*]} == 1 )); then process_menu ${MENU_STACK[-1]} else # Unstack the newly found submenu # ''''''''''''''''''''''''''''''' unset MENU_STACK[-1] # And generate the previous menu # '''''''''''''''''''''''''''''' process_menu ${MENU_STACK[-1]} fi elif [[ $SEL == ">"* ]]; then # Enter the selected submenu # '''''''''''''''''''''''''' SMENU_FILE=${SEL#>} SMENU_FILE=${SMENU_FILE%.mnu}.mnu [[ -f $SMENU_FILE ]] || error "The file $SMENU_FILE was not found/readable." # Stack the newly found submenu # ''''''''''''''''''''''''''''' MENU_STACK+=($SMENU_FILE) # And generate the submenu # '''''''''''''''''''''''' process_menu $SMENU_FILE else # An empty selection means than q or ^C has been hit # '''''''''''''''''''''''''''''''''''''''''''''''''' [[ -z $SEL ]] && exit 0 # Output the selected menu tag or exit the menu without outputting # anything. # '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' [[ $SEL == @EXIT@* ]] && exit 0 # Lauch the user action which has the responsibility to act according # to the tag passed as argument. # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' $USER_PROGRAM $SEL # And re-generate the current menu # '''''''''''''''''''''''''''''''' process_menu ${MENU_STACK[-1]} fi done smenu-0.9.17/examples/simple_menu/sub1.mnu000066400000000000000000000002271400523266500204710ustar00rootroot00000000000000.columns 1 .title First submenu SUB1ITEM1 First item of the first submenu SUB1ITEM2 Second item of the first submenu === < Previous Menu smenu-0.9.17/examples/simple_menu/sub2.mnu000066400000000000000000000002321400523266500204660ustar00rootroot00000000000000.columns 2 .title Second submenu SUB2ITEM1 First item of the second submenu SUB2ITEM2 Second item of the second submenu === < Previous Menu smenu-0.9.17/examples/yesno/000077500000000000000000000000001400523266500157155ustar00rootroot00000000000000smenu-0.9.17/examples/yesno/README000066400000000000000000000005351400523266500166000ustar00rootroot00000000000000With this example you will discover how easily you can ask a user to confirm a previous choice First, make sure to make yesno.sh executable (chmod +x yesno.sh) and enter: ./yesno.sh The screenshot shows three use cases, one when just hitting 'Enter', one when moving the cursor to YES before hitting 'Enter' and the last one when just hitting 'q' smenu-0.9.17/examples/yesno/screenshot.png000066400000000000000000000411321400523266500206010ustar00rootroot00000000000000PNG  IHDR>V"wzTXtRaw profile type exifx͛[\E1 ϵz=Eٖ%?ZYdVֽD?}_>\^s4?_:>~_uw7l|o?ak;y=f]^h}.Ev`.(xRH?c }~~d/^ /9ؐ_WAl򏿹?͏P~zyK:\Q;w}nӍ\ͨexd/w~u~5?"/?B\rab9HLb+Z#F=.Ň+h\x9\Kx~+4o~rͿݻEA+,Cӟ[y77E%f ˭x_맄[Ľ R 5xB`<'"cNFgXXbzl"j2b X9r#FI%Rj\eTs-Vaɲf֬hVZmZmXz[}7\k+34,Nm9*.[m5vinm=N!O:Sv\[nvw7/D-|_>5^uf?.'E1#b1"n 3BQS|E,(6nEbg?7Wڟ[Ws EmzT'B+;\_+$zW=Nn_*cɍ>kAf_EC~߶?72C߭:K!̆ro2섴w5]z~k;u7C.48grM%X1+Ӹ쉛Y)Z֣;3V Kt7:r82m%wɪH~J*ij̍,T{uR[Y H횷E+O GW}*?r]Ꝭx3qz.Z'ר8Ҽ6afZ%YجOߏ\5К~\JULvژujό[ĀڱoؕK6$(BeLDP^i]n7scFJ}Q>v-cc;l<ֳm<_%PGe^WMk'CSVj?2@7cjE "j=de|%rrlJg)zn<<(1™x,W~&Ҷ;J r@N2Yl< Z?O4oE@+ã!Po6־:C3&?'wD'ИJ?gy[AlUZܫnS]T, zc֕nIBmP$V'pʏD)M.S2{ļi D@? rB!Fin774tN O:Z@YME7=M}gnVDv5ٕ?0f%vsA, 1hvT J,}3M@m93 N/K*N޽ih'l VbB x6!yXd"Opz9 Nh˓fp28$TPw$*4WJf&E Zdmz+3'قnx:JliI!" uyZاunɀ\" roT3$ 3UϮQ7M0-,w6Pfo[L0hzHN|7~o! nHg,8X]Mmd1]\g"]IzKN2|3C^ 1/`.tϘwQcIaHj@?H ݌Iּk:~.@ 8}KB5vΉxYHȸf{ /Ű$t'=~g-RA(@GR4?!Y0ss@G023^,'i9JaY|?ި*(_Gxl R9KEhP ގ@I=R+ U@:=Qܱ*kk6$o-@,2kh;*ڒxo#bH"Zw5(9{6[rD zt, ܏܇ʒ,/SRx((Bi9]ir▢6{PlFSUPbZ暲dWJ$,{{:$˚"F\P:!'6ޅ@'y(==pE @%(ZU2EN\Bf3`b]T'ܾ<<47 MB$Ja4l, x.VDk 'i 1p,FlCJ%𧄱]|Q 791"j-e+ hS ƽ#+h\`*H2$Ldʒ _|{lR*{mA*װ\<_R'.һ\p \Pp/h! TCK $r>-%C hMn\Ix-(% *b<#*| 'zz Bƅnpؐ nP 2}xp?PD I)+91\<9XghGpa&1P[u.vb UI\pԾ8%&0t7ts+gMc%"nV5F{:Z9KC\75\OH^8A.>> .de{DÒ^a-C9~t5Gl [5W YccDŽ#xzo@ Fy 0)().lόC^=XzRj|Hޠ@`|-E nxE9 O~-&xw֒M ^1~~8 vCόWRgDh0 kjb{=B<Ȋ`Z.Ba;aC$ײmxSω1`ӀxJ vT# 0%Y>?8__w~.\@DxPlrHom@ɲI cAؗ9ƒWb2Fn*bݍ|߱뵋@thRjK][,PZ(Q$+GPE򧖩9h'Zt$ f^0#ഀx ƐkeVȃMAWϐShH\ Q(H,C-޲]&`D{$$ǎD<\pGv у(C@`aX'wFP\SɀYJxp5"(k,Dϱ.|UGg%rjRM-#?J|k83RroPQc&@Ƴ8YjsÌH1쪼p"5L- Vzlj[ LB%ns0=Ĩ$08bJ2gq^pq@CX!b[cqs'%; qKGpön$dkGkEDwR :NǢ76-WĄ:2WW‚ZcCB:XU""F`rXc/43N .WBNqĽZMҘbRFx_\Y#THG,(u1xlV[AuY*I"h!tQ lFl2qD,~dxDER*&TC XlOAM%[6o"{ʜG~@zXyj7<\NM-&$Cc0*EԧVR";Hd5lv4-Cws°PX;%h)u9mlS= LqPP](Pt<<v\TYhrljru(9 MU'Pġ!h j]2'։[LpxStXl¥\JuWլ[6rQ6 ԑ4\Hw;g%^l^!*XbT*'29hH Ub7 W9 9"YV;.c$BjIk4?Z(?v`)||ۉ.h[_0fʰ.p+IU'] '{eLEň}j)ܧ WzSpEIm3vB0+ U pk;+jL V'<6%h4 qHCS*qw>l"*(; o=9Iѣ$@@|PoPM_bCHj&9Ҍ*' ip81u  sID{7*{wB"H꜐Y= z7rܱPcg= u,Ŷ&M~WѢI4䋃ܛZvԔx`!OT"Jg:: 6Kn1,!J  % |2Uw쁆1DvYv¤ xSgu(y+XK!:"^)M#l$i:9S\ʾ|FK6C>`jqCwI|nY7N#Wu$iC)s04Xu8(-M!D͸F%T.N&Ne )f L&7j!_dQ(M݂GP ^dlG XEzB5%5̨#GiQ(լ )rvQ%少cyF$wס:hk-6:BG%쎬 y4@E.W=ܬF$ٝKWQX" $b@ 3Ⱦʍ"+ i;76տ%b6YBvt, .pS\7oj9F HP?aRQ:5P~י j_@IBb[;.hoM0b\Pc}+'DiZ0y$^x+L^fl09 a 2驱U;@}5T1M8 ";pisPFdj93!j!hȁd42\|uFmVsIڨjpX@b"Nuˆ Gt2 xfu.瀉>`)E \O5Jw7Mt9vZlaÊv.@@4&$-> c$F&) 4/:B]Ly:vбQxY!b75ZC~gu-VXYg$&_b&DIf3WbSRP<r8Xf0:nH;PhSՑ uG?aAn:OR:/a7jA"$kijGiNKdbɕM;nU~-cjj'FfNDr! X[unVT_#(A;8$(u6,ǮO6 =5t-ҤS=K +rM>t{l-Q&FU|'Wx:uړ9t< :d,+D7Qkl'h6#*M]22F[v_4JD=)S!GO$1CblMc}? \u[NTtY1v7D=붓ܷ0Taefuci b+uJT5;fp N,^-w44"蚦@%_QŁ,IM~+{]&hKeot&H0D*7( zY 3?43j[hjFz3$Q [%@H(TdA'Z,R,=H>z3NU R1)3" AekT9CܸIYVpu΃&%6IScAu;@RR, W(V`;,5W$Pi&Q^o_6 =PU@,MM1\ʟjC'}dA0;l@ { b8miUҷZSs`n%zkn]P?u3$yhC)Q jmuyD}" =0 dK%X\&FƯt^t[Ph{۞4EVuD6 ez(Xtj@}h u\Ԁv#8"'h`UkfpFf/&o_o80y9>Y>H՘&n{qNDER[_o)<@N8q?vS2ń` U|Qv-i8t ҆&PKT_5l^zRhxiSkQ۫6|GMiMڋ-0Mj vjB5 4Zf vA+,Qfz<̺ăPFHGqO!|ԭ1H>}Аʘ#%{ ,Pi wi dm4Z!]쉆[phZ ;=d?q4- ŻxrawI/,Y gk*riڞD7?1,bg"p]>-inFP[];3G ]q B}9YWg6ÐE'{F}!vo*KVCEu7$w4LHW,n є(-[ qH~-7~oDT+G)/#wp>99S3InQJ>KC'`v ¼0P`Y)g?=?_)> ݚhd \5i,P}LU;shcU3QvY 4CS"4)OA g\_{!8n BiCCPICC profilex}=HPOS""vqP,8jP! :GhҐ8 .κ: x_Rh8{B4c tL'b6"^Bz@Df1+I)=QyߟQ" 3Lxxj68GYIVωGM #8]xf̤爣b6f%S#$NBcg\e{i !,BUl quR,<trmch]?U q>.Ш94N3p:0IzŎm⺥){0dȦJAZB7[{՛[@f"e}n4Lrq0PLTEUUU**UU**UU***UԪԪ|bKGDH pHYs  tIME1YIDATxoFƋ*J4Kz"O{Ei{Iӥm fOs[ 6PNrF4X BB E{f{Un#dG#!]dU_Ujc$EQr1Y3RSTcVI'Ls@<B ˰r'fN:4*z)dcϮ'vFX#׽׭nE#L6"b[:>nvw<)ՎL;:N{,8r|t|ݽ1*6j0k0LTAJU;Fݮ#F˼I@mq̬=գ'0K!"= !$>$D"!{uk3zX N<lDxJ;Ja٘YC>n=gs2N(R%A=IU(vbnR,9!Dc>C#2q~u,ߧvGjbm<| &ZJ=1ᱵo w'7Gkxb|-4n,x CΝXV)8f? /I/'eG7'pkUΌ՚9+YR1/t6B.,?TkDZ^gqk> [5)ruˏ||A-r:8lq_OXtV1kćD"r-V2ۋo'ɅKEjX3Ojɏ9yl>J5$;9H,証\xSw>|0 ,6cnχu|xFvٞyKYƷT$CZeEw}kf[(uRΐթmoeErU|x._z|dg >v5b7UrQ<07Oz'ԵlBNȢ6aPn A (g< lˣ+cby3ϧP;?uUs|&qBc+&ڍ L{b'a}zNd|tz e|IY:y>Z2g'+/Z >i9Aƛv}h([cmjӖ2{G᳐.b;+D.Y N][bźؠGxؿOC[1b;R>Jl:U140_d|` TdGǝKA8ӊfZ.S*wZ. %~ysrIE:Puk!H$D"H$D"H$D*ޓJG$!>?~}H[4?+SA 5fA|d'>B>KuYgk*hN4*>|6B>SMQnN[7MJ{ܖuV_n**h{>f;Ss_֨|&>fxFY>U^*|},o4VSZOYoD<m1,ve|?1ύJY{|`?/'<7~V|͂/C|!H$R&+:aA&,;b%z 9aJ? '$( |^3#,mCʞPs~תXC.[2Kٸ`|pӰc 'Bꀌ Ň"[ M/߄KYC؍ZS/k> ?|`K Z+)zU>?S!NUUk ɰr'VR.V=}5p$5) a\^z3$JIѐ `7;8yw"6u*,& 7Ke9AUSot,pt "Miw~nבHeSˤ NfN|8UMG]0C0JćD"H1p7d8rtnwp}@o?!މ'3͞|XYkfc1㳆|nzdhߢ ;K 'UPTB<؉M,9 ;~d<rXbHL@]?=]>Qw!  'ROE|xl݉͡Zl%^_pA;&C>*s'VU ǣK2m'|FG7'pkUΌ՚9+Yȇ1S:!Ok/38gѵ -z@:^GET>|LT-ﰵ~@fQlLVbǜeXކs ge,g[ '{p߿dpHxoe|eeS6$UA F!H\|KgU grRzѷ>vtD')[;O_2~G ~5:) _xr |>{}>Oo4?ħtڤw^~*u|8OTG7g :={f[[*KT!zXtq%>t-><̶Z;P0 !SX܋ NzGFko=\^}#aWC.vSu-z\3{wB]&,|i+m @>dQxAjٖGյ? 1 :7ؾ`Z`|ˆTa|}m_یiL'+ a|4H(3:pP sWwjx"sоu5OFT6OEQ)EA~Gtpk]aW5q^;3>]er3]X47Oi/GAo^=_k:pRdWi`žo= Y~'2>W[H̆2>$,<wNA-3h?K}>>r;_5޴{CCn>WmUyG 5dfg| .; t[dYy$r)g0uڒC-6A>2A7xؿOC[!;}1NU ةd:Y$cq'omR`괢4/:kùʝKz>h=l_^\q{ZH$D"H$D"H$D"^ɾ!>RYoo[uلY9 M4W'>YV|ăUgk*hN4*$2Y#1!ܜ o |T aF+Aye[x7O3.5o| |+>Olx%<>U^*ӻ'!츊;y>MU|5 |Ͳ >>W3mbYwl?[l,V =Q|y]t\$D_ćC"HU-h~ (I: |NXu0 |oqoS^@>Uټm~HuCZ,| A)Rz{6?4w 2)Z<Rhz&\ nV7k<- Y \j>ىTåLfAo9>Wɸ>ugjcCuT \Pt|݇J׭KXyv=Ѩ%*|׎F-f:n}6|jB7n8I_ۉq ObwZ9iI$D"H$=h5GFK FFXPnQcb@"H$D".VyyK|NPR lO?gskF_s_.;8']cq)}:R֤Il1|8r'fՄ*܉)Ia FjQ€8dj`;16!Zj(2C ;jfѧ[:-q b]5HZnKg/T_uRCO.N3>޳ x7dj{kpBxx.N 7)Nt̗!iVj6d0"Lў[ewL|ᵘ9z g 3? |7^>3zD8T'Z (nΠxem.tŶsu8Ӡ|05q2ࣣ&p#3|f+JBSוYu'k*&N'hgzb4jW336cN*l*'Sc*G1M>1FͺB#3NAxwʉ[+ 'S7\gJ]KUO~N떎/$C=E4Bu73faEφb z4Ol?Ku>cGѓ%E&3ASrD|@s}p6Pu?~2#êѳa'L ~zjSӽYػ%>z2!c<i1wnc*ZCa9-?,Ob+bQXW ɨ@|^]qC"^ (F,|gL:0s=B|>Uk0*TA5\ A-=hpK96F{[]m~\eK n]SNē--+S*ѩbұ_O62Y9?Yߕv6]G"ZyO-*4;amzt.="ӻ`a&D"Hcn4p^ZcB'c5D;zxƳ᝛7^|+aK*Cfcg NOKƝQ¥Kg{ޓP(*! ?2qg{o_&~ޞtѮA(TMǐO@TSXK'Ƣ>ᓰE/Q"_'Ÿ ʣ%Y/hì}> j[ 0? K۰r.a E|x+dwt|p"rV'`\{#eS6$UA F!H\Ry)+v\^-پyT{O~ӗgk_QBfX erON0Oׇxχ`NkKX7zgN@#эFd=M󖲚om^}Q!zXtqP@ׂ9=olA :퍵̽HϦ_z|d1g >v5b7UrQ<07Oz'ԵlBNȢΗ& @3HA匧mytu|a[GOBߛFGl^0-0e*0LٶmF4&ϰckT\8ݹ+8'Zk*eGq:\e'a-o] tѪd|07q: ~S||T kQgPuZWuOtѮ.,'ofjΠt7>&I\N4d^m.#93*t|!>:d8O%λW_NH#܉Cvjڴ;z!3;)uQd,"#KA8wזj}GN2Mc> Yo$^W}1NU ةd:Y$cq'omR`괢4/:kùʝKz>h=l_^\q{ZH$D"H$D"H$D"^ɾ!>RYoo[uلY9 M4W'>YV|ăUgk*hN4*$2Y#1!ܜ o |T aF+Aye[x7O3.5o| |+>Olx%<>U^*ӻ'!츊;y>MU|5 |Ͳ >>W3mbYwl?[l,V =Q|y]t\$D_ćC"HVo²)X$eǟ V"#V3>Jݬjj>tU*nXbjcƧF-Q hwv4j1E0qvSWkwu躝7d*{ׯS|]D"Ho#C|[!>#5!>#U%>##A| 0snS3JvL!>ćD"H$D"H$D"H$D"H$D"H$D":? wpIENDB`smenu-0.9.17/examples/yesno/yesno.sh000066400000000000000000000011151400523266500174040ustar00rootroot00000000000000#!/usr/bin/env bash # ==================== # # Fatal error function # # ==================== # function error { echo $* >&2 exit 1 } # Check for the presence of smenu # """"""""""""""""""""""""""""""" SMENU=$(which smenu 2>/dev/null) [[ -x "$SMENU" ]] || error "smenu is not in the PATH or not executable." RES=$( $SMENU -2 ^Y -1 ^N -3 ^C -s /^N -x cur 10 \ -m "Please confirm your choice:" \ <<< "YES NO CANCEL" ) [[ -z "$RES" ]] && echo "'q' was hit, exiting without selecting anything" \ || echo "You selected: $RES" exit 0 smenu-0.9.17/fgetc.c000066400000000000000000000024151400523266500142000ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html. */ /* ########################################################### */ /* ************************************************************************* */ /* Custom fgetc/ungetc implementation able to unget more than one character. */ /* ************************************************************************* */ #include #include "fgetc.h" enum { GETC_BUFF_SIZE = 16 }; static char getc_buffer[GETC_BUFF_SIZE] = { '\0' }; static long next_buffer_pos = 0; /* Next free position in the getc buffer. */ /* ======================================== */ /* Gets a (possibly pushed-back) character. */ /* ======================================== */ int my_fgetc(FILE * input) { return (next_buffer_pos > 0) ? getc_buffer[--next_buffer_pos] : fgetc(input); } /* =============================== */ /* Pushes character back on input. */ /* =============================== */ void my_ungetc(int c) { if (next_buffer_pos >= GETC_BUFF_SIZE) fprintf(stderr, "Error: cannot push back more than %d characters\n", GETC_BUFF_SIZE); else getc_buffer[next_buffer_pos++] = c; } smenu-0.9.17/fgetc.h000066400000000000000000000005461400523266500142100ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ #ifndef FGETC_H #define FGETC_H int my_fgetc(FILE * input); void my_ungetc(int c); #endif smenu-0.9.17/index.c000066400000000000000000000216321400523266500142210ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html. */ /* ########################################################### */ /* Ternary Search Tree and sorted array creation functions. */ /* Inspired by a code described in "Ternary Search Trees" by Jon */ /* Bentley and Robert Sedgewick in the April, 1998, Dr. Dobb's Journal. */ /* Links: */ /* https://www.drdobbs.com/database/ternary-search-trees/184410528?pgno=1 */ /* https://www.cs.princeton.edu/~rs/strings/tstdemo.c. */ /* ************************************************************************ */ #include #include #include #include #include #include "xmalloc.h" #include "list.h" #include "utils.h" #include "index.h" /* List of words matching the current search. */ /* """""""""""""""""""""""""""""""""""""""""" */ ll_t * tst_search_list; /* Must be initialized by ll_new() before use. */ /* ======================================= */ /* Ternary search tree insertion function. */ /* ======================================= */ tst_node_t * tst_insert(tst_node_t * p, wchar_t * w, void * data) { if (p == NULL) { p = (tst_node_t *)xmalloc(sizeof(tst_node_t)); p->splitchar = *w; p->lokid = p->eqkid = p->hikid = NULL; p->data = NULL; } if (*w < p->splitchar) p->lokid = tst_insert(p->lokid, w, data); else if (*w == p->splitchar) { if (*w == L'\0') { p->data = data; p->eqkid = NULL; } else p->eqkid = tst_insert(p->eqkid, ++w, data); } else p->hikid = tst_insert(p->hikid, w, data); return (p); } /* ====================================== */ /* Ternary search tree deletion function. */ /* User data area not cleaned. */ /* ====================================== */ void tst_cleanup(tst_node_t * p) { if (p) { tst_cleanup(p->lokid); if (p->splitchar) tst_cleanup(p->eqkid); tst_cleanup(p->hikid); free(p); } } /* ========================================================== */ /* Recursive traversal of a ternary tree. A callback function */ /* is also called when a complete string is found. */ /* Returns 1 if the callback function succeed (returned 1) at */ /* least once. */ /* The first_call argument is for initializing the static */ /* variable. */ /* ========================================================== */ int tst_traverse(tst_node_t * p, int (*callback)(void *), int first_call) { static int rc; if (first_call) rc = 0; if (!p) return 0; tst_traverse(p->lokid, callback, 0); if (p->splitchar != L'\0') tst_traverse(p->eqkid, callback, 0); else rc += (*callback)(p->data); tst_traverse(p->hikid, callback, 0); return !!rc; } /* ======================================================================= */ /* Traverses the word tst looking for a wchar and build a list of pointers */ /* containing all the sub-tst potentially leading to words containing the */ /* next wchar os the search string. */ /* ======================================================================= */ int tst_substring_traverse(tst_node_t * p, int (*callback)(void *), int first_call, wchar_t w) { static int rc; if (first_call) rc = 0; if (!p) return 0; if (p->splitchar == w) { ll_node_t * node; sub_tst_t * sub_tst_data; node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); if (p->eqkid) insert_sorted_ptr(&(sub_tst_data->array), &(sub_tst_data->size), &(sub_tst_data->count), p->eqkid); rc = 1; } tst_substring_traverse(p->lokid, callback, 0, w); if (p->splitchar != L'\0') tst_substring_traverse(p->eqkid, callback, 0, w); else if (callback != NULL) rc += (*callback)(p->data); tst_substring_traverse(p->hikid, callback, 0, w); return !!rc; } /* ======================================================================== */ /* Traverses the word tst looking for a wchar and build a list of pointers */ /* containing all the sub-tst nodes potentially leading to words containing */ /* the next wchar os the search string. */ /* ======================================================================== */ int tst_fuzzy_traverse(tst_node_t * p, int (*callback)(void *), int first_call, wchar_t w) { static int rc; wchar_t w1s[2]; wchar_t w2s[2]; w1s[1] = w2s[1] = L'\0'; if (first_call) rc = 0; if (!p) return 0; w1s[0] = p->splitchar; w2s[0] = w; if (xwcscasecmp(w1s, w2s) == 0) { ll_node_t * node; sub_tst_t * sub_tst_data; node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); if (p->eqkid != NULL) insert_sorted_ptr(&(sub_tst_data->array), &(sub_tst_data->size), &(sub_tst_data->count), p->eqkid); rc += 1; } tst_fuzzy_traverse(p->lokid, callback, 0, w); if (p->splitchar != L'\0') tst_fuzzy_traverse(p->eqkid, callback, 0, w); else if (callback != NULL) rc += (*callback)(p->data); tst_fuzzy_traverse(p->hikid, callback, 0, w); return !!rc; } /* ======================================================================= */ /* Searches a complete string in a ternary tree starting from a root node. */ /* ======================================================================= */ void * tst_search(tst_node_t * root, wchar_t * w) { tst_node_t * p; p = root; while (p) { if (*w < p->splitchar) p = p->lokid; else if (*w == p->splitchar) { if (*w++ == L'\0') return p->data; p = p->eqkid; } else p = p->hikid; } return NULL; } /* ================================================================= */ /* Searches all strings beginning with the same prefix. */ /* the callback function will be applied to each of theses strings */ /* returns NULL if no string matched the prefix. */ /* ================================================================= */ void * tst_prefix_search(tst_node_t * root, wchar_t * w, int (*callback)(void *)) { tst_node_t * p = root; size_t len = wcslen(w); size_t rc; while (p) { if (*w < p->splitchar) p = p->lokid; else if (*w == p->splitchar) { len--; if (*w++ == L'\0') return p->data; if (len == 0) { rc = tst_traverse(p->eqkid, callback, 1); return (void *)(long)rc; } p = p->eqkid; } else p = p->hikid; } return NULL; } /* ========================================================= */ /* Insertion of an integer in a already sorted integer array */ /* without duplications. */ /* ========================================================= */ void insert_sorted_index(long ** array, long * size, long * nb, long value) { long pos = *nb; long left = 0, right = *nb, middle; if (*nb > 0) { /* Bisection search. */ /* """"""""""""""""" */ while (left < right) { middle = (left + right) / 2; if ((*array)[middle] == value) return; /* Value already in array. */ if (value < (*array)[middle]) right = middle; else left = middle + 1; } pos = left; } if (*nb == *size) { *size += 64; *array = xrealloc(*array, *size * sizeof(long)); } if (*nb > pos) memmove((*array) + pos + 1, (*array) + pos, sizeof(value) * (*nb - pos)); (*nb)++; (*array)[pos] = value; } /* ========================================================= */ /* Insertion of an pointer in a already sorted pointer array */ /* without duplications. */ /* ========================================================= */ void insert_sorted_ptr(tst_node_t *** array, unsigned long long * size, unsigned long long * nb, tst_node_t * ptr) { unsigned long long pos = *nb; unsigned long long left = 0, right = *nb, middle; if (*nb > 0) { /* Bisection search. */ /* """"""""""""""""" */ while (left < right) { middle = (left + right) / 2; if ((intptr_t)((*array)[middle]) == (intptr_t)ptr) return; /* Value already in array. */ if ((intptr_t)ptr < (intptr_t)((*array)[middle])) right = middle; else left = middle + 1; } pos = left; } if (*nb == *size) { *size += 64; *array = xrealloc(*array, *size * sizeof(long)); } if (*nb > pos) memmove((*array) + pos + 1, (*array) + pos, sizeof(ptr) * (*nb - pos)); (*nb)++; (*array)[pos] = ptr; } smenu-0.9.17/index.h000066400000000000000000000035121400523266500142230ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ #ifndef INDEX_H #define INDEX_H /* *************************************** */ /* Ternary Search Tree specific structures */ /* *************************************** */ typedef struct tst_node_s tst_node_t; typedef struct sub_tst_s sub_tst_t; #if 0 /* here for coherency but not used. */ void tst_cleanup(tst_node_t * p); #endif tst_node_t * tst_insert(tst_node_t * p, wchar_t * w, void * data); void * tst_prefix_search(tst_node_t * root, wchar_t * w, int (*callback)(void *)); void * tst_search(tst_node_t * root, wchar_t * w); int tst_traverse(tst_node_t * p, int (*callback)(void *), int first_call); int tst_substring_traverse(tst_node_t * p, int (*callback)(void *), int first_call, wchar_t w); int tst_fuzzy_traverse(tst_node_t * p, int (*callback)(void *), int first_call, wchar_t w); sub_tst_t * sub_tst_new(void); void insert_sorted_index(long ** array, long * size, long * filled, long value); void insert_sorted_ptr(tst_node_t *** array, unsigned long long * size, unsigned long long * filled, tst_node_t * ptr); /* Ternary node structure */ /* """""""""""""""""""""" */ struct tst_node_s { wchar_t splitchar; tst_node_t *lokid, *eqkid, *hikid; void * data; }; /* Structure to contain data and metadata attached to a fuzzy/substring. */ /* search step. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct sub_tst_s { tst_node_t ** array; unsigned long long size; unsigned long long count; }; #endif smenu-0.9.17/list.c000066400000000000000000000210161400523266500140610ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ /* ********************************************************************* */ /* Tiny linked list implementation. */ /* */ /* Each node contain a void pointer to some opaque data, these functions */ /* will not try to allocate or free this data pointer. */ /* */ /* Also accessors are not provided, the user has to directly manipulate */ /* the structure members (head, tail, len, data, prev, next). */ /* ********************************************************************* */ #include #include #include #include #include #include "xmalloc.h" #include "list.h" static ll_node_t * ll_partition(ll_node_t * l, ll_node_t * h, int (*comp)(void *, void *), void (*swap)(void *, void *)); /* ========================== */ /* Creates a new linked list. */ /* ========================== */ ll_t * ll_new(void) { ll_t * ret = xmalloc(sizeof(ll_t)); ll_init(ret); return ret; } /* ========================== */ /* Initializes a linked list. */ /* ========================== */ void ll_init(ll_t * list) { list->head = NULL; list->tail = NULL; list->len = 0; } /* ====================================================== */ /* Allocates the space for a new node in the linked list. */ /* ====================================================== */ ll_node_t * ll_new_node(void) { ll_node_t * ret = xmalloc(sizeof(ll_node_t)); return ret; } /* ====================================================================== */ /* Appends a new node filled with its data at the end of the linked list. */ /* The user is responsible for the memory management of the data. */ /* */ /* Note: list is assumed to be initialized by ll_new(). */ /* ====================================================================== */ void ll_append(ll_t * const list, void * const data) { ll_node_t * node; node = ll_new_node(); /* ll_new_node cannot return NULL because it * * uses xmalloc which does not return if there * * is an allocation error. */ node->data = data; node->next = NULL; node->prev = list->tail; if (list->tail) list->tail->next = node; else list->head = node; list->tail = node; ++list->len; } #if 0 /* ==================================================================== */ /* Puts a new node filled with its data at the beginning of the linked */ /* list. The user is responsible for the memory management of the data. */ /* */ /* Note: list is assumed to be initialized by ll_new(). */ /* ==================================================================== */ void ll_prepend(ll_t * const list, void * const data) { ll_node_t * node; node = ll_new_node(); /* ll_new_node cannot return NULL because it * * uses xmalloc which does not return if there * * is an allocation error. */ node->data = data; node->prev = NULL; node->next = list->head; if (list->head) list->head->prev = node; else list->tail = node; list->head = node; ++list->len; } #endif #if 0 /* ========================================================= */ /* Inserts a new node before the specified node in the list. */ /* ========================================================= */ void ll_insert_before(ll_t * const list, ll_node_t * node, void * const data) { ll_node_t * new_node; if (node->prev == NULL) ll_prepend(list, data); else { new_node = ll_new_node(); /* ll_new_node cannot return NULL because it * * uses xmalloc which does not return if there * * is an allocation error. */ new_node->data = data; new_node->next = node; new_node->prev = node->prev; node->prev->next = new_node; node->prev = new_node; ++list->len; } } #endif #if 0 /* ======================================================== */ /* Inserts a new node after the specified node in the list. */ /* ======================================================== */ void ll_insert_after(ll_t * const list, ll_node_t * node, void * const data) { ll_node_t * new_node; if (node->next == NULL) ll_append(list, data); else { new_node = ll_new_node(); /* ll_new_node cannot return NULL because it * * uses xmalloc which does not return if there * * is an allocation error. */ new_node->data = data; new_node->prev = node; new_node->next = node->next; node->next->prev = new_node; node->next = new_node; ++list->len; } } #endif /* ====================================================== */ /* Partition code for the quicksort function. */ /* Based on code found here: */ /* http://www.geeksforgeeks.org/quicksort-for-linked-list */ /* ====================================================== */ static ll_node_t * ll_partition(ll_node_t * l, ll_node_t * h, int (*comp)(void *, void *), void (*swap)(void *, void *)) { /* Considers last element as pivot, places the pivot element at its */ /* correct position in sorted array, and places all smaller (smaller than */ /* pivot) to left of pivot and all greater elements to right of pivot. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ /* Set pivot as h element. */ /* """"""""""""""""""""""" */ void * x = h->data; ll_node_t * i = l->prev; ll_node_t * j; for (j = l; j != h; j = j->next) { if (comp(j->data, x) < 1) { i = (i == NULL) ? l : i->next; swap(i->data, j->data); } } i = (i == NULL) ? l : i->next; swap(i->data, h->data); return i; } /* ======================================================== */ /* A recursive implementation of quicksort for linked list. */ /* ======================================================== */ void ll_quicksort(ll_node_t * l, ll_node_t * h, int (*comp)(void *, void *), void (*swap)(void * a, void *)) { if (h != NULL && l != h && l != h->next) { ll_node_t * p = ll_partition(l, h, comp, swap); ll_quicksort(l, p->prev, comp, swap); ll_quicksort(p->next, h, comp, swap); } } /* ============================ */ /* A linked list sort function. */ /* ============================ */ void ll_sort(ll_t * list, int (*comp)(void *, void *), void (*swap)(void * a, void *)) { /* Call the recursive ll_quicksort function. */ /* """"""""""""""""""""""""""""""""""""""""" */ ll_quicksort(list->head, list->tail, comp, swap); } /* ================================== */ /* Removes a node from a linked list. */ /* ================================== */ int ll_delete(ll_t * const list, ll_node_t * node) { if (list->head == list->tail) { if (list->head != NULL) list->head = list->tail = NULL; else return 0; } else if (node->prev == NULL) { list->head = node->next; list->head->prev = NULL; } else if (node->next == NULL) { list->tail = node->prev; list->tail->next = NULL; } else { node->next->prev = node->prev; node->prev->next = node->next; } free(node); --list->len; return 1; } /* ==========================================================================*/ /* Finds a node in the list containing data. Return the node pointer or NULL */ /* if not found. */ /* A comparison function must be provided to compare a and b (strcmp like). */ /* ==========================================================================*/ ll_node_t * ll_find(ll_t * const list, void * const data, int (*cmpfunc)(const void * a, const void * b)) { ll_node_t * node; if (NULL == (node = list->head)) return NULL; do { if (0 == cmpfunc(node->data, data)) return node; } while (NULL != (node = node->next)); return NULL; } smenu-0.9.17/list.h000066400000000000000000000030051400523266500140640ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ #ifndef LIST_H #define LIST_H typedef struct ll_node_s ll_node_t; typedef struct ll_s ll_t; /* ******************************* */ /* Linked list specific structures */ /* ******************************* */ /* Linked list node structure */ /* """""""""""""""""""""""""" */ struct ll_node_s { void * data; struct ll_node_s * next; struct ll_node_s * prev; }; /* Linked List structure */ /* """"""""""""""""""""" */ struct ll_s { ll_node_t * head; ll_node_t * tail; long len; }; void ll_append(ll_t * const list, void * const data); #if 0 void ll_prepend(ll_t * const list, void * const data); #endif #if 0 void ll_insert_before(ll_t * const list, ll_node_t * node, void * const data); #endif #if 0 void ll_insert_after(ll_t * const list, ll_node_t * node, void * const data); #endif void ll_quicksort(ll_node_t * l, ll_node_t * h, int (*comp)(void *, void *), void (*swap)(void * a, void *)); void ll_sort(ll_t * list, int (*comp)(void *, void *), void (*swap)(void * a, void *)); int ll_delete(ll_t * const list, ll_node_t * node); ll_node_t * ll_find(ll_t * const, void * const, int (*)(const void *, const void *)); void ll_init(ll_t * list); ll_node_t * ll_new_node(void); ll_t * ll_new(void); #endif smenu-0.9.17/simple_menu.gif000066400000000000000000003453151400523266500157610ustar00rootroot00000000000000GIF89aF tprtEGI)/.A5'čPb<?o ( 9YnaS%TrP.BWm ~En2!zyMęz|Kܫ[fјNm&nl Xd x! NETSCAPE2.0! ,F@pH,Ȥrl:ШtJZجvzxL.zn|N~=M~X=M0+, V K$0(#k=I .Ȳ4=6J!"-n,4,,I.&+H,K ' ,% HIN)iЊ N JHh(<AE ZI2a+"OʜIȭ tΦѣH)D $$P!OIjݺmYv \Ӫ]KVvF`ۻxBt`h`P۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6p! ,@p((ƣrl:#BaCNGeHN!BaXOB cG"%H 0&%mI~ (aE$`CDje~fC0/F & &&#Üqx}IKRA! ,.l@@@((ĤrlN(ą2j.e&)[XŢib")imFn_Wly~L1 $bd}V#FqEqHA!,6@A0,Ȥrd"! HHP +4L#Xy{eVr~ye|CpxLzr.vKzg%YFJpr*+VZ/}nDIrJBHHA! ,>_ *B9hƪ8ڼ^R$P|dx)R̞JrY7,2qcq,ja/u<~2 `xr|!! ,Fr@@HHE D LQ*hZde%VDKZ8m A^D\l^%-\ d &&+uMBFeLzxeKA! ,NI͵EG7ƁAp G! ,Vi@P@ Ȥr(̈́i&E&)+Y%ƀ_Er*FHlq.x~{q_sce(VEiDGLA! ,^@`HHEr9LdCd6KTFVh`3.ߤ±n/$(SvIc2+Dao,!rmw(# &&LFaaFBVaA! ,fv@P(ȤBdf@y6@vJp,+`Y\'b Y^kUFLg o }Jw{CWY[t"oBoNGDoA! ,nt@PȤr)'!`KE" R$33N6K[p_a/NjGJt,1c 1L^1' xJCkJDA! ,v0I8ͻ5C!Qq kJp G! ,~m@p((HErt *H9 '`b uQkZy±p0@]$kBg^,fd &&[og~|gCA!,x@P'Ȥr9QLvh;KHUz-qD%q¾0G|OFT G}M '|wa0(# cDOC[EA! ,|@Ȥr0Na"-!DrXR#+1n|I|ã%FBTı .'O"tK }su(a$(|ujZ'JP~Ll~pA! ,x@P@ȤrD:fBi.qT8& ID ![q">K fh}vxIptvEy{~Hi' 2)I cKFcA! ,@`( Ȥrɤdd"MXV#XH'b fYͭe5Ly$|tGqsuxqX YFK /g)*& Oc oDIuJIA!,f@P!(Ȥr S٩HN钅 Gn6%Hb/S݅3wy~w|1mFC0&jDjO^vCA! ,o@@@HȤR":U,BJ@VLz "UO 'Jϩ`/#"iBm &db!\&&&ZR[~|zeCBA! ,  EDBƤX@˨0, #iTh rQ<$GI,|IʠrvxPFA!,@P ȤrdƦtUTUˌ@ܰxL> zf|N~q,V==6ip4==V\,==4M,4=Ǩ=,[ΌՃ4~|zm  (T#$1^!n,(y@aAȤr6ШtJuVXG]zzGk{&/ @zouBX@ci`lCo4al_i]==ybTx_44fnpljfdZ\T]YA! ,1c@p((HE D Q$hJd4c`rB1r])uټCJi'%-x &&+RnxfseA! ,.@pH,Ȥr9Ӆ@Kˊev rHPE"?eP.}~B.)\]%UB2Xv1~ _1& "#sO̺A!,&1@p((Ȥr< pb0NacXR˄1`((*#l:Ph81t6J0a:iZH&)[\ke;-luh`/0& nJO$2- ([N+z(bP./0M}bP%Q$|1(*P#׀Q嘭JvKOM G`$A!,N.g@0 (Ȥr^ Ms9bN +52U+cA$[UqcqnKy{)Sq"tCwp Xj1!w$q*&_aVCwMUA!,1@0 PDdRl:LR0d0&GKy,L [?'k"km!zlnp+ b}^y|"{GM"O1! x0%^`o*' ~^[]K^ǜCCA!,>@P ȤҸlP@aZAAqeVG+Lbzn-Mq>]cC,N==6`4==st,==4k,4MB̧=,ޫ4xaÇH(E7 ظ1 Ch !,M 1@p(Ȥr9ᔊ$́)z߰@."]Cbf' J! ,B@p8ѵ(ФQZPg-֋E6Pa#hR3`Y>g|\!C_xhY C~qm./xB1&+\SD-c[NxIaNo|)1UQ"  Wlh 'mJP  \A!,&D@pH,Ȥ9!˲Z#뱔@fT cIx S0hEOCsu+ (# V2bI+YCH_G]n!I1O)k$+H] % ,ZQ}YJ  A!,6Gx`($ȤXa( s| De`'P.f+cJy.zrt\(woqi"mH '#] "&cnI{ NKdIOIJ  KA! ,>E@p !b91P$1iXErd!oq-N8SuË%ePPJ PB${lI (#c\C2)*H} .&)IpzbQ"re ' %EPVC"(O(vaHxE _Hީ  ٫A!,NQ+ (`clN"馍Tr#p(D R0Pc !,VGf@p dU 0(BajJ$.FQpo^0>4׹w&s(S0% egFREBg  A! ,^Gt`(,ȤrYa 'Isy|ʠ:9K{euXΐVAe#2Ŵ_movaf0(#C%k#(*& g _  vCA!,fGh`($Ȥ>JE$.VBJohrڸV#dn/ymo}D}x zoqKG^+ud,Z2)JFP  XG  A!,E@pH,HcCH: h0iج1DT0H*cթ 1TNʊLYz*1lds{,1)xIz"{B"l d]X/m&lI _)%ThZ΍RFC  ZA!,G\@@@8$ȤQ}0c D%FD " uߖXue-sKS%hfyoBT  DA!,G`H,Ǥrd,=JJmAyT4"U6n^HIqhvzD Nu,(G]w"+XgBCP#dXGs  °CA!,Gi`($Ȥ:DT$X%40P#+RVŢ @(ˢ_C|wpubg e{}Jv!*mEbiV  DA!,Gf`H,$JC'<Xǀ:eU#S5*oGqĢPtG"(+LX#nyF xyA! ,F@PBȤQtZ $Fɧ N(at(fj=<n49aCA:J\GƜ*#Gyc~Weο?XI)``҅v^OoZvqדeW\B`M3Gy\~$.(AMgӥUuUczj,Xێ@C!d>ɩ(U Έݍ9u_]`Ø6@U01Y&L)M>i7QNg9ԕx`tezViv,ݐdIyߝ~t➠2M:R`zxjwfM5rrރhj,1+mݕ!2Jghvyc`\k=*(q@%#Kl[F)FHŔ5PX[)h,f45+YU)Pb}tVxuq_{1JLޠ,3*ls;.Tgw^Oޚ+ιgy0zXQ갫^wyz쒯^{㾶W޻cS3߼C]Acsߟ}roUr>jff/b`?)F:ZX+I1NDHX@0Vh$ D>p!$bRR4`AuG*%UNjH\!"@)nJ)tC*be2i,^DfbFThW2=RycWb.A8q6bk $ ը]t$,ȆWN dd(  @X3|p@e.9%YCD N~#B #Af%9tuԉB^Lȓ̳͆@II8r}a$PB~9T3wy(\4diG(2$pQiܴ2)jS♩:D,CĀɝ#"4 u7h3 VLZyhCܪ*%SXrc9}&_bqŬ՟B^@~! 6 X0t+?,,S bB^eRk% fN@l)oMU[3^y^a13m жұ$yԦ2})3Ao?+JdOfٸ6-4p5rZ!u3wMmVk6.OwJ'$c/VV!ׇ" + Nz D [wV$HE֥-oTšN&zQ<Η6Zg@0ṭthII_\7t%1.TQ҂<7ː]k;b0"Al&(L%q[QV HYS}Mդf)+qfs!MI˶ʀgi2Dy{eaUAh5.pfJ%`-=77/7N/p^XyF@zJt&t06ٚȽVYX Kd Եe} 7 Lj@L"jhch $1vmη~NOpz78'[ϸ7{ GN(OW0gN8Ϲw&,@ЇNHOҗ;]=CwXXϺַ{`NPZpNxϻ]]W#O;񐏼'O[O< q)^ N.~OWֻ',j@,@z*O|~jOq{dؾ l? @/~W x;d@(!% ^PW`@חWp @0>(p@xׁoxn'/2w!.v)$0w7"~4z'~m|H+XXP'{.`},`Ey3{&P} `/pE`q}|xP~mghXp7YxЀr+w`-8,B``}"F`~ :v @}m0 1@whx nW~P |X.ЂM(@t`# XuPx`"@Xxx}טBphVg87Ј\8}(2`{/x p7(@0>B#@smGz9,~ш`u7dC~h0 ~X ('p~AGA9P(8{A~̗Eȓ[`)7xCHم؆pnY z9yw/og}(X  -D1w0{f8eL'00 0l} <)p}YE|OwwgP ` 'YO8,pR'eɅȃG`hox0i߹ng}iw/@ b ~O9,''9GD(YY?'G0\h J Y؜#  p ٍja؝hoxykX~w鉒}yuYDj|-F0 zhQAp@KJy8{jjJ'`I1y.vyoW0ن7soHG@ Y^`S:0 ZB8)E7e@j18hZʡO@ s6(jDr׏rqi8u6|'D'ACj\p~`OYH ezgڦ .zB &:6ŊZتKz w 6i-vI" p!|-:*)ITpv;G]w8:{Qx1"$>7OxEN䨃Gz 쐩ϻK!Ji;X;˛^-DP58kqlP.w[zджiޛ3]2`nPz.|: Ɉ[XߋXzRp2{y}ҬQx XCNB- zV~s-9+0j>}Ә ޢ=P¸:弄O>1Y~k]Zx>kCP&0yi`| ݼح'':'Ak{} [ ښmڈ'Ua)Xn pَLTϓ?1Q=`ǧ+BJ֎We-;7ٚ0Q wҚ#ҡRPGpBH .mBm{,К*.љ=տT6ɧ_|rʇIܟD0[mҟw?_?_X4It>QZ^Y~a\6ivq^y !#%:2&5<06A #D>.CQ&,N4R_ H`k:X?ly$C Nt.-hw;*1!T$>69#T.{.DVN1:?FޓR3/3xa  pPC vh+ɪ(P@00 \ ZVDfR"0!HH CС@ iK-ⅺyZ>T%5 !P$ZB2g(cI{UL1Hv$ YM# ǠDL"]<-5("8DF2x؊m;HHe Rx fS  :~®_ /6$ RExm) B%8|p0-WPc \ >(Nh0(َP@]"PЂt&,*Ls x( 0D0*3P (`U*@)@܈vLqP{X {Z@-H$B AG+*NZ2HtuJ L.ޙ;R!L*.S wb].DXహ 7W$r'1 5Ղ0(4O"($g=Zb;ibzgX?W@Bc]†\Q b#Bƍ\"ULQ3qav6V5-^d\ X-"Mc I#%!V4AcVk^B/!p&\|NhL*Q{ՑhU ` h/)˸ahkV&1 , [y<vS%woŕ 8%p(o2ZɎB!Wر+y-P+?)e\KK42T͆DցPך' S<xK@ű` b .%EczTpDD#VTU{`/; &†H::" v|B"0ruO$@Dt8q..6 OBSY.42>LYA iOkUp'QXx%C'3 li5pHp!O @lg^2^ZU* Tj*ԭ(7fŏkaq7Xf8 >WEғ.Ebc 7`*5 FF8\H ̼\RzZZ^nnB@Ø# w4c;ٖ|h> ( u'tt지ch:}„E5gjzTZx`lk]輬`7z#=EJn4Av/s\lr(jp<]bȵ[)2[V"8T/sW;M7o3HL 0PLM\0V1@(AbPV[:!B(BP숽hh tBJ4P K0VM!hA8@°3%("B)5,h<<(# 4vaD1*  S)'(kF8qD ba .8FcVmv1x0@2%D_+ZPT  2@3f0`#66b;6Zmd dH7T7|CF1fd s&G\BR70&B;D a`O=xC>#.E JV@d,d@~2dAA+@*$@\(2g)G@DHD /V"J܌g,\J($>IDHHD d(h)tBJDjq)0gU[LFrJ'NsPJj HG-B@sza0͘nM2WK >/fJ% "U 3P@O`@¦lӺ N2g츌Y4mXBZR'Մf++)4xo6 &^r]r~ef_gX |`pҖ>' %3ANLvcsr0$s4:vFͻ|N^tfc3Ӕih6 815?i @p܄GkZ6k34dNs-f,j*f&2I4p@6a* [>W"72]P0et LDtLumlf؅D w4%'f|Gxx #yTUG?ic4l{D|MMo'Χ8;GSSBGUb~H$dҧpfXhӈ,F^@,9d>["6.Ho.:((4P>,H$\uynՔp 0_^\Z(Mi>ȊPHHnRf@\H:(,r䈍r̨Hh`} PpbabQc c@ QdMdQ6eUveYe]ea6fevfifmfq6guvgyg}g6hvhhh6iviii6jvjjj6kvkkk@6lɶP0vClVbKVmVMn2(NMP Nr[K7~. (@^0 \m۠ D'j a4m B:za026Wuq@i\N!K-a M`9W tru GMkT@;2Cd440tg))!(?$ErUGCFAĨ2Tg$Cc0X,U l$Ad *DԒBh8A-PH쵀E ($@0RʤN^@Ʀ21Oj*S"SIgN(lzSW.")E$, x2|hTӒOڪ *kA˞x92O\49擙l#쎵 cT9.:6SVP> %9O(ykRn$Yr*ٖ: D?@@Cv`xUY=89;ja VdѠhywjUs_║$ 9k˜!S @-JZFT9k,gfaXҊ \7yGEv)vox/8LU9l,ӹLth!}”4=_';"s<#`Č=i̟8˪$Z'z w"v#ρ 0D.Su/rjO}:~~XeW>L,$m$oB:ϢF>JW>:BS( D 5PZ- xF8e[ʛrߦ8Nd,@bp=<(BvTL5a]3A]S)Np{uQF;?B_[obo ضjЖ;{ !x6,@pH,Ȥrl:tJZجvz0I. zn|N~}CbG6c6 ـVَ&{ rHPZU[ȰÇ"3j8&sCIk-\"@0 0I:lR;p B(ABb,@j ,uĕ``D JH Ĥ 4tq@. 1+f  [U0\[Abɐ1w| eDL0 A@ )X a!X(AkxC `93-Z6rAN?=! x~B佃/qQ۬N_ARMPa1V TT 8V@@`qgeBbT=H Xx "7g}T^ &E Xb"hu)LW 9P= !c@ bXZ}ٶ nS T: [X{Z6l[[~u zs K)é"gI@N!4![6G ~Th@ vb%_Zd0 nB@$g)j*hK èOPVC4Nj/\5%u9!DԧB%Yk:dxM4q cYA C9EQ@G$~#Yȏa(dZb`@)-b1D.H8| @O$ 28 0 : X2_rD nx&T (B*g;фpP5º)NDjyմ%M%D3mK t !BͰg12䡲DFCP?:2P%:d1}H  .HI$SxL2R å/L3 r)N9b{@ Pzt9ݩR LF$P*36zTH,L]`ծz` XJֲhMZJVp\zYЕX%1R<~ ,`+V(wMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַΦ{`NhOpNxϻOO;񐏼'O׮;<yGhnfzͷ|O=@;3eЏ B s0gys澳AX:Џ ! ,T@pH,lLZ vzp3q؈zn|~KPү*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgה #de33`22l[ sY,-L  ̷؈ 5>3l׬]GH95;1xE,]:>79 9F_^3ܵLQtB$/sG(=]?ک/ ~C.$Fh/jKt^ U}L/Co>P터m V2z^% wc pocZVB!Pf[ݎip3Xĺan2A {W9q& &Cdc9g*PsLK#yU";6aڑzc4!,TF@pH,lP FӬvz`zn|N~^7;7~8;9:;RM䧬ȨE& CD7nؘ881a17<IR‡(SK4І yXO'U zG"U:PaT6,U?qxJMӧ7< WLzYA];E70vD2Ÿ ҪxIXv L~ eij (X"P/F!7 fmc,X`+4r [ ܨ!pJ*Լ^e}h\6&4~b6BBȋo?%{[o&}~Vфior*"*1zl01RėκK!ԣ՞jö+JDƄgf [V)d i -ƆHE(ZcEnbUL0uʐE{*tLG,4Wςva\*_U!UXT5F < ՃyڒSyv_v曇5ڞ'訓y@hκun{쳗+${j|yG?P__cOٽ~g>wßoV?[ZKzGqVTXQ@)\5H9kz7 bLi"D:!?Ă4%$\ w@Q !2oTPgsiDBJg S৞P݉ Ւ3K<ɋJ0CAUdz^2Ndl6-:x>$kVWTCXb@qlZ`Pu#\-sq{:oqcbc(6̡nBN*Yn$_sfɰst42sIb>VnH 0ad*jH܈J^ ؄>ȡYM Tbς!Ri]fE.:É4hO0!vjL/,su_'iÀI7- ݖֿfa%lrU_v*EwcQ5%TmdZCɱ@*PDF@pmhq\KQa]OV|㠷'N[ϸ7{ GNN9W !n,Y@pH,rl:ШtJZجvzǰxL.zn88# ~uba& C K( s1閶 dP #Tć1`|fBbDr:8_4'Qm Dn"(@ v@zqQb–dN,^ ]yx'(l} 灚8ΨT&ьB[52 Jpe A_H0iJD>\vI4nq Һhk][l 15zԒ8c0ᵗ1{@B5"zLx~(d&bq;)fa;u.}JҡvD`M(Of!\ ["@@S(Q&(K_.Id}fbt3[&$թ*Op$'85OĞj#T-#1A)k cU'Ty@E-YT;R̉G JTD"z rQ,hGO'Tp DgDZ*U@gWM;iSc`J&aAdpWՆ|,XͬMb6$XC)-津5j զplaALk p!Ҭr2BZͮvz xKՅng|I(%}/ 0,N09 `20',_R":mXdGτ@%W8 :yk6 x*R0(._ȓu/A&3 %.d!'(OUp4ԡb0$:&j ,_ bVgҝPYPlt_ES#/+ |hٹρ`>ЀPB\XGh4I a:,ah! Ve}# n9igsjQ#Tj &^V>,m "fBu!pra4Zɲ\_X)Ʒ릦\`Pxv;ہJ)Rd*Uv|$$U}3$]SyA? TNn:&7q@ Mԓ =y4MfݎG.o0@(sZ@j}H' )g}>[c$Ig_v2 ,@`7D |@N߱ qO S'HLU`ckt8 lz72; 8ŝǛXOZ-ol ^1yd_W^j#, %0H oH,"8 5Е`,0$oGBSG iq. @$cwנq2U#ʖd mC0~W}jPD9($ B`nˆod!^yf~,0@M:sw0w7 MP3{idua @h S?Ҁ]fIGFn j&.!r 0 oۦl&aCSm0J𷀾‚>aip )AVhqGЃ&:(^3535rmwLlCX V)` =& .aԀjhm'Y!wx {r fI&q"A&8؂>< Hrd2WhB.E%ځ?d~҄8d9`oT&x$(,bxbe8ogׇ)wͦ %~$S+|dv$)+b(Zј\6bn b%&=w{Lȏ$68(,xW # Q$3g˓B78~h5@ggK*cHnQS ~uxoĂHf9db0TE*m%:QtGxPOB4CqrU5fyf&y`xqGx}'xwŸwwi30{a(@sGz 9!ǏCa{>@ji}ɗ>ٞya0 r*?K- r{{}#~C&ٛc'Z cW*Mg iUsG!7hWUfSqFFfr(2cUtd`ty$ZOu̸&;VUrGet'opmUs%Zw @gGw %'t\qW h: wqpfevc H _n:fct`m_X{jigVa jzajVkaZa}Vg*j5:Ԫ/Vzjɺڬ*:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[[zd۱-"{Vm`Pd:Jr3 kzxo6qp `ffPc 6f1poul&,.Rj[kY.T9|6jK;ffds-0nmYm@QZka: ySV$!0`|J`OWG+ Xe0%&0.Z,rRs/j!b!Y:t%R^tOٶ~*s9x`bm8@y=adz qbpʗx0$+)i+ 0|X9H`jU6*t3 "6'Smܶ ȒJg*_O: 20qiS}yPU/-s)?pG҅昀ygGU[ i4p2y}۶\g oJ;n8'u fr.p0 mHeQ'zT::Jpi@l1W tuG=5~ ؑf0DžNBgJkcظrL.ձ9 q= ^Limv^L5)$Dn.ЂK$xAhSs9$xdxIyDž,9DƞF˾\ ?JcҔ~H#oDʹ(~Cˌ9c"'5:v*:;@U-pPJHB+n5{zgѶbaJYːz I -m;+k6=A!d3,T@pH,llH*Wɂzx܌6zn|N~|K^FuRmhSǹ Cnɷd͸^Ҭ,'QS_*&X'0(./0& ^̊A#4b– Α4+sQݚ -©\d7,,  Sn E TB4ZH1SN0@D7⑁ [>K ח"`  HN윥fB̔$ iK PȸZDRKV9 Dmlaʞ="LHLwy@37(>A\ rZTMWAE%,vW_' P,Gt0A$eU ($/5TNЍq0.䓶Ō,2Ar4N.Q$R#H0') !g&:ZCSl9DH7$aNX C)ye_n,Ѐ '旿 z9yHoM^~…0tj8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:ȣ @;UbL"xE:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ90LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZA!,jE@pH,Hql:ШtJZXvzxL.zm|N~N8787;7o8;9:̾;l~X74;6;8 ږ B>v&C;7lDAQ/%Ñ CDɓm"zXv,u S2{y!'1k܅3gˑHDɴ)8z0p6sLw'岰G=Ko“.-NaA17^uh9FNԓ,`jpDw^Ff'buT1׋y Qߘ".7wQȠ KrXlHyh$5P"/$” t$7eG2&:Vea^( y䚴$L5 ?@Co;@lvH!t;5&GyblV` {!Kv̦^uR*?ʱƩs@t G((HZ*,lKV$OA 啬\fM@*1Y?DXVD[].˗5j;wt(G9Q!RNdP[DrB .qfW|glwph,lrr%2),3-l1pE)+LŽ IaH/p#5!Kȷ&yO_A 2>Ebȋ!&"ڈr& @ej`Ĩ8¨>+rqgC#& /Κ@z5qEg@zČg dQ& .0cDX \(#P 3 N`JU)U(b,%KGQ4 E^(ͺR*ؐ:ϣs dI%˗mȉrrA>CLAAs rTb+u:Klly-F c:n3sQ%L/LfТLR/@<$#Q(nz W1e\ETRCɀ+ Mfd}) ㌺0p+(S$ ьoD0C4 KhD( lU L U$ ~ çNP=NQ҉LKzT#X2B@}}tN݄9kF(6.CJ2uѱj($/%@ZU̅`<_^/Jgu\u(U@R38eFQF!|-9(@ JL s {y%}612_3AU+tBaq2J 6SP%qyVgy_47{hEWk@B_"pE0eFEX›o#G}ћeq(;*$h$!*##@ ]Ƭx-4[5 HělIZ^jYX$ōbd|lvm|m (Cˆm1ɩox H ڍ;J )SwM4~JGeٲo;Ao3OL)RGDuuIxM\漘A>T\^wN@ DLo➳d~ߴAK)K\(%U"$ *.FvC Alu;-iyuS^)$PU]&l(MَRyzŠ go"3 {XVZ}|?a Xtm}zGMp2j uMu%Ԑ逤P\CQ8o+IoFᬱ@1B @&ú%r`JD8C}v k q}oxb`9 H5+=F4\C9 ȏu'P\%YK 0ka \@Q+,ŕJQj16aM@H9@Ut[hi!0a-'(a^S&! :'hѓ\` j-m>RukVA. 6 ^DD=Ju(0@X%A PЦ 2? Ki͝2HQpmԤ>bPTJ=![N`˪ (0@u[_DwOɫ^׾6ƚz1#Ab%&ֱ,, +Vò}+P` 5FKҚMjAdlgK5lnBu pKMr:Ѝt9 B ̓vz Mzm/oUdUx45ovQG ttb.!N܅aoi6,`wM]竬U 0_]:{* P"q׻ȬH@?x˟A9x4b0;!gM͓ntW*xScL T%J0^Ef :!~=j O: $P\ հe.SXhT\av&( =8G`y_~7 Nd?x<=g !ϞV" =[WHMl}&E>$(ȃS&- , *F >Iq\^ !bkaYs1)\w-=Ks/.-{AseCU>_ͮY"8Y*Rٹ ;Uof2"Zgt!Qz 1xPaa~(zxG{(i'Cbqw\4ic.bGXl[az25u/p'&~w~4G!*oRL.ΉgppoLJoc;rwubE*stOp7V Z'WX<J&qDKjƥbpl5tIf4l_o{o#-LdkztBtNka6ava6fZ_Vda:_ƦjR`W^eF`_gv`JhE_6h wf_ _* XOꌚjfn@^Ze:Z]z꺮ڮ/a:Zzگ;[{ ۰;[{۱ ";$[&{(*,۲.02;4[!6::۳etB`s֓i8+aC뮯F`Kꌗyjj9oSXA2X&ZR$b;j^z`n Ҵ~_8i̚x`Ucfm*ّ*W0WgRiaʳ`F=~ao coVt+qJV6smDUK^'adg 8wJKE EJЎA{_/Jzߋwi6 h8h'&J5Z[ z4sD p˿  `wGHDF@`zњi~;PCP}2|_hs.)"[| qB"6:D Љ5_ə;P#F2I3u.rgJ!JoOډK }fW5U u9_Q'I7368r-pE֛  M hs<3XvADIke4 g_gf D.SPxĝlv҉Sk#j#'5̐olnḡ|8 I&vj|. &LX·l{x=,ou&жo+h !ܞj Ƕ w]H }nФL^KN< H2e0FbSҼ8F,*D]bvVRf(M J՝.W]NkM}ES[b'iFhܐ_hw{\ը R-=˖vmI1!,@&ڋ޼H扦ʶ L]!x5,rpH,Ȥrl:Ш ZجvzxL.un|N~ }j`5}l]EXgtRV,'!V  g a0W,# \,)%*)f ݧH 2 N&9$‚D/dDv&Vt `]nG~&s^_!'.|TX49 vi, AAO+$D3!V+:#Z5erx.d)]&c>MBiDH0,{ϑD vPA: P-p`d_Pr aK`_hba0$ty 䩃T %tз,r M^:fk+KA@y t0 XAy PPY\p^^RhD `/uHpe&MkӁ 'p!n8h ⏦uC1c_iA F @t! EMU^YDJM`Aj@#pBĐ @)mJUѧ'$1fmeH/A e A%iMH+1@ !EUNe,4J$lx1  c@S04B옺lI: ,'mK/̳5=ς*3%ІzDЊ*aͨFP Hђ¤(MJ!7Җ+LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7zvUhBEKњ=jSպ}D@K[^,6^ ɭnw pKMr\y@ *Zͮvz xKM*]Kͯ~\ҥ|`'Laro7{ {W 4 +t8|s 81xGnD@`""Юl ;jd[q39`ԛo#0 A=6Xˆq !_ff {>/fƜsuOl> ՝qɉnh B[2ƴ7鲋؀!  yzB묫jV=9Fg7(hD R"k\g@̝6?MX9Ca1`4$o 8bq)$5J`iFNvV?%(o߾bԭB)N=P8S<\-n!=b|W ( ~.8xw Tn\ y.X9w'ctń1D+Q|}DAkPsA*dur˩3aצGH $DP' ^](M ݍ=B ePvx혟kmM9]X 2;]msrS~qg7W{~WC[+ p{F`SDswxc>AB?DX#Q;p^ oku6@B9DYFyHJLٔNPR9TYVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Xr 8p^3P-pչoY S)ۉB@3k^ P)]#`Q^НB-ɟ5I:iw! :: ` ::95zO ۙB `Bթrh2ʝI>Z7ږ Сo9sو/\ڥ^A!,j@@8 rl:ШtJZجvzxLNzn|N~ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무jkl䪫X0B0C ;CV &K.,ŶpS P t ֞' "D#lDpܹ6hP-J -؛DV>ܹ:p%f Hش ېL#pzʕsϡMTdMEφXAߐGxoÛ?q1/zi8v6ӀǛ`{V-x񅦑?_Up}T_6'{4^d9LY@qƠNQJ8W60D`Nu1Ð1jM`!6#j4 bey)I=z@Xc]xiNPcC@ױ^؃=;56$'t'Q_9_B %B0)IZ?IThrx n*QOة 묩J_ڊ믆C(^kȖsl:ll2mrmܲmsh"5nmnmVKoދol pL5m'΃SꅷM'i-F4:Fsc*v^14ZEe; cO:,ھG7*THLɕ@ <[ 'эHA6c#EGRJ؊b+`: LOxX75ƊȀ!ߗpqgs!.\bc/Fl Adv   ~y2@ɮ=#/Ml !X?8Ѷ;0dUKn]x`6 P(DL!0XeIXy[[`hnzepT pvt@@,W%,@a@AH\@ sQUUq  |pYn%!H5AN@|drT9'j +߃ $VQ'$PBhhAl"@ @ 既Uj³B|zM# 䯮KσR8Ue@"| @)PpPA@(PPe㚶܎7jA``A G0J*Bh'CcTU$ @ 2Y4f^#D"`GKT`DL Su.P ̅a֋~.@%k" a `xLB@`Ltq{ }  -$K{& d\J0* {]r)#_1)>bQ#< YPԥTp^l)¦{9+ j}0ڍҏRd-މm"um6`Kkt9qHř=,A $&r,NJM |a::&tNӴ@L &]d, y"w QP'PqzsL6Œp3 *0pٛ*G @Vi~>H-IFϓnN u 3A2w d@`A\>(X1eNF1 ;Y84¼`C)4HC AVk.>DnO=B4٩E1.ATFYO+S  Dpleԑ-Im`AVB/QXX0(;̧B5DŽ)8ҭ,`_0X @@CHIi 1V1 - tZ@ZlmIYA, Y\ N0 LG,fMBg+^q(L'rԢ)رC `:JMkʸ58B9uyl pjCR*q5*gu+L0J5MBĦ $,J0PR@p( I@Ka"Rd7$t_f=A Ʉ~ѹHQEjW[.Ƶ}@ @Gv ha游:@c׈tKZ_Kͯ~Im8D(;}尢6 ΰ7{ރ X w "nOL٦ f-EHt"k5NXxAŃxOPiu>, xy\0[YV#s\;R%yuC1\S69iXRG([qV#3{?zmYBȄ+i߾ ! p `+iAkr ɡJu~U;^W+%GͤwQrC8GC;;9:ipGMƞ`̻ݶu4F(ڬN $hp VgU6M3/pԌ 6鶽p8-U29.O'&Hi>޳PW;͛vU6MCljΟ*wɄ6+ _zH$jb $Sc+ ON`YmKخGۊBҞ@g6P7ZL5HPfw lځ~McRmFdSiO L) djuLS%>*_#\x~dclHB%UJ@A;?{ q$4siM{d@g#XҬZ- *.͒T@[ασ!2::0 lfB u^2|PvJR|Tx*Ao@}d`S8}&0nSjc0ӡ6:R5P@e4jyk5BQJ D5ZC46cAdAFDXG6 ErGVGo"ЂKb}iPXVGݷ*~1/*zmXg.`ANp}C&-v6mk(|OH&;6o/ʚ9 %Qkᤝa?ejV(Sڦ')Bn<6v:r|x|:r}:Zzڨ:Zzک:Zzڪ:ZzdJ7š4Go6b%fSbD6`d6 }y kR[Pf$Z7SS.gUZAZoG&%VfeR1cepGC Jei Z ; 8w Q"%6:bj"T F1& ZB-jB J*gXiA5aZ=E۸wHIA\1/OTQ³R&n!x0q`5)WJ8 Z@!n)>i\( Q3h۷ F∋=oJQr۩xp8p5q۩pqOC纥l*Oʕ^rZPsN/&4ڞ&rdƺ, &R(Fu!xֹ v1$0&}\vvn7)w. qh7obINH276+x% /Oƹ;xgB`Xf-_1 2l:jo4HR0kX+Sĸ|Aʨ{q#m[\E DT4%J2KԚI&K.іR'-U.Y>8ˏB,? &()㱙*O&v1/J3ؽ9BO_-2<[, [܉b+;[:PL˷!GuBǙh,p~E()cY$G:O: %ť؈(#FzlɮAULid8 1_4.wKDPK@@iN=ɜȱqXD\*"͟<[&|85<^|{;ܵSGV:@aE΀|kL2{Û_DSϘdā2>c Cf"o |{( wk qfQi'GEl%pY6r4 A4%ųG[*@v.d9Q] o7 Ϥܽ1?Gh9=&!M5 Va 67Xi- Pr;8KNNF,mzM+Irfk^fqFg6^GׯGWYȯ8Jq:sвӼWF5(ff?Gt;Idp͡ f=dHנ,,zΊF&ۢ Ye,e|djD[&Fk`j[j\Wٲѭs[*Tk_ibt?Fb;Ω*Bnb0~E LNQ@SZ}EcԊ)K&ʥjX ?OV 1dR>@`V[7w:-zSe>eF$fu猊h(ZE\1qޅ]:^ЁVZ2%.P$PUj-Ӄ]Z&Z\D|h;DBNL=S[;V]l::\be[>DT;{UPN,WaiieP VV_~1'GF#L~1;: XtE6r%)_d'%]({jX PzYO%(ɱ$)-dH/Բ-).Or/' =i4@+/{F&#p;=3R,/ !!- \I@uQKQF=-1lE.AQHb)/ 8d-=ϙU1k>UAdRT,19}Fcwr UqyD@K" j= ZK4n3Q(bCMFr3i`@yG`^Fސ@.NPOFG"&X]6TR2\zg6RiP6Vrb*u`XLV2 $Hǩʰɮ47X<ǝ<-ZC!ƇgРu~LVK?b&Av$. "(cnDpa"L.ND}d2 X \*uyòt!J4P7pPwh^/,;u`вɞ'YHQ*B]RLNj *ؖ50/[C%zLxK +XElx] (7˚ͪ$=G0K hT^@M mX,(_`C8-P Vs#`cFh@#klkB@HADjXD'N@ (7"PF)8A`C& Ȥ@lрj,/>(̌k"蠃#)X5 ꌡڔ`јi0sO*h7+G8 &R9X.P%3580T$@Wi R$N=K[˫Yր >Cs: DP` FUP-!X`]d w`KQ ܽ# $f[sY̐&HG⽞Yֈd"87ƑlbYd]h[0f6`6JfaY %N(j9R0;J_6竍:-ݡ.ND $馹Z\Y26 ۸oncږ[r!7*[dAt9gg =]!plB_$uZ[t 4q"س!m5B0`#E<0 H7y (-7vpEăE qAu}PoQ8 ei 2Pր1l0wbk'c[R%soMupb5@G$nyb(%C1>3Ql bWV `:dô0m 9|ؘ7g8NbXXXD&1/&6MIf0ҹcp\C"QK`"ʏuljx!03`31+"DL((\v!|*VMGO|3!ͮـ2E(M*Xr HHP, _$&3m Vnv&X %0z`pP_&hbN4ώ[8@SqJK?&ت"Hw! ZЀ`!a) Lh'~t.J0( K1K@ !#ۋ 6-h +(~AP[&h2<|M1=Ux  DBսbLX]Et$B;G~%Y?bʩ@R F>rF0ÿ:$sbX@w g]LhDd H1U%W *LJgjތ$BШaAYyGQ%( -LRݫE ejb'_Ф*O2d؋KT-R_w/5H .kjJ((J t+ ˌb A !wjJ/g.6;cCCڭ;Cpfঊ6M}r \j JP(&myM o2j}Dx/U]B;H7B|կ =A 0|LdDOy<(@,u@E] 3)52`Ø /891$x(%H 49/Ɔ%-!FNRMą@V jK4-xw8MFmZǜ"&MY(-nZ!d J~CGzc`b=r E  NH7 U/363tOc8)lߝ hA*ѧ2@PD7!{wd_LZGA~a<%lZܦI vA!Ai KlsCU5ەjS,a-ՏPdWOȟ>y/o{9n<\=?;쓞^}7џ~wϟ0p 0p!0%p)-105p9QA0ql&I0J0ǚ̂XOt 5^( bdfvROwx^M^II6"g}~}EFp V Ȱ&=k:TO怬\i״g ebP0iOCB !SfrPSD.ZCx#bN:B,4w:n Fpu$h0CB&: `V ʒ,L-|H i xI 14 SiznP`jBgahc1|ɛ ;` P6K.qrʆRĠ\j2&( R&j#G@ &LdD@n&@Iv2oN`.䈖Ƞn.'W2 |h防\y2,ʏ =xjʪe   :(ltn#jm"ǖ9`7!%1#;`T8 ".'aI$+Sahsv0ҲD", H/Qxelcܫ.Brd04MlB.6J%`т;ԋv ? D 3,Jӹ0`'2"a~.B@.-<%b6<&R DxR1]j0|dTjBb5I`vK(*iT8QWlK@F@i,^=>qs:[d *@ ӇnCf1mfGŢ7Ҋt'c4\48@]xL9HҊ>B;P}Q7ʞ p D hi@HV >4J:5;Vd*A@FsTc9? *TAbQ{L94I )%b4C3.tE*V- fg7 WA3'5LFu B"$KFŇ^U_qJ dK4W.P0>RJ( 9."}bɤ1Χcc. Y6L0fNpf hzIVk`'zY™̉0y]0'YA~dV &@A$Y9Ղ|9bAhjCJnF (<A"\*eN\L A=aJ_{m@z +],@1:uB1@ @,j  *BK/:ED\dD֫~e}u*ZC,:iaT̚ƵN+ =Gst 4P.iwX \o|0F.5\ `,[EUwirDǗeUSȋ,̍dSJ)x1 ntO2am{26yH`qfo{J r> l+0s06_ҡ*wWi&@/kӕYULN+gb+``0XȤՅ%C l hw*{ҸgٚwPYor@ X oSױڕx%tY 2 |IXP0(+bGA\pX)WF@M0" N/+(&k#`@e( ʉNASY*U>iEǚ D)*^ۣ$4;!1P O# ھӿ#$swr3 $+R07oF H '@N%Ch B  (m( }@>'I[0K<56lV>ŷh M1? PQţ!(={h[qЊZͨF!I& BJҒBVHWj0LgJӚ8ͩNwӞƴHJ:ԢHM TLJժZXͪVԦz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[Iַδ{`NhOpNxϻBN ;#?{gwmվy{KOɎ ƭi'w{< qn zyXZil{'∖PS?]L@ 9b.˜4 VuMXOL DfUkGPVHn@+ ֍DtLϲgQ uA,58V͔W`Ͽt V{jwLD 3Y$ !,Rʭ\O~Q4l8<8 дMh PG-TWmXg\w-J3-6B@hlp-tmxc=D.n'7 >@~WLـwϝ喗K桧ꬷ.A@/ 9.|>霽lCK_دAp_n{×:ȧ d/+$yor`  Nǻ,04 ,P*hLPX<*@rYt>B䤃,`9F@pI@O Ft (!-T87ôNrׂy@x'^=E]<@n8#,/;8oIRSΜQ/S[\_ɀߴ ^Fp8!f:o6ԣ,Oa6"h$( ym"|@ L3f&xL$ h3P?Ih*IWnx:+:܆ t9 wiiFRz#i"ӋÔf98?B*󜛋:7:کma)@Rsm'A> xPn޳psp&ӠJB=v(C:΋boR>I8M i`&T&B99q|>u JJ4iC`QCSrR꣇!eupRyҐ o8fns * X#A?<+u2,"Fα&;PTF)[X)G`L2hN6pL:xγ>πMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;'N[ϸ7{ GN(OW0gN8Ϲw@ЇNHOҗ;PԧN[XϺַ{`NhOpNxϻOO;񐏼'O[ϼ7{GOқOWֻgOϽwOO;ЏO[Ͼ{OOO/2ڗ30#0{8W6(h ؀1' hxz y^P|zFB#Hy)^z%'zH(xz7Ȁ ؁@B 3!ez!R-y OXu]4dXfxhg!,ppH,Ȥrl:ШtQجvzxL.ͺznۻ{dwqt7u;kjCG7oGuqiEi87j769u,6j8nyty,C66r8;ɾY6l A :(: Pd)[l8#${rAG@a6"$KiG6{ɳXp tbE HdCL&y-7uUD 7l\9MڋÔM|ʝKn:X,FC済kV4Xl7"(X!Tޤ1yͽƵKFP!@k~k)JL7n'1(g5q*E[[8QKNَ*{Hgdy Ȇ΍ h s9cG oI9TSYqFp)EmPU: C4W``jpuat|46+b8[(@(-C>zĎKNM06@ATy B6"Xf%@_2xَ1b: *z(<ŰL;BQFSǚt塈&btb'VrH(h up-u2&*ꨊAꩨ:꫽D 무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXgut`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺvle˶ ? Z Mf .@@mo{64 pg\vjl@l h.mɻMGް@sA"W-po2pjl@۵2M0r+Hw!w{\wĭ/\\]Ik$qC k^{]mnw|\!TY)q\ͺ^2q'0c/,`0/;^KvaoQ<BY39>{ a4`D#9l{vm̻vHiF~ϛ`z!prR}׿vp= /@e4< >N. 믁=u]fCлm? zԜf1w퓶v7l#@}d~N!s,[C@pH,@rl2(t*R,vr0x,.Ǵzn|N~BMkJnj{#i&}  ߲ HWpbC"=HqĊ3jܸ,ڴ:`ᄆl=:ʗ„Xp?4#`p"CH8 JѣٹI$R[ڈiU5  "p& "Ƹ /CXC@zP !.DNT,G0P0R>] L>&T{2ۂ~ P: D`36[ zֆ\8~x ώh:<^'r>O5!PK}?] 䩷_ ߀(5iU $ P_]PC$#H-g<+.4QbJKV H$P# $#+$p$~n0<)I$+Sd)jJX&vXYPm:8 tx*ەWٽFPi*^]  pPBA1O"mџA'$!(}=u0|{A]ޏҎ2xp猯dPNN7@P(d} HQ0J @??oo4)(x D`e Qؿ!- K0$T~ DkZJOCR hO84 hlIP@Y6L9D@ k5c rsX *cNjF`7;Xn5?pH[*Ȳ;aM@_$YBC6BzI>PI fqixL͒( E(0TEB=zWVz"*++Mp\;a沽NĎ}䄂~ubdhEI}t<=Q*t5ۨp>%@>"h=*€Ru $G(5E/䴋|ĐQrQw@|!SV Ƶs`X'Y63U[Hf*SJN%0&.PU[~'T[=+M@8DepzBkw QnK%zظFaɋ ¿@>'x ϯ v cda sw`SCr/zTL!?Wkpler* @Vm|6xrHV7J!~TvE819cWpEC:y?e'#H mj3|`[1YɊ2$@e( O#p6`OyP3\%6λ@Ɍ9Hܹy69ój(_W0J~#iP:x.+қgaDJ zkVY, i*ąlSYe{jeLDӠL?#|U[rIVv(N5&S5Tx&#= ܠ1]4 0O؈/s> @/[ CxuCpUQBAHQC!tB)$B5@eQC˄:AcB &DT^qwɈB)2W 3 (yN@!}TF>m"GFgdL]_xGAhG(Pn>1PFYvS}W g*ôybecŎTF~HyD|HKDKtKRfK# x6rtI)2$rK=RVcuf@"W(/Г1@}" D8'2fq-:.bo3L VY-@1sK !8ݒ-&/}Q]fi1<@ @1&1910vt22y.S22DI3K@Ҙ@2TEki- H)s#BPb P 0=^6&6}Cc3)œ2`1:oC)"@ q!:% Pg#%f#R+߰<oc3@;"ҵ99b`٩;aI(C;ܩ,q(:;e1; =y)A(zwypbA+IJ+ j)Bx,'*w,(J SnĢE" q(3 <= @Z QAz>jHL #OR#HRQ2*I2$+j2RܦEB B%02#4$GrYr%Yz[ʦZ cgJfʥ.1^::Zz`PRz!:SPqڪ:ZzBŠ)ZzȚ fp:ZzPںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,۲.02;4qZ8:<;٧=B[  q+sK뫳2P[qQ{426cJ]q:4!& y.l p0y+b)7K6"G3rrj)$5;D mpIXX0V&'RYVH" ө#e GۭdEOGRz$6f1sɓ;Y(:JS9by. :P-02c :ᷥ{,,i;C;d"DL)=M`> 95`RT5WPJ d 1 $ADN\c\ػzq{ prf@8Z zeӠ T[V-r"'r).>&,+ EzS<[T3@q3[52`WXX5XJwqrdi-p%gZ9 +;jd–0\-8"aW:" U+[n 6\]`nhh|:|k53d}Isn[S%Th K|p>S/{7a+ nS*X,\,ɼtIs0}r\)߀ov3p-Y3qRHKnCPŷD* Ya a LHm!sH(RKd&(BhDL5MP,;͢X`ͬLenE=6TFQj[ݙ [E;ü#S; i!ꠔ *pI֛D!6JM2:,c[R UpUŹy#mhF[BS}Wl=p-atA!x5,[r@pH,Ȥrl:ШtJZج6 z8L:^s6cӱ"nsI~dYm7D$pU[AUn@ # RrVBw*-H w|`܄0zڔpbJh} @A T@AN.wSNU(Evd O  I$4D$0L`tKPS #BL%DD @:DYB8:Y)thmVf*=02q@pGV) B hh{l:!4it!Dp{aYuXŖ{B!Zp@ jaE22;-y[ /;@2L;\|쀌 q  k@22{2%cAT`0k1xf@@#$t1hKS j)P [  gDN k'GDAKRu0%.~ P^D)]@fvP_{s`€ df`⁏cKT `cAf7c +p3B\+ \LN XZ_V08ePilps3  p^c\h-3304-^N (0YZt jؑE P\taN5К) (GCW;:pak$d>.D U˜ qP$xM`#i@kDJ3jB=?l &W<Ɍ#W:̰y;FOxë!aXZpPOX @fQD2^C``@Pf&r %5ĄN @6#ΩZs-|'2ĹkaBd>Y`Ȍ걑sXT/|/g) LHV~FBPZ$q &VԐg"P=.[i@}&\f,MDnoC%K:4k;nGu>^=ʜ&82"W E`bAZ3s~7!#|w$ ;f+da9 oȦ +zfzTZn‰PY0R pF Xf;mlJDRB;$ҢN%za!f;^R l:7nA zcT=ĎNqSقGORU#(%jWM]f;ڻջG+1LR hy [l|k.5InCtl`JT6ȬŴSn"SU:*'2Q eHv`Ng.gZ6s|<DS\V*GCZjjUĪXFL2a0X3yi𲒭v+4< ח?yRJ⿎ăɊM+y bX]%me͚fDp3 <: @@ )ABn>,%ԁKR4dA0#Ns3dPo:ECe,C 'pb7;! $'$ ]_r,$aUrKqr`*Ph)1AJf5d&1G* +~+2(()FY&b*} D@+ ɑ?G1`0&,P2Ѳ,X,/!@-֢r")`2h+!pqnR1P a08T1 {Mt'g,$d! t1X.r,23)p1ء3VD1% `k0"9$IK)usA4)Q6397@B:DZFzHJLڤNPR:TZVzXZ\ڥ^`b:dZfzhjlڦnpr:tZvzxz|ڧ~:Zzڨ:Zzک:Zzڪ:Zzګ:ZzȚʺڬ:Zzؚںڭ:Zz蚮꺮ڮ:Zzگ;[{ ۰;[{۱ ";$[&{(*,۲.02;4[6{8:<۳>@B;D[F{HJL۴NPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{ۺ;[{ۻ;[{țʻۼ;[{؛ڻ۽;[<3蛾껾۾;[{ۿ<\| <\|3@"<" (*l&<./}+<4- 0q5ВᴣVaZ*r]iQω˅V۷p@ + rP ZFtAKsLs\mao^!wSh^ yM큄R nDP%I B0nAi"%¸`Sd'̹.dǐ8#E4{ox`Z $3@ADvݷ? Ёׁ֜A܄V@tCA.i'sML  +1T285"Yxޅ İ*.|zlvtAY@:ՐG>0 U`\7@VN;Z> GpPJASAAf Ra( Z=">ԧU%pKhց%2c7>ѠB@,L`nCD@˟9@@cSX`( P)5AP&VVM'ffԦ` 5`´m(L ޚBKdTf&cNb]׭)XN՟j2ܒd @ǰ#!F}wq$ *+̏Țs9q_: %SB|Hځ7ZYa_0.%)9DA` <0Us EsHAKl}K\ Tt(jf#.8Z0P@h%cDJ|x|$0{#7얓IvxM,XhFL@tAw K UmYO~LD/,SO5IڑB$C2l^e !!c3 WB2u- gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:OD!> ?@"rC:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮvz xKMz|Kͯ~LN;'L [ΰ7{ GL(NW0gL8αw@L"HN&;PL*[Xβ.{`L2hN6pL:xγ>πMBȀh+`ofЂJ[z!460Lwҝu5mtK5/i* ԟ4 h1n2_ us݄Tz8uҀ-Pp0` 4V o}V EG) ['`Mzh<-w@cf HFoo/BAnD;?A!,F@pH,'l:ШtJZl`zxL.zֺ|N~O7;7p8;9:; Fޠ ḱo#Joŋtn ӄxXoHh S Y˗Wn@c'k6:I!gP|sϠI{HrUp-aj4btFٚn5F0tޘ-ٳξEhl/W7ʵ1 e By9'ΘΚiVx "?ݤ pM/IzV5xf6"x]Nn.8W `C6m1{7e^;Ҷ rAMx`M|8x\s1݃"6(@_N6H~v!KHRwH0 _xiǟlڭJB(;h:dO9g Lx ؎f/4 c4 yNd(W 5CNZw СTYXVe\p`^sk%=XrvZȔ50a91yT^8&86zvbڦ q鰀x5 C}`wۙ,Tu9 J0e) {D,M9X+ K{hD@j6apao.pY.) j xo0<rv K~ (M|\ry &,R[j,XZ3],0o7_3$Sb_xۇS[_~磿 پ?_399P`w PZa`c@nug";H,IOa rB$rKHC 4 a]g'U B%^GDv`M!:W vz-'< 2$)tZAHSR>1I01Ñ` AMh@Q(ڎAttL=dc!4G@2HhKNƓH$$j2KJBlBdW RSB%IBP$/tAUQ8 hf3k<[dVL?fYR @;Ͱ2Ҳ/)C%@I})?ZZ;%=tLebOb |mSp/`c(P`*9y*eWʨC_9%s&)og LR ^YIYB$ jd eMlX:Tyϧ>U[30<9L֓U".&Ov LNR}2q=\x ,”b}!mFL ʏ|Ujv*q*LuV*4JН"Nꓮq!5sHv:gAZҲ:b¯V2Ǎ,#CHr<-y@ gqU;R8(nrBt {ݒ26kXᬻHINz;#MP/ Df Ty[ǒN,Yء ӷJuXd$6TK8<<׈lY`i`?›LֆMBUQ;1cuJ:XVgv$W"挝 U&a>&/{]+KL4[0;y6sk,[Sh$`: $м^!Qr8LpXBMdXR57u2 ,BZ3fq8Yk-)~BFb/01AɁx7MeWums!uox̔W9ܒm7{ ?1 (OW0gNs8yv>ϞP !,[D@pH,rl:ШtJZجvzǰxL.zn|~vcv{jGŹ| x b&q J0&4s7cӦÇ! +F LD2$Q\2,(`ě8s3a<7- AƠSMS?K$!(hsBm&H0,N$0^jbsAgsŖ"o]t+kbMい`@Ȋ 2j&2P%I 3:J7s 4p"t'Fx8p4Z޺o16+$y-uAH@P\௧WϞy֟`}t3-\WP?I֏ *IZGWp@ϩ(@`@_L v#d3SZV!!cCVÖ@Xޜ e N"G/n_"V sH;u L/7?:LsBPWIM9Nzps "iX8sda6r6_v` ( &wf%uG$ pwe`mwmm drx`x>&,?$)H `^3zIm?d/ w2H"+L"N^'e>gYp$*PeEv6*.v[lR';AC# B],WЗ NԔԧ_XL}q-] ;XLBiO{QDdN^M-Qu*t;A^gu j(6#Ufe@+diGS15SS6U<:$5SKTF0T(!c ($#a#`m 6*S4x'Fc3% xVs]a^v3=!Y @?C;Cj3?~F;i.4+<2: @vAAUa3BU'0v\}Š'81Q5 2-iCB@Cw(?lD17" (!_Q()2'UKqaC-2#FA3|HF,r!uz$y !*zjڪZ+Q"(f#%)""#[2!z!!C:u"A$\EZ$%r6$JM2$#e<ڮt݁r;0t ,IC8;[{۱ "$;&[({*,ˬ2;4 (5{8:<=@A;B[D{FHJ۴ڳPR;T[V{XZ\۵^`b;d[f{hjl۶npr;t[v{xz|۷~;[{۸;[{۹;[{.񴨻{M{:'R [V0!{# kXjYXqre 4&`?;[ IBEљW26"$P1 V$H!(6eŠID!Go4./boBbS `xzxHUeKt`'UxH R!"O Sv#pMH :*. y*3Q "~I 'Pu31%Fv$E r _[W#˦'{LH1\?&0 W& !:ҡʸތ KăL!fDd#qPVv*W &peHɬnk)"Y 5fe{LPx =Js)0"k7\y,5{_1WC :iIcM :M,!\TW4E5eFi J2C0Tq i(+BQӲYBV d t,$oYvJV5øB",`oTզsDa<6We]`o"Nl!f!ۂfٰFɐh!l͢n!*Hm!:rHO5xHk͖ DJmMRYMh:h@1,6gmgJQ?,8M#@iJٗc|jĉz{],Mj$<l*ེjkk:.q+n{~޸A!,@&ڋ޼H扦ʶ L]!x5,$]@pH,Ȥrl:ШtJZhmzxL.znsvNH}oILpCTMBKIX',-T N !,&%JC"+FVF V=BbbgH H  jŚ9|qH$h #@0l݁th3I)Ȥi^ P"p0ٵh2XY5IW6@z5G`톳z̰Wc-KHc#4(T ,TDPHra*,c~*&>`hxMΙqR&fFȄSRNcW` rB:8@Bl"a֊6Nl/8ő7ᥓ1Pt0@(41|`Au!4ڨ3"0 NsEh4t gVD  'A a )M:@>B&0f^5+~j8$PtlA +T MZB D [yj.ċ D@AyAZDЬ@3jA[,*`/J!1)rG)kCLsf tW(¥FxAp,Kv8z)h"ՎϬU<2|AJ&)ZjBQ?@:q"oDUljjiy~c,:ssH@->OٟM8cfXd~ @JЂMBІ:D'JъZ(57 Mz HCJґKJWҖ0LA8ͩNwӞ@ PJԢH0Q:PTJժZXͪVծz` U |42hMZֶp\J׺xͫ^V0hkT+MbTd'KZ~-fS 6Ē焑uM l\M-Xk@K֩m[:FoUK6%t4#žl"U-kW ڰRmiֆ%:K׼A{kju@̷]cK6dD-Aځ0'3*V S0 \+nR N4 Gdm!@d@l.kx|@w\DiiQh#n 6a#4҉FKbd-7ET A(0@HiȊV@e0ģe@~}Lg"8ݝF"0mnb Dm|aj% @B=:y\Rk =U4&бʼA1\i #J5{W4b1N]*4iLBbfvm8[4pI!C5{(0DmB;vIM~KmĐjm7'\]ѐp$~:!t3 .[<ہe䶲Es޷OOOϿ8Xx ؀8Xx؁ "8$X&x(*,؂.0284X6x8:<؃>@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXfxhjl؆npr8tXvxxz|؇~8Xx؈8Xx؉8Xx؊8Xx؋8XxȘʸ،8Xxؘڸ؍8Xx蘎긎؎8XP#t3-BtX+q ~bH 8 Y8q)o3@&( i-ن/) 93Ɇ/ِv%%#0uq,i19ѓ БB$Oi-H`i)9t !,i@pH,00:ШtJZجvzxL.贺n|N~j h*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$c(#d`j3 3rP:T<:=Ґ@DU<8ڐ|5 =˼ݙ/@Cd.uϖC,e7]DԬPԾp7:{ww -LOΈo=i?=ތ]=rþ=g'^{C0;ғ0v;P?#s\zg |C6m[Z5aMQk w\P OB@C΁%NA;bLq#|` P=Mw{6We ? F0tR%2qleL@`6#+t㸻5fdxM!s3,@pH,'Ial:ШtJZج6zxL.zno|N~7;7V8;9:; yʣ (Ne7kpŋ3+ǎ7ni±M Ɨ0cjMp7 ܁ R ۧW;X;laG-z̫Xi,~ >O1N?PA1!EbXa"uȁX>u-RQt/!fASYAK# <"+'qƣ*ha*L Z:I9XFZ@d.@g8 <#EΆ5l H$cX>bVRimt32q)p ]4S)Ν0bLlŢm3Pgd_fƫBs^ md't2^ ߒ0zeO2KkHDt"J+)u8G@%i3bcB3'ĪT6yhǚ@H0][ꉮV8٦\Vd369sb7|9’#_DS*"Y)jRGSF$n6dUP @4/pD x{/_ 0 3Mk<@Pnq'zRsCwcH.HX ǐ('P*qtŏI'.mjCVu(͡AX)XOy 7IY:jMW\Xu>ǚZt#Q%C*U̘YdbO./ŰmD*AelcP%H J&3b,e2+֪pv*+%he''J]WuqWpgp>j s,T) Mj~Y,Vt/XݝLJܨjbc&W$ u` u.@hYGq>< iLt H\XݱRTAkt 9aP!,isP7MP'DA ٚ' · |ꠖI6]ɜe9I'˗~ wو鈟yX)(<{r(v8P sC&ФT)pzJjZ ƹ%:")dWgfW$t w3z5J٣SzAz?kȋxW |Q ,`ʡ*P9 z#5*بCPp:svx/z@gfآ ({QА(Ekթ j &e: ժ \31yrvZvZv d٠ ew k$()IPt)*J늈([s{B # #@^ j1 - $lJ"HE/#P@&tJ)Yv+f#z`yI*;;pe7 N 3kg g4*Nʗ}Diz^KJ8&K6tzXGc}gJ@lcvb8~'P} u{Vkp|gFZH嘾ؘ (ǘǍ[8Wz;v{|Pw, ||<j ,RJswx*,.‹V ,8L4\t@BB EI (@h7HܗS q XI] ]t9-X]=䯪. HjlۀH ~=.$iNl}Th g8"X<}pM޻Bޘ@^=߶~ \#`D&svcP;g [C,퉽j N8H P$C#| (d(uB`2HQN[ HEK؁'Ua (F3iTF7qXG;AWw#)G?da I* " FPA\%IKAOS 2:   Х=y:@Oip\THJ$ti]R$+X AA&Q,(Μhqt (& U@tD .P;Xy@YBfH4ŗʉ_,vD>`b+*+),ܩ,ctBB Bb.Џ".@^+R2%"o1zK2&28>EDHTW`l T`T4:Fm`t@ {8c|9?dEc$R@>R@?C 7z/P??8|?9?AAe$du61Q@7أGH#FEbENP֔Gh, K ̈gKF0Ǡ.ģLrjqæ`ؠĶD PD%t+f. +z/Q g6 ~% yD,/dV%W̤_6n=u60RLl 4HfZxm_5ɒnClxBo+[4%ږ$%[xsE \ae:E4B>l&Lcl @f>f<`ee7B|3d4lSx c4n?H&S,s@*;ejF `MY42?dv1|%( `a(Aolx`j̣ gC!VbE4r"D~d<t|Ļ NgdPHuu iv44wGXx=^ Fk{F켊cn@Sr|(~̧v(sV~Jh`@%f BeP Wr R H$Ls0X:>\HcY0-XhH6^ "aFhP 󕍚uq`٨4IV,P-jXͣP@^LueNp"ԃsˊ enOdP?rp"#,Bq@&GdLZP/{V'WfA B`5Oԣ%9d(c6cTwPx>B7C[Ħ'))R(VGKF4u$x ikc3$%U,3Nؒ%%88bHyL %  $c A& *+a&AB7`ɘcBG2㸙Ms7k6Y"P~X$&9%jE ljt<YJ8ǁMg&!AڟRpC~QNfr9.ZIE>Mjm#5Ax'osyj+U T?*ffR9IZ(mMYe (a D WRS@Dk !8/~| D%g  P+{Rա4$ aTA .t}hqh V[!,@&ڋ޼H扦ʶ L]!x5,]pH,Ȥrl:tJZجvz0I.zn8TN~B5bGUO{^dSʮRR#]RR1'%R0!]. 4t ߨʅ A`eBpQ.PK C:Yذxr`iN JyJG#<#d%[H&ƊShڃ@ h#l+HIWw k Pl:1&a0cvYF9AYga$VD9Et:pt,X(}H "&*F|c tT2EE5MUqp#S?6mPM z&+꫱ bqa)Ϟ@Vff+Lv;چnR߲k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-mhlp_8}@5|߀.n'|WPwFWngw砇.[Oel.n>O:쥷^'.@nπMBЈNF;ѐ'MJ[Ҙδ7N{ӠGMRԨNWVհgMZָεw^MbNf;ЎMj[ζn{MrNvMzη~NO;>[%hMm `3`@řq<ܶLoL.Yly/ʿ-!@grk`.yM.tWF|snP@Qdvɏ;5:ʟcBֵ-Ϡ7կkƺOv `bqsK^'O"!d4,@pH,'Ial:ШtJZجvzxL.zn|N~ZjFq ^# L`Z Wo,'ޙS) '0L/'`,&aiJ+)\0x8XHxe\ pDѢ͛8`- ~ pV"?h`a+(B T ypLj䳀V֛3kɷ/5}0<ʄM&RYVR p0,0p Y!I }C @#4%q<@LRX`A aMA]Rb<+L@U73s>  '$ =(@pʙ=l 6y8H% 6yrHݓTA f$  ( *v7$b)JJLdBL(XĖ:9)>ZL (Z$ނCtPmhe+D|2N@_Vg?LS+׎|"NM.66@o"yXY#DA &E̳ C+VXBz#s:KiBlj4Xa) Ew4%HQO,BO0<` d +6X/7.1A]NxXCn߁/~P3>Ln斀^[$zOgp@]_1DoSMRo'7G/Wogw/o觯/o H@/TT"Q̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 8IrL:v~ @JЂMBІ:D'JъZͨF7юz HGJҒ(MJWҖ0LgJӚ8ͩNwӞ@ PJԢHMRԦ:PTJժZXͪVծz` XJֲhMZֶp\J׺xͫ^׾ `KMb:d'KZͬf7z hGKҚMjWֺlgKͭnw pKMr:ЍtKZͮv+ x߽Fp`-Hzga3`O׽EA|Sw; uJ#!%bNAz7:#o x_* Ko?ƫؾ(}xKo%W C|wo>)>8\^p)#:an21h!|oޗsH3:l M6Ƌa `!,E@pH,#l:ШtJZl@r0x,.4zn8|.~D8787;7x9:ǻtڤ;꿦;6 taC "\ǰCpH  lǁplɓU\RFrLO^U$H&*f8w:TM(زS)/B7 h8a/(VXA] a bg߮1Bڬ4ׂTwӧ&st=W7F9xШpٜm`zl*̼9. p Sc pNr}yX]uqO1GX?? 2ٴSl@M5/fd;6fN?{ukzgw*>nF 뱐|'.tE[~9<ǡSx$ۀ$ZMVaSN00 Ay֭b0TBráB*fajݘO?{\!'XLG `fMYF@O8؀F:0F=8"}vˍPt~*erjƑrx'Vo cCUl #]2A^Ah3R0#@apC+bAk, DP5U{a^!JkjmEIuX*F7YRʘ*댃«o_wFcKp {p7p+o?1qyq q$p\&r*,3C.o3S ⠨QZy ;{u"G׵xbܒ{uLEkp@D 69Q%lݪC(Fb\2L_TfÇE4ɒH$&wF&iudk@x P S' σ䒞p-0y -2%: >ȕh$y:Tx/ -!"Y<P|#c`GȏQtFwq* U= ^a_JP%1aAql%7 yrh$Vii )ZQHQ!"/c<2Ti(C8#ft;`fB!Tep@QGP:hQ.(M$P[ >J5ƕl&309Hj`_K3&y(2Ƥ &+u, iu]%7[^^Ҍ[I "'s DO\a 5 {s%9w-$s $*K'st]{w/}]V\$8w|r\xγgVyMBЈNF;ѐ~4'MJ[δ72!,fl@pH,Rl2(t*R,vrqL.znہ|N~qex~ {Bsc&νs 駁"ʨtJ,pn]!I $Lŋ3j5M8԰cI_HH1'FYZq3\5}p*Mrl8sE#qTJ؊bdF$S/*0DU(֞c`Pdh/U]ʆb [%vbPV?WE[J87ܝ% 2Zņb-9XeS!"nٳ~q2q.HH 9'"K+ \?/m +F|5!]X1&B`Vޑ QՀxAkC{єv) p֩R ЁuNd@!ŒZ7Xbgn `@(ގ\TB9XYl0HPYqpTV 6<] IXF 5QB-tAeI}h) ,Tkb `+' PhiAlC 0BC,(H*8ZVrMA㮵'g$$2cPGdA `,pB Hm+@9j NpW# 8x z6S 1j5*H&c7+ Tmd ^k ʵ"4gC+IJ  $`u@B,W8ԩB@(, SiKִ@vl3Cx0 q !Uep:2Y" hF|BnDk%H+(@&tbq`T@  VęщFSЬPx6(:"Rx覬X@Nw:8 @F0QbBL@%i;ySL`\"I#w.H)`XrR *%kk$P4] ~jɓA:P`bV7Yd (x *Ĵ?΂ml#[lteԡ32 g&_nvCD@nr<6QoO@"Ȯvz7}Y5zؽz՛;ӼQͯ~LxN BBQ'K [qy{ GLaWܻƅqBW6,q?8ĸSdE@'3Iޫ&-0d 6B@Ё 9@i5nWBUy.tp) pms?, 7+E*ғ  hg6#8sC\l4>M@rj /`tr!{:) ʤ&u5i*Vq#gvHE@R%0@`wꚷl܎k;DZZ5xBgS"2p>lk&\W GI w4\Sk̥1iR+@*j〷z@Ne;^)۸Z]@䆚'fD.Nb8.sJaoa ᝚ ZS^ k^_$CUͽVI PsEZҌUY]`+XwW^ON[V (tKMc&\B^չYJ8I+JmBdqg2fVܘK3hJd|B3 6F q>a qdn #iVL33jKg 0vٳ<WV&4<&O2o'7aц$>`Lr$PW[7}{a䅺$Q2r%?5W4B%TC bWUY&'}1Yw4j1P5 oRϴo[) @kn{ytg8)mv!2 9v`P\|.bw[_q,|i?c9"0ұ3/05sD3$מg Y bȏ 4N91zAՕPm3lkf3P$US %6g7{kAc0D'2VZJFK ")`@y,xD ŢQƖs H@@BXP!#%:$L,NBD\P FG`^F@Z^PU#N'Nd<TR2@q{AFZiP6.v&YcVL4O?`vLV2.$PFѷH־؉N~ɩN;S A XbE낐_<&-lJ6:^ZupZqV;Bqm˛MEPa6LKsE @ƚ|mZ\͚!=6BPNѱG  hPCHI 1xCV:j{#3JjEbU ᴊGVcpgѦMxݳ3v12^k@I xgiBBF#-2i8~Vb\ +FDmDi  ZʬwJil-T.`w2JA~ n0@iXD9ჭR\ G(Z 00 (  Bb&V4o' )t yNW B@L EG   & &2>LP $4 JpJLHnLH#3O RHh$VkNPJ"0uEVMU,Tb5(L@R @YLV7< > nԩ$V 0-Y V蠥 ^^x@Au# oߛ ?O(!}bG8z'DPHj^+Xc*1N\dcpJ=m}'n#iV+_x捀v^gTvo!2z$T} >< hkSNzmަ.쳏YGLEáx\pk0Fpoh2;}@>3X,NdZ8!.YwO rS0F%RQS} `|H;P5R@whUυs|NA<@HUB8H6Q;009fã1uHmn`YBއJDfP |jQ^OFw=f;qĠ_?(3* {HѤf)E6?,I{h1U:a*kP9aXb-p &@d'N  $Ɔ)L T}** &( D^Qd8:};Y 5!`|ݸUޓ*idʹ(8+{ RR :Ya$h( Ӻ6Fie`8dU= ,mN΀dnd!J$Em 󄲮@4ȣHP-q 1j]W;h xܐ4,'LPYCЗlF ER& S۝Xp%)q5d0w1hֱ%uTtP*2XJv9$cUӀ|HR`H-!J/ᄆ["1eD1h LnVpohna>p) u5U_켻-RD5%=(iN88O~_  t?&9"~ɄoVXk<03< N H%:Ƃ[P)CgjoU% Z/BV4+ puQͱ#]~ aPxE>dALV[aDVXTBq'~n)Ǵ5:CQʘmkkJ[ٿA 'F ҹ <gbsHOR 4h)\ !Xƍl9TUKI _ c3:i)g%\*Tu0oP솠J}+M(/Ҋ@^)4 @c*NiS@C]ѵW > _++eW-B @/y˺E@uktOS*jxjY1Xl̔Yǎ)<B!O>WWPvLJص/ЋBYq9gbӾLR̀W{ۯw#~(>O?p; 8o?z}#%7џ~wϟ0p 0p!0%p)-105p9=A0k+DL0N]ЗnItVOhCdZP0izp_gfxb舑f&ggfP}(ip)')0a'{H"'  g#"h&hٶ N"zf2XdN?$S xztp|ObZ(+Ʒb0(bC^bzeȈ8.fTѷ R"g$l(9@BM:BnQPm:ͺ: eG}x }dRPħx}NB€On}Gd6@db( 'Ef5Ti ` q|}[kK6LlLqaH K@*#$n- #c3 8N$j zlder6 ax:dhBN(1Sz&Ic)p`:H: G ?E-+n@PalBR_ ;@^J>t@r "\!m>xjfZ($1 ɼ,oG *"1\'N`PPH@;Rf-n^̴b7 p$!R$$r 0CNRN'&rjfZ I-Z3* $*$:-+/%Tj8Srik- sZi,'s:`0;J4+2q ACVs.*e7aB^̾>3b: bAFw sat*BUnc2B/*5c `.X@8]f;G Ȃ*x7C%U8Mc>Dj\aJn:,!HOmEF1“@9c$aj&y@H`&KBmT ~Mgcl@I:dHfj ,@ D3X5N]"׮Y$@1>TeNS<7 섟Q&Zj-x5T\J,Exx.-!"q:E%,cXZ%+ adMb a訁G'&bV. T2 9YRPc,yf_g 9gŤTJr #mf?0fx0l$/jnk-oC0cPH'wng 7M^-o@fP0o=Hok/fo ;oiwwqC-q!!_,@&ڋ޼H扦ʶ L]!3,~@pH,Ȥrl:ШtJZجvzxL.znx-a ^8}L |DrR%C !~N0NEUOK%B }*1v+# H) B ̲mE& $'y* Hҭ a`ѯ <fz8@@?Of|1ܷV 9 Iȃɫ,]ȅ4CV@TH ͚@U" bD_GeS` ОX 9CE:HUa%~x$~f ň )}v ($h(,j4Ë0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+kflpp /p?,qO\qww ,$l(o0,4l8<@JF/fH'L7PG-T#=4E#t [w6 Wg=h5m7p?  5vÌw&T aA0 puu\@BhE@ 4&%B$  8cNsa):t a쪷3 9;)8Z_ $;`bxtA0Ad! ǹg\M>&C>J@Fg'd 3Dw0ȍ"By4A ~uof`R> 5;KH'=$K݅P(x|/A"_#N,-J01(yG՜OVrf-"Ntg?4KCt1KV"-0bJ3zڬf̲!nl p@dHH'ʏRc\ X"3T^fX(jfTf <@9YEI9բ'ΎZ"h:pEYmc?ʌ<7tf)09f@C¼o AXR)IA>U$`uMv%- s@<9piMNy,Tc:n `Arւgy@ YTtB tk%\477K -a`Vfs $_gك ECk 1`:k6o \h"8X`j4fd$@t: h|>b-V=(@X$Q`]491^|.\Bs@:b yK>d-LV`d.oE`l@IG)[aw89avV'˞uMB6Eѩc'J[›룫N{Ӡu8,CԨՒVհgMZָεwjeG𵰇Mbv!s,@pHQLG IlBlKCnlYq"٢ΧXԈ-`L~3cqY}uak!mh3hm|a\#fB3^zH rMY\Ska-JĈ{TE ]kԎTA!,@pH,#JA`l:ШtJZجvzxL.zn|N~un=D=6x4=4 \=4,4ɛ,ц͹w=,dSĖ4ؖ x,B3*\X#ċ3j vIRRL@˗0cʜI͛8sɳ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6hDA!s,A@pH,Ȥrl:Όt: FuYH[kf" ]{'BN}f3sLJd#G rUFHooDG!_r Cm-^BrE3  gEkX#Clmmg#!gvghl_ v ůCʹ|Dkl!l! ؜CȞ䒇0&#Q:u0(} 2*FCgH"  A5A֒ED 9TAQ mXΏ BSW;F`e<;3%Gbh`3t1,DY0-gg׬P`^\T!VkT4B<2eJ⒑`Qf $ ^ͺ#A!,s@pH,Ȥrl:3AU%Bhޤ;`iY5j] |&إx=~\df=,r6U4qSgbvsaj\fQNd]A!@,@&ڋ޼H扦ʶ L]!,c@p((ȤRy02d"6Q$\$6P#1vJq(,y'%/PjSU( j BNyFbNNCA! ,@pH,Ȥr$z rMO!!p? Pi"Zz+!qk4N CowGK cR' +^KccRQNJ/"}GJ mpu&H`bdahҩXLױHA;smenu-0.9.17/smenu.1000066400000000000000000001711561400523266500141660ustar00rootroot00000000000000.TH smenu 1 .SH NAME smenu - filter that allows one to interactively select a word from stdin and outputs the selection to stdout. .SH SYNOPSIS .nf [\fB*-h\fP|\fB-help\fP] [\fB*-H\fP|\fB-long_help\fP] [\fB*-?\fP|\fB-u\fP|\fB-usage\fP] [\fB*-V\fP|\fB-version\fP] [\fB-n\fP|\fB-lines\fP|\fB-height\fP [\fIheight\fP]] [\fB-i\fP|\fB-in\fP|\fB-inc\fP|\fB-incl\fP|\fB-include\fP... \fIregex\fP] [\fB-e\fP|\fB-ex\fP|\fB-exc\fP|\fB-excl\fP|\fB-exclude\fP... \fIregex\fP] [\fB-m\fP|\fB-msg\fP|\fB-message\fP|\fB-title\fP \fImessage\fP] [\fB-!\fP|\fB-int\fP|\fB-int_string\fP [\fIstring\fP]] [\fB-a\fP|\fB-attr\fP|\fB-attributes\fP \fIprefix:attr\fP...] [\fB-1\fP|\fB-l1\fP|\fB-level1\fP \fIregex\fP [\fIattr\fP]] [\fB-2\fP|\fB-l2\fP|\fB-level2\fP \fIregex\fP [\fIattr\fP]] [\fB-3\fP|\fB-l3\fP|\fB-level3\fP \fIregex\fP [\fIattr\fP]] [\fB-4\fP|\fB-l4\fP|\fB-level4\fP \fIregex\fP [\fIattr\fP]] [\fB-5\fP|\fB-l5\fP|\fB-level5\fP \fIregex\fP [\fIattr\fP]] [\fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP [\fIdelim\fP]] [\fB-z\fP|\fB-zap\fP|\fB-zap_glyphs\fP \fIbytes\fP] [\fB-P\fP|\fB-pm\fP|\fB-pin\fP|\fB-pin_mode\fP [\fIdelim\fP]] [\fB-p\fP|\fB-at\fP|\fB-auto_tag\fP] [\fB-N\fP|\fB-number\fP... [\fIregex\fP...]] [\fB-U\fP|\fB-unnumber\fP... [\fIregex\fP...]] [\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP] [\fB-D\fP|\fB-data\fP|\fB-options\fP [\fIparameter\fP...] [\fB-b\fP|\fB-blank\fP] [\fB-M\fP|\fB-middle\fP|\fB-center\fP] [\fB-d\fP|\fB-restore\fP|\fB-delete\fP|\fB-clean\fP|\ \fB-delete_window\fP|\fB-clean_window\fP] [\fB-c\fP|\fB-col\fP|\fB-col_mode\fP|\fB-column\fP] [\fB-l\fP|\fB-line\fP|\fB-line_mode\fP] [\fB-t\fP|\fB-tab\fP|\fB-tab_mode\fP|\fB-tabulate_mode\fP [\fIcols\fP]] [\fB-w\fP|\fB-wide\fP|\fB-wide_mode\fP] [\fB-C\fP|\fB-cs\fP|\fB-cols\fP|\fB-cols_select\fP... \fIselector\fP...] [\fB-R\fP|\fB-rs\fP|\fB-rows\fP|\fB-rows_select\fP... \fIselector\fP...] [\fB-A\fP|\fB-fc\fP|\fB-first_column\fP \fIregex\fP] [\fB-Z\fP|\fB-lc\fP|\fB-last_column\fP \fIregex\fP] [\fB-g\fP|\fB-gutter\fP [\fIstring\fP]] [\fB-k\fP|\fB-ks\fP|\fB-keep_spaces\fP] [\fB-W\fP|\fB-ws\fP|\fB-wd\fP|\fB-word_delimiters\fP|\ \fB-word_separators\fP \ \fIbytes\fP] [\fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\ \fB-line_separators\fP \ \fIbytes\fP] [\fB-q\fP|\fB-no_bar\fP|\fB-no-scroll_bar\fP] [\fB-S\fP|\fB-subst\fP... \fI/regex/repl/opts\fP] [\fB-I\fP|\fB-si\fP|\fB-subst_included\fP... \fI/regex/repl/opts\fP] [\fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP... \fI/regex/repl/opts\fP] [\fB-/\fP|\fB-search_method\fP \fIprefix\fP|\fIsubstring\fP|\fIfuzzy\fP] [\fB-s\fP|\fB-sp\fP|\fB-start\fP|\fB-start_pattern\fP \fIpattern\fP] [\fB-x\fP|\fB-tmout\fP|\fB-timeout\fP \fItype\fP [\fIword\fP] \fIdelay\fP] [\fB-X\fP|\fB-htmout\fP|\fB-hidden_timeout\fP \fItype\fP [\fIword\fP] \ \fIdelay\fP] [\fB-r\fP|\fB-auto_validate\fP] [\fB-v\fP|\fB-vb\fP|\fB-visual_bell\fP] [\fB-Q\fP|\fB-ignore_quotes\fP] selectors ::= \fIcol1\fP[-\fIcol2\fP],...|\fIrow1\fP[-\fIrow2\fP],...|\ \fIRE\fP,... parameter ::= [l|r:]|[a:left|right]|[p:included|all|[w:]| [f:yes|no]|[o:[+]]|[n:]|[i:]|[d:]| [s:]|[h:trim|cut|keep] attr ::= [fg][/bg][,style] RE ::= \fB\fIregex\fB\fR selectors and RE can be freely mixed. in RE is any non-blank ASCII character except ','. .fi Note that some parameters require that others have been previously entered in the command line to be accepted. .SH DESCRIPTION This small utility acts as a filter when no input file is given (reads from stdin and writes to stdout) or takes its inputs from that file. All the words read are presented in a scrolling window on the terminal \fBat the current cursor position\fP without having previously cleared the screen. .PP The selection cursor is initially positioned on the first selectable word by default. .PP There are options to explicitly or implicitly include or exclude words using extended regular expressions. Note that when some words are explicitly excluded they can no longer be re-included after. .PP Excluded words are skipped when the selection cursor is moved and cannot be searched for. .PP The \fB-W\fP|\fB-ws\fP|\fB-wd\fP|\fB-word_delimiters\fP|\fB-word_separators\fP option can be used to set the characters (or multibyte sequences) which will be used to delimit the input words. The default delimiters are: \fISPACE\fP, \fI\\t\fP and \fI\\n\fP. .PP The \fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\fB-line_separators\fP has a similar meaning for lines. Special character sequences formed by a \fI\\\fP followed by one of the characters \fIa\fP \fIb\fP \fIt\fP \fIn\fP \fIv\fP \fIf\fP \fIr\fP and \fI\\\fP are understood and have their traditional meanings. UTF-8 sequences introduced by \fI\\u\fP and \fI\\U\fP are also understood. \fBWarning\fP, when used together, it is important to know that all sequences starting with \fI\\U\fP will be interpreted before the start of interpretation of sequences starting with \fI\\u\fP. \fI\\u\fP can be followed by 2,4,6 or 8 hexadecimal characters composing an UTF-8 bytestring. Here is an example of using \fI\\u\fP to compose a lowercase latin e with acute accent: \fI\\uc3a9\fP. \fI\\U\fP must be followed by exactly 6 hexadecimal digits, including leading zeros, that represent a unicode codepoint according to ISO 10646 UCS-4. The lowercase latin e with acute of the previous example (codepoint \fBU+00E9\fP) can then be represented using the notation: \fI\\U0000e9\fP. .PP Note that with most shells, the \fI\\\fP before \fIu\fP and \fIU\fP need to be protected or escaped. .PP Quotations (single and double) in the input stream can be used to ignore the word separators so that a group of words are taken as a single entity. .PP Non printable characters in words that are not delimiters are converted to their traditional form (\fI\\n\fP for end-of-line, \fI\\t\fP for tabulation...) by default. .PP An invalid UTF-8 sequence or other non-printable character will be replaced by a dot (\fI.\fP) by default. .PP There is nevertheless a possibility to change this substitution character with another \fBASCII\fP printable one with the help of the command line option \fB-.\fP|\fB-dot\fP|\fB-invalid\fP. .PP \fBWarning\fP, \fBUTF-8\fP encoded codepoints are quietly converted into the substitution character when the user locale is not \fBUTF-8\fP aware like \fBPOSIX\fP or \fBC\fP by example. .PP Words containing only spaces, entered directly or resulting from a substitution, are also rejected unless they are not selectable. This allows special effects like creating blank lines for example. These words are also kept in column mode, selectable or not. .PP smenu has an option to define a set of characters or UTF-8 sequences which should be ignored when reading words. This can be very useful when dealing with inputs where the EOL sequence consists in more than one character. .PP A typical example is DOS or Windows files with lines ending with \fICRLF\fP. In such a case one might decide to ignore all \fICR\fP characters from the input. .PP .SS "Moving among words" The cursor can be moved in every direction by using the keyboard arrow keys (\fB\(<-\fP,\fB\(da\fP,\fB\(ua\fP,\fB\(->\fP) or the \fIvi\fP direction keys (\fBh\fP, \fBj\fP, \fBk\fP and \fBl\fP). \fBHOME\fP, \fBEND\fP, \fBPgDn\fP and \fBPgUp\fP can also be used, if available, and have the following meanings: .TS tab(@); l l. \fB\(<-\fP, \fBh\fP@Previous word \fBCTRL\ \(<-\fP, \fBH\fP@Start of line \fB\(ua\fP, \fBk\fP@Previous line \fBPgUp\fP, \fBK\fP@Previous page \fBHOME\fP@First word of the window \fBCTRL\ HOME\fP, \fBSHIFT\ HOME\fP, \fBCTRL\ K\fP@First word \fB\(->\fP, \fBl\fP@Next word \fBCTRL\ \(->\fP, \fBL\fP@End of line \fB\(da\fP, \fBj\fP@Next line \fBPgDn\fP, \fBJ\fP@Next page \fBEND\fP@Last word of the window \fBCTRL\ END\fP, \fBSHIFT\ END\fP, \fBCTRL\ J\fP@Last word .TE \fBCTRL\ \(<-\fP/\fBH\fP (resp. \fBCTRL\ \(->\fP/\fBL\fP) places the cursor so that a maximum number of words (selectable or not) are visible to the left (reps. right) side of the window. If \fB-N\fP|\fB-number\fP, \fB-U\fP|\fB-unnumber\fP or \fB-F\fP|\fB-en\fP|\fB-embedded_number\fP are used, then it becomes possible to directly access a word by entering its number. The numbering created using these option is done \fBbefore\fP any words substitution done using \fB-S\fP|\fB-subst\fP \fI/regex/repl/opts\fP, \fB-I\fP|\fB-si\fP|\fB-subst_included\fP or \fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP. Using a combination of these options, it is easy to control which words will be numbered by adding a special symbol in it before using smenu and removing it (substituted by nothing) afterward using \fB-I\fP|\fB-si\fP|\fB-subst_included\fP by example. \fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP gives another way to do that, see below or more. .SS "Searching for words" A word can be searched using different algorithms: \fIprefix\fP, \fIsubstring\fP of \fIfuzzy\fP. .TP \fIprefix\fP (keys \fB^\fP or \fB=\fP): The sequence of characters entered must match the beginning of a word. .TP \fIsubstring\fP (keys \fB"\fP or \fB'\fP): The sequence of characters entered must match a substring in a word. .TP \fIfuzzy\fP (keys \fB~\fP or \fB*\fP): All the characters in the entered sequence must appear in the same order in a word, but need not be consecutive. The case is also ignored. Note that spaces and tabs at the beginning and end of words are ignored when searching for substrings or fuzzy strings. The cursor is placed, if possible, on the first matching word having the minimum number of gaps between the first and last matching character, see the difference between the actions of the \fBs\fP/\fBS\fP and \fBn\fP/\fBN\fP keys below. This method also tolerates intermediate symbols not appearing in the words which will be ignored. If this is the case, the attributes of the approximatively matching words are changed into an error versions of them to warn the user to this situation. The erroneous symbols will \fInot\fP be inserted in the search buffer. For example: if the word \fBabcdef\fP is present in the standard input, then entering \f(CBabxcdye\fP puts \fBabcdef\fP in the search buffer and the word is added to the list of matching words and displayed with an error attribute (in red by default). This special state will persist until all the symbols following the first erroneous one are deleted (using backspace) or if \fBESC\fP is pressed to cancel the search session and clear the search buffer. .PP During a search session, the cursor changes and each character entered is added in (or removed from) the search buffer. The display is refreshed after each change in this buffer. .PP A 10 seconds timeout (by default) automatically ends the current search session as if the \fBEnter\fP key had been pressed. This timeout is reset each time a new key is hit in search mode. This delay can be configured using the \fBsearch\fP entry in the \fBtimers\fP section of the configuration file as shown in the example in the configuration subsection. .PP The slash key (\fB/\fP) can also be used instead of any of these keys. By default it is is programmed to do a \fIfuzzy\fP search but this can be changed by using the command line option (\fB-/\fP|\fB-search_method\fP) or by tuning a configuration file, see below. .PP All the words matching the current search buffer are enhanced: The characters present in the current search buffer are highlighted in one way and the other characters in another way. Both of these highlighting methods are configurable. .PP If the user has entered the search sequence: \fBo\fP, \fBs\fP, then the matching word "words" will be displayed as \fBw\fP\fIo\fP\fBrd\fP\fIs\fP when the \fIfuzzy\fP algorithm is in use depending of the display attributes configured. .PP \fBENTER\fP and all cursor moves terminate the search session but do not clear the list of the matching words and the search buffer. .PP The user can then use the \fBn\fP/\fBs\fP/\fBSPACE\fP keys (forward) and the \fBN\fP/\fBS\fP keys (backward) to navigate in the list of matching words, In \fIfuzzy\fP search mode, the \fBs\fP/\fBS\fP keys attempt to move the cursor to the next/previous word whose matching part forms a substring of this word. If no such matches exist, \fBs\fP/\fBS\fP and \fBn\fP/\fBN\fP do the same things. To move the cursor to the next/previous fuzzy match, use the \fBn\fP/\fBN\fP/\fBSPACE\fP keys. \fBs\fP means next \fPs\fPubstring match in this context while \fBn\fP just means \fBn\fPext match. .PP If the user hits the \fBHOME\fP or \fBEND\fP key during a search session then the list of matching words is reduced to the words starting (respectively) ending with the current search pattern and the window is refreshed. For those who consider \fBHOME\fP and \fBEND\fP as non-intuitive, the \fBCTRL\ A\fP and \fBCTRL\ Z\fP keys are also available in search mode as an alternative. This behaviour is persistent until the user hit the \fBESC\fP or \fBENTER\fP key. For example, if the search pattern in substring mode is \f(CBsh\fP and the user hits \fBEND\fP, then only the words \fIending\fP with \f(CBsh\fP will be added in the searched word list and enhanced. Note that when a matching word is selected, its enhanced characters only show one of the multiple matching possibilities. When not in a search session \fBESC\fP can be also used to clear the list of matching words and to reset the search buffer. .PP In summary, here is the meaning of the special keys in search mode: .TS tab(@); lb s s l l c ^ ^ l l lw(6c) c . Keys which clear the list of matching words. Key@Meaning@Closes @@the @@search @@session _ Esc@Cancel search@Yes _ .T& lb s s l l l ^ ^ l l lw(6c) c . Keys which keep or update the list of matching words. Key@Meaning@Closes @@the @@search @@session _ \fB\(<-\fP@Previous word@Yes \fB\(ua\fP@Previous line@Yes \fBCTRL\ \(<-\fP@Start of line@Yes \fBPgUp\fP@Previous page@Yes \fBCTRL\ HOME\fP, \fBSHIFT\ HOME\fP, \fBCTRL\ K\fP@First word@Yes \fB\(->\fP@Next word@Yes \fB\(da\fP@Next line@Yes \fBCTRL\ \(->\fP@END of line@Yes \fBPgDn\fP@Next pages@Yes \fBCTRL\ END\fP, \fBSHIFT\ END\fP, \fBCTRL\ J\fP@Last word@Yes \fBHOME\fP, \fBCTRL\ A\fP@T{ Only keep the words starting with the search pattern T}@No \fBEND\fP, \fBCTRL\ Z\fP@T{ Only keep the words ending with the search pattern T}@No \fBINS\fP@Tag word@No \fBDEL\fP@Untag word@No _ .TE .PP Note that the search buffer is persistent as long as the same search algorithm is used and \fBESC\fP has not been pressed. .SS "Selection and Exit" Pressing \fBq\fP gives the possibility to exit without selecting anything. .PP \fBCTRL\ C\fP (Abort) also allows you to exit the program immediately with a return code equal to 128+SINGINT (by default) without selecting anything. See the \fB-!\fP|\fB-int\fP|\fB-int_string\fP option for more information about the customization of the \fBCTRL\ C\fP behaviour. .PP By default, \fBENTER\fP writes the selected word to stdout when not in search mode otherwise it exits from this mode and does nothing more. If you want to be able to select a word \fIeven\fP when in search mode, use the \fB-r\fP|\fB-auto_validate\fP option to change this behavior. .SS "Tagging (multiple selections)" When the tagging is activated by using the command line \fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP or \fB-P\fP|\fB-pm\fP|\fB-pin\fP|\fB-pin_mode\fP option, then the keys \fBt\fP, \fBT\fP, \fBINS\fP and \fBDEL\fP can be used to tag/untag some words. These tagged words will then be output on the standard output when \fBENTER\fP is pressed. .TP \fBt\fP Tag/untag or Pin/unpin the word under the cursor (toggle). .TP \fBT\fP Tag or pin the matching words if any. .TP \fBU\fP Untag or unpin the matching words if any. .TP \fBINS\fP Tag or pin the word under the cursor. .TP \fBDEL\fP Untag or unpin the word under the cursor. .SS Help A small help message can be displayed when hitting \fB?\fP. This display will last for 10s or until a valid key or \fBESC\fP is pressed. .SS Scroll bar A scroll bar is displayed at the right of the scrolling window. Its appearance is meant to be classical but it has some particularities: .IP * 2 The scroll bar is not displayed if all the input words fit on only one line. .IP * 2 Otherwise, the scroll bar is always displayed except when the \fB-q\fP option is set. This option completely disables the scroll bar display. .IP * 2 When the scrolling window has only one line, the scroll bar has only 3 states: .RS 2 .IP - 2 \fBv\fP when on all but the last line, indicating that you can go down to see more. .IP - 2 \fB^\fP when on the last line. .IP - 2 \fB|\fP otherwise. .RE .IP * 2 When there is more than one line to display, \fB/\fP means that the window displays the first line, \fB\\\fP the last line. \fB|\fP is used to fill the gap, see below the different possible configurations. .TS tab(@); l l l l l l l l l l l l l l . \\@\\@^@^@\\ @Do not remove this trailing space! |@|@|@|@/ /@v@/@v .TE .PP A \fB+\fP can also appear in the scroll bar in lieu of the vertical bar, giving the relative position of the cursor line in the bunch of input words. .SS "Terminal resizing (also see BUGS/LIMITATIONS)" The windows is redrawn if the terminal is resized. The redrawing is actually done only 1s after the end of the resizing to avoid artefacts on screen. The cursor will remain on the current selected word but may be displayed at another place in the window. .SS Unicode support This utility is Unicode aware and should be able to display correctly any Unicode character (even double-width ones) as long as the current encoding is \fBUTF-8\fP (\fBUTF-8\fP in the output of the \fIlocale\fP command). .SS Configuration If a file with adequate permissions and the same name as the executable but prefixed with a dot is present in the current directory or in the user's home directory, then it will be parsed as a \fIini\fP file. The values read from the file in the home directory will be overridden by the ones read from the local directory (if it is present). Missing and bad keywords are silently skipped. The values read, if valid, override the default hard-coded ones. If a value is invalid an error message is shown and the program terminates. The values of the timers must be given in units of \fB1/10\fP of a second. Here is an example giving the syntax and the names of the keywords allowed: .PP .nf \f(CR--8<------------------------------------------------------------------ [colors] ; The terminal must have at least 8 colors and/or have attributes like bold ; and reverse for this to be useful ; if not the following settings will be ignored. method=ansi ; classic | ansi (default) cursor=0/2 ; cursor attributes cursor_on_tag=0/2,u ; cursor on tag attributes shift=6,b ; shift symbol attributes message=0/3 ; message (title) attributes bar = 7/4,b ; scroll bar attributes search_field = 0/6 ; search field attributes search_text = 7,bu ; search text attributes match_field = 1,b ; matching words field attributes match_text = 7,bu ; matching words text attributes search_err_field = 1 ; approximate search field attributes search_err_text = 1,r ; approximate search text attributes ; match_err_field = 3 ; approximate matching words field attributes match_err_text = 1 ; approximate matching words text attributes ; include = b ; selectable color attributes exclude = 4/0,u ; non-selectable color attributes tag = 0/5 ; tagged (selected) attributes daccess = 3,b ; direct access tag attributes special1 = 7/4,b ; attributes for the special level 1 special2 = bu ; attributes for the special level 2 special3 = /3,b ; attributes for the special level 3 special4 = 7/4 ; attributes for the special level 4 special5 = 7/2,b ; attributes for the special level 5 [window] lines = 7 ; default number of lines of the window [limits] word_length = 1024 ; arbitrary max length of input words (int) words = 32767 ; arbitrary max number of allowed input ; words (int) columns = 128 ; arbitrary max number of columns (int) [timers] search = 100 ; search timeout in 1/10 s help = 150 ; duration of the help message in 1/10 s window = 7 ; delay before redrawing if the size of the ; terminal's window change in 1/10 s direct_access = 6 ; duration allowed to add a new digit to ; the direct word access number in 1/10 s [misc] default_search_method = substring --8<------------------------------------------------------------------ \fP .fi .IP * 2 The \fBmethod\fP keyword can take the two possible values displayed above and determines if you want to use the native method (limited to 8 colors) of the \fBansi\fP method (ISO 8613-6) if your terminal supports more than 8 colors. The default value corresponds to \fBansi\fP. The attributes syntax is [fg][/bg][,toggles] where \fBfg\fP and \fBbg\fP are numbers representing the foreground and background color and \fBtoggles\fP is a strings which can contain the characters \fIb\fP, \fId\fP, \fIr\fP, \fIs\fP, \fIu\fP and \fIi\fP standing for \fIb\fPold, \fId\fPim, \fIr\fPeverse, \fIs\fPtandout, \fIu\fPnderline and \fIi\fPtalic. .IP * 2 Spaces are allowed anywhere in the lines and between them, even around the \fB=\fP. .IP * 2 Everything following a \fB;\fP is ignored. .IP * 2 When undefined, the default limits are: .TS tab(@); l l . words@32767 word_length@512 columns@256 .TE .SH OPTIONS Not all options may be available, depending on the current context. When smenu is called and before the first option is evaluated, it is in the \fBMain\fP context. Each option can switch to another context in which only a subset of the options is usable. For each parameter described below, the contexts in which the associated option is defined as well as the context to which it leads, if any, are given. An option not defined in a context will force the end of the current context and will be recursively evaluated in the previous contexts until found (or not). If not found, an error message is displayed and smenu is terminated. The contexts defined in smenu are: .IP \fBMain\fP 2 The default context .IP \fBColumns\fP 2 After the \fB-c\fP|\fB-col\fP|\fB-col_mode\fP|\fB-column\fP parameter. .IP \fBLines\fP 2 After the \fB-l\fP|\fB-line\fP|\fB-line_mode\fP parameter. .IP \fBTabulations 2 After the \fB-t\fP|\fB-tab\fP|\fB-tab_mode\fP|\fB-tabulate_mode\fP parameter. .IP \fBTagging\fP 2 After the \fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP or \fB-P\fP|\fB-pm\fP|\fB-pin\fP|\fB-pin_mode\fP parameter. .PP .IP \fBWARNING\fP 2 Here is a situation that may seem confusing at first glance. Imagine the only parameter command line parameter is \fB-cols_select\fP. Since this is a parameter of an option which is not valid when not in the \fBColumns\fP context, it should have raised an error but it still seems to be accepted. The trick is: when not in column mode \fB-cols_select\fP is indeed not accepted but its prefix (\fB-col\fP) is valid. The options are thus understood as: \fB-col\fP \fB-s_select\fP. The same mechanism occurs again as \fB-s\fP is also valid in column mode so the final understanding of the command line is: \fB-col\fP \fB-s\fP \fB_select\fP. In such a case, the user can set the environment variable \fBCTXOPT_DEBUG\fP which any non-empty content. When run again the following output will appear on the standard error: .PP .nf CTXOPT_DEBUG: Parameter: -cols_select. Evaluation context: Main. CTXOPT_DEBUG: Found a valid parameter as a prefix of -cols_select: -col. CTXOPT_DEBUG: Parameter: -col. Evaluation context: Main. CTXOPT_DEBUG: Switch to context Columns. CTXOPT_DEBUG: Parameter: -s_select. Evaluation context: Columns. CTXOPT_DEBUG: Found a valid parameter as a prefix of -s_select: -s. CTXOPT_DEBUG: Parameter: -s. Evaluation context: Columns. CTXOPT_DEBUG: Argument: _select. .fi .PP The command line: \fB-col\fP \fB-cols_select\fP \fB1\fP solves the issue in this case and indicates that only the first column should be selectable. Note, however, that at least one argument for \fB-cols_select\fP is now required: .PP .nf CTXOPT_DEBUG: Parameter: -col. Evaluation context: Main. CTXOPT_DEBUG: Switch to context Columns. CTXOPT_DEBUG: Parameter: -cols_select. Evaluation context: Columns. CTXOPT_DEBUG: Argument: 1. .fi .PP The \fB-h\fP|\fB-help\fP and \fB-?\fP|\fB-u\fP|\fB-usage\fP options now display the help and synopsis of the available options in the current context. .IP Example: 2 \f(CBsmenu -col -u\fP will only show the usage in the \fBColumns\fP context .PP The contexts contain all the non-context-changing options so, in practice, the usage should be intuitive. You may nevertheless have to adjust some scripts using the old smenu releases as I did in the lvm_menu example. .PP Some of the advantages of this new system of options are: .IP * 2 Long parameter names are allowed One dash is enough, but two are also allowed for compatibility reasons. .IP * 2 An option can be referenced by any number of parameters with short or long names. .IP * 2 Auto checking of missing mandatory options, duplicated option,... .IP * 2 Only options usable in the current context are allowed. .PP This option management system is explained in more detail at https://github.com/p-gen/ctxopt. .PP The description of each command line parameter is as follows: .IP "\fB-h\fP|\fB-help\fP" (Allowed in all contexts.) Display a context specific help messages and exits. .IP "\fB-H\fP|\fB-long_help\fP" (Allowed in the "Main" context.) Display a long (non context specific) help messages and exits. .IP "\fB-?\fP|\fB-u\fP|\fB-usage\fP" (Allowed in all contexts.) Displays a short help message and exits. .IP "\fB-V\fP|\fB-version\fP" (Allowed in the "Main" context.) The \fB.smenu\fP files in the user's home directory and in the current directory, if present, will be ignored when this option is used. .IP "\fB-n\fP|\fB-lines\fP|\fB-height\fP [\fIheight\fP]" (Allowed in all contexts.) Gives the maximum number of lines in the scrolling selection window. If \fB-n\fP|\fB-lines\fP|\fB-height\fP is not present the number of lines will be set to \fI5\fP. If \fB-n\fP|\fB-lines\fP|\fB-height\fP is present without argument, then the height of the terminal will be used to determine the number of lines. This remains true even if the terminal is resized. If \fB-n\fP|\fB-lines\fP|\fB-height\fP is present with a numerical argument, this value will be used to determine the number of lines. .IP "\fB-i\fP|\fB-in\fP|\fB-inc\fP|\fB-incl\fP|\fB-include\fP... \fIregex\fP" (Allowed in all contexts.) Sets the \fBi\fPnclude filter to match the selectable words. All the other words will become implicitly non-selectable (excluded) \fB-i\fP|\fB-in\fP|\fB-inc\fP|\fB-incl\fP|\fB-include\fP can be used more than once with cumulative effect. \fI\\u\fP and \fI\\U\fP sequences can also be used in the regexp. .IP "\fB-e\fP|\fB-ex\fP|\fB-exc\fP|\fB-excl\fP|\fB-exclude\fP... \fIregex\fP" (Allowed in all contexts.) Sets the \fBe\fPxclude filter to match the non-selectable words. All the other selectable words will become implicitly selectable (included) \fB-e\fP|\fB-ex\fP|\fB-exc\fP|\fB-excl\fP|\fB-exclude\fP can be used more than once with cumulative effect. This filter has a higher priority than the include filter. The \fIregex\fP selections made using \fB-i\fP|\fB-in\fP|\fB-inc\fP|\fB-incl\fP|\fB-include\fP and/or \fB-e\fP|\fB-ex\fP|\fB-exc\fP|\fB-excl\fP|\fB-exclude\fP are done before the possible words alterations made by \fB-I\fP|\fB-si\fP|\fB-subst_included\fP or \fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP (see below). \fI\\u\fP and \fI\\U\fP sequences can also be used in the regexp. .IP "\fB-m\fP|\fB-msg\fP|\fB-message\fP|\fB-title\fP \fImessage\fP" (Allowed in all contexts.) Displays a message (title) above the window. If the current locale is not \fIUTF-8\fP, then all \fIUTF-8\fP characters will be replaced by the substitution character. \fI\\u\fP and \fI\\U\fP sequences can be used in the message. Note that the message will be truncated if it does not fit on a terminal line. .IP "\fB-!\fP|\fB-int\fP|\fB-int_string\fP [\fIstring\fP]" (Allowed in all contexts.) The optional \fIstring\fP argument, when present, defines the string to be used as the selection string when the \fBCTRL\ C\fP sequence is entered. If \fIstring\fP is missing then nothing will be selected. In all cases, when \fB-!\fP|\fB-int\fP|\fB-int_string\fP is present in the command line, the return code of the program will be \fB0\fP. This gives the user the choice to make the behaviour of \fBCTRL\ C\fP similar to that of \fBq\fP and \fBQ\fP or to that of the Unix shell leaving the shell with a return code greater than 128. .IP "\fB-a\fP|\fB-attr\fP|\fB-attributes\fP \fIprefix:attr\fP..." (Allowed in all contexts.) Sets the display attributes of the elements displayed and the cursor. At least one attribute prefixed attribute must be given. \fIprefix\fP can take the following values: .RS .IP \fIi\fP included words. .IP \fIe\fP excluded words. .IP \fIc\fP cursor. .IP \fIb\fP scroll bar. .IP \fIs\fP shift indicator. .IP \fIm\fP message (title). .IP \fIt\fP tagged words. .IP \fIct\fP cursor on tagged words. .IP \fIsf\fP search field. .IP \fIst\fP search text. .IP \fIsfe\fP approximate search field with error. .IP \fIste\fP approximate search text with error. .IP \fImf\fP matching words field. .IP \fImt\fP matching words text. .IP \fImfe\fP matching words field with error. .IP \fImte\fP matching words text with error. .IP \fIda\fP direct access tag. .RE .IP If more than one attribute is given, they must be separated by spaces. Example: \f(CB-attr i:/5 e:4,br b:7/3,rb c:7/2,b\fP See the the \fB-1\fP|\fB-l1\fP|\fB-level1\fP option below for the description of the attributes syntax after the colon and an example. .IP "\fB-1\fP|\fB-l1\fP|\fB-level1\fP \fIregex\fP [\fIattr\fP]" .IP "\fB-2\fP|\fB-l2\fP|\fB-level2\fP \fIregex\fP [\fIattr\fP]" .IP "\fB-3\fP|\fB-l3\fP|\fB-level3\fP \fIregex\fP [\fIattr\fP]" .IP "\fB-4\fP|\fB-l4\fP|\fB-level4\fP \fIregex\fP [\fIattr\fP]" .IP "\fB-5\fP|\fB-l5\fP|\fB-level5\fP \fIregex\fP [\fIattr\fP]" (Allowed in all contexts.) Allows one to give a special display color to up to 5 classes of words specified by regular expressions. They are called \fBspecial levels\fP. Only selectable words will be considered. By default, the 5 special levels have their foreground color set to red, green, brown/yellow, purple and cyan. All these colors also can be set or modified permanently in the configuration files. See the example file above for an example. The optional second argument (\fIattr\fP) can be used to override the default or configured attributes of each class. Its syntax is the same as the one used in the configuration file: .nf [\fIfg\fP][/\fIbg\fP][,{\fIb\fP|\fId\fP|\fIr\fP|\fIs\fP|\fIu\fP|\fIi\fP}] \ | [{\fIb\fP|\fId\fP|\fIr\fP|\fIs\fP|\fIu\fP|\fIi\fP}] .fi Examples of possible attributes are: .nf \f(CB2/0,bu \fPgreen on black bold underline \f(CB/2 \fPgreen background \f(CB5 \fPtext in purple \f(CBrb \fPreverse bold .fi \fI\\u\fP and \fI\\U\fP sequences can be used in the pattern. .IP "\fB-z\fP|\fB-zap\fP|\fB-zap_glyphs\fP \fIbytes\fP" (Allowed in all contexts.) Initializes a set of UTF-8 characters to be ignored when reading words from stdin or a file. Example: The argument \f(CR'\\u0d\\ue282ac,'\fP means: ignore all commas, Euro signs and carriage return characters when reading from stdin or a file. As shown above \fI\\u\fP and \fI\\U\fP sequences can be used in the bytes set. .IP "\fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP [\fIdelim\fP]" (Allowed in the following contexts: "Main", "Columns", "Lines", and "Tabulations", switches to the "Tagging" context.) Enables multiple selections or tag mode. In this mode, several selectable words can be selected without leaving the program. The current word can be automatically tagged when the \fBENTER\fP key is pressed to complete the selection process if the \fB-p\fP|\fB-at\fP|\fB-auto_tag\fP option is also set or if no word has been tagged. All the tagged words (and possibly the world under the cursor) will be sent to stdout separated by the optional argument given after the option \fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP. Note than this \fIseparator\fP can have more than one character, contain UTF-8 characters (in native or \fI\\u\fP or \fI\\U\fP form) and can even contain control character as in \f(CB$'\\n'\fP. A space is used as the default separator if none is given. \fBCaution\fP: To get exactly the same behavior as in version 0.9.11 and earlier, you must also use the \fB-p\fP|\fB-at\fP|\fB-auto_tag\fP option. .IP "\fB-P\fP|\fB-pm\fP|\fB-pin\fP|\fB-pin_mode\fP [\fIdelim\fP]" (Allowed in the following contexts: "Main", "Columns", "Lines", and "Tabulations", switches to the "Tagging" context.) Works like \fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP but, unlike \fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP, the output depends on the order in which the words were tagged. In other words, the first tagged word comes first in the output, the second tagged word comes next, and so on. .IP "\fB-p\fP|\fB-at\fP|\fB-auto_tag\fP" (Allowed in the "Tagging" context.) This option modifies the default behavior of the \fB-T\fP|\fB-tm\fP|\fB-tag\fP|\fB-tag_mode\fP and \fB-P\fP|\fB-pm\fP|\fB-pin\fP|\fB-pin_mode\fP options. An untagged word under the cursor will be automatically tagged when \fBENTER\fP is pressed. .IP "\fB-N\fP|\fB-number\fP>da_ctx... [\fIregex\fP]" (Allowed in the following contexts: "Main", "Columns", "Lines" and "Tabulation".) This option allows you to number selectable words that match a specific regular expression. These numbers are numbered from 1 and allow direct access to the words. To use this functionality, the user must enter the number which corresponds to the desired entry digit per digit. Each new digit must be added in a time frame of 1/2 seconds (per default) otherwise the number is considered complete and a newly entered digit will start a new number. If the number does not exists, then the cursor is restored to it's initial position. The sub-options of the \fB-D\fP|\fB-data\fP|\fB-options\fP option described below can change the way \fB-N\fP|\fB-number\fP sets and formats the numbers. This option accepts more than one argument and can be used multiple times with cumulative effects. \fB-N\fP|\fB-number\fP, \fB-U\fP|\fB-unnumber\fP and \fB-F\fP|\fB-en\fP|\fB-embedded_number\fP can be mixed. .IP "\fB-U\fP|\fB-unnumber\fP>da_ctx... [\fIregex\fP]" (Allowed in the following contexts: "Main", "Columns", "Lines" and "Tabulation".) This option allows one to unnumber words. If placed after a previous \fB-N\fP|\fB-number\fP, it can be used to remove the numbering of selected words. If placed before, the word which doesn't match its regular expression will be numbered by default. This mechanism is similar to to the inclusion/exclusion of words by \fB-i\fP|\fB-in\fP|\fB-inc\fP|\fB-incl\fP|\fB-include\fP and \fB-e\fP|\fB-ex\fP|\fB-exc\fP|\fB-excl\fP|\fB-exclude\fP. This option accepts more than one argument and can be used multiple times with cumulative effects. \fB-U\fP|\fB-unnumber\fP, \fB-N\fP|\fB-number\fP and \fB-F\fP|\fB-en\fP|\fB-embedded_number\fP can be mixed. .IP "\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP" (Allowed in the following contexts: "Main", "Columns", "Lines" and "Tabulation".) This option is similar to \fB-N\fP|\fB-number\fP but does not generate a continuous flow of numbers but extracts them from the word itself. With this option you can take full control of the numbering of the displayed word. Note that the numbering does not need to be ordered. The resulting word after the extraction of the number must be non empty. Some sub-option are required, see the \fB-D\fP|\fB-data\fP|\fB-options\fP option described below. \fBNotice\fP that for this option to work correctly, all the embedded numbers must have the same number of digits. To get that, a preprocessing may be necessary on the words before using this program. \fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP can be mixed. .IP "\fB-D\fP|\fB-data\fP|\fB-options\fP [\fIparameter\fP...]" (Allowed in the Following contexts: "Main", "Columns", "Lines" and "Tabulations".) This option allows one to change the default behaviour of the \fB-N\fP|\fB-number\fP, \fB-U\fP|\fB-unnumber\fP and \fB-F\fP|\fB-en\fP|\fB-embedded_number\fP options. Its optional parameters are called sub-options and must respect the format \fBx\fP:\fBy\fP where \fBx\fP can be: .RS .TP \f(CBl\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is the UTF-8 character (in native or \fI\\u\fP or \fI\\U\fP form) to print before the number. The default is a single space. . .TP \f(CBr\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is the UTF-8 character (in native or \fI\\u\fP or \fI\\U\fP form) to print after the number. The default is \f(CB)\fP. . .TP \f(CBa\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is '\f(CBleft\fP' (or one of its prefixes) if the number must be \fIleft\fP aligned, or '\f(CBright\fP' (or one of its prefixes) if it must be \fIright\fP aligned. The default is \f(CBright\fP. . .TP \f(CBp\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is '\f(CBincluded\fP' or '\f(CBall\fP' for the initial \fIp\fPadding of the non numbered words. The keyword '\f(CBincluded\fP' means that only \fIincluded\fP word will be padded while '\f(CBall\fP' means pad \fIall\fP words. The default is \f(CBall\fP. These keywords can be abbreviated. . .TP \f(CBw\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is the \fIw\fPidth of the number between 1 and 5 included. . .TP \f(CBf\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP controls if the numbering must \fIf\fPollow the last extracted number (defaults to \f(CByes\fP) or if it must remain independent. The possible values are \f(CByes\fP and \f(CBno\fP but can be abbreviated. . .TP \f(CBm\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP option) Here \fBy\fP controls if the numbering of word with missing embedded numbers must be done or not (defaults to \f(CByes\fP). When this sub-option is set to \f(CBno\fP, the \f(CBs\fP and \f(CBf\fP sub-options are ignored. The possible values are \f(CByes\fP and \f(CBno\fP but can be abbreviated. . .TP \f(CBh\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP option) Tells what to do with the characters present before the embedded number if any. The allowed directives are: '\f(CBtrim\fP' which discads them if they form an empty word (only made of spaces and tabulations), '\f(CBcut\fP' which unconditionally discards them and '\f(CBkeep\fP' which places them at the beginning of the resulting word. The default value for this directive is '\f(CBkeep\fP', these keywords can be abbeviated. . .TP \f(CBo\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP option) Here \fBy\fP is the \fIo\fPffset of the first multibyte character of the number to extract from the word (defaults to \f(CB0\fP). If this offset if immediately followed by the character '\f(CB+\fP', then the parser will look for the first number (if any) after the given offset instead of using its absolute value to extract the number. Note that when the '\f(CB+\fP' is used, it is necessary that the length of all the numbers to extract have the same size as the algorithm looks for a digit to identify the beginning of the number to extract. Hence, for example, \fB1\fP should appear as \fB01\fP in the input is \f(CBn\fP is set to \f(CB2\fP. . .TP \f(CBn\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP option) Here \fBy\fP is the \fIn\fPumber of multibyte characters to extract from the word starting at the offset given by the \f(CBo\fP sub-option. Example: \f(CRn:2\fP will extract and use the first 2 digits of each words from the input stream to number them. .TP \f(CBi\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP option) Here \fBy\fP is number of multibyte characters to \fIi\fPgnore after the extracted number . .TP \f(CBd\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is a multibyte separator. When present, this directive instructs smenu to output the selected numbered word(s) \fIprefixed\fP by its(their) direct access number(s) and the given separator. Only the numbered word(s) will be prefixed. \f(CBd\fP stands for \fBd\fPecorate. This directive can be useful when you want to post-process the output according to its direct access number. . .TP \f(CBs\fP (\fB-F\fP|\fB-en\fP|\fB-embedded_number\fP, \ \fB-N\fP|\fB-number\fP and \fB-U\fP|\fB-unnumber\fP options) Here \fBy\fP is the direct access number that will be set for the first numbered word. Its value is \fB1\fP by default, a value of \fB0\fP is possible. .P Example: \f(CR-data r:\\> l:\\< a:l d:_ \fP To number all words with the default parameters, use the syntax: "\f(CR-N .\fP" which is a shortcut for: "\f(CR-N . -D l:' ' r:')' a:r p:a\fP" The \fIpadding\fP sub-option specifies whether spaces must also be added in front of excluded words or not to improve compactness. When the \f(CBw\fP sub-option is not given the width of the numbers is determined automatically but if \fB-F\fP|\fB-en\fP|\fB-embedded_number\fP is set and the value of the \f(CBn\fP sub-option is given then this value is used. .RE .IP "\fB-b\fP|\fB-blank\fP" (Allowed in all contexts.) Replaces all non-printable characters by a blank. If this results in a blank word, it will be potentially deleted. .IP "\fB-.\fP|\fB-dot\fP|\fB-invalid\fP" (Allowed in all contexts.) Sets the substitution character for non-printable characters. When this parameter is not used, the default substitution character is a single dot. .IP "\fB-M\fP|\fB-middle\fP|\fB-center\fP" (Allowed in all contexts.) Centers the display if possible. .IP "\fB-d\fP|\fB-restore\fP|\fB-delete\fP|\fB-clean\fP|\fB-delete_window\fP|\ \fB-clean_window\fP" (Allowed in all contexts.) Tells the program to clean up the display before quitting by removing the selection window after use as if it was never displayed. .IP "\fB-c\fP|\fB-col\fP|\fB-col_mode\fP|\fB-column\fP" (Allowed in the "Main" and "Tagging" contexts, switches to the "Columns" context.) Sets the column mode. In this mode the lines of words do not wrap when the right border of the terminal is reached but only when a special character is read. Some words will not be displayed without an horizontal scrolling. If such a scrolling is needed, some indications may appear on the left and right edge of the window to help the user to reach the unseen words. In this mode, the width of each column is minimal to keep the maximum information visible on the terminal. .IP "\fB-l\fP|\fB-line\fP|\fB-line_mode\fP" (Allowed in the "Main" and "Tagging" contexts, switches to the "Lines" context.) Sets the line mode. This mode is the same as column mode but without any column alignment. .IP "\fB-t\fP|\fB-tab\fP|\fB-tab_mode\fP|\fB-tabulate_mode\fP [\fIcols\fP]" (Allowed in the "Main" and "Tagging" contexts, switches to the "Tabulations" context.) This option sets the tabulation mode and, if a number is specified, attempts to set the number of displayed columns to that number. In this mode, embedded line separators are ignored if not explicitly set with \fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\fB-line_separators\fP. The options \fB-A\fP|\fB-fc\fP|\fB-first_column\fP and \fB-Z\fP|\fB-lc\fP|\fB-last_column\fP can nevertheless be used to force words to appear in the first (respectively last) position of the displayed line. .PP .RS Note that the number of requested columns will be automatically reduced if a word does not fit in the calculated column size. .PP In this mode each column has the same width. .RE .IP "\fB-w\fP|\fB-wide\fP|\fB-wide_mode\fP" (Allowed in the "Columns" and "Tabulations" contexts.) When \fB-t\fP|\fB-tab\fP|\fB-tab_mode\fP|\fB-tabulate_mode\fP is followed by a number of columns, the default is to compact the columns so that they use the less terminal width as possible. This option enlarges the columns in order to use the whole terminal width. When in column mode, \fB-w\fP|\fB-wide\fP|\fB-wide_mode\fP can be used to force all the columns to have the same size (the largest one). See option \fB-c\fP|\fB-col\fP|\fB-col_mode\fP|\fB-column\fP below. .PP .RS Note that the column's size is only calculated once when the words are displayed for the first time. A terminal resize will not update this value. This choice enables a faster display. .RE .PP .IP "\fB-C\fP|\fB-cs\fP|\fB-cols\fP|\fB-cols_select\fP... \ [\fIi\fP|\fIe\fP]\fIselectors\fP..." (Allowed in the "Columns" context.) \fII\fP and \fIE\fP have the same meaning as \fIi\fP and \fIe\fP. In column mode, this option is useful to restrict the selections to a subset of all columns. Either by including (nothing or \fIi\fP) or by excluding (\fIe\fP) them. Columns can be designated by their number (1 based) or by a regular expression enclosed in delimiter made from any non-blank ASCII character excluding the comma. Range of columns (number or RE) can be given by separated then with a dash. Multiple selectors can be regrouped in one argument using commas to separate them. This option also accepts multiple arguments, each of them being a selector. A selection by regular expressions means that a column containing a word matching any of these expressions will be included or excluded depending on the letter given after the option or before the selector if there is more than one argument. Regular expressions and column numbers can be freely mixed. Regular expression in \fB-C\fP|\fB-cs\fP|\fB-cols\fP|\fB-cols_select\fP and \fB-R\fP|\fB-rs\fP|\fB-rows\fP|\fB-rows_select\fP can contain \fIUTF-8\fP characters either directly or by using the \fI\\u\fP or \fI\\U\fP notation. Example of columns selection: \f(CB-Ci2,3,/X./,5-7\fP forces the cursor to only navigate in columns \fB2\fP,\fB3\fP,\fB5\fP,\fB6\fP and \fB7\fP and those containing a two characters word starting with '\fBX\fP'. If \fIe\fP was used in place of \fIi\fP, all the columns would have been selected \fBexcept\fP the columns \fB2\fP,\fB3\fP,\fB5\fP,\fB6\fP,\fB7\fP and those matching the extended regular expression '\f(CBX.\fP'. Spaces are allowed in the selection string if they are protected. Other example where multiple selectors are used as multiple arguments: \f(CBps | smenu -col -cols e/TTY/ e/CMD/ e3\fP .PP .IP "\fB-R\fP|\fB-rs\fP|\fB-rows\fP|\fB-rows_select\fP... \fIselectors\fP..." (Allowed in the "Columns" and "Lines" contexts.) Similar to \fB-C\fP|\fB-cs\fP|\fB-cols\fP|\fB-cols_select\fP but for the rows. \fB-C\fP|\fB-cs\fP|\fB-cols\fP|\fB-cols_select\fP and \fB-R\fP|\fB-rs\fP|\fB-rows\fP|\fB-rows_select\fP can be used more than once in a cumulative manner: The selection mode (selection or de-selection) is given by the first occurrence of the options, the other occurrences will only update the selected or de-selected ranges. Once a column or a row has been excluded, it cannot be re-included. .IP "\fB-A\fP|\fB-fc\fP|\fB-first_column\fP \fIregex\fP" (Allowed in the following contexts: "Columns", "Lines" and "Tabulations".) In column mode, forces all words matching the given regular expression to be the first one in the displayed line. If you want to only rely on this method to build the lines, just specify an empty \fBregex\fP to set the end-of-line separator with \fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\fB-line_separators\fP '') .PP .RS \fI\\u\fP and \fI\\U\fP sequences can also be used in the regexp after \fB-A\fP|\fB-fc\fP|\fB-first_column\fP. .RE .IP "\fB-Z\fP|\fB-lc\fP|\fB-last_column\fP \fIregex\fP" (Allowed in the following contexts: "Columns", "Lines" and "Tabulations".) Similar to \fB-A\fP|\fB-fc\fP|\fB-first_column\fP but forces the word to be the latest of its line. The same trick with \fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\fB-line_separators\fP can also be used. .PP .RS \fI\\u\fP and \fI\\U\fP sequences can also be used in the regexp after \fB-Z\fP|\fB-lc\fP|\fB-last_column\fP. .RE .IP "\fB-g\fP|\fB-gutter\fP [\fIstring\fP]" (Allowed in the "Columns" and "Tabulations" contexts.) Replaces the blank after each words in column or tabular mode by a column separator. This separator is extracted from the \fIstring\fP argument and each of its (multibyte) character is used one after the other to fill the gutter. If there are more columns that gutter characters then the last character is used for the remaining columns. When not given, the separator defaults to a vertical bar \fI|\fP (or a full height vertical bar if the locale is set to UTF-8). Each character can be given in normal or \fI\\u\fP or \fI\\U\fP form in the \fIstring\fP argument. Example: "\f(CB|- \fP" will allow one to separate the first two columns with '\f(CB|\fP', then '\f(CB-\fP' will be used and '\f(CB \fP' will separate the remaining columns if any. .IP "\fB-k\fP|\fB-ks\fP|\fB-keep_spaces\fP" (Allowed in all contexts.) By default, the spaces surrounding the output string will be deleted. This option forces them to be retained. .IP "\fB-W\fP|\fB-ws\fP|\fB-wd\fP|\fB-word_delimiters\fP|\ \fB-word_separators\fP \fIbytes\fP" (Allowed in all contexts.) This option can be used to specify the characters (or multibyte sequences) which will be used to delimit the input words. Multibyte sequences (UTF-8) can be natives of using the same ASCII representation used in words (a leading \fI\\u\fP or \fI\\U\fP following by up to 8 hexadecimal characters for the former and 6 hexadecimal characters for the latter). Non-printable characters in arguments should be given using the standard \fI$''\fP representation. \fI$'\\t'\fP stands for the tabulation character for example. The default delimiters are: \fISPACE\fP, \fI$'\\t'\fP and \fI$'\\n'\fP. .IP "\fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\ \fB-line_separators\fP \fIbytes\fP" (Allowed in all contexts.) This option can be used to specify the characters (or multibyte sequences) which will be used to delimit the lines in the input stream. Multibyte sequences (UTF-8) can be natives of using the same ASCII representation used in words (a leading \fI\\u\fP or \fI\\U\fP following by up to 8 hexadecimal characters for the former and 6 hexadecimal characters for the latter). Non-printable characters in arguments should be given using the standard $'' representation. $'\\n' stands for the newline character for example. The default delimiter is: \fI$'\\n'\fP. This option is only useful when the \fB-c\fP|\fB-col\fP|\fB-col_mode\fP|\fB-column\fP or \fB-l\fP option is also set. The characters (or multibyte sequences) passed to \fB-L\fP|\fB-ls\fP|\fB-ld\fP|\fB-line-delimiters\fP|\fB-line_separators\fP are automatically added to the list of word delimiters as if \fB-W\fP|\fB-ws\fP|\fB-wd\fP|\fB-word_delimiters\fP|\fB-word_separators\fP was also used. \fI\\u\fP and \fI\\U\fP sequences can also be used here. .TP .IP "\fB-q\fP|\fB-no_bar\fP|\fB-no-scroll_bar\fP" (Allowed in all contexts.) Prevents the display of the scroll bar. .IP "\fB-S\fP|\fB-subst\fP... \ /\fIregex\fP/\fIrepl\fP/[\fIg\fP][\fIv\fP][\fIs\fP]" (Allowed in all contexts.) Post-processes the words by applying a regular expression based substitution. The argument must be formatted as in the \fBsed\fP editor. This option can be used more than once. Each substitution will be applied in sequence on each word. This sequence can be stopped if a \fBstop\fP flag is encountered. .RS \fBflags:\fP .IP * 2 The optional trailing \fBg\fP (for \fIg\fPlobal) means that all matching occurrences shall be replaced and not only the first one. .IP * 2 The optional trailing \fBv\fP (for \fIv\fPisual) means that the altered words will only be used for display and search. The modifications will \fInot\fP be reflected in the returned word. .IP * 2 The optional trailing \fBs\fP (for \fIs\fPtop) means that no more substitution will be allowed on this word even if another \fB-S\fP|\fB-subst\fP is used. .IP * 2 The optional trailing \fBi\fP (for \fIi\fPgnore case) means that the string search operation should ignore the case for this pattern. Small example: \f(CBR=$(echo a b c | smenu -S /b/B/)\fP will display \f(CR"a B c"\fP and \f(CBR\fP will contain \fIB\fP if \fI B\fP is selected meanwhile \f(CBR=$(echo a b c | smenu -S /b/B/\fBv\fP)\fR will display the same as above but \f(CBR\fP will contain the original word \fIb\fP if \fIB\fP is selected. In both cases, only the word \fIB\fP will be searchable and not \fIb\fP. .RE .IP "\fB-I\fP|\fB-si\fP|\fB-subst_included\fP... \ /\fIregex\fP/\fIrepl\fP/[\fIg\fP][\fIv\fP][\fIs\fP]" (Allowed in all contexts.) Post-processes the \fBselectable\fP words by applying a regular expression based substitution (see \fB-S\fP|\fB-subst\fP for details). .IP "\fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP... \ /\fIregex\fP/\fIrepl\fP/[\fIg\fP][\fIv\fP][\fIs\fP]" (Allowed in all contexts.) Post-processes the \fBexcluded\fP (or \fBnon-selectable\fP) words by applying a regular expression based substitution (see \fB-S\fP|\fB-subst\fP for details). .PP .RS The \fB/\fP separator that \fB-I\fP|\fB-si\fP|\fB-subst_included\fP and \fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP are using above can be substituted by any other character except \fISPACE\fP, \fI\\t\fP, \fI\\f\fP, \fI\\n\fP, \fI\\r\fP and \fI\\v\fP. .PP In the three previous options, \fIregex\fP is a \fBPOSIX\fP \fBE\fPxtended \fBR\fPegular \fBE\fPxpression. For details, please refer to the \fBregex\fP manual page. .PP Additionally \fI\\u\fP and \fI\\U\fP sequences can also be used in the regexp. .PP .RE If a post-processing action (\fB-S\fP|\fB-subst\fP, \fB-I\fP|\fB-si\fP|\fB-subst_included\fP, \ \fB-E\fP|\fB-se\fP|\fB-subst_excluded\fP) results in an empty (length 0) word, then we have two cases: .RS .IP "in column mode:" Substitutions involving empty words can lead to misalignments, so it is necessary to prohibit them and terminate the program. These substitutions have to be made with other tools before using this utility. .IP "otherwise:" The word is simply removed. .RE .IP "\fB-/\fP|\fB-search_method\fP \fIsearch_method\fP" (Allowed in all contexts.) Affects the '\fB/\fP' key to a search method. By default '\fB/\fP' is affected to '\fIfuzzy\fP' but the argument can be any prefix of '\fIprefix\fP', '\fIsubstring\fP' or '\fIfuzzy\fP'. .IP "\fB-s\fP|\fB-sp\fP|\fB-start\fP|\fB-start_pattern\fP \fIpattern\fP" (Allowed in all contexts.) Place the cursor on the first word corresponding to the specified pattern. \fIpattern\fP can be: .RS .IP * 2 A \fB#\fP immediately followed by a \fBnumber\fP giving the initial position of the cursor (counting from 0). If the word at this position is excluded, then the first previous non excluded word is selected if it exists, otherwise the first non excluded word is selected. If this number if greater than the number of words, the cursor will be set on the latest selectable position. .IP * 2 A single \fB#\fP or the string \fB#last\fP to set the initial cursor position to the latest selectable word position. .IP * 2 A string starting with a \fB/\fP indicating that we want the cursor to be set to the first word matching the given regular expression. .IP * 2 A \fBprefix\fP string indicating that we want the cursor to be set on the first word matching the string given (\fBa\fP will match \fBCancel\fP by example). .PP Warning, when searching for a prefix or a regular expression, smenu only looks for them after an eventual modification, so for example, the command: \f(CBsmenu -I/c/x/ -s/c <<< "a b c d"\fP won't find c and put the cursor on \fBa\fP but \f(CBsmenu -I/c/x/v -s/c <<< "a b c d"\fP will find it and put the cursor on the \fBx\fP substituting the \fBc\fP on screen only \fI\\u\fP and \fI\\U\fP sequences can be used in the pattern. .RE .IP "\fB-x\fP|\fB-tmout\fP|\fB-timeout\fP \fItype\fP [\fIword\fP] \fIdelay\fP" .IP "\fB-X\fP|\fB-htmout\fP|\fB-hidden_timeout\fP \fItype\fP [\fIword\fP]\ \fIdelay\fP" (Allowed in all contexts.) Sets a timeout. Three types of timeout are possible: .RS .TP 10 current: At the timeout, the word under the cursor and/or the tagged words are sent to the standard output if the \fBENTER\fP key has been pressed .TP 10 quit: At the timeout, nothing is selected as if the \fBq\fP key has been pressed .TP 10 word: At the timeout, the word given after the type is selected. Note that this word doesn't need to be part of the words coming from the standard input. .PP Each type can be be shortened as a prefix of its full name ("cur" for "current" of "q" for "quit" per example). The delay must be set in seconds and cannot be above 99999 seconds. The remaining time (in seconds) is added at the end of the message displayed above the selection window and is updated in real time each second. Any key except \fBENTER\fP, \fBq\fP, \fBQ\fP and \fBCTRL\ C\fP resets the timer to its initial value. The \fB-X\fP|\fB-htmout\fP|\fB-hidden_timeout\fP version works like \fB-x\fP|\fB-tmout\fP|\fB-timeout\fP but no periodic remaining messages is displayed above the selection window. .RE .IP "\fB-r\fP|\fB-auto_validate\fP" (Allowed in all contexts.) Enables \fBENTER\fP to validate the selection even in search mode. .IP "\fB-v\fP|\fB-vb\fP|\fB-visual_bell\fP" (Allowed in all contexts.) By default, when searching, an alarm is produced by the terminal when the user enters a character or makes a move which lead to no result or to an error condition. This argument make this beep visual by briefly showing the cursor. .IP "\fB-Q\fP|\fB-ignore_quotes\fP" (Allowed in all contexts.) Using this option will remove the word grouping feature from single and double quotes which will be considered normal characters. For example: \f(CB"a b"\fP will be considered by smenu as two words \fB"a\fP and \fBb"\fP and no more as a single word: \fBa b\fP. .SH NOTES If tabulators (\fI\\t\fP) are embedded in the input, there is no way to replace them with the original number of spaces. In this case use another filter (like \fIexpand\fR) to pre-process the data. .SH EXAMPLES .SS 1 Simple Yes/No/Cancel request with "No" as default choice: .PP .nf \f(CRIn \fBbash\fP: \f(CBread R <<< $(echo "Yes No Cancel" \\ | smenu -d -m "Please choose:" -s /N)\fP or \f(CBR=$(echo "Yes No Cancel" \\ | smenu -d -m "Please choose:" -s /N)\fP In \fBksh\fP: \f(CBprint "Yes No Cancel" \\ | smenu -d -m "Please choose:" -s /N \\ | read R\fP \fP .fi .SS 2 Get a 3 columns report about VM statistics for the current process in \fBbash\fP/\fBksh\fP on Linux: .PP .nf \f(CBR=$(grep Vm /proc/$$/status | expand | smenu -b -W$'\\n' -t3 -g -d)\fB .PP \fP .fi .SS 3 Create a one column selection window containing the list of the first 20 LVM physical volumes. At the end, the selection window will be erased. This example is written in \fBksh\fP). .PP .nf \f(CB pvs -a -o pv_name --noheadings \\ | smenu -m "PV list" -n20 -t1 -d -s //dev/root \\ | read R \fP .fi The display will have a look similar to the following with the cursor set on the word \fI/dev/root\fP: .nf \f(CRPV list /dev/md126 \\ /dev/md127 | /dev/root | <- cursor here. /dev/sda2 | /dev/sdb2 | /dev/sdc1 | /dev/sdc2 | /dev/system/homevol / \fP .fi .SS "4 (advanced)" Imagine a file named \fBsample.mnu\fP with the following content: .nf \f(CR--8<--------------------------------- "1 First Entry" "3 Third entry" "2 Second entry" "4 Fourth entry" @@@ "5 Fifth entry" @@@ "0 Exit menu" --8<--------------------------------- \fP .fi Then this quite esoteric command will render it (centered on the screen) as: .nf \f(CR+----------------------------------+ | Test menu | | | | 1) First Entry 3) Third entry | | 2) Second entry 4) Fourth entry | | 5) Fifth entry | | | | 0) Exit menu | +----------------------------------+ \fP .fi with the cursor on \fIQuit\fP and only the numbers and "Quit" selectable. \f(CBR=$(smenu -q -d -s/Exit -M -n 30 -c \\ -e "@+" -E '/@+/ /' \\ -F -D n:1 i:1 \\ -m "Test menu" < sample.mnu) The selected entry will be available in \f(CBR\fP Try to understand it as an exercise. .SH ENVIRONMENT .TS tab(@); l l. \fINO_COLOR\fP@force a monochrome terminal when set. \fICTXOPT_DEBUG\fP@put the option parser in debug mode. .TE .SH BUGS/LIMITATIONS Some terminal emulators, those notably based on VTE version later than 0.35 (see https://github.com/GNOME/vte/commit/01380d), have a new feature that gives them the possibility to wrap/unwrap already displayed lines when resizing the window. As far as I known, there is no terminfo entry to disable that. On these types of terminals, the automatic re-display of the output of smenu will be disturbed and some artifacts may appear on the screen if the terminal window is resized. .SH AUTHORS \(co 2015-present, Pierre Gentile (p.gen.progs@gmail.com) smenu-0.9.17/smenu.c000066400000000000000000013203231400523266500142410ustar00rootroot00000000000000/* ################################################################### */ /* Copyright 2015-present, Pierre Gentile (p.gen.progs@gmail.com) */ /* */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* */ /* you can redistribute it and/or modify it under the terms of the GNU */ /* General Public License as published by the Free Software */ /* Foundation; either version 2 of the License. */ /* */ /* This software is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* General Public License for more details. */ /* ################################################################### */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #if (defined(__sun) && defined(__SVR4)) || defined(_AIX) #include #endif #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "list.h" #include "index.h" #include "utf8.h" #include "fgetc.h" #include "utils.h" #include "ctxopt.h" #include "usage.h" #include "smenu.h" /* ***************** */ /* Extern variables. */ /* ***************** */ extern ll_t * tst_search_list; /* ***************** */ /* Global variables. */ /* ***************** */ word_t * word_a; /* array containing words data (size: count). */ long count = 0; /* number of words read from stdin. */ long current; /* index the current selection under the cursor). */ long new_current; /* final cur. position, (used in search function). */ long prev_current; /* prev. position stored when using direct access. */ long * line_nb_of_word_a; /* array containing the line number (from 0) * * of each word read. */ long * first_word_in_line_a; /* array containing the index of the first * * word of each lines. */ search_mode_t search_mode = NONE; search_mode_t old_search_mode = NONE; int help_mode = 0; /* 1 if help is displayed else 0. */ char * word_buffer; int (*my_isprint)(int); /* UTF-8 useful symbols. */ /* """"""""""""""""""""" */ char * left_arrow = "\xe2\x86\x90"; char * up_arrow = "\xe2\x86\x91"; char * right_arrow = "\xe2\x86\x92"; char * down_arrow = "\xe2\x86\x93"; char * vertical_bar = "\xe2\x94\x82"; /* box drawings light vertical */ char * shift_left_sym = "\xe2\x97\x80"; /* leftwards_arrow */ char * shift_right_sym = "\xe2\x96\xb6"; /* rightwards_arrow */ char * sbar_line = "\xe2\x94\x82"; /* box_drawings_light_vertical */ char * sbar_top = "\xe2\x94\x90"; /* box_drawings_light_down_and_left */ char * sbar_down = "\xe2\x94\x98"; /* box_drawings_light_up_and_left */ char * sbar_curs = "\xe2\x95\x91"; /* box_drawings_double_vertical */ char * sbar_arr_up = "\xe2\x96\xb2"; /* black_up_pointing_triangle */ char * sbar_arr_down = "\xe2\x96\xbc"; /* black_down_pointing_triangle */ char * msg_arr_down = "\xe2\x96\xbc"; /* black_down_pointing_triangle */ /* Variables used to manage the direct access entries. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ daccess_t daccess; char * daccess_stack; int daccess_stack_head; /* Variables used for fuzzy and substring searching. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ long * matching_words_a; long matching_words_a_size; long matches_count; long * best_matching_words_a; long best_matching_words_a_size; long best_matches_count; long * alt_matching_words_a = NULL; long alt_matches_count; /* Variables used in signal handlers. */ /* """""""""""""""""""""""""""""""""" */ volatile sig_atomic_t got_winch = 0; volatile sig_atomic_t got_winch_alrm = 0; volatile sig_atomic_t got_help_alrm = 0; volatile sig_atomic_t got_daccess_alrm = 0; volatile sig_atomic_t got_search_alrm = 0; volatile sig_atomic_t got_timeout_tick = 0; volatile sig_atomic_t got_sigsegv = 0; volatile sig_atomic_t got_sigterm = 0; volatile sig_atomic_t got_sighup = 0; /* Variables used when a timeout is set (option -x). */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ timeout_t timeout; char * timeout_word; /* printed word when the timeout type is WORD. */ char * timeout_seconds; /* string containing the number of remaining * * seconds. */ int quiet_timeout = 0; /* 1 when we want no message to be displayed. */ /* *************** */ /* Help functions. */ /* *************** */ /* ===================== */ /* Help message display. */ /* ===================== */ void help(win_t * win, term_t * term, long last_line, toggle_t * toggles) { int index; /* used to identify the objects long the help line. */ int line = 0; /* number of windows lines used by the help line. */ int len = 0; /* length of the help line. */ int offset = 0; /* offset from the first column of the terminal to * * the start of the help line. */ int entries_nb; /* number of help entries to display. */ int help_len; /* total length of the help line. */ struct entry_s { char attr; /* r=reverse, n=normal, b=bold. */ char * str; /* string to be displayed for an object in the help line. */ int len; /* length of one of these objects. */ }; char * arrows = concat(left_arrow, up_arrow, right_arrow, down_arrow, (char *)0); struct entry_s entries[] = { { 'n', "Move:", 5 }, { 'b', arrows, 4 }, { 'n', "|", 1 }, { 'b', "h", 1 }, { 'b', "j", 1 }, { 'b', "k", 1 }, { 'b', "l", 1 }, { 'n', ",", 1 }, { 'b', "PgUp", 4 }, { 'n', "/", 1 }, { 'b', "PgDn", 4 }, { 'n', "/", 1 }, { 'b', "Home", 4 }, { 'n', "/", 1 }, { 'b', "End", 3 }, { 'n', " ", 1 }, { 'n', "Abort:", 6 }, { 'b', "q", 1 }, { 'n', " ", 1 }, { 'n', "Find:", 5 }, { 'b', "/", 1 }, { 'n', "|", 1 }, { 'b', "\"\'", 2 }, { 'n', "|", 1 }, { 'b', "~*", 2 }, { 'n', "|", 1 }, { 'b', "=^", 2 }, { 'n', ",", 1 }, { 'b', "SP", 2 }, { 'n', "|", 1 }, { 'b', "nN", 2 }, { 'n', " ", 1 }, { 'n', "Select:", 7 }, { 'b', "CR", 2 }, { 'n', "|", 1 }, { 'b', "tTU", 3 } }; entries_nb = sizeof(entries) / sizeof(struct entry_s); /* Remove the last two entries if tagging is not enabled. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!toggles->taggable) entries_nb -= 2; /* Get the total length of the help line. */ /* """""""""""""""""""""""""""""""""""""" */ help_len = 0; for (index = 0; index < entries_nb; index++) help_len += entries[index].len; /* Save the position of the terminal cursor so that it can be */ /* put back there after printing of the help line. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(save_cursor), 1, outch); /* Center the help line if the -M (Middle option is set. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win->offset > 0) if ((offset = win->offset + win->max_width / 2 - help_len / 2) > 0) { int i; for (i = 0; i < offset; i++) fputc(' ', stdout); } /* Print the different objects forming the help line. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ for (index = 0; index < entries_nb; index++) { if ((len += entries[index].len) >= term->ncolumns - 1) { line++; if (line > last_line || line == win->max_lines) break; len = entries[index].len; fputc('\n', stdout); } switch (entries[index].attr) { case 'b': if (term->has_bold) tputs(TPARM1(enter_bold_mode), 1, outch); break; case 'r': if (term->has_reverse) tputs(TPARM1(enter_reverse_mode), 1, outch); else if (term->has_standout) tputs(TPARM1(enter_standout_mode), 1, outch); break; case 'n': tputs(TPARM1(exit_attribute_mode), 1, outch); break; } fputs(entries[index].str, stdout); } tputs(TPARM1(exit_attribute_mode), 1, outch); tputs(TPARM1(clr_eol), 1, outch); /* Relocate the cursor to its saved position. */ /* """""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(restore_cursor), 1, outch); } /* *********************************** */ /* Attributes string parsing function. */ /* *********************************** */ /* ================================= */ /* Decode attributes toggles if any. */ /* b -> bold */ /* d -> dim */ /* r -> reverse */ /* s -> standout */ /* u -> underline */ /* i -> italic */ /* */ /* Returns 0 if some unexpected. */ /* toggle is found else 0. */ /* ================================= */ int decode_attr_toggles(char * s, attrib_t * attr) { int rc = 1; attr->bold = attr->dim = attr->reverse = 0; attr->standout = attr->underline = attr->italic = 0; while (*s != '\0') { switch (*s) { case 'b': attr->bold = 1; attr->is_set = SET; break; case 'd': attr->dim = 1; attr->is_set = SET; break; case 'r': attr->reverse = 1; attr->is_set = SET; break; case 's': attr->standout = 1; attr->is_set = SET; break; case 'u': attr->underline = 1; attr->is_set = SET; break; case 'i': attr->italic = 1; attr->is_set = SET; break; default: rc = 0; break; } s++; } return rc; } /* =========================================================*/ /* Parse attributes in str in the form [fg][/bg][,toggles] */ /* where: */ /* fg and bg are short representing a color value */ /* toggles is an array of toggles (see decode_attr_toggles) */ /* Returns 1 on success else 0. */ /* attr will be filled by the function. */ /* =========================================================*/ int parse_attr(char * str, attrib_t * attr, short max_color) { int n; char * pos; char s1[12] = { 0 }; char s2[7] = { 0 }; short d1 = -1, d2 = -1; int rc = 1; n = sscanf(str, "%11[^,],%6s", s1, s2); if (n == 0) return 0; if ((pos = strchr(s1, '/'))) { if (pos == s1) /* s1 starts with a / */ { d1 = -1; if (sscanf(s1 + 1, "%hd", &d2) == 0) { d2 = -1; if (n == 1) return 0; } } else if (sscanf(s1, "%hd/%hd", &d1, &d2) < 2) { d1 = d2 = -1; if (n == 1) return 0; } } else /* no / in the first string. */ { d2 = -1; if (sscanf(s1, "%hd", &d1) == 0) { d1 = -1; if (n == 2 || decode_attr_toggles(s1, attr) == 0) return 0; } } if (d1 < -1 || d2 < -1) return 0; if (max_color == 0) { attr->fg = -1; attr->bg = -1; } else { attr->fg = d1; attr->bg = d2; } if (n == 2) rc = decode_attr_toggles(s2, attr); return rc; } /* ============================================== */ /* Set the terminal attributes according to attr. */ /* ============================================== */ void apply_attr(term_t * term, attrib_t attr) { if (attr.fg >= 0) set_foreground_color(term, attr.fg); if (attr.bg >= 0) set_background_color(term, attr.bg); if (attr.bold > 0) tputs(TPARM1(enter_bold_mode), 1, outch); if (attr.dim > 0) tputs(TPARM1(enter_dim_mode), 1, outch); if (attr.reverse > 0) tputs(TPARM1(enter_reverse_mode), 1, outch); if (attr.standout > 0) tputs(TPARM1(enter_standout_mode), 1, outch); if (attr.underline > 0) tputs(TPARM1(enter_underline_mode), 1, outch); if (attr.italic > 0) tputs(TPARM1(enter_italics_mode), 1, outch); } /* ********************* */ /* ini parsing function. */ /* ********************* */ /* ===================================================== */ /* Callback function called when parsing each non-header */ /* line of the ini file. */ /* Returns 0 if OK, 1 if not. */ /* ===================================================== */ int ini_cb(win_t * win, term_t * term, limit_t * limits, ticker_t * timers, misc_t * misc, langinfo_t * langinfo, const char * section, const char * name, char * value) { int error = 0; int has_colors = (term->colors > 7); if (strcmp(section, "colors") == 0) { attrib_t v = { UNSET, -1, -1, -1, -1, -1, -1, -1, -1 }; #define CHECK_ATTR(x) \ else if (strcmp(name, #x) == 0) \ { \ error = !parse_attr(value, &v, term->colors); \ if (error) \ goto out; \ else \ { \ if (win->x##_attr.is_set != FORCED) \ { \ win->x##_attr.is_set = SET; \ if (v.fg >= 0) \ win->x##_attr.fg = v.fg; \ if (v.bg >= 0) \ win->x##_attr.bg = v.bg; \ if (v.bold >= 0) \ win->x##_attr.bold = v.bold; \ if (v.dim >= 0) \ win->x##_attr.dim = v.dim; \ if (v.reverse >= 0) \ win->x##_attr.reverse = v.reverse; \ if (v.standout >= 0) \ win->x##_attr.standout = v.standout; \ if (v.underline >= 0) \ win->x##_attr.underline = v.underline; \ if (v.italic >= 0) \ win->x##_attr.italic = v.italic; \ } \ } \ } #define CHECK_ATT_ATTR(x, y) \ else if (strcmp(name, #x #y) == 0) \ { \ error = !parse_attr(value, &v, term->colors); \ if (error) \ goto out; \ else \ { \ if (win->x##_attr[y - 1].is_set != FORCED) \ { \ win->x##_attr[y - 1].is_set = SET; \ if (v.fg >= 0) \ win->x##_attr[y - 1].fg = v.fg; \ if (v.bg >= 0) \ win->x##_attr[y - 1].bg = v.bg; \ if (v.bold >= 0) \ win->x##_attr[y - 1].bold = v.bold; \ if (v.dim >= 0) \ win->x##_attr[y - 1].dim = v.dim; \ if (v.reverse >= 0) \ win->x##_attr[y - 1].reverse = v.reverse; \ if (v.standout >= 0) \ win->x##_attr[y - 1].standout = v.standout; \ if (v.underline >= 0) \ win->x##_attr[y - 1].underline = v.underline; \ if (v.italic >= 0) \ win->x##_attr[y - 1].italic = v.italic; \ } \ } \ } /* [colors] section. */ /* """"""""""""""""" */ if (has_colors) { if (strcmp(name, "method") == 0) { if (strcmp(value, "classic") == 0) term->color_method = 0; else if (strcmp(value, "ansi") == 0) term->color_method = 1; else { error = 1; goto out; } } /* clang-format off */ CHECK_ATTR(cursor) CHECK_ATTR(bar) CHECK_ATTR(shift) CHECK_ATTR(message) CHECK_ATTR(search_field) CHECK_ATTR(search_text) CHECK_ATTR(match_field) CHECK_ATTR(match_text) CHECK_ATTR(match_err_field) CHECK_ATTR(match_err_text) CHECK_ATTR(include) CHECK_ATTR(exclude) CHECK_ATTR(tag) CHECK_ATTR(cursor_on_tag) CHECK_ATTR(daccess) CHECK_ATT_ATTR(special, 1) CHECK_ATT_ATTR(special, 2) CHECK_ATT_ATTR(special, 3) CHECK_ATT_ATTR(special, 4) CHECK_ATT_ATTR(special, 5) /* clang-format on */ } } else if (strcmp(section, "window") == 0) { int v; /* [window] section. */ /* """"""""""""""""" */ if (strcmp(name, "lines") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v >= 0))) goto out; else win->asked_max_lines = v; } } else if (strcmp(section, "limits") == 0) { int v; /* [limits] section. */ /* """"""""""""""""" */ if (strcmp(name, "word_length") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else limits->word_length = v; } else if (strcmp(name, "words") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else limits->words = v; } else if (strcmp(name, "columns") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else limits->cols = v; } } else if (strcmp(section, "timers") == 0) { int v; /* [timers] section. */ /* """"""""""""""""" */ if (strcmp(name, "help") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else timers->help = v; } else if (strcmp(name, "window") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else timers->winch = v; } else if (strcmp(name, "direct_access") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else timers->direct_access = v; } else if (strcmp(name, "search") == 0) { if ((error = !(sscanf(value, "%d", &v) == 1 && v > 0))) goto out; else timers->search = v; } } else if (strcmp(section, "misc") == 0) { /* [misc] section. */ /* """"""""""""""" */ if (strcmp(name, "default_search_method") == 0) { if (misc->default_search_method == NONE) { if (strcmp(value, "prefix") == 0) misc->default_search_method = PREFIX; else if (strcmp(value, "fuzzy") == 0) misc->default_search_method = FUZZY; else if (strcmp(value, "substring") == 0) misc->default_search_method = SUBSTRING; } } } out: return error; } /* ======================================================================== */ /* Load an .ini format file. */ /* filename - path to a file */ /* report - callback can return non-zero to stop, the callback error code */ /* returned from this function. */ /* return - return 0 on success. */ /* */ /* This function is public domain. No copyright is claimed. */ /* Jon Mayo April 2011. */ /* ======================================================================== */ int ini_load(const char * filename, win_t * win, term_t * term, limit_t * limits, ticker_t * timers, misc_t * misc, langinfo_t * langinfo, int (*report)(win_t * win, term_t * term, limit_t * limits, ticker_t * timers, misc_t * misc, langinfo_t * langinfo, const char * section, const char * name, char * value)) { char name[64] = ""; char value[256] = ""; char section[128] = ""; char * s; FILE * f; int cnt; int error; /* If the filename is empty we skip this phase and use the */ /* default values. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (filename == NULL) return 1; /* We do that if the file is not readable as well. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ f = fopen(filename, "r"); if (!f) return 0; /* Returns success as the presence of this file * | is optional. */ error = 0; /* Skip blank lines. */ /* """"""""""""""""" */ while (fscanf(f, "%*[\n]") == 1) { } while (!feof(f)) { if (fscanf(f, " [%127[^];\n]]", section) == 1) { /* Do nothing. */ /* """"""""""" */ } if ((cnt = fscanf(f, " %63[^=;\n] = %255[^;\n]", name, value))) { if (cnt == 1) *value = 0; for (s = name + strlen(name) - 1; s > name && isspace(*s); s--) *s = 0; for (s = value + strlen(value) - 1; s > value && isspace(*s); s--) *s = 0; /* Callback function calling. */ /* """""""""""""""""""""""""" */ error = report(win, term, limits, timers, misc, langinfo, section, name, value); if (error) goto out; } if (fscanf(f, " ;%*[^\n]")) { /* To silence the compiler about unused results. */ } /* Skip blank lines. */ /* """"""""""""""""" */ while (fscanf(f, "%*[\n]") == 1) { /* Do nothing. */ /* """"""""""" */ } } out: fclose(f); if (error) fprintf(stderr, "Invalid entry found: %s=%s in %s.\n", name, value, filename); return error; } /* ======================================================= */ /* Return the full path on the configuration file supposed */ /* to be in the home directory of the user. */ /* NULL is returned if the built path is too large. */ /* ======================================================= */ char * make_ini_path(char * name, char * base) { char * path; char * home; long path_max; long len; char * conf; /* Set the prefix of the path from the environment */ /* base can be "HOME" or "PWD". */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ home = getenv(base); if (home == NULL) home = ""; path_max = pathconf(".", _PC_PATH_MAX); len = strlen(home) + strlen(name) + 3; if (path_max < 0) path_max = 4096; /* POSIX minimal value. */ if (len <= path_max) { path = xmalloc(len); conf = strrchr(name, '/'); if (conf != NULL) conf++; else conf = name; snprintf(path, 4096, "%s/.%s", home, conf); } else path = NULL; return path; } /* ********************************* */ /* Functions used when sorting tags. */ /* ********************************* */ /* ============================================================ */ /* Compare the pin order of two pinned word in the output list. */ /* ============================================================ */ int tag_comp(void * a, void * b) { output_t * oa = (output_t *)a; output_t * ob = (output_t *)b; if (oa->order == ob->order) return 0; return (oa->order < ob->order) ? -1 : 1; } /* ========================================================= */ /* Swap the values of two selected words in the output list. */ /* ========================================================= */ void tag_swap(void * a, void * b) { output_t * oa = (output_t *)a; output_t * ob = (output_t *)b; char * tmp_str; long tmp_order; tmp_str = oa->output_str; oa->output_str = ob->output_str; ob->output_str = tmp_str; tmp_order = oa->order; oa->order = ob->order; ob->order = tmp_order; } /* ****************** */ /* Utility functions. */ /* ****************** */ /* =================================================================== */ /* Create a new element to be added to the tst_search_list used by the */ /* search mechanism. */ /* =================================================================== */ sub_tst_t * sub_tst_new(void) { sub_tst_t * elem = xmalloc(sizeof(sub_tst_t)); elem->size = 64; elem->count = 0; elem->array = xmalloc(elem->size * sizeof(tst_node_t)); return elem; } /* ========================================= */ /* Emit a small (visual) beep warn the user. */ /* ========================================= */ void my_beep(toggle_t * toggles) { struct timespec ts, rem; int rc; if (!toggles->visual_bell) fputc('\a', stdout); else { tputs(TPARM1(cursor_visible), 1, outch); ts.tv_sec = 0; ts.tv_nsec = 200000000; /* 0.2s */ errno = 0; rc = nanosleep(&ts, &rem); while (rc < 0 && errno == EINTR) { errno = 0; rc = nanosleep(&rem, &rem); } tputs(TPARM1(cursor_invisible), 1, outch); } } /* =========================================== */ /* Integer verification constraint for ctxopt. */ /* =========================================== */ int check_integer_constraint(int nb_args, char ** args, char * value, char * par) { if (!is_integer(value)) { fprintf(stderr, "This argument of %s is not an integer: %s", par, value); return 0; } return 1; } /* ======================================================================== */ /* Update the bitmap associated with a word. This bitmap indicates the */ /* positions of the UFT-8 glyphs of the search buffer in each word. */ /* The disp_word function will use it to display these special characters. */ /* ======================================================================== */ void update_bitmaps(search_mode_t mode, search_data_t * data, bitmap_affinity_t affinity) { long i, j, n; /* work variables */ long lmg; /* position of the last matching glyph of the search buffer * * in a word. */ long sg; /* index going from lmg backward to 0 of the tested glyphs * * of the search buffer (searched glyph). */ long bm_len; /* number of chars taken by the bitmask. */ char * start; /* pointer on the position of the matching position * * of the last search buffer glyph in the word. */ char * bm; /* the word's current bitmap. */ char * str; /* copy of the current word put in lower case. */ char * str_orig; /* original version of the word. */ char * first_glyph; char * sb_orig = data->buf; /* sb: search buffer. */ char * sb; long * o = data->utf8_off_a; /* array of the offsets of the search * * buffer glyphs. */ long * l = data->utf8_len_a; /* array of the lengths in bytes of * * the search buffer glyphs. */ long last = data->utf8_len - 1; /* offset of the last glyph in the * * search buffer. */ long badness = 0; /* number of 0s between two 1s. */ best_matches_count = 0; if (mode == FUZZY || mode == SUBSTRING) { first_glyph = xmalloc(5); if (mode == FUZZY) { sb = xstrdup(sb_orig); utf8_strtolower(sb, sb_orig); } else sb = sb_orig; for (i = 0; i < matches_count; i++) { n = matching_words_a[i]; str_orig = xstrdup(word_a[n].str + daccess.flength); /* We need to remove the trailing spaces to use the */ /* following algorithm. */ /* .len holds the original length in bytes of the word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ rtrim(str_orig, " \t", 0); bm_len = (word_a[n].mb - daccess.flength) / CHAR_BIT + 1; bm = word_a[n].bitmap; /* In fuzzy search mode str are converted in lower case letters */ /* for comparison reason. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (mode == FUZZY) { str = xstrdup(str_orig); utf8_strtolower(str, str_orig); } else str = str_orig; start = str; lmg = 0; /* starts points to the first UTF-8 glyph of the word. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ while ((size_t)(start - str) < word_a[n].len - daccess.flength) { /* Reset the bitmap. */ /* """"""""""""""""" */ memset(bm, '\0', bm_len); /* Compare the glyph pointed to by start to the last glyph of */ /* the search buffer, the aim is to point to the first */ /* occurrence of the last glyph of it. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (memcmp(start, sb + o[last], l[last]) == 0) { char * p; /* Pointer to the beginning of an UTF-8 glyph in * * the potential lowercase version of the word. */ if (last == 0) { /* There is only one glyph in the search buffer, we can */ /* stop here. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ BIT_ON(bm, lmg); if (affinity != END_AFFINITY) break; } /* If the search buffer contains more than one glyph, we need */ /* to search the first combination which match the buffer in */ /* the word. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ p = start; j = last; /* j counts the number of glyphs in the search buffer * * not found in the word. */ /* Proceed backwards from the position of last glyph of the */ /* search to check if all the previous glyphs can be fond before */ /* in the word. If not try to find the next position of this */ /* last glyph in the word. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ sg = lmg; while (j > 0 && (p = utf8_prev(str, p)) != NULL) { if (memcmp(p, sb + o[j - 1], l[j - 1]) == 0) { BIT_ON(bm, sg - 1); j--; } else if (mode == SUBSTRING) break; sg--; } /* All the glyphs have been found. */ /* """"""""""""""""""""""""""""""" */ if (j == 0) { BIT_ON(bm, lmg); if (affinity != END_AFFINITY) break; } } lmg++; start = utf8_next(start); } if (mode == FUZZY) { size_t utf8_index; free(str); /* We know that the first non blank glyph is part of the pattern, */ /* so highlight it if it is not and unhighlight the next occurrence */ /* that must be here because this word has already been filtered */ /* by select_starting_pattern(). */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (affinity == START_AFFINITY) { char *ptr1, *ptr2; long i; long utf8_len; /* Skip leading spaces and tabs. */ /* """"""""""""""""""""""""""""" */ for (i = 0; i < word_a[n].mb; i++) if (!isblank(*(word_a[n].str + daccess.flength + i))) break; first_glyph = utf8_strprefix(first_glyph, word_a[n].str + i, 1, &utf8_len); if (!BIT_ISSET(word_a[n].bitmap, i)) { BIT_ON(word_a[n].bitmap, i); ptr1 = word_a[n].str + i; i++; while ((ptr2 = utf8_next(ptr1)) != NULL) { if (memcmp(ptr2, first_glyph, utf8_len) == 0) { if (BIT_ISSET(word_a[n].bitmap, i)) { BIT_OFF(word_a[n].bitmap, i); break; } else ptr1 = ptr2; } else ptr1 = ptr2; i++; } } } /* Compute the number of 'holes' in the bitmap to determine the */ /* badness of a match. Th goal is to put the cursor on the word */ /* with the smallest badness. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_index = 0; j = 0; badness = 0; while (utf8_index < word_a[n].mb && !BIT_ISSET(word_a[n].bitmap, utf8_index)) utf8_index++; while (utf8_index < word_a[n].mb) { if (!BIT_ISSET(word_a[n].bitmap, utf8_index)) badness++; else j++; /* Stop here if all the possible bits has been checked as they */ /* cannot be more numerous than the number of UTF-8 glyphs in */ /* the search buffer. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (j == data->utf8_len) break; utf8_index++; } } free(str_orig); if (search_mode == FUZZY) { /* When the badness is zero (best match), add the word position. */ /* at the end of a special array which will be used to move the. */ /* cursor among this category of words. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (badness == 0) { if (best_matches_count == best_matching_words_a_size) { best_matching_words_a = xrealloc(best_matching_words_a, (best_matching_words_a_size + 16) * sizeof(long)); best_matching_words_a_size += 16; } best_matching_words_a[best_matches_count] = n; best_matches_count++; } } } if (mode == FUZZY) free(sb); free(first_glyph); } else if (mode == PREFIX) { for (i = 0; i < matches_count; i++) { n = matching_words_a[i]; bm = word_a[n].bitmap; bm_len = (word_a[n].mb - daccess.flength) / CHAR_BIT + 1; memset(bm, '\0', bm_len); for (j = 0; j <= last; j++) BIT_ON(bm, j); } } } /* ====================================================== */ /* Find the next word index in the list of matching words */ /* returns -1 if not found. */ /* ====================================================== */ long find_next_matching_word(long * array, long nb, long value, long * index) { long left = 0, right = nb, middle; /* Use the cached value when possible" */ /* """"""""""""""""""""""""""""""""""" */ if (*index >= 0 && *index < nb - 1 && array[*index] == value) return (array[++(*index)]); if (nb > 0) { /* Bisection search. */ /* ''''''''''''''''' */ while (left < right) { middle = (left + right) / 2; if (value < array[middle]) right = middle; else left = middle + 1; } if (left < nb - 1) { *index = left; return array[*index]; } else { if (value > array[nb - 1]) { *index = -1; return *index; } else { *index = nb - 1; return array[*index]; } } } else { *index = -1; return *index; } } /* ========================================================== */ /* Find the previous word index in the list of matching words */ /* returns -1 if not found. */ /* ========================================================== */ long find_prev_matching_word(long * array, long nb, long value, long * index) { long left = 0, right = nb, middle; /* Use the cached value when possible. */ /* """"""""""""""""""""""""""""""""""" */ if (*index > 0 && array[*index] == value) return (array[--(*index)]); if (nb > 0) { /* Bisection search. */ /* ''''''''''''''''' */ while (left < right) { middle = (left + right) / 2; if (array[middle] == value) { if (middle > 0) { *index = middle - 1; return array[*index]; } else { *index = -1; return *index; } } if (value < array[middle]) right = middle; else left = middle + 1; } if (left > 0) { *index = left - 1; return array[*index]; } else { *index = -1; return *index; } } else { *index = -1; return *index; } } /* ============================================================= */ /* Remove all traces of matched words and redisplay the windows. */ /* ============================================================= */ void clean_matches(search_data_t * search_data, long size) { sub_tst_t * sub_tst_data; ll_node_t * fuzzy_node; long i; /* Clean the list of lists data-structure containing the search levels */ /* Note that the first element of the list is never deleted. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (tst_search_list) { fuzzy_node = tst_search_list->tail; while (tst_search_list->len > 1) { sub_tst_data = (sub_tst_t *)(fuzzy_node->data); free(sub_tst_data->array); free(sub_tst_data); ll_delete(tst_search_list, tst_search_list->tail); fuzzy_node = tst_search_list->tail; } sub_tst_data = (sub_tst_t *)(fuzzy_node->data); sub_tst_data->count = 0; } search_data->fuzzy_err = 0; /* Clean the search buffer. */ /* """""""""""""""""""""""" */ memset(search_data->buf, '\0', size - daccess.flength); search_data->len = 0; search_data->utf8_len = 0; search_data->only_ending = 0; search_data->only_starting = 0; /* Clean the match flags and bitmaps. */ /* """""""""""""""""""""""""""""""""" */ for (i = 0; i < matches_count; i++) { long n = matching_words_a[i]; word_a[n].is_matching = 0; memset(word_a[n].bitmap, '\0', (word_a[n].mb - daccess.flength) / CHAR_BIT + 1); } matches_count = 0; } /* *************************** */ /* Terminal utility functions. */ /* *************************** */ /* ===================================================================== */ /* outch is a function version of putchar that can be passed to tputs as */ /* a routine to call. */ /* ===================================================================== */ int #ifdef __sun outch(char c) #else outch(int c) #endif { putchar(c); return 1; } /* =============================================== */ /* Set the terminal in non echo/non canonical mode */ /* wait for at least one byte, no timeout. */ /* =============================================== */ void setup_term(int const fd) { /* Save the terminal parameters and configure it in row mode. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ tcgetattr(fd, &old_in_attrs); new_in_attrs.c_iflag = 0; new_in_attrs.c_oflag = old_in_attrs.c_oflag; new_in_attrs.c_cflag = old_in_attrs.c_cflag; new_in_attrs.c_lflag = old_in_attrs.c_lflag & ~(ICANON | ECHO | ISIG); new_in_attrs.c_cc[VMIN] = 1; /* wait for at least 1 byte. */ new_in_attrs.c_cc[VTIME] = 0; /* no timeout. */ tcsetattr(fd, TCSANOW, &new_in_attrs); } /* ====================================== */ /* Set the terminal in its previous mode. */ /* ====================================== */ void restore_term(int const fd) { tcsetattr(fd, TCSANOW, &old_in_attrs); } /* ============================================== */ /* Get the terminal numbers of lines and columns */ /* Assume that the TIOCGWINSZ, ioctl is available */ /* Defaults to 80x24. */ /* ============================================== */ void get_terminal_size(int * const r, int * const c, term_t * term) { struct winsize ws; *r = *c = -1; if (ioctl(0, TIOCGWINSZ, &ws) == 0) { *r = ws.ws_row; *c = ws.ws_col; if (*r > 0 && *c > 0) return; } *r = tigetnum("lines"); *c = tigetnum("cols"); if (*r <= 0 || *c <= 0) { *r = 80; *c = 24; } } /* ======================================================= */ /* Get cursor position the terminal. */ /* Assume that the Escape sequence ESC [ 6 n is available. */ /* Returns 1 on success and 0 on error. */ /* ======================================================= */ int get_cursor_position(int * const r, int * const c) { char buf[32] = { 0 }; char * s; int count = 64; int v; int rc = 1; int ask; /* Number of asked characters. */ int got; /* Number of characters obtained. */ int buf_size = sizeof(buf); /* Report cursor location. */ /* """"""""""""""""""""""" */ while ((v = write(STDOUT_FILENO, "\x1b[6n", 4)) == -1 && count) { if (errno == EINTR) count--; else { rc = 0; goto read; } errno = 0; } if (v != 4) rc = 0; read: /* Read the response: ESC [ rows ; cols R. */ /* """"""""""""""""""""""""""""""""""""""" */ *(s = buf) = 0; do { ask = buf_size - 1 - (s - buf); got = read(STDIN_FILENO, s, ask); if (got < 0 && errno == EINTR) got = 0; else if (got == 0) break; s += got; } while (strchr(buf, 'R') == 0); /* Parse it. */ /* """"""""" */ if (buf[0] != 0x1b || buf[1] != '[') return 0; if (sscanf(buf + 2, "%d;%d", r, c) != 2) rc = 0; return rc; } /* ====================================================== */ /* Returns 1 if a string is empty or only made of spaces. */ /* ====================================================== */ int isempty(const char * s) { while (*s != '\0') { if (my_isprint(*s) && *s != ' ' && *s != '\t') return 0; s++; } return 1; } /* ======================================================================== */ /* Parse a regular expression based selector. */ /* The string to parse is bounded by a delimiter so we must parse something */ /* like: as in /a.*b/ by example. */ /* */ /* str (in) delimited string to parse */ /* filter (in) INCLUDE_FILTER or EXCLUDE_FILTER */ /* inc_regex_list (out) INCLUDE_FILTER or EXCLUDE_FILTER */ /* regular expression if the filter is INCLUDE_FILTER */ /* exc_regex_list (out) INCLUDE_FILTER or EXCLUDE_FILTER */ /* regular expression if the filter is EXCLUDE_FILTER */ /* ======================================================================== */ void parse_regex_selector_part(char * str, filters_t filter, ll_t ** inc_regex_list, ll_t ** exc_regex_list) { regex_t * regex; str[strlen(str) - 1] = '\0'; regex = xmalloc(sizeof(regex_t)); if (regcomp(regex, str + 1, REG_EXTENDED | REG_NOSUB) == 0) { if (filter == INCLUDE_FILTER) { if (*inc_regex_list == NULL) *inc_regex_list = ll_new(); ll_append(*inc_regex_list, regex); } else { if (*exc_regex_list == NULL) *exc_regex_list = ll_new(); ll_append(*exc_regex_list, regex); } } } /* ===================================================================== */ /* Parse a description string. */ /* ,,... */ /* is n1-n2 | n1 where n1 starts with 1. */ /* */ /* is a|A|s|S|r|R|u|U where */ /* a|A is for Add */ /* s|S is for Select (same as Add) */ /* r|R is for Remove */ /* d|D is for Deselect (same as Remove) */ /* */ /* str (in) string to parse */ /* filter (out) is INCLUDE_FILTER or EXCLUDE_FILTER according */ /* to */ /* unparsed (out) is empty on success and contains the unparsed */ /* part on failure */ /* inc_interval_list (out) is a list of the interval of elements to */ /* be included. */ /* inc_regex_list (out) is a list of extended regular expressions of */ /* elements to be included. */ /* exc_interval_list (out) is a list of the interval of elements to be */ /* excluded. */ /* exc_regex_list (out) is a list of extended interval of elements to */ /* be excluded. */ /* ===================================================================== */ void parse_selectors(char * str, filters_t * filter, char * unparsed, ll_t ** inc_interval_list, ll_t ** inc_regex_list, ll_t ** exc_interval_list, ll_t ** exc_regex_list, langinfo_t * langinfo, misc_t * misc) { char mark; /* Value to set */ char c; size_t start = 1; /* column string offset in the parsed string. */ size_t first, second; /* range starting and ending values. */ char * ptr; /* pointer to the remaining string to parse. */ interval_t * interval; /* Replace the UTF-8 ascii representation in the selector by */ /* their binary values. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_interpret(str, langinfo, misc->invalid_char_substitute); /* Get the first character to see if this is */ /* an additive or restrictive operation. */ /* """"""""""""""""""""""""""""""""""""""""" */ if (sscanf(str, "%c", &c) == 0) return; switch (c) { case 'i': case 'I': *filter = INCLUDE_FILTER; mark = INCLUDE_MARK; break; case 'e': case 'E': *filter = EXCLUDE_FILTER; mark = EXCLUDE_MARK; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *filter = INCLUDE_FILTER; mark = INCLUDE_MARK; start = 0; break; default: if (!isgraph(c)) return; *filter = INCLUDE_FILTER; mark = INCLUDE_MARK; start = 0; break; } /* Set ptr to the start of the interval list to parse. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ ptr = str + start; first = second = -1; /* Scan the comma separated ranges. */ /* """""""""""""""""""""""""""""""" */ while (*ptr) { size_t swap; int is_range = 0; char delim1, delim2 = '\0'; char * oldptr; oldptr = ptr; while (*ptr && *ptr != ',') { if (*ptr == '-') is_range = 1; ptr++; } /* Forbid the trailing comma (ex: xxx,). */ /* """"""""""""""""""""""""""""""""""""" */ if (*ptr == ',' && (*(ptr + 1) == '\0' || *(ptr + 1) == '-')) { my_strcpy(unparsed, ptr); return; } /* Forbid the empty patterns (ex: xxx,,yyy). */ /* """"""""""""""""""""""""""""""""""""""""" */ if (oldptr == ptr) { my_strcpy(unparsed, ptr); return; } /* Mark the end of the interval found. */ /* """"""""""""""""""""""""""""""""""" */ if (*ptr) *ptr++ = '\0'; /* If the regex contains at least three characters then delim1 */ /* and delim2 point to the first and last delimiter of the */ /* regular expression. Ex /abc/ */ /* ^ ^ */ /* | | */ /* delim1 delim2 */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ delim1 = *(str + start); if (*ptr == '\0') delim2 = *(ptr - 1); else if (ptr > str + start + 2) delim2 = *(ptr - 2); /* Check is we have found a well describes regular expression. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ptr > str + start + 2 && delim1 == delim2 && isgraph(delim1) && isgraph(delim2) && !isdigit(delim1) && !isdigit(delim2)) { /* Process the regex. */ /* """""""""""""""""" */ parse_regex_selector_part(str + start, *filter, inc_regex_list, exc_regex_list); /* Adjust the start of the new interval to read in the */ /* initial string. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ start = ptr - str; continue; } else if (delim2 != '\0' && (!isdigit(delim1) || !isdigit(delim2))) { /* Both delimiter must be numeric if delim2 exist. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ my_strcpy(unparsed, str + start); return; } if (is_range) { int rc; int pos; rc = sscanf(str + start, "%zu-%zu%n", &first, &second, &pos); if (rc != 2 || *(str + start + pos) != '\0') { my_strcpy(unparsed, str + start); return; } if (first < 1 || second < 1) { /* Both interval boundaries must be strictly positive. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ my_strcpy(unparsed, str + start); return; } /* Ensure that the low bound of the interval is lower or equal */ /* to the high one. Swap them if needed. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ interval = interval_new(); if (first > second) { swap = first; first = second; second = swap; } interval->low = first - 1; interval->high = second - 1; } else { /* Read the number given. */ /* """""""""""""""""""""" */ if (sscanf(str + start, "%zu", &first) != 1) { my_strcpy(unparsed, str + start); return; } interval = interval_new(); interval->low = interval->high = first - 1; } /* Adjust the start of the new interval to read in the */ /* initial string. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ start = ptr - str; /* Add the new interval to the correct list. */ /* """"""""""""""""""""""""""""""""""""""""" */ if (mark == EXCLUDE_MARK) { if (*exc_interval_list == NULL) *exc_interval_list = ll_new(); ll_append(*exc_interval_list, interval); } else { if (*inc_interval_list == NULL) *inc_interval_list = ll_new(); ll_append(*inc_interval_list, interval); } } /* If we are here, then all the intervals have be successfully parsed */ /* Ensure that the unparsed string is empty. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ *unparsed = '\0'; } /* ========================================================= */ /* Parse the sed like string passed as argument to -S/-I/-E. */ /* Update the sed parameter. */ /* ========================================================= */ int parse_sed_like_string(sed_t * sed) { char sep; char * first_sep_pos; char * last_sep_pos; char * buf; long index; int icase; char c; if (strlen(sed->pattern) < 4) return 0; /* Get the separator (the 1st character). */ /* """""""""""""""""""""""""""""""""""""" */ buf = xstrdup(sed->pattern); sep = buf[0]; /* Space like separators are not permitted. */ /* """""""""""""""""""""""""""""""""""""""" */ if (isspace(sep)) goto err; /* Get the extended regular expression. */ /* """""""""""""""""""""""""""""""""""" */ if ((first_sep_pos = strchr(buf + 1, sep)) == NULL) goto err; *first_sep_pos = '\0'; /* Get the substitution string. */ /* """""""""""""""""""""""""""" */ if ((last_sep_pos = strchr(first_sep_pos + 1, sep)) == NULL) goto err; *last_sep_pos = '\0'; sed->substitution = xstrdup(first_sep_pos + 1); /* Get the global indicator (trailing g) */ /* and the visual indicator (trailing v) */ /* and the stop indicator (trailing s). */ /* """"""""""""""""""""""""""""""""""""" */ sed->global = sed->visual = icase = 0; index = 1; while ((c = *(last_sep_pos + index)) != '\0') { if (c == 'g') sed->global = 1; else if (c == 'v') sed->visual = 1; else if (c == 's') sed->stop = 1; else if (c == 'i') icase = 1; else goto err; index++; } /* Empty regular expression ? */ /* """""""""""""""""""""""""" */ if (*(buf + 1) == '\0') goto err; /* Compile the regular expression and abort on failure. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (regcomp(&(sed->re), buf + 1, !icase ? REG_EXTENDED : (REG_EXTENDED | REG_ICASE)) != 0) goto err; free(buf); return 1; err: free(buf); return 0; } /* ===================================================================== */ /* Utility function used by replace to expand the replacement string */ /* IN: */ /* orig: matching part of the original string to be replaced. */ /* repl: string containing the replacement directives */ /* subs_a: array of ranges containing the start and end offset */ /* of the remembered parts of the strings referenced */ /* by the sequence \n where n is in [1,10]. */ /* match_start/end: offset in orig for the current matched string */ /* subs_nb: number of elements containing significant values in */ /* the array described above. */ /* match: current match number in the original string. */ /* */ /* OUT: */ /* The modified string according to the content of repl. */ /* ===================================================================== */ char * build_repl_string(char * orig, char * repl, long match_start, long match_end, range_t * subs_a, long subs_nb, long match) { size_t rsize = 0; size_t allocated = 16; char * str = xmalloc(allocated); int special = 0; long offset = match * subs_nb; /* offset of the 1st sub * * corresponding to the match. */ if (*repl == '\0') str = xstrdup(""); else while (*repl) { switch (*repl) { case '\\': if (special) { if (allocated == rsize) str = xrealloc(str, allocated += 16); str[rsize] = '\\'; rsize++; str[rsize] = '\0'; special = 0; } else special = 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (special) { if ((*repl) - '0' <= subs_nb) { long index = (*repl) - '0' - 1 + offset; long delta = subs_a[index].end - subs_a[index].start; if (allocated <= rsize + delta) str = xrealloc(str, allocated += (delta + 16)); memcpy(str + rsize, orig + subs_a[index].start, delta); rsize += delta; str[rsize] = '\0'; } special = 0; } else { if (allocated == rsize) str = xrealloc(str, allocated += 16); str[rsize] = *repl; rsize++; str[rsize] = '\0'; } break; case '&': if (!special) { long delta = match_end - match_start; if (allocated <= rsize + delta) str = xrealloc(str, allocated += (delta + 16)); memcpy(str + rsize, orig + match_start, delta); rsize += delta; str[rsize] = '\0'; break; } /* No break here, '&' must be treated as a normal */ /* character when protected. */ /* '''''''''''''''''''''''''''''''''''''''''''''' */ default: special = 0; if (allocated == rsize) str = xrealloc(str, allocated += 16); str[rsize] = *repl; rsize++; str[rsize] = '\0'; } repl++; } return str; } /* ====================================================================== */ /* Replace the part of a string matched by an extender regular expression */ /* by the substitution string. */ /* The regex used must have been previously compiled. */ /* */ /* orig: original string */ /* sed: composite variable containing the regular expression, a */ /* substitution string and various other informations. */ /* output: destination buffer. */ /* */ /* RC: */ /* return 1 if the replacement has been successful else 0. */ /* */ /* NOTE: */ /* uses the global variable word_buffer. */ /* ====================================================================== */ int replace(char * orig, sed_t * sed) { size_t match_nb = 0; /* number of matches in the original string. */ int sub_nb = 0; /* number of remembered matches in the * * original sting. */ size_t target_len = 0; /* length of the resulting string. */ size_t subs_max = 0; if (*orig == '\0') return 1; range_t * matches_a = xmalloc(strlen(orig) * sizeof(range_t)); range_t * subs_a = xmalloc(10 * sizeof(range_t)); const char * p = orig; /* points to the end of the previous match. */ regmatch_t m[10]; /* array containing the start/end offsets * * of the matches found. */ while (1) { size_t i = 0; size_t match; /* current match index. */ size_t index = 0; /* current char index in the original string. */ int nomatch = 0; /* equals to 1 when there is no more matching. */ char * exp_repl; /* expanded replacement string. */ if (*p == '\0') nomatch = 1; else nomatch = regexec(&sed->re, p, 10, m, 0); if (nomatch) { if (match_nb > 0) { for (index = 0; index < matches_a[0].start; index++) word_buffer[target_len++] = orig[index]; for (match = 0; match < match_nb; match++) { size_t len; size_t end; exp_repl = build_repl_string(orig, sed->substitution, matches_a[match].start, matches_a[match].end, subs_a, subs_max, match); len = strlen(exp_repl); my_strcpy(word_buffer + target_len, exp_repl); target_len += len; free(exp_repl); index += matches_a[match].end - matches_a[match].start; if (match < match_nb - 1 && sed->global) end = matches_a[match + 1].start; else end = strlen(orig); while (index < end) word_buffer[target_len++] = orig[index++]; word_buffer[target_len] = '\0'; if (!sed->global) break; } } else { my_strcpy(word_buffer, orig); return 0; } return nomatch; } subs_max = 0; for (i = 0; i < 10; i++) { size_t start; size_t finish; if (m[i].rm_so == -1) break; start = m[i].rm_so + (p - orig); finish = m[i].rm_eo + (p - orig); if (i == 0) { matches_a[match_nb].start = start; matches_a[match_nb].end = finish; match_nb++; if (match_nb > utf8_strlen(orig)) goto fail; } else { subs_a[sub_nb].start = start; subs_a[sub_nb].end = finish; sub_nb++; subs_max++; } } if (m[0].rm_eo > 0) p += m[0].rm_eo; else p++; /* Empty match. */ } fail: return 0; } /* ============================================================ */ /* Remove all ANSI color codes from s and puts the result in d. */ /* Memory space for d must have been allocated before. */ /* ============================================================ */ void strip_ansi_color(char * s, toggle_t * toggles, misc_t * misc) { char * p = s; long len = strlen(s); while (*s != '\0') { /* Remove a sequence of \x1b[...m from s. */ /* """""""""""""""""""""""""""""""""""""" */ if ((*s == 0x1b) && (*(s + 1) == '[')) { while ((*s != '\0') && (*s++ != 'm')) ; } /* Convert a single \x1b in the invalid substitute character. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ else if (*s == 0x1b) { if (toggles->blank_nonprintable && len > 1) *s++ = ' '; else *s++ = misc->invalid_char_substitute; p++; } /* No ESC char, we can move on. */ /* """""""""""""""""""""""""""" */ else *p++ = *s++; } *p = '\0'; } /* ================================================================= */ /* Callback function to insert the index of a matching word index in */ /* the sorted list of the already matched words. */ /* ================================================================= */ int set_matching_flag(void * elem) { ll_t * list = (ll_t *)elem; ll_node_t * node = list->head; while (node) { size_t pos; pos = *(size_t *)(node->data); if (word_a[pos].is_selectable) word_a[pos].is_matching = 1; insert_sorted_index(&matching_words_a, &matching_words_a_size, &matches_count, pos); node = node->next; } return 1; } /* ======================================================================= */ /* Callback function used by tst_traverse. */ /* Iterate the linked list attached to the string containing the index of */ /* the words in the input flow. Each page number is then added in a sorted */ /* array avoiding duplications keeping the array sorted. */ /* Mark the identified words as a matching word. */ /* ======================================================================= */ int tst_cb(void * elem) { /* The data attached to the string in the tst is a linked list of */ /* position of the string in the input flow, This list is naturally */ /* sorted. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ ll_t * list = (ll_t *)elem; ll_node_t * node = list->head; while (node) { size_t pos; pos = *(long *)(node->data); word_a[pos].is_matching = 1; insert_sorted_index(&matching_words_a, &matching_words_a_size, &matches_count, pos); node = node->next; } return 1; } /* ======================================================================= */ /* Callback function used by tst_traverse. */ /* Iterate the linked list attached to the string containing the index of */ /* the words in the input flow. Each page number is then used to determine */ /* the lower page greater than the cursor position */ /* ----------------------------------------------------------------------- */ /* This is a special version of tst_cb which permit to find the first */ /* word. */ /* ----------------------------------------------------------------------- */ /* Require new_current to be set to count - 1 at start. */ /* Update new_current to the smallest greater position than current. */ /* ======================================================================= */ int tst_cb_cli(void * elem) { long n = 0; int rc = 0; /* The data attached to the string in the tst is a linked list of */ /* position of the string in the input flow, This list is naturally */ /* sorted. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ ll_t * list = (ll_t *)elem; ll_node_t * node = list->head; while (n++ < list->len) { long pos; pos = *(long *)(node->data); word_a[pos].is_matching = 1; insert_sorted_index(&matching_words_a, &matching_words_a_size, &matches_count, pos); /* We already are at the last word, report the finding.*/ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (pos == count - 1) return 1; /* Only consider the indexes above the current cursor position. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (pos >= current) /* Enable the search of the current word. */ { /* As the future new current index has been set to the highest */ /* possible value, each new possible position can only improve */ /* the estimation we set rc to 1 to mark that. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (pos < new_current) { new_current = pos; rc = 1; } } node = node->next; } return rc; } /* **************** */ /* Input functions. */ /* **************** */ /* =============================================== */ /* Non delay reading of a scancode. */ /* Update a scancodes buffer and return its length */ /* in bytes. */ /* =============================================== */ int get_scancode(unsigned char * s, size_t max) { int c; size_t i = 1; struct termios original_ts, nowait_ts; if ((c = my_fgetc(stdin)) == EOF) return 0; /* Initialize the string with the first byte */ /* """"""""""""""""""""""""""""""""""""""""" */ memset(s, '\0', max); s[0] = c; /* 0x1b (ESC) has been found, proceed to check if additional codes */ /* are available. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (c == 0x1b || c > 0x80) { /* Save the terminal parameters and configure getchar() */ /* to return immediately. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ tcgetattr(0, &original_ts); nowait_ts = original_ts; nowait_ts.c_lflag &= ~ISIG; nowait_ts.c_cc[VMIN] = 0; nowait_ts.c_cc[VTIME] = 0; tcsetattr(0, TCSADRAIN, &nowait_ts); /* Check if additional code is available after 0x1b. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if ((c = my_fgetc(stdin)) != EOF) { s[1] = c; i = 2; while (i < max && (c = my_fgetc(stdin)) != EOF) s[i++] = c; } else { /* There isn't a new code, this mean 0x1b came from ESC key. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ } /* Restore the save terminal parameters. */ /* """"""""""""""""""""""""""""""""""""" */ tcsetattr(0, TCSADRAIN, &original_ts); /* Ignore EOF when a scancode contains an escape sequence. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ clearerr(stdin); } return i; } /* ============================================================ */ /* Helper function to compare to delimiters for use by ll_find. */ /* ============================================================ */ int buffer_cmp(const void * a, const void * b) { return strcmp((const char *)a, (const char *)b); } /* ===================================================================== */ /* Get bytes from stdin. If the first byte is the leading character of a */ /* UTF-8 glyph, the following ones are also read. */ /* The utf8_get_length function is used to get the number of bytes of */ /* the character. */ /* ===================================================================== */ int get_bytes(FILE * input, char * utf8_buffer, ll_t * zapped_glyphs_list, langinfo_t * langinfo, misc_t * misc) { int byte; int last; int n; do { last = 0; /* Read the first byte. */ /* """""""""""""""""""" */ byte = my_fgetc(input); if (byte == EOF) return EOF; utf8_buffer[last++] = byte; /* Check if we need to read more bytes to form a sequence */ /* and put the number of bytes of the sequence in last. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (langinfo->utf8 && ((n = utf8_get_length(byte)) > 1)) { while (last < n && (byte = my_fgetc(input)) != EOF && (byte & 0xc0) == 0x80) utf8_buffer[last++] = byte; if (byte == EOF) return EOF; } utf8_buffer[last] = '\0'; /* Replace an invalid UTF-8 byte sequence by a single dot. */ /* In this case the original sequence is lost (unsupported */ /* encoding). */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (langinfo->utf8 && !utf8_validate(utf8_buffer, last)) { byte = utf8_buffer[0] = misc->invalid_char_substitute; utf8_buffer[1] = '\0'; } } while (ll_find(zapped_glyphs_list, utf8_buffer, buffer_cmp) != NULL); return byte; } /* =======================================================================*/ /* Expand the string str by replacing all its embedded special characters */ /* by their corresponding escape sequence. */ /* dest must be long enough to contain the expanded string. */ /* ====================================================================== */ size_t expand(char * src, char * dest, langinfo_t * langinfo, toggle_t * toggles, misc_t * misc) { char c; int n; int all_spaces = 1; char * ptr = dest; size_t len = 0; while ((c = *(src++))) { /* UTF-8 codepoints take more than on character. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if ((n = utf8_get_length(c)) > 1) { all_spaces = 0; if (langinfo->utf8) /* If the locale is UTF-8 aware, copy src into ptr. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ do { *(ptr++) = c; len++; } while (--n && (c = *(src++))); else { /* If not, ignore the bytes composing the UTF-8 */ /* glyph and replace them with a single '.'. */ /* """""""""""""""""""""""""""""""""""""""""""" */ do { /* Skip this byte. */ /* ''''''''''''''' */ } while (--n && ('\0' != *(src++))); *(ptr++) = misc->invalid_char_substitute; len++; } } else /* This is not an UTF-8 glyph. */ /* """"""""""""""""""""""""""" */ switch (c) { case '\a': *(ptr++) = '\\'; *(ptr++) = 'a'; len += 2; all_spaces = 0; break; case '\b': *(ptr++) = '\\'; *(ptr++) = 'b'; len += 2; all_spaces = 0; break; case '\t': *(ptr++) = '\\'; *(ptr++) = 't'; len += 2; all_spaces = 0; break; case '\n': *(ptr++) = '\\'; *(ptr++) = 'n'; len += 2; all_spaces = 0; break; case '\v': *(ptr++) = '\\'; *(ptr++) = 'v'; len += 2; all_spaces = 0; break; case '\f': *(ptr++) = '\\'; *(ptr++) = 'f'; len += 2; all_spaces = 0; break; case '\r': *(ptr++) = '\\'; *(ptr++) = 'r'; len += 2; all_spaces = 0; break; case '\\': *(ptr++) = '\\'; *(ptr++) = '\\'; len += 2; all_spaces = 0; break; default: if (my_isprint(c)) { *(ptr++) = c; all_spaces = 0; } else { if (toggles->blank_nonprintable) *(ptr++) = ' '; else { *(ptr++) = misc->invalid_char_substitute; all_spaces = 0; } } len++; } } /* If the word contains only spaces, replace them */ /* by underscores so that it can be seen. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ if (all_spaces) memset(dest, ' ', len); *ptr = '\0'; /* Ensure that dest has a nul terminator. */ return len; } /* ===================================================================== */ /* get_word(input): return a char pointer to the next word (as a string) */ /* Accept: a FILE * for the input stream. */ /* Return: a char * */ /* On Success: the return value will point to a nul-terminated */ /* string. */ /* On Failure: the return value will be set to NULL. */ /* ===================================================================== */ char * get_word(FILE * input, ll_t * word_delims_list, ll_t * record_delims_list, ll_t * zapped_glyphs_list, char * utf8_buffer, unsigned char * is_last, toggle_t * toggles, langinfo_t * langinfo, win_t * win, limit_t * limits, misc_t * misc) { char * temp = NULL; int byte; long utf8_count = 0; /* count chars used in current allocation. */ long wordsize; /* size of current allocation in chars. */ int is_dquote; /* double quote presence indicator. */ int is_squote; /* single quote presence indicator. */ int is_special; /* a character is special after a \ */ /* Skip leading delimiters. */ /* """""""""""""""""""""""" */ byte = get_bytes(input, utf8_buffer, zapped_glyphs_list, langinfo, misc); while (byte == EOF || ll_find(word_delims_list, utf8_buffer, buffer_cmp) != NULL) { if (byte == EOF) return NULL; byte = get_bytes(input, utf8_buffer, zapped_glyphs_list, langinfo, misc); } /* Allocate initial word storage space. */ /* """""""""""""""""""""""""""""""""""" */ temp = xmalloc(wordsize = CHARSCHUNK); /* Start stashing bytes. Stop when we meet a non delimiter or EOF. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_count = 0; is_dquote = 0; is_squote = 0; is_special = 0; while (byte != EOF) { size_t i = 0; if (utf8_count >= limits->word_length) { fprintf(stderr, "The length of a word has reached the limit of " "%ld characters.\n", limits->word_length); exit(EXIT_FAILURE); } if (byte == '\\' && !is_special) { is_special = 1; goto next; } /* Parse special characters. */ /* """"""""""""""""""""""""" */ if (is_special) switch (byte) { case 'a': utf8_buffer[0] = byte = '\a'; utf8_buffer[1] = '\0'; break; case 'b': utf8_buffer[0] = byte = '\b'; utf8_buffer[1] = '\0'; break; case 't': utf8_buffer[0] = byte = '\t'; utf8_buffer[1] = '\0'; break; case 'n': utf8_buffer[0] = byte = '\n'; utf8_buffer[1] = '\0'; break; case 'v': utf8_buffer[0] = byte = '\v'; utf8_buffer[1] = '\0'; break; case 'f': utf8_buffer[0] = byte = '\f'; utf8_buffer[1] = '\0'; break; case 'r': utf8_buffer[0] = byte = '\r'; utf8_buffer[1] = '\0'; break; case 'u': utf8_buffer[0] = '\\'; utf8_buffer[1] = 'u'; utf8_buffer[2] = '\0'; break; case 'U': utf8_buffer[0] = '\\'; utf8_buffer[1] = 'U'; utf8_buffer[2] = '\0'; break; case '\\': utf8_buffer[0] = byte = '\\'; utf8_buffer[1] = '\0'; break; } else { if (!misc->ignore_quotes) { /* Manage double quotes. */ /* """"""""""""""""""""" */ if (byte == '"' && !is_squote) is_dquote = !is_dquote; /* Manage single quotes. */ /* """"""""""""""""""""" */ if (byte == '\'' && !is_dquote) is_squote = !is_squote; } } /* Only consider delimiters when outside quotations. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if ((!is_dquote && !is_squote) && ll_find(word_delims_list, utf8_buffer, buffer_cmp) != NULL) break; if (!misc->ignore_quotes) { /* We no dot count the significant quotes. */ /* """"""""""""""""""""""""""""""""""""""" */ if (!is_special && ((byte == '"' && !is_squote) || (byte == '\'' && !is_dquote))) { is_special = 0; goto next; } } /* Feed temp with the content of utf8_buffer. */ /* """""""""""""""""""""""""""""""""""""""""" */ while (utf8_buffer[i] != '\0') { if (utf8_count >= wordsize - 1) temp = xrealloc(temp, wordsize += (utf8_count / CHARSCHUNK + 1) * CHARSCHUNK); *(temp + utf8_count++) = utf8_buffer[i]; i++; } is_special = 0; next: byte = get_bytes(input, utf8_buffer, zapped_glyphs_list, langinfo, misc); } /* Nul-terminate the word to make it a string. */ /* """"""""""""""""""""""""""""""""""""""""""" */ *(temp + utf8_count) = '\0'; /* Replace the UTF-8 ASCII representations in the word just */ /* read by their binary values. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_interpret(temp, langinfo, misc->invalid_char_substitute); /* Skip all field delimiters before a record delimiter. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ll_find(record_delims_list, utf8_buffer, buffer_cmp) == NULL) { byte = get_bytes(input, utf8_buffer, zapped_glyphs_list, langinfo, misc); while (byte != EOF && ll_find(word_delims_list, utf8_buffer, buffer_cmp) != NULL && ll_find(record_delims_list, utf8_buffer, buffer_cmp) == NULL) byte = get_bytes(input, utf8_buffer, zapped_glyphs_list, langinfo, misc); if (langinfo->utf8 && utf8_get_length(utf8_buffer[0]) > 1) { size_t pos; pos = strlen(utf8_buffer); while (pos > 0) my_ungetc(utf8_buffer[--pos]); } else my_ungetc(byte); } /* Mark it as the last word of a record if its sequence matches a */ /* record delimiter. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (byte == EOF || ((win->col_mode || win->line_mode || win->tab_mode) && ll_find(record_delims_list, utf8_buffer, buffer_cmp) != NULL)) *is_last = 1; else *is_last = 0; /* Remove the ANSI color escape sequences from the word. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ strip_ansi_color(temp, toggles, misc); return temp; } /* ================================================================ */ /* Convert the 8 first colors from setf/setaf coding to setaf/setf. */ /* ================================================================ */ short color_transcode(short color) { switch (color) { case 1: return 4; case 3: return 6; case 4: return 1; case 6: return 3; default: return color; } } /* ========================================================== */ /* Set a foreground color according to terminal capabilities. */ /* ========================================================== */ void set_foreground_color(term_t * term, short color) { if (term->color_method == 0) { if (term->has_setf) tputs(TPARM2(set_foreground, color), 1, outch); if (term->has_setaf) tputs(TPARM2(set_a_foreground, color_transcode(color)), 1, outch); } else if (term->color_method == 1) { if (term->has_setaf) tputs(TPARM2(set_a_foreground, color), 1, outch); if (term->has_setf) tputs(TPARM2(set_foreground, color_transcode(color)), 1, outch); } } /* ========================================================== */ /* Set a background color according to terminal capabilities. */ /* ========================================================== */ void set_background_color(term_t * term, short color) { if (term->color_method == 0) { if (term->has_setb) tputs(TPARM2(set_background, color), 1, outch); if (term->has_setab) tputs(TPARM2(set_a_background, color_transcode(color)), 1, outch); } else if (term->color_method == 1) { if (term->has_setab) tputs(TPARM2(set_a_background, color), 1, outch); if (term->has_setb) tputs(TPARM2(set_background, color_transcode(color)), 1, outch); } } /* ======================================================= */ /* Put a scrolling symbol at the first column of the line. */ /* ======================================================= */ void left_margin_putp(char * s, term_t * term, win_t * win) { apply_attr(term, win->shift_attr); /* We won't print this symbol when not in column mode. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ if (*s != '\0') fputs(s, stdout); tputs(TPARM1(exit_attribute_mode), 1, outch); } /* ====================================================== */ /* Put a scrolling symbol at the last column of the line. */ /* ====================================================== */ void right_margin_putp(char * s1, char * s2, langinfo_t * langinfo, term_t * term, win_t * win, long line, long offset) { apply_attr(term, win->bar_attr); if (term->has_hpa) tputs(TPARM2(column_address, offset + win->max_width + 1), 1, outch); else if (term->has_cursor_address) tputs(TPARM3(cursor_address, term->curs_line + line - 2, offset + win->max_width + 1), 1, outch); else if (term->has_parm_right_cursor) { fputc('\r', stdout); tputs(TPARM2(parm_right_cursor, offset + win->max_width + 1), 1, outch); } else { long i; fputc('\r', stdout); for (i = 0; i < offset + win->max_width + 1; i++) tputs(TPARM1(cursor_right), 1, outch); } if (langinfo->utf8) fputs(s1, stdout); else fputs(s2, stdout); tputs(TPARM1(exit_attribute_mode), 1, outch); } /* *************** */ /* Core functions. */ /* *************** */ /* ============================================================== */ /* Split the lines of the message given to -m to a linked list of */ /* lines. */ /* Also fill the maximum screen width and the maximum number */ /* of bytes of the longest line. */ /* ============================================================== */ void get_message_lines(char * message, ll_t * message_lines_list, long * message_max_width, long * message_max_len) { char * str; char * ptr; char * cr_ptr; long n; wchar_t * w = NULL; *message_max_width = 0; *message_max_len = 0; ptr = message; /* For each line terminated with a EOL character. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ while (*ptr != '\0' && (cr_ptr = strchr(ptr, '\n')) != NULL) { if (cr_ptr > ptr) { str = xmalloc(cr_ptr - ptr + 1); str[cr_ptr - ptr] = '\0'; memcpy(str, ptr, cr_ptr - ptr); } else str = xstrdup(""); ll_append(message_lines_list, str); /* If needed, update the message maximum width. */ /* """""""""""""""""""""""""""""""""""""""""""" */ n = wcswidth((w = utf8_strtowcs(str)), utf8_strlen(str)); free(w); if (n > *message_max_width) *message_max_width = n; /* If needed, update the message maximum number */ /* of bytes used by the longest line. */ /* """""""""""""""""""""""""""""""""""""""""""" */ if ((n = (long)strlen(str)) > *message_max_len) *message_max_len = n; ptr = cr_ptr + 1; } /* For the last line. */ /* """""""""""""""""" */ if (*ptr != '\0') { ll_append(message_lines_list, xstrdup(ptr)); n = wcswidth((w = utf8_strtowcs(ptr)), utf8_strlen(ptr)); free(w); if (n > *message_max_width) *message_max_width = n; /* If needed, update the message maximum number */ /* of bytes used by the longest line. */ /* """""""""""""""""""""""""""""""""""""""""""" */ if ((n = (long)strlen(ptr)) > *message_max_len) *message_max_len = n; } else ll_append(message_lines_list, xstrdup("")); } /* =================================================================== */ /* Set the new start and the new end of the window structure according */ /* to the current cursor position. */ /* =================================================================== */ void set_win_start_end(win_t * win, long current, long last) { long cur_line, end_line; cur_line = line_nb_of_word_a[current]; if (cur_line == last) win->end = count - 1; else { /* In help mode we must not modify the windows start/end position as */ /* It must be redrawn exactly as it was before. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!help_mode) { if (cur_line + win->max_lines / 2 + 1 <= last) win->end = first_word_in_line_a[cur_line + win->max_lines / 2 + 1] - 1; else win->end = first_word_in_line_a[last]; } } end_line = line_nb_of_word_a[win->end]; if (end_line < win->max_lines) win->start = 0; else win->start = first_word_in_line_a[end_line - win->max_lines + 1]; } /* ======================================================================== */ /* Set the metadata associated with a word, its starting and ending */ /* position, the line in which it is put and so on. */ /* Set win.start win.end and the starting and ending position of each word. */ /* This function is only called initially, when resizing the terminal and */ /* potentially when the search function is used. */ /* ======================================================================== */ long build_metadata(term_t * term, long count, win_t * win) { long i = 0; long word_len; long len = 0; long last = 0; long word_width; long tab_count; /* Current number of words in the line, * * used in tab_mode. */ wchar_t * w; line_nb_of_word_a[0] = 0; first_word_in_line_a[0] = 0; /* In column mode we need to calculate win->max_width, first initialize */ /* it to 0 and increment it later in the loop. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!win->col_mode) win->max_width = 0; tab_count = 0; while (i < count) { /* Determine the number of screen positions used by the word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ word_len = mbstowcs(NULL, word_a[i].str, 0); word_width = wcswidth((w = utf8_strtowcs(word_a[i].str)), word_len); /* Manage the case where the word is larger than the terminal width. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_width >= term->ncolumns - 2) { /* Shorten the word until it fits. */ /* """"""""""""""""""""""""""""""" */ do { word_width = wcswidth(w, word_len--); } while (word_len > 0 && word_width >= term->ncolumns - 2); } free(w); /* Look if there is enough remaining place on the line when not in */ /* column mode. Force a break if the 'is_last' flag is set in all */ /* modes or if we hit the max number of allowed columns in tab mode. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if ((!win->col_mode && !win->line_mode && (len + word_width + 1) >= term->ncolumns - 1) || ((win->col_mode || win->line_mode || win->tab_mode) && i > 0 && word_a[i - 1].is_last) || (win->tab_mode && win->max_cols > 0 && tab_count >= win->max_cols)) { /* We must build another line. */ /* """"""""""""""""""""""""""" */ line_nb_of_word_a[i] = ++last; first_word_in_line_a[last] = i; word_a[i].start = 0; len = word_width + 1; /* Resets the current line length. */ tab_count = 1; /* Resets the current number of words * * in the line. */ word_a[i].end = word_width - 1; word_a[i].mb = word_len; } else { word_a[i].start = len; word_a[i].end = word_a[i].start + word_width - 1; word_a[i].mb = word_len; line_nb_of_word_a[i] = last; len += word_width + 1; /* Increase line length. */ tab_count++; /* We've seen another word in the line/ */ } /* If not in column mode, we need to calculate win->(real_)max_width */ /* as it hasn't been already done. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (len > win->max_width) { if (len > term->ncolumns) win->max_width = term->ncolumns - 2; else win->max_width = len; } if (len > win->real_max_width) win->real_max_width = len; i++; } if (!win->center || win->max_width > term->ncolumns - 2) win->offset = 0; else win->offset = (term->ncolumns - 2 - win->max_width) / 2; /* We need to recalculate win->start and win->end here */ /* because of a possible terminal resizing. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ set_win_start_end(win, current, last); return last; } /* ==================================================================== */ /* Helper function used by disp_word to print a matching word under the */ /* cursor when not in search mode with the matching characters of the */ /* word highlighted. */ /* ==================================================================== */ void disp_cursor_word(long pos, win_t * win, term_t * term, int err) { size_t i; int att_set = 0; char * p = word_a[pos].str + daccess.flength; char * np; /* Set the cursor attribute. */ /* """"""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); tputs(TPARM1(exit_attribute_mode), 1, outch); if (word_a[pos].is_tagged) apply_attr(term, win->cursor_on_tag_attr); else apply_attr(term, win->cursor_attr); for (i = 0; i < word_a[pos].mb - daccess.flength; i++) { if (BIT_ISSET(word_a[pos].bitmap, i)) { if (!att_set) { att_set = 1; /* Set the buffer display attribute. */ /* """"""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); if (err) apply_attr(term, win->match_err_text_attr); else apply_attr(term, win->match_text_attr); if (word_a[pos].is_tagged) apply_attr(term, win->cursor_on_tag_attr); else apply_attr(term, win->cursor_attr); } } else { if (att_set) { att_set = 0; /* Set the search cursor attribute. */ /* """""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); if (word_a[pos].is_tagged) apply_attr(term, win->cursor_on_tag_attr); else apply_attr(term, win->cursor_attr); } } np = utf8_next(p); if (np == NULL) fputs(p, stdout); else printf("%.*s", (int)(np - p), p); p = np; } } /* ==================================================================== */ /* Helper function used by disp_word to print a matching word NOT under */ /* the cursor with the matching characters of the word highlighted. */ /* ==================================================================== */ void disp_matching_word(long pos, win_t * win, term_t * term, int is_cursor, int err) { size_t i; int att_set = 0; char * p = word_a[pos].str + daccess.flength; char * np; /* Set the search cursor attribute. */ /* """""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); if (is_cursor) { if (err) apply_attr(term, win->match_err_field_attr); else apply_attr(term, win->match_field_attr); } else { if (err) apply_attr(term, win->search_err_field_attr); else apply_attr(term, win->search_field_attr); } if (word_a[pos].is_tagged) apply_attr(term, win->tag_attr); for (i = 0; i < word_a[pos].mb - daccess.flength; i++) { if (BIT_ISSET(word_a[pos].bitmap, i)) { if (!att_set) { att_set = 1; /* Set the buffer display attribute. */ /* """"""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); if (is_cursor) { if (err) apply_attr(term, win->match_err_text_attr); else apply_attr(term, win->match_text_attr); } else apply_attr(term, win->search_text_attr); if (word_a[pos].is_tagged) apply_attr(term, win->tag_attr); } } else { if (att_set) { att_set = 0; /* Set the search cursor attribute. */ /* """""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); if (is_cursor) { if (err) apply_attr(term, win->match_err_field_attr); else apply_attr(term, win->match_field_attr); } else { if (err) apply_attr(term, win->search_err_field_attr); else apply_attr(term, win->search_field_attr); } if (word_a[pos].is_tagged) apply_attr(term, win->tag_attr); } } np = utf8_next(p); if (np == NULL) fputs(p, stdout); else printf("%.*s", (int)(np - p), p); p = np; } } /* ====================================================================== */ /* Display a word in, the windows. Manages the following different cases: */ /* - Search mode display */ /* - Cursor display */ /* - Normal display */ /* - Color or mono display */ /* ====================================================================== */ void disp_word(long pos, search_mode_t search_mode, search_data_t * search_data, term_t * term, win_t * win, char * tmp_word) { long s = word_a[pos].start; long e = word_a[pos].end; long p; char * buffer = search_data->buf; if (pos == current) { if (search_mode != NONE) { utf8_strprefix(tmp_word, word_a[pos].str, (long)word_a[pos].mb, &p); if (word_a[pos].is_numbered) { /* Set the direct access number attribute. */ /* """"""""""""""""""""""""""""""""""""""" */ apply_attr(term, win->daccess_attr); /* And print it. */ /* """"""""""""" */ fputs(daccess.left, stdout); printf("%.*s", daccess.length, tmp_word + 1); fputs(daccess.right, stdout); tputs(TPARM1(exit_attribute_mode), 1, outch); fputc(' ', stdout); } else if (daccess.length > 0) { /* Prints the leading spaces. */ /* """""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); printf("%.*s", daccess.flength, tmp_word); } /* Set the search cursor attribute. */ /* """""""""""""""""""""""""""""""" */ if (search_data->fuzzy_err) apply_attr(term, win->search_err_field_attr); else apply_attr(term, win->search_field_attr); /* The tab attribute must complete the attributes already set. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[pos].is_tagged) apply_attr(term, win->tag_attr); /* Print the word part. */ /* """""""""""""""""""" */ fputs(tmp_word + daccess.flength, stdout); if (buffer[0] != '\0') { long i = 0; /* Put the cursor at the beginning of the word. */ /* """""""""""""""""""""""""""""""""""""""""""" */ for (i = 0; i < e - s + 1 - daccess.flength; i++) tputs(TPARM1(cursor_left), 1, outch); tputs(TPARM1(exit_attribute_mode), 1, outch); /* Set the search cursor attribute. */ /* """""""""""""""""""""""""""""""" */ if (search_data->fuzzy_err) apply_attr(term, win->search_err_field_attr); else apply_attr(term, win->search_field_attr); disp_matching_word(pos, win, term, 0, search_data->fuzzy_err); } } else { if (daccess.length > 0) { /* If this word is not numbered, reset the display */ /* attributes before printing the leading spaces. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ if (!word_a[pos].is_numbered) { /* Print the non significant part of the word. */ /* """"""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); printf("%.*s", daccess.flength - 1, word_a[pos].str); tputs(TPARM1(exit_attribute_mode), 1, outch); fputc(' ', stdout); } else { apply_attr(term, win->daccess_attr); /* Print the non significant part of the word. */ /* """"""""""""""""""""""""""""""""""""""""""" */ fputs(daccess.left, stdout); printf("%.*s", daccess.length, word_a[pos].str + 1); fputs(daccess.right, stdout); tputs(TPARM1(exit_attribute_mode), 1, outch); fputc(' ', stdout); } } /* If we are not in search mode, display a normal cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_strprefix(tmp_word, word_a[pos].str, (long)word_a[pos].mb, &p); if (word_a[pos].is_matching) disp_cursor_word(pos, win, term, search_data->fuzzy_err); else { if (word_a[pos].is_tagged) apply_attr(term, win->cursor_on_tag_attr); else apply_attr(term, win->cursor_attr); fputs(tmp_word + daccess.flength, stdout); } } tputs(TPARM1(exit_attribute_mode), 1, outch); } else { /* Display a normal word without any attribute. */ /* """""""""""""""""""""""""""""""""""""""""""" */ utf8_strprefix(tmp_word, word_a[pos].str, (long)word_a[pos].mb, &p); /* If words are numbered, emphasis their numbers. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[pos].is_numbered) { apply_attr(term, win->daccess_attr); fputs(daccess.left, stdout); printf("%.*s", daccess.length, tmp_word + 1); fputs(daccess.right, stdout); tputs(TPARM1(exit_attribute_mode), 1, outch); fputc(' ', stdout); } else if (daccess.length > 0) { long i; /* Insert leading spaces if the word is non numbered and */ /* padding for all words is set. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(exit_attribute_mode), 1, outch); if (daccess.padding == 'a') for (i = 0; i < daccess.flength; i++) fputc(' ', stdout); } if (!word_a[pos].is_selectable) apply_attr(term, win->exclude_attr); else if (word_a[pos].special_level > 0) { long level = word_a[pos].special_level - 1; apply_attr(term, win->special_attr[level]); } else apply_attr(term, win->include_attr); if (word_a[pos].is_matching) disp_matching_word(pos, win, term, 1, search_data->fuzzy_err); else { if (word_a[pos].is_tagged) apply_attr(term, win->tag_attr); if ((daccess.length > 0 && daccess.padding == 'a') || word_a[pos].is_numbered) fputs(tmp_word + daccess.flength, stdout); else fputs(tmp_word, stdout); } tputs(TPARM1(exit_attribute_mode), 1, outch); } } /* ======================================== */ /* Display a message line above the window. */ /* ======================================== */ void disp_message(ll_t * message_lines_list, long message_max_width, long message_max_len, term_t * term, win_t * win, langinfo_t * langinfo) { ll_node_t * node; char * line; char * buf; size_t len; long size; long offset; wchar_t * w; int n = 0; /* Counter used to display message lines. */ int cut = 0; /* Will be 1 if the message is shortened. */ sigset_t mask; win->message_lines = 0; /* Do nothing if there is no message to display. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (message_lines_list == NULL) return; /* Recalculate the number of to-be-displayed lines in the messages */ /* if space is missing. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (term->nlines < 3) return; win->message_lines = message_lines_list->len; if (win->message_lines > term->nlines - 2) { win->message_lines = term->nlines - 2; win->max_lines = term->nlines - win->message_lines - 1; cut = 1; } win->message_lines++; /* Deactivate the periodic timer to prevent the interruptions to corrupt */ /* screen by altering the timing of the decoding of the terminfo */ /* capabilities. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ sigemptyset(&mask); sigaddset(&mask, SIGALRM); sigprocmask(SIG_BLOCK, &mask, NULL); node = message_lines_list->head; buf = xmalloc(message_max_len + 1); /* Follow the message lines list and display each line. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ for (n = 1; n < win->message_lines; n++) { long i; line = node->data; len = utf8_strlen(line); w = utf8_strtowcs(line); /* Adjust size and len if the terminal is not large enough. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ size = wcswidth(w, len); while (len > 0 && size > term->ncolumns) size = wcswidth(w, --len); free(w); /* Compute the offset from the left screen border if -M option is set. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ offset = (term->ncolumns - message_max_width - 3) / 2; if (win->center && offset > 0) for (i = 0; i < offset; i++) fputc(' ', stdout); apply_attr(term, win->message_attr); /* Only print the start of a line if the screen width if too small. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_strprefix(buf, line, len, &size); /* Print the line without the ending \n. */ /* ''''''''''''''''''''''''''''''''''''' */ if (n > 1 && cut && n == win->message_lines - 1) { if (langinfo->utf8) fputs(msg_arr_down, stdout); else fputc('v', stdout); } else printf("%s", buf); /* Complete the short line with spaces until it reach the */ /* message max size. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''' */ for (i = size; i < message_max_width; i++) { if (i + (offset < 0 ? 0 : offset) >= term->ncolumns) break; fputc(' ', stdout); } /* Drop the attributes and print a \n. */ /* ''''''''''''''''''''''''''''''''''' */ if (term->nlines > 2) { tputs(TPARM1(exit_attribute_mode), 1, outch); puts(""); } node = node->next; } /* Add an empty line without attribute to separate the menu title */ /* and the menu content. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ puts(""); free(buf); /* Re-enable the periodic timer. */ /* """"""""""""""""""""""""""""" */ sigprocmask(SIG_UNBLOCK, &mask, NULL); } /* ============================= */ /* Display the selection window. */ /* ============================= */ long disp_lines(win_t * win, toggle_t * toggles, long current, long count, search_mode_t search_mode, search_data_t * search_data, term_t * term, long last_line, char * tmp_word, langinfo_t * langinfo) { long lines_disp; long i; char scroll_symbol[5]; long len; long display_bar; sigset_t mask; /* Disable the periodic timer to prevent the interruptions to corrupt */ /* screen by altering the timing of the decoding of the terminfo */ /* capabilities. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ sigemptyset(&mask); sigaddset(&mask, SIGALRM); sigprocmask(SIG_BLOCK, &mask, NULL); scroll_symbol[0] = ' '; scroll_symbol[1] = '\0'; lines_disp = 1; tputs(TPARM1(save_cursor), 1, outch); i = win->start; /* Modify the max number of displayed lines if we do not have */ /* enough place. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win->max_lines > term->nlines - win->message_lines) win->max_lines = term->nlines - win->message_lines; if (last_line >= win->max_lines) display_bar = 1; else display_bar = 0; if (win->col_mode || win->line_mode) len = term->ncolumns - 3; else len = term->ncolumns - 2; /* If in column mode and the sum of the columns sizes + gutters is */ /* greater than the terminal width, then prepend a space to be able to */ /* display the left arrow indicating that the first displayed column */ /* is not the first one. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (len > 1 && ((win->col_mode || win->line_mode) && win->real_max_width > term->ncolumns - 2)) { if (win->first_column > 0) { if (langinfo->utf8) strcpy(scroll_symbol, shift_left_sym); else strcpy(scroll_symbol, "<"); } } else scroll_symbol[0] = '\0'; /* Center the display ? */ /* """""""""""""""""""" */ if (win->offset > 0) { long i; for (i = 0; i < win->offset; i++) fputc(' ', stdout); } left_margin_putp(scroll_symbol, term, win); while (len > 1 && i <= count - 1) { /* Display one word and the space or symbol following it. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[i].start >= win->first_column && word_a[i].end < len + win->first_column) { disp_word(i, search_mode, search_data, term, win, tmp_word); /* If there are more element to be displayed after the right margin. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if ((win->col_mode || win->line_mode) && i < count - 1 && word_a[i + 1].end >= len + win->first_column) { apply_attr(term, win->shift_attr); if (langinfo->utf8) fputs(shift_right_sym, stdout); else fputc('>', stdout); tputs(TPARM1(exit_attribute_mode), 1, outch); } /* If we want to display the gutter. */ /* """"""""""""""""""""""""""""""""" */ else if (!word_a[i].is_last && win->col_sep && (win->tab_mode || win->col_mode)) { long pos; /* Make sure that we are using the right gutter character even */ /* if the first displayed word is * not the first of its line. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ pos = i - first_word_in_line_a[line_nb_of_word_a[i]]; if (pos >= win->gutter_nb) /* Use the last gutter character. */ fputs(win->gutter_a[win->gutter_nb - 1], stdout); else fputs(win->gutter_a[pos], stdout); } else /* Else just display a space. */ /* """""""""""""""""""""""""" */ fputc(' ', stdout); } /* Mark the line as the current line, the line containing the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (i == current) win->cur_line = lines_disp; /* Check if we must start a new line. */ /* """""""""""""""""""""""""""""""""" */ if (i == count - 1 || word_a[i + 1].start == 0) { tputs(TPARM1(clr_eol), 1, outch); if (lines_disp < win->max_lines) { /* If we have more than one line to display. */ /* """"""""""""""""""""""""""""""""""""""""" */ if (display_bar && !toggles->no_scrollbar && (lines_disp > 1 || i < count - 1)) { /* Display the next element of the scrollbar. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (line_nb_of_word_a[i] == 0) { if (win->max_lines > 1) right_margin_putp(sbar_top, "\\", langinfo, term, win, lines_disp, win->offset); else right_margin_putp(sbar_arr_down, "^", langinfo, term, win, lines_disp, win->offset); } else if (lines_disp == 1) right_margin_putp(sbar_arr_up, "^", langinfo, term, win, lines_disp, win->offset); else if (line_nb_of_word_a[i] == last_line) { if (win->max_lines > 1) right_margin_putp(sbar_down, "/", langinfo, term, win, lines_disp, win->offset); else right_margin_putp(sbar_arr_up, "^", langinfo, term, win, lines_disp, win->offset); } else if (last_line + 1 > win->max_lines && (long)((float)(line_nb_of_word_a[current]) / (last_line + 1) * (win->max_lines - 2) + 2) == lines_disp) right_margin_putp(sbar_curs, "+", langinfo, term, win, lines_disp, win->offset); else right_margin_putp(sbar_line, "|", langinfo, term, win, lines_disp, win->offset); } /* Print a newline character if we are not at the end of */ /* the input nor at the end of the window. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (i < count - 1 && lines_disp < win->max_lines) { fputc('\n', stdout); if (win->offset > 0) { long i; for (i = 0; i < win->offset; i++) fputc(' ', stdout); } left_margin_putp(scroll_symbol, term, win); } /* We do not increment the number of lines seen after */ /* a premature end of input. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (i < count - 1) lines_disp++; if (win->max_lines == 1) break; } else if (i <= count - 1 && lines_disp == win->max_lines) { /* The last line of the window has been displayed. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ if (display_bar && line_nb_of_word_a[i] == last_line) { if (!toggles->no_scrollbar) { if (win->max_lines > 1) right_margin_putp(sbar_down, "/", langinfo, term, win, lines_disp, win->offset); else right_margin_putp(sbar_arr_up, "^", langinfo, term, win, lines_disp, win->offset); } } else { if (display_bar && !toggles->no_scrollbar) right_margin_putp(sbar_arr_down, "v", langinfo, term, win, lines_disp, win->offset); break; } } else /* These lines were not in the widows and so we have nothing to do. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ break; } /* Next word. */ /* """""""""" */ i++; } /* Update win->end, this is necessary because we only */ /* call build_metadata on start and on terminal resize. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (i == count) win->end = i - 1; else win->end = i; /* We restore the cursor position saved before the display of the window. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(restore_cursor), 1, outch); /* Re-enable the periodic timer. */ /* """"""""""""""""""""""""""""" */ sigprocmask(SIG_UNBLOCK, &mask, NULL); return lines_disp; } /* ============================================= */ /* Signal handler. Manages SIGWINCH and SIGALRM. */ /* ============================================= */ void sig_handler(int s) { switch (s) { /* Standard termination signals. */ /* """"""""""""""""""""""""""""" */ case SIGSEGV: got_sigsegv = 1; break; case SIGTERM: got_sigterm = 1; break; case SIGHUP: got_sighup = 1; break; /* Terminal resize. */ /* """""""""""""""" */ case SIGWINCH: got_winch = 1; break; /* Alarm triggered, This signal is used by the search mechanism to */ /* forces a window refresh. */ /* The help mechanism uses it to clear the message */ /* It is also used to redisplay the window after the end of a terminal */ /* resizing. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ case SIGALRM: if (timeout.initial_value > 0) got_timeout_tick = 1; if (help_timer > 0) help_timer--; if (help_timer == 0 && help_mode) got_help_alrm = 1; if (daccess_timer > 0) daccess_timer--; if (daccess_timer == 0) got_daccess_alrm = 1; if (winch_timer > 0) winch_timer--; if (winch_timer == 0) { got_winch = 0; got_help_alrm = 0; got_winch_alrm = 1; } if (search_timer > 0) search_timer--; if (search_timer == 0 && search_mode != NONE) got_search_alrm = 1; break; } } /* ========================================================= */ /* Set new first column to display when horizontal scrolling */ /* Alter win->first_column. */ /* ========================================================= */ void set_new_first_column(win_t * win, term_t * term) { long pos; if (word_a[current].start < win->first_column) { pos = current; while (win->first_column > 0 && word_a[current].start < win->first_column) { win->first_column = word_a[pos].start; pos--; } } else if (word_a[current].end - win->first_column >= term->ncolumns - 3) { pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (!word_a[pos].is_last && word_a[current].end - win->first_column >= term->ncolumns - 3) { pos++; win->first_column = word_a[pos].start; } } } /* ===================================================== */ /* Restrict the matches to word ending with the pattern. */ /* ===================================================== */ void select_ending_matches(win_t * win, term_t * term, search_data_t * search_data, long * last_line) { if (matches_count > 0) { long i; long j = 0; long index; long nb; long * tmp; char * ptr; char * last_glyph; int utf8_len; /* Creation of an alternate array which will */ /* contain only the candidates having potentially */ /* an ending pattern, if this array becomes non */ /* empty then it will replace the original array. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ alt_matching_words_a = xrealloc(alt_matching_words_a, matches_count * (sizeof(long))); for (i = 0; i < matches_count; i++) { index = matching_words_a[i]; char * str = word_a[index].str; /* count the trailing blanks non counted in the bitmap. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ ptr = str + strlen(str); nb = 0; while ((ptr = utf8_prev(str, ptr)) != NULL && isblank(*ptr)) if (ptr - str > 0) nb++; else break; /* Check the bit corresponding to the last non blank glyph */ /* If set we add the index to an alternate array, if not we */ /* clear the bitmap of the corresponding word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (BIT_ISSET(word_a[index].bitmap, word_a[index].mb - nb - daccess.flength - 1)) alt_matching_words_a[j++] = index; else { /* Look if the end of the word potentially contain an */ /* ending pattern. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (search_mode == FUZZY) { utf8_len = mblen(ptr, 4); last_glyph = search_data->buf + search_data->len - utf8_len; /* in fuzzy search mode we only look the last glyph. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if (memcmp(ptr, last_glyph, utf8_len) == 0) alt_matching_words_a[j++] = index; else memset(word_a[index].bitmap, '\0', (word_a[index].mb - daccess.flength) / CHAR_BIT + 1); } else { /* in not fuzzy search mode use all the pattern. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ for (nb = 0; nb < search_data->utf8_len - 1; nb++) ptr = utf8_prev(str, ptr); if (memcmp(ptr, search_data->buf, search_data->len) == 0) alt_matching_words_a[j++] = index; else memset(word_a[index].bitmap, '\0', (word_a[index].mb - daccess.flength) / CHAR_BIT + 1); } } } /* Swap the normal and alt array. */ /* """""""""""""""""""""""""""""" */ matches_count = j; matching_words_a_size = j; tmp = matching_words_a; matching_words_a = alt_matching_words_a; alt_matching_words_a = tmp; if (j > 0) { /* Adjust the bitmap to the ending version. */ /* """""""""""""""""""""""""""""""""""""""" */ update_bitmaps(search_mode, search_data, END_AFFINITY); current = matching_words_a[0]; if (current < win->start || current > win->end) *last_line = build_metadata(term, count, win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(win, term); } } } /* ======================================================= */ /* Restrict the matches to word starting with the pattern. */ /* ======================================================= */ void select_starting_matches(win_t * win, term_t * term, search_data_t * search_data, long * last_line) { if (matches_count > 0) { long i; long j = 0; long index; long nb; long * tmp; long pos; char * first_glyph; int utf8_len; alt_matching_words_a = xrealloc(alt_matching_words_a, matches_count * (sizeof(long))); first_glyph = xmalloc(5); for (i = 0; i < matches_count; i++) { index = matching_words_a[i]; for (nb = 0; nb < word_a[index].mb; nb++) if (!isblank(*(word_a[index].str + daccess.flength + nb))) break; if (BIT_ISSET(word_a[index].bitmap, nb)) alt_matching_words_a[j++] = index; else { if (search_mode == FUZZY) { first_glyph = utf8_strprefix(first_glyph, word_a[index].str + nb + daccess.flength, 1, &pos); utf8_len = pos; /* in fuzzy search mode we only look the first glyph. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (memcmp(search_data->buf, first_glyph, utf8_len) == 0) alt_matching_words_a[j++] = index; else memset(word_a[index].bitmap, '\0', (word_a[index].mb + nb - daccess.flength) / CHAR_BIT + 1); } else { /* in not fuzzy search mode use all the pattern. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (memcmp(search_data->buf, word_a[index].str + nb, search_data->len - nb) == 0) alt_matching_words_a[j++] = index; else memset(word_a[index].bitmap, '\0', (word_a[index].mb + nb - daccess.flength) / CHAR_BIT + 1); } } } free(first_glyph); matches_count = j; matching_words_a_size = j; tmp = matching_words_a; matching_words_a = alt_matching_words_a; alt_matching_words_a = tmp; if (j > 0) { /* Adjust the bitmap to the ending version. */ /* """""""""""""""""""""""""""""""""""""""" */ update_bitmaps(search_mode, search_data, START_AFFINITY); current = matching_words_a[0]; if (current < win->start || current > win->end) *last_line = build_metadata(term, count, win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(win, term); } } } /* ====================== */ /* Moves the cursor left. */ /* ====================== */ void move_left(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long last_line, char * tmp_word) { long old_current = current; long old_start = win->start; long old_first_column = win->first_column; long wi; /* Word index. */ do { if (current > 0) { /* Sets the new win->start and win->end if the cursor */ /* is at the beginning of the windows. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (current == win->start) if (win->start > 0) { for (wi = win->start - 1; wi >= 0 && word_a[wi].start != 0; wi--) { } win->start = wi; if (word_a[wi].str != NULL) win->start = wi; if (win->end < count - 1) { for (wi = win->end + 2; wi < count - 1 && word_a[wi].start != 0; wi++) { } if (word_a[wi].str != NULL) win->end = wi; } } /* In column mode we need to take care of the */ /* horizontal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (win->col_mode || win->line_mode) { long pos; if (word_a[current].start == 0) { long len; len = term->ncolumns - 3; pos = first_word_in_line_a[line_nb_of_word_a[current - 1]]; while (word_a[current - 1].end - win->first_column >= len) { win->first_column += word_a[pos].end - word_a[pos].start + 2; pos++; } } else if (word_a[current - 1].start < win->first_column) win->first_column = word_a[current - 1].start; } current--; } else break; } while (current != old_current && !word_a[current].is_selectable); /* The old settings need to be restored if the */ /* new current word is not selectable. */ /* """"""""""""""""""""""""""""""""""""""""""" */ if (!word_a[current].is_selectable) { current = old_current; win->start = old_start; if (win->col_mode || win->line_mode) win->first_column = old_first_column; } if (current != old_current) *nl = disp_lines(win, toggles, current, count, search_mode, search_data, term, last_line, tmp_word, langinfo); } /* ======================= */ /* Moves the cursor right. */ /* ======================= */ void move_right(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long last_line, char * tmp_word) { long old_current = current; long old_start = win->start; long old_first_column = win->first_column; long wi; /* word index */ do { if (current < count - 1) { /* Sets the new win->start and win->end if the cursor */ /* is at the end of the windows. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (current == win->end) if (win->start < count - 1 && win->end != count - 1) { for (wi = win->start + 1; wi < count - 1 && word_a[wi].start != 0; wi++) { } if (word_a[wi].str != NULL) win->start = wi; if (win->end < count - 1) { for (wi = win->end + 2; wi < count - 1 && word_a[wi].start != 0; wi++) { } if (word_a[wi].str != NULL) win->end = wi; } } /* In column mode we need to take care of the */ /* horizontal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (win->col_mode || win->line_mode) { if (word_a[current].is_last) win->first_column = 0; else { long pos; long len; len = term->ncolumns - 3; if (word_a[current + 1].end >= len + win->first_column) { /* Find the first word to be displayed in this line. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (word_a[pos].start <= win->first_column) pos++; pos--; /* If the new current word cannot be displayed, search */ /* the first word in the line that can be displayed by */ /* iterating on pos. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ while (word_a[current + 1].end - word_a[pos].start >= len) pos++; if (word_a[pos].start > 0) win->first_column = word_a[pos].start; } } } current++; } else break; } while (current != old_current && !word_a[current].is_selectable); /* The old settings need to be restored if the */ /* new current word is not selectable. */ /* """"""""""""""""""""""""""""""""""""""""""" */ if (!word_a[current].is_selectable) { current = old_current; win->start = old_start; if (win->col_mode || win->line_mode) win->first_column = old_first_column; } if (current != old_current) *nl = disp_lines(win, toggles, current, count, search_mode, search_data, term, last_line, tmp_word, langinfo); } /* ================================================================== */ /* Get the last word of a line after it has been formed to fit in the */ /* terminal. */ /* ================================================================== */ long get_line_last_word(long line, long last_line) { if (line == last_line) return count - 1; else return first_word_in_line_a[line + 1] - 1; } /* ==================================================================== */ /* Try to locate the best word in the target line when trying to move */ /* the cursor upward. */ /* returns 1 if a word has been found else 0. */ /* This function has the side effect to potentially change the value of */ /* the variable 'current' if an adequate word is found. */ /* ==================================================================== */ int find_best_word_upward(long last_word, long s, long e) { int found = 0; long index; long cursor; /* Look for the first word whose start position in the line is */ /* less or equal to the source word starting position. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ cursor = last_word; while (word_a[cursor].start > s) cursor--; /* In case no word is eligible, keep the cursor on */ /* the last word. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ if (cursor == last_word && word_a[cursor].start > 0) cursor--; /* Try to guess the best choice if we have multiple choices. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[cursor].end >= s && word_a[cursor].end - s >= e - word_a[cursor + 1].start) current = cursor; else { if (cursor < last_word) current = cursor + 1; else current = cursor; } /* If the word is not selectable, try to find a selectable word */ /* in the line. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!word_a[current].is_selectable) { index = 0; while (word_a[current - index].start > 0 && !word_a[current - index].is_selectable) index++; if (word_a[current - index].is_selectable) { current -= index; found = 1; } else { index = 0; while (current + index < last_word && !word_a[current + index].is_selectable) index++; if (word_a[current + index].is_selectable) { current += index; found = 1; } } } else found = 1; return found; } /* ==================================================================== */ /* Try to locate the best word in the target line when trying to move */ /* the cursor downward. */ /* returns 1 if a word has been found else 0. */ /* This function has the side effect to potentially change the value of */ /* the variable 'current' if an adequate word is found. */ /* ==================================================================== */ int find_best_word_downward(long last_word, long s, long e) { int found = 0; long index; long cursor; /* Look for the first word whose start position in the line is */ /* less or equal than the source word starting position. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ cursor = last_word; while (word_a[cursor].start > s) cursor--; /* In case no word is eligible, keep the cursor on */ /* the last word. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ if (cursor == last_word && word_a[cursor].start > 0) cursor--; /* Try to guess the best choice if we have multiple choices. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (cursor < count - 1 && word_a[cursor].end - s >= e - word_a[cursor + 1].start) current = cursor; else { if (cursor < count - 1) { if (cursor < last_word) current = cursor + 1; else current = cursor; } else current = count - 1; } /* If the word is not selectable, try to find a selectable word */ /* in ts line. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!word_a[current].is_selectable) { index = 0; while (word_a[current - index].start > 0 && !word_a[current - index].is_selectable) index++; if (word_a[current - index].is_selectable) { current -= index; found = 1; } else { index = 0; while (current + index < last_word && !word_a[current + index].is_selectable) index++; if (word_a[current + index].is_selectable) { current += index; found = 1; } } } else found = 1; return found; } /* ==================== */ /* Moves the cursor up. */ /* ==================== */ void move_up(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long page, long first_selectable, long last_line, char * tmp_word) { long line; /* The line being processed (target line). */ long start_line; /* The first line of the window. */ long cur_line; /* The line of the cursor. */ long nlines; /* Number of line in the window. */ long first_selectable_line; /* the line containing the first * * selectable word. */ long lines_skipped; /* The number of line between the target line and the * * first line containing a selectable word in case of * * exclusions. */ long last_word; /* The last word on the target line. */ long s, e; /* Starting and ending terminal position of a word. */ int found; /* 1 if a line could be fond else 0. */ /* Store the initial starting and ending positions of */ /* the word under the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ s = word_a[current].start; e = word_a[current].end; /* Identify the line number of the first window's line */ /* and the line number of the current line. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ start_line = line_nb_of_word_a[win->start]; cur_line = line_nb_of_word_a[current]; first_selectable_line = line_nb_of_word_a[first_selectable]; lines_skipped = 0; found = 0; nlines = win->max_lines < last_line + 1 ? win->max_lines : last_line + 1; /* initialise the target line. */ /* """"""""""""""""""""""""""" */ line = cur_line; /* Special case if the cursor is already in the line containing the */ /* first selectable word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (line == first_selectable_line) { /* we can't move the cursor up but we still can try to show the */ /* more non selectable words as we can. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (line <= start_line + nlines - 1 - page) { /* We are scrolling one line at a time and the cursor is not in */ /* the last line of the window. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (start_line - page > 0) /* There is enough remaining line to fill a window. */ /* '''''''''''''''''''''''''''''''''''''''''''''''' */ start_line -= page; else /* We cannot scroll further. */ /* ''''''''''''''''''''''''' */ start_line = 0; } else { /* The cursor is already in the last line of the windows. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (line >= nlines) /* There is enough remaining line to fill a window. */ /* '''''''''''''''''''''''''''''''''''''''''''''''' */ start_line = line - nlines + 1; else /* We cannot scroll further. */ /* ''''''''''''''''''''''''' */ start_line = 0; } } else { if (line - page < 0) { /* Trivial case, we are already on the first page */ /* just jump to the first selectable line. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ line = first_selectable_line; last_word = get_line_last_word(line, last_line); find_best_word_upward(last_word, s, e); } else { /* Temporarily move up one page. */ /* """"""""""""""""""""""""""""" */ line -= page; /* The target line cannot be before the line containing the first */ /* selectable word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (line < first_selectable_line) { line = first_selectable_line; last_word = get_line_last_word(line, last_line); find_best_word_upward(last_word, s, e); } else { /* If this is not the case, search upward for the line with a */ /* selectable word. This line is guaranteed to exist. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (line >= first_selectable_line) { last_word = get_line_last_word(line, last_line); if (find_best_word_upward(last_word, s, e)) { found = 1; break; } line--; lines_skipped++; } } } } /* Look if we need to adjust the window to follow the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!found && start_line - page >= 0) { /* We are on the first line containing a selectable word and */ /* There is enough place to scroll up a page but only scrolls */ /* up if the cursor remains in the window. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (start_line + nlines - line > page) start_line -= page; } else if (line < start_line) { /* The target line is above the windows. */ /* """"""""""""""""""""""""""""""""""""" */ if (start_line - page - lines_skipped < 0) /* There isn't enough remaining lines to scroll up */ /* a page size. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ start_line = 0; else start_line -= page + lines_skipped; } /* And set the new value of the starting word of the window. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ win->start = first_word_in_line_a[start_line]; /* Set the new first column to display */ /* """"""""""""""""""""""""""""""""""" */ set_new_first_column(win, term); /* Redisplay the window. */ /* """"""""""""""""""""" */ *nl = disp_lines(win, toggles, current, count, search_mode, search_data, term, last_line, tmp_word, langinfo); } /* ====================== */ /* Moves the cursor down. */ /* ====================== */ void move_down(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long page, long last_selectable, long last_line, char * tmp_word) { long line; /* The line being processed (target line). */ long start_line; /* The first line of the window. */ long cur_line; /* The line of the cursor. */ long nlines; /* Number of line in the window. */ long last_selectable_line; /* the line containing the last * * selectable word. */ long lines_skipped; /* The number of line between the target line and the * * first line containing a selectable word in case of * * exclusions. */ long last_word; /* The last word on the target line. */ long s, e; /* Starting and ending terminal position of a word. */ int found; /* 1 if a line could be fond in the next page else 0. */ /* Store the initial starting and ending positions of */ /* the word under the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ s = word_a[current].start; e = word_a[current].end; /* Identify the line number of the first window's line */ /* and the line number of the current line. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ start_line = line_nb_of_word_a[win->start]; cur_line = line_nb_of_word_a[current]; last_selectable_line = line_nb_of_word_a[last_selectable]; lines_skipped = 0; found = 0; nlines = win->max_lines < last_line + 1 ? win->max_lines : last_line + 1; /* initialise the target line. */ /* """"""""""""""""""""""""""" */ line = cur_line; /* Special case if the cursor is already in the line containing the */ /* last selectable word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (line == last_selectable_line) { /* we can't move the cursor down but we still can try to show the */ /* more non selectable words as we can. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (line >= start_line + page) { /* We are scrolling one line at a time and the cursor is not in */ /* the first line of the window. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (start_line + page + nlines - 1 <= last_line) /* There is enough remaining line to fill a window. */ /* '''''''''''''''''''''''''''''''''''''''''''''''' */ start_line += page; else /* We cannot scroll further. */ /* ''''''''''''''''''''''''' */ start_line = last_line - nlines + 1; } else { /* The cursor is already in the first line of the windows. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (last_line - line + 1 > nlines) /* There is enough remaining line to fill a window. */ /* '''''''''''''''''''''''''''''''''''''''''''''''' */ start_line = line; else /* We cannot scroll further. */ /* ''''''''''''''''''''''''' */ start_line = last_line - nlines + 1; } } else { /* The cursor is above the line containing the last selectable word. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (last_line - line - page < 0) { /* Trivial case, we are already on the last page */ /* just jump to the last selectable line. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ line = last_selectable_line; last_word = get_line_last_word(line, last_line); find_best_word_downward(last_word, s, e); } else { /* Temporarily move down one page. */ /* """"""""""""""""""""""""""""""" */ line += page; /* The target line cannot be before the line containing the first */ /* selectable word. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (line > last_selectable_line) { line = last_selectable_line; last_word = get_line_last_word(line, last_line); find_best_word_downward(last_word, s, e); } else { /* If this is not the case, search upward for the line with a */ /* selectable word. This line is guaranteed to exist. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (line <= last_selectable_line) { last_word = get_line_last_word(line, last_line); if (find_best_word_downward(last_word, s, e)) { found = 1; break; } line++; lines_skipped++; } } } /* Look if we need to adjust the window to follow the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!found && start_line + nlines - 1 + page <= last_line) { /* We are on the last line containing a selectable word and */ /* There is enough place to scroll down a page but only scrolls */ /* down if the cursor remains in the window. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (line - start_line >= page) start_line += page; } else if (line > start_line + nlines - 1) { /* The target line is below the windows. */ /* """"""""""""""""""""""""""""""""""""" */ if (start_line + nlines + page + lines_skipped - 1 > last_line) /* There isn't enough remaining lines to scroll down */ /* a page size. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ start_line = last_line - nlines + 1; else start_line += page + lines_skipped; } } /* And set the new value of the starting word of the window. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ win->start = first_word_in_line_a[start_line]; /* Set the new first column to display. */ /* """""""""""""""""""""""""""""""""""" */ set_new_first_column(win, term); /* Redisplay the window. */ /* """"""""""""""""""""" */ *nl = disp_lines(win, toggles, current, count, search_mode, search_data, term, last_line, tmp_word, langinfo); } /* ========================================= */ /* Initialize some internal data structures. */ /* ========================================= */ void init_main_ds(attrib_t * init_attr, win_t * win, limit_t * limits, ticker_t * timers, toggle_t * toggles, misc_t * misc, timeout_t * timeout, daccess_t * daccess) { int i; /* Initial attribute settings. */ /* """"""""""""""""""""""""""" */ init_attr->is_set = UNSET; init_attr->fg = -1; init_attr->bg = -1; init_attr->bold = -1; init_attr->dim = -1; init_attr->reverse = -1; init_attr->standout = -1; init_attr->underline = -1; init_attr->italic = -1; /* Win fields initialization. */ /* """""""""""""""""""""""""" */ win->max_lines = 5; win->message_lines = 0; win->asked_max_lines = -1; win->center = 0; win->max_cols = 0; win->col_sep = 0; win->wide = 0; win->tab_mode = 0; win->col_mode = 0; win->line_mode = 0; win->first_column = 0; win->real_max_width = 0; win->cursor_attr = *init_attr; win->cursor_on_tag_attr = *init_attr; win->bar_attr = *init_attr; win->shift_attr = *init_attr; win->message_attr = *init_attr; win->search_field_attr = *init_attr; win->search_text_attr = *init_attr; win->search_err_field_attr = *init_attr; win->search_err_text_attr = *init_attr; win->match_field_attr = *init_attr; win->match_text_attr = *init_attr; win->match_err_field_attr = *init_attr; win->match_err_text_attr = *init_attr; win->include_attr = *init_attr; win->exclude_attr = *init_attr; win->tag_attr = *init_attr; win->daccess_attr = *init_attr; win->sel_sep = NULL; for (i = 0; i < 5; i++) win->special_attr[i] = *init_attr; /* Default limits initialization. */ /* """""""""""""""""""""""""""""" */ limits->words = 32767; limits->cols = 256; limits->word_length = 512; /* Default timers in 1/10 s. */ /* """"""""""""""""""""""""" */ timers->search = 100 * FREQ / 10; timers->help = 150 * FREQ / 10; timers->winch = 20 * FREQ / 10; timers->direct_access = 6 * FREQ / 10; /* Toggles initialization. */ /* """"""""""""""""""""""" */ toggles->del_line = 0; toggles->enter_val_in_search = 0; toggles->no_scrollbar = 0; toggles->blank_nonprintable = 0; toggles->keep_spaces = 0; toggles->taggable = 0; toggles->autotag = 0; toggles->pinable = 0; toggles->visual_bell = 0; /* Misc default values. */ /* """""""""""""""""""" */ misc->default_search_method = NONE; misc->ignore_quotes = 0; /* Set the default timeout to 0 (no expiration). */ /* """"""""""""""""""""""""""""""""""""""""""""" */ timeout->initial_value = 0; timeout->remain = 0; timeout->reached = 0; /* Initialize Direct Access settings. */ /* """""""""""""""""""""""""""""""""" */ daccess->mode = DA_TYPE_NONE; daccess->left = xstrdup(" "); daccess->right = xstrdup(")"); daccess->alignment = 'r'; daccess->padding = 'a'; daccess->head = 'k'; /* Keep by default. */ daccess->length = -2; daccess->flength = 0; daccess->offset = 0; daccess->plus = 0; daccess->size = 0; daccess->ignore = 0; daccess->follow = 'y'; daccess->missing = 'y'; daccess->num_sep = NULL; daccess->def_number = -1; } /* *********************************** */ /* ctxopt contexts callback functions. */ /* *********************************** */ /* ******************************** */ /* ctxopt option callback function. */ /* ******************************** */ void help_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { if (strcmp(ctx_name, "Columns") == 0) columns_help(); else if (strcmp(ctx_name, "Lines") == 0) lines_help(); else if (strcmp(ctx_name, "Tabulations") == 0) tabulations_help(); else if (strcmp(ctx_name, "Tagging") == 0) tagging_help(); else main_help(); exit(EXIT_FAILURE); } void long_help_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { ctxopt_disp_usage(continue_after); printf("\nRead the manual for more information.\n"); exit(EXIT_FAILURE); } void usage_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { ctxopt_ctx_disp_usage(ctx_name, exit_after); } void lines_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; if (nb_values == 1) sscanf(values[0], "%ld", &(win->asked_max_lines)); else win->asked_max_lines = 0; } void tab_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; long max_cols; if (nb_values == 1) { sscanf(values[0], "%ld", &max_cols); /* Numericity and range were * * already checked by ctxopt. */ win->max_cols = max_cols; } win->tab_mode = 1; win->col_mode = 0; win->line_mode = 0; } void set_pattern_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { char ** pattern = opt_data[0]; langinfo_t * langinfo = opt_data[1]; misc_t * misc = opt_data[2]; *pattern = xstrdup(values[0]); utf8_interpret(*pattern, langinfo, misc->invalid_char_substitute); } void int_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { char ** string = opt_data[0]; int * shell_like = opt_data[1]; langinfo_t * langinfo = opt_data[2]; misc_t * misc = opt_data[3]; if (nb_values == 1) { *string = xstrdup(values[0]); if (!langinfo->utf8) utf8_sanitize(*string, misc->invalid_char_substitute); utf8_interpret(*string, langinfo, misc->invalid_char_substitute); } *shell_like = 0; } void set_string_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { char ** string = opt_data[0]; langinfo_t * langinfo = opt_data[1]; misc_t * misc = opt_data[2]; *string = xstrdup(values[0]); if (!langinfo->utf8) utf8_sanitize(*string, misc->invalid_char_substitute); utf8_interpret(*string, langinfo, misc->invalid_char_substitute); } void wide_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; win->wide = 1; } void center_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; win->center = 1; } void columns_select_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { int v; ll_t ** cols_selector_list = opt_data[0]; if (*cols_selector_list == NULL) *cols_selector_list = ll_new(); for (v = 0; v < nb_values; v++) ll_append(*cols_selector_list, xstrdup(values[v])); } void rows_select_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { int v; ll_t ** rows_selector_list = opt_data[0]; win_t * win = opt_data[1]; if (*rows_selector_list == NULL) *rows_selector_list = ll_new(); for (v = 0; v < nb_values; v++) ll_append(*rows_selector_list, xstrdup(values[v])); win->max_cols = 0; /* Disable the window column restriction. */ } void toggle_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { toggle_t * toggles = opt_data[0]; if (strcmp(opt_name, "clean") == 0) toggles->del_line = 1; else if (strcmp(opt_name, "keep_spaces") == 0) toggles->keep_spaces = 1; else if (strcmp(opt_name, "visual_bell") == 0) toggles->visual_bell = 1; else if (strcmp(opt_name, "validate_in_search_mode") == 0) toggles->enter_val_in_search = 1; else if (strcmp(opt_name, "blank_nonprintable") == 0) toggles->blank_nonprintable = 1; else if (strcmp(opt_name, "no_scroll_bar") == 0) toggles->no_scrollbar = 1; else if (strcmp(opt_name, "auto_tag") == 0) toggles->autotag = 1; } void invalid_char_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { misc_t * misc = opt_data[0]; char ic = *values[0]; if (isprint(ic)) misc->invalid_char_substitute = ic; else misc->invalid_char_substitute = '.'; } void gutter_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; langinfo_t * langinfo = opt_data[1]; misc_t * misc = opt_data[2]; if (nb_values == 0) { /* As there is no argument, the gutter array will only contain */ /* a vertical bar. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ win->gutter_a = xmalloc(1 * sizeof(char *)); if (langinfo->utf8) win->gutter_a[0] = xstrdup(vertical_bar); else win->gutter_a[0] = xstrdup("|"); win->gutter_nb = 1; } else { /* The argument is used to feed the gutter array, each of its character */ /* Will serve as gutter in a round-robin way. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ long n; wchar_t * w; long i, offset; int mblen; char * gutter; gutter = xstrdup(values[0]); utf8_interpret(gutter, langinfo, misc->invalid_char_substitute); /* Guarantees a well * * formed UTF-8 string/ */ win->gutter_nb = utf8_strlen(gutter); win->gutter_a = xmalloc(win->gutter_nb * sizeof(char *)); offset = 0; for (i = 0; i < win->gutter_nb; i++) { mblen = utf8_get_length(*(gutter + offset)); win->gutter_a[i] = xcalloc(1, mblen + 1); memcpy(win->gutter_a[i], gutter + offset, mblen); n = wcswidth((w = utf8_strtowcs(win->gutter_a[i])), 1); free(w); if (n > 1) { fprintf(stderr, "%s: A multi columns gutter is not allowed.\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } offset += mblen; } free(gutter); } win->col_sep = 1; /* Activate the gutter. */ } void column_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; win->tab_mode = 0; win->col_mode = 1; win->line_mode = 0; win->max_cols = 0; } void line_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; win->line_mode = 1; win->tab_mode = 0; win->col_mode = 0; win->max_cols = 0; } void include_re_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { int * pattern_def_include = opt_data[0]; char ** include_pattern = opt_data[1]; langinfo_t * langinfo = opt_data[2]; misc_t * misc = opt_data[3]; /* Set the default behaviour if not already set. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (*pattern_def_include == -1) *pattern_def_include = 0; if (*include_pattern == NULL) *include_pattern = concat("(", values[0], ")", (char *)0); else *include_pattern = concat(*include_pattern, "|(", values[0], ")", (char *)0); /* Replace the UTF-8 ASCII representations by their binary values in */ /* inclusion patterns. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_interpret(*include_pattern, langinfo, misc->invalid_char_substitute); } void exclude_re_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { int * pattern_def_exclude = opt_data[0]; char ** exclude_pattern = opt_data[1]; langinfo_t * langinfo = opt_data[2]; misc_t * misc = opt_data[3]; /* Set the default behaviour if not already set. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (*pattern_def_exclude == -1) *pattern_def_exclude = 0; if (*exclude_pattern == NULL) *exclude_pattern = concat("(", values[0], ")", (char *)0); else *exclude_pattern = concat(*exclude_pattern, "|(", values[0], ")", (char *)0); /* Replace the UTF-8 ASCII representations by their binary values in */ /* exclusion patterns. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ utf8_interpret(*exclude_pattern, langinfo, misc->invalid_char_substitute); } void post_subst_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { ll_t ** list = opt_data[0]; langinfo_t * langinfo = opt_data[1]; misc_t * misc = opt_data[2]; sed_t * sed_node; int i; if (*list == NULL) *list = ll_new(); for (i = 0; i < nb_values; i++) { sed_node = xmalloc(sizeof(sed_t)); sed_node->pattern = xstrdup(values[i]); utf8_interpret(sed_node->pattern, langinfo, misc->invalid_char_substitute); sed_node->stop = 0; ll_append(*list, sed_node); } } void special_level_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { char ** special_pattern = opt_data[0]; win_t * win = opt_data[1]; term_t * term = opt_data[2]; langinfo_t * langinfo = opt_data[3]; attrib_t * init_attr = opt_data[4]; misc_t * misc = opt_data[5]; attrib_t attr = *init_attr; char opt = param[strlen(param) - 1]; /* last character of param. */ int i; special_pattern[opt - '1'] = xstrdup(values[0]); utf8_interpret(special_pattern[opt - '1'], langinfo, misc->invalid_char_substitute); /* Parse optional additional arguments. */ /* """""""""""""""""""""""""""""""""""" */ for (i = 1; i < nb_values; i++) { /* Colors must respect the format: /. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (parse_attr(values[i], &attr, term->colors)) { win->special_attr[opt - '1'].is_set = FORCED; win->special_attr[opt - '1'].fg = attr.fg; win->special_attr[opt - '1'].bg = attr.bg; win->special_attr[opt - '1'].bold = attr.bold; win->special_attr[opt - '1'].dim = attr.dim; win->special_attr[opt - '1'].reverse = attr.reverse; win->special_attr[opt - '1'].standout = attr.standout; win->special_attr[opt - '1'].underline = attr.underline; win->special_attr[opt - '1'].italic = attr.italic; } } } void attributes_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { win_t * win = opt_data[0]; term_t * term = opt_data[1]; attrib_t * init_attr = opt_data[2]; long i, a; /* loop index. */ long offset = 0; /* nb of chars to ship to find the attribute * * representation (prefix size). */ attrib_t attr; attrib_t * attr_to_set = NULL; /* Flags to check if an attribute is already set */ /* """"""""""""""""""""""""""""""""""""""""""""" */ int inc_attr_set = 0; /* included words. */ int exc_attr_set = 0; /* excluded words. */ int cur_attr_set = 0; /* highlighted word (cursor). */ int bar_attr_set = 0; /* scroll bar. */ int shift_attr_set = 0; /* hor. scrolling arrows. */ int message_attr_set = 0; /* message (title). */ int tag_attr_set = 0; /* selected (tagged) words. */ int cursor_on_tag_attr_set = 0; /* selected words under the cursor. */ int sf_attr_set = 0; /* currently searched field color. */ int st_attr_set = 0; /* currently searched text color. */ int mf_attr_set = 0; /* matching word field color. */ int mt_attr_set = 0; /* matching word text color. */ int daccess_attr_set = 0; /* Direct access text color. */ /* Information relatives to the attributes to be searched and set. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct { attrib_t * attr; char * msg; int * flag; char * prefix; int prefix_len; } attr_infos[] = { { &win->exclude_attr, "The exclude attribute is already set.", &exc_attr_set, "e:", 2 }, { &win->include_attr, "The include attribute is already set.", &inc_attr_set, "i:", 2 }, { &win->cursor_attr, "The cursor attribute is already set.", &cur_attr_set, "c:", 2 }, { &win->bar_attr, "The scroll bar attribute is already set.", &bar_attr_set, "b:", 2 }, { &win->shift_attr, "The shift attribute is already set.", &shift_attr_set, "s:", 2 }, { &win->message_attr, "The message attribute is already set.", &message_attr_set, "m:", 2 }, { &win->tag_attr, "The tag attribute is already set.", &tag_attr_set, "t:", 2 }, { &win->cursor_on_tag_attr, "The cursor on tagged word attribute is already set.", &cursor_on_tag_attr_set, "ct:", 3 }, { &win->search_field_attr, "The search field attribute is already set.", &sf_attr_set, "sf:", 3 }, { &win->search_text_attr, "The search text attribute is already set.", &st_attr_set, "st:", 3 }, { &win->search_err_field_attr, "The search with error field attribute is already set.", &sf_attr_set, "sfe:", 4 }, { &win->search_err_text_attr, "The search text with error attribute is already set.", &st_attr_set, "ste:", 4 }, { &win->match_field_attr, "The matching word field attribute is already set.", &mf_attr_set, "mf:", 3 }, { &win->match_text_attr, "The matching word text attribute is already set.", &mt_attr_set, "mt:", 3 }, { &win->match_err_field_attr, "The matching word with error field attribute is already set.", &mf_attr_set, "mfe:", 4 }, { &win->match_err_text_attr, "The matching word with error text attribute is already set.", &mt_attr_set, "mte:", 4 }, { &win->daccess_attr, "The direct access tag attribute is already set.", &daccess_attr_set, "da:", 3 }, { NULL, NULL, NULL, NULL, 0 } }; /* Parse the arguments. */ /* """""""""""""""""""" */ for (a = 0; a < nb_values; a++) { attr = *init_attr; i = 0; while (attr_infos[i].flag != NULL) { if (strncmp(values[a], attr_infos[i].prefix, attr_infos[i].prefix_len) == 0) { if (*attr_infos[i].flag) { fprintf(stderr, "%s: ", param); fputs(attr_infos[i].msg, stderr); fputs("\n", stderr); ctxopt_ctx_disp_usage(ctx_name, exit_after); } attr_to_set = attr_infos[i].attr; *attr_infos[i].flag = 1; offset = attr_infos[i].prefix_len; break; /* We have found a matching prefix, * * no need to continue. */ } i++; } if (attr_infos[i].flag == NULL) { fprintf(stderr, "%s: Bad attribute prefix in %s\n", param, values[a]); ctxopt_ctx_disp_usage(ctx_name, exit_after); } /* Attributes must respect the format: */ /* /,. */ /* """"""""""""""""""""""""""""""""""" */ if (parse_attr(values[a] + offset, &attr, term->colors)) { attr_to_set->is_set = FORCED; attr_to_set->fg = attr.fg; attr_to_set->bg = attr.bg; attr_to_set->bold = attr.bold; attr_to_set->dim = attr.dim; attr_to_set->reverse = attr.reverse; attr_to_set->standout = attr.standout; attr_to_set->underline = attr.underline; attr_to_set->italic = attr.italic; } else { fprintf(stderr, "%s: Bad attribute settings %s\n", param, values[a]); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } } void version_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { fputs("Version: " VERSION "\n", stdout); exit(EXIT_SUCCESS); } void timeout_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { langinfo_t * langinfo = opt_data[0]; misc_t * misc = opt_data[1]; if (strcmp(opt_name, "hidden_timeout") == 0) quiet_timeout = 1; if (strprefix("current", values[0])) timeout.mode = CURRENT; else if (strprefix("quit", values[0])) timeout.mode = QUIT; else if (strprefix("word", values[0])) { if (nb_values == 3) { timeout.mode = WORD; timeout_word = xstrdup(values[1]); utf8_interpret(timeout_word, langinfo, misc->invalid_char_substitute); } else { fprintf(stderr, "%s: Missing timeout selected word or delay.\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } if (sscanf(values[nb_values - 1], "%5u", &timeout.initial_value) == 1) { timeout.initial_value *= FREQ; timeout.remain = timeout.initial_value; } else { fprintf(stderr, "%s: Invalid timeout delay.\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } void tag_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { toggle_t * toggles = opt_data[0]; win_t * win = opt_data[1]; langinfo_t * langinfo = opt_data[2]; misc_t * misc = opt_data[3]; toggles->taggable = 1; if (nb_values == 1) { win->sel_sep = xstrdup(values[0]); utf8_interpret(win->sel_sep, langinfo, misc->invalid_char_substitute); } } void pin_mode_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { toggle_t * toggles = opt_data[0]; win_t * win = opt_data[1]; langinfo_t * langinfo = opt_data[2]; misc_t * misc = opt_data[3]; toggles->taggable = 1; toggles->pinable = 1; if (nb_values == 1) { win->sel_sep = xstrdup(values[0]); utf8_interpret(win->sel_sep, langinfo, misc->invalid_char_substitute); } } void search_method_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { misc_t * misc = opt_data[0]; if (strprefix("prefix", values[0])) misc->default_search_method = PREFIX; else if (strprefix("fuzzy", values[0])) misc->default_search_method = FUZZY; else if (strprefix("substring", values[0])) misc->default_search_method = SUBSTRING; else { fprintf(stderr, "%s: Bad search method: %s\n", param, values[0]); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } void auto_da_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { char ** daccess_pattern = opt_data[0]; char * value; int i; if (nb_values == 0) { if (daccess.missing == 'y' || ((daccess.mode & DA_TYPE_POS) == 0)) { if (*daccess_pattern == NULL) { *daccess_pattern = xstrdup("(.)"); daccess.mode |= DA_TYPE_AUTO; /* Auto. */ } else *daccess_pattern = concat(*daccess_pattern, "|(.)", (char *)0); } } else for (i = 0; i < nb_values; i++) { if (*values[i] == '\0' && (daccess.missing == 'y' || ((daccess.mode & DA_TYPE_POS) == 0))) value = "."; else value = values[i]; if (*daccess_pattern == NULL) { *daccess_pattern = concat("(", value, ")", (char *)0); daccess.mode |= DA_TYPE_AUTO; /* Auto. */ } else *daccess_pattern = concat(*daccess_pattern, "|(", value, ")", (char *)0); } if (daccess.def_number < 0) { if (strcmp(param, "-N") == 0) daccess.def_number = 0; /* Words are unnumbered by default. */ else daccess.def_number = 1; /* Words are numbered by default. */ } } void field_da_number_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { daccess.mode |= DA_TYPE_POS; } void da_options_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { langinfo_t * langinfo = opt_data[0]; long * daccess_index = opt_data[1]; misc_t * misc = opt_data[2]; int pos; wchar_t * w; int n; int i; /* Parse optional additional arguments. */ /* """""""""""""""""""""""""""""""""""" */ for (i = 0; i < nb_values; i++) { char * value = values[i]; switch (*value) { case 'l': /* Left char .*/ free(daccess.left); daccess.left = xstrdup(value + 2); utf8_interpret(daccess.left, langinfo, misc->invalid_char_substitute); if (utf8_strlen(daccess.left) != 1) { fprintf(stderr, "%s: Too many characters after l:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } n = wcswidth((w = utf8_strtowcs(daccess.left)), 1); free(w); if (n > 1) { fprintf(stderr, "%s: A multi columns character is not allowed " "after l:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'r': /* Right char. */ free(daccess.right); daccess.right = xstrdup(value + 2); utf8_interpret(daccess.right, langinfo, misc->invalid_char_substitute); if (utf8_strlen(daccess.right) != 1) { fprintf(stderr, "%s: Too many characters after r:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } n = wcswidth((w = utf8_strtowcs(daccess.right)), 1); free(w); if (n > 1) { fprintf(stderr, "%s: A multi columns character is not allowed " "after r:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'a': /* Alignment. */ if (strprefix("left", value + 2)) daccess.alignment = 'l'; else if (strprefix("right", value + 2)) daccess.alignment = 'r'; else { fprintf(stderr, "%s: The value after a: must be " "l(eft) or r(ight)\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'p': /* Padding. */ if (strprefix("all", value + 2)) daccess.padding = 'a'; else if (strprefix("included", value + 2)) daccess.padding = 'i'; else { fprintf(stderr, "%s: Bad value after p:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'w': /* Width. */ if (sscanf(value + 2, "%d%n", &daccess.length, &pos) != 1) { fprintf(stderr, "%s: Bad value after w:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } if (value[pos + 2] != '\0') { fprintf(stderr, "%s: Bad value after w:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } if (daccess.length <= 0 || daccess.length > 5) { fprintf(stderr, "%s: w sub-option must be between 1 and 5\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'o': /* Start offset. */ if (sscanf(value + 2, "%zu%n+", &daccess.offset, &pos) == 1) { if (value[pos + 2] == '+') { daccess.plus = 1; if (value[pos + 3] != '\0') { fprintf(stderr, "%s: Bad value after o:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } else if (value[pos + 2] != '\0') { fprintf(stderr, "%s: Bad value after o:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } else { fprintf(stderr, "%s: Bad value after o:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'n': /* Number of digits to extract. */ if (sscanf(value + 2, "%d%n", &daccess.size, &pos) != 1) { fprintf(stderr, "%s: Bad value after n:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } if (value[pos + 2] != '\0') { fprintf(stderr, "%s: Bad value after n:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } if (daccess.size <= 0 || daccess.size > 5) { fprintf(stderr, "n sub-option must have a value between 1 and 5.\n"); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'i': /* Number of UTF-8 glyphs to ignore after the * * selector to extract. */ if (sscanf(value + 2, "%zu%n", &daccess.ignore, &pos) != 1) { fprintf(stderr, "%s: Bad value after i:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } if (value[pos + 2] != '\0') { fprintf(stderr, "%s: Bad value after i:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'f': /* Follow. */ if (strprefix("yes", value + 2)) daccess.follow = 'y'; else if (strprefix("no", value + 2)) daccess.follow = 'n'; else { fprintf(stderr, "%s: Bad value after f:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'm': /* Possibly number missing embedded numbers. */ if (strprefix("yes", value + 2)) daccess.missing = 'y'; else if (strprefix("no", value + 2)) daccess.missing = 'n'; else { fprintf(stderr, "%s: Bad value after m:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 'd': /* Decorate. */ free(daccess.num_sep); daccess.num_sep = xstrdup(value + 2); utf8_interpret(daccess.num_sep, langinfo, misc->invalid_char_substitute); if (utf8_strlen(daccess.num_sep) != 1) { fprintf(stderr, "%s: Too many characters after d:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } n = wcswidth((w = utf8_strtowcs(daccess.num_sep)), 1); free(w); if (n > 1) { fprintf(stderr, "%s: A multi columns separator is not allowed " "after d:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; case 's': /* Start index. */ { long pos; if (sscanf(value + 2, "%ld%ln", daccess_index, &pos) == 1) { if (*daccess_index < 0 || *(value + 2 + pos) != '\0') *daccess_index = 1; } else { fprintf(stderr, "%s: Invalid first index after s:\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } break; case 'h': /* Head. */ if (strprefix("trim", value + 2)) daccess.head = 't'; else if (strprefix("cut", value + 2)) daccess.head = 'c'; else if (strprefix("keep", value + 2)) daccess.head = 'k'; else { fprintf(stderr, "%s: Bad value after :h\n", param); ctxopt_ctx_disp_usage(ctx_name, exit_after); } break; default: { fprintf(stderr, "%s: Bad sub-command: %s\n", param, value); ctxopt_ctx_disp_usage(ctx_name, exit_after); } } if (daccess.length <= 0 || daccess.length > 5) daccess.length = -2; /* special value -> auto. */ } } void ignore_quotes_action(char * ctx_name, char * opt_name, char * param, int nb_values, char ** values, int nb_opt_data, void ** opt_data, int nb_ctx_data, void ** ctx_data) { misc_t * misc = opt_data[0]; misc->ignore_quotes = 1; } /* ================= */ /* Main entry point. */ /* ================= */ int main(int argc, char * argv[]) { /* Mapping of supported charsets and the number of bits used in them. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ charsetinfo_t all_supported_charsets[] = { { "UTF-8", 8 }, { "ANSI_X3.4-1968", 7 }, { "ANSI_X3.4-1986", 7 }, { "646", 7 }, { "ASCII", 7 }, { "CP367", 7 }, { "IBM367", 7 }, { "ISO_646.BASIC", 7 }, { "ISO_646.IRV:1991", 7 }, { "ISO_646.IRV", 7 }, { "ISO646-US", 7 }, { "ISO-IR-6", 7 }, { "US", 7 }, { "US-ASCII", 7 }, { "hp-roman8", 8 }, { "roman8", 8 }, { "r8", 8 }, { "ISO8859-1", 8 }, { "ISO-8859-1", 8 }, { "ISO-IR-100", 8 }, { "ISO_8859-1:1987", 8 }, { "ISO_8859-1", 8 }, { "LATIN1", 8 }, { "L1", 8 }, { "IBM819", 8 }, { "CP819", 8 }, { "ISO8859-2", 8 }, { "ISO-8859-2", 8 }, { "ISO-IR-101", 8 }, { "ISO_8859-2:1987", 8 }, { "ISO_8859-2", 8 }, { "LATIN2", 8 }, { "L2", 8 }, { "CP28592", 8 }, { "ISO8859-3", 8 }, { "ISO-8859-3", 8 }, { "ISO-IR-109", 8 }, { "ISO_8859-3:1988", 8 }, { "ISO_8859-3", 8 }, { "LATIN3", 8 }, { "L3", 8 }, { "CP28593", 8 }, { "ISO8859-4", 8 }, { "ISO-8859-4", 8 }, { "ISO-IR-110", 8 }, { "ISO_8859-4:1988", 8 }, { "LATIN4", 8 }, { "L4", 8 }, { "CP28594", 8 }, { "ISO8859-5", 8 }, { "ISO-8859-5", 8 }, { "ISO-IR-144", 8 }, { "ISO_8859-5:1988", 8 }, { "CYRILLIC", 8 }, { "CP28595", 8 }, { "KOI8-R", 8 }, { "KOI8-RU", 8 }, { "KOI8-U", 8 }, { "ISO8859-6", 8 }, { "ISO-8859-6", 8 }, { "ISO-IR-127", 8 }, { "ISO_8859-6:1987", 8 }, { "ECMA-114", 8 }, { "ASMO-708", 8 }, { "ARABIC", 8 }, { "CP28596", 8 }, { "ISO8859-7", 8 }, { "ISO-8859-7", 8 }, { "ISO-IR-126", 8 }, { "ISO_8859-7:2003", 8 }, { "ISO_8859-7:1987", 8 }, { "ELOT_928", 8 }, { "ECMA-118", 8 }, { "GREEK", 8 }, { "GREEK8", 8 }, { "CP28597", 8 }, { "ISO8859-8", 8 }, { "ISO-8859-8", 8 }, { "ISO-IR-138", 8 }, { "ISO_8859-8:1988", 8 }, { "HEBREW", 8 }, { "CP28598", 8 }, { "ISO8859-9", 8 }, { "ISO-8859-9", 8 }, { "ISO-IR-148", 8 }, { "ISO_8859-9:1989", 8 }, { "LATIN5", 8 }, { "L5", 8 }, { "CP28599", 8 }, { "ISO8859-10", 8 }, { "ISO-8859-10", 8 }, { "ISO-IR-157", 8 }, { "ISO_8859-10:1992", 8 }, { "LATIN6", 8 }, { "L6", 8 }, { "CP28600", 8 }, { "ISO8859-11", 8 }, { "ISO-8859-11", 8 }, { "ISO-8859-11:2001", 8 }, { "ISO-IR-166", 8 }, { "CP474", 8 }, { "TIS-620", 8 }, { "TIS620", 8 }, { "TIS620-0", 8 }, { "TIS620.2529-1", 8 }, { "TIS620.2533-0", 8 }, /* ISO-8859-12 was abandoned in 1997. */ /* """""""""""""""""""""""""""""""""" */ { "ISO8859-13", 8 }, { "ISO-8859-13", 8 }, { "ISO-IR-179", 8 }, { "LATIN7", 8 }, { "L7", 8 }, { "CP28603", 8 }, { "ISO8859-14", 8 }, { "ISO-8859-14", 8 }, { "LATIN8", 8 }, { "L8", 8 }, { "ISO8859-15", 8 }, { "ISO-8859-15", 8 }, { "LATIN-9", 8 }, { "CP28605", 8 }, { "ISO8859-16", 8 }, { "ISO-8859-16", 8 }, { "ISO-IR-226", 8 }, { "ISO_8859-16:2001", 8 }, { "LATIN10", 8 }, { "L10", 8 }, { "CP1250", 8 }, { "CP1251", 8 }, { "CP1252", 8 }, { "MS-ANSI", 8 }, { NULL, 0 } }; int nb_rem_args = 0; char ** rem_args = NULL; char * message = NULL; /* message to be displayed above the selection * * window. */ ll_t * message_lines_list = NULL; /* list of the lines in the message to * * be displayed. */ long message_max_width = 0; /* total width of the message (longest line). */ long message_max_len = 0; /* max number of bytes taken by a message * * line. */ char * int_string = NULL; /* String to be output when typing ^C. */ int int_as_in_shell = 1; /* CTRL-C mimics the shell behaviour. */ FILE * input_file; /* The name of the file passed as argument if any. */ long index; /* generic counter. */ long daccess_index = 1; /* First index of the numbered words. */ char * daccess_np = NULL; /* direct access numbered pattern. */ regex_t daccess_np_re; /* variable to store the compiled direct access * * pattern (-N) RE. */ char * daccess_up = NULL; /* direct access not numbered pattern. */ regex_t daccess_up_re; /* variable to store the compiled direct access * * pattern (-U) RE. */ char * include_pattern = NULL; char * exclude_pattern = NULL; int pattern_def_include = -1; /* Set to -1 until an -i or -e option * * is specified, This variable remembers * * if the words not matched will be * * included (value 1) or excluded * * (value 0) by default. */ regex_t include_re; /* variable to store the compiled include (-i) REs. */ regex_t exclude_re; /* variable to store the compiled exclude (-e) REs. */ ll_t * sed_list = NULL; /* List of sed like string representation * * of regex given after (-S). */ ll_t * include_sed_list = NULL; /* idem for -I. */ ll_t * exclude_sed_list = NULL; /* idem for -E. */ ll_t * inc_col_interval_list = NULL; /* list of included or */ ll_t * exc_col_interval_list = NULL; /* excluded numerical intervals */ ll_t * inc_row_interval_list = NULL; /* for lines and columns. */ ll_t * exc_row_interval_list = NULL; ll_t * inc_col_regex_list = NULL; /* same for lines and columns specified. */ ll_t * exc_col_regex_list = NULL; /* by regular expressions. */ ll_t * inc_row_regex_list = NULL; ll_t * exc_row_regex_list = NULL; filters_t rows_filter_type = UNKNOWN_FILTER; char * first_word_pattern = NULL; /* used by -A/-Z. */ char * last_word_pattern = NULL; regex_t first_word_re; regex_t last_word_re; char * special_pattern[5] = { NULL, NULL, NULL, NULL, NULL }; /* -1 .. -5 */ regex_t special_re[5]; int include_visual_only = 0; /* If set to 1, the original word which is * * read from stdin will be output even if its */ int exclude_visual_only = 0; /* visual representation was modified via * * -S/-I/-E. */ ll_t * cols_selector_list = NULL; char * cols_selector = NULL; ll_t * rows_selector_list = NULL; char * rows_selector = NULL; long wi; /* word index. */ term_t term; /* Terminal structure. */ tst_node_t * tst_word = NULL; /* TST used by the search function. */ tst_node_t * tst_daccess = NULL; /* TST used by the direct access system. */ long page; /* Step for the vertical cursor moves. */ char * word; /* Temporary variable to work on words. */ char * tmp_word; /* Temporary variable able to contain the beginning of * * the word to be displayed. */ long last_line = 0; /* last logical line number (from 0). */ win_t win; limit_t limits; /* set of various limitations. */ ticker_t timers; /* timers contents. */ misc_t misc; /* misc contents. */ toggle_t toggles; /* set of binary indicators. */ int old_fd0; /* backups of the old stdin file descriptor. */ int old_fd1; /* backups of the old stdout file descriptor. */ FILE * old_stdin; FILE * old_stdout; /* The selected word will go there. */ long nl; /* Number of lines displayed in the window. */ long offset; /* Used to correctly put the cursor at the start of the * * selection window, even after a terminal vertical scroll. */ long first_selectable; /* Index of the first selectable word in the input * * stream. */ long last_selectable; /* Index of the last selectable word in the input * * stream. */ long min_size; /* Minimum screen width of a column in tabular mode. */ long tab_max_size; /* Maximum screen width of a column in tabular * * mode. */ long tab_real_max_size; /* Maximum size in bytes of a column in tabular * * mode. */ long * col_real_max_size = NULL; /* Array of maximum sizes (bytes) of each */ /* column in column mode. */ long * col_max_size = NULL; /* Array of maximum sizes of each column */ /* in column mode. */ long word_real_max_size = 0; /* size of the longer word after expansion. */ long cols_real_max_size = 0; /* Max real width of all columns used when * * -w and -c are both set. */ long cols_max_size = 0; /* Same as above for the columns widths */ long col_index = 0; /* Index of the current column when reading words, * * used in column mode. */ long cols_number = 0; /* Number of columns in column mode. */ char * pre_selection_index = NULL; /* pattern used to set the initial * * cursor position. */ unsigned char buffer[16]; /* Input buffer. */ search_data_t search_data; search_data.buf = NULL; /* Search buffer */ search_data.len = 0; /* Current position in the search buffer */ search_data.utf8_len = 0; /* Current position in the search buffer in * * UTF-8 units. */ search_data.fuzzy_err = 0; /* reset the error indicator. */ search_data.fuzzy_err_pos = -1; /* no last error position in search * buffer. */ long matching_word_cur_index = -1; /* cache for the next/previous moves * * in the matching words array. */ struct sigaction sa; /* Signal structure. */ char * iws = NULL, *ils = NULL, *zg = NULL; ll_t * word_delims_list = NULL; ll_t * zapped_glyphs_list = NULL; ll_t * record_delims_list = NULL; char utf8_buffer[5]; /* buffer to store the bytes of a UTF-8 glyph * * (4 chars max). */ unsigned char is_last; char * charset; char * home_ini_file; /* init file full path. */ char * local_ini_file; /* init file full path. */ charsetinfo_t * charset_ptr; langinfo_t langinfo; int is_supported_charset; long line_count = 0; /* Only used when -R is selected. */ attrib_t init_attr; ll_node_t * inc_interval_node = NULL; /* one node of this list. */ ll_node_t * exc_interval_node = NULL; /* one node of this list. */ interval_t * inc_interval; /* the data in each node. */ interval_t * exc_interval; /* the data in each node. */ int row_def_selectable; /* default selectable value. */ int line_selected_by_regex = 0; int line_excluded = 0; char * timeout_message; char * common_options; char * main_options, *main_spec_options; char * col_options, *col_spec_options; char * line_options, *line_spec_options; char * tab_options, *tab_spec_options; char * tag_options, *tag_spec_options; /* Used to check the usablility of the DSR terminal feature. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ int row; /* absolute line position in terminal (1...) */ int col; /* absolute column position in terminal (1...) */ /* Initialize some internal data structures. */ /* """"""""""""""""""""""""""""""""""""""""" */ init_main_ds(&init_attr, &win, &limits, &timers, &toggles, &misc, &timeout, &daccess); /* direct access variable initialization. */ /* """""""""""""""""""""""""""""""""""""" */ daccess_stack = xcalloc(6, 1); daccess_stack_head = 0; /* fuzzy variables initialization. */ /* """"""""""""""""""""""""""""""" */ tst_search_list = ll_new(); ll_append(tst_search_list, sub_tst_new()); matching_words_a_size = 64; matching_words_a = xmalloc(matching_words_a_size * sizeof(long)); matches_count = 0; best_matching_words_a_size = 16; best_matching_words_a = xmalloc(best_matching_words_a_size * sizeof(long)); best_matches_count = 0; /* Initialize the tag hit number which will permit to sort the */ /* pinned words when displayed. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ long next_tag_nb = 0; /* Columns selection variables. */ /* """""""""""""""""""""""""""" */ char * cols_filter = NULL; /* Initialize the count of tagged words. */ /* """"""""""""""""""""""""""""""""""""" */ long tagged_words = 0; /* Get the current locale. */ /* """"""""""""""""""""""" */ setlocale(LC_ALL, ""); charset = nl_langinfo(CODESET); /* Check if the local charset is supported. */ /* """""""""""""""""""""""""""""""""""""""" */ is_supported_charset = 0; charset_ptr = all_supported_charsets; while (charset_ptr->name != NULL) { if (my_strcasecmp(charset, charset_ptr->name) == 0) { is_supported_charset = 1; langinfo.bits = charset_ptr->bits; break; } charset_ptr++; } if (!is_supported_charset) { fprintf(stderr, "%s is not a supported charset.", charset); exit(EXIT_FAILURE); } /* Remember the fact that the charset is UTF-8. */ /* """""""""""""""""""""""""""""""""""""""""""" */ if (strcmp(charset, "UTF-8") == 0) langinfo.utf8 = 1; else langinfo.utf8 = 0; /* my_isprint is a function pointer that points to the 7 or 8-bit */ /* version of isprint according to the content of UTF-8. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (langinfo.utf8 || langinfo.bits == 8) my_isprint = isprint8; else my_isprint = isprint7; /* Set terminal in noncanonical, noecho mode and */ /* if TERM is unset or unknown, vt100 is assumed. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ if (getenv("TERM") == NULL) setupterm("vt100", 1, (int *)0); else setupterm((char *)0, 1, (int *)0); /* Get the number of colors if the use of colors is available */ /* and authorized. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (getenv("NO_COLOR") != NULL) term.colors = 0; else { term.colors = tigetnum("colors"); if (term.colors < 0) term.colors = 0; } /* Ignore SIGTTIN. */ /* """"""""""""""" */ sigset_t sigs, oldsigs; sigemptyset(&sigs); sigaddset(&sigs, SIGTTIN); sigprocmask(SIG_BLOCK, &sigs, &oldsigs); /* Temporarily set /dev/tty as stdin/stdout to get its size */ /* even in a pipe. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ old_fd0 = dup(0); old_stdin = freopen("/dev/tty", "r", stdin); old_fd1 = dup(1); old_stdout = freopen("/dev/tty", "w", stdout); if (old_stdin == NULL || old_stdout == NULL) { fprintf(stderr, "A terminal is required to use this program.\n"); exit(EXIT_FAILURE); } /* Get the number of lines/columns of the terminal. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ get_terminal_size(&term.nlines, &term.ncolumns, &term); /* Restore the old stdin and stdout. */ /* """"""""""""""""""""""""""""""""" */ dup2(old_fd0, 0); dup2(old_fd1, 1); close(old_fd0); close(old_fd1); /* Default substitution character on invalid input. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ misc.invalid_char_substitute = '.'; /* Build the full path of the .ini file. */ /* """"""""""""""""""""""""""""""""""""" */ home_ini_file = make_ini_path(argv[0], "HOME"); local_ini_file = make_ini_path(argv[0], "PWD"); /* Set the attributes from the configuration file if possible. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ini_load(home_ini_file, &win, &term, &limits, &timers, &misc, &langinfo, ini_cb)) exit(EXIT_FAILURE); if (ini_load(local_ini_file, &win, &term, &limits, &timers, &misc, &langinfo, ini_cb)) exit(EXIT_FAILURE); free(home_ini_file); free(local_ini_file); /* Command line options setting using ctxopt. */ /* """""""""""""""""""""""""""""""""""""""""" */ ctxopt_init(argv[0], "stop_if_non_option=No " "allow_abbreviations=No " "display_usage_on_error=Yes "); common_options = "[*help] " "[*usage] " "[include_re... #regex] " "[exclude_re... #regex] " "[title #message] " "[int [#string]] " "[attributes #prefix:attr...] " "[special_level_1 #...<3] " "[special_level_2 #...<3] " "[special_level_3 #...<3] " "[special_level_4 #...<3] " "[special_level_5 #...<3] " "[zapped_glyphs #bytes] " "[lines [#height]] " "[blank_nonprintable] " "[*invalid_character #invalid_char_subst] " "[center_mode] " "[clean] " "[keep_spaces] " "[word_separators #bytes] " "[no_scroll_bar] " "[post_subst_all... #/regex/repl/opts] " "[post_subst_included... #/regex/repl/opts] " "[post_subst_excluded... #/regex/repl/opts] " "[search_method #prefix|substring|fuzzy] " "[start_pattern #pattern] " "[timeout #...] " "[hidden_timeout #...] " "[validate_in_search_mode] " "[visual_bell] " "[ignore_quotes] "; /* Do not remove the last space. */ main_spec_options = "[*version] " "[*long_help] " "[da_options #prefix:attr...] " "[auto_da_number... [#regex...]] " "[auto_da_unnumber... [#regex...]] " "[field_da_number] " "[column_mode>Columns] " "[line_mode>Lines] " "[tab_mode>Tabulations [#cols]] " "[tag_mode>Tagging [#delim]] " "[pin_mode>Tagging [#delim]]"; col_spec_options = "[wide_mode] " "[columns_select... #selector...] " "[rows_select... #selector...] " "[gutter [#string]] " "[line_separators #bytes] " "[da_options #prefix:attr...] " "[auto_da_number... [#regex...]] " "[auto_da_unnumber... [#regex...]] " "[field_da_number] " "[tag_mode>Tagging [#delim]] " "[pin_mode>Tagging [#delim]] " "[force_first_column #regex] " "[force_last_column #regex]"; line_spec_options = "[rows_select... #selector...] " "[line_separators #bytes] " "[da_options #prefix:attr...] " "[auto_da_number... [#regex...]] " "[auto_da_unnumber... [#regex...]] " "[field_da_number] " "[tag_mode>Tagging [#delim]] " "[pin_mode>Tagging [#delim]] " "[force_first_column #regex] " "[force_last_column #regex]"; tab_spec_options = "[wide_mode] " "[gutter [#string]] " "[line_separators #bytes] " "[da_options #prefix:attr...] " "[auto_da_number... [#regex...]] " "[auto_da_unnumber... [#regex...]] " "[field_da_number] " "[tag_mode>Tagging [#delim]] " "[pin_mode>Tagging [#delim]] " "[force_first_column #regex] " "[force_last_column #regex]"; tag_spec_options = "[auto_tag] " "[column_mode>Columns] " "[line_mode>Lines] " "[tab_mode>Tabulations [#cols]]"; main_options = concat(common_options, main_spec_options, (char *)0); col_options = concat(common_options, col_spec_options, (char *)0); line_options = concat(common_options, line_spec_options, (char *)0); tab_options = concat(common_options, tab_spec_options, (char *)0); tag_options = concat(common_options, tag_spec_options, (char *)0); ctxopt_new_ctx("Main", main_options); ctxopt_new_ctx("Columns", col_options); ctxopt_new_ctx("Lines", line_options); ctxopt_new_ctx("Tabulations", tab_options); ctxopt_new_ctx("Tagging", tag_options); free(main_options); free(col_options); free(line_options); free(tab_options); free(tag_options); /* ctxopt parameters. */ /* """""""""""""""""" */ ctxopt_add_opt_settings(parameters, "help", "-h -help"); ctxopt_add_opt_settings(parameters, "long_help", "-H -long-help"); ctxopt_add_opt_settings(parameters, "usage", "-? -u -usage"); ctxopt_add_opt_settings(parameters, "version", "-V -version"); ctxopt_add_opt_settings(parameters, "include_re", "-i -in -inc -incl -include"); ctxopt_add_opt_settings(parameters, "exclude_re", "-e -ex -exc -excl -exclude"); ctxopt_add_opt_settings(parameters, "lines", "-n -lines -height"); ctxopt_add_opt_settings(parameters, "title", "-m -msg -message -title"); ctxopt_add_opt_settings(parameters, "int", "-! -int -int_string"); ctxopt_add_opt_settings(parameters, "attributes", "-a -attr -attributes"); ctxopt_add_opt_settings(parameters, "special_level_1", "-1 -l1 -level1"); ctxopt_add_opt_settings(parameters, "special_level_2", "-2 -l2 -level2"); ctxopt_add_opt_settings(parameters, "special_level_3", "-3 -l3 -level3"); ctxopt_add_opt_settings(parameters, "special_level_4", "-4 -l4 -level4"); ctxopt_add_opt_settings(parameters, "special_level_5", "-5 -l5 -level5"); ctxopt_add_opt_settings(parameters, "tag_mode", "-T -tm -tag -tag_mode"); ctxopt_add_opt_settings(parameters, "pin_mode", "-P -pm -pin -pin_mode"); ctxopt_add_opt_settings(parameters, "auto_tag", "-p -at -auto_tag"); ctxopt_add_opt_settings(parameters, "auto_da_number", "-N -number"); ctxopt_add_opt_settings(parameters, "auto_da_unnumber", "-U -unnumber"); ctxopt_add_opt_settings(parameters, "field_da_number", "-F -en -embedded_number"); ctxopt_add_opt_settings(parameters, "da_options", "-D -data -options"); ctxopt_add_opt_settings(parameters, "invalid_character", "-. -dot -invalid"); ctxopt_add_opt_settings(parameters, "blank_nonprintable", "-b -blank"); ctxopt_add_opt_settings(parameters, "center_mode", "-M -middle -center"); ctxopt_add_opt_settings(parameters, "clean", "-d -restore -delete -clean " "-delete_window -clean_window"); ctxopt_add_opt_settings(parameters, "column_mode", "-c -col -col_mode -column"); ctxopt_add_opt_settings(parameters, "line_mode", "-l -line -line_mode"); ctxopt_add_opt_settings(parameters, "tab_mode", "-t -tab -tab_mode -tabulate_mode"); ctxopt_add_opt_settings(parameters, "wide_mode", "-w -wide -wide_mode"); ctxopt_add_opt_settings(parameters, "columns_select", "-C -cs -cols -cols_select"); ctxopt_add_opt_settings(parameters, "rows_select", "-R -rs -rows -rows_select"); ctxopt_add_opt_settings(parameters, "force_first_column", "-A -fc -first_column"); ctxopt_add_opt_settings(parameters, "force_last_column", "-Z -lc -last_column"); ctxopt_add_opt_settings(parameters, "gutter", "-g -gutter"); ctxopt_add_opt_settings(parameters, "keep_spaces", "-k -ks -keep_spaces"); ctxopt_add_opt_settings(parameters, "word_separators", "-W -ws -wd -word_delimiters -word_separators"); ctxopt_add_opt_settings(parameters, "line_separators", "-L -ls -ld -line-delimiters -line_separators"); ctxopt_add_opt_settings(parameters, "zapped_glyphs", "-z -zap -zap-glyphs"); ctxopt_add_opt_settings(parameters, "no_scroll_bar", "-q -no_bar -no-scroll_bar"); ctxopt_add_opt_settings(parameters, "post_subst_all", "-S -subst"); ctxopt_add_opt_settings(parameters, "post_subst_included", "-I -si -subst_included"); ctxopt_add_opt_settings(parameters, "post_subst_excluded", "-E -se -subst_excluded"); ctxopt_add_opt_settings(parameters, "search_method", "-/ -search_method"); ctxopt_add_opt_settings(parameters, "start_pattern", "-s -sp -start -start_pattern"); ctxopt_add_opt_settings(parameters, "timeout", "-x -tmout -timeout"); ctxopt_add_opt_settings(parameters, "hidden_timeout", "-X -htmout -hidden_timeout"); ctxopt_add_opt_settings(parameters, "validate_in_search_mode", "-r -auto_validate"); ctxopt_add_opt_settings(parameters, "visual_bell", "-v -vb -visual_bell"); ctxopt_add_opt_settings(parameters, "ignore_quotes", "-Q -ignore_quotes"); /* ctxopt options incompatibilities. */ /* """"""""""""""""""""""""""""""""" */ ctxopt_add_ctx_settings(incompatibilities, "Main", "column_mode line_mode tab_mode"); ctxopt_add_ctx_settings(incompatibilities, "Main", "tag_mode pin_mode"); ctxopt_add_ctx_settings(incompatibilities, "Main", "help usage"); ctxopt_add_ctx_settings(incompatibilities, "Main", "timeout hidden_timeout"); /* ctxopt options requirements. */ /* """""""""""""""""""""""""""" */ ctxopt_add_ctx_settings(requirements, "Main", "da_options " "field_da_number auto_da_number auto_da_unnumber"); ctxopt_add_ctx_settings(requirements, "Columns", "da_options " "field_da_number auto_da_number auto_da_unnumber"); ctxopt_add_ctx_settings(requirements, "Lines", "da_options " "field_da_number auto_da_number auto_da_unnumber"); ctxopt_add_ctx_settings(requirements, "Tabulations", "da_options " "field_da_number auto_da_number auto_da_unnumber"); /* ctxopt actions. */ /* """"""""""""""" */ ctxopt_add_opt_settings(actions, "auto_tag", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "invalid_character", invalid_char_action, &misc, (char *)0); ctxopt_add_opt_settings(actions, "blank_nonprintable", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "center_mode", center_mode_action, &win, (char *)0); ctxopt_add_opt_settings(actions, "clean", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "column_mode", column_mode_action, &win, (char *)0); ctxopt_add_opt_settings(actions, "line_mode", line_mode_action, &win, (char *)0); ctxopt_add_opt_settings(actions, "tab_mode", tab_mode_action, &win, (char *)0); ctxopt_add_opt_settings(actions, "columns_select", columns_select_action, &cols_selector_list, (char *)0); ctxopt_add_opt_settings(actions, "rows_select", rows_select_action, &rows_selector_list, &win, (char *)0); ctxopt_add_opt_settings(actions, "include_re", include_re_action, &pattern_def_include, &include_pattern, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "exclude_re", exclude_re_action, &pattern_def_include, &exclude_pattern, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "gutter", gutter_action, &win, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "help", help_action, (char *)0); ctxopt_add_opt_settings(actions, "long_help", long_help_action, (char *)0); ctxopt_add_opt_settings(actions, "usage", usage_action, (char *)0); ctxopt_add_opt_settings(actions, "keep_spaces", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "lines", lines_action, &win, (char *)0); ctxopt_add_opt_settings(actions, "no_scroll_bar", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "start_pattern", set_pattern_action, &pre_selection_index, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "title", set_string_action, &message, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "int", int_action, &int_string, &int_as_in_shell, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "validate_in_search_mode", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "version", version_action, (char *)0); ctxopt_add_opt_settings(actions, "visual_bell", toggle_action, &toggles, (char *)0); ctxopt_add_opt_settings(actions, "wide_mode", wide_mode_action, &win, (char *)0); ctxopt_add_opt_settings(actions, "post_subst_all", post_subst_action, &sed_list, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "post_subst_included", post_subst_action, &include_sed_list, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "post_subst_excluded", post_subst_action, &exclude_sed_list, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "special_level_1", special_level_action, special_pattern, &win, &term, &langinfo, &init_attr, &misc, (char *)0); ctxopt_add_opt_settings(actions, "special_level_2", special_level_action, special_pattern, &win, &term, &langinfo, &init_attr, &misc, (char *)0); ctxopt_add_opt_settings(actions, "special_level_3", special_level_action, special_pattern, &win, &term, &langinfo, &init_attr, &misc, (char *)0); ctxopt_add_opt_settings(actions, "special_level_4", special_level_action, special_pattern, &win, &term, &langinfo, &init_attr, &misc, (char *)0); ctxopt_add_opt_settings(actions, "special_level_5", special_level_action, special_pattern, &win, &term, &langinfo, &init_attr, &misc, (char *)0); ctxopt_add_opt_settings(actions, "attributes", attributes_action, &win, &term, &init_attr, (char *)0); ctxopt_add_opt_settings(actions, "timeout", timeout_action, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "hidden_timeout", timeout_action, &langinfo, (char *)0); ctxopt_add_opt_settings(actions, "force_first_column", set_pattern_action, &first_word_pattern, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "force_last_column", set_pattern_action, &last_word_pattern, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "word_separators", set_pattern_action, &iws, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "line_separators", set_pattern_action, &ils, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "zapped_glyphs", set_pattern_action, &zg, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "tag_mode", tag_mode_action, &toggles, &win, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "pin_mode", pin_mode_action, &toggles, &win, &langinfo, &misc, (char *)0); ctxopt_add_opt_settings(actions, "search_method", search_method_action, &misc, (char *)0); ctxopt_add_opt_settings(actions, "auto_da_number", auto_da_action, &daccess_np, (char *)0); ctxopt_add_opt_settings(actions, "auto_da_unnumber", auto_da_action, &daccess_up, (char *)0); ctxopt_add_opt_settings(actions, "field_da_number", field_da_number_action, (char *)0); ctxopt_add_opt_settings(actions, "da_options", da_options_action, &langinfo, &daccess_index, &misc, (char *)0); ctxopt_add_opt_settings(actions, "ignore_quotes", ignore_quotes_action, &misc, (char *)0); /* ctxopt constraints. */ /* """"""""""""""""""" */ ctxopt_add_opt_settings(constraints, "attributes", ctxopt_re_constraint, "[^:]+:.+"); ctxopt_add_opt_settings(constraints, "da_options", ctxopt_re_constraint, "[^:]+:.+"); ctxopt_add_opt_settings(constraints, "lines", check_integer_constraint, ""); ctxopt_add_opt_settings(constraints, "tab_mode", check_integer_constraint, ""); ctxopt_add_opt_settings(constraints, "tab_mode", ctxopt_range_constraint, "1 ."); /* Evaluation order. */ /* """"""""""""""""" */ ctxopt_add_opt_settings(after, "field_da_number", "auto_da_number auto_da_unnumber"); ctxopt_add_opt_settings(after, "da_options", "field_da_number auto_da_number auto_da_unnumber"); /* Command line options analysis. */ /* """""""""""""""""""""""""""""" */ ctxopt_analyze(argc - 1, argv + 1, &nb_rem_args, &rem_args); /* Command line options evaluation. */ /* """""""""""""""""""""""""""""""" */ ctxopt_evaluate(); /* Check remaining non analyzed command line arguments. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (nb_rem_args == 1) { input_file = fopen(rem_args[0], "r"); if (input_file == NULL) { fprintf(stderr, "The file \"%s\" does not exist or cannot be read.\n", rem_args[0]); ctxopt_disp_usage(exit_after); exit(EXIT_FAILURE); /* Avoid a compiler warning. */ } } else if (nb_rem_args == 0) input_file = stdin; else { fprintf(stderr, "Extra arguments detected:\n"); fprintf(stderr, "%s", rem_args[1]); for (int i = 2; i < nb_rem_args; i++) fprintf(stderr, ", %s", rem_args[i]); fprintf(stderr, ".\n"); ctxopt_disp_usage(exit_after); exit(EXIT_FAILURE); /* Avoid a compiler warning. */ } /* Free the memory used internally by ctxopt. */ /* """""""""""""""""""""""""""""""""""""""""" */ ctxopt_free_memory(); /* If we did not impose the number of columns, use the whole */ /* terminal width. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.tab_mode && !win.max_cols) win.wide = 1; win.start = 0; term.color_method = 1; /* We default to setaf/setbf to set colors. */ term.curs_line = term.curs_column = 0; { char * str; str = tigetstr("cuu1"); term.has_cursor_up = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("cud1"); term.has_cursor_down = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("cub1"); term.has_cursor_left = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("cuf1"); term.has_cursor_right = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("cup"); term.has_cursor_address = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("sc"); term.has_save_cursor = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("rc"); term.has_restore_cursor = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("setf"); term.has_setf = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("setb"); term.has_setb = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("setaf"); term.has_setaf = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("setab"); term.has_setab = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("hpa"); term.has_hpa = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("cuf"); term.has_parm_right_cursor = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("bold"); term.has_bold = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("dim"); term.has_dim = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("rev"); term.has_reverse = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("smul"); term.has_underline = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("smso"); term.has_standout = (str == (char *)-1 || str == NULL) ? 0 : 1; str = tigetstr("sitm"); term.has_italic = (str == (char *)-1 || str == NULL) ? 0 : 1; } if (!term.has_cursor_up || !term.has_cursor_down || !term.has_cursor_left || !term.has_cursor_right || !term.has_save_cursor || !term.has_restore_cursor) { fprintf(stderr, "The terminal does not have the required cursor " "management capabilities.\n"); exit(EXIT_FAILURE); } word_buffer = xcalloc(1, daccess.flength + limits.word_length + 1); /* default_search_method is not set in the command line nor in a config */ /* file, set it to fuzzy. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (misc.default_search_method == NONE) misc.default_search_method = FUZZY; /* If some attributes were not set, set their default values. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (term.colors > 7) { int special_def_attr[5] = { 1, 2, 3, 5, 6 }; if (!win.cursor_attr.is_set) { if (term.has_reverse) win.cursor_attr.reverse = 1; else if (term.has_standout) win.cursor_attr.standout = 1; else { win.cursor_attr.fg = 0; win.cursor_attr.bg = 1; } win.cursor_attr.is_set = SET; } if (!win.cursor_on_tag_attr.is_set) { if (term.has_reverse) win.cursor_on_tag_attr.reverse = 1; if (term.has_underline) win.cursor_on_tag_attr.underline = 1; else win.cursor_on_tag_attr.fg = 2; win.cursor_on_tag_attr.is_set = SET; } if (!win.bar_attr.is_set) { win.bar_attr.fg = 2; win.bar_attr.is_set = SET; } if (!win.shift_attr.is_set) { win.shift_attr.fg = 2; win.shift_attr.is_set = SET; } if (!win.message_attr.is_set) { if (term.has_bold) win.message_attr.bold = 1; else if (term.has_reverse) win.message_attr.reverse = 1; else { win.message_attr.fg = 0; win.message_attr.bg = 7; } win.message_attr.is_set = SET; } if (!win.search_field_attr.is_set) { win.search_field_attr.bg = 5; win.search_field_attr.is_set = SET; } if (!win.search_text_attr.is_set) { win.search_text_attr.fg = 0; win.search_text_attr.bg = 6; win.search_text_attr.is_set = SET; } if (!win.search_err_field_attr.is_set) { win.search_err_field_attr.bg = 1; win.search_err_field_attr.is_set = SET; } if (!win.search_err_text_attr.is_set) { if (term.has_reverse) win.search_err_text_attr.reverse = 1; win.search_err_text_attr.fg = 1; win.search_err_text_attr.is_set = SET; } if (!win.match_field_attr.is_set) { win.match_field_attr.is_set = SET; } if (!win.match_text_attr.is_set) { win.match_text_attr.fg = 5; win.match_text_attr.is_set = SET; } if (!win.match_err_field_attr.is_set) { win.match_err_field_attr.is_set = SET; } if (!win.match_err_text_attr.is_set) { win.match_err_text_attr.fg = 1; win.match_err_text_attr.is_set = SET; } if (!win.exclude_attr.is_set) { win.exclude_attr.fg = 6; win.exclude_attr.is_set = SET; } /* This attribute should complete the attributes already set. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!win.tag_attr.is_set) { if (term.has_underline) win.tag_attr.underline = 1; else if (term.has_bold) win.tag_attr.bold = 1; else win.tag_attr.fg = 2; win.tag_attr.is_set = SET; } if (!win.daccess_attr.is_set) { if (term.has_bold) win.daccess_attr.bold = 1; win.daccess_attr.is_set = SET; } for (index = 0; index < 5; index++) { if (!win.special_attr[index].is_set) { win.special_attr[index].fg = special_def_attr[index]; win.special_attr[index].is_set = SET; } } } else { if (!win.cursor_attr.is_set) { if (term.has_reverse) win.cursor_attr.reverse = 1; win.cursor_attr.is_set = SET; } if (!win.cursor_on_tag_attr.is_set) { if (term.has_reverse) win.cursor_on_tag_attr.reverse = 1; if (term.has_underline) win.cursor_on_tag_attr.underline = 1; else if (term.has_bold) win.cursor_on_tag_attr.bold = 1; win.cursor_on_tag_attr.is_set = SET; } if (!win.bar_attr.is_set) { if (term.has_bold) win.bar_attr.bold = 1; win.bar_attr.is_set = SET; } if (!win.shift_attr.is_set) { if (term.has_reverse) win.shift_attr.reverse = 1; win.shift_attr.is_set = SET; } if (!win.message_attr.is_set) { if (term.has_bold) win.message_attr.bold = 1; else if (term.has_reverse) win.message_attr.reverse = 1; win.message_attr.is_set = SET; } if (!win.search_field_attr.is_set) { if (term.has_reverse) win.search_field_attr.reverse = 1; win.search_field_attr.is_set = SET; } if (!win.search_text_attr.is_set) { if (term.has_bold) win.search_text_attr.bold = 1; win.search_text_attr.is_set = SET; } if (!win.search_err_field_attr.is_set) { if (term.has_bold) win.search_err_field_attr.bold = 1; win.search_err_field_attr.is_set = SET; } if (!win.search_err_text_attr.is_set) { if (term.has_reverse) win.search_err_text_attr.reverse = 1; win.search_err_text_attr.is_set = SET; } if (!win.match_field_attr.is_set) { if (term.has_bold) win.match_field_attr.bold = 1; else if (term.has_reverse) win.match_field_attr.reverse = 1; win.match_field_attr.is_set = SET; } if (!win.match_text_attr.is_set) { if (term.has_reverse) win.match_text_attr.reverse = 1; else if (term.has_bold) win.match_text_attr.bold = 1; win.match_text_attr.is_set = SET; } if (!win.exclude_attr.is_set) { if (term.has_dim) win.exclude_attr.dim = 1; else if (term.has_italic) win.exclude_attr.italic = 1; else if (term.has_bold) win.exclude_attr.bold = 1; win.exclude_attr.is_set = SET; } if (!win.tag_attr.is_set) { if (term.has_underline) win.tag_attr.underline = 1; else if (term.has_standout) win.tag_attr.standout = 1; else if (term.has_reverse) win.tag_attr.reverse = 1; win.tag_attr.is_set = SET; } if (!win.daccess_attr.is_set) { if (term.has_bold) win.daccess_attr.bold = 1; win.daccess_attr.is_set = SET; } for (index = 0; index < 5; index++) { if (!win.special_attr[index].is_set) { if (term.has_bold) win.special_attr[index].bold = 1; else if (term.has_standout) win.special_attr[index].standout = 1; win.special_attr[index].is_set = SET; } } } /* Initialize the timeout message when the x/X option is set. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!quiet_timeout && timeout.initial_value > 0) { switch (timeout.mode) { case QUIT: timeout_message = xstrdup( "[ s before quitting without selecting anything]"); break; case CURRENT: timeout_message = xstrdup( "[ s before selecting the current highlighted word]"); break; case WORD: { char * s = "[ s before selecting the word \""; timeout_message = xcalloc(1, 4 + strlen(s) + strlen(timeout_word)); strcpy(timeout_message, s); strcat(timeout_message, timeout_word); strcat(timeout_message, "\"]"); break; } default: /* The other cases are impossible due to options analysis. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ timeout_message = xstrdup(" "); /* Just in case. */ } timeout_seconds = xcalloc(1, 6); sprintf(timeout_seconds, "%5u", timeout.initial_value / FREQ); memcpy(timeout_message + 1, timeout_seconds, 5); message_lines_list = ll_new(); if (message) { long len; get_message_lines(message, message_lines_list, &message_max_width, &message_max_len); ll_append(message_lines_list, timeout_message); if ((len = strlen(timeout_message)) > message_max_len) message_max_len = message_max_width = len; } else { ll_append(message_lines_list, timeout_message); message_max_len = message_max_width = strlen(timeout_message); } } else if (message) { message_lines_list = ll_new(); get_message_lines(message, message_lines_list, &message_max_width, &message_max_len); } /* Force the maximum number of window's line if -n is used. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (term.nlines <= win.message_lines) { win.message_lines = term.nlines - 1; win.max_lines = 1; } else if (win.asked_max_lines >= 0) { if (win.asked_max_lines == 0) win.max_lines = term.nlines - win.message_lines; else { if (win.asked_max_lines > term.nlines - win.message_lines) win.max_lines = term.nlines - win.message_lines; else win.max_lines = win.asked_max_lines; } } else /* -n was not used. Set win.asked_max_lines to its default value. */ win.asked_max_lines = win.max_lines; /* Allocate the memory for our words structures. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ word_a = xmalloc(WORDSCHUNK * sizeof(word_t)); /* Fill an array of word_t elements obtained from stdin. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ tab_real_max_size = 0; tab_max_size = 0; min_size = 0; /* Parse the list of glyphs to be zapped (option -z). */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ zapped_glyphs_list = ll_new(); if (zg != NULL) { int utf8_len; char * zg_ptr = zg; char * tmp; utf8_len = mblen(zg_ptr, 4); while (utf8_len != 0) { tmp = xmalloc(utf8_len + 1); memcpy(tmp, zg_ptr, utf8_len); tmp[utf8_len] = '\0'; ll_append(zapped_glyphs_list, tmp); zg_ptr += utf8_len; utf8_len = mblen(zg_ptr, 4); } } /* Parse the word separators string (option -W). If it is empty then */ /* the standard delimiters (space, tab and EOL) are used. Each of its */ /* UTF-8 sequences are stored in a linked list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ word_delims_list = ll_new(); if (iws == NULL) { ll_append(word_delims_list, " "); ll_append(word_delims_list, "\t"); ll_append(word_delims_list, "\n"); } else { int utf8_len; char * iws_ptr = iws; char * tmp; utf8_len = mblen(iws_ptr, 4); while (utf8_len != 0) { tmp = xmalloc(utf8_len + 1); memcpy(tmp, iws_ptr, utf8_len); tmp[utf8_len] = '\0'; ll_append(word_delims_list, tmp); iws_ptr += utf8_len; utf8_len = mblen(iws_ptr, 4); } } /* Parse the line separators string (option -L). If it is empty then */ /* the standard delimiter (newline) is used. Each of its UTF-8 */ /* sequences are stored in a linked list. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ record_delims_list = ll_new(); /* A default line separator is set to '\n' except in tab_mode */ /* where it should be explicitly set. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (ils == NULL && !win.tab_mode) ll_append(record_delims_list, "\n"); else { int utf8_len; char * ils_ptr = ils; char * tmp; utf8_len = mblen(ils_ptr, 4); while (utf8_len != 0) { tmp = xmalloc(utf8_len + 1); memcpy(tmp, ils_ptr, utf8_len); tmp[utf8_len] = '\0'; ll_append(record_delims_list, tmp); /* Add this record delimiter as a word delimiter. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ if (ll_find(word_delims_list, tmp, buffer_cmp) == NULL) ll_append(word_delims_list, tmp); ils_ptr += utf8_len; utf8_len = mblen(ils_ptr, 4); } } /* Initialize the first chunks of the arrays which will contain the */ /* maximum length of each column in column mode. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode) { long ci; /* Column index. */ col_real_max_size = xmalloc(COLSCHUNK * sizeof(long)); col_max_size = xmalloc(COLSCHUNK * sizeof(long)); for (ci = 0; ci < COLSCHUNK; ci++) col_real_max_size[ci] = col_max_size[ci] = 0; col_index = cols_number = 0; } /* Compile the regular expression patterns. */ /* """""""""""""""""""""""""""""""""""""""" */ if (daccess_np && regcomp(&daccess_np_re, daccess_np, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", daccess_np); exit(EXIT_FAILURE); } if (daccess_up && regcomp(&daccess_up_re, daccess_up, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", daccess_up); exit(EXIT_FAILURE); } if (include_pattern && regcomp(&include_re, include_pattern, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", include_pattern); exit(EXIT_FAILURE); } if (exclude_pattern && regcomp(&exclude_re, exclude_pattern, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", exclude_pattern); exit(EXIT_FAILURE); } if (first_word_pattern && regcomp(&first_word_re, first_word_pattern, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", first_word_pattern); exit(EXIT_FAILURE); } if (last_word_pattern && regcomp(&last_word_re, last_word_pattern, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", last_word_pattern); exit(EXIT_FAILURE); } for (index = 0; index < 5; index++) { if (special_pattern[index] && regcomp(&special_re[index], special_pattern[index], REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Bad regular expression: %s.\n", special_pattern[index]); exit(EXIT_FAILURE); } } /* Parse the post-processing patterns and extract its values. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (sed_list != NULL) { ll_node_t * node = sed_list->head; while (node != NULL) { if (!parse_sed_like_string((sed_t *)(node->data))) { fprintf(stderr, "Bad -S argument. Must be something like: " "/regex/repl_string/[g][v][s][i].\n"); exit(EXIT_FAILURE); } if ((!include_visual_only || !exclude_visual_only) && ((sed_t *)(node->data))->visual) { include_visual_only = 1; exclude_visual_only = 1; } node = node->next; } } if (include_sed_list != NULL) { ll_node_t * node = include_sed_list->head; while (node != NULL) { if (!parse_sed_like_string((sed_t *)(node->data))) { fprintf(stderr, "Bad -I argument. Must be something like: " "/regex/repl_string/[g][v][s][i].\n"); exit(EXIT_FAILURE); } if (!include_visual_only && ((sed_t *)(node->data))->visual) include_visual_only = 1; node = node->next; } } if (exclude_sed_list != NULL) { ll_node_t * node = exclude_sed_list->head; while (node != NULL) { if (!parse_sed_like_string((sed_t *)(node->data))) { fprintf(stderr, "Bad -E argument. Must be something like: " "/regex/repl_string/[g][v][s][i].\n"); exit(EXIT_FAILURE); } if (!exclude_visual_only && ((sed_t *)(node->data))->visual) exclude_visual_only = 1; node = node->next; } } /* Parse the row selection string if any. */ /* """""""""""""""""""""""""""""""""""""" */ if (rows_selector_list != NULL) { ll_node_t * node_selector = rows_selector_list->head; filters_t filter_type; rows_filter_type = UNKNOWN_FILTER; while (node_selector != NULL) { rows_selector = node_selector->data; char * unparsed = xstrdup((char *)rows_selector); parse_selectors(rows_selector, &filter_type, unparsed, &inc_row_interval_list, &inc_row_regex_list, &exc_row_interval_list, &exc_row_regex_list, &langinfo, &misc); if (*unparsed != '\0') { fprintf(stderr, "Bad -R argument. Unparsed part: %s.\n", unparsed); exit(EXIT_FAILURE); } if (rows_filter_type == UNKNOWN_FILTER) rows_filter_type = filter_type; node_selector = node_selector->next; free(unparsed); } merge_intervals(inc_row_interval_list); merge_intervals(exc_row_interval_list); } /* Parse the column selection string if any. */ /* """"""""""""""""""""""""""""""""""""""""" */ if (cols_selector_list != NULL) { filters_t filter_type, cols_filter_type; interval_t * data; ll_node_t * node; ll_node_t * node_selector = cols_selector_list->head; cols_filter = xmalloc(limits.cols); cols_filter_type = UNKNOWN_FILTER; while (node_selector != NULL) { cols_selector = node_selector->data; char * unparsed = xstrdup((char *)cols_selector); parse_selectors(cols_selector, &filter_type, unparsed, &inc_col_interval_list, &inc_col_regex_list, &exc_col_interval_list, &exc_col_regex_list, &langinfo, &misc); if (*unparsed != '\0') { fprintf(stderr, "Bad -C argument. Unparsed part: %s.\n", unparsed); exit(EXIT_FAILURE); } merge_intervals(inc_col_interval_list); merge_intervals(exc_col_interval_list); free(unparsed); if (cols_filter_type == UNKNOWN_FILTER) cols_filter_type = filter_type; /* Only initialize the whole set when -C is encountered for the */ /* first time. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (cols_filter_type == INCLUDE_FILTER) memset(cols_filter, SOFT_EXCLUDE_MARK, limits.cols); else memset(cols_filter, SOFT_INCLUDE_MARK, limits.cols); /* Process the explicitly included columns intervals. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (inc_col_interval_list != NULL) for (node = inc_col_interval_list->head; node; node = node->next) { data = node->data; if (data->low >= limits.cols) break; if (data->high >= limits.cols) data->high = limits.cols - 1; memset(cols_filter + data->low, INCLUDE_MARK, data->high - data->low + 1); } /* Process the explicitly excluded column intervals. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if (exc_col_interval_list != NULL) for (node = exc_col_interval_list->head; node; node = node->next) { data = node->data; if (data->low >= limits.cols) break; if (data->high >= limits.cols) data->high = limits.cols - 1; memset(cols_filter + data->low, EXCLUDE_MARK, data->high - data->low + 1); } node_selector = node_selector->next; } } /* Initialize the useful values needed to walk through */ /* the rows intervals. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ if (rows_filter_type == INCLUDE_FILTER) row_def_selectable = SOFT_EXCLUDE_MARK; else if (rows_filter_type == EXCLUDE_FILTER) row_def_selectable = SOFT_INCLUDE_MARK; else { if (pattern_def_include == 0) row_def_selectable = SOFT_EXCLUDE_MARK; else row_def_selectable = SOFT_INCLUDE_MARK; } /* Set the head of the interval list. */ /* """""""""""""""""""""""""""""""""" */ if (inc_row_interval_list) inc_interval_node = inc_row_interval_list->head; else inc_interval_node = NULL; if (exc_row_interval_list) exc_interval_node = exc_row_interval_list->head; else exc_interval_node = NULL; /* And get the first interval.*/ /* """"""""""""""""""""""""""" */ if (inc_interval_node) inc_interval = (interval_t *)inc_interval_node->data; else inc_interval = NULL; if (exc_interval_node) exc_interval = (interval_t *)exc_interval_node->data; else exc_interval = NULL; /* First pass: */ /* Get and process the input stream words. */ /* In this pass, the different actions will occur: */ /* - A new word is read from stdin */ /* - A new SOL and or EOL is possibly set */ /* - A special level is possibly affected to the word just read */ /* - The -R is taken into account */ /* - The first part of the -C option is done */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while ((word = get_word(input_file, word_delims_list, record_delims_list, zapped_glyphs_list, utf8_buffer, &is_last, &toggles, &langinfo, &win, &limits, &misc)) != NULL) { int selectable; int is_first = 0; int special_level; int row_inc_matched = 0; if (*word == '\0') continue; /* Manipulates the is_last flag word indicator to make this word */ /* the first or last one of the current line in column/line/tab mode. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode || win.tab_mode) { if (first_word_pattern && regexec(&first_word_re, word, (int)0, NULL, 0) == 0) is_first = 1; if (last_word_pattern && !is_last && regexec(&last_word_re, word, (int)0, NULL, 0) == 0) is_last = 1; } /* Check if the word is special. */ /* """"""""""""""""""""""""""""" */ special_level = 0; for (index = 0; index < 5; index++) { if (special_pattern[index] != NULL && regexec(&special_re[index], word, (int)0, NULL, 0) == 0) { special_level = (int)index + 1; break; } } /* Default selectable state. */ /* """"""""""""""""""""""""" */ selectable = SOFT_INCLUDE_MARK; /* For each new line check if the line is in the current */ /* interval or if we need to get the next interval if any .*/ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (rows_selector) { if (count > 0 && word_a[count - 1].is_last) { /* We are in a new line, reset the flag indicating that we are on */ /* a line selected by a regular expression and the flag saying */ /* that the whole line has been excluded. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ line_selected_by_regex = 0; line_excluded = 0; /* And also reset the flag telling that the row has been explicitly */ /* removed from the selectable list of words. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ row_inc_matched = 0; /* Increment the line counter used to see if we are an include or */ /* exclude set of lines. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ line_count++; /* Look if we need to use the next interval of the list. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (inc_interval_node && line_count > inc_interval->high) { inc_interval_node = inc_interval_node->next; if (inc_interval_node) inc_interval = (interval_t *)inc_interval_node->data; } if (exc_interval_node && line_count > exc_interval->high) { exc_interval_node = exc_interval_node->next; if (exc_interval_node) exc_interval = (interval_t *)exc_interval_node->data; } } /* Look if the line is in an excluded or included line. */ /* The included line intervals are only checked if the word didn't */ /* belong to an excluded line interval before. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (exc_interval) { if (line_count >= exc_interval->low && line_count <= exc_interval->high) selectable = EXCLUDE_MARK; } if (selectable != EXCLUDE_MARK && inc_interval) { if (line_count >= inc_interval->low && line_count <= inc_interval->high) { selectable = INCLUDE_MARK; /* As the raw has been explicitly selected, record that so than */ /* we can distinguish that from the implicit selection. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ row_inc_matched = 1; } } } /* Check if the all the words in the current row must be included or */ /* excluded from the selectable set of words. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (selectable != EXCLUDE_MARK) { /* Look in the excluded list of regular expressions. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''' */ if (exc_row_regex_list != NULL) { regex_t * row_re; ll_node_t * row_regex_node = exc_row_regex_list->head; while (row_regex_node != NULL) { row_re = row_regex_node->data; if (regexec(row_re, word, (int)0, NULL, 0) == 0) { long c = count - 1; /* Mark all the next words of the line as excluded. */ /* '''''''''''''''''''''''''''''''''''''''''''''''' */ line_selected_by_regex = 1; line_excluded = 1; /* Mark all the previous words of the line as excluded. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''' */ while (c >= 0 && !word_a[c].is_last) { word_a[c].is_selectable = EXCLUDE_MARK; c--; } /* Mark the current word as not excluded. */ /* '''''''''''''''''''''''''''''''''''''' */ selectable = EXCLUDE_MARK; /* No need to continue as the line is already marked as */ /* excluded. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''' */ break; } row_regex_node = row_regex_node->next; } } /* If the line has not yet been excluded and the list of explicitly */ /* include regular expressions is not empty then give them a chance. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (selectable != EXCLUDE_MARK && inc_row_regex_list != NULL) { regex_t * row_re; ll_node_t * row_regex_node = inc_row_regex_list->head; while (row_regex_node != NULL) { row_re = row_regex_node->data; if (regexec(row_re, word, (int)0, NULL, 0) == 0) { long c = count - 1; while (c >= 0 && !word_a[c].is_last) { /* Do not include an already excluded word. */ /* """""""""""""""""""""""""""""""""""""""" */ if (word_a[c].is_selectable) word_a[c].is_selectable = INCLUDE_MARK; c--; } /* Mark all the next words of the line as included. */ /* '''''''''''''''''''''''''''''''''''''''''''''''' */ line_selected_by_regex = 1; /* Mark all the previous words of the line as included. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''' */ selectable = INCLUDE_MARK; } row_regex_node = row_regex_node->next; } } } /* If the line contains a word that matched a regex which determines */ /* the inclusion of exclusion of this line, then use the regex */ /* selection flag to determine the inclusion/exclusion of the future */ /* words in the line. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (line_excluded) selectable = EXCLUDE_MARK; else { if (line_selected_by_regex) selectable = (row_def_selectable == ROW_REGEX_EXCLUDE) ? SOFT_EXCLUDE_MARK : INCLUDE_MARK; /* Check if the current word is matching an include or exclude */ /* pattern */ /* Only do it if if hasn't be explicitly deselected before. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (selectable != EXCLUDE_MARK) { /* Check if the word will be excluded in the list of selectable */ /* words or not. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (exclude_pattern) { if (regexec(&exclude_re, word, (int)0, NULL, 0) == 0) selectable = EXCLUDE_MARK; } if (selectable != 0 && !line_selected_by_regex) { /* Check if the word will be included in the list of selectable */ /* words or not. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (include_pattern) { if (regexec(&include_re, word, (int)0, NULL, 0) == 0) selectable = INCLUDE_MARK; else if (!row_inc_matched) selectable = row_def_selectable; } else if (rows_selector && !row_inc_matched) selectable = row_def_selectable; } } } if (win.col_mode) { /* In column mode we must manage the allocation space for some */ /* column's related data structures and check if some limits ave not */ /* been reached. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (is_first) col_index = 1; else { col_index++; if (col_index > cols_number) { /* Check the limits. */ /* ''''''''''''''''' */ if (col_index == limits.cols) { fprintf(stderr, "The number of columns has reached the limit of %ld.\n", limits.cols); exit(EXIT_FAILURE); } cols_number++; /* Look if we need to enlarge the arrays indexed by the */ /* number of columns. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (cols_number % COLSCHUNK == 0) { long ci; /* column index */ col_real_max_size = xrealloc(col_real_max_size, (cols_number + COLSCHUNK) * sizeof(long)); col_max_size = xrealloc(col_max_size, (cols_number + COLSCHUNK) * sizeof(long)); /* Initialize the max size for the new columns. */ /* '''''''''''''''''''''''''''''''''''''''''''' */ for (ci = 0; ci < COLSCHUNK; ci++) { col_real_max_size[cols_number + ci] = 0; col_max_size[cols_number + ci] = 0; } } } } /* We must now check if the word matches a RE that */ /* exclude the whole column. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ if (cols_selector != NULL) { long ci; /* column index. */ regex_t * col_re; if (cols_filter[col_index - 1] == EXCLUDE_MARK) selectable = EXCLUDE_MARK; else { if (exc_col_regex_list != NULL) { /* Some columns must be excluded by regex. */ /* ''''''''''''''''''''''''''''''''''''''' */ ll_node_t * col_regex_node = exc_col_regex_list->head; while (col_regex_node != NULL) { col_re = col_regex_node->data; if (regexec(col_re, word, (int)0, NULL, 0) == 0) { cols_filter[col_index - 1] = EXCLUDE_MARK; selectable = EXCLUDE_MARK; /* Mark non selectable the items above in the column. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''' */ ci = 0; for (wi = 0; wi < count; wi++) { if (ci == col_index - 1) word_a[wi].is_selectable = EXCLUDE_MARK; if (word_a[wi].is_last) ci = 0; else ci++; } break; } col_regex_node = col_regex_node->next; } } if (inc_col_regex_list != NULL) { /* Some columns must be included by regex. */ /* ''''''''''''''''''''''''''''''''''''''' */ ll_node_t * col_regex_node = inc_col_regex_list->head; while (col_regex_node != NULL) { col_re = col_regex_node->data; if (regexec(col_re, word, (int)0, NULL, 0) == 0) { cols_filter[col_index - 1] = INCLUDE_MARK; break; } col_regex_node = col_regex_node->next; } } } } } /* Store some known values in the current word's structure. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ word_a[count].start = word_a[count].end = 0; word_a[count].str = word; word_a[count].is_selectable = selectable; word_a[count].special_level = special_level; word_a[count].is_matching = 0; word_a[count].is_tagged = 0; word_a[count].is_numbered = 0; word_a[count].tag_order = 0; if (win.col_mode || win.line_mode || win.tab_mode) { /* Set the last word in line indicator when in */ /* column/line/tab mode. */ /* ''''''''''''''''''''''''''''''''''''''''''' */ if (is_first && count > 0) word_a[count - 1].is_last = 1; word_a[count].is_last = is_last; if (is_last) col_index = 0; } else word_a[count].is_last = 0; /* One more word... */ /* """""""""""""""" */ if (count == limits.words) { fprintf(stderr, "The number of read words has reached the limit of %ld.\n", limits.words); exit(EXIT_FAILURE); } count++; if (count % WORDSCHUNK == 0) word_a = xrealloc(word_a, (count + WORDSCHUNK) * sizeof(word_t)); } /* Early exit if there is no input or if no word is selected. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (count == 0) exit(EXIT_FAILURE); /* Ignore SIGINT */ /* """"""""""""" */ sigaddset(&sigs, SIGINT); sigprocmask(SIG_BLOCK, &sigs, &oldsigs); /* The last word is always the last of its line. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode || win.tab_mode) word_a[count - 1].is_last = 1; /* Second pass to modify the word according to all/include/exclude */ /* regular expressions and the columns settings set in the previous pass. */ /* This must be done separately because in the first pass, some word */ /* could have been marked as excluded before the currently processed word */ /* (second part of the -C option) */ /* In this pass the following actions will also be done: */ /* - Finish the work on columns. */ /* - Possibly modify the word according to -S/-I/-E arguments */ /* - Replace unprintable characters in the word by mnemonics */ /* - Remember the max size of the words/columns/tabs */ /* - Insert the word in a TST (Ternary Search Tree) index to facilitate */ /* word search (each node pf the TST will contain an UTF-8 glyph). */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ col_index = 0; for (wi = 0; wi < count; wi++) { char * unaltered_word; long size; long word_len; wchar_t * tmpw; word_t * word; long s; long len; char * expanded_word; long i; /* If the column section argument is set, then adjust the final */ /* selectable attribute according to the already set words and column */ /* selectable flag contents. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (cols_selector_list != NULL) { if (cols_filter[col_index] == EXCLUDE_MARK) word_a[wi].is_selectable = EXCLUDE_MARK; else if (word_a[wi].is_selectable != EXCLUDE_MARK) { switch (cols_filter[col_index]) { case INCLUDE_MARK: word_a[wi].is_selectable = INCLUDE_MARK; break; case SOFT_EXCLUDE_MARK: if (word_a[wi].is_selectable == SOFT_EXCLUDE_MARK || word_a[wi].is_selectable == SOFT_INCLUDE_MARK) word_a[wi].is_selectable = EXCLUDE_MARK; else word_a[wi].is_selectable = INCLUDE_MARK; break; case SOFT_INCLUDE_MARK: if (word_a[wi].is_selectable == SOFT_EXCLUDE_MARK) word_a[wi].is_selectable = EXCLUDE_MARK; else word_a[wi].is_selectable = INCLUDE_MARK; break; } } } word = &word_a[wi]; /* Make sure that daccess.length >= daccess.size */ /* with DA_TYPE_POS. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (daccess.mode != DA_TYPE_NONE) { if (daccess.mode & DA_TYPE_POS) { if (daccess.size > 0) if (daccess.size > daccess.length) daccess.length = daccess.size; } /* Auto determination of the length of the selector */ /* with DA_TYPE_AUTO. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ if ((daccess.mode & DA_TYPE_AUTO) && daccess.length == -2) { long n = count; daccess.length = 0; while (n) { n /= 10; daccess.length++; } } /* Set the full length of the prefix in case of numbering. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (daccess.length > 0) daccess.flength = 3 + daccess.length; if (word->is_selectable != EXCLUDE_MARK && word->is_selectable != SOFT_EXCLUDE_MARK) { char * selector; char * tmp = xmalloc(strlen(word->str) + 4 + daccess.length); long * word_pos = xmalloc(sizeof(long)); int may_number; if (!isempty(word->str)) { *word_pos = wi; tmp[0] = ' '; /* Check if the word is eligible to the numbering process. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (daccess_up == NULL && daccess_np == NULL) { if (daccess.mode & DA_TYPE_POS) may_number = 1; else may_number = 0; } else { if (daccess_up != NULL && !!regexec(&daccess_up_re, word->str, (int)0, NULL, 0) == 0) may_number = 0; else { if (daccess_np != NULL && !!regexec(&daccess_np_re, word->str, (int)0, NULL, 0) == 0) may_number = 1; else may_number = daccess.def_number; } } /* It is... */ /* """""""" */ if (may_number) { if (daccess.mode & DA_TYPE_POS) { if (!word->is_numbered) { if (daccess.size > 0 && daccess.offset + daccess.size + daccess.ignore <= utf8_strlen(word->str)) { unsigned selector_value; /* numerical value of the * * extracted selector. */ long selector_offset; /* offset in byte to the selector * * to extract. */ char * ptr; /* points just after the selector * * to extract. */ long plus_offset; /* points to the first occurrence * * of a number in word->str after * * the offset given. */ selector_offset = utf8_offset(word->str, daccess.offset); if (daccess.plus) { plus_offset = strcspn(word->str + selector_offset, "0123456789"); if (plus_offset + daccess.size + daccess.ignore <= strlen(word->str)) selector_offset += plus_offset; } ptr = word->str + selector_offset; selector = xstrndup(ptr, daccess.size); /* read the embedded number and, if correct, format */ /* it according to daccess.alignment. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ if (sscanf(selector, "%u", &selector_value) == 1) { sprintf(selector, "%u", selector_value); sprintf(tmp + 1, "%*u", daccess.alignment == 'l' ? -daccess.length : daccess.length, selector_value); /* Overwrite the end of the word to erase */ /* the selector. */ /* """""""""""""""""""""""""""""""""""""" */ my_strcpy(ptr, ptr + daccess.size + utf8_offset(ptr + daccess.size, daccess.ignore)); /* Modify the word according to the 'h' directive */ /* of -D. */ /* """""""""""""""""""""""""""""""""""""""""""""" */ if (daccess.head == 'c') /* h:c is present cut the leading characters */ /* before the selector. */ /* ''''''''''''''''''''''''''''''''''''''''' */ memmove(word->str, ptr, strlen(ptr) + 1); else if (daccess.head == 't') { /* h:t is present trim the leading characters */ /* before the selector if they are ' ' or '\t'. */ /* '''''''''''''''''''''''''''''''''''''''''''' */ char * p = word->str; while (p != ptr && (*p == ' ' || *p == '\t')) p++; if (p == ptr) memmove(word->str, ptr, strlen(ptr) + 1); } ltrim(selector, " "); rtrim(selector, " ", 0); tst_daccess = tst_insert(tst_daccess, utf8_strtowcs(selector), word_pos); if (daccess.follow == 'y') daccess_index = selector_value + 1; word->is_numbered = 1; } free(selector); } } } /* Try to number this word if it is still non numbered and */ /* the -N/-U option is given. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!word->is_numbered && (daccess.mode & DA_TYPE_AUTO)) { sprintf(tmp + 1, "%*ld", daccess.alignment == 'l' ? -daccess.length : daccess.length, daccess_index); selector = xstrdup(tmp + 1); ltrim(selector, " "); rtrim(selector, " ", 0); /* Insert it in the tst tree containing the selector's */ /* digits. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''''' */ tst_daccess = tst_insert(tst_daccess, utf8_strtowcs(selector), word_pos); daccess_index++; free(selector); word->is_numbered = 1; } } /* Fill the space taken by the numbering by space if the word */ /* is not numbered. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (daccess.length > 0 && !word->is_numbered) { for (i = 0; i < daccess.flength; i++) tmp[i] = ' '; } /* Make sure that the 2 character after this placeholder */ /* are initialized. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (daccess.length > 0) { tmp[1 + daccess.length] = ' '; tmp[2 + daccess.length] = ' '; } } else if (daccess.length > 0) { /* make sure that the prefix of empty word is blank */ /* as they may be display in column mode. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ for (i = 0; i < daccess.flength; i++) tmp[i] = ' '; } if (daccess.length > 0) { my_strcpy(tmp + daccess.flength, word->str); free(word->str); word->str = tmp; } else free(tmp); } else { /* Should we also add space at the beginning of excluded words ? */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (daccess.padding == 'a') { char * tmp = xmalloc(strlen(word->str) + 4 + daccess.length); for (i = 0; i < daccess.flength; i++) tmp[i] = ' '; my_strcpy(tmp + daccess.flength, word->str); free(word->str); word->str = tmp; } } } else { daccess.size = 0; daccess.length = 0; } /* Save the original word. */ /* """"""""""""""""""""""" */ unaltered_word = xstrdup(word->str); /* Possibly modify the word according to -S/-I/-E arguments. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ { ll_node_t * node = NULL; char * tmp; /* Manage the -S case. */ /* """"""""""""""""""" */ if (sed_list != NULL) { node = sed_list->head; while (node != NULL) { tmp = xstrndup(word->str, daccess.flength); if (replace(word->str + daccess.flength, (sed_t *)(node->data))) { free(word->str); memmove(word_buffer + daccess.flength, word_buffer, strlen(word_buffer) + 1); memmove(word_buffer, tmp, daccess.flength); word->str = xstrdup(word_buffer); if (((sed_t *)(node->data))->stop) break; } *word_buffer = '\0'; node = node->next; free(tmp); } } else { /* Manage the -I/-E case. */ /* """""""""""""""""""""" */ if ((word->is_selectable == INCLUDE_MARK || word->is_selectable == SOFT_INCLUDE_MARK) && include_sed_list != NULL) node = include_sed_list->head; else if ((word->is_selectable == EXCLUDE_MARK || word->is_selectable == SOFT_EXCLUDE_MARK) && exclude_sed_list != NULL) node = exclude_sed_list->head; else node = NULL; *word_buffer = '\0'; while (node != NULL) { tmp = xstrndup(word->str, daccess.flength); if (replace(word->str + daccess.flength, (sed_t *)(node->data))) { free(word->str); memmove(word_buffer + daccess.flength, word_buffer, strlen(word_buffer) + 1); memmove(word_buffer, tmp, daccess.flength); word->str = xstrdup(word_buffer); if (((sed_t *)(node->data))->stop) break; } *word_buffer = '\0'; node = node->next; free(tmp); } } } /* A substitution leading to an empty word is invalid in column mode. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode) { if (*(word->str + daccess.flength) == '\0') exit(EXIT_FAILURE); } /* Alter the word just read be replacing special chars by their */ /* escaped equivalents. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ word_len = strlen(word->str); expanded_word = xmalloc(5 * word_len + 1); len = expand(word->str, expanded_word, &langinfo, &toggles, &misc); /* Update it if needed. */ /* '''''''''''''''''''' */ if (strcmp(expanded_word, word->str) != 0) { word_len = len; free(word->str); word->str = xstrdup(expanded_word); } free(expanded_word); if (win.col_mode) { /* Update the max values of col_real_max_size[col_index] */ /* and col_max_size[col_index]. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if ((s = (long)word_len) > col_real_max_size[col_index]) { col_real_max_size[col_index] = s; /* Also update the real max size of all columns seen. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (s > cols_real_max_size) cols_real_max_size = s; } s = (long)mbstowcs(NULL, word->str, 0); s = wcswidth((tmpw = utf8_strtowcs(word->str)), s); free(tmpw); if (s > col_max_size[col_index]) { col_max_size[col_index] = s; /* Also update the max size of all columns seen. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (s > cols_max_size) cols_max_size = s; } /* Update the size of the longest expanded word. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ word_real_max_size = cols_real_max_size; } else if (win.tab_mode) { /* Store the new max number of bytes in a word */ /* and update the size of the longest expanded word. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ if ((long)word_len > tab_real_max_size) word_real_max_size = tab_real_max_size = (long)word_len; /* Store the new max word width. */ /* """"""""""""""""""""""""""""" */ size = (long)mbstowcs(NULL, word->str, 0); if ((size = wcswidth((tmpw = utf8_strtowcs(word->str)), size)) > tab_max_size) tab_max_size = size; free(tmpw); } else if (word_real_max_size < word_len) /* Update the size of the longest expanded word. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ word_real_max_size = word_len; /* When the visual only flag is set, we keep the unaltered word so */ /* that it can be restored even if its visual and searchable */ /* representation may have been altered by the previous code. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ /* Record the length of the word in bytes. This information will be */ /* used if the -k option (keep spaces ) is not set. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ word->len = strlen(word->str); /* Save the non modified word in .orig if it has been altered. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if ((strcmp(word->str, unaltered_word) != 0) && ((word->is_selectable && include_visual_only) || (!word->is_selectable && exclude_visual_only))) { word->orig = unaltered_word; } else { word->orig = NULL; free(unaltered_word); } if (win.col_mode) { if (word_a[wi].is_last) col_index = 0; else col_index++; } } /* Set the minimum width of a column (-w and -t or -c option). */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.wide) { if (win.tab_mode) { if (win.max_cols > 0) min_size = (term.ncolumns - 2) / win.max_cols - 1; if (min_size < tab_max_size) min_size = tab_max_size; word_real_max_size = min_size + tab_real_max_size - tab_max_size; } else /* Column mode. */ { min_size = (term.ncolumns - 2) / cols_number; if (min_size < cols_max_size) min_size = cols_max_size; word_real_max_size = cols_real_max_size; } } /* Third (compress) pass: remove all empty word and words containing */ /* only spaces when not in column mode. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (!win.col_mode) { long offset; offset = 0; for (wi = 0; wi < count; wi++) { while (wi + offset < count && isempty(word_a[wi + offset].str + daccess.flength)) { /* Keep non selectable empty words to allow special effects. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (word_a[wi + offset].is_selectable == SOFT_EXCLUDE_MARK || word_a[wi + offset].is_selectable == EXCLUDE_MARK) break; offset++; } if (offset > 0) word_a[wi] = word_a[wi + offset]; } count -= offset; } if (count == 0) exit(EXIT_FAILURE); /* Allocate the space for the satellites arrays. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ line_nb_of_word_a = xmalloc(count * sizeof(long)); first_word_in_line_a = xmalloc(count * sizeof(long)); /* Fourth pass: */ /* When in column or tabulating mode, we need to adjust the length of */ /* all the words by adding the right number of spaces so that they will */ /* be aligned correctly. In column mode the size of each column is */ /* variable; in tabulate mode it is constant. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode) { char * temp; /* Sets all columns to the same size when -w and -c are both set. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.wide) for (col_index = 0; col_index < cols_number; col_index++) { col_max_size[col_index] = cols_max_size; col_real_max_size[col_index] = cols_real_max_size; } /* Total space taken by all the columns plus the gutter. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ win.max_width = 0; win.real_max_width = 0; for (col_index = 0; col_index < cols_number; col_index++) { if (win.max_width + col_max_size[col_index] + 1 <= term.ncolumns - 2) win.max_width += col_max_size[col_index] + 1; win.real_max_width += col_max_size[col_index] + 1; } col_index = 0; for (wi = 0; wi < count; wi++) { long s1, s2; long word_width; wchar_t * w; s1 = (long)strlen(word_a[wi].str); word_width = mbstowcs(NULL, word_a[wi].str, 0); s2 = wcswidth((w = utf8_strtowcs(word_a[wi].str)), word_width); free(w); temp = xcalloc(1, col_real_max_size[col_index] + s1 - s2 + 1); memset(temp, ' ', col_max_size[col_index] + s1 - s2); memcpy(temp, word_a[wi].str, s1); temp[col_real_max_size[col_index] + s1 - s2] = '\0'; free(word_a[wi].str); word_a[wi].str = temp; if (word_a[wi].is_last) col_index = 0; else col_index++; } } else if (win.tab_mode) { char * temp; if (tab_max_size < min_size) { tab_max_size = min_size; if (tab_max_size > tab_real_max_size) tab_real_max_size = tab_max_size; } for (wi = 0; wi < count; wi++) { long s1, s2; long word_width; wchar_t * w; s1 = (long)strlen(word_a[wi].str); word_width = mbstowcs(NULL, word_a[wi].str, 0); s2 = wcswidth((w = utf8_strtowcs(word_a[wi].str)), word_width); free(w); temp = xcalloc(1, tab_real_max_size + s1 - s2 + 1); memset(temp, ' ', tab_max_size + s1 - s2); memcpy(temp, word_a[wi].str, s1); temp[tab_real_max_size + s1 - s2] = '\0'; free(word_a[wi].str); word_a[wi].str = temp; } } /* Fifth pass: transforms the remaining SOFT_EXCLUDE_MARKs with */ /* EXCLUDE_MARKs. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ for (wi = 0; wi < count; wi++) { long * data; wchar_t * w; ll_t * list; if (word_a[wi].is_selectable == SOFT_EXCLUDE_MARK) word_a[wi].is_selectable = EXCLUDE_MARK; /* If the word is selectable insert it in the TST tree */ /* with its associated index in the input stream. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[wi].is_selectable) { data = xmalloc(sizeof(long)); *data = wi; /* Create a wide characters string from the word screen */ /* representation to be able to store in in the TST. */ /* Note that the direct access selector,if any, is not */ /* stored. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[wi].is_numbered) w = utf8_strtowcs(word_a[wi].str + daccess.flength); else w = utf8_strtowcs(word_a[wi].str); /* If we didn't already encounter this word, then create a new */ /* entry in the TST for it and store its index in its list. */ /* Otherwise, add its index in its index list. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (tst_word && (list = tst_search(tst_word, w)) != NULL) ll_append(list, data); else { list = ll_new(); ll_append(list, data); tst_word = tst_insert(tst_word, w, list); } free(w); } } /* The word after the last one is set to NULL. */ /* """"""""""""""""""""""""""""""""""""""""""" */ word_a[count].str = NULL; /* We can now allocate the space for our tmp_word work variable. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ tmp_word = xcalloc(word_real_max_size + 1, 1); search_data.utf8_off_a = xmalloc(word_real_max_size * sizeof(long)); search_data.utf8_len_a = xmalloc(word_real_max_size * sizeof(long)); win.start = 0; /* index of the first element in the * * words array to be displayed. */ /* We can now build the first metadata. */ /* """""""""""""""""""""""""""""""""""" */ last_line = build_metadata(&term, count, &win); /* Index of the selected element in the array words */ /* The string can be: */ /* "last" The string "last" put the cursor on the last word */ /* n a number put the cursor on the word n */ /* /pref /+a regexp put the cursor on the first */ /* word matching the prefix "pref" */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ for (wi = 0; wi < count; wi++) word_a[wi].bitmap = xcalloc(1, (word_a[wi].mb - daccess.flength) / CHAR_BIT + 1); /* Find the first selectable word (if any) in the input stream. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ for (first_selectable = 0; first_selectable < count && !word_a[first_selectable].is_selectable; first_selectable++) ; /* If not found, abort. */ /* """""""""""""""""""" */ if (first_selectable == count) { fprintf(stderr, "No selectable word found.\n"); exit(EXIT_FAILURE); } /* Else find the last selectable word in the input stream. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ last_selectable = count - 1; while (last_selectable > 0 && !word_a[last_selectable].is_selectable) last_selectable--; if (pre_selection_index == NULL) /* Option -s was not used. */ /* """"""""""""""""""""""" */ current = first_selectable; else if (*pre_selection_index == '/') { /* A regular expression is expected. */ /* """"""""""""""""""""""""""""""""" */ regex_t re; long index; if (regcomp(&re, pre_selection_index + 1, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "Invalid regular expression :%s.\n", pre_selection_index); exit(EXIT_FAILURE); } else { int found = 0; char * word; for (index = first_selectable; index <= last_selectable; index++) { if (!word_a[index].is_selectable) continue; if (word_a[index].orig != NULL) word = word_a[index].orig; else word = word_a[index].str; if (regexec(&re, word, (int)0, NULL, 0) == 0) { current = index; found = 1; break; } } if (!found) current = first_selectable; } } else if (*pre_selection_index == '=') /* exact search. */ { /* A prefix is expected. */ /* """"""""""""""""""""" */ wchar_t * w; ll_t * list; ll_node_t * node; list = tst_search(tst_word, w = utf8_strtowcs(pre_selection_index + 1)); if (list != NULL) { node = list->head; current = *(long *)(node->data); } else current = first_selectable; free(w); } else if (*pre_selection_index != '\0') { /* A prefix string or an index is expected. */ /* """""""""""""""""""""""""""""""""""""""" */ int len; char * ptr = pre_selection_index; if (*ptr == '#') { /* An index is expected. */ /* """"""""""""""""""""" */ ptr++; if (sscanf(ptr, "%ld%n", ¤t, &len) == 1 && len == (int)strlen(ptr)) { /* We got an index (numeric value). */ /* """""""""""""""""""""""""""""""" */ if (current < 0) current = first_selectable; if (current >= count) current = count - 1; if (!word_a[current].is_selectable) { if (current > last_selectable) current = last_selectable; else if (current < first_selectable) current = first_selectable; else while (current > first_selectable && !word_a[current].is_selectable) current--; } } else if (*ptr == '\0' || strcmp(ptr, "last") == 0) /* We got a special index (empty or last). */ /* """"""""""""""""""""""""""""""""""""""" */ current = last_selectable; else { fprintf(stderr, "Invalid index: %s.\n", ptr); exit(EXIT_FAILURE); } } else { /* A prefix is expected. */ /* """"""""""""""""""""" */ wchar_t * w; new_current = last_selectable; if (NULL != tst_prefix_search(tst_word, w = utf8_strtowcs(ptr), tst_cb_cli)) current = new_current; else current = first_selectable; free(w); } } else current = first_selectable; /* We now need to adjust the 'start'/'end' fields of the */ /* structure 'win'. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ set_win_start_end(&win, current, last_line); /* Re-associates /dev/tty with stdin and stdout. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (freopen("/dev/tty", "r", stdin) == NULL) { fprintf(stderr, "Unable to associate /dev/tty with stdin.\n"); exit(EXIT_FAILURE); } old_fd1 = dup(1); old_stdout = fdopen(old_fd1, "w"); setbuf(old_stdout, NULL); if (freopen("/dev/tty", "w", stdout) == NULL) { fprintf(stderr, "Unable to associate /dev/tty with stdout.\n"); exit(EXIT_FAILURE); } setvbuf(stdout, NULL, _IONBF, 0); /* Set the characteristics of the terminal. */ /* """""""""""""""""""""""""""""""""""""""" */ setup_term(fileno(stdin)); if (!get_cursor_position(&row, &col)) { fprintf(stderr, "The terminal does not have the capability to report " "the cursor position.\n"); restore_term(fileno(stdin)); exit(EXIT_FAILURE); } /* Initialize the search buffer with tab_real_max_size+1 NULs */ /* It will never be reallocated, only cleared. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ search_data.buf = xcalloc(1, word_real_max_size + 1 - daccess.flength); /* Hide the cursor. */ /* """""""""""""""" */ tputs(TPARM1(cursor_invisible), 1, outch); /* Force the display to start at a beginning of line. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ get_cursor_position(&term.curs_line, &term.curs_column); if (term.curs_column > 1) puts(""); /* Display the words window and its title for the first time. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ disp_message(message_lines_list, message_max_width, message_max_len, &term, &win, &langinfo); /* Before displaying the word windows for the first time when ins */ /* column or line mode, we need to ensure that the word under the */ /* cursor will be visible by setting the number of the first column */ /* to be displayed. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode) { long pos; long len; len = term.ncolumns - 3; /* Adjust win.first_column if the cursor is not visible. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (word_a[current].end - word_a[pos].start >= len) pos++; win.first_column = word_a[pos].start; } /* Save the initial cursor line and column, here only the line is */ /* interesting us. This will tell us if we are in need to compensate */ /* a terminal automatic scrolling. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ get_cursor_position(&term.curs_line, &term.curs_column); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); /* Determine the number of lines to move the cursor up if the window */ /* display needed a terminal scrolling. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (nl + term.curs_line - 1 > term.nlines) offset = term.curs_line + nl - term.nlines; else offset = 0; /* Set the cursor to the first line of the window. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ { long i; /* generic index in this block. */ for (i = 1; i < offset; i++) tputs(TPARM1(cursor_up), 1, outch); } /* Save again the cursor current line and column positions so that we */ /* will be able to put the terminal cursor back here. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ get_cursor_position(&term.curs_line, &term.curs_column); /* Arm the periodic timer. */ /* """"""""""""""""""""""" */ periodic_itv.it_value.tv_sec = 0; periodic_itv.it_value.tv_usec = TCK; periodic_itv.it_interval.tv_sec = 0; periodic_itv.it_interval.tv_usec = TCK; setitimer(ITIMER_REAL, &periodic_itv, NULL); /* Signal management. */ /* """""""""""""""""" */ void sig_handler(int s); sa.sa_handler = sig_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGWINCH, &sa, NULL); sigaction(SIGALRM, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sigaction(SIGSEGV, &sa, NULL); /* Main loop. */ /* """""""""" */ while (1) { int sc = 0; /* scancode */ /* Manage a segmentation fault by exiting with failure and restoring */ /* the terminal and the cursor. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (got_sigsegv) { fputs("SIGSEGV received!\n", stderr); tputs(TPARM1(carriage_return), 1, outch); tputs(TPARM1(cursor_normal), 1, outch); restore_term(fileno(stdin)); exit(128 + SIGSEGV); } /* Manage the hangup and termination signal by exiting with failure */ /* and restoring the terminal and the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (got_sigterm || got_sighup) { fputs("Interrupted!\n", stderr); tputs(TPARM1(carriage_return), 1, outch); tputs(TPARM1(cursor_normal), 1, outch); restore_term(fileno(stdin)); if (got_sigterm) exit(128 + SIGTERM); else exit(128 + SIGHUP); } /* If this alarm is triggered, then redisplay the window */ /* to remove the help message and disable this timer. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (got_help_alrm) { got_help_alrm = 0; /* Calculate the new metadata and draw the window again. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ last_line = build_metadata(&term, count, &win); help_mode = 0; nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } /* Reset the direct access selector if the direct access alarm rang. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (got_daccess_alrm) { got_daccess_alrm = 0; memset(daccess_stack, '\0', 6); daccess_stack_head = 0; daccess_timer = timers.direct_access; } if (got_search_alrm) { got_search_alrm = 0; /* Calculate the new metadata and draw the window again. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ last_line = build_metadata(&term, count, &win); search_mode = NONE; nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } if (got_winch) { got_winch = 0; got_winch_alrm = 0; winch_timer = timers.winch; /* Rearm the refresh timer. */ } /* If the timeout is set then decrement its remaining value */ /* Upon expiration of this alarm, we trigger a content update */ /* of the window. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (got_winch_alrm) { long i; /* generic index in this block */ int nlines, ncolumns; int line, column; int original_message_lines; got_winch_alrm = 0; /* Reset the flag signaling the need for a refresh. */ winch_timer = -1; /* Disarm the timer used for this refresh. */ if (message_lines_list != NULL && message_lines_list->len > 0) original_message_lines = message_lines_list->len + 1; else original_message_lines = 0; get_terminal_size(&nlines, &ncolumns, &term); /* Update term with the new number of lines and columns */ /* of the real terminal. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ term.nlines = nlines; term.ncolumns = ncolumns; /* Reset the number of lines if the terminal has enough lines. */ /* message_lines_list->len+1 is used here instead of */ /* win.message_lines because win.message_lines may have been */ /* altered by a previous scrolling and not yet recalculated. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (term.nlines <= original_message_lines) { win.message_lines = term.nlines - 1; win.max_lines = 1; } else { win.message_lines = original_message_lines; if (win.max_lines < term.nlines - win.message_lines) { if (win.asked_max_lines == 0) win.max_lines = term.nlines - win.message_lines; else { if (win.asked_max_lines > term.nlines - win.message_lines) win.max_lines = term.nlines - win.message_lines; else win.max_lines = win.asked_max_lines; } } else win.max_lines = term.nlines - win.message_lines; } /* Erase the visible part of the displayed window. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ for (i = 0; i < win.message_lines; i++) { tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(cursor_up), 1, outch); } tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(save_cursor), 1, outch); get_cursor_position(&line, &column); for (i = 1; i < nl + win.message_lines; i++) { if (line + i >= nlines) break; /* We have reached the last terminal line. */ tputs(TPARM1(cursor_down), 1, outch); tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); } tputs(TPARM1(restore_cursor), 1, outch); /* Get new cursor position. */ /* """""""""""""""""""""""" */ get_cursor_position(&term.curs_line, &term.curs_column); /* Calculate the new metadata and draw the window again. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ last_line = build_metadata(&term, count, &win); if (win.col_mode || win.line_mode) { long pos; long len; len = term.ncolumns - 3; /* Adjust win.first_column if the cursor is no more visible. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (word_a[current].end - word_a[pos].start >= len) pos++; win.first_column = word_a[pos].start; } disp_message(message_lines_list, message_max_width, message_max_len, &term, &win, &langinfo); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); /* Determine the number of lines to move the cursor up if the window */ /* display needed a terminal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (nl + win.message_lines + term.curs_line > term.nlines) offset = term.curs_line + nl + win.message_lines - term.nlines; else offset = 0; /* Set the cursor to the first line of the window. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ for (i = 1; i < offset; i++) tputs(TPARM1(cursor_up), 1, outch); /* Get new cursor position. */ /* """""""""""""""""""""""" */ get_cursor_position(&term.curs_line, &term.curs_column); /* Short-circuit the loop. */ /* """"""""""""""""""""""" */ continue; } /* and possibly set its reached value. */ /* The counter is frozen in search and help mode. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (timeout.initial_value && search_mode == NONE && !help_mode) { if (got_timeout_tick) { long i; char * timeout_string; got_timeout_tick = 0; timeout.remain--; if (!quiet_timeout && timeout.remain % FREQ == 0) { sprintf(timeout_seconds, "%5u", timeout.remain / FREQ); timeout_string = (char *)(((ll_node_t *)(message_lines_list->tail))->data); memcpy(timeout_string + 1, timeout_seconds, 5); /* Erase the current window. */ /* """"""""""""""""""""""""" */ for (i = 0; i < win.message_lines; i++) { tputs(TPARM1(cursor_up), 1, outch); tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); } tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); /* Display the words window and its title for the first time. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ disp_message(message_lines_list, message_max_width, message_max_len, &term, &win, &langinfo); } /* The timeout has expired. */ /* """""""""""""""""""""""" */ if (timeout.remain == 0) timeout.reached = 1; } } if (timeout.reached) { if (timeout.mode == QUIT) goto quit; else if (timeout.mode == CURRENT || timeout.mode == WORD) goto enter; } /* Pressed keys scancodes processing. */ /* """""""""""""""""""""""""""""""""" */ page = 1; /* Default number of lines to do down/up * * with PgDn/PgUp. */ sc = get_scancode(buffer, 15); if (sc && winch_timer < 0) /* Do not allow input when a window * * refresh is scheduled. */ { if (timeout.initial_value && buffer[0] != 0x0d && buffer[0] != 'q' && buffer[0] != 'Q' && buffer[0] != 3) { long i; char * timeout_string; /* Reset the timeout to its initial value. */ /* """"""""""""""""""""""""""""""""""""""" */ timeout.remain = timeout.initial_value; if (!quiet_timeout) { sprintf(timeout_seconds, "%5u", timeout.initial_value / FREQ); timeout_string = (char *)(((ll_node_t *)(message_lines_list->tail))->data); memcpy(timeout_string + 1, timeout_seconds, 5); /* Clear the message. */ /* """""""""""""""""" */ for (i = 0; i < win.message_lines; i++) { tputs(TPARM1(cursor_up), 1, outch); tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); } tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(clr_eol), 1, outch); /* Display the words window and its title for the first time. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ disp_message(message_lines_list, message_max_width, message_max_len, &term, &win, &langinfo); } setitimer(ITIMER_REAL, &periodic_itv, NULL); } if (search_mode == NONE) if (help_mode && buffer[0] != '?') { got_help_alrm = 1; continue; } switch (buffer[0]) { case 0x01: /* ^A */ if (search_mode != NONE) goto khome; break; case 0x1a: /* ^Z */ if (search_mode != NONE) goto kend; break; case 0x1b: /* ESC */ /* An escape sequence or a UTF-8 sequence has been pressed. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (memcmp("\x1bOH", buffer, 3) == 0 || memcmp("\x1bk", buffer, 2) == 0 || memcmp("\x1b[H", buffer, 3) == 0 || memcmp("\x1b[1~", buffer, 4) == 0 || memcmp("\x1b[7~", buffer, 4) == 0) { /* HOME key has been pressed. */ /* """""""""""""""""""""""""" */ if (search_mode != NONE) { khome: search_data.only_starting = 1; search_data.only_ending = 0; select_starting_matches(&win, &term, &search_data, &last_line); } else { /* Find the first selectable word. */ /* """"""""""""""""""""""""""""""" */ current = win.start; while (current < win.end && !word_a[current].is_selectable) current++; /* In column mode we need to take care of the */ /* horizontal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode) if (word_a[current].end < win.first_column) win.first_column = word_a[current].start; } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; } if (memcmp("\x1b[1;5H", buffer, 6) == 0 || memcmp("\x1b[1;2H", buffer, 6) == 0 || memcmp("\x1b[7^", buffer, 4) == 0) /* SHIFT/CTRL HOME key has been pressed. */ /* """"""""""""""""""""""""""""""""""""" */ goto kschome; if (memcmp("\x1bOF", buffer, 3) == 0 || memcmp("\x1bj", buffer, 2) == 0 || memcmp("\x1b[F", buffer, 3) == 0 || memcmp("\x1b[4~", buffer, 4) == 0 || memcmp("\x1b[8~", buffer, 4) == 0) { /* END key has been pressed. */ /* """"""""""""""""""""""""" */ if (search_mode != NONE) { kend: if (matches_count > 0 && search_mode != PREFIX) { search_data.only_starting = 0; search_data.only_ending = 1; select_ending_matches(&win, &term, &search_data, &last_line); } } else { /* Find the last selectable word. */ /* """""""""""""""""""""""""""""" */ current = win.end; while (current > win.start && !word_a[current].is_selectable) current--; /* In column mode we need to take care of the */ /* horizontal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode) { long pos; long len; len = term.ncolumns - 3; if (word_a[current].end >= len + win.first_column) { /* Find the first word to be displayed in this line. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (word_a[pos].start <= win.first_column) pos++; /* If the new current word cannot be displayed, search */ /* the first word in the line that can be displayed by */ /* iterating on pos. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ pos--; while (word_a[current].end - word_a[pos].start >= len) pos++; if (word_a[pos].start > 0) win.first_column = word_a[pos].start; } } } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; } if (memcmp("\x1b[1;5F", buffer, 6) == 0 || memcmp("\x1b[1;2F", buffer, 6) == 0 || memcmp("\x1b[8^", buffer, 4) == 0) /* SHIFT/CTRL END key has been pressed. */ /* """""""""""""""""""""""""""""""""""" */ goto kscend; if (memcmp("\x1bOD", buffer, 3) == 0 || memcmp("\x1b[D", buffer, 3) == 0) /* Left arrow key has been pressed. */ /* """""""""""""""""""""""""""""""" */ goto kl; if (memcmp("\x1bOC", buffer, 3) == 0 || memcmp("\x1b[C", buffer, 3) == 0) /* Right arrow key has been pressed. */ /* """"""""""""""""""""""""""""""""" */ goto kr; if (memcmp("\x1bOA", buffer, 3) == 0 || memcmp("\x1b[A", buffer, 3) == 0) /* Up arrow key has been pressed. */ /* """""""""""""""""""""""""""""" */ goto ku; if (memcmp("\x1bOB", buffer, 3) == 0 || memcmp("\x1b[B", buffer, 3) == 0) /* Down arrow key has been pressed. */ /* """""""""""""""""""""""""""""""" */ goto kd; if (memcmp("\x1b[I", buffer, 3) == 0 || memcmp("\x1b[5~", buffer, 4) == 0) /* PgUp key has been pressed. */ /* """""""""""""""""""""""""" */ goto kpp; if (memcmp("\x1b[G", buffer, 3) == 0 || memcmp("\x1b[6~", buffer, 4) == 0) /* PgDn key has been pressed. */ /* """""""""""""""""""""""""" */ goto knp; if (memcmp("\x1b[L", buffer, 3) == 0 || memcmp("\x1b[2~", buffer, 4) == 0) /* Ins key has been pressed. */ /* """"""""""""""""""""""""" */ goto kins; if (memcmp("\x1b[3~", buffer, 4) == 0) /* Del key has been pressed. */ /* """"""""""""""""""""""""" */ goto kdel; if (memcmp("\x1b[1;5C", buffer, 6) == 0 || memcmp("\x1bOc", buffer, 3) == 0) /* CTRL -> has been pressed. */ /* """""""""""""""""""""""""" */ goto keol; if (memcmp("\x1b[1;5D", buffer, 6) == 0 || memcmp("\x1bOd", buffer, 3) == 0) /* CTRL <- key has been pressed. */ /* """"""""""""""""""""""""""""" */ goto ksol; if (buffer[0] == 0x1b && buffer[1] == '\0') { /* ESC key has been pressed. */ /* """"""""""""""""""""""""" */ search_mode_t old_search_mode = search_mode; /* Cancel the search timer. */ /* """""""""""""""""""""""" */ search_timer = 0; search_data.fuzzy_err = 0; search_data.only_starting = 0; search_data.only_ending = 0; if (help_mode) nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); /* Reset the direct access selector stack. */ /* """"""""""""""""""""""""""""""""""""""" */ memset(daccess_stack, '\0', 6); daccess_stack_head = 0; daccess_timer = timers.direct_access; /* Clean the potential matching words non empty list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ search_mode = NONE; if (matches_count > 0 || old_search_mode != search_mode) { clean_matches(&search_data, word_real_max_size); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } break; } /* Else ignore key. */ break; quit: case 'q': case 'Q': case 3: /* ^C */ /* q or Q of ^C has been pressed. */ /* """""""""""""""""""""""""""""" */ if (search_mode != NONE && buffer[0] != 3) goto special_cmds_when_searching; { long i; /* Generic index in this block. */ for (i = 0; i < win.message_lines; i++) tputs(TPARM1(cursor_up), 1, outch); if (toggles.del_line) { tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(save_cursor), 1, outch); for (i = 1; i < nl + win.message_lines; i++) { tputs(TPARM1(cursor_down), 1, outch); tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(clr_bol), 1, outch); } tputs(TPARM1(restore_cursor), 1, outch); } else { for (i = 1; i < nl + win.message_lines; i++) tputs(TPARM1(cursor_down), 1, outch); puts(""); } } /* Restore the visibility of the cursor. */ /* """"""""""""""""""""""""""""""""""""" */ tputs(TPARM1(cursor_normal), 1, outch); if (buffer[0] == 3) { if (int_string != NULL) fprintf(old_stdout, "%s", int_string); /* Set the cursor at the start on the line an restore the */ /* original terminal state before exiting. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(carriage_return), 1, outch); restore_term(fileno(stdin)); if (int_as_in_shell) exit(128 + SIGINT); } else restore_term(fileno(stdin)); exit(EXIT_SUCCESS); case 0x0c: /* Form feed (^L) is a traditional method to redraw a screen. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; case 'n': case ' ': /* n or the space bar has been pressed. */ /* """""""""""""""""""""""""""""""""""" */ if (search_mode != NONE) goto special_cmds_when_searching; if (matches_count > 0) { long pos = find_next_matching_word(matching_words_a, matches_count, current, &matching_word_cur_index); if (pos >= 0) current = pos; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } break; case 'N': /* N has been pressed.*/ /* """"""""""""""""""" */ if (search_mode != NONE) goto special_cmds_when_searching; if (matches_count > 0) { long pos = find_prev_matching_word(matching_words_a, matches_count, current, &matching_word_cur_index); if (pos >= 0) current = pos; } if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; case 's': /* s has been pressed. */ /* """"""""""""""""""" */ if (search_mode != NONE) goto special_cmds_when_searching; if (matches_count > 0) { long pos; if (best_matches_count > 0) pos = find_next_matching_word(best_matching_words_a, best_matches_count, current, &matching_word_cur_index); else pos = find_next_matching_word(matching_words_a, matches_count, current, &matching_word_cur_index); if (pos >= 0) current = pos; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } break; case 'S': /* S has been pressed. */ /* """"""""""""""""""" */ if (search_mode != NONE) goto special_cmds_when_searching; if (matches_count > 0) { long pos; if (best_matches_count > 0) pos = find_prev_matching_word(best_matching_words_a, best_matches_count, current, &matching_word_cur_index); else pos = find_prev_matching_word(matching_words_a, matches_count, current, &matching_word_cur_index); if (pos >= 0) current = pos; } if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; enter: case 0x0d: /* CR */ { /* has been pressed. */ /* """"""""""""""""""""""""" */ int extra_lines; char * output_str; output_t * output_node; int width = 0; wchar_t * w; long i; /* Generic index in this block. */ if (help_mode) nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); if (search_mode != NONE) { /* Cancel the search timer. */ /* """""""""""""""""""""""" */ search_timer = 0; search_mode = NONE; search_data.only_starting = 0; search_data.only_ending = 0; nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); if (!toggles.enter_val_in_search) break; } /* Erase or jump after the window before printing the */ /* selected string. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (toggles.del_line) { for (i = 0; i < win.message_lines; i++) tputs(TPARM1(cursor_up), 1, outch); tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(clr_bol), 1, outch); tputs(TPARM1(save_cursor), 1, outch); for (i = 1; i < nl + win.message_lines; i++) { tputs(TPARM1(cursor_down), 1, outch); tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(clr_bol), 1, outch); } tputs(TPARM1(restore_cursor), 1, outch); } else { for (i = 1; i < nl; i++) tputs(TPARM1(cursor_down), 1, outch); puts(""); } /* When a timeout of type WORD is set, prints the specified word */ /* else prints the current selected entries. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (timeout.initial_value > 0 && timeout.remain == 0 && timeout.mode == WORD) fprintf(old_stdout, "%s", timeout_word); else { char * num_str; char * str; if (toggles.taggable) { ll_t * output_list = ll_new(); ll_node_t * node; /* When using -P, updates the tagging order of this word to */ /* make sure that the output will be correctly sorted. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (toggles.pinable) word_a[current].tag_order = next_tag_nb++; for (wi = 0; wi < count; wi++) { if (word_a[wi].is_tagged || wi == current) { /* If the -p option is not used we do not take into */ /* account an untagged word under the cursor. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ if (wi == current && tagged_words > 0 && !toggles.autotag && !word_a[wi].is_tagged) continue; /* Chose the original string to print if the current one */ /* has been altered by a possible expansion. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ output_node = xmalloc(sizeof(output_t)); if (word_a[wi].orig != NULL) str = word_a[wi].orig; else str = word_a[wi].str; if (word_a[wi].is_numbered && daccess.num_sep) { num_str = xstrndup(str + 1, daccess.length); ltrim(num_str, " "); rtrim(num_str, " ", 0); output_node->output_str = concat(num_str, daccess.num_sep, str + daccess.flength, (char *)0); free(num_str); } else output_node->output_str = xstrdup(str + daccess.flength); output_node->order = word_a[wi].tag_order; /* Trim the spaces if -k is not given. */ /* """"""""""""""""""""""""""""""""""" */ if (!toggles.keep_spaces) { ltrim(output_node->output_str, " \t"); rtrim(output_node->output_str, " \t", 0); } ll_append(output_list, output_node); } } /* If nothing is selected, exist without printing anything. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (output_list->head == NULL) goto exit; /* If -P is in use, then sort the output list. */ /* """"""""""""""""""""""""""""""""""""""""""" */ if (toggles.pinable) ll_sort(output_list, tag_comp, tag_swap); /* And print them. */ /* """"""""""""""" */ node = output_list->head; while (node->next != NULL) { str = ((output_t *)(node->data))->output_str; fprintf(old_stdout, "%s", str); width += wcswidth((w = utf8_strtowcs(str)), 65535); free(w); free(str); free(node->data); if (win.sel_sep != NULL) { fprintf(old_stdout, "%s", win.sel_sep); width += wcswidth((w = utf8_strtowcs(win.sel_sep)), 65535); free(w); } else { fprintf(old_stdout, " "); width++; } node = node->next; } str = ((output_t *)(node->data))->output_str; fprintf(old_stdout, "%s", str); width += wcswidth((w = utf8_strtowcs(str)), 65535); free(w); free(str); free(node->data); } else { /* Chose the original string to print if the current one has */ /* been altered by a possible expansion. */ /* Once this made, print it. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (word_a[current].orig != NULL) str = word_a[current].orig; else str = word_a[current].str; if (word_a[current].is_numbered && daccess.num_sep) { num_str = xstrndup(str + 1, daccess.length); ltrim(num_str, " "); rtrim(num_str, " ", 0); output_str = concat(num_str, daccess.num_sep, str + daccess.flength, (char *)0); free(num_str); } else output_str = str + daccess.flength; /* Trim the spaces if -k is not given. */ /* """"""""""""""""""""""""""""""""""" */ if (!toggles.keep_spaces) { ltrim(output_str, " \t"); rtrim(output_str, " \t", 0); } width = wcswidth((w = utf8_strtowcs(output_str)), 65535); free(w); /* And print it. */ /* """"""""""""" */ fprintf(old_stdout, "%s", output_str); } /* If the output stream is a terminal. */ /* """"""""""""""""""""""""""""""""""" */ if (isatty(old_fd1)) { /* width is (in term of terminal columns) the size of the */ /* string to be displayed. */ /* */ /* With that information, count the number of terminal lines */ /* printed. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ extra_lines = width / term.ncolumns; /* Clean the printed line and all the extra lines used. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(delete_line), 1, outch); for (i = 0; i < extra_lines; i++) { tputs(TPARM1(cursor_up), 1, outch); tputs(TPARM1(clr_eol), 1, outch); tputs(TPARM1(clr_bol), 1, outch); } } } exit: /* Restore the visibility of the cursor. */ /* """"""""""""""""""""""""""""""""""""" */ tputs(TPARM1(cursor_normal), 1, outch); /* Set the cursor at the start on the line an restore the */ /* original terminal state before exiting. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ tputs(TPARM1(carriage_return), 1, outch); restore_term(fileno(stdin)); exit(EXIT_SUCCESS); } ksol: /* Go to the start of the line. */ /* """""""""""""""""""""""""""" */ if (search_mode != NONE) search_mode = NONE; case 'H': if (search_mode == NONE) { current = first_word_in_line_a[line_nb_of_word_a[current]]; while (!word_a[current].is_selectable) current++; win.first_column = 0; set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } else goto special_cmds_when_searching; break; kl: /* Cursor Left key has been pressed. */ /* """"""""""""""""""""""""""""""""" */ if (search_mode != NONE) search_mode = NONE; case 'h': if (search_mode == NONE) move_left(&win, &term, &toggles, &search_data, &langinfo, &nl, last_line, tmp_word); else goto special_cmds_when_searching; break; keol: /* Go to the end of the line. */ /* """""""""""""""""""""""""" */ if (search_mode != NONE) search_mode = NONE; case 'L': if (search_mode == NONE) { long cur_line = line_nb_of_word_a[current]; current = get_line_last_word(cur_line, last_line); win.first_column = win.real_max_width - 1 - (term.ncolumns - 3); while (!word_a[current].is_selectable) current--; set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } else goto special_cmds_when_searching; break; kr: /* Right key has been pressed. */ /* """"""""""""""""""""""""""" */ if (search_mode != NONE) search_mode = NONE; case 'l': if (search_mode == NONE) move_right(&win, &term, &toggles, &search_data, &langinfo, &nl, last_line, tmp_word); else goto special_cmds_when_searching; break; case 0x0b: /* ^K key has been pressed. */ /* """""""""""""""""""""""" */ goto kschome; case 'K': if (search_mode != NONE) goto special_cmds_when_searching; kpp: /* PgUp key has been pressed. */ /* """""""""""""""""""""""""" */ page = win.max_lines; ku: /* Cursor Up key has been pressed. */ /* """"""""""""""""""""""""""""""" */ if (search_mode != NONE) search_mode = NONE; case 'k': if (search_mode == NONE) move_up(&win, &term, &toggles, &search_data, &langinfo, &nl, page, first_selectable, last_line, tmp_word); else goto special_cmds_when_searching; break; kschome: /* Go to the first selectable word. */ /* """""""""""""""""""""""""""""""" */ current = 0; if (search_mode != NONE) search_mode = NONE; /* Find the first selectable word. */ /* """"""""""""""""""""""""""""""" */ while (!word_a[current].is_selectable) current++; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* In column mode we need to take care of the */ /* horizontal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode) { long pos; /* Adjust win.first_column if the cursor is */ /* no more visible. */ /* """""""""""""""""""""""""""""""""""""""" */ pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (word_a[current].end - word_a[pos].start >= term.ncolumns - 3) pos++; win.first_column = word_a[pos].start; } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; case 0x0a: /* ^J key has been pressed. */ /* """""""""""""""""""""""" */ goto kscend; case 'J': if (search_mode != NONE) goto special_cmds_when_searching; knp: /* PgDn key has been pressed. */ /* """""""""""""""""""""""""" */ page = win.max_lines; kd: /* Cursor Down key has been pressed. */ /* """"""""""""""""""""""""""""""""" */ if (search_mode != NONE) search_mode = NONE; case 'j': if (search_mode == NONE) move_down(&win, &term, &toggles, &search_data, &langinfo, &nl, page, last_selectable, last_line, tmp_word); else goto special_cmds_when_searching; break; kscend: /* Go to the last selectable word. */ /* """"""""""""""""""""""""""""""" */ current = count - 1; if (search_mode != NONE) search_mode = NONE; /* Find the first selectable word. */ /* """"""""""""""""""""""""""""""" */ while (!word_a[current].is_selectable) current--; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* In column mode we need to take care of the */ /* horizontal scrolling. */ /* """""""""""""""""""""""""""""""""""""""""" */ if (win.col_mode || win.line_mode) { long pos; /* Adjust win.first_column if the cursor is no more visible. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ pos = first_word_in_line_a[line_nb_of_word_a[current]]; while (word_a[current].end - word_a[pos].start >= term.ncolumns - 3) pos++; win.first_column = word_a[pos].start; } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; case '/': /* Generic search method according the misc settings. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ if (misc.default_search_method == PREFIX) goto prefix_method; else if (misc.default_search_method == SUBSTRING) goto substring_method; else if (misc.default_search_method == FUZZY) goto fuzzy_method; break; case '~': case '*': /* ~ or * key has been pressed */ /* (start of a fuzzy search session). */ /* """""""""""""""""""""""""""""""""" */ fuzzy_method: /* Set the search timer. */ /* """"""""""""""""""""" */ search_timer = timers.search; /* default 10 s. */ if (search_mode == NONE) { search_mode = FUZZY; if (old_search_mode != FUZZY) { old_search_mode = FUZZY; clean_matches(&search_data, word_real_max_size); } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } else goto special_cmds_when_searching; break; case '\'': case '\"': /* ' or " key has been pressed */ /* (start of a substring search session). */ /* """""""""""""""""""""""""""""""""""""" */ substring_method: /* Set the search timer. */ /* """"""""""""""""""""" */ search_timer = timers.search; /* default 10 s. */ if (search_mode == NONE) { search_mode = SUBSTRING; if (old_search_mode != SUBSTRING) { old_search_mode = SUBSTRING; clean_matches(&search_data, word_real_max_size); } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } else goto special_cmds_when_searching; break; case '=': case '^': /* ^ or = key has been pressed */ /* (start of a prefix search session). */ /* """"""""""""""""""""""""""""""""""" */ prefix_method: /* Set the search timer. */ /* """"""""""""""""""""" */ search_timer = timers.search; /* default 10 s. */ if (search_mode == NONE) { search_mode = PREFIX; if (old_search_mode != PREFIX) { old_search_mode = PREFIX; clean_matches(&search_data, word_real_max_size); } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); break; } else goto special_cmds_when_searching; break; kins: /* The INS key has been pressed to tag a word if */ /* tagging is enabled. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ if (toggles.taggable) { if (word_a[current].is_tagged == 0) { tagged_words++; word_a[current].is_tagged = 1; if (toggles.pinable) word_a[current].tag_order = next_tag_nb++; nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } break; kdel: /* The DEL key has been pressed to untag a word if */ /* tagging is enabled. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ if (toggles.taggable) { if (word_a[current].is_tagged == 1) { word_a[current].is_tagged = 0; tagged_words--; nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } break; case 't': /* t has been pressed to tag/untag a word if */ /* tagging is enabled. */ /* """"""""""""""""""""""""""""""""""""""""" */ if (search_mode == NONE) { if (toggles.taggable) { if (word_a[current].is_tagged) { word_a[current].is_tagged = 0; tagged_words--; } else { word_a[current].is_tagged = 1; tagged_words++; if (toggles.pinable) word_a[current].tag_order = next_tag_nb++; } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } else goto special_cmds_when_searching; break; case 'T': /* T has been pressed to tag all matching words resulting */ /* from a previous search if tagging is enabled. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (search_mode == NONE) { if (toggles.taggable) { long i, n; for (i = 0; i < matches_count; i++) { n = matching_words_a[i]; if (!word_a[n].is_tagged) { word_a[n].is_tagged = 1; tagged_words++; if (toggles.pinable) word_a[n].tag_order = next_tag_nb++; } } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } else goto special_cmds_when_searching; break; case 'U': /* U has been pressed to untag all matching words resulting */ /* from a previous search if tagging is enabled. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (search_mode == NONE) { if (toggles.taggable) { long i, n; for (i = 0; i < matches_count; i++) { n = matching_words_a[i]; if (word_a[n].is_tagged) { word_a[n].is_tagged = 0; tagged_words--; } } nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } else goto special_cmds_when_searching; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* A digit has been pressed to build a number to be used for */ /* A direct acces to a words if direct access is enabled. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ { if (search_mode == NONE && daccess.mode != DA_TYPE_NONE) { wchar_t * w; long * pos; /* Set prev_current to the initial current word to be */ /* able to return here if the first direct access fails. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (daccess_stack_head == 0) prev_current = current; if (daccess_stack_head == daccess.length) break; daccess_stack[daccess_stack_head] = buffer[0]; daccess_stack_head++; w = utf8_strtowcs(daccess_stack); pos = tst_search(tst_daccess, w); free(w); if (pos != NULL) { current = *pos; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } else { if (current != prev_current) { current = prev_current; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } daccess_timer = timers.direct_access; } else goto special_cmds_when_searching; } break; case 0x08: /* ^H */ case 0x7f: /* BS */ /* backspace/CTRL-H management. */ /* """""""""""""""""""""""""""" */ { long i; if (daccess_stack_head > 0) daccess_stack[--daccess_stack_head] = '\0'; if (search_mode != NONE) { if (search_data.utf8_len > 0) { char * prev; prev = utf8_prev(search_data.buf, search_data.buf + search_data.len - 1); if (search_data.utf8_len == search_data.fuzzy_err_pos - 1) { search_data.fuzzy_err = 0; search_data.fuzzy_err_pos = -1; } search_data.utf8_len--; if (prev) { *(utf8_next(prev)) = '\0'; search_data.len = prev - search_data.buf + 1; } else { *search_data.buf = '\0'; search_data.len = 0; for (i = 0; i < matches_count; i++) { long n = matching_words_a[i]; word_a[n].is_matching = 0; memset(word_a[n].bitmap, '\0', (word_a[n].mb - daccess.flength) / CHAR_BIT + 1); } matches_count = 0; nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } else my_beep(&toggles); if (search_data.utf8_len > 0) goto special_cmds_when_searching; else /* When there is only one glyph in the search list in */ /* FUZZY and SUBSTRING mode then all is already done except */ /* the cleanup of the first level of the tst_search_list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (search_mode != PREFIX) { sub_tst_t * sub_tst_data; ll_node_t * node; node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); search_data.fuzzy_err = 0; sub_tst_data->count = 0; } } } break; case '?': /* Help mode. */ /* """""""""" */ if (search_mode == NONE) { help(&win, &term, last_line, &toggles); help_mode = 1; /* Arm the help timer. */ /* """"""""""""""""""" */ help_timer = timers.help; /* default 15 s. */ } else goto special_cmds_when_searching; break; special_cmds_when_searching: default: { int c; /* byte index in the scancode string .*/ sub_tst_t * sub_tst_data; unsigned long long index; long i; if (search_mode != NONE) { long old_len = search_data.len; long old_utf8_len = search_data.utf8_len; ll_node_t * node; wchar_t * ws; /* Copy all the bytes included in the key press to buffer. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (buffer[0] != 0x08 && buffer[0] != 0x7f) /* Backspace. */ { /* The only case where we have to manage backspace hits */ /* here is if the user has entered them in fuzzy search */ /* mode. As the search buffer has already been amended, */ /* we do not have to update the search buffer again. */ /* '''''''''''''''''''''''''''''''''''''''''''''''''''' */ for (c = 0; c < sc && search_data.utf8_len < word_real_max_size - daccess.flength; c++) search_data.buf[search_data.len++] = buffer[c]; /* Update the glyph array with the content of the search */ /* buffer. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""" */ if (search_data.utf8_len < word_real_max_size - daccess.flength) { search_data.utf8_off_a[search_data.utf8_len] = old_len; search_data.utf8_len_a[search_data.utf8_len] = search_data.len - old_len; search_data.utf8_len++; } } /* Restart the search timer. */ /* """"""""""""""""""""""""" */ search_timer = timers.search; /* default 10 s. */ if (search_mode == PREFIX) { ws = utf8_strtowcs(search_data.buf); /* Purge the matching words list. */ /* """""""""""""""""""""""""""""" */ for (i = 0; i < matches_count; i++) { long n = matching_words_a[i]; word_a[n].is_matching = 0; memset(word_a[n].bitmap, '\0', (word_a[n].mb - daccess.flength) / CHAR_BIT + 1); } matches_count = 0; tst_prefix_search(tst_word, ws, tst_cb); /* Latches_count is updated by tst_cb. */ /* """"""""""""""""""""""""""""""""""" */ if (matches_count > 0) { if (search_data.len == old_len && matches_count == 1 && buffer[0] != 0x08 && buffer[0] != 0x7f) my_beep(&toggles); else { /* Adjust the bitmap to the ending version. */ /* """""""""""""""""""""""""""""""""""""""" */ update_bitmaps(search_mode, &search_data, NO_AFFINITY); current = matching_words_a[0]; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } else { my_beep(&toggles); search_data.len = old_len; search_data.utf8_len = old_utf8_len; search_data.buf[search_data.len] = '\0'; } } else if (search_mode == FUZZY) { /* tst_search_list: [sub_tst_t *] -> [sub_tst_t *]... */ /* ^ ^ */ /* | | */ /* level 1 level_2 */ /* */ /* Each sub_tst_t * points to a data structure including */ /* a sorted array to nodes in the words tst. */ /* Each of these node starts a matching candidate. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ wchar_t * w = utf8_strtowcs(search_data.buf + old_len); /* zero previous matching indicators */ /* """"""""""""""""""""""""""""""""" */ for (i = 0; i < matches_count; i++) { long n = matching_words_a[i]; word_a[n].is_matching = 0; memset(word_a[n].bitmap, '\0', (word_a[n].mb - daccess.flength) / CHAR_BIT + 1); } matches_count = 0; if (buffer[0] == 0x08 || buffer[0] == 0x7f) /* Backspace */ { node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); sub_tst_data->count = 0; if (tst_search_list->len > 0) { free(sub_tst_data->array); free(sub_tst_data); ll_delete(tst_search_list, tst_search_list->tail); } if (search_data.utf8_len == search_data.fuzzy_err_pos - 1) { search_data.fuzzy_err = 0; search_data.fuzzy_err_pos = -1; } } else { if (search_data.utf8_len == 1) { /* Search all the sub-tst trees having the searched */ /* character as children, the resulting sub-tst are put */ /* in the sub tst array attached to the currently */ /* searched symbol. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ tst_fuzzy_traverse(tst_word, NULL, 0, w[0]); node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); if (sub_tst_data->count == 0) { my_beep(&toggles); search_data.len = 0; search_data.utf8_len = 0; search_data.buf[0] = '\0'; break; } } else { /* Prevent the list to grow larger than the maximal */ /* word's length. */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ if (tst_search_list->len < word_real_max_size - daccess.flength) { /* use the results in the level n-1 list to build the */ /* level n list. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ int rc; sub_tst_t * tst_fuzzy_level_data; tst_fuzzy_level_data = sub_tst_new(); ll_append(tst_search_list, tst_fuzzy_level_data); node = tst_search_list->tail->prev; sub_tst_data = (sub_tst_t *)(node->data); rc = 0; for (index = 0; index < sub_tst_data->count; index++) rc += tst_fuzzy_traverse(sub_tst_data->array[index], NULL, 1, w[0]); if (rc == 0) { free(tst_fuzzy_level_data->array); free(tst_fuzzy_level_data); ll_delete(tst_search_list, tst_search_list->tail); search_data.fuzzy_err = 1; if (search_data.fuzzy_err_pos == -1) search_data.fuzzy_err_pos = search_data.utf8_len; my_beep(&toggles); search_data.len = old_len; search_data.utf8_len = old_utf8_len; search_data.buf[search_data.len] = '\0'; } } else my_beep(&toggles); } } free(w); /* Process this level to mark the word found as a matching */ /* word if any. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); for (index = 0; index < sub_tst_data->count; index++) tst_traverse(sub_tst_data->array[index], set_matching_flag, 0); /* Update the bitmap and re-display the window. */ /* """""""""""""""""""""""""""""""""""""""""""" */ if (matches_count > 0) { if (search_data.only_starting) select_starting_matches(&win, &term, &search_data, &last_line); else if (search_data.only_ending) select_ending_matches(&win, &term, &search_data, &last_line); else /* Adjust the bitmap to the ending version. */ /* """""""""""""""""""""""""""""""""""""""" */ update_bitmaps(search_mode, &search_data, NO_AFFINITY); current = matching_words_a[0]; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } else my_beep(&toggles); } else /* SUBSTRING. */ { wchar_t * w = utf8_strtowcs(search_data.buf); /* Purge the matching words list. */ /* """""""""""""""""""""""""""""" */ for (i = 0; i < matches_count; i++) { long n = matching_words_a[i]; word_a[n].is_matching = 0; memset(word_a[n].bitmap, '\0', (word_a[n].mb - daccess.flength) / CHAR_BIT + 1); } matches_count = 0; if (search_data.utf8_len == 1) { /* Search all the sub-tst trees having the searched */ /* character as children, the resulting sub-tst are put */ /* in the level list corresponding to the letter order. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */ tst_substring_traverse(tst_word, NULL, 0, w[0]); node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); for (index = 0; index < sub_tst_data->count; index++) tst_traverse(sub_tst_data->array[index], set_matching_flag, 0); } else { /* Search for the rest of the word in all the sub-tst */ /* trees previously found. */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ node = tst_search_list->tail; sub_tst_data = (sub_tst_t *)(node->data); matches_count = 0; for (index = 0; index < sub_tst_data->count; index++) tst_prefix_search(sub_tst_data->array[index], w + 1, tst_cb); } if (matches_count > 0) { if (search_data.len == old_len && matches_count == 1 && buffer[0] != 0x08 && buffer[0] != 0x7f) my_beep(&toggles); else { if (search_data.only_starting) select_starting_matches(&win, &term, &search_data, &last_line); else if (search_data.only_ending) select_ending_matches(&win, &term, &search_data, &last_line); else update_bitmaps(search_mode, &search_data, NO_AFFINITY); current = matching_words_a[0]; if (current < win.start || current > win.end) last_line = build_metadata(&term, count, &win); /* Set new first column to display. */ /* """""""""""""""""""""""""""""""" */ set_new_first_column(&win, &term); nl = disp_lines(&win, &toggles, current, count, search_mode, &search_data, &term, last_line, tmp_word, &langinfo); } } else { my_beep(&toggles); search_data.len = old_len; search_data.utf8_len--; search_data.buf[search_data.len] = '\0'; } } } } } } } } smenu-0.9.17/smenu.gif000066400000000000000000006145471400523266500146010ustar00rootroot00000000000000GIF89aFa`_7<4,';K:q}F*g7 fM5/K_B- *vG[*:5[doFsX8j .UN{֢gѫn(xИRԷƏ=_LiHFTӽ f |4[/4,! NETSCAPE2.0! ,F@pH,Ȥrl:ШtJZجvzxL.zn|N~M ~X8M%'0-VL*&%-,k788/J( 2.Ǵ80J)q070H 'I08ʦI% 0 !ʒ^`0!ÇY`fH"lȱǏfNRbɲ˗J$\ "@ ԍH(lЂ'6J*pHBA 2XK쬙t+p}TjE1˷*J@b+>KǐKL˘HsC Ө T$ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2W !,@p((ȣr`:`€$Z. Ɔ>E1` ]FuD2xpUn('BnMw1C0 .f' -*xz}, #IOС A!,.x@A@ Ȥr,6@h4U(Ƃ}0fY3WQԢ2߲g=Ux1 SaoqE mo/W#$&Fw~ " '`J #D mUGHmA!,6p@0@Ȥrd _`d]l\p-}0$ZY*sɬn_XZ{~u#b |V'}V'Yr~mBmKGC mA!,>l@p!Ƥr/*m\\ e&^뙫V4\uGv$ d 'a{S%'zKC,VHI A!,F0H@k8OwdB|\A,qp,!,N`@p((Ȥ2 %ip 8E-vXi*PA-q*RMn .gn#v cwv cBA!,Vz@0 (Ȥl:e0,րDhmLf-JрZE8xz{~uwysr{(h31{,#[pHFI GBA!,^}@P((ȤrTt3I4 f:N%s@hAQ#To \#*wf(314{\( (.x\ fhIE j¡A!,fi@p!(Ȥr$%SID>h# ha󸬍/='D$]ryC #FLf" wJoBRrOO_A!,nZ@p!(Ȥr$%SID>͆%f7]l. &H15]7#M_,Xz42}v${suJ nprJV g|T #`IEF K`A!,r`HȤ( 'AsIK8 PF ,VD=F'm|s(Kc"Bc !JD`TFB `A!,  ?@aƤR)$"ФaxTXQ:Q}V%ua+nMO|.unA!,@PȤrl:O4:RجvzxL.zn|Ns0}O[p}a$80REM787z08777}8/vnf Va]8`\ZyqGA!n,(sSȤrl:ШtJZƫr+hWupׁ;aZ-\0{ }nY_~8Wa$8wVva77Zni_hj_CbBtGO_ VA!,.x@0 (Ȥr$}8MBE\,-QkpMHhmOtu15{|-,c'f{jS/ v (zg]%1rr]\B GPPhDA!,2WpärX:,CFgv%#m)~`4(\ px.kx}y^GA!,+@pH,Ȥr,TڀC'c$mLS,.k$.F>lVC*kgX"-"'S)X'"1fg$ X # uv mgp-Og0 4XW BJsB"+3bw~2.abquwmd-F.RGK @@`A*!,/1e@`ȤrL(\ ,J,4'-br*b`|2Qsa-[&jV -iq,e`GyeFye \A!,61z@0 (.¤rl:RL'|@6)s9Rn*#Z/~ t1lxtk~2r|wXf1#oDF oA!,>1}@`H ȤQ9T~@ha5}0`Bb,XrQxߴnp21  Say3sC a-,fX$&o`% 'n#CaBUaA!,F1@p!Ȥrl$b yGK|2HRT؍>uKj3.V*&{k i]1,GoJ \h|L j%-V(|p/ z I'mkt 'MBC,]LE YA!,V>I8ͻEI(&GaR! ,^.@pH, Ȥr*:ɴAUb4cs2fR AR,j]"!D%qI21iiH$ pC%-\3 u lTCyyěBA!,n-[@pH,Ȥri<1=il@oDeH ]548~|w NtBA!,~.s@0@ ȤrH'\ 4|2PEe k;DV٘^`i]Z'd|C0st/ F0C] |G tA!,>I8{I(&7aR! ,36@0 (Ȥrv AL8Xl%vǯxL.0ZowfGqBc} A!,-G@p ȤRx(.0H@k8ͻC"UB+bNg,U! ,.@pH, ȤrZ ɨtDƉ&=x4 M"3P'Cbo f]LWrJtgjE*'SB vS(14t)D qBP{ hCA! ,-%@pH,Ȥ(X:sz>!e'"ruk4d#,} }r_sKIt 4)CKwTNTSNNS*'_OT*14 "iMHqS YÔKD\ RDA!,39`d)lSb$tRq<+p݄i1ШtIBIzU! ,1c@p(Ȥ(, ђ0ciPL"&Yr`k08qMJ6-zؤZ 0{/ , {{GL{ SA!,>I5=ɱdIb[,!,+j@pH,H%QIa8sSI 7rMj 1htD@t/ RdY%-hN[&tqtft*{oNtS IA!,- `H,Er`ɁI-:"p2=-as9AD n Y cC w -{}UcCW Dw* |F".Ew)% $YD{yeCS~E ӖA!,>I͓^dI\,!,&+l@PȤr$*$b&KHj@FK6z\,fƨM-TU`QL[6t(+t3-i}[l_VbdV*.#x["nKDQ HoA!,>9@p @ry# X(q(I{FQKn#G$D#\|YB}{ZHPx}IP aA!,E@pH,'ͰĀa8 S؆Ѣ 'Pi2jc'(FIy$og(.#D0w( xXvJB U!JLpF \DA!,Gc`(,Ȥx"X.rz,esR}U0rl0̙Ƥ=6oq|xWp7&n0'!nHdW A!,U)VPƱdg!,Gd@pH,HZ8pY @*s0FM3 D@M3D 4Nk{(Z{31&$ {/ztC[I [A! ,G`(,Frdr2CQq,lnOi=,б %Z72s M]{_[ kmMZ| y}K#yzlnM(&C$w0M' .,M!D'~ oA!,GU@00$ȤrY,qz0glƫil9+@#v CrTo|Os|tb mA!,G[@p(ȤR8E'͒Xc D@B%m0è|$٨}N .t|J!nGH A!,&E@0@ȣI:MY Mk8"!O LJA%<`bJy9&B0  B$ O#QS}PW#H,RO 0Ou#M"' 'vNv !Z~ZZA!,7F]@p"kiȤrrє@t,5UvK@[@Y(7uݖOVw˚t cS 'GiSlSRSiA!,>G`@p(ȤR8)EǒXԘtlRB2d0*{.[6 !GU' ', \D'B!qGjA!,FGr`(,ȤNJƩiDOhqU"ؤd 8ҙȰͧ inw  Cl'_"' -TJ_B!waK wA!,MB@pH,Ȥrl/r8Oͱ]DXf٤ElNC6̲ςZHVy,I$ B !ph/ hE DyE'hC F A!,]UIùzFd)!,eEJ@pH,d@p 0=礉ͻZ0)5kIJ|CJ LA!,mE\@@@H,HAr'ظʵiIF]8)5yYoD WX$F qA!,B@pH,Ȥr`2)q*E!EǦ`rsyNHJ8ksWi\B2.,y+V, BmprG2- Dj1I*&HG(E% ˠA!,Em@@@HA4%2c\-q[MFh-DU'FhW]}FjSbdE*1 !aGk%.Seq A!,D@pH,ȤrhOq,kjI(kqE!` g;y&ؓ<'jB!c}CB".mG'vD 01/" !(1   oBº nBA!,Et@pH,͉4G#5c(hYٺF0x0h8M@q|v0oN rZ5-4yM V3TQSV/ jb$'P'Zy BA!,D@p8$d lIp2-1#,FKC{,$l\48Drt~yr|alq5ln{iV0(1  t !#aDŮA!,U, ʻ`(&!,Dd@pH,$ti0@,%q!:h!b!z[ey(Bsׁs.{{X>5B".yI(1! p [tEjG]tA!,E@pH,ȤRX"kDC"-Ѱw-;q2j.J'fv.'h[xE0 Y,T- uM%-,$ T10v* )2&BOQ~ ZkK$.#OZ\,bXIgTe/'0',[]SC@ !,Dy@pH,H. Fbƅ4LEʺjucnʇv> ~v|-nqry5B%.kHX(1  rjrrwA! ,Ep@pHdHh6\hAa4NP x{?C)\g[jyaizhBhK. DêuvNq~Jj@gf,S LobesS'`@҂cf,N&ܛ-fda>o4I4è; :,,+)hH ~1q011w)!TJF ABɌ!,ݭWW:C֬@lbv71-hg9pȷwM&R&``k tX Z:"^8`v 3Dŀ`4$:4kFԸH=N5p0 uQ> >kBT*rUUh!v8 ܯNKNeYݩd)@C`FEQ"_@Tf2 I L%Hd@Q5vPHl+qxMPQ"!Ŭ~ @JЂMBІ:f+~AQmFTdE 3QV!B K% ɒ Jԥ´eiW8b/!b0X2D$`TcG @<צLnI C^= *9AWdrw]3bPTG0o5. u9(c +N\k-YM)Kcϙԋ(|M %5HlZO6k>6YlWLӸ&xc^Q;JE 4Pf# ݝ Rnrb˃ބd@2_[f <nհum ܊(V zw^65z szu`^sh@׹σsX Mu%gQ])h̺-3ʦ? QW:PoxTK'{y_pOەH6]b>'w띛A!F,\@pH,H`l:Ш4ZTvr `L.4Z\𺍉|N|/ zz|~Dqt^C,5B#B55,J s s-rs' BC::5:Hq$r&"s)r$1 ,-,%.#*LjɝC ` !ͮ" s2xa$eBĵxА}s8k$ Ա N rZp %;>طv P~+Y`ә̩4$y}HG,iiJdQ-3iѰ,) ^iAi댤`naw2kN8u3Ɓ B.@@KlZUSzz6Ł})ЙMTҞ9Ky7Vńn Fٖ|q箢Wt[V8q(i]eʹ4ͽP^| EIH@S)84]Q`LpdQ, Ё1\Ha'"F5BHNr0eRH)Gx$u]R%\`əwIf!kvѦnsyw&q=#hjhh=dEF*餏Vj饘R馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv+k覫+k,l' 7G,Wlgw ,$l(,0,4l8<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.^*D $?nNn'iwN@ Lypz)Nl!F ,\@pH,Ȥril:ШtJZXhax`-znqi|wzI|Vt|dB N 1 j-k M,ECBCBF &0j) E)666)C;#Bѷ6M)$+(15"4Х`@ȍ+w9#r x$ d|x1$ 1x@BrR ~&8&^Q !k@6Xm?ی9Hv(:!Yd5lUH-jj0ؤ$"&:I0Р+B%鴶:mX-EtĻX~=;h*V uqȑ%%bA< ;H)&@<T$\A~D%!Vl "6ذvPHz3᠁ z8z4dn,֌ArZts"@W~ ,!ZIR  0h/cyUΊt{+0B({BpРT8)$``U;YGd#pN;T.%k%*oF_dS]R\{x*Dw?XWL`rvbf0~o%cPzߌ 8pM7ljUx+6zu ĵ6/ߊ :k 1Ї6J(34`m9Tm`j dR$HL%@3}b p oHgcI1hE #@c䑀IȑLdMF9dS8X^e\ne`Cn`W@='F5(&X%1,3z aO#LOBVS L"F}l-ug3BKg`"'PǗhRףRA!,&n`(,ȤrTK#i6?#x%)=*hF2 jn:oqkt1wCeh{\`Fx"OZ TsLDA!,6O@pR `plNP.,iZ P.W۪X(7< $a~xzA!,>P:ql:M!`b!U.h@l a `qHc$HHucak.q[xpH%}H(K["&*DUL MM%${c(M- uũA!,Nh@ärl ӨX295]pւ#rwkEv.ݢ `HW- gt$-!%+nhEGEGA!,VZ`(,ȤrY2 $\C4@F 4%Yav[m|X{W`{%BM`{krFDA!,^,F08RS !,fY@p(Ȥ208(OjJ wX c⤴4LPQ5@rd:ɫWQF\N{rGhcA!,nq`(,Ȥr- Y?isH$"+s9(:\XէV Yikr3-%!M[-^D$a aA! ,v@ j4Zrl.  XUzV k|]dIjipռIV\#(+x*.,a}#&X'*F UCac\X%!| `2-xJ-!Iq-tx Lg)B$ `xkx ٪VիA!,j(ȤrD.Sh:7B e`ruԊ P€ 'NYc(fU^$.Z1\ME$PRluqF yA! ,@pH,ȤritD0FzdV,x*al\+h Ȃؘ,\cK BB z_IaYF$ VX^DHeT`(TF1 !(1$'wJi%'h"SfLdݨ`A!,@@@8,ȣrl:/TL<SM6_MTyU&NPvr*'&~(+} w#^JD}prtvnU`b(eM B/SUWW|JA!,K`H,BX)8eq0Z"H%v -+i5Y_fe[ DA!,@pH,ȤrY$ (H%t>kD-JD&NP+RigD j'Z.1u}C% D0 0-lvo&T)0 .| !cUD/Jv ǰCA!,{@p8$ȤrxVEDNP.DQ+Hh0j`M.&(&os5biFo-jl%_`Wleq B0 4#wLN!B`y A!,W@`1`l:F r-Xc3E]cjܜ *г~g{y zA!6,/@pH,Ȥrl:ШtJZجvzxL.z{NUd$TFb{  ,xX"131pK/T F"`*.B(&/   .V0 4B2 sO) b3./ 5E%1+U֫|o |+8AlC $" ':lCEL@BGB, Y: 0jaZo.h@4uf4r!FԘCUت-@Z9Ɉ RdD+Kg#NS`J%\7v @'D^pKUÇCF*-w7$s<|nI> n,0b( QJIaXɧ )@!J?-Rnh(=M(й/0!anbec4 7]$mÀ{8y ܘwtms^07l>KR6x׮;8Co{ڳ _0o7G#0P?ͽA!,z@p1,Ȥrl:I T%fFv`i6 8)شh{,rLs!%#4 (.w# 1dxB(pd0 Q3.0c~" mC])\RGEGF  A!,&@pH,@r!i" Qұ9 XG43>+hr\wL"^f)F Y$ Q0 qxHn 4GQ(BQ~{Q}CQ eoC" U`}C`.jIIWxF Y h JOFXA!,6e@@@HHcrYi|dZ**K,d#i%a`cM+-('\ XYpLOQxLIx  dPFA!,>I8{% MŀPk2!,Fi@pH,H,y$5 Tc)'dCN\'(+wew"1w*brct)w05',Hw^  TA!,Nk`1 ŤRT:0 Ki4Z:.)r{  7ߖ!€C(&F0aOg^_vSWMG  A! ,V@p!rl:X<52R{&(q.;&(+F~C$t w*.,}E0j~H0 YHmH[kEkl  QA!,^@pH,ȤrHP%2a u9k=m8AI&,T€*bp\> -oc{P(U3x})CcI ]uF0 5P1_j !yc-KUa 1Z#eL#Deg$Q04Rw_[(úbhH"C%'EC  rA!,nc@`1 ŤҠl:L$aP=ϧ9Jx5@J8H WVTtdfhH`Y[ ^yCSVqGJ  pSCA! ,v@0 (Ȥrl: Iv6c#'aT=߰i4n.ZS)T|rE (&c^}v +qC% bJB(y{E$ B* "Txv{/Y B#$ȐbFM Q NBA! ,@p(ţrl:€0N*ybEVdy$ezD*OD }/ !B!rkJB 1j$jM|G+O "'_mO}$b .O BWSPXTMI  CRA!,{@pH,d#Q"cЦF-i}5 a ʄ5d,im{*.#]N1p`bS+B0g^QB3[N.rX$ i%~X%E  S{A!,  h0,P(=F'c>]wBH4@Ɉn  S TkHnEU$F#YQ'"i&/_ŽHɬUgO  ԱA!,z@` Ȥr9, 1XihFؤGPUr=CK~+-Rj 4h"N('wUG%xRD"1xFY[  BFK  h~A!,~@pH,$q2(Fy4T5Zd K5 Ts8kj8AT 50Y 5CVY\^']T{z_C0dp2cp_~hxd31F|  iA!,IHC&G7CpR!,o@0 Ȥ9HP B0tl2ܤFb=Ml R#xj"Z| `Ve(de%-Tt/|E\  \\BA!,@pH,Ȥrl:Шt: XvzxL.\+v}ExM~y"'4W$  !,.Æ"'{#l/ ԤR !,I8ͻ`(@hlp,tmx|pH,Ȥrl:ШtJZجvzxL.zn`N邼^!,Ijd7&dL! ,&L pXdl;ȸY<= l1[gyV߱fIԯ/ '8l|n@|!,6`@@@H,Ǥrl('3r i˙Op8/'ƧabED2c Ci[ |ER!dIWw~A!,Fg`(Ȥr$%'1@3|Nuܚ Ufݾf=nhzt WeiW~y%1uL!O j'nGEWnA!,Nk@`(ȤrT a" 'cHG5XC:TCqn٧nprsB-,fw"!lg[])"'h$ -JaGA!,V`(,ȣrl2!ҩ`b 2iAeP^8 YDVz:ui3m|~zk~nMlyN{"!i"1YL\|i.bX{x/ !ɛA!,f,a5D{X !,n.@@`Qj+r, AIZCvzxL./n2!,vd@pH,dѳR"'( %Xkpi|X6㠰@5G*zxuwyqI2.moHa'dHZ- FJWCA!,~,a5D{X !,o@pH,ȤrItp0(H x F'D4_0$nb?VfFSZB#CtNw !1C^'~A!,,a5E{X ! ,p@pH,ȤXj0NrITqmGU67NI9Omm$ FIdEONT'x}BZ# ]x / '-/ 'S} BA!,@pH,Ȥr)xbb&'OYY؏eAUҊ@&s6]Vp(+". f_ sjfT#&%zu$ZCg" V hBA!,Id7&dL!,_@pH,$ā(S,6`4>ȉ}N:h iKI?=K-vJ*1(-s 'zzTJ CA!,m@pH,$ā(S,IJ\F4Z(%#E ʣSy_?P~J$-N$K-YzF-*1.,fH'C uvI A!,t@` Ȥl'52N`4A UMZ,)/al̕v''dGFr.qLn$-j t ec}O[B%14K*.HaD$mnd nA!,*XWcl"k8.kpH,yH_l( !,`@p(Ȥr 8I|BHkzD62NEh٤.|]1p%"GKfB0oT* XEzQ`qKL vvqA!,Id7&dE!,@pp2Ĥr)96)tiNNJIs DSADZ"&!TUHfLOOQ$|KB%RNPU VJw+B/m{S!lQ1qR_sHbeIM ИA!,7@0 $rRTG'u%vBAӕRƢ}Lx! ,^@pH,ȤXb@P惁.U-F5`=Ͷ[VƘkly#{EpD$jDq{A!,&@pH,Ȥr@BL:6.`TH6AuFqp#Z6:NlSn  zLa*1{st3.WqUW a$CW)BqnTrL ØͼA!,7Ii&d`F!,>,8Qc6 kNȀxBpH,G@gi !,F]@0 Ȥr$q8%4Z0)34 WԨ\M&"Cubϗ{wrWY|i)yN4"&GE LA!,M`@pH Sl:Oͱ جv `ez0|庳,x۽c2Z D\gO E A!,]n@p qI܀K8=M `$Xj'ր0]caq(' 'dX !WhjCyP(q[e L A!,e[@Ȥr$L.jDN(XeEW(X,NcH츚]~~"!-ee  }A!,mg@BHȤr8|Bi4ƨyxπA`ip8`b_T!V-GJ-N 'pK Fg A! ,u`H$rl*!`p8az8 Ȃ:G\'ƨYq:h%RN/aC1vo#_`b 1~/-~rD$ C$ (-qM0 5C%uy}_- p_'q$ ' FA! ,%@H1l:Ѓ8)qZ!apЈka&6.hH Q5a5D#PD0 /yM'sL-0  N-P-,OqO5 M S ~DbS2gprIl- bL'UfI\ '‡ JM A!,@pH,Ȥr9 9t" ,C$iF ܸX #H#5[9H B"1bkZB0 0 {I-" 1y^JozS$aH,rtnp%!Hcs%nI  A!,e@@@H ȤrT$8ЈbD-(Ǖϧ]A}xSB$eL!,V Y.,TeN~fL Ff GA!,mP(Ȥr$H+4j&'*F(YFM{,FCi_d,0d".hyX1[ +FyRTyFd E dA!,o@p Ȥ1tJTgqi`(hpaJZAeEYֺOOwa^O Q 3.,LNP$ ' )j !#w}~D |V~ A!,tE@,Ȥr0L ұi Pc<\vֺ6ZP Cn*H" D0}tHGis*J J$'I VK'su A!,I1`h ]iA!,W@p ȤY-(SqUhhpZ,4Xx]jq5Z4/ & nf uJxyOrA!,g@p Ȥr-(3N@i48-sր|-m{ϧ +JZ2.#LN I B0 wD-BiqOwA! ,E $Crl.[ NYB'4*6iF'N:M0A$I snoK"1mJ pr*wD D* QIz]o0.UIjl-^Z h/ o3.K2+N ̓ԵA! ,.pH,Ȥrl:ШtJZجvz@L.zn1|N~ r|z-v "!#/B(., B# *-,"5$ )q 0 b3#,ȥ/ 2-#0`#,D(+H$rτ#J l!>ȱGgHIJcع;ɲK>ڸm|IM2yğPZ ѣERFӧ54z4իJ+C~{G,T/dXB}x( 25V*^\D #1!1Sd2E*14a10&#BBC XDI$E6IT@!;"q}Tnɓ(S)D% q TvÆP' @lpWi^dT*(BZ2N늬ZAdZ TʝK.9J"eH5 @8 ,0z*B?! B Hʉ@4UlEBfK㿖1ɍ5]JwVA􂰰EHl@ޱDēE")\@Jp6 @%6tFyprfa/|'ӗxZ} ˄V) p_}%reD+a{1bA pyˁEXY([+1&ȸTVI9 1 ( `ը@0GK]~{]h4 -|y'@ $02oے mY)餔ʁe}EG,N|Eh) yJy6WWWi !ZD: h$˂g4 !`aF+mLfIp&!`ˤ0 o!>xa&~Dil(xsd HG\ ZQ"0@M7 u$@Je .t* F7ȡ'C0֒,  q"p&7݄}CZ6TY1O%L@+C!M+"J E@K$L):z#LA!B($ IxKaxD¦آ(/*@ bzuǩ:JPBgGp N B-\S`|d" e:W\-6axH@pmڣ`ECrGpD .YzbТ,@M#dsC \d : XWH0MJ\+Duִ}45sI{e-|VjMp58%8Kι˂Rx-@5L@#B 5 LE:`w P HkJbU$`}0M4C8 5*)pwp @G!@8 ~v >S9HAYLTg  ̓*B;,(0 nW<1O7:.`ÀkZ%$g :=NOH[-O U+o,5qb"Xw䃅á9t6"A1?  ,CE p2~x :`*Ãk)wcfp`/ <λf0gL<ǨdgbE8-qzMM-HSdY%[1B QHɧġXm1:9\6ZC#lX AcGe+QGNr3t =Ca2sk(;>|vay$Cp\VY֤@eX]zxϰp!4|",h3/$x PǏ@]B 1'rg\wCOR;> (& EoΛTxgKgC90Ĩ,s<]o&\.l}x~WB:0_v,6^@_o`gh2Ox` 7Ы{揞·LjDJX #T1p n& P ,XpqpVpjHz|trJh2} Yɭzf-+e }F p&\OЋ萣<)B& kbHo4qD"9Fаg/HFqTKr@n 6J;@$=ɬNtXS &o&j檲FK lxYkб೩4r`lDUضQۦe,eAn±JS`8gZ]ENE ;5e$ Tm MвڬIuӛf ~a lnL 3jkXĽm0`U%bܶP{ 7Z"堁hX!`Jx֘i gȷ"F7%ּ ĕ|db0@1K;rHkrYWGf6LY^y!}tx Nj}BxQ| u\W/5 Xpe(BlD ɕv۰$\rqpIdUx '01 .a f`LDG#Q,0b#0LF5kƻz0Raܺ,\7g,CrЕ sޖ-iRSYb}YRI PnIFnA1,] 3(f@jg\3T34 G^%J}M6xl`qQm84 ^eYkr) FL  8]wպ`ȹ]O $y\Zbv@aUCWfV`͋oIs{ iVm%,)=M% Se];v}]ۺ: @T&!# rvْc@/ 0ؕԝD=}hʝ u*r|I\ȆNQG%V]38wBPQpiE7F*`LP*u@7t[f ]e%mF  FUdGo/HNV\pޜ@ SF #zAYd|I*G$Hе[$ϱGPR!gI94oIǷWΠ)0PJ\^K\>Y d\[ IIӛl~h0n({|5|afǜϪL)|8vy/eKdG^L mؤI~eZ2W()a;iTiMN,Ts{d kċɰ+Q 5+2bu$D\3|APKPS }0'L&uS\R13uv8걠|' )35@cU AT \miBC@Sg,UZV1VȰV5g>Ҟ  ൅^uPM,5Rd,C}t6hCR"9=VͪΏ{9>Ďloƽ3;/b$m_+%\FAn+~*? ;CPr^ ׫W,7pp(iV(4%NPՕqG>2*k`>px)OP$S,6JO*Dbl rIp4=qH&Ɏ"$gZUPY1WU\m^܀ha0J#ZV!,cjɄU\SNPG jLHI)gr©Y kTh1s5 %9'Ԕ 0)]Ո  Z6gMpZ9֍; B7Aq0zQ; 1?'ѣrJ]r(seS \y% k[n_E\qb \7י@'Dts' TҼ'kpp#p~ F 4-&ؒc('8$"DR4ΰ;E$XERbnSLp ;j#> L &cB6# ǵBbD}^e>1Q8,5ޒD5+S+" 9PXfܸcAsH7/)H{a₆%ЪM3ʆѾ\ET u)u,evEtVibKW0!5iGTZ:5j@Pzeƒ`%OPPh`.Q[bt <X6'դG8)ٲa`rN)m#R NJl(`a>ems{ֺhs; 5å7h ;>B; B[H -m +󤜀l-VI'd҂Nr9s,He49H q EQYtJ=#^@)"d%^ppPѲ.:v,&%p'&;LwШ hHKfhd_ IDGD `VPdl;(r=!p@Y Y"E;&AE5g52\&%HZatRVuJ0W'%ut+ȁ&vOلNt(eJj!{$d#"T+TйqT++OT0":a"=ܖ-~;xe @GE~e\nu0->6v sK`G)8@~Mii8bMe[E ^Z@ p^dۙXXp3Y\<Ղx+ VA0-  a 0NY.05#W;3xo&F_) ےl&X|Rh;N/%Qbh\25Җ6 )ֶ $I@\gPV]zʹrQi^l ؉S8U`cVBZԝv 1=sS}wEz%mHPETz%T}+-RNH/S]pTPD:ܪ~Q_9C=҃9#בZNRƎk7ՏD{@#2(|r`&ҙca:=Nl-]!`ue+>NY~@n VPC\ ͠TI2i[33c_f24Ƭb1\ Xxo+ ~mH"XD|7ͳQ-`UP't#4+N9/!s*J\lZ֦?$5e $i8%~h儕>aO&קiXzRݽߙ=0iuIزl PP@n _ߥ`Q({.2f&:zTM4>I<ɻb;\oE ĈPoE޽LWqR!XdhAg{|﬊jŒbDz#[҆*8ŸhG- "+Z߾@`M@N0| bg@[ "Cwp-*)p " \4O@ 0 n ./YP($p_7$ t}&dT o, Q@ /@Р0tNB"Q@p. ʅ VO,NBGrC }j$&6,mfh ° jX`Kj<GΈZB .(N%fQ/j S$$জJ$*m6bCEI&Of%t 6<`'i>g9Si:`9L;CS ;&o=i7TcAaSCG@>bMP1bZa26f?QpVg ,cv XTKR/#is5>KLg\."'A(:aZ$d mLX b.A©fU.m$Wk$b!:.q8p@}v.(ף,WMZ*LGÎcBUҤmc`M.ɀs@ioAV.S@\NE !'o%rv-^t2'1D874\-tT@DXEb uV >wdx1-5oM{H:'vmp,2\VCiQu7DR*hEΐ6@k* bQ"P!&`QQLi—L%d0X5tw`b.Tiw7eKVsimG4oA-2VbNÅj0Ƹ0oQ  ;83JyCCs +zOy$y ,9CF ִ$ϪHW \A~T23:r Ř!dzƇ ^4f|Lv(۲C^b^mZdq.t  uBJnD3! si(L BF9Ŋ!2NՐdC3aA C?pBb9ymzLMbC !nM=;M7``֠|&_;ŏg!M-` &mC y6x ^<}"!}4g\eXDHlU`BXj^&Ao%g_- X0,D_݆;ݨ'h_^ZUT[ y Aa1h0c`~ZUC@'g(# 4ph(աh)i.܂O$HP1ptE <0 4(UVMPPK"P 2 >*k J"_|P@4m8-*n gV2Hz;B+{7Il' 7|tG,ṼgwqK$Ko*%248<@-DmH'L7PG-TWmXg\w`-dmhlp-tmx|߀.n'7G.Wngw砇.褗n騧ꬷ.n/o'7G/Wogw/o觯/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` cN&2gL#04I n:r?x#m0G;"| ?L$HTTdFZ2A%/S` %!F7,+ @pH,Ȥrl:ШtJZجvzxL.znpmN~uqLKK nvL/L$tCB !#, ZӢ(- +#( ., *[*10B/ !"FH4H ՛Hq5ָPP`0b@R={ s E 04%:4fo~ 9J*ŋFZP`Β%`@ճO9n xmqC (N͂/5|8"">`) *Z.ujke*"xMBg PRmJ׫dj4PXͻ :ONȓͼڷ[ hسkνW ӫ_ϾBgD޽0+'߁G|ߜ7aPi(B(!8& d^ Xh-~'ȣ}'P3sB 0x#M'd_ ƀSV)X~]SC%d5:9"M0 "$`@8@1z $>*8+8 pBN k~xPMƞl2)A4^Ґvm dpeڋ/aR*A)+ox g%_6&}.ljf\`"k @u޵r4לes:y@򑐈LB F:򑐌$!F ,A=0@0!Ȥrl:ШtJZجvzXOQ$1쫁AM|~qXxB$i'("Z  ',-,)BpZ 'D#E(&G3-,wFHуW$ 0hZe#B Gg3.^) D9Tpp2AE(Z61`I,<̢M @2H# l\ ꄛQjFEtiӧD @իXju)`ÊKٳh ۷fa ݸkA.6 7S.Fx@ VWd@r؇.`l5xͶP40.>Qgsb@`|D"A& FaΠ ]4hpK]55%/`@ˈQ&rp?N^]"B B.eWfOWAm- h~Ac d @ )рA'@̿!L]JJĀEP">^A8m,hu3OFsS^I4 3wc0$"U *toaAVC#͋]/|К @mIa)J+r! Q@B/H0 .pB\l$V%z@! s$$`jj)쇃vL:4A!(VC= A s }bh3Ď#x%`/%(R."@c[ JR£KuFBx 7Fv&a 6HT^¨9l|rvG '~ZSfO@ DN Ph,q9%5n.bw1 #ÔB&^5t q2}MA}!$Od`A`W+Z#oW^$$ 69=#ZKV4]bY(CzAS|1LtZ&*A 1TXrU$3BppZB7oYm]n1qZ:n |-]EA =JѨ㉩-C=q.'Z@vpQ^)h'Fm- 춀 -Ȭǖџ\.f5ErSl&J?_'Q`x-$~z;6Њƴtqu<+zCa'Uf+;0$ EQ( C@  0, +N/ AUh& m"B,L/ 0M"NA_B(A- 0(Tr#$Hd2K@ANfyBʘd{[ʆ  & 鑴Q&= C"F$nBX 8/i\Lڕ@E() &ިBǰ_nj4| +aE[p`J, F@wȬ <Yb^Mqѱ٠,h*q4GTm`)Ԭ=ܨQ h0:1)/vb);fK 2aӖ  8@ja0[9<` W!@/c DXC&7L>i|xĜFI梩̻H0V5!j0 CJZR@eBk>d!qe2fP_^G8?+5wY`xc*yv0 k<[ 5XWJLٔNi2R9TYfZ\ٕ%Ib9dY 4fjlٖ AI#q L e  U-_94T35]quN@ٰ 9ڠTF `lP(/6a"1!6ך:X7iIXCH2i/0 I89 (@3`4R[g2~9 R)}0SeytXr6I`'CN#J*js *@x0B!U>^.~('09 knD 3'S HR%6l&WZAXaBԂ :(X0!㒤}@lp0}/Spgzᩨ7/6 0@@q`;R'3)Ǫ =izRn6rJFDz/ͩ+! ;8E*bx4h-34n+fU 1@R(p A Zc*EbCz:'{@ 0 F-@F rv@eZ4Q>␮'J:dHIԀ{F wGC $`Zfu"oI 1K1+v¦. I",ԉ iP1/q-3VjLs @Qr5.UI-QQ%p*hΆGs q { V2Ǥ{覉4{ IG! >Movd1+ ϷTp8ǂ~!prT2nՐ0=(M7o2,X#û*+q}s[YI"# u=|ںɠ-pKΥ0FeRt,xBSB@ BܫVzz9g ɳ&3RKQ$֗@aUEo1mj>m\P'- ''l'c:M- 6 B 4pܜysѸ_%ILrq35` h ٍ ,IZwS 9>*Ѣ 2%W #,p};SRӨ;6I )7Ul+Q /x&߉V; g’E0j; pw L$Bcc sOMy 3mѢN-`܍ L*u ]>H挗T%Z1*4B.Dt;ET?xf nn6 I @?s۲`Z̎a-z_GmxY rэ{ tx= [7NraՇ$Xցɼ:h1W_F:XBf%V`r9 vxIc>cW<(T0jG joUc+yp );Qc=o R𓏽S 2ɟ c-ME*W|e& <ūƕX~U yI`_?_Əh{Wα&Ya4``П_ar } 6B7a$+F %y5c:`@TIt>iqYzK0>iq(H[׋, F!#`p``%;J>V<J>LUnxnpde;!T>2.LCVd Hpnn%,"> H"J0W-dfgk 7>LMȲ׏7!ae1)/C4MlHΏ7Sc"xP5#1(~Q"C iPx0AF !R䆲ub 3Y>Fbqɋ H:P7$ʏ*8p5tMPzxa5kLp"/$x%|5o h bԷ`AquI*Z%[-Am`*V v֊%\Ι P@$%̊X \II6Nny Ҿܰ8Vd)! (~B@C#`ٳ'N Z[@`m(ƛoL,0 @! ) t=iR2Rǐ9@#> nAJ,!aAaZHkYK0ר*lP8b&0fIdaOJK\3ؼ9?A29 +@@Xܛ ¡70K %vDL (\ݐsÒ4+a8@N 1bј,gL#׺7B sa$F5 c?dq@#;.t#!IIN%1IMn'AJQ4)QJUt+aKYΒ-qK]/La41Le.t3MiNմ5Mmn7Nq49љNut;OyΓ=O}?P5AP. uC!QNE1QnGAR%5IQR-uKaSΔ5MqS=OTE5QT.MuSUNUUUn]WVe5YњVmu[WΕu]W}_X5aX.uc!YNe1YngAZю5iQZծuka[Ζmq[o\5q\.us]Nյu?nw^񎗼5yћ^=KR#Η}_*`6`!X`/ v0y!O l8pa%pb-va^x1qc X=-E6IdHv,/,򕱜e\-enlf5HbA 0ԯuapYz1h;+zֳ|hETn!+ ɒ>ӝtOԥ6QjUխvakYc8!F6,70g@ph+ rl:ŀ`J"ɵvఴ%ngxK[zONzV}h~wexZjsi$V$DNC}$$TK B {c$ N,KԻBBL֭#Vi Z}080Bne=SJ|`!$P|0nY#&XȠADhD^&`xJ?>d"|6ӟs^rO,h2$zL" %CڰA ,V, 7gJ mʋ'PP䒊-*)@ʼn*ZaT[<+OV [RՈ22>(։EH^ ^- Y+A׋t*^-sCDD|e8,p0/ 9g_NܕF%4l8ۇd5cؚ3VnԦ["F!|1!5Dry qɔL v؄!_  7'D4A'xF 1Uj{ @i`L"T"YU #fdiIU|,@ZW 1`@Ya ěQ"H#`@&$Nf✑^iH%:Zf T=SpЀc6 f~Yx]0BDjJZoM0X]pRS,NU2F0A0|  @ uz6xUpKەJ%Ƃ(6ia~0MlF| W N!\{2 eFKψİOLY\j*;@VL{/5B@FW5^nd&rWT C\gzQ.;Z C31"p H zu|8;fԽS /iO'ARacx2ĝuhaJqv~0tFL-T1cSx@2Sa`U鎯ff]% 0:O:Flb1]/|=נtKٲ2} q*s@7(q2mU;I\=@>{5oh vkEQL#V"5ad:k@I m#Hf0(%bIX>~o0*zj%i2T*3I53Y7q "K J`6Qxq2FR1oC1P4lcceDs¶*{uZBRǐAAm%0'Q҂B*ѲJC/) @n%S Bxhe))!bL2f:Ќ4IjZ̦6nz 8IrSp-aJ1)92;b tj1@*hG&]cp4פ(Bl:B\m@B@oLJAIܽ _t!pFq᧒Fd)p!'!LL, C`jCw*3q=@`r4_H sf)BTɉc|QmY.dQmbquV )|X=]?d/6[C [s+5݋n rgAxlF1 9g4p9[PVf`mhMul[g|H܊Ա+C F ~qŠ-XB[EO6I r[((p80Ms Yzy@ۢC0BB/D 73|wJ Req5`"OKdP%FP ĂO_,xgG'<؃>@B8DXFxHJL؄NPtg&oRJ6O(PK|Q[pV<CZ )xkJUY¤q|X`P3@Q 'U U AjP\ $ ( w"RDhJFk @G cuGRSTP0TT;.*a'p' Pׂ&u0,aheCa8 W5`7mr$hv`981F-wqCtn)1b14`|Q gbj3R8 7F0Aŋ #X0U\[%IE&|^w=Q8DȆ*.B-Uf 0tV\y PͣT-i XPE |7j!110=pQ~Dz&h/ ]y^ m3\86bXavsxa:PyT7!'D&ب.ܸrD*┵[ @@=a Y;wSn$ЖF1QAI {FƑ i0e!G)*86{@c7Q+ėbpP~ڲ$_es0'$,%0%@AP7q Ǟ(&*Xɍ(sdf➜ELq- \C09Yf&mX-e@ ӘLB-. 1nA#r n[D1B8-A8;IE7}oi0z*yXI6P#14Qk34#ƷtKPm~? 7Ph($LCppb#2qFY@{V af/cf$# Q50+:Atp1oPyu`aw<:r[-uSQPh⨣w(t>S"8-:b,7Iiy `{f3AJ4p7&|FBJB@_8;çPЫhE1V2E0(_ 74ᦥYaAx+c QZ E!EopRGFFVEi%\S!~r K3XhۦpHA$F&J8H$6KpxTRȋsL/Y_J0PБecHUiO`W;t[v{xz|۷~;˃(h^e OmnOeJq0m8lHKkعr˅KL78r\q~ p5K,F#CкKô*."p h :AQ@2-BFJ` T/AEPi%3W)Ug!/V4pTR"81v{cWx)rnJj{z31qsWĸ"c΃IH#F}VuQ'W(zA\mZ,eggZB'2P'147g* ᙕ2Fq^^Vt*g.5#g`f7]/v$)J* 2HBaxsĶj5i6}vZ~*[w0z`u`4@ + $#"/P:nF0AtoZcqb )Im=͕ hqfm5? 6j U@{i̤^/ohF̾p:}V`.4aqW VBPi* :wgئ40ʦX @1qP90ʐTfQURnuy|*WΝQS0Ŧw@"u ,K6mBEAum)B&KVpo\֍"$Y|!}, ٳ vzA5"\)Kwl!9el-<K>ABA 6 qyOJ50𕨽ua9JڵyV:X1Sc&!)J—޶GJr}gAw \p1' ##i^-(TM5`V*;E~aL&1JREce=e>B"N xc~$K:B{s('ܸ/.Ll!k͵kM냖kKW{6Kޢ ͹VbII>d^f~hjlnprN{`.¹:NnK^?vNxP|3TdnA@4NdšH s^ t6{@pIpe@N4n@GPfYCq,( 1;4}C|R=ݾD@)̸Ch> RDȨ Du*MTb0I9T[E vh& P~nmYa100ywq(P/+$9\aُ +#ز' AtB|#(kA0A*~aZ:-``,r!aNq$P&ٱ ! @ /@ @i_}lB0#Ylt, ,HI h^ 9Zi);"aS0!e崈3rPB0fp.Qh7R_ h"NG'%X#b&&ƘM E~^O e3$׎&i]:4_Sd00a+Њ@ܟs`Wա`v".]7@e I@S Y]8-Eh#P$FD;0q=#N=YSP /W0A>%3љ|n RϋpߢC x ^ظ0ɉ2ᦟ@E@[`_3[PJ4DZD4߂DVśsc_'ry[ʅr{7|y٩!+\ql/Z>ʶ8ѩk xzyn˃ǤJTT1+Cw{w>x?ei<,;u3ڹ02ƛh2[)V@`g!=v&lmMe0tj Az1@qiAB.3|>NTYD6ET ,d Gn\vHi~3 $6ڎa9.D.|Z0 m|y<2ؘc ?ؘck`vO 6{;Bѫ A(c9&~kk]AP<~cG9^qO]! T {=zğS\4< \$JIP=Htݤ]8O3俴Nd2.OA!F7,VpH,Ȥrl:ШtZت0" duJ.)8|Nw^lt{N_vhW X{PW/X{/14V FW$z',V"^U" !# (.#W(>4hſ 3Q†a0Xłli씬3+/z!!rZV"Аa܅VfPGxDR= 8#`" TFH ŊkȊ\*TPBb56\?Lt,+Håy83X16hjYqL{J}DS^&tk+Hۑ^7aYNI#*HS{,ËAvӫ_O޻"yOϿ|hqЂ 6F(hQ{^(vp!((:igb0"չA ` 8 168#X c&u`  H*gc `&q$@!m@-`栜 8`" gHA6̡u,!HD HLb&:G|&RX@'Z`DHF ~hp<:3la5;1)Ƞ m?D!HB2LA!!IJZb!F,lR@pH,Ȥrl:ШZXEzة8)(h+XyL~c`f`H MY İɶͨӱ|bW$X^ ''':`` oĕ[Pɕ 0DhƝ({+,Dhr0@l` ͛WZZDb.P2ų\Llt fjAER?*ͯXC 'X-{6FGX0Adܠ+(aob J2> tq**ya 48shѤC:4 )DZ - HP cyNU 380io5w-O,-k\Ђ T1PLftJ~`a('A:6IH( d F1#'IIUd)Jzۀ : Rr) )WV򕰌,gIZ̥.w^ 0Ib !F,&l@pH,I!qlШtJZЀ`zwL.wznθ|NM-p xKt{S}\FD0Er" 'Ix  "٣ !  /C" 4 #N%!1! 'ؑV "Lx !v دql!F z`xQi&)PDrA!'0jB?$I' 04rC# \.!KmpQ `-W2~ ?*k Ix`"I A ^ׯ`i8Wp4NV^֭㈜&f=! k*9PdR P894 \)J]dy`C5p!#S\ Wa2d85$ew["a |B` $ЃՇAI\B'(iہ \`xP p̡av͇dQ "IRMT0H%S x lbT qHWQIY} 4yM6m‰ ~OrN$O"S#B<‡bIu 1 \A]ѧ&Y),X6!_`K(@EC k<ن]x4A ͥVrB @ΰŒSK ; ZʟhƑ ,lB @HpPm(Ƣgg-ԘRK,DK uLp@</%RqW\8wfL!F6,l@pH,)6l:ɨtJZр`zwL.zmڵ|N~ 8xl|W[ OT\Bb·E%',KCh -!.x%ާ -D2-[2.*1!lз@Ć1hd 0 !FLl ^Ҽ!3\(2 H B`p0B  ޑðH&R jʄVP@(I-ldrh vʼn !4NOPN` V̭{ÉuNL\`*IO݌ԂFaK'I$@ A $G|9DĠ&l#E }p:6R#9ZhĺPKbjBZT9h !C;=Í(%~6xXDǙ=|#1"عw?}$!8x7A !L Q!AC@ "Gq+jЁ h$'p$=Wa7NasF!6[GpL)E; %Ā2`O@e6Kbvj@%0@ p^~ ^Fe\Of~5`5 B:N sb9 =x@i$t~0 *I323 9& 0`lj,@;Fb¶Vp(upX:vߤs.E\J\0l8GkoвaI )%*(pC,El&rSh˅0Hɩl |2)i> t!F,V#pH,Ȥrl:ШtJZجvzX0.yn|N~ Lt~|~Z^ ¬ ̝ѱƦT- ߬08@襲ÇJAD XTXď C:Հ?~1PJRdɳ'62L9`&d\`C*J>j:UW.?U j|刕۷px6Ub W=L0® Ue@˘3/A vc) 8NͨSkK#U&Ȗoݠn`#şpЎʂK.[  pB]xMS_>b p Ojjwj4L͗* 8L@ V(3slRLt(b#@u6,0(4h8n2Hg*$IiӺ$'^hZ+/>{`F?Txs/O" k/o HL:'H Z̠7z GH(L W0 gH8̡w@ H"HL&:PH*ZX̢.z` H2hL6pH:x̣> IBL"F:򑐌$'IJZ̤&7Nz (GIRL*WV򕰌,gIZ̥.w^ 0IbL2f:Ќ4IjZ̦6nz 6w$Ά^9qN\=*NwSg=|#6HA ӟx@0` -ԝ 8$QTDQ"H=IA; klJ[iv *2PќH)~zGtMC%.Q^CMu*K/jJuTUԪn#*W*e<*ZQp\J׺xͫ^ !2, ڋ޹!F:,-9@pH,Ȥrl:ШtJZجvzxL.uzn|N~fg|L{KnJmH^DE: JIyõBB#YkQ" GqƮ0 䛥-$plIfkň \..Z]x ͚@em*Ȇ$, p$aSv!1j5's+P݇ Z5M p;'x"wZq-.5B 8B!20 D{hnRPLQ.7 Z)AEZt` vҨ&5~A PT^gTX `Z8Y!+D!@}!(L7LD~!7C]|1_)uUJ]g2^&Rpsy CEeF9{Lgx} 0 `@08]>`UAFB֡T DpδK"KИ6#$AR4 tJ*B] }Ea .Bn19yZ<_f8F@:BxГq\~BFVY! xY h@9ĦxɶAHלpBOhZրbGƣEp#2%)u`u'6 ]8hb0k7ѽGBi`&Z OUa@ !گb( 2h4;iK #A0uH/H# *GsH H1X ]4!*1+zWog % (//篿)- ` p@͜6Q+`7A^pt,A-@P R' 8P D. yqi"%nN';>)R!BP8DkZA <Ot9dr p$6/@"טeǩ3hR;KJdsA͹ Fz`tg'29zT}XaRh3,k))!h\\Rj j 3Ҋ|2"rPl#GCHu _с0ƙ`lNeQ!eGX(*ͺε]cpbIZgE@S˰\v" Q#k*ּrm̸%/s5ЙTo\? FǺf4:!t,7dݪZ˟ FhhEr0UF~ȫ( 'a,crmEC+C*x8LIvBt znt1M!Txi_Qf`e45Ё@- m)$`Uc\䖤N~=43j.!(s1 O_Ңt_w-47jQʙOuTc ay>v9ibn0eqlޠ5I-l]sݫlKw!4@e7/U|[7؇z{P޻\;-G{6x֢Qy{j59n{Kn3ÿ]|/߲$g JnrsMk/< `=$O<,PuGMHrdjk $P\mX)6CL;f/9|" iHp(`C evEǥ*~LGak!&XaFUb. ,$OaXvzw\/z/ǐ8U-vF&r^ث?Op1}okGq/wuuwQHw!e ܱ}S{9gngxU7gO! %tW (!"%P +pw:1Msx 0?"}Y0wrgEe0pr<aMe~`aЂ01PQBQ)8†aBh3nxKUMwrVDPxy,S8B{]8 C^Q`1deVC|$(y)Z@P^&`i^%2uM!@(vu<6`Y^ ^qIe`8EG,RE A%X_D@z9T+fb~'8x}6sSd` %U U[_8oXy29gJ{`C‹Cg_% 6Z2cc8{+B)4" ^_n(5<$SDe`Б2# _Qh@"%Wɒ *iB҆z;_=1 $-FH _9 )O)ge)'{0+'@gU2b{&C i@bh`g5j0}C&ٙفZ B8`Jgy!sF!({0X8Wƕ 0\Bto36407)AQ)wau0`"$0c +99՞Q#x7u53DsF['PS۱ m`3C: jlb&P 7'r>U:p":Y $*7<02:4*hƢ8:*t²BMh%y1o"@s:.DڟQr| d砇߱-cz7`yQh0;@-~i /'&e)v7g 7FD)z8@0O;70Nj W1brW`x2wf>t2W~`3t1 9w` ݁ PC{ʩp h$p ȥA0`xQX\@.q&Mw/GayyugjWtFDź۴8j| !2UI0.Ca@HF1  BÃEЯʧ:Li qYz0UBd]%*^ jp!42ُW 8 SzeG#! {ZЎ 0h{|w9 ђ P] )W.3G!ap]"| !.!h0U[]*Ţd=k F "!g]tH0PI"9Ȁ[đ \`f;˶ J˓H(t G~q۷)D0P%lI+o]7熋f9 ț/9dkh&exk皋۶p"@\tI+H2p +s a'.X%!p ,T9,`'' Z<[ʲ{J 3~clll=Lq`L WG#o e|xz|~ǀȂ<Ȅ\Ȇ|ȈȊȘ;@B?D_FHJLNPR?T_VXZ\^`b?d_fhjlnpr?t_vxz|~?_?_?_?_?_ȟʿ?_؟ڿ?_?_ `O`6``6`6\p6`6`)`6``6`)`6`e`6`6`6o`6`6`6`6TP6`6`6`6`6T6`6`6``6`CP6`6M6`6`6pN6`60`6``6`6`66`6`6`60UP6`6`6`6`1`6`6`)`PP!Q!d,ڋ޼Z!F,H-@p1Y Ȥrl:ШtJZجvzxLZnzn|Nۣ\xg87$Wy78/P07y00by8zl7 8|גy$8l0/y77T0[fCȰF,2b3jȱGZ 92(SR`#I͛8QZɳ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix|矀*蠄j衈&袌6裐F*餔Vj饘f馜v駠*ꨤjꩨꪬ꫰*무j뭸뮼+k&6F+Vkfv NPp Ϧ`ú쮛MTn֋nKoD6A DE,Q@ί6Pn+b>fkp p?pnؓWnx{ל9Ctm/te`w#o:GO >E[ @]qn/uϯ.TW7TBHU ~ފ !,@&ڋ޼H扦ʶ L]! ,@pȤrDmK!f]\+Hո86&1`Z^ I3 1trE!yu ECs.,/Ldf(u/nqVX -] .GFG  U¹MBA!,z@p!Ȥ2IYE"K-bZ( z8DՐ/ BXZ3UPDOxNHmeYK.nRZ2-JZNB$E  wKGA!,&u@p(Hal6a>Ka>)iv3hXg&@fbܸa^Zyqm}%o z_+fq,X .,II{F  SIA!,.I8{% M("Cqk@!,6@pH,d`$*alNP'@)$T \ \\D׻/ )q |xzWvL0  H*-]C/ G$ FE$B z  SeA!,Fp@ ƤReR:X@TFФa:)5'V">QF>(ǎMx|~wuG3sg$m`Ivx  nOA!,Np@0@Er*gSH`dQU2Nٱ}&Fjٻtzֲma0/ &Gu dgB$PD  BA!,Vgrl:Qy.!Y'F_"@b2(xp-_x~z#*}B$h{GFH  A! ,^t`H,Ȥr90'a|JhChmXl6i04# yL(&G0x D$ ^hBBplE  GA! ,n%@pH$ Ȥrl:@xZXlg@!͚R|SxxK zM )"0 GceV*&C2.#hC'M* .{#(hJ _!}J(BCnɥL +bC֮ك w .Y%x .UgEBClaHPHYA8 #J{H`AA!,@pH,ȤrITt4(HKs%!a!x]'}0{B[R'(&CVL.#(+GKR SPI~/ B(Gx *v'l/ XQci^]HI  cJA!,m@p( Ȥ`A'E*a(³j6Fk$5omwX4B}qK U+" i vI]wFEZ UBA!,f@@H ȤrI@TIhF (DV8A|]NX-C+Ֆb50aZTyZdOjGC  cFA!,p@0@,Er* Dy&Ӱ*B`12T'$m*zX}kHmx|~a yrG+,Xz~ OCRG  kA!,`@pȤr,(B`1 `Vϊyna@Q.>+f|IVgRrE  PNCA!,~@p ȤRxX*a- =FJs`@zЪuL*9k|@,_C0.P}h l(ouN21  g{K  "14uUt #F  MHýA!,@0 ( Ȥrl6G `Zq6'YJJdX5 h=Gp8|'Z[c ij(..Pc/ }t2._($ hVswyyCIxF S ųA!,Y@pH,*IcNBvNlwlZMb2׌B/]K$PpC`?Q|H A!6,F@pbȤ1d6Ϩt9ZWlJzK.zn|N~B0., "'/ -eJ/tPU H '1B3]z%_J"Z[)IQ &G'15/ B*ڽeJcLOGV42R

>xDGBb5uU8L<ٌ( %x8Vd ~'ɍ;XE4 Phc'*\%Q* Z%_GF(GLVgFy$Nt=B'sBt<|RY⁙ dAPvMiƨ/ЏvMžr,'i"Tw$Huer ճXTEJa[4.0d1P0uSyQjCgQn x%\W07B'H\°p!PD>a&yi&D@ l%D 2?T:P5[ -(}IHTLXgķ%k_Ca amsl/``p-tm݃L6|a b- 77y~8tpCá9筅n:~k8ㆲ.gQ8 8|uBpC[{/W1[=?Do觯72 o:?9/D?s^-q/'=MppSVo}n`A֭vs f ~+d cB8ò!@ "r !,Fn@p(Ȥ 0-) OfJFB96.dl\V%'e.> Znv-,/ }~-i3lp|J%1qb`f"tg.mGjfGA! ,IU0(l6hp[#ѧX pr(Hz-@ Znr'|`'FFnlA!,C@pH,@rб F;$m@E.O6, 2쓈P.#(+Z%.\^M{$ ZWXD0 5dl"pkJL )BK \3-2ȄM c_vxLo'Uyg JadDWDOQl@ !,.Iq`(Ȥr$ 4j"VpURL X gG6.]}V/ !sIC D(TGJ0!`%!C" -iiA!,6IY@(Ȥr9l:CQr9UPsNYةmЙ+7s)moB%` ukKKGHA!,>Ig@`(Ȥr' yV$ ~1{&a" Z#2.C`PM'D^KS) Q0 4(JrKce~."-[a3nBFaiaA!,~I[`(,ȤrY BI$2 4w!Q0be]#zvNqc/bCwysXD+jr`JA!,I`@`(Ȥr<$Ta"#Oƕ@ha)k*LBk` 9&ljlD/ '15D BaKA!,Ij`(Q$V$\*ciJb&\,Tx8ͮ Fnd*ymVH`/ 'wB |M|bA!,C@pH,ȤR9!:Q M[LPĨrO7Qb -OIE2.i*+$1K1}% cP(/ Ct1_JC3-^B% ofhjC0 uIB ,a(+KNkD*&/1K*` -KqF!PD0Z2-yF$'@ V `CJ4!,D@p ȤZX x>[c X6 d !nyK % sEJ iA!,Cj@pH ȤrL. Tb5IUZ"R]DCsF7I8AY?|5 |B_QF|2.VZ4q *wmn"1$ rsEh A!,V@pH,Ȥ!$E-IRi0LX"BV6|h |N~amn"  !,y"Qq-SO!ŧ'ؿgo !,U!dihlp,tm||pH,Ȥrl:ШtJZجvzxL.zn|N~-'&%̌!!,k0Ik+#A[9^iJd!,k0Ik+#A[VxSJQ!,&XR dfl+*΀dlOM#L%QEJ+5[qF+6[Nѱ!U,a@͂^(!!,6k0I##A,+VxRJQ!,>^d@p(ȤRY@FKҨ*Q(8.c Ҝg}'ơz b( ]FYvQHbFA! ,F^@0@Ǥrl0氕U}'$*듙F0: #*& "-,2wBvULop ,*1 L12 !lL(o#FZ(wy&Z (%1, `4ZB/ $ZDJEA!,V^@0@, qL6BeB a 0]ׅ l6@'x52čg._ (&gi*|mL#iyB}Dk{} z(P 2|0ue}h zO$C/ĝJ\DKCA!,fk .0hd=uyg! ,n[@pH,Ȥr9, FBJThGDMz> |g39.85'']% m2&% !zrCcqP*2.BD2*#(/CRj~~ʝBA!,~k0H@k8Ow2P|Q'꾮VE!,`2@0 (ȤrPh4zxL.'h3mvA! ,[t@pH,dPQ"'(]MCarb˧aXA,DsZD󵊿(gP^N}rN%150uH( S MWJDS_A!,k0H@k8Ow2p|X'꾮VE!,`3@0 (ȤrRPhxlDzxL.޶ _ ! ,[@0@Ȥl& !ILIdEuN.ؑy9QQ5r,!\nlg'01(|I"' H04F.',g(.aDn {eQHǹA!,Yz@p Ȥr8{HT:F"LT>b ūh s0[^0-e i(lsL21  W  !"14N #FWMBA! ,Zv@p ȤrTXPI"Z Y`=^@CXF'-[,(zRnKmR}H`J({J#aI*)L~qDRA!,X@PȤr4R*ͨQ-Q:6Q&$KԨvqB(52P] C( 'V]2.,n/ zw01\Cf)FwC*nf" rXtC_"f(+F" !3$EҦBaDFKJCA!,Xy@PȤ9T 5Z@t40\&FZj@ʄjE+}/b4}E)#dVPC% WYD$_\qu\kF3{w0nFDw\A!,Z@pH,ȤrYTTF(@{HuI^ I^-eH[{fi"z%tl2yDh BhnyV#({y,ddy GRF GCA!,kIwt!,`/ dh,0QCW-j]LcupH,U&ӱ&k>3\֪!,^`@p(ȤRI 86m5#NP&B])B0 U}K$xB+B"-cP" C3Y Q*01_JwwqI()Kt D'Z~(0 yPkD14V"G/K[LPVKA!,V^r dQP:FmB Tx>aB]W#s&A,v8zHIZ}yqj~wJ/ u[_5m P$[EJJA!,^X@pH,ȤY-ȉ\6&Sx-]᫑>!bހHHhd^tv/yC(Y H-tzD2.THu}'r%-G zr"I}rFuB3wH}vxF~hjlC%1J qߺ UI$SD(E{LOB!,kx08k'.Aec:/ )sͺpH,Ȥr1ШtZvzxL.zn|N~t !, P!A,qf@0ƤlΨtJZDq ]fװ ez\&relk%-!,wInw C+s OZ"1CD}3! &#n$  'l #vX-|RȚbryPnB$ *.fZ *'# |P!kBЉ M fNW9!/8h ȡD E0p TÉZ. c@ćb\t$Q0ܝ4 Í<9, t0hJ!)WA1=lPfgIES "|ifH%],(ƠV,^P#i\ERʘt!"LF ĀBxRpPdȣ&?iw8D 6GXg/y#N`.#U8B%q1 Kր,F0ŝyAE <ا•x# TFo'IIhŒ#jE Ogts}CD-\v,TE bB@}t02K(P$zDx@lࠇJd@-@F&eG| ـlA0AC<#P"cU&jgFsJše0if馜v駠nhV|(R!J+F").A@o ,F@@=Eq-5F\(BZI'J 0lN$Vk o6@E}PQ6|`rS/iof#e^.$0 <@bQ&:i03>Aw ^c̼fGĀd|Ni>^"@]>1~jAhUƴr203q )&xAZh@cCRna5+AJfId~it\Y-`TiT}1$0aj2xhb2/U`B o @ |}4B9_׊e3ԋ/R8줏0l6MP @ g{L#H0kY"K|A A"g֧O#l^z#R :18GT@5@.BFTkRښ*Z&6S&IYhBJ!j@ @^%f@ .W}%lӝ9E橘 %d%  e>G@  ׸g@"ȱl~\ IG a [ӀzN ~>`;$y_6`O0E04c ~ |tKe58]$-IYjV<'} Y Y7[N" oX0t xP>̀A{˲FC`(#Jt&bgTT+[vizΌsGk{rbg.Nr`w/[>r/\6@%h72wGTҗtr4VD%9IISNw:ѹ"0|aKVQz]Xlñ0EBtwdѝVZ&Ί@bk <7Ϝ5;BE̫&ٔT`PiI&5u(` l?$t3 9$}m)\Hrw %K! 6f:"d F 5f>Mj ƀeHNP(FZu_iJZ Šs v(0brB `zG]S$Χmo3}07aQހ7zWk{& ()2tDE@iDhÑ17nP C+}d9 ;+6E AАrop2%yf;rki;{TE5 # !wP4I]cA3/>؅2B#g eykv])vEiF9A!6,50@pH,Ȥrl:ШtJZ؀6B'b  h q0MKd5]z)~B-"iK(|E(1 *N*'t$d ,#(  J%0 4. z) &b]I4%.,71( r0' LM"@0C1KĠ *bHEL2D8O4r'5OQȑ+Jz3CY5)m 0\37 Lƀ5B3+^XJ#C,2˖3O&@ BMӨC !װ?:۲Yz-" 6mG#'o-jD18CRݢBxO?oaz MǨ > ~!G{9 0C}pAvׅ&CbrtPA&WPZ= {3~ *tP\h=U * @ ,04XU^is)ɤB,HZ#'nƥ$"䎘f C V PyFBCzpFw7)unޢcǠe&pjnQ~ +XЀth@ nL4sBkZXX۪hs~+hs60ϙ{.D0+k5E!A, T@P@f;J\ڦGAIbZ3R4lcp͌j7O6mP)L6GPFIO)OGA!F6,50@pH,Ȥrl:ШtJZجJ'(kd0DVBtq7(x#M(n)u% *-g"&{#bn_jL.,/ 5 15q(.ʈ'P"-b"1)%10'b  Q$ 2ɽ7-  p/ C"+QQ7bHEʙ ĊPdp` 1KN~D hbz}Td`a'80 B-Bc( A E8Q30'NW"E'$`Z07  -31È+^Xp HL˘38@ϠCMϜMpRd Dh}Z6!<|!*i!  Znj3JǠ@M@$H chBQvq`Cy}"FPB1Tux$` r~ 6$wVԼ݁B]nK5@s+ꥁm @*@@B~`@=`}p 8 %9du9\ }]hf(ÕE2zu)$y]&@LZ矁Y0P@tv~'4ICzYpŸ4x^2}Y2|q¹u4GF 45A $lJE@0g-Hp@w 8_Э+V.ۼjg{>l'09jG,S!F6,qlf@p(Crl:ШtJ6Huz8i%mB$"p@BpSB*'B)DNs',( 0'z#!iIp/ 14 #J1!'-(1kĂ6 \ 'D0Ƕ6#RYk݋OXٴKJGB)A.!@Z3Hу2"0`РE&8PI$!-&S\ɲ˗0cʜgM@nɳ@?⳨ѣHwvY@`g5 LuC `1XZXH%P:|),lX `|׵t86pAj?`"b!/6,筢q]N1!±{by<00`]QJ( .:h,P"qРIvJ8k Hxۻk H@B5\dƤv q  ϡ]w(|1CSpxբIp \-JpA \PHL  G^ֵP̃=E Jd0C `x_/0ӢFF4"ِ 'R !C CDJ#&dAW1tec(X͔1p%2h5@Y8\lҙ]TKd lp(9 y㩄-\\5WIEL:f EU$@IM$TW@BӳF+V[ok8nۅyba T`zx4*/xjqB෯,dK4Po30Ќ1,g!r%q6AD n+CP0tCDGq(|3,Rh !##tsX?qAXyA5WETro1lx|Ln$FAπ(8\eV`I QXRp1 z59JrFpF)*`Aa] #9+:A *@@͗Ѐ\P;B\kv b"aa<q=y̔8.HR "^Jj0@HbH6G N ` jGLD`~-D Kv᐀jB5cl7 ̉Z>r/hk !E|~(x a\ &lcL'"2j \%fE . [(]0f0;?\%w)O#~tCKI _:&;r8Lr BziA[Np^SD;(H^eDzќ&$!XCSZUFIָNaYWXV;Ҭ̧>.ų(}kt`Bs _*q K@.ʂ&tq`OJv!! dTKG~`h *ҕ"AnjC/p\ @3PSZԤq2"bY&ʀ>ҘEJ1~"pB8h T4a]?`y.Es'0 =APM:ƫm W&]hˉ`4&buf?@xcjZlAƳ_NTՋ Fю'ze&ࡴ)P *KnZD7$t]p4f Xm!%@kWB'h01E+c(ƃ=Si- c(5jᄟ\!F6,qe@0@ڎšrl:hRJ~^`r945UVGi &^4ecC7 p*˲İdN7HV-.5箰JmD6~X %60N&2@]% n1 fv ($X!ne1JYL@WTxc6RG$SP2G䒔%M @ -!L.WL yc/fr(i&\ c!%M7z-R0sͺՋ[`isALIUd]B†KC (z4;Ȏ-?) \Or-@wv<4}ʔ PK t}N(Yh;1A$8!RADXK*(=3Z }QO n@k dI3_tqhڂܶ{{qme7Ii A4n';\1m,Uȉ Jq>fH=V؄M݄ T2%tDNg~ X kx Jk'Ѓ Q0cL;NeCol P11 t ( ?AX~P$$ Ϲ]Z"":zp>2~ $)BL9!/D `$HHJ<DJF2' # ApبB9Z!9,҃ٓ6.bT @-(im(=7ω*M,lvfP7t&P4@;)BR*CӚkH&U8k1)_LF eIFՄ w Ij0JC8AeB,oPUۈpЅ*KA"u]4j 4jYJ x&G~Ҥz!f 8aDuN%N?!.#-8v*bo;>8XaxT^ ]ҘLP &twk=9ͮt)s+GCSACv1͋a}8&P Ti L 1Gf16ehͰI~ "2_I;R^@r=sk" lͮvcG]A ݮ(uĶkzZ8yhmMQxY:[fЂuNЄ 48 -7|TT{G _iY87x%JVeYDJjp F1qo Px$" >p*rSi u|b,6x b DlU6Ԯa{ vp`CoPPmR*!Bu@bYy5SJ3,oWKMc$XkZc!4li J0 s}Xo=VmHf H *ppة{Fwfd !F6,qlf@&c<ШtJZXfrx 08fA*l7IA"Z>'(154Iw`)I)+IU,( Z# ^B% ]]w'k ,[Jc( .J-sI[b*.J-\`M] Vb<` ߽ ҠֿP˧A(MP#>`A)B Jlhp"[ i,"I ͛aEԉ@ Jѣ;E>yŴӧP="LԫXj:tM-|J6!Ev] ҂WS )˗ 00H` \s!/ z ӑ=Ġ1bSK.ŧ h 7%Ū`}' 0Ыtj5 ͗Ds!oF Fx,%`Q(!G|%+!w>\cj8I-hdFTfz1h\xWph5$(j %%)2Yix(g,LEEc 2!0pQ"Ԫ $G.J2AT AԶLЁ7L͵n+S t@2Y@--&5EU{ћ UR,l' J #%dƷXFг;5A 53yR"B0w_-r\e bB BG? 3(X&0D⬋ JΪΗe}pur ,5SڅTxwֲ; \PHggz&2pA@C7D)<x3spA^}35^q3枬+̥oqzxrڳ(~m%!^eBQ *Bҙ/?kټHI^ QQn D1ۥ<ܘ 2@ Ir Ky K'hj`ZV6)0ouo\whRtADDb GH'xX*^YX>e4a `lL yX&D&<.-I Q- -_kl=O4NCzArep3'cZq,w[97rj=2<4p *tP j-fϩd35f̕X?$c 3@2'v Dܙh1 ATY%T'$Й9JsvI@ D)R-d7<"BD(!IODwR͍@1f浗= Bb'\ ,A(4[Kl@j% !`d!0[GSBXh FE-"H/FҖ0L1Tw6:#$!eT(m!R 65P}]i$LtQX{j=A{gZ& gdX" e}f Jp䀂X!ඬ%_ N_Tz-+@rW'nTeV$k[VV'9sc@sMv\5 /XFޔ@z%Ћ8庂R0a!>&`ȕ$6,TCC#]Z@aI wXL3;1!?xgE\u .P0@ 'pI˯fx  @jZQB㐺4MFT M ,1h LĂjF)Hg' /@R1c@5l° 37W܎NtQ6 R|3Av0̃g!e,aBj'VaM0m*<TeŽi $ /u1d_F8UVD؈(Ve@ M[zA%F' '1(a:~@q,TɞY}gx 1T+>#K)trudJ-ŷgox XRD0T[x@қMw1P?x :jq\LYtakeZk:J٫alKF+VK.fvϷ+knA!A,:@pH,Ȥrl:PL Ƈv]ްK i+^b/S~~A!,[0@@@0,Ȥrl:¨tJZجv[ t0x,.4z.{|N~7}{ wBqs s {s'*r1 ,-,y.t./u u+$x-s.%t-1t0!SC9.t.wR@CdoN}vz— 0 G•ExRK +'8P*p ^8KpQ=K2-b9ŵ C !%`BFuff-!PAJ=A7qvdE"&]$ ?Qm > eX=b"d: ,?4ۇ:stiLaYh)H^0D1^,)ʅ `Qw92 ($20@ǁ_l ! >(!Nha#Q\Q 0($h($"ŋ0(Rf8<裏4)PiH&xA, q ,\@gS8p'(y$7. @T p dP$4EI' ^M TTP%i# @ EY'܀3QS} D zhn XD {% Q +DeCf:]|Z{&hbFDNրT !4P+#mpnmmp˭Zpc),ll+7HlP 0pon >%@k05 ΆVqe 4l8<@!F,W@pH,hlJUiK.RT &8%a`)U\,)D%]N!M`2 89CP w%"g1-4( Pe}r05! XNᒗ` KADnJ+ A *| q 6+ jF+ScX"Rg*B6m\b(~:d1qMyM Q0`n-|kV'ص(㨞0 .;Bq  1p"@5HdEu<0ALQ A_aB$PG-7Xg\wB!F,qF@ 0,$rl2(t*Zجvz@(zneNtA x{ vz ~ }{' *}. ..,/ Å)5/{10{-~.(Z<(@8<j!ƃl">}as)8… Iq" 06$Y'A}```@| ي p<1/eFhɇPLbe% AJ&ËEsl'h >]0$1{%F 5̀8̪*>t y E pItى(ZPم?/MDwPMBUr m 6B`Vhfv h(jb9E0(4JŊ-;=)9_8pA,"4 WЂ[8pJ% D& G;1԰ `p'KXc1 ,"0@,ɀZ h$01- ,( ` - 0y X*zz_ fa+K橺k\p5p + pR=)Ta D ,xА1b5`@NE/e*]*A[, 0n|.Q\  9NB A-:p!n8{\y\ug ^ Tօ0  @T[3kvVxZh!kPȲͰc'yT_"0#czlMiW[p7 v.#HR#ﰕ*y6oI2 B .n}6g@- 0| hiq[i'YU8LUZG`("LZth(,0FxR㍐`<@)Di`!@ TViXf\veOb>iHl首 (ItJx橧q:!MXl硈g JiD1HP”&TP@w~ oeVY)|((Ysd L@,@G>iy VӁ,B.1ff[ B9:iSbPXp@Up@AHBahj01 &kPjNn ;[ffYp+䦓ѕ _.:K`l81V |.1@9)P@v|ĵR1;k Tjs)W  `$ABIͲZm7:ge gАX5b,۩|RypSA+L,BCl`k-RnuޗS 39m1k .[n7ֵS Tb@YD΁ Ֆ]t)\@Uj C@PBJ׼zU<1UB @|1tbWl90S%AmH(L Wx$,(  Q gx  =@ ( ԡar. K*2cVb,$$E`DHFMp9b18HBxD ~ @JЂMBІ:D'JъZͨF7юz HGJҒ(aR=R2fVj@"LBS™O BP#"Дx ժZXͪVծzX;9ZkZ66P *VIU`k] sRMbۉ !F,[0@pH,Ȥrl:ШtJZجvzEAL.EDži* &@mhH  %! &# c/ 15I$ E'cH3., B" 4Bk HC$  *'G{0-B/BE01ʶ+( GجG*.% 'w10Ljm$6M<R A{TgS,u2(ByED`6AJ-X!߇:nA!^D9%F@IQZ`!/bI9Q}hP`+YK ul|'|"ܑ>Hq!tQ:̹͠CM3PNzְ_ˎM{ڰSi@ N v_μ ?NzBx[ν9ڻ_簓 A)O ==x'ت@o(4xp* Iw_o L0+PA5)'>"c@A0 J0@­aO<3#>(AK4b'EA @Yn$sA%R_0F Т=0 %pB($&"x $!MG=2܊sTB&ϣ'PBA@WG `B礡%C`yJ~!JAI*A] jo+I UfxwBQ yⳝzʘ+M'Dm Z?@.-b40^4A𫏯@&P@X \.pp ,M\hry(G \8OwsG2x470Hfj+Q00 ٵXh} xN8a+_μУK_n: hνËO{!$ӫ_Ͼˇ`}({ q߀&_ P@0z!tz1 TH0m $P I1|7 g Pa|-@z.a!0l Y|I 4d 7MIe y[5['V\RO[M0R%Btb BO@{I&Pç- zgW>Ov lIҝ$>ށj2•"&x0S'dh( b${ºΗf@3{פ N  Cf _( !$,0P@ yzNKI%Z{rp$l(,ɧY'̒l8s!F6,qh@Ph+Ȥrl:͢UNجvxL.T89I!B-!,]_"'(15 0 # wa C! ',* ,R(&Bsu qL%&$tBD\ W-B}_I_$ ^%G H Aӹ\.f[(R("k2J0Ѐɉb1䰘\bg)ƛRV !FL0`2h‡+Bs?Ĉb.t8@M5jCl&t]"${fi7sв_r}hE$9keuLNR8W!:Jk\ƘzrzhK%6 v@ sr}'< \LנzzcȼqYT_Ͼ˟OnQ "mM `n3! (8D̢0P1a`4(0<s~@Er#HR}Tx64$c䲋9SuEKE~E0B%hu%BlB˜2xI.,6~y@Oa&>uqj:1Í/Pu"eQd9p .$0``Eb`bXZ3P@'d(E V3rdG Q)7Oj@2tsA[E*ECR~(D=)IXRTr7)IV$" _k[bZWmW0A?M0@ @KlU1@=2xK`74;Q3 za<@-DmѶ\gH',RpBJ)B",k1: iiɖ/(e@@,ПكSIa fu\US(g6 Nma۟\dd0Ty_ FHB * ‰$A%Hb] 4|MXb'Z!DK ݟ{) 17/00'1i@6ߕ_9497;Bf*Xմ2_o[2{ˀ_xS0M8\㊀8hQ@> !9TeXxĪ@"p#~2އ=l3N*PEkN{b JX̢.zk4ùhd,!dI = ,02ֹH:Ldd'd@}F  r}LB7tar'1$%V)gaJ9ȖL9~uC5l?*Z00\iOIX8pF &~d  2fn3\bBV.?2A.5,[1@/t ?ڙJE*M lß`_4`8}(=Ӊ|'7dP]'&ĐCY-QF p  Cg)6mmiXpI,{c?Ԧ:PBrP-9hU{&@P*xjlRc: !h\A$>dUB#NP!)?K(+*WL,})1aGUԺ%tebZJ1 "k(`I4؈-1Z@7PS*50G  v.m\!j @!$3hC4h &7" HdZ=ʑ6D|ŰДbۭ*ǝkr =( G F본 e/mErY-Hm^V~UE0hJp` 7sδ?mojP ZA;YƾőCbOf9u 8 5C&l$[x*=4ޜ Ssg!F,h@pH,Ȥrl:ШtJZAvzxL_zn|Ns~|yD  U sǰSȽԬ ֘Bѻ14 ,/'0ܚ.*, x X1*d@ {Zpo ȱsa)FP]lH!]%A!AK @$K\(@q  3mJdV1j @`pS&&PlYC(DJW?A<̫gv *1*Gbv#K^b5o$hB%rX`2"BɰciY-E< D6҃aW@KsC?('BhiTqK͜:2 ͊>.nO}=︼&*X@ | >* X@ \@~D0`sx'a"Rb@XNx4 1X:(d-h%- PF)TViXf,%-2)dih_iJZ)tixnɚ*er袌u4*)"L g:ܘ\@2A*jzB!$@C IIB' @Q+*&R)fΊk$0@*8Т/4W/2yFk3Z- WX+ /@ |QAB`6M>Mk* ~E!D`R֚@! GH\*<رd66+ S.< i3?K*TԳl{YWO2 A4j%4kX|a=6 b6O* `Zw'<+8CcF~2嘛lc砇L瓋n騧ꬷ.n/o'7G/Wogw/o觯/o HL:&d+( C*`!@ arHXB ,Par`@a e e39#0&:PH*ZX ,5C -`@#3Rp;\#9PFQx4H> !F5,[0@`H,Ȥrl6ШtJZجVhxxL.h|Nxzw |sBms!(n1/'%&u1oo.C*n    !0m,"u.p., *{q "-$ 13n'1%n&t-0pƹҐE>7)}CyssAaD/qP  0A9w@W 0B|Ys#Z ܀8p`%K1 hNAf|92 hqU֦H@E (a[ZY!ɺb0D *ޅu!&O$ΞSтzx¬{1x Υ ) (G?{'%Mu7),8!~ULǠ4`ƷqV!v8++#^]iHN?ƀh`[$ 6F(Vhfv (VL@("@@nZ pW1".x,P ` _mc@3N 9dF  Kr(OBRT#dT Av<'3TEBpN94R`]^| xf9! })\pbzjWBQ)Wn#Nlʠ候LnlB@)Pnj-\bx^nZ@2;­UBV .[Z  b)EF l0/,E D2닅 0D<1 ld<@;,$kaD(, !F6,[0@ 0,$rl2(t*ZجvzBxL.zN|N~7}{ wBq|  v-ytqz1 ,.s14y.*u./+$ y-s.(-%҃01r. wijPNgG`ӳ, /d ) sH306 Z69-*Q8.ltJp`"IY4D1!Ĝ Bcrc )xO<8P ($ @R:ޜuCF'E9~0A1FȈ md롈Bx5c2( w l]h<Pj0A CV&L.'h1B_Y2]t30pT߷*x̣_?G=˗#Ͽƀh R$ 6`KPhfp xA !&tćp@֊jBq` $0@Q!$ArG~dDxE>A D>]=S3,M BA5 4hA y[¸GX7/4 =HiśzuV +C dmG^Z [YMrfvRzܣ} OdPT ЙEbU"SyŘB{)/ DBn6e+RdB,P*=+>WȪ=>z( @BiNjMQۀ Po (y3*`&>LpgȹmK!t270@m%\FQ  se.iV!lx%lX3\w`-d!F6,lqZ@`H,ȤrX, 8Xi u0YȜ#H4` <ÀèwV@4 u00?8wfΉ @LP8dPWDŽ #8rn]; j5Q' )Z〇!ʝ\Zb< A z45YC3&=B 1T ]ز G@@Fp@ 9ā"|1"r]TSuλ^۷7 8p$ !GD(a`ana4Gxa!c,f"A-j1 `#9ZQQdcTPU1f@ LUTTrhx5hAYR!)6 Ѐ ~`CYH$0@Jb-\Eٖ)CdR~؃ϻۯ|+??"o 8R@ @* emuYt  4ȈAcB R,r~s ~&g/MՈ %0,RB PԵg8 8-$U*BrۂžW,pŝ4 xUvvO΋OH&֋=7scSW5Ծh >!gh1C2ҥ<@ bL HGb1hЁdg푂J'h ԣM=_ 0 e$F !USaxk|r 5*C6̏J(d|*&@b2L6PF)TViXfY\v_VihvEP  1A' P|2*X 6BfIRЄv`@NB Ae'FaQIqABG_CmPPd@@'Ⱦ@C5N@$p7TFa$~O!@@"$li~:'<5y :–9mȖ{i"R(;.۹+jHXpA Q:2A^+Z ". >2LrQ /+9Ē磺q486# 0ЩAZT"2g9aT LL;HPp8 >AzSyF1cwx.z0Th2&訧ꬷ.X"YGQN9 `pD@w$))]^a'>;h%ǀejǗUO\` mÔC o5۰!|q#PN(AoFMxK0Ax Rت "p Ā!&X?6 sAP2(M *EQ(\Lޘ hҘChהP (P$PRT0p-BFDUb (p&"0ƻY$xBf цj:xMQ"L "p!xA hN N#ɏ,gIZ;g!1u,@K$0V0Ч?9M5T i)W)Xb@ J@6$[Ȱp5lu03%j(,#qX؎τ؞ >H*9Ȳk#oMU9&B\1̈́-k'Rx̛ #H ܋\ !(eC0da1{.$@]_@('U:*7;Ȝso8jI\IP0y'KY.C.ljH`ۃBBt2"q =<0cfL7!@MNIuVB!F6,qlf@0 GdRT6>ШtJZXlsnٰx<^,q ;S/`29S(1}}/(Q! yE. -n"'(154^Nzd14/ r*Q !0`B)B)+HyY3X)$O!"-1. &, ( EwW% U14`-܇<-\`Wb`AĊҘB (Db"U@. :ChyFS![D,z/le@zI-+_t1<>|.jh]#D%UG}L  36j @w<DN @]SQi$MK85JCL2k0I /CʸT2v}9sP0Y.<tkn<~̾{,i^Ow/o OPeN0^ !$3 'صSHMOSMB`n``Ÿ xt-&hkBoY H,eY찔>c ̰T"yIn& فROLqH{h ccM0@ ^U&hZMXsE2_QX|p_KF@ `&- B휙`lhUXU))rBw })'`9r%b  @Ph0omNxJ%D` }d*n,7eɰBhUJuZ Rb  '܄` ʚ*}NR[ 5I<sB1u HzM!p IBL"F:򑐌$'IJZ̤&7Nz (GIRLV򕰌,gIZ̥.w^ 0I_!B1+ ̌&h|48tfIΊ< U9Is <0vڳ<=ysV @JЂMBІ:D'JъZ4A!F,l@pH,Ȥrl:ШtJZج6Y`mxL.zn|N~d$ C8l8/O087$8/8"y77$iX7 HƎۦ07쁗z0spC*\Ȱ] Hh`Ë3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^ͺװc˞M۸sͻ Nȓ+_μУKNسkνËOӫ_Ͼ˟OϿ(h‚ .(@E)`\h`b8aZajD6hV"#pĆ,  j@ KXBGgQ Mx*bVXYA *> i~≞Gbh#&!c[)Ēr.d)y^,\HD*<ꡐE:zą|j>'@ޗ *z*BYܪ냱,Pl{"[L@P*9k zx>ب :.VZ# Nޒ)oɎpcre"(ʩ^6xBY#!Z#*X/k@r@jP2< @`3)m!,tB@p((Ȥrl:p ҬviAfK&b45ZЙqb94-y{H3-uCg/!m- + P H*\ȰÇ#JHŋ3jȱǏ CIɓ(S: !,td`HȤr9-~0 *\ цh,XQqb&FUdxC%&{K .%)}{$ -`KCA!,q@pH,Ȥ(:Ѐtz kTZnaEp$Cs@?@I\>aKe/e'"~(&14B(.XHr^32W]VKB# K-I%%1*HV.Kq.V$ -h_BA!,. Ik6#ûAR!,6pH@pH,$PBdqrf1" N.'@)~(KbnGxXr\eBA!,>qh@pH, N#aX Y%Tצќ@`ؤ&MdeO/r~D%T$ DUsiBA! ,Ft@ @L@ͨΩBF(uH+qAR8%Z0A3r quI*'F%-#`p*JduG1g t"1|S'V./ -F/ !JSDA!,Vt[ärl:R9i' hb4P\,rɅ/sf7v~zu}KQbwXFXA!,ftU@p((Ȥ2Ip8%8%.(s ;P=DaX耰@(}RBXʷd! wq " -!gbBA!,nq@pH,Ȥr9l8 )d:%1%b0pN;dM+Ѭ찲#X+x`\*&2.^J,*  yK)('zS*.#Bo$ I'Xa.iIcB/ -V \zBA!,~t`@@@HȤRI2pN%i%"ij+LD-Oc9}P82mB"[$ ')[ / -BA!,tb@p(Ȥrl$Dk2IVY `Ac=#'b^Fgq/ 'hq -|NODBA!,qd@p Ȥq(3i8B`a4k+,:)? f@/(E}qU)xtHv# 11ZGqw -GBA!,q[@p( Ȥ@'MU q8J6D8&kt4Xv-qupnOUR!\KO" |uUBA!,t@@@Hȣrl:IIB)y$m\HL3Q} T%\,eZq&MPuF*'v&B\(+}*~} *.CIJT/ '15GB UŴ BA!,tF@p(Ȥ8 v8%9D>&p@]8f$ژw)ymAaaf~K BA!, Ik6'û)R! ,o@p ȤrtHXHD808S \>hkr %ZF Z6}EK|Tl+k&t-%-\(eQ(r'L  g -cQ0  5 W,0-QT{BYsI" -#)d$g!dTVC/'d BA!6,p@@pH,Ȥrl:ШtJجvzxL.7- 28h(`!rw(&{[|Hx p#{a^Ynhxu>! Z*NDO,DCn6x&T14T*>0hi" 8x4i"U z9/k 8s`{&\X!Mţv00Kb16Ά"mXBňSƯ#=~4 3{ PK@ Tů@ #7-(f0G T6OaJ' TgH9Adi ":g]AO4v&> h ,UOIqpj'=J=(V^#Ŗ4kkJ9S\0 *Wy6#=_l#~AK:BY/0PCO&(Ao5| bnY^kDbt(U4xYˉ6~U`bW*uh>Ґ q' "q$x!˕q)40`@UV+ B3Fޖʦ#Z5*%nbZ*0@vjކjf_*I ) ѐ)jdދo#YOAkts7&Ԡ W0 gH84&@-LCB / DPH|O|DP.7b@z渢6P,cHGqǥ6E-cc:ְP{x`7z [P'0xz|-4op !5B/ i#ein0 I`T(+fhU%m 31TD${$ŲJLLA!,@p Ȥr8 ѲHO%:#bb-caDW/'M r_-4x&n_!(&W!T3.#oL" +W%  ^$e#dF^MƀRA!,&@pH,8,iTpjaJd5ZP .eNaa w_5w-bw(&B{}olsi~JRC*o0 Zw(qC$&rzvFDTO`A! ,.@@H ȤrD,KEXM.@2D> q :0bxE2{zbz, Zxj~.Y"$  rdM!/jY/iCqLRB KHܓA!,>`HǤrTVBX,-J ƉiE2e.D33-l^Z2g 1,B% 2 olZI.Mq(&ex+C- -e1V~M C ɷMM2-~ڷLSA!,N0I##Q,[)^iJd!,V@0@Ȥrl*'M(X"+,f4N.h'x5R!.ib.# y&y% C2Djv BM(2-qGL"51 -]K/Eŗ ‡BHIDHEA!,f0I##Q,[)^iJL!,nl@pH,dUQ"-j@Y'(HdCCTQwl٤{Z,s^`R}^$ x"1\X'rhv 5x%}xcSNA!,vp@`$ l6cB8!0IχjHk4TDq}s~Gkq`2$ pl2- .r& }xF*GzHhpCA!,~`@p(<Ȥr4£T O\>E"TVz:룪#g(.yzIDooBA!,l@p(Ȥr L*+V*&$ 4c^0 aD"!\Ei1) $1(+21   !#B0tC0X^ ŕKCA! ,@pH,ȤrTPccЬXl{%\y}]>'1p/ yJv*'/1D%-jJ, *&4C(+`0 -dCSPi"!j"cP'piLTCb#tUK bz5Q 21 B3.K!i  v`"j$`a^C%1e` &G G0 Ad !,@`(Gdr90cXI0.-Fa8IO#0H!VOK50pD`)01*' #r %kBJOyp&Y& (% (." d x^,E/ pA!,}@00$ȤYx(e1ZM4ZHk }0R@2 _^ mo(qyHsb50i +- ',iV  J|iGxGA! ,z@p(Ȥr$N BHOqbMB: +DUQ&*'!q  .CnG$)BU%&^] ~}KkA!,L@p ȤIQEJ5ro(6j:_֕([ samcUmCA!,I5`8$dY! ,c@p(Ȥ29)$)i4@prAE-vDVѸ(pZ1p|jd% j$ )s" w'PFZz{kcA!,w@0@Ȥ8)8GrhB86!M &U"btZTlZ%vztH n-sKw_71+ _tFkGA!,_@0@ȤRX . dhD =DM0PpH,$rkN5g d)!!,Fe@p(Ȥrɜ,|>-9xLP-Bm XՀȗt$]| n('Q% 5E/  )CD{FwA!,V, d9h 5 DM0pH,1k|Nҧ !,^_@p( P@P沚ꛤ8K2qE*-B0 ;A G0v߇R5@ Ѐ=]XP2(I +r0ʬǂ X@)PGu1 Y9|*@YA5 *BH5W/̓ bR7ʭ- = giJþ2"_EMPQGݻT e7ǡwӘCx(C}apy@s\.L73L?)(oE FG_+qɼDK4liλ<zB @=CL``,n^;E]9JX68`( ~x!P\`4B! HT MbDP@UV`T zq1Q>V=i)*i`л0OF*gD$XHcMÞ!g0#\L7u5 P1B%t`4"Q@vRɒtHDd#DH"4 8pt  X5a(\ PZ5iM@t`y s'>5rǤ|@P0(u/H2d2YڍT |2g(A*R6*#`d95P `@/3^B@.+=-ZEe6c vX4p*B&Ui[ H+Q58l 7cum #qBqՔ&B4GH#KT&Z+r!(8i~^ @0e q=QA}y!B@1ea;ʀL n]‰{ު+ZApjoߦu]Y@5jO州uEݿ+[wi=i'.M/&k@ dž)~t4,i΃* ,i/ZwvcbF>!d{՘A$\+szA\:,~zpJPX}*2@Iț4c+?!ntpE$(+d ;4R"dE `Z0M[r!XE"yg"d%&(.dyٰyWkK;>h_@h`;@F2!a(P(_r(Q%a4rr]=0U/ JS#j!dJ rKd}"0Z#,d}{twn}}D 7OtRT!x8/ -f'`0@YDtuD($0:(W$ADyL\/QhȌ.}&G$33/ '%P8'045!)*5fZ5$4KȎ (U`D2 Rq>}|pKP̱'Yh@IO  9llؑpyY&9,ْ. "$y4Y:-06BYuyu9Lٔ(Y1TYVyXZ\ٕ^`b9dٕKh7 jٖnp|P56&uxz|ٗ~iY@li٘`LYyU}iLNOP)G虷Iw0jKcR`CуTz"8a Z6 uFC0*"o@{{Ou7c%\\C0:\cIC\cBtEJä2zI3T:[<j/ac2[*VaJk"9gCӦ.04wq,`C0/)@zNH8A8oBPRU10ZPFOLqr 1y0$c(Q<D1yBJ4>w.a"54%4& Ŋz(ܹJ?*@ Z#"= ͪ^|wDjچw`j_0qqE8/6&ʊiiiJ"&$idLqx:_*~z&fEUY:.1X%fK/P=+: F2)L#b5t7+Kw5=:o*+4E;_H JL%a+@T #ӲGG+79_- ;9 <; drF>*c^-#{47x }3u LBg#y5?h34! Ě+@|@' `K 8Z:ρh2;4;K)#F#07` oL,1k#* P2+rɻ1 rA/EvK/{׋)RKj=3;0GuX4gþ!Radc4;=Zi-$wR|>-7swNs+V|b2CI@W&&!XZk4%񧹰1K@"R *e0=Co*8< k@(&r\F%Fуk p$0L8hlBH<ıA14;+xzd igLE NsrLq{Q른#3%3yI S 1Ȋl<8Sr5cbJyGL+3yU03a3wr;3^ $ 'YhU.KFxB|K28DҳC#kX٘%<@f@.00L+|A<+U$b*{(z`B@[+PB3j/JΪw"[plEY1 {6 -"cMջ4 &2;[z U#h$#3T+S. _R1G7's42PЃ4Wa& }%ꪋ1Ƨ< '#K'1 5`e&  T7Ya(Bb3Y-fE iDʱ+a.($4$t%SOCq =+mtѣ7"=q=*4p2K,R܁T193`1SɧIY'6ߍ2OͭVQd3*SLm*-Ls/?;FE%Ժ N&A/>˵OPdա1aa<; O7~KJ< ף膂ZcTBr2 LfC& #g4FqQ&2sG¦,ze+w4a|uV7^282RpM?b4RO)Sd؈F;<C23$qG4BK::$K4{A*xSe\b{ =T")D /=m'Kd)KQ&"Kb$e !\mx 4]U@@߮Sz_$/+K a1Xm!Uv0* 5C0UTj=-?a5WG[/%|t2/"河E*N"Pj6-`Q ld1\6iv۹"wv L$Y,BH_$%':,$49^F:>;.OI(N-+&h\`6I|OᔗQI&H,z ^ qC3Y Ѷ_6kH Pk̝I:E Gbnd@BU@9r:$QTeK/a0fM7qɹg9uz ) QG&EriS+**UDzSV_ lYga*Їm[ok;n]wKU^<} 'VqcǏ!G p88>Вd(Kh(Ip@ b!?&i/HHPS%HKl,1AU/UD!`Zmf@R]]ո0| cpL2}Ck&64,PRXDWH E!>O>[mcmMQԘq"'@`@1҄- sT1@ 6t%nÁPJ- Z dR&T2DhM/&Pszy-dQ@iHIߨbb MuacuE`f 2QcWm n4H@3&#eU^ \79G/o*l9P  e_$"2rT8a`6avz1c|  H~;`g͘?TN9e2X:Qh_0n ?X}]R`AgA @ 4`7N%nZ(8ɑz:('Xp^)sS!`Z=@p,jfľCd H B%x qɔL1[8ŦNP@l=n )"\ =Ԁ hA u `F$;F N>08)ǻ!- ^P@)BjJ@#:>J-86KH([%&X%Joo/02ml.@ҋ`8. `K)*JtBHn0%46yӆk )p t`"epܤىNvb4W>W}KY*I] (@.W:,b8u9ztG7`+@ -<hЂp73v| }RX7#)!tTs2ikC@JFӭa!ڐ$gse4iH)n)kv PdSf7]Z)碮86Pys2 <:( Q mcV"n$8melˎrmi(GXp\P}h$.M M\LPB"*[еJjb!X^ŀe9 .v) iq!\s 4PE*[Q~BI]vr`#h,8) n!i|/5AӰ( 8ҋ2:wM?pPN*E Y4 4vcCd'E*۪ȽFӽYK~RVq-l(8h+O,WOyIafjְe`r~i}Neɠݦ%F.8?Oh jW=oq8dSQ9^yB$4`IA h8`r~@o'A.U $2(-aI%; UvhX~ R !f L)4)m|OQ #3€㐣F#\0 h5%(WFW諒C`$&\l4"t@^6Y'qTINnғe.[Ѝ9 f9LbL2f:Ќ4Ij"ؔ nz 8IrL:v'$pz̧>~ @JЂ'@τ:D'JъtE7юz (FCJҒ(HI {r|L+6'NcS{<~*!t?%P$T'Zϩө>=PN5Ũ-@q $ P ?{ҵ%sFeD5ҝ+u kvyL@|@a!W>(L@'2gA˧nN= ցT?ʝ@0.XCϕoUd>B:]8#:و˦1W*EOo5@;aPFdo5?XjtV䠛]!@Ea%BC UY_xVⓩ- ,U/g H`,as4B> Z2uL {f( a,7QPjc ;f~_ X1!+`9$QH"Ђįw2\ͨ/dlԵPf;X0w:EǨAt = P^iPКb}jPi QUz2Z-@ؚ$d !lmˌ*¹5V1ldHi ^iiA/4ӡ>8|@@;EC>6PJɻ& JKVBVbCxw si;ޛ3I8PL L05Q@Fidp=$КGd).2,踭+3gre-mߊg'E5*k%'((g6w ~P\ƴ.Pnq`MϷ;]]ܞ@W0Dw OWOg&@`=1 u6}]-^Dl@ #KNj@Μ|CS@><{^]%L\Od"(EA@{ڽ'c*`AǞ04coiD9sG,D@5 6;f?U#@E=G]4`Hp`WSWVO7b^*U`X^G}swq\x[7ieOf,v'7xt5f5iQւ(QHtd`uv74)6KqmJxsWW3%#bdC&"Bb1Ph%OOG[T(]Z&1vObZ kJF3j((1;J6p((Bi]ȇ]X7~TF4G~0 ({)|H#(d eOejClBl@cd,PC!(X-XĆ{h4RFfCj:V SXO(ghOeav~GSOXOehOOSH0hi,w8PGYOu9 i@2&y(*,ْ.0294Y6y8-9 ԓ>iB9DYFyHJLٔNPRQPVyXZ\ٕ^`b9dYfyhjlٖnpr9tYvyxz|ٗ~9Yy٘9Yyٙ9Yyٚ9Yyٛ9Yyșʹٜ9Yyؙڹٝ9ɓ?y9`6P64Y?)iyMƄ:ԟz$d q:z ` :$z{ (t,o0:j pC8:69b96K@zI CjHڤHFRJ)SzXZA!A6, 0@pH,Ȥrl:ШtJZجvzxL.zn|t|ۮ`#C CEKEBEDIDMDLB L" ., &%')M0ף"w'HC/!eMJ|QdB%5`c-X1Đ1D$6 0AE M,(wG>2pɐ~ ݐPmt1ĉF6BJJS.°%bӃ^"hS '[0BqT|H(PD _y >x!$WBPFL ֪E&""!(( QaR[2R)@@"^ #rƵiA&I֧ bL/т0P33r.X/6!X3l̼ abxXo -fʌ`"1Ag t`-v p` G T?) /ɧ xPMt:HLaL$BCRr-8L9_*d28ƇK8h  dL,0"t"pT `1XKdf$.$ֳyn)C^$KBfh@ p'3-B,Te`,*(T \ 0 J Nyp5\C Dw%°wU)#~ګh~ )oofBtt5\9Bf1Q."INHy,l-|XF4JuЂL @0q2 `IC"= $ 5T{wuIZg@V)кղPvPA@o67u3j܀Q2(&'F0؎d7[rt36w79!`ew;4aNR#T\Ēf(ݖ Z`7Ă/tkxwmMyxcs]~ doE.zGtK#l1NftE. 5^D ^2"dU"ƨ+m|yMLr+r!f" Q)P&Z(e6AlYf% PDNHz| ޮؑ*r1 0U3dV 0(۱$#`eAC6m @ #<(HٌPPD $ |$,0<2L:/H(E) t@K<dr /!;V yMά@RJ Z&Q0s4IjZ 86nzӛXYrV32L:v F48FI!=GY% `ЈF:V 5 U- @Q `'$uv%,GC(` lYp6+Uj F #H2.rBYe :RohN R>YokZ'e\QNJ@t "E_Wӥm4@W4X2Ы& IQ8$)-rdh`ඊ!GIxph@ Dh0`!  i  VÈL4]ƒ8_MbbZ}Q8Ѱ1_^ { )muN@ENc AXU 8iw,זd-)H{ p&t0T@hqG 8Jkp߯%  'Km㧐$w!1)O CeIUYlUXJj\DV8Tr}2ٹj-13m8<`uBS@k}0eIJ4 2hhpQ&>s;m֍8 X1 p~(#e,gM!QwZC]H6]"h ~ap!s:LC%|22ik>5uϷ@0~\oܰVO0:qk f,'^ tn n=z8Xt|~U@ ]gb'_;q'9*ɫ=%<_ltҷ v2'0] q@bY(% gz @{6RbQkXN,g+x]X0{Yxir<0a\קOw>WPqˠʦHFE[w94jMORX7 z ue~B#.Fr_w?ky 37'@to 15F ׁ$\$bq5p\(w~y`LGv zqwsU{w[mFS_4uVa4cFxf!Epvaz WwRQp_y+pEa5b0|9V`(h.~x|}Q'crLDŽfːh|fE"8y8 j U~*H:x;9Qfhrw zrsx_kȆCQT%eՇhq`b!ЇyɘU`&4Ȍ(V'mu1H$BQ`bhѐb3 ȏ/ eЏX/t 8y #dY yS$ "9$Y&y(*,ْ.0294Y'S:ԓ<>S!F6,y;@p( G(`"Ш4Zجr}V8<.kznk/|NcEy>9wdefYvWS0 ',H"GP$}b!# H\C']%%GPS/ye/ZF"]~j Hl g.ǰ "&B\B?`@XP@E#2Zq 1AHMHb(brZJ(P|$ԧH^4819`PbH/U"B,N1xF-%ڂGEHȌC,bt D !Eq`䈨@-HѢՄ@/~KHD f`6PM̼9 )sŋ5f‘D#22B.-Q?v(H8Gw0h5 0*@XBm%x BnZQnNPD ybp*&hcGdByKB(/'  1$A 8,i$9fBQ[! A+5Ђ2@xYbc,)(SIy '0RAp*0zE}㙰rd\ `.R)4HYa5w  õSyO=PBaI 3{_v-NF$b,v TT@,@Z7ց@qr'4q Ay5`$jI5I;v 1${ 4 &oMP2uO(pm Ƞ.C fQ/ua]MZqAJn!'V*)A o*H^/l 2.(!Rp0F-3gl) {`wab4 nj,FTL$gYnΪ]P-8N*#@ӤWE_8u G`I!* HLi6@4jW\N9F\7*W&0Gl Je|$w F>?2Ψq4 ΋!0|.<Q92S:k# B"qa=¤R2F`؍KxwS9ؚ7k:kAB S7O8N*up3Al8(~L lѼK7DaxYʝ^iR1ٟiUYNc ߶}~ 3tX̌;=' EEcy7 [%PIH0Z4#ڀ#y+rɀ awj[<4Ohm4۪.әJ^{ᡌWկJ.X޽I{ ҍ > QY<QCNjt@t5a):+CÞpW@`0RߠmB5gwsvg/׊+{='t܆ 59X,-fűT!- Z+ _3Xͥ &EM <Ķ~xC !P/S 0xdmC`0@׀qf] $?hOV'(w f|x$(bW$]-\Q\Jl0ZH(UJjjQXU\*[XW NdXfxhjl؆npr8tXvxx8X ʗ~X\h=orRq!1wW^C&o @D6V) pUo!t nU\hX+ Do&`a6'nb&ob5Sq'o0U)f61hh(JCJ.EiIL(@Ș&=S1FQ5Q1" Q0f8+BB$P%tC((+@'qB,,Έm~%0lcA/oa(1PULTg3$c28%Ĩ1xC)wPUR0CBOY9Avx@@@,1&P=d'Lh#وg?,?bvhd`a&UhYfE];xeg'(aj鐝 \Ō8hX,xsv!$5YbV}H65AZu+O1 гfH3DnVcQ'i/Gi. 'US ! i@U@9ٝIYoҟYnu!F7,|G@pH,Ȥrl:ШtJZvz`L.z;|N~a L HgKezdEDCJ}ŻȫCѰVޝC0&, B'BEM!#$90Ν@ ,A &)!J{ "/8̫$d~Dyq<3ʖ'^yS> @ 3DnJQN9ԧDj!\`DpPx`!B>`CxxZl]m^1ρ[!w +ıLܴadB c1 R. # TA1 hvD"Y~Ёڂ,Ƞ(h! AYmi<!* %%ǚ&%!Wի qfr!B'Ď~@620  kM<2hh6:Rk\ۭ5x^uu}nRv]d1@zPzZgUTWp3h)Z.D[ hm}) -x.J2STB7P: &dqA*F/{@0lA  zɦ<8Ϫ qbhd cKza/d;ve A0arVC~׎ՁC%0hť{F>/R*. JiJ$`a1 AAD{7m;>%:!-M D$z54_dlQ]r>MˊZc4FEj4t]q@BAE 5|[:,iȹl\ aW«WJբÙ HME8 R;㇩ @B8bxbP]A, pkLjjrC^T&t(}fYtlS|((B|NFh?~,@ ̊M~<_88ď H' ;BfS(YbuS"<ғȧk:eD<eJXc"3`Z3 5Hi͏M,TqH. oN5"E|rM% :E^qX"PE+ j.`5ȢD,5e(PT|bJѥӲֿ851J,(Y3njh[dSYbS[ D׹; gb$3(MTIYLP=m((%h۲Uw.iJˊI^RUSn yW FPسƫ gB\ lK}z[5&Z0j#h@Oy X, l@vD&K u0p$H"Y QtBND|De IZB$6n_L%L-}b JS^6~DE!,CB û%C"#ռBߡ ! %1}5݉N\{g A :k"PPbfx\[?,$1߉#,h B~1 89߇$} S\)U&|lTn qٻqQ^2 e.L0ݭdv r.t Q[) Xy5Y@iE5Fqے4$pv.VHnN/BݩY)@%)2س/QK01) (װ~PB׸/.d ~-M9}s` = x@' @7.;np7 qy䚏yfLb: f>g@ 뫶P~@F  +U,̿2-Я||O2}ܣq}}}2~{A@0 o?4~ H0!F6,C@pH,Ȥrl:ШtJ:vzxzn|N~ dX$EXU\S^r^05" ^%1]B`FŔKIPƥG2.#(&Z'DCC_S$ڂ7=0 qd^*3 TT=p"ׂεB}Z,DQJ$ Pdĉ,PDkKJl`C!*I`KA: at(QMǼA9,<c!BWb"Dh1," e{A;-@7,//0=zr*HpbU$+cŇɐ0$GEka"A0I\ha \,hq4 VYzbav~ g#d `ψ;.{/0n+ jŔC~054 '(@CxØ;O7zq=PdPE$KM@O z`" )$:AH!xcli2HdPh`ɤyjH i -1 S+ma{bn4F:A_eG#WuP\qQ ҝnѬu'z?}$lx?zheweʠHPBi-P$v#HѥbéX!uj:-.(meAl7Gx P4B>'B[OudN7dNQ`Vj1` *[=.nM]d!yw ui#8`1Z$Im Z쓲Tx~C6`h#bɪMʉeo,> -xBé~Ľ3> ܸ\8+ NƪE?z0.^ \l6#4|j Q"*L. @P ՒZ`5 , r\N,8c@ n 8Ĥ\BPF(Ѐ$nRP 1X m K(lȢ {qhf{N;Rd!3,ih'0E@AM ]7".I PuaVQL+}a,XZ P @;GK 8P "" XK;(аa Y&FEs†0&[Xy2$ׅ%"bJN\P$x2oڱ&B1@z䛐8 ߅P'1!|9lTC(GS03M~K`la_d>dt<&x]1i( D 0EDrwׅr9h #)˜46(: _nvG䬎9D2;yJ'ZЁ "K{rDJbXdxPV:*Z鬴 :-Xt2Q*BKS &/pvQ9e( P0Q@qzѓ@%{AmO&UsXc D1. ]./tȓM%@qa/ZD^RE]*ն@NH:%9Vq\;B  UֲX !m8Hd/%,ʼnK<>L9ȂQQf[ ݪYXe@Z f9^ʻ%ӂF! Vd~!o[nӦ1[m*b>1<׿؝Mm,N)Gb9W)Չl&LG' (3:/`t2?+cX2f*3e=DA%u'Fh^JEl& 07V Ax 2kӔ(pմ@@@= w!0u_NU Rū;pf FUVd&Ye?q`> H=aۘ|zC$<8YFca@a+Ċ2Iz u  v&Ѧ#i0|V"%00 < Xt>6yd m^XU- [S~hO؅!TD 6@a3QJ,$+>]{eJ`7bpy sHi OA i Į "_vFqr 0AypW6> Q%!A=sI``g̝Q ׫Џ7X5L C Ɖ_ C Dg9Wf—÷L`P 8Xx ؀xi mbQ3d`~p  i)}L0h g t "(/8c|U ׁH\Gg[\@@J8d@d0RHaP&|D8%'acx4F\9] s"DjPn@X]`oBtNySBp(S&4[wH&I@"Q׉.hم! E`V{x>F[!bBf_y%WԈFS}! gw%Fys4C`( F {$EPx"*P@ V*iaJwe=!iqp=zZ@%4 YD)ѐ `>b*$M[PkfRE&bs..>A p+!r0rѧ vtEuڃu*X & pHzET3E07X/}:"3@;+=u[RqH$Uƫ w`Pbl<QR굃JdE ' b gr#9V=!puVb4GnzPc$azh$VvY X)Q;%-pI) r&EQL4*F%f]p!!0kڠ@ uu=RDqܰ6p4^v%00? !F? y4Z7&|D2X|"bejş,3\ :!d8` E=+/ lY`0AZm$"֠FSdbʹ="s2Av<}WR60h}h,4+%4$ap>K4.4Q #P44P{iw1 } EUb z=B (5$#@%K)ZQ6#b(H᳕SYC[$cȷ&B!)GC-;PF,kDd\詄%7|`qF8p%LJ ybrX^T07rĥ-)D{:2;G4@gНGQ#9 0B =:6Ҧ$!]wUv'9}X48]1&4 -,hU5!@2ӰAI@?}T/Nu=@]Vl6OMIpI ӗt}2A!? 2gw\ `؋ '-~ }Jq wˇ9 MP؇ z0ڮڰ۲=۴]۶}۸ۺ=۪۾ S}ȝʽ=]}ýS=]}M 1@!3>^Mث6mٙp}a@ ">}kE2>4&΀2A5m]:y)2Gn0,(iqPc+c4XR5!P eRm&@E"D 1f}@ px5^%daQ4DG6s O|19vns8QʦzĚGW[[d.<_U6 =ޥQDt_.-s\1Q)Nv^h1>:[hqQn^7>|"E|KEYP" 0%šr¸zO"0=(*KP E M5NkcL8K$ Pm4ކBѾ+^A)R i^"?&P2s"d/(ɂK2)#P} *Eg;phhѪ 9:mh䴛[1x 1P.9/4PR #ݥVEBPo ` m;F鏈 .Ɛ{PY**3i 8ák3~ޠb {#ؐ8bEY;D:( h$&Q@b7 (8ar ~1AeZD%f 7{L dB|h ' ‚BAP`PXLƞXسb­)^!Yq P;H@M˞S B+6ӧQ&[± ۶U4ޒSI߉8c2cx?&J-ѯÈ„>3rN]%#< H8A`Ѳsv >0c.!?; +R>h#fdN0 CL>Ï sE\H*Jj~ L`NEGRRKkVsKnm( ~b h+g1n!7b( $##/!ܠ()SB2 7C p j =eQ @D?V! 8`[SؽdqE%1kp:#)kNO.ճ,\@R0 g2sXc6#%`_H_9PQB@'OP8((m:@"xIF &ia'A@eM(:^"( ]B+eqoQE @i#FdqY k\vM Ăa-M;tm;#%$x)afDC;.akP)O2c`%&b1=*7+ڀ H pgnQ),>hX{S1\FRz#AQºj  H%$VpH&oE"S ,"*D(Jy HƋLHC$ph:zȣ> IBL"H񑐌$'IJZ̤&!p X(GIR $VNV򕰌,gIZҎ!FR64(7ILH! 5Ō%Iw B2 PC L?A@9o("^q$&` JfZ, $@:9C$*Oi⢚] $rPS *z!naHh3f Tj@Pfr#mUYmE!*4 *D؀M*=-jPAӦ:*A@r%  qzO Ge*ci5} #D p;v 0qϙSnlE'r] ! :7- |$x @sbAȪ$f¿8X d^ =pM 0:],@0 |,ZrUr0n홰$,>G a!@g<l&Em, sr;9m\q e,ykeD$譊IE/.i8){LgDmU3AD2M P  }UV ntjURӜ*@^3K T[;%hqJFn3$i,ܦp 4 H*]bHh*Kn}@Y HP^jWׂQ ju G0@wnPd%(`鏵+g92JƂ'̑ .ށ+MLPk[7UXd8 5DhH R/Ԁ 5: QS"ЂN){.綀@@z˓!@ܱ`l^|}dm9!N / } ~lyN$yjPRc.UG5;ODlwugKǽOO;ЏO[Ͼ{OOOϿ8Xx ؀8@[W6`N X~؁&x~#H6n'؂g)06}97ا6Pz@X'{JBFчRXVGZ؅ɇ^DžbXfGj؆6ƆnrXvDz؇~ćX@{8!F6,0@P@,Ȥrl:Ш4` :zơxL.zn|6p ~vwv b b1*-.(E '&  Ҧ)$0Ӟ“15%143!" 1ⅲUdLPϝ!0fDć<@K 28 aB].,;| [@I 0LLX8H¶U5N2S BLC bbB#FRjeڴ aί /ej/~g.XcWZ1A"%a,JeNc+y Ǘ d,~H =`2Y x;Bܦ@ʓlS ORmbjF1 O}P =M7A T2@d\M]SAX$GK.7MvV0s߶;Sع!@ʰR<&-'5HOH%%'$uy&p C9?G8 ]4z\A2IAb2\ьj$.Y*%s#(O ]6}% ˧-(G; veTqdyrIS>I@@)nP ,`vOѳjoL(`xůu. 4x}3ja.45O9F'(h*aa}6ÖCsE.l`hsQa(0՟JQrel?yŀ^ۘ @'84KjΐW˒=dRܛPmS7H"8%XJ~Z4"{mX?;cK]b$P =[{Ё';" #+2x5>;z9ÐGOқOW֧@)!!F6,G9<@pH,Ȥrl:ШtJ[gz?ְxL.贚hp5`/t;^(KuqI+_\Tz0S$Cv$'}v"-5 %u# u41*I\12Z룴h$. /|XaGF а@!(D H!EBX`J̙87Z<ɮ͛8S,Ph&z #xIU=XtciD?ܛFM-)ťx!0o6[ݻڔU:2}fP{ܙ F Y[0`G;bTJ %.@4J~D \N `z5krk+wC@_fq84hJj(@J00J- G4XP@DM@(0~ rf(u\LB !"*T xB/X"G7!^Eą&( tC x1u!,i()H9{wXB `&XfvPBTl`|zvy0fBnݕu75rυ߼5[L# /DZ[\YΘW竃(Pk5Q.Hs}LLJ6XWycAh[9ZlMA X\pjJ{P]+G`-FaTyq:hy3fI |fMBXҒrۍ[}3@Y $v6^ʁˢ F`}#n8kݡ $](Iem/te#;&Ln tjdCU/ %T-]3 ޞ58mn YOZ b΁ +`+ة*N٨c5 %>gDGDBt !'Zi p #Sn,B P`Jp~C~.i6,;ΣiPrNI+ 'H*Ԫd @1e ,BHPPXf0 gCwnĕ"HLCL8q7oH0bP"l311h<#Y'EubᘉO %0X f F &nQPa4| 3A_iTX&݃ 2Dd) G4B#1QSvRu(,Sj?&4d r)$[@8b!H$ kR3oʸ` e |L'&Ѐ{,C zѳct?BT%z[z0oҀԙ?@Gd%_yШia01hlZၘ.J,Da@?'ЙF8Ei +^+2R2D "rv~+"JMDMtdTM"n2G9t(. 2A s[A ڀ. J}%V|UȄH% p̿^$mgЙ }(l#`A` j. ڮ3*# aP*Ȫ@?U`3h]mx8#c/r iCb }fۘ3Sz!N6ca2P^1 HQqYЭa:p*RN 0vAPNv ܕF-QwY"p<^C9 Qk0"y-;`aɕ܊Cr_$l BQ5'hdHcg'ML yԀ~*{#WqeA9^E"WW&xfXג@DT$`g WNV6vPlXh&U>-0g+>E`XuQqPKV""[wg"w b 6"P(OvE!$su^mǁrD'`{GVW#+(`.r.B_M(#ʠdЉAeEyfm (@MZN{50i̷VQU '   `*x ,@m'r4$QqgT @]  . B</`X6xqIJ $BC`Bgdz$10|@ I'ёn@C1/p5!Б4n!𐻤A.1u<oWtu 9P$ tԕ3J'AQjՖnɒJxSVVoi(_y?apv ?{w"LpGGu,GCMi Ø$GFwӗ|$9Yyٚ9Yat`@ٙ|9@h qOiU\5?3@x&BL)IB0<ɹdtb@ibz0q(H#͹ ɘ:@!BlqNja4Ö . +ԛBZxwSڄ6 >KFZ?Z |iyt"g!z6"0 UcTD wDc8:ҡ6WŒ菰0`f7P!qҴg ?zH$t ,p$cSyMR&qGp!`/ ;]) q#S_ a:I"yutv$rzP?uꙂ5ʩe"*WG珈htڂrj } ׅ?RCZf עljea!GF&C4}CM។U(8 cCvsMqLP2䴩!rC7wÁS/P8P &b&KY &7 C,2~#"ՐQI";$[P;5QQ*ۡ* Qtib\GDh;6ŧ|(䥞=Ou4^C#uٴvcT[V{XKYDșM`b?A!F,O,r+Ȥrl:ЧgFجHpx+H 9zNoO >Qbo80Zd7yR8/J$$Sq0V~eohwQkz  Q,,X)6)PW6Y6j6#K,E&!o * .$,S!na8d@)1فӸ twb勆pC"' %ɽ!@-V̪ >M2VRyZs6fe-k'ʃ3\V\jح7[C){Dw(lnS6Lgs,! 6l@bU1{86#҈sNOUD ?o7\ˡ.8ntT}*o ߛ #hA!,@-ڋ+H扦ʶ L !, @p(Ǥrl*u;b\kX^  b6+1Zg1 13.~H\rEGkL0*'K -4  !DIU  JBA!,z@pH,Ȥ2J&g1"4ZҪ*Փjh|Ճ XO*}`BK+fg{SU~SMIG'XI-LPY2-Hx//|`_F  A!,& w@p(Hal:Im6U},2g-p k$b7\Nol}%i 0&ef,- IIzuF FA!,.0I8ͻ-C(G8$JE!,6W@pH,p( #%qr9J-t8A1m`K‹ o*HM|jGPF  oBA!,>x@pH4Ȥr,TNrb e.( I5e"KՑ@y'( v0  $C$~  BA!,F @ ƤrITШq2* kxxHQ4@,lxT+,4Q{CyG_NF%-# _,Rykio_"q0$OE_* .^ !/ʒH[ A!,V e@@@HȤxxs)TVbQ+񖼋ec}kmUO7#ry_bVTBouJCo  A! ,^ q@pH,Ȥr)|0P(-a d)&9"R ',uh%qK+E'N(&D/ DwNGJGw A!,n@pH,Ȥr9T )j4>bdZp(ӓAX6B]`JR*&C2'tJR*- .RsS-4 * !I+H]I|Yr ~Lh C -wF ǤaGL DA!,~ n@@@HȤRy(IiF ((D]-Qe hG\,R9W#K }FI- -4Z  q~OD A!, p@p(ȤRy(0)5> D]8Lf0\Ԫ|HtP*es%14$   .e,C FyOG  CA!,@p ȤryGE<:6c-VWe|&U(]&ゾ6zb^J)B$XsC/ L ]aG$gCW]CgIfP_v#&0 _}C0 - '#" HT/ T FHU  nA!, j@@@HȤRy(ɉaG'3)}0Xeã1H:X5VK4/ )X`(  ',X B  uhFOH BA! , o@00$ȤYxLbh4 t`*/@D(@Z"JOgvu~FI txzH ~wg BD  CA!, Y@p Ȥ(Cpt4A}VXZ, XaƷ@xh'O*lZkP}C$pspulI  pA!,I{EC(7 Ɉffp D!,@p Ȥrl:_ IGa{HI>tKm0Fͼ>De ( tBEKf}1 ,Sw-Wf B/ )^% ke ', ^0b(- .l- 0 y U*.N*-% S k&Bu15C婊^LMB |oH!,[@pH,p0FG$PvulK&xE|k7SǷMpqPHyPFA! 6,/@pPȤ`d6hsJFXiz Ԃ`}zn|N~^ r)rb[`l$ r/S"1rr%-fw0'"/i `$z*.#ap*'#%!S[(&JB3ɖmbN HHP"ya"ao jYF);D%)+D^` &BbF6XoL$0M:@ 4S ;{*ϤJ-A 'Z9p5^TUD&5 N"ِCߖR"pa$hs!!pq(@X|D [5b`Pc0ÉO!E,`!ț7PpT]eA PñrS(<9|<6`sxa|5[GlZ-RӍmXv\dl*Ίʕ |P~T[}-,HDN#Nx7zҭjpLq6/=N Gϯ|!EfԪ Ń. sJ{ʮzlM"2 @;715(V'=A|3MhkXrU(ȯB9ݴ6Y`= 1X,(0I$hH.1[`dΪ絝SE }5't.fs\F@ 158I"4p5S gB @@+@ӏһoyRqx9xώCNA"aj;;м_]$% P @7:- m;#  8ƻS`  &XA$H1 Rx{̕mPq@dpܱp AB6 8D% Cu9.[-X5-f[^I]3S^o8мTrnc|)RFHBP Vp8fTF:򑐌$'IJZ̤&7I7Z2(3ir`P,%fdLyn J#i)LJ`0c3YfJDd gH@R:n'n@K_o 6I ̀4Mh M(0V4(3!>,E@pH,Hql:ШtJZجvzxL.zn|Nۧɼ~w^}V_IŃˆՏٸzuGpF)p‡6-ŋ)jǏ>6Iɓ(S\ɲ˗0cʜI͛8s v x@@C*]kL:#C,DWeYHPa J]K d`]Za r!Þ |a@l {hSq"pCrMѠ4`4XA7/)6vЀ~2`PHή4D 2bp&PG°101:pۡC5f -6 @p|r(  $Dj5 .BǺUxG  &G,-}kH(PʭY 7rP=+a Gާo}XM:מP“] uE$%5 6(, s\>@N pQӓ@ 0>1n3'^ONp!.Nfa}]">%bW8H5UAF/ءH GޘnCNq}?lޒ` K~ WrҥAf`Y\@ h] LTJkP1aombA2S1CnV58␪8 -BlaFHH耱洳n16M vr!,k %<A%"TS(689fXT$^`'7LA$qEμheɺ& ddy_¤Qac4LϦHc.($0FAIP 5 N?8_DP1׉x\ \0umVh'T3Q=4J-%@]uJ  尛0D:6 M\y9'2;³y "Չ6SZkK4pͭnwKȶ pKMr4,.wX hK]H7ӽe;UfA@YH\)AU`@l  @[Y;! zE/xh}hk^$ PӔ(` ,p x@l`$8X'ŁH0351 L~q:aI^Z4A+1r{ʅK`8 PQǓs0FPͅ-]R/5zp!M h. |>~cD$X(( uW]є38BiOU3/A!HufȔjB0&BPB|`ۘ3ٕR`#I Y, c!y/ʉoRi(1u%8s{Sf1 iNXH_+՘$؊*il`"}#Ntisg? .."fFJi53'Q0frI~ڛ d6i Ob zR@`C/ƢY:lFo} =*bmH؈a r4eAbG>E9+@@H0@Vbw* `?QL ԵYLK0v`?[Y4s4h4NG<3w͕9@r:K]Lڸ%$ yaJ]gcٹ[kKZx:;[{ۻ;*_r%v{{pۼLTQK)G !JƲP] rAeֵ"c:9xN fPpjQ16\\ n z%m>\U{ .}V p+<`[+(:m'\Gi+ZsE PT3gk@b gc!!9t0+g&<q@`&>|j$|~IC]|j@kj' C3B\aSi(cs{w#_0ځ0+ˬ2Ŀ"4 5kټt0|mӀ Tw1+-sCP/Wg #VqoXM.1YӋhY-f\,N[λg՞ھ>^~>^~?_ ?_ X51_5m*`&14?B.0.4|:C>@/Hp,B.YkG6:!,`X6``sf;Qderx0ٷO"KW/#%pI:@5#4646kO'O`jQPwy?  2m?}oY d ydkomH`(_02A2)Z}]YOv`h)oΏ|@B+0'r 1h|>BiQFWӍhWIeI8؍1)2>Rj 2y !#% dbjF^6Z4,.tlnl4llSb&'+?NF6iD8"BFD>XutX]`flhn0|l04r=)FKZA&TaCHbh m7.X0G-fW bar/~w t8fM7q Q7!DX<Fti%R*؈B꽒-L:;lٜ<+ d &zgJvdJsɬ7WW\&VqcDŽ >HKㅁ |pE PRu5t ՔO<3fS@Tݼ<>xq !JPAqNu\XU@`{*[^NP VU|a׿@, P@LPA \P )A* A QAGLQY  QiZQy A,H!LRI%' RG'<\+"JHcr5TG>;d\x> B@204b8Ӂ @9SEH`dNkZE<9J"1[ "+Ip:NL7TiqQE}abVT0!! 6啑8` %}̭ځ ,}$ሟ(# (ƃHU-w/(^ 3'Xgt4g<|b `Pzvi*\Jh\Q6msE=>!h]`'Th>W2@a4qfC&O 3 T8\^w0L`&o`aN4ޯG 8V͎~7G][>PRsa@6з~]]b,]q8\p5]nه@:POX`,w)I ɞ:q>qr%D`\`C(=MKR@T/~ Y@ypcfZN 2P  Xq bȅFA [WChu / ( !F`pVGjQ/8DQX tN#b;YpE"uф# ATh>kdS(6PfiWwP*u}Q&<(Emڃe2p{tUA=5Я buw\h%ohP}X] j<) %.Px\d^Zy䛠N $J{87ThێpN^d5K@7pn\.YCAv"T+!DqQx5 RXϠ@.Bdø0`"/7`\\MQ/u2X~(f|Qc]/>`eYg` #Ɏ`_CP4Rx%6Qb-vacϘ5qc=q=Ve_!y!K`;΍UZoC  p',X {[D"oiafJsK40]!`dn( 1amV.جAANYʿҢ\'4k¨)c^-HpnhF`ʴU௷Jph^9H!ɂ=ޔ-B&n#e'[&Xnm(i(޲ \gR3#&ì:d4ٶI 0I;d4X1Pٗ$ )\f>58*媛U#*ӿ<^ E>$M7P fiO1a)'z,HWsF3 @LAz9Oe}8Խ\u~(!o&ܨսj'dL&;*/2@;>$w۟ܤ/1y׽:߃C! (Tu"LƮ 6YdS-t-yf83c-@͑'m@-H(z&\3@`-.YR gVD )3A8ͼ//30} c`"gF* # @2eFqɯ ]'ȑ4M4Q350)HȠ{'"2R*pSt6A/13xS5Ts99+YS":b  rl2ոA2U Yڦ5y ©.c̅t\'\\A$3*k+ ,W^$Ɍ9>4@t;Ph:F:p&ԉHu - A`uJJ0[2 D*_a6feV }5Tb04HѶ`4$H,aVR 4T7OVb5OhM{_lcO7gl6m3 \.ijl$0>EIJpܜo-\LUgDFig[6dxpxrx&z1ĺ3ɠt'$ :Fb>,Tb9{P`R4w@i b:#Q]Fwi eȸP!X M!a J\E\F@ JV%] JWE#Kqʄ|pH=S&gwtc9@Oz9ن׷be`]T#DR#L5B]; !)sa3yG&4Iv]-dbXX<}l9rVc|׷"ok ?]@~CߘH Op`N>Fk4aK^^brjשhʨc*REȸ]L%>NxGFA5/8$WA(Z^ܨISyZR^cכȆ+%gi-ֽdrK@`Ɂ BEFKo:`r>w:Yzre:N@MH% wrl~ #[YԾ*#j)qM`P%PݽOtJ!Hj@pL."Y&#䦴 b PQiH1}e:񅜹XtiYDɸ50E:MDN hu M><^9)QHxfւƸ֩ uf~}RW[_cgTh{gpt[A|x9z*6UDު=R%ΌID|Sm…U> 2X*8 ‡ aTh2 f ȦFyO @vDQK`\*Ƒ0PĨaB8Ri0a*4  2JsዋopYJPZ#WD^ZUPA H DB]y3-=[T NADm=nɭ!*CE?m;0`ܕł~ *䟇8ȹQw* g1@0"N3b$K㯓n/D}j/|Հ$0 En `B%w5X'5R ~`هe@s^ .ΖY bLG"7@ L ISDЍH7Ld|<5a4t`3z1ÐՑg7|I.XRVbSe0&FͤfRI)Y pj 10ƹPijxB 2iN:DeX%!F DG!%JR[Hv\r-E`碛&7Ʈr&YipGԌ+?7 .>.7yǀS\_Dsܱ*\'+ܲ/3,Ҝ;ܳ?C]GODHv~j$&Wc5N@W֜BQxg֐ 7{WJ @PqfX<4v@`%00P b ݹ߀7,Y |K$Xxp0ΛP.e8Ýl5$ |YuVz1"J-L_t4JF RO:pX7$J.Z`@TzP2dgwD@40`d% YXqbA-8 e @$TRrbp"gV7tMmJ`pq@v- Մ'ܦ#㎒P@ 9" ,ȃ+  6e0lR!Y#G4ry0Ժ>b/+\dpbhH#) SȪJ%.%-kipzpK$##/!6;iD ЃT\Q{ 6 ֗;*@]^ae-(b3,y_Ҭ}tN ĔD^Tp8lJG p-ouM/;Е_vE05p6Z Y f0 aHJD3BP8 זIdC (--Nt^|]c10G .IhDB2z"q;q+݌o(Q!x/{`(lЁBwTz^1rˀw J0q Ъzn"|qȈJRO`%? tny&mx^4a c@,O)n N`K7:Ԣ5KmS:ժ^5[W:ֲ5km}*g5{_sH組 iuB)P$/;~ecQx+1O㥑p bg6]1| k4޷>I;I|8'Wm "u}K$| /i Gr@p$ K]-@6`P& yq^ p8Әэ. pp-ƫ?epɱkP-yLq(߉U9/r-Pf]ƐQ9rDZOcgʉ/ _yg=X?(k\ |{|e 1Dt^ zqx@TqԅFRvQ༄C5I_MՍ$o&``W0A]QOXA}E>2 Q_x)\-BSECU5 C*!y-LlICv ǴAaFXH C#5_ ,pRȃDDAꁓmJ"Bx |šI Z**b++b,,b-"[%"=lpA_8څs( /B p arՂQKTGi I_sT[£<˞ < ^H<< @r #1<ǑIN6 }EB(a18$C"[HϮyK5PĖdK ڤ$[MjK0MKO$@GeQQ"eR*R2eS:SBeT(TZQZ^VƟ We<NXVe[_[ťee^j[.ͥ^ep`Z8Wj%a*`ebB` fdZfXer&? Yg&eh=fjfkkfllfmJ_lᵴ6L@Yo-gqq"gr*r2gKOJ8%&LQ ,@szwgxx,aD&ƨhBp@G \T /g~~ge$ X^D$$!앶hW}eEndrhz臾@D1B@'vrNJ&َPމ~߸givNn=Q(Rx_TdxtD{<]G!i0A(1jXp<>BhI`Fqy Kz\=BIϹ4z 0@ S) j&@A=N(j'j&C/+ Fd6r7" It!+4ީ]"e LvLsX $t oɝ^-3뾶tۙ1j:ö1@|ƛ 7ʆW|5%콣xjDPh!h%U-%*Āp}vAtDq,-.+O[lnpV$#P5 }黪.d.@*[ WqGwz`H/&v ByiGW\z$r1qxeD-?P (i1!& PMm@$ D[AS ҕ8  0Bc$I)2J Af.H~A&\O5AÞ'w+54UGGmwSѩTPnnC8TRMJ' s^ x5Lܗx9p `:X_>{uSHxzaO88W,'6{ʫ>{׻g@bѾ=ӤL 8&&s⃎&(#rym8 ,XIO` Z[kpH[ [, YрKRq0th8zaR9TV9M=:q(Jqy(]P.3JJRIU?]s!ِU2)#в% TUhDa Pa$z8"ܑlM ÐR.S"Jʐ $H`<TPEE4L!KpJw&tcQ@'І]eԇhR䂪#.*"U Z ^?p90P_">1["p1  +>Ѡ4:INR޽}˅K쫁~| hH샩esvފA dw>y^߇G 4G70²4EB!xo<-]9>o!Ze$eX-†FhH~FU t~q>p χ?|쥀54e( r,FQ.&(]VgP(}Cz_Lh+q\,ACnu.ͤ&"9(KD `F~FL0Ȁ%3#f=̇B @w$Kz2S,#@apA-͓޸K*Q9 J ҘDHa  HAވF%q ی@-$@"b@,r&GNiv#a’)EC\ZЁdq2Pa: nLF| #,|+($VIxûƱb0-K]pP2"#'CT_O%_P~)p$ ˏ* (BUHj |3spU-~o4BXM8HZ;\@O7xA9ْ"*f!u|I *Mn8f2 ]P1D-(' "L?|nۍl]j Qy#B@1Y.]v׻QӌIh7M@ GH@ӌ3}c7A^W]8}\} \ao-b #qd3Whe-q 9lQBԋ8uc?rb?].; ΟN6RP<"W]ؖ3i1u)ɜ]8l}Z9glNq:46 Df6JLtzSلbcu%Dlִ1i4]\-HvGL:}$`IMW"ݴ_b!C@;WzoQro}Q|8a>! If0U/3eى5Kp(a1I_g(L2L0P"<7āt}SYF 1PO~DN;\SaG u( X-04f0A px4'ЙŨ?`GH6 -pxLOJ敠qEo d׍ s ſ)du%{xLBn|6d9U룁V{)(@FQ" o# )k KY] P00[ iRzC*Ѝ5 |4F9øw!P C4KAX؊A(˰; 2ɇ;}4RQv3 Ha[㐦M*7pTsO)JE@aN0ΊHk8@ S Q Ua \pTWj4ERc}#_#8p˪Ȍ k`.p(VLU*@@902J{v % t 8 R,Gx8qMWA 2u٠0P> 2٫TBXaaT[e0ґ@`$ ^h=)3>-RyCWy~¹ 퇥%9d-9Sz%nMB$>5P[G` ]C5V5 >,DSo7i6ɛAxk S =iRle!.&FanSS2({L= V[#[)yC\eZp8KXI8;b[`[}RH2b DX㚅^}j8U=,W~ =Zml0z+*R^@Gw{z4xt"R"x}JXiۺ1$< YIbÀbfSZ-YE%P_ӀW;vY&@Y1&؋Xgs']D El2":)xCgMCjܠ-ܒ႖=jꁭ+Z;[5ˀk\ܽ2K3@ 7u-)Jɦ0M(5) Y6m#E.J K$Ў莶D~MĦPO<5xWA#%f_܍Wpd%q^ `E-!ak뚐U$(KnŨ0hJoK=fpi 2UY8 ^2|=NVjʅ0)A^1%mO[] z!龈` kq\(qg"=S80-J,@A 6՜`.FALc\!QtCgEwt[IJ'dItJLMtEOtJN'O7RGuC@.WXYZ[\]^_V, vYoIX_$ihivj<'GqlWO=CjOjsGtWl?A7cOp j=hu~w^owpL}yaWe(;'7i_>Wp@x͙g;{B%5$sa#Ya]t v\xoѱ!2RꊥW聬 zǓ{~,] +*v{V+fvUyG(,jw9,uuXcu7Pwgw)ʤP|H/ " 3jgL W""g}Oهg6ң "8",;/mC nyig= suz~v wz&ˁp"ɧHGh0"/܋z> pP%$Gsx '=7EJfNr5EI);iz4¢ز1I`IɈ!SjJ9Zڐyɘ r`J\l|̑(=M]m}TCs&M.@T@n.-T`͚4*L(8d <`C@wGXHFtTLe`@ 2GL-3OhzbtaC fNA HS;H8%SVVa9.ll}8a]]F:6g;~ Y4y*[9f4 y^G 3H6]JE6 t hvGɅDМ4('9.#l;jEV$-"qB6;lD! P⨓i~jp ,PAT WX1V E<)$+Ȉ J&5 ĥ#KdBIdLYJ.ɤ5 eHNt8QfuץG訣TGf 8>eIHAf !m dPB #'ž%3Z|T )YbPNqK0PCDB|@PRB8Ֆ$XV`*/O%KL ²l}`d1₁d@JU $ 4- iN˕gd MKofUȽMZ '&cBz [Y A31) dugl ) +W)䴔F1$-5A ?opq@N(pm>wt~h51MA- 2E,AAJECY0PCT,5#uJ$ \:4W 0 4=`1 }ɨ`ڈn0]%g*hIL'}k4Ӱ+PlhPtPԶ0!,QM:EJ#c4xR"(:fO B ,%E-hQ $JPo>t ;40|\/G6psISsD /09Qh H@&n K|dzrl#{"}s7 B9\L>`R [VvSʹI jt|pw?R3}i!@??1İzmهܾ/= a $&8Ç `jɦjD  .X>B0$C0~ '/o?uBp^4]@;8{{q $A fޅxmC$xcbCIǡj <p<>Gӕ 0B "WMX5: G~2x/1 `l4ׁ_9t '3X _JH~?uE&ps {uN8_:Gw=o(7 _i'Kq)G衁d`:HQgpt_TTpwDLt]sZ"^0Utt ^z^C@7xWf~U"r^OE3x{['`]7{(p+</a(F91O+0*Fuϣws*ֈU^T~^dhbSK8ĎL+O x_zГ:mrJ%@X8y.tr-HEO<ґCgT0OXi`h9ܗB7xGoKC p=nRuԘ0z9jxߖB^`) =]g@BVу@نw4uYL#4a~;؛7xk{2.)9};/l霦 ĘxS@6io'' 471Ѓn>3CI=KDT8D@L붞C@I B@A1w+}`&J~靈9%J/&#i`mTȤ|h%VJcxx2@\4oTY32jsTá|skfogɢGu1uU3y6 P@+Y*Z_Ij9$'J!@w{!Tb=b!pd*+RJys1rj u@)B;x9CЬy*ֺZ7ף$zle!3I67Q7'`rCa3qsʫJ ;omNeS|i3.% 3RDbɱ_  S)I[2uO՛Ez5Qde3]=3(Jj7%QPk!0x y 2x%9ƒ,;K&JQ1']=R"9l[Ij+&! n7 }/@יKj|d; EՇ8FeKW;D ^1]@慢KH{˻d+K!6jkū˼ϻ$+p kb˽q@dTx׋mbb{p˿fpi@) ;[bK=ܷm0lիT l4 CP/|4.\<d;V)eRnp@.|%1VM!R`nPb:1`rT,7 @F@.=2ަ;3< -”K5ߘ5YbJ>]E݆T1xCY$|1#7xW׏!E[-6u{JT,?Ֆ;(n;pMoymkN {vx/bZz5 _oG q{o/˱o; %؟ODžPjXW[Ei!q"YLQ[8)Ԛ[qe$[8q#׹0&IbW9LrbgK PYvNGRݤMf9,>>@X&PZ"Z6QL13579;=?ACEGIKMOQSHp^ZGKjdDWTjH-6 FDA&'+/וnn,p ^8 *\0p Y=H4p䠿#"] n:Zt@>1X^KBCXCNH!qAȒ!>NHΗ:$d F$%oPx ǎkW_gn,``i^0ć|b܁Ve=^(# a)"[ah #L`dH@b YϐP @D#zT^#G ""j0DH;zuױ1^͠ /LpIk.gc0-=A8@:(>B  2Zƶh8)lI.³P!QiF!p\`AcG#¤CBl?Úd. xl`?Z.CaA %"-$OE2ҤZ @8l,CMx.K'h@Rr#,lL$ *iG($P6@$ T2qIPRT#N YnE6DUgVZ'ٱ%aR?SkLNQ[*r-)H=,&Њ_3ʪ].ahZ&i1XӁxn s H(qc15If 䠲F^ =8@&fV\ b*l(.1q`\36.mXFc|@:FG h@(#n$<;} 23‡AX DZbu ἳ "Y*Bߧ`wJX-c'7r{&$^&P)"N)'g(䏠`G$}GLBUi"Wą* ( ŀA NFע0& i)G)B+k4/c08HCΐ5 qC=D!E4D%. )(փUbF1q]g ^mt#*,@PN\)@A3@GR-NXh!I=aBE=Vx5` RE5gH!0OB%dh ᄂ"6vE&.Y*IZH`a i L3@HK)uN%@ "E pq L!dy" @5 TR6pl #w ALH{b᧰J4V V!V@9Ngj807D Qˏ']!+c"#9DA3\UN+5,3#!r`a$HH*@Ua8$pV+ٌxFzd4:@uaj5 x6!zU'-MwӡuOUձuo]ש4mTauhP@B j8Ds} ZTۥFrI4G6&cݦ P7p -X0?"v}g)'Y5y,RཧD SH Z@2|"/ay^BY'Gv?Yw@@c(/?`VphƗ”*` p (.P xav2a20P.Ip> SHIFT] &= ~(1 << ((x)&MASK)))) #define BIT_ON(a, x) ((void)((a)[(x) >> SHIFT] |= (1 << ((x)&MASK)))) #define BIT_FLIP(a, x) ((void)((a)[(x) >> SHIFT] ^= (1 << ((x)&MASK)))) #define BIT_ISSET(a, x) ((a)[(x) >> SHIFT] & (1 << ((x)&MASK))) /* ******** */ /* Typedefs */ /* ******** */ typedef struct charsetinfo_s charsetinfo_t; typedef struct term_s term_t; typedef struct toggle_s toggle_t; typedef struct win_s win_t; typedef struct word_s word_t; typedef struct attrib_s attrib_t; typedef struct limit_s limit_t; typedef struct ticker_s ticker_t; typedef struct misc_s misc_t; typedef struct sed_s sed_t; typedef struct timeout_s timeout_t; typedef struct output_s output_t; typedef struct daccess_s daccess_t; typedef struct search_data_s search_data_t; /* ***** */ /* Enums */ /* ***** */ /* Various filter pseudo constants */ /* """"""""""""""""""""""""""""""" */ typedef enum filter_types { UNKNOWN_FILTER, INCLUDE_FILTER, EXCLUDE_FILTER } filters_t; /* Used by the -N -F and -D options */ /* """""""""""""""""""""""""""""""" */ typedef enum daccess_modes { DA_TYPE_NONE = 0, /* must be 0 (boolean value) */ DA_TYPE_AUTO = 1, DA_TYPE_POS = 2 } da_mode_t; /* Various timeout mode used by the -x/-X option */ /* """"""""""""""""""""""""""""""""""""""""""""" */ typedef enum timeout_modes { CURRENT, /* on timeout, outputs the selected word */ QUIT, /* on timeout, quit without selecting anything */ WORD /* on timeout , outputs the specified word */ } to_mode_t; /* Constants used to set the color attributes */ /* """""""""""""""""""""""""""""""""""""""""" */ typedef enum attribute_settings { UNSET = 0, /* must be 0 for future testings */ SET, FORCED /* an attribute setting has been given in the command line */ } attr_set_t; /* Constant to distinguish between the various search modes */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */ typedef enum search_modes { NONE, PREFIX, FUZZY, SUBSTRING } search_mode_t; /* Constants used in search mode to orient the bit-mask building */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ typedef enum bitmap_affinities { NO_AFFINITY, END_AFFINITY, START_AFFINITY } bitmap_affinity_t; /* Used when managing the -R option */ /* """""""""""""""""""""""""""""""" */ enum { ROW_REGEX_EXCLUDE = 0, /* must be 0 (boolean value) */ ROW_REGEX_INCLUDE = 1 }; /* Used when managing the -C option */ /* """""""""""""""""""""""""""""""" */ enum { EXCLUDE_MARK = 0, /* must be 0 because used in various tests * * these words cannot be re-included */ INCLUDE_MARK = 1, /* to forcibly include a word, these words can * * be excluded later */ SOFT_EXCLUDE_MARK = 2, /* word with this mark are excluded by default * * but can be included later */ SOFT_INCLUDE_MARK = 3 /* word with this mark are included by default * * but can be excluded later */ }; /* ******* */ /* Structs */ /* ******* */ /* Used to store the different allowed charsets data */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ struct charsetinfo_s { char * name; /* canonical name of the allowed charset */ int bits; /* number of bits in this charset */ }; /* Various toggles which can be set with command line options */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct toggle_s { int del_line; /* 1 if the clean option is set (-d) else 0 */ int enter_val_in_search; /* 1 if ENTER validates in search mode else 0 */ int no_scrollbar; /* 1 to disable the scrollbar display else 0 */ int blank_nonprintable; /* 1 to try to display non-blanks in * * symbolic form else 0 */ int keep_spaces; /* 1 to keep the trailing spaces in columns * * and tabulate mode. */ int taggable; /* 1 if tagging is enabled */ int pinable; /* 1 if pinning is selected */ int autotag; /* 1 if tagging is selected and pinning is * * not and we do no want an automatic tagging * * when the users presses */ int visual_bell; /* 1 to flash the window, 0 to make a sound */ }; /* Structure to store the default or imposed smenu limits */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct limit_s { long word_length; /* maximum number of bytes in a word */ long words; /* maximum number of words */ long cols; /* maximum number of columns */ }; /* Structure to store the default or imposed timers */ /* """""""""""""""""""""""""""""""""""""""""""""""" */ struct ticker_s { int search; int help; int winch; int direct_access; }; /* Structure to store miscellaneous informations */ /* """"""""""""""""""""""""""""""""""""""""""""" */ struct misc_s { search_mode_t default_search_method; char invalid_char_substitute; int ignore_quotes; }; /* Terminal setting variables */ /* """""""""""""""""""""""""" */ struct termios new_in_attrs; struct termios old_in_attrs; /* Interval timers used */ /* """""""""""""""""""" */ struct itimerval periodic_itv; /* refresh rate for the timeout counter. */ int help_timer = -1; int winch_timer = -1; int daccess_timer = -1; int search_timer = -1; /* Structure containing the attributes components */ /* """""""""""""""""""""""""""""""""""""""""""""" */ struct attrib_s { attr_set_t is_set; short fg; short bg; signed char bold; signed char dim; signed char reverse; signed char standout; signed char underline; signed char italic; }; /* Structure containing some terminal characteristics */ /* """""""""""""""""""""""""""""""""""""""""""""""""" */ struct term_s { int ncolumns; /* number of columns */ int nlines; /* number of lines */ int curs_column; /* current cursor column */ int curs_line; /* current cursor line */ short colors; /* number of available colors */ short color_method; /* color method (0=classic (0-7), 1=ANSI) */ char has_cursor_up; /* has cuu1 terminfo capability */ char has_cursor_down; /* has cud1 terminfo capability */ char has_cursor_left; /* has cub1 terminfo capability */ char has_cursor_right; /* has cuf1 terminfo capability */ char has_parm_right_cursor; /* has cuf terminfo capability */ char has_cursor_address; /* has cup terminfo capability */ char has_save_cursor; /* has sc terminfo capability */ char has_restore_cursor; /* has rc terminfo capability */ char has_setf; /* has set_foreground terminfo capability */ char has_setb; /* has set_background terminfo capability */ char has_setaf; /* idem for set_a_foreground (ANSI) */ char has_setab; /* idem for set_a_background (ANSI) */ char has_hpa; /* has column_address terminfo capability */ char has_bold; /* has bold mode */ char has_dim; /* has dim mode */ char has_reverse; /* has reverse mode */ char has_underline; /* has underline mode */ char has_standout; /* has standout mode */ char has_italic; /* has italic mode */ }; /* Structure describing a word */ /* """"""""""""""""""""""""""" */ struct word_s { long start, end; /* start/end absolute horiz. word positions * * on the screen */ size_t mb; /* number of UTF-8 glyphs to display */ long tag_order; /* each time a word is tagged, this value * * is increased */ size_t special_level; /* can vary from 0 to 5; 0 meaning normal */ char * str; /* display string associated with this word */ size_t len; /* number of bytes of str (for trimming) */ char * orig; /* NULL or original string if is had been * * shortened for being displayed or altered * * by is expansion. */ char * bitmap; /* used to store the position of the * * currently searched chars in a word. The * * objective is to speed their display */ unsigned char is_matching; unsigned char is_tagged; /* 1 if the word is tagged, 0 if not */ unsigned char is_last; /* 1 if the word is the last of a line */ unsigned char is_selectable; /* word is selectable */ unsigned char is_numbered; /* word has a direct access index */ }; /* Structure describing the window in which the user */ /* will be able to select a word */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ struct win_s { long start, end; /* index of the first and last word */ long first_column; /* number of the first character displayed */ long cur_line; /* relative number of the cursor line (1+) */ long asked_max_lines; /* requested number of lines in the window */ long max_lines; /* effective number of lines in the window */ long max_cols; /* max number of words in a single line */ long real_max_width; /* max line length. In column, tab or line * * mode it can be greater than the * * terminal width */ long message_lines; /* number of lines taken by the messages * * (updated by disp_message */ long max_width; /* max usable line width or the terminal */ long offset; /* window offset user when centered */ char * sel_sep; /* output separator when tags are enabled */ char ** gutter_a; /* array of UTF-8 gutter glyphs */ long gutter_nb; /* number of UTF-8 gutter glyphs */ unsigned char tab_mode; /* -t */ unsigned char col_mode; /* -c */ unsigned char line_mode; /* -l */ unsigned char col_sep; /* -g */ unsigned char wide; /* -w */ unsigned char center; /* -M */ attrib_t cursor_attr; /* current cursor attributes */ attrib_t cursor_on_tag_attr; /* current cursor on tag attributes */ attrib_t bar_attr; /* scrollbar attributes */ attrib_t shift_attr; /* shift indicator attributes */ attrib_t message_attr; /* message (title) attributes */ attrib_t search_field_attr; /* search mode field attributes */ attrib_t search_text_attr; /* search mode text attributes */ attrib_t search_err_field_attr; /* bad search mode field attributes */ attrib_t search_err_text_attr; /* bad search mode text attributes */ attrib_t match_field_attr; /* matching word field attributes */ attrib_t match_text_attr; /* matching word text attributes */ attrib_t match_err_field_attr; /* bad matching word field attributes */ attrib_t match_err_text_attr; /* bad matching word text attributes */ attrib_t include_attr; /* selectable words attributes */ attrib_t exclude_attr; /* non-selectable words attributes */ attrib_t tag_attr; /* non-selectable words attributes */ attrib_t daccess_attr; /* direct access tag attributes */ attrib_t special_attr[5]; /* special (-1,...) words attributes */ }; /* Sed like node structure */ /* """"""""""""""""""""""" */ struct sed_s { char * pattern; /* pattern to be matched */ char * substitution; /* substitution string */ unsigned char visual; /* visual flag: alterations are only * * visual */ unsigned char global; /* global flag: alterations can * * occur more than once */ unsigned char stop; /* stop flag: only one alteration * * per word is allowed */ regex_t re; /* compiled regular expression */ }; /* Structure used to keep track of the different timeout values */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct timeout_s { to_mode_t mode; /* timeout mode: current/quit/word */ unsigned initial_value; /* 0: no timeout else value in sec */ unsigned remain; /* remaining seconds */ unsigned reached; /* 1: timeout has expired, else 0 */ }; /* Structure used during the construction of the pinned words list */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct output_s { long order; /* this field is incremented each time a word is pinned */ char * output_str; /* The pinned word itself */ }; /* Structure describing the formatting of the automatic direct access entries */ /* """""""""""""""""""""""""""""""'"""""""""""""""""""""""""""""""""""""""""" */ struct daccess_s { da_mode_t mode; /* DA_TYPE_NONE (0), DA_TYPE_AUTO, DA_TYPE_POS */ char * left; /* character to put before the direct access selector */ char * right; /* character to put after the direct access selector */ char alignment; /* l: left; r: right */ char padding; /* a: all; i: only included words are padded */ char head; /* What to do with chars before the embedded number */ int length; /* selector size (5 max) */ int flength; /* 0 or length + 3 (full prefix length */ size_t offset; /* offset to the start of the selector */ char missing; /* y: number missing embedded numbers */ int plus; /* 1 if we can look for the number to extract after * * the offset, else 0. (a '+' follows the offset) */ int size; /* size in bytes of the selector to extract */ size_t ignore; /* number of UTF-8 glyphs to ignore after the number */ char follow; /* y: the numbering follows the last number set */ char * num_sep; /* character to separate number and selection */ int def_number; /* 1: the numbering is on by default 0: it is not */ }; /* Structure used in search mod to store the current buffer and various */ /* related values. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct search_data_s { char * buf; /* search buffer */ long len; /* current position in the search buffer */ long utf8_len; /* current position in the search buffer in * * UTF-8 units */ long * utf8_off_a; /* array of mb offsets in buf */ long * utf8_len_a; /* array of mb lengths in buf */ int fuzzy_err; /* fuzzy match error indicator */ long fuzzy_err_pos; /* last good position in search buffer */ int only_ending; /* only searches giving a result with the * * pattern at the end of the word will be * * selected */ int only_starting; /* same with the pattern at the beginning */ }; /* ********** */ /* Prototypes */ /* ********** */ void help(win_t * win, term_t * term, long last_line, toggle_t * toggles); int tag_comp(void * a, void * b); void tag_swap(void * a, void * b); int isempty(const char * s); void my_beep(toggle_t * toggles); int get_cursor_position(int * const r, int * const c); void get_terminal_size(int * const r, int * const c, term_t * term); int #ifdef __sun outch(char c); #else outch(int c); #endif void restore_term(int const fd); void setup_term(int const fd); void strip_ansi_color(char * s, toggle_t * toggles, misc_t * misc); int tst_cb(void * elem); int tst_cb_cli(void * elem); int ini_load(const char * filename, win_t * win, term_t * term, limit_t * limits, ticker_t * timers, misc_t * misc, langinfo_t * langinfo, int (*report)(win_t * win, term_t * term, limit_t * limits, ticker_t * timers, misc_t * misc, langinfo_t * langinfo, const char * section, const char * name, char * value)); int ini_cb(win_t * win, term_t * term, limit_t * limits, ticker_t * timers, misc_t * misc, langinfo_t * langinfo, const char * section, const char * name, char * value); char * make_ini_path(char * name, char * base); short color_transcode(short color); void set_foreground_color(term_t * term, short color); void set_background_color(term_t * term, short color); void set_win_start_end(win_t * win, long current, long last); long build_metadata(term_t * term, long count, win_t * win); long disp_lines(win_t * win, toggle_t * toggles, long current, long count, search_mode_t search_mode, search_data_t * search_data, term_t * term, long last_line, char * tmp_word, langinfo_t * langinfo); void get_message_lines(char * message, ll_t * message_lines_list, long * message_max_width, long * message_max_len); void disp_message(ll_t * message_lines_list, long width, long max_len, term_t * term, win_t * win, langinfo_t * langinfo); int check_integer_constraint(int nb_args, char ** args, char * value, char * par); void update_bitmaps(search_mode_t search_mode, search_data_t * search_data, bitmap_affinity_t affinity); long find_next_matching_word(long * array, long nb, long value, long * index); long find_prev_matching_word(long * array, long nb, long value, long * index); void clean_matches(search_data_t * search_data, long size); void disp_cursor_word(long pos, win_t * win, term_t * term, int err); void disp_matching_word(long pos, win_t * win, term_t * term, int is_cursor, int err); void disp_word(long pos, search_mode_t search_mode, search_data_t * search_data, term_t * term, win_t * win, char * tmp_word); size_t expand(char * src, char * dest, langinfo_t * langinfo, toggle_t * toggles, misc_t * misc); int get_bytes(FILE * input, char * utf8_buffer, ll_t * ignored_glyphs_list, langinfo_t * langinfo, misc_t * misc); int get_scancode(unsigned char * s, size_t max); char * get_word(FILE * input, ll_t * word_delims_list, ll_t * record_delims_list, ll_t * ignored_glyphs_list, char * utf8_buffer, unsigned char * is_last, toggle_t * toggles, langinfo_t * langinfo, win_t * win, limit_t * limits, misc_t * misc); void left_margin_putp(char * s, term_t * term, win_t * win); void right_margin_putp(char * s1, char * s2, langinfo_t * langinfo, term_t * term, win_t * win, long line, long offset); void sig_handler(int s); void set_new_first_column(win_t * win, term_t * term); int parse_sed_like_string(sed_t * sed); void parse_selectors(char * str, filters_t * filter, char * unparsed, ll_t ** inc_interval_list, ll_t ** inc_regex_list, ll_t ** exc_interval_list, ll_t ** exc_regex_list, langinfo_t * langinfo, misc_t * misc); int replace(char * orig, sed_t * sed); int decode_attr_toggles(char * s, attrib_t * attr); int parse_attr(char * str, attrib_t * attr, short max_color); void apply_attr(term_t * term, attrib_t attr); int delims_cmp(const void * a, const void * b); long get_line_last_word(long line, long last_line); void move_left(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long last_line, char * tmp_word); void move_right(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long last_line, char * tmp_word); int find_best_word_upward(long last_word, long s, long e); int find_best_word_downward(long last_word, long s, long e); void move_up(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long page, long first_selectable, long last_line, char * tmp_word); void move_down(win_t * win, term_t * term, toggle_t * toggles, search_data_t * search_data, langinfo_t * langinfo, long * nl, long page, long last_selectable, long last_line, char * tmp_word); void init_main_ds(attrib_t * init_attr, win_t * win, limit_t * limits, ticker_t * timers, toggle_t * toggles, misc_t * misc, timeout_t * timeout, daccess_t * daccess); #endif smenu-0.9.17/smenu.spec.in000066400000000000000000000023311400523266500153510ustar00rootroot00000000000000# # spec file for package smenu # Name: smenu Version: @VERSION@ Release: 0 Summary: A standard input word picker License: GPL-2.0-only Group: Productivity/Text/Utilities URL: https://github.com/p-gen/%{name} Source: %{name}-%{version}.tar.bz2 BuildRequires: ncurses-devel BuildRoot: %{_tmppath}/%{name}-%{version}-build %description This tool reads words from a file or standard input, presents them in an interactive window after the current line on the terminal, and writes the selected words, if any, to standard output. %prep %setup -q %build %configure make %{?_smp_mflags} %package tests Summary: Testing system for %{name} Group: Productivity/Text/Utilities Requires: smenu %description tests This packages contains some scripts and a number of tests to check the %{name} tool. %install %if 0%{?suse_version} < 1315 make install DESTDIR="%{?buildroot}" %else %make_install %endif %files tests %defattr(-,root,root,-) %doc tests %files %defattr(-,root,root,-) %attr(0755,root,root) %{_bindir}/* %if 0%{?sle_version} < 120300 %doc COPYRIGHT %else %license COPYRIGHT %endif %doc examples README.rst FAQ %{_mandir}/man1/* %changelog smenu-0.9.17/tests/000077500000000000000000000000001400523266500141045ustar00rootroot00000000000000smenu-0.9.17/tests/README.rst000066400000000000000000000064741400523266500156060ustar00rootroot00000000000000WARNING ------- To be able to run these tests, you first need to get two of my other small utilities available here: https://github.com/p-gen. Make sure you have installed the latest git commit of these two utilities before going any further. - The first named **ptylie** is a kind of script without the replay capacity but with a mechanism to inject keystrokes in the keyboard queue of the slave pty running your code. - The second named **hlvt** is a minimalist embryonic headless terminal emulation able to process a typescript like the one generated by **ptylie** or scripts and render it in a virtual screen. The resulting output is the content of the screen after all the typescript content and DEC escape sequences have been interpreted. - For accurate results, please use a terminal using DEC escape sequences for attribute settings (colors, bold...). As most tests are using colors and UTF-8 the terminal and locale in use must support them. Setting and exporting TERM=xterm is a good idea. Files ----- The files present in this directory are: - ``t????.in`` contains the words to feed smenu. - ``t????.good`` is the screen content of the test after a successful run. - ``t????.tst`` contains the keystrokes to pass to smenu. - ``*.bl`` contains the blacklisted tests to ignore for an given OS (one per line). - ``test.sh`` runs a single test. - ``tests.sh`` runs selected or all tests. Usage ----- - Copy the ``tests`` directory to a place where you have write access if it is not already the case. - Go to the ``tests`` directory. - If the packaging is based on the result of ``make dist``, then you may have to get the tests from a gziped cpio archive. In that case: - Decompress the **tests.cpio.gz** archive (``gzip -dv tests.cpio.gz``). - Extract the tests from the **tests.cpio** archive in this directory (``cpio -idv < tests.cpio``). - Make tests.sh and test.sh executable (``chmod u+x tests.sh test.sh``) - Make sure that your terminal has at least a size of 80x84. - Make sure that you have previously built **smenu** with ``build.sh``. - Make sure that **smenu** is (re-)installed as the tests will use the PATH to find it. - if **ptylie** and/or **hlvt** are not in the PATH, then put their base directories in the variables ``PTYLIE_PATH`` and/or ``HLVT_PATH`` and **export** them. - If you want to run all the provided tests, then simply run ``./tests.sh`` else add the subdirectory containing the ``txxxx`` files you want to test as argument. Example: ``./tests.sh spaces``. - An individual test can be performed by going into the ``tests`` directory and by executing the command ``../test.sh`` with the test as argument without extension. Example ``../test.sh t0001``. Note that the script name is ``test.sh`` in this case and **not** ``tests.sh``. The terminal should animate as if you were typing all that stuff yourself. You can do whatever you want with this terminal during the test except close it or reduce its size to less than 80x24. The resulting files (``.log``) should not contain any occurrence of the *BAD* word. The ``tests.sh`` script will show these occurrences, if any, anyway. Note ---- Before reporting a bug due to a failing test, please re-execute is again at least 3 times with ``test.sh`` as you may have found a (timing) bug in **ptylie**/**hlvt** and not in **smenu**. smenu-0.9.17/tests/attributes/000077500000000000000000000000001400523266500162725ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/data1000066400000000000000000000000231400523266500172020ustar00rootroot00000000000000a b c aa bb cc aba smenu-0.9.17/tests/attributes/data2000066400000000000000000000000161400523266500172050ustar00rootroot000000000000001 2 3 4 5 6 7 smenu-0.9.17/tests/attributes/data3000066400000000000000000000007511400523266500172140ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 smenu-0.9.17/tests/attributes/t0001.good000066400000000000000000000002661400523266500177140ustar00rootroot00000000000000$ OUT=$(smenu -a i:7/4,b -ia -- t0001.in) a b c aa bb cc aba 0:01252c 2:24 4:24 6:07 7:07 9:24 10:24 12:24 13:24 15:01252c 16:01252c 17:01252c $ $ echo ":$OUT:" :aa: $ exit 0 smenu-0.9.17/tests/attributes/t0001.in000077700000000000000000000000001400523266500202762data1ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0001.tst000066400000000000000000000001571400523266500175750ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a i:7/4,b -ia -- t0001.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/attributes/t0002.good000066400000000000000000000003431400523266500177110ustar00rootroot00000000000000$ OUT=$(smenu -a e:0/6,bu i:0/1,r -ia -- t0002.in) a b c aa bb cc aba 0:071e29 2:01041e2e 4:01041e2e 6:07 7:07 9:01041e2e 10:01041e2e 12:01041e2e 13:01041e2e 15:071e29 16:071e29 17:071e29 $ $ echo ":$OUT:" :aa: $ exit 0 smenu-0.9.17/tests/attributes/t0002.in000077700000000000000000000000001400523266500202772data1ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0002.tst000066400000000000000000000001701400523266500175710ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a e:0/6,bu i:0/1,r -ia -- t0002.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/attributes/t0003.good000066400000000000000000000003601400523266500177110ustar00rootroot00000000000000$ OUT=$(smenu -a i:/5 e:4,br b:7/3,rb c:7/2,b -c -R2,4 -- t0003.in) 1 ┐ 0:010722 3:0107252b 2 │ 0:2d 3:0107252b 3 ║ 0:010722 3:0107252b 4 │ 0:01252a 3:0107252b 5 ▼ 0:010722 3:0107252b $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/attributes/t0003.in000077700000000000000000000000001400523266500203012data2ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0003.tst000066400000000000000000000002111400523266500175660ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a i:/5 e:4,br b:7/3,rb c:7/2,b -c -R2,4 -- t0003.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/attributes/t0004.good000066400000000000000000000003121400523266500177070ustar00rootroot00000000000000$ OUT=$(smenu -a e:5,br b:0/6 -c -R2 -- t0004.in) 1 ┐ 0:010723 3:1e2e 2 ║ 0:07 3:1e2e 3 │ 0:010723 3:1e2e 4 │ 0:010723 3:1e2e 5 ▼ 0:010723 3:1e2e $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/attributes/t0004.in000077700000000000000000000000001400523266500203022data2ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0004.tst000066400000000000000000000001671400523266500176010ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a e:5,br b:0/6 -c -R2 -- t0004.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/attributes/t0005.good000066400000000000000000000027571400523266500177270ustar00rootroot00000000000000$ OUT=$(smenu -P -N 0 -a i:6 da:1,b s:5,b -c -- t0005.in) 1 2 3 4 5 6 7 ▶ ┐ 0:0123 7:24 8:24 9:24 17:07 18:07 19:07 27:24 28:24 29:24 37:24 38:24 39:24 47:24 48:24 49:24 57:24 58:24 59:24 67:24 68:24 69:24 70:0123 79:20 32 33 34 35 36 37 38 ▶ ║ 0:0123 7:24 8:24 9:24 17:24 18:24 19:24 27:24 28:24 29:24 37:24 38:24 39:24 47:24 48:24 49:24 57:24 58:24 59:24 67:24 68:24 69:24 70:0123 79:20 61 62 63 64 65 66 67 ▶ │ 0:0123 7:24 8:24 9:24 17:24 18:24 19:24 27:24 28:24 29:24 37:24 38:24 39:24 47:24 48:24 49:24 57:24 58:24 59:24 67:24 68:24 69:24 70:0123 79:20 11) 101 12) 102 13) 103 14) 104 15) 105 16) 106 17) 107▶ │ 0:0123 1:011f 2:011f 3:011f 4:011f 5:011f 7:24 8:24 9:24 11:011f 12:011f 13:011f 14:011f 15:011f 17:24 18:24 19:24 21:011f 22:011f 23:011f 24:011f 25:011f 27:24 28:24 29:24 31:011f 32:011f 33:011f 34:011f 35:011f 37:24 38:24 39:24 41:011f 42:011f 43:011f 44:011f 45:011f 47:24 48:24 49:24 51:011f 52:011f 53:011f 54:011f 55:011f 57:24 58:24 59:24 61:011f 62:011f 63:011f 64:011f 65:011f 67:24 68:24 69:24 70:0123 79:20 131 132 133 134 135 136 137▶ ▼ 0:0123 7:24 8:24 9:24 17:24 18:24 19:24 27:24 28:24 29:24 37:24 38:24 39:24 47:24 48:24 49:24 57:24 58:24 59:24 67:24 68:24 69:24 70:0123 79:20 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/attributes/t0005.in000077700000000000000000000000001400523266500203042data3ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0005.tst000066400000000000000000000001771400523266500176030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -P -N 0 -a i:6 da:1,b s:5,b -c -- t0005.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/attributes/t0006.good000066400000000000000000000001701400523266500177130ustar00rootroot00000000000000$ OUT=$(smenu -T -a t:3,b -- t0006.in) a b c aa bb cc aba 2:0407 6:0121 7:0121 $ $ echo ":$OUT:" :b aa: $ exit 0 smenu-0.9.17/tests/attributes/t0006.in000077700000000000000000000000001400523266500203032data1ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0006.tst000066400000000000000000000001621400523266500175760ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -T -a t:3,b -- t0006.in) \S[150]\s[150]ltllthh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/attributes/t0007.good000066400000000000000000000002451400523266500177170ustar00rootroot00000000000000$ OUT=$(smenu -a ct:2/0,rb t:2/0,r -P -- t0007.in) a b c aa bb cc aba 2:072028 6:01072028 7:01072028 12:072028 13:072028 $ $ echo ":$OUT:" :b cc aa: $ exit 0 smenu-0.9.17/tests/attributes/t0007.in000077700000000000000000000000001400523266500203042data1ustar00rootroot00000000000000smenu-0.9.17/tests/attributes/t0007.tst000066400000000000000000000002011400523266500175710ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a ct:2/0,rb t:2/0,r -P -- t0007.in) \S[150]\s[150]ltllllthht\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/center_window/000077500000000000000000000000001400523266500167535ustar00rootroot00000000000000smenu-0.9.17/tests/center_window/data1000066400000000000000000000000251400523266500176650ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 smenu-0.9.17/tests/center_window/t0001.good000066400000000000000000000001701400523266500203670ustar00rootroot00000000000000$ OUT=$(smenu -M t0001.in) 1 2 3 4 5 6 7 8 9 10 34:07 $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/center_window/t0001.in000077700000000000000000000000001400523266500207572data1ustar00rootroot00000000000000smenu-0.9.17/tests/center_window/t0001.tst000066400000000000000000000001421400523266500202500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -M t0001.in) \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/center_window/t0002.good000066400000000000000000000005221400523266500203710ustar00rootroot00000000000000$ OUT=$(smenu -c -M t0002.in) 1 ┐ 41:20 2 ║ 41:20 3 │ 41:20 4 │ 37:07 38:07 41:20 5 ▼ 41:20 $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/center_window/t0002.in000077700000000000000000000000001400523266500207602data1ustar00rootroot00000000000000smenu-0.9.17/tests/center_window/t0002.tst000066400000000000000000000001451400523266500202540ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -M t0002.in) \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/center_window/t0003.good000066400000000000000000000007701400523266500203770ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -c -M t0003.in) 1 2 37:07 38:07 3 4 5 6 7 8 9 10 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/center_window/t0003.in000077700000000000000000000000001400523266500207612data1ustar00rootroot00000000000000smenu-0.9.17/tests/center_window/t0003.tst000066400000000000000000000001571400523266500202600ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -c -M t0003.in) \S[150]\s[150]jjjjkkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/center_window/t0004.good000066400000000000000000000014121400523266500203720ustar00rootroot00000000000000$ OUT=$(smenu -N. -n 10 -c -M t0004.in) 1) 1 35:01 36:01 37:01 38:01 2) 2 35:01 36:01 37:01 38:01 40:07 41:07 3) 3 35:01 36:01 37:01 38:01 4) 4 35:01 36:01 37:01 38:01 5) 5 35:01 36:01 37:01 38:01 6) 6 35:01 36:01 37:01 38:01 7) 7 35:01 36:01 37:01 38:01 8) 8 35:01 36:01 37:01 38:01 9) 9 35:01 36:01 37:01 38:01 10) 10 35:01 36:01 37:01 38:01 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/center_window/t0004.in000077700000000000000000000000001400523266500207622data1ustar00rootroot00000000000000smenu-0.9.17/tests/center_window/t0004.tst000066400000000000000000000001631400523266500202560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -N. -n 10 -c -M t0004.in) \S[150]\s[150]jjjjkkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/column_mode/000077500000000000000000000000001400523266500164055ustar00rootroot00000000000000smenu-0.9.17/tests/column_mode/data1000066400000000000000000000001211400523266500173140ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 smenu-0.9.17/tests/column_mode/data2000066400000000000000000000001301400523266500173150ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 xxxxx 13 14 15 16 17 18 19 20 21 22 yyyyyy 24 25 26 27 28 29 30 smenu-0.9.17/tests/column_mode/data3000066400000000000000000000001211400523266500173160ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 smenu-0.9.17/tests/column_mode/t0001.good000066400000000000000000000002701400523266500200220ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -c t0001.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 12:07 13:07 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ $ echo ":$OUT:" :15: $ exit 0 smenu-0.9.17/tests/column_mode/t0001.in000077700000000000000000000000001400523266500204112data1ustar00rootroot00000000000000smenu-0.9.17/tests/column_mode/t0001.tst000066400000000000000000000001571400523266500177100ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -c t0001.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/column_mode/t0002.good000066400000000000000000000003421400523266500200230ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -c t0002.in) 1 2 3 4 5 6 7 8 9 10 11 xxxxx 13 14 15 19:07 20:07 16 17 18 19 20 21 22 yyyyyy 24 25 26 27 28 29 30 $ $ echo ":$OUT:" :15: $ exit 0 smenu-0.9.17/tests/column_mode/t0002.in000077700000000000000000000000001400523266500204132data2ustar00rootroot00000000000000smenu-0.9.17/tests/column_mode/t0002.tst000066400000000000000000000001571400523266500177110ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -c t0002.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/column_mode/t0003.good000066400000000000000000000002721400523266500200260ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -c t0003.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 3:07 4:07 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ $ echo ":$OUT:" :13: $ exit 0 smenu-0.9.17/tests/column_mode/t0003.in000077700000000000000000000000001400523266500204152data3ustar00rootroot00000000000000smenu-0.9.17/tests/column_mode/t0003.tst000066400000000000000000000001571400523266500177120ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -c t0003.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/column_mode/t0004.good000066400000000000000000000016331400523266500200310ustar00rootroot00000000000000$ OUT=$(smenu -U 3 -n 10 -c t0004.in) 1) 1 2) 2 3 3) 4 4) 5 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 24:01 25:01 26:01 27:01 32:01 33:01 34:01 35:01 5) 6 6) 7 7) 8 8) 9 9) 10 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16:01 17:01 18:01 19:01 24:01 25:01 26:01 27:01 32:01 33:01 34:01 35:01 10) 11 0:01 1:01 2:01 3:01 11) 12 13 12) 14 13) 15 0:01 1:01 2:01 3:01 13:07 14:07 16:01 17:01 18:01 19:01 24:01 25:01 26:01 27:01 14) 16 15) 17 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16) 18 17) 19 18) 20 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16:01 17:01 18:01 19:01 19) 21 20) 22 23 21) 24 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 24:01 25:01 26:01 27:01 22) 25 23) 26 24) 27 25) 28 26) 29 30 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16:01 17:01 18:01 19:01 24:01 25:01 26:01 27:01 32:01 33:01 34:01 35:01 $ $ echo ":$OUT:" :13: $ exit 0 smenu-0.9.17/tests/column_mode/t0004.in000077700000000000000000000000001400523266500204162data3ustar00rootroot00000000000000smenu-0.9.17/tests/column_mode/t0004.tst000066400000000000000000000001641400523266500177110ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -U 3 -n 10 -c t0004.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/000077500000000000000000000000001400523266500166775ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/data1000066400000000000000000000000301400523266500176050ustar00rootroot00000000000000a b c d e f g h u j k l smenu-0.9.17/tests/direct_access/data2000066400000000000000000000104511400523266500176160ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 smenu-0.9.17/tests/direct_access/data3000066400000000000000000000000141400523266500176110ustar00rootroot00000000000000"2 a" "1 b" smenu-0.9.17/tests/direct_access/data4000066400000000000000000000001051400523266500176130ustar00rootroot00000000000000"05 a" "04 b" "10 c" d "06 e" "03 f" "11 g" h "07 u" "02 j" "12 k" l smenu-0.9.17/tests/direct_access/data5000066400000000000000000000001051400523266500176140ustar00rootroot00000000000000"05 a" "04 b" "10 c" d "06 e" f "11 g" h "07 u" j "12 k" l smenu-0.9.17/tests/direct_access/data6000066400000000000000000000000411400523266500176140ustar00rootroot00000000000000"abc100 def" " 200 ijk" lmnopq smenu-0.9.17/tests/direct_access/data7000066400000000000000000000001241400523266500176170ustar00rootroot00000000000000"01 item 1" " 10 item 10" " 11 item 11" "02 item 1" " 20 item 20" " 21 item 21" smenu-0.9.17/tests/direct_access/t0001.good000066400000000000000000000006661400523266500203250ustar00rootroot00000000000000$ OUT=$(smenu -N. -- t0001.in) 1) a 2) b 3) c 4) d 5) e 6) f 7) g 8) h 9) u 10) j 11) k 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 28:01 29:01 30:01 31:01 35:01 36:01 37:01 38:01 42:01 43:01 44:01 45:01 49:01 50:01 51:01 52:01 56:01 57:01 58:01 59:01 63:01 64:01 65:01 66:01 68:07 70:01 71:01 72:01 73:01 12) l 0:01 1:01 2:01 3:01 $ $ echo ":$OUT:" :j: $ exit 0 smenu-0.9.17/tests/direct_access/t0001.in000077700000000000000000000000001400523266500207032data1ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0001.tst000066400000000000000000000001451400523266500201770ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -N. -- t0001.in) \S[150]\s[150]10\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0002.good000066400000000000000000000111371400523266500203210ustar00rootroot00000000000000$ OUT=$(smenu -N. -n 15 -c -e 000 -- t0002.in) ◀ 955) 955 956) 956 957) 957 958) 958 959) 959 960) 960 ▲ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 965) 965 966) 966 967) 967 968) 968 969) 969 970) 970 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 975) 975 976) 976 977) 977 978) 978 979) 979 980) 980 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 985) 985 986) 986 987) 987 988) 988 989) 989 990) 990 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 995) 995 996) 996 997) 997 998) 998 999) 999 1000 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 68:24 69:24 70:24 71:24 79:20 ◀ 1004) 1005 1005) 1006 1006) 1007 1007) 1008 1008) 1009 1009) 1010 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1014) 1015 1015) 1016 1016) 1017 1017) 1018 1018) 1019 1019) 1020 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1024) 1025 1025) 1026 1026) 1027 1027) 1028 1028) 1029 1029) 1030 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1034) 1035 1035) 1036 1036) 1037 1037) 1038 1038) 1039 1039) 1040 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1044) 1045 1045) 1046 1046) 1047 1047) 1048 1048) 1049 1049) 1050 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1054) 1055 1055) 1056 1056) 1057 1057) 1058 1058) 1059 1059) 1060 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1064) 1065 1065) 1066 1066) 1067 1067) 1068 1068) 1069 1069) 1070 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1074) 1075 1075) 1076 1076) 1077 1077) 1078 1078) 1079 1079) 1080 │ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1084) 1085 1085) 1086 1086) 1087 1087) 1088 1088) 1089 1089) 1090 ║ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 61:01 62:01 63:01 64:01 65:01 66:01 79:20 ◀ 1094) 1095 1095) 1096 1096) 1097 1097) 1098 1098) 1099 1099) 1100 ┘ 0:20 1:01 2:01 3:01 4:01 5:01 6:01 13:01 14:01 15:01 16:01 17:01 18:01 25:01 26:01 27:01 28:01 29:01 30:01 37:01 38:01 39:01 40:01 41:01 42:01 49:01 50:01 51:01 52:01 53:01 54:01 56:07 57:07 58:07 59:07 61:01 62:01 63:01 64:01 65:01 66:01 79:20 $ $ echo ":$OUT:" :1099: $ exit 0 smenu-0.9.17/tests/direct_access/t0002.in000077700000000000000000000000001400523266500207052data2ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0002.tst000066400000000000000000000002251400523266500201770ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -N. -n 15 -c -e 000 -- t0002.in) \S[150]\s[250]1080\S[700]10\S[700]800\S[700]1098\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0003.good000066400000000000000000000004111400523266500203130ustar00rootroot00000000000000$ OUT=$(smenu -k -N "b|d" -N "a|f" -c t0003.in) 1) a 2) b c 3) d 0:01 1:01 2:01 3:01 5:07 7:01 8:01 9:01 10:01 21:01 22:01 23:01 24:01 e 4) f g h 7:01 8:01 9:01 10:01 u j k l $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0003.in000077700000000000000000000000001400523266500207052data1ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0003.tst000066400000000000000000000001641400523266500202020ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -N "b|d" -N "a|f" -c t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0004.good000066400000000000000000000003151400523266500203170ustar00rootroot00000000000000$ OUT=$(smenu -k -N "b|d" -U "a|f|b" -c t0004.in) a b c 1) d 5:07 21:01 22:01 23:01 24:01 e f g h u j k l $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0004.in000077700000000000000000000000001400523266500207062data1ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0004.tst000066400000000000000000000001661400523266500202050ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -N "b|d" -U "a|f|b" -c t0004.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0005.good000066400000000000000000000006211400523266500203200ustar00rootroot00000000000000$ OUT=$(smenu -k -U "b|d" -N "a|b" -c t0005.in) 1) a b 2) c d 0:01 1:01 2:01 3:01 5:07 14:01 15:01 16:01 17:01 3) e 4) f 5) g 6) h 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 7) u 8) j 9) k 10) l 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0005.in000077700000000000000000000000001400523266500207072data1ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0005.tst000066400000000000000000000001641400523266500202040ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -U "b|d" -N "a|b" -c t0005.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0006.good000066400000000000000000000002011400523266500203130ustar00rootroot00000000000000$ OUT=$(smenu -k -F -D n:1 i:1 -- t0006.in) 2) a 1) b 0:01 1:01 2:01 4:07 6:01 7:01 8:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0006.in000077700000000000000000000000001400523266500207122data3ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0006.tst000066400000000000000000000001601400523266500202010ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -F -D n:1 i:1 -- t0006.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0007.good000066400000000000000000000002141400523266500203200ustar00rootroot00000000000000$ OUT=$(smenu -k -F -D n:1 i:1 d:'\u7e' -- t0007.in) 2) a 1) b 0:01 1:01 2:01 4:07 6:01 7:01 8:01 $ $ echo ":$OUT:" :2~a: $ exit 0 smenu-0.9.17/tests/direct_access/t0007.in000077700000000000000000000000001400523266500207132data3ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0007.tst000066400000000000000000000001721400523266500202050ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -F -D n:1 i:1 d:'\\u7e' -- t0007.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0008.good000066400000000000000000000002321400523266500203210ustar00rootroot00000000000000$ OUT=$(smenu -k -F -D n:2 n:1 d:: i:2 d:'\u7e' i:1 -- t0008.in) 2) a 1) b 0:01 1:01 2:01 6:01 7:01 8:01 10:07 $ $ echo ":$OUT:" :1~b: $ exit 0 smenu-0.9.17/tests/direct_access/t0008.in000077700000000000000000000000001400523266500207142data3ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0008.tst000066400000000000000000000002101400523266500201770ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -F -D n:2 n:1 d:: i:2 d:'\\u7e' i:1 -- t0008.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0009.good000066400000000000000000000005731400523266500203320ustar00rootroot00000000000000$ OUT=$(smenu -c -k -F -D f:no n:2 i:1 -- t0009.in) 5) a 4) b 10) c d 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 6) e 3) f 11) g h 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 26:07 7) u 2) j 12) k l 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 $ $ echo ":$OUT:" :h: $ exit 0 smenu-0.9.17/tests/direct_access/t0009.in000077700000000000000000000000001400523266500207162data4ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0009.tst000066400000000000000000000001771400523266500202140ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -k -F -D f:no n:2 i:1 -- t0009.in) \S[150]\s[150]lllllll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0010.good000066400000000000000000000005101400523266500203110ustar00rootroot00000000000000$ OUT=$(smenu -c -F -D i:1 n:2 -- t0010.in) 5) a 4) b 10) c d 0:01 1:01 2:01 3:01 5:07 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 6) e f 11) g h 0:01 1:01 2:01 3:01 14:01 15:01 16:01 17:01 7) u j 12) k l 0:01 1:01 2:01 3:01 14:01 15:01 16:01 17:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0010.in000077700000000000000000000000001400523266500207072data5ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0010.tst000066400000000000000000000001601400523266500201740ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -F -D i:1 n:2 -- t0010.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0011.good000066400000000000000000000010331400523266500203130ustar00rootroot00000000000000$ OUT=$(smenu -c -F -N -D i:1 n:2 s:100 w:3 -- t0011.in) 5) a 4) b 10) c 11) d 0:01 1:01 2:01 3:01 4:01 6:07 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 6) e 7) f 11) g 12) h 0:01 1:01 2:01 3:01 4:01 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 7) u 8) j 12) k 13) l 0:01 1:01 2:01 3:01 4:01 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0011.in000077700000000000000000000000001400523266500207102data5ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0011.tst000066400000000000000000000001751400523266500202030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -F -N -D i:1 n:2 s:100 w:3 -- t0011.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0012.good000066400000000000000000000010371400523266500203200ustar00rootroot00000000000000$ OUT=$(smenu -c -F -N -D i:1 n:2 s:100 f:n w:3 -- t0012.in) 5) a 4) b 10) c 100) d 0:01 1:01 2:01 3:01 4:01 6:07 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 6) e 101) f 11) g 102) h 0:01 1:01 2:01 3:01 4:01 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 7) u 103) j 12) k 104) l 0:01 1:01 2:01 3:01 4:01 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0012.in000077700000000000000000000000001400523266500207112data5ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0012.tst000066400000000000000000000002011400523266500201720ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -F -N -D i:1 n:2 s:100 f:n w:3 -- t0012.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0013.good000066400000000000000000000010321400523266500203140ustar00rootroot00000000000000$ OUT=$(smenu -c -F -N -D i:1 n:2 f:no w:3 -- t0013.in) 5) a 4) b 10) c 1) d 0:01 1:01 2:01 3:01 4:01 6:07 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 6) e 2) f 11) g 3) h 0:01 1:01 2:01 3:01 4:01 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 7) u 4) j 12) k 5) l 0:01 1:01 2:01 3:01 4:01 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 24:01 25:01 26:01 27:01 28:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0013.in000077700000000000000000000000001400523266500207122data5ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0013.tst000066400000000000000000000001741400523266500202040ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -F -N -D i:1 n:2 f:no w:3 -- t0013.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0014.good000066400000000000000000000003301400523266500203150ustar00rootroot00000000000000$ OUT=$(smenu -l -F -D o:3 n:3 i:1 -- t0014.in) 100) abcdef 0:01 1:01 2:01 3:01 4:01 6:07 7:07 8:07 9:07 10:07 11:07 200) ijk 0:01 1:01 2:01 3:01 4:01 lmnopq $ $ echo ":$OUT:" :abcdef: $ exit 0 smenu-0.9.17/tests/direct_access/t0014.in000077700000000000000000000000001400523266500207142data6ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0014.tst000066400000000000000000000001641400523266500202040ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l -F -D o:3 n:3 i:1 -- t0014.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0015.good000066400000000000000000000003021400523266500203150ustar00rootroot00000000000000$ OUT=$(smenu -l -F -D o:3 n:3 i:1 h:c -- t0015.in) 100) def 0:01 1:01 2:01 3:01 4:01 6:07 7:07 8:07 200) ijk 0:01 1:01 2:01 3:01 4:01 lmnopq $ $ echo ":$OUT:" :def: $ exit 0 smenu-0.9.17/tests/direct_access/t0015.in000077700000000000000000000000001400523266500207152data6ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0015.tst000066400000000000000000000001701400523266500202020ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l -F -D o:3 n:3 i:1 h:c -- t0015.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0016.good000066400000000000000000000003311400523266500203200ustar00rootroot00000000000000$ OUT=$(smenu -l -F -D o:3 n:3 i:1 h:t -- t0016.in) 100) abcdef 0:01 1:01 2:01 3:01 4:01 6:07 7:07 8:07 9:07 10:07 11:07 200) ijk 0:01 1:01 2:01 3:01 4:01 lmnopq $ $ echo ":$OUT:" :abcdef: $ exit 0 smenu-0.9.17/tests/direct_access/t0016.in000077700000000000000000000000001400523266500207162data6ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0016.tst000066400000000000000000000001701400523266500202030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l -F -D o:3 n:3 i:1 h:t -- t0016.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0017.good000066400000000000000000000003341400523266500203240ustar00rootroot00000000000000$ OUT=$(smenu -l -F -D o:3 n:3 i:1 h:k -- t0017.in) 100) abcdef 0:01 1:01 2:01 3:01 4:01 6:07 7:07 8:07 9:07 10:07 11:07 200) ijk 0:01 1:01 2:01 3:01 4:01 lmnopq $ $ echo ":$OUT:" :abcdef: $ exit 0 smenu-0.9.17/tests/direct_access/t0017.in000077700000000000000000000000001400523266500207172data6ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0017.tst000066400000000000000000000001701400523266500202040ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l -F -D o:3 n:3 i:1 h:k -- t0017.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0018.good000066400000000000000000000005671400523266500203350ustar00rootroot00000000000000$ OUT=$(smenu -l -F -D o:0+ i:1 n:2 -- t0018.in) 1) item 1 ┐ 0:01 1:01 2:01 3:01 16:20 10) item 10 │ 0:01 1:01 2:01 3:01 16:20 11) item 11 ║ 0:01 1:01 2:01 3:01 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 16:20 2) item 1 │ 0:01 1:01 2:01 3:01 16:20 20) item 20 ▼ 0:01 1:01 2:01 3:01 16:20 $ $ echo ":$OUT:" :item 11: $ exit 0 smenu-0.9.17/tests/direct_access/t0018.in000077700000000000000000000000001400523266500207212data7ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0018.tst000066400000000000000000000001671400523266500202130ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l -F -D o:0+ i:1 n:2 -- t0018.in) \S[150]\s[150]jj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/direct_access/t0019.good000066400000000000000000000006211400523266500203250ustar00rootroot00000000000000$ OUT=$(smenu -c -N -F -D i:1 n:2 s:100 m:n f:n w:3 -- t0019.in) 5) a 4) b 10) c d 0:01 1:01 2:01 3:01 4:01 6:07 8:01 9:01 10:01 11:01 12:01 16:01 17:01 18:01 19:01 20:01 6) e f 11) g h 0:01 1:01 2:01 3:01 4:01 16:01 17:01 18:01 19:01 20:01 7) u j 12) k l 0:01 1:01 2:01 3:01 4:01 16:01 17:01 18:01 19:01 20:01 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/direct_access/t0019.in000077700000000000000000000000001400523266500207202data5ustar00rootroot00000000000000smenu-0.9.17/tests/direct_access/t0019.tst000066400000000000000000000002051400523266500202050ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -N -F -D i:1 n:2 s:100 m:n f:n w:3 -- t0019.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/do_not_trim_selection/000077500000000000000000000000001400523266500204665ustar00rootroot00000000000000smenu-0.9.17/tests/do_not_trim_selection/data1000066400000000000000000000000251400523266500214000ustar00rootroot00000000000000" 1 2" "3 4 " " 5 6" smenu-0.9.17/tests/do_not_trim_selection/data2000066400000000000000000000000261400523266500214020ustar00rootroot00000000000000" 1 2" "3 4 " " 5 6 " smenu-0.9.17/tests/do_not_trim_selection/t0001.good000066400000000000000000000001471400523266500221060ustar00rootroot00000000000000$ OUT=$(smenu -k t0001.in) 1 2 3 4 5 6 0:07 1:07 2:07 3:07 $ $ echo ":$OUT:" : 1 2: $ exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0001.in000077700000000000000000000000001400523266500224722data1ustar00rootroot00000000000000smenu-0.9.17/tests/do_not_trim_selection/t0001.tst000066400000000000000000000001371400523266500217670ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k t0001.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0002.good000066400000000000000000000001471400523266500221070ustar00rootroot00000000000000$ OUT=$(smenu -k t0002.in) 1 2 3 4 5 6 5:07 6:07 7:07 8:07 $ $ echo ":$OUT:" :3 4 : $ exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0002.in000077700000000000000000000000001400523266500224732data1ustar00rootroot00000000000000smenu-0.9.17/tests/do_not_trim_selection/t0002.tst000066400000000000000000000001401400523266500217620ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k t0002.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0003.good000066400000000000000000000001631400523266500221060ustar00rootroot00000000000000$ OUT=$(smenu -k t0003.in) 1 2 3 4 5 6 10:07 11:07 12:07 13:07 14:07 $ $ echo ":$OUT:" : 5 6 : $ exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0003.in000077700000000000000000000000001400523266500224752data2ustar00rootroot00000000000000smenu-0.9.17/tests/do_not_trim_selection/t0003.tst000066400000000000000000000001411400523266500217640ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k t0003.in) \S[150]\s[150]ll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0004.good000066400000000000000000000002651400523266500221120ustar00rootroot00000000000000$ OUT=$(smenu -N. -k t0004.in) 1) 1 2 2) 3 4 3) 5 6 0:01 1:01 2:01 9:01 10:01 11:01 18:01 19:01 20:01 22:07 23:07 24:07 25:07 26:07 $ $ echo ":$OUT:" : 5 6 : $ exit 0 smenu-0.9.17/tests/do_not_trim_selection/t0004.in000077700000000000000000000000001400523266500224762data2ustar00rootroot00000000000000smenu-0.9.17/tests/do_not_trim_selection/t0004.tst000066400000000000000000000001451400523266500217710ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -N. -k t0004.in) \S[150]\s[150]ll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/000077500000000000000000000000001400523266500174625ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/data1000066400000000000000000000000251400523266500203740ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 smenu-0.9.17/tests/elementary_moves/data2000066400000000000000000000000251400523266500203750ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 smenu-0.9.17/tests/elementary_moves/t0001.good000066400000000000000000000001301400523266500210720ustar00rootroot00000000000000$ OUT=$(smenu t0001.in) 1 2 3 4 5 6 7 8 9 10 6:07 $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0001.in000077700000000000000000000000001400523266500214662data1ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0001.tst000066400000000000000000000001371400523266500207630ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0001.in) \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0002.good000066400000000000000000000001301400523266500210730ustar00rootroot00000000000000$ OUT=$(smenu t0002.in) 1 2 3 4 5 6 7 8 9 10 0:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0002.in000077700000000000000000000000001400523266500214672data1ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0002.tst000066400000000000000000000001371400523266500207640ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0002.in) \S[150]\s[150]hhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0003.good000066400000000000000000000001401400523266500210750ustar00rootroot00000000000000$ OUT=$(smenu t0003.in) 1 2 3 4 5 6 7 8 9 10 18:07 19:07 $ $ echo ":$OUT:" :10: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0003.in000077700000000000000000000000001400523266500214702data1ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0003.tst000066400000000000000000000001461400523266500207650ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0003.in) \S[150]\s[150]llllllllll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0004.good000066400000000000000000000001301400523266500210750ustar00rootroot00000000000000$ OUT=$(smenu t0004.in) 1 2 3 4 5 6 7 8 9 10 8:07 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0004.in000077700000000000000000000000001400523266500214712data1ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0004.tst000066400000000000000000000001461400523266500207660ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0004.in) \S[150]\s[150]lllhhhllll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0005.good000066400000000000000000000001351400523266500211030ustar00rootroot00000000000000$ OUT=$(smenu -l t0005.in) 1 2 3 4 5 8:07 6 7 8 9 10 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0005.in000077700000000000000000000000001400523266500214732data2ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0005.tst000066400000000000000000000001471400523266500207700ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l t0005.in) \S[150]\s[150]ljlkljlk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0006.good000066400000000000000000000001351400523266500211040ustar00rootroot00000000000000$ OUT=$(smenu -l t0006.in) 1 2 3 4 5 8:07 6 7 8 9 10 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0006.in000077700000000000000000000000001400523266500214742data2ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0006.tst000066400000000000000000000001531400523266500207660ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l t0006.in) \S[150]\s[150]ljjlkkljjlkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0007.good000066400000000000000000000001351400523266500211050ustar00rootroot00000000000000$ OUT=$(smenu -l t0007.in) 1 2 3 4 5 8:07 6 7 8 9 10 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0007.in000077700000000000000000000000001400523266500214752data2ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0007.tst000066400000000000000000000001771400523266500207750ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -l t0007.in) \S[150]\s[150]lljjllkklljjllkkhhjjhhkkhhjjllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0008.good000066400000000000000000000005661400523266500211160ustar00rootroot00000000000000$ OUT=$(smenu -N. -l t0008.in) 1) 1 2) 2 3) 3 4) 4 5) 5 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 28:01 29:01 30:01 31:01 33:07 6) 6 7) 7 8) 8 9) 9 10) 10 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 28:01 29:01 30:01 31:01 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0008.in000077700000000000000000000000001400523266500214762data2ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0008.tst000066400000000000000000000002031400523266500207640ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -N. -l t0008.in) \S[150]\s[150]lljjllkklljjllkkhhjjhhkkhhjjllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/elementary_moves/t0009.good000066400000000000000000000005371400523266500211150ustar00rootroot00000000000000$ OUT=$(smenu -U 4 -l t0009.in) 1) 1 2) 2 3) 3 4 4) 5 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 28:01 29:01 30:01 31:01 33:07 5) 6 6) 7 7) 8 8) 9 9) 10 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 28:01 29:01 30:01 31:01 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/elementary_moves/t0009.in000077700000000000000000000000001400523266500214772data2ustar00rootroot00000000000000smenu-0.9.17/tests/elementary_moves/t0009.tst000066400000000000000000000002041400523266500207660ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -U 4 -l t0009.in) \S[150]\s[150]lljjllkklljjllkkhhjjhhkkhhjjllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/force_first/000077500000000000000000000000001400523266500164115ustar00rootroot00000000000000smenu-0.9.17/tests/force_first/data1000066400000000000000000000000341400523266500173230ustar00rootroot00000000000000a b c d X e f g h i j X k l smenu-0.9.17/tests/force_first/data2000066400000000000000000000000401400523266500173210ustar00rootroot00000000000000X a b c d Y e f g h i j X k l Y smenu-0.9.17/tests/force_first/t0001.good000066400000000000000000000001531400523266500200260ustar00rootroot00000000000000$ OUT=$(smenu -c -A X t0001.in) a b c d X e f g h i j 4:07 X k l $ $ echo ":$OUT:" :f: $ exit 0 smenu-0.9.17/tests/force_first/t0001.in000077700000000000000000000000001400523266500204152data1ustar00rootroot00000000000000smenu-0.9.17/tests/force_first/t0001.tst000066400000000000000000000001471400523266500177130ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -A X t0001.in) \S[150]\s[150]llj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/force_first/t0002.good000066400000000000000000000001651400523266500200320ustar00rootroot00000000000000$ OUT=$(smenu -c -A 'X|Y' t0002.in) X a b c d Y e f g h i j 4:07 X k l Y $ $ echo ":$OUT:" :f: $ exit 0 smenu-0.9.17/tests/force_first/t0002.in000077700000000000000000000000001400523266500204172data2ustar00rootroot00000000000000smenu-0.9.17/tests/force_first/t0002.tst000066400000000000000000000001531400523266500177110ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -A 'X|Y' t0002.in) \S[150]\s[150]llj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/force_last/000077500000000000000000000000001400523266500162255ustar00rootroot00000000000000smenu-0.9.17/tests/force_last/data1000066400000000000000000000000341400523266500171370ustar00rootroot00000000000000a b c d X e f g h i j X k l smenu-0.9.17/tests/force_last/data2000066400000000000000000000000401400523266500171350ustar00rootroot00000000000000X a b c d Y e f g h i j X k l Y smenu-0.9.17/tests/force_last/t0001.good000066400000000000000000000001531400523266500176420ustar00rootroot00000000000000$ OUT=$(smenu -c -Z X t0001.in) a b c d X e f g h i j X 4:07 k l $ $ echo ":$OUT:" :g: $ exit 0 smenu-0.9.17/tests/force_last/t0001.in000077700000000000000000000000001400523266500202312data1ustar00rootroot00000000000000smenu-0.9.17/tests/force_last/t0001.tst000066400000000000000000000001471400523266500175270ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -Z X t0001.in) \S[150]\s[150]llj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/force_last/t0002.good000066400000000000000000000001651400523266500176460ustar00rootroot00000000000000$ OUT=$(smenu -c -Z 'X|Y' t0002.in) X a b c d Y e f g h i j X 2:07 k l Y $ $ echo ":$OUT:" :f: $ exit 0 smenu-0.9.17/tests/force_last/t0002.in000077700000000000000000000000001400523266500202332data2ustar00rootroot00000000000000smenu-0.9.17/tests/force_last/t0002.tst000066400000000000000000000001531400523266500175250ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -Z 'X|Y' t0002.in) \S[150]\s[150]llj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/full_width/000077500000000000000000000000001400523266500162455ustar00rootroot00000000000000smenu-0.9.17/tests/full_width/data1000066400000000000000000000000441400523266500171600ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 smenu-0.9.17/tests/full_width/t0001.good000066400000000000000000000001731400523266500176640ustar00rootroot00000000000000$ OUT=$(smenu -t -w t0001.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 3:07 4:07 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/full_width/t0001.in000077700000000000000000000000001400523266500202512data1ustar00rootroot00000000000000smenu-0.9.17/tests/full_width/t0001.tst000066400000000000000000000001441400523266500175440ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -t -w t0001.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/full_width/t0002.good000066400000000000000000000005771400523266500176750ustar00rootroot00000000000000$ OUT=$(smenu -t 5 -w t0002.in) 1 2 3 4 5 6 7 8 9 10 15:07 16:07 17:07 18:07 19:07 20:07 21:07 22:07 23:07 24:07 25:07 26:07 27:07 28:07 11 12 13 14 15 $ $ echo ":$OUT:" :7: $ exit 0 smenu-0.9.17/tests/full_width/t0002.in000077700000000000000000000000001400523266500202522data1ustar00rootroot00000000000000smenu-0.9.17/tests/full_width/t0002.tst000066400000000000000000000001461400523266500175470ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -t 5 -w t0002.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/gutter/000077500000000000000000000000001400523266500154165ustar00rootroot00000000000000smenu-0.9.17/tests/gutter/data1000066400000000000000000000000411400523266500163260ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 smenu-0.9.17/tests/gutter/data2000066400000000000000000000001371400523266500163350ustar00rootroot00000000000000abcd efgh ijkl mnop qrst vwxy zabc defg hijk lmno pqrs tuvw xyza bcde efgh jklm nopq rstu vwxy smenu-0.9.17/tests/gutter/t0001.good000066400000000000000000000002251400523266500170330ustar00rootroot00000000000000$ OUT=$(smenu -t -g -- t0001.in) 1 │2 │3 │4 │5 │6 │7 │8 │9 │10│11│12│13│14 0:07 1:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/gutter/t0001.in000077700000000000000000000000001400523266500174222data1ustar00rootroot00000000000000smenu-0.9.17/tests/gutter/t0001.tst000066400000000000000000000001451400523266500167160ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -t -g -- t0001.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/gutter/t0002.good000066400000000000000000000002151400523266500170330ustar00rootroot00000000000000$ OUT=$(smenu -c -g -- t0002.in) 1│2 │3 │4 │5 0:07 6│7 │8 9│10│11│12│13│14 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/gutter/t0002.in000077700000000000000000000000001400523266500174232data1ustar00rootroot00000000000000smenu-0.9.17/tests/gutter/t0002.tst000066400000000000000000000001451400523266500167170ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -g -- t0002.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/gutter/t0003.good000066400000000000000000000002441400523266500170360ustar00rootroot00000000000000$ OUT=$(smenu -c -g '\ue29483\ue29db1\uF09D8481 ' t0003.in) 1┃2 ❱3 𝄁4 5 0:07 6┃7 ❱8 9┃10❱11𝄁12 13 14 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/gutter/t0003.in000077700000000000000000000000001400523266500174242data1ustar00rootroot00000000000000smenu-0.9.17/tests/gutter/t0003.tst000066400000000000000000000002031400523266500167130ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -g '\\ue29483\\ue29db1\\uF09D8481 ' t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/gutter/t0004.good000066400000000000000000000002741400523266500170420ustar00rootroot00000000000000$ OUT=$(smenu -c -g '|: ' t0004.in) ◀efgh:ijkl mnop qrst vwxy zabc defg hijk lmno pqrs tuvw xyza bcde efgh jklm▶ 0:20 1:07 2:07 3:07 4:07 75:20 $ $ echo ":$OUT:" :efgh: $ exit 0 smenu-0.9.17/tests/gutter/t0004.in000077700000000000000000000000001400523266500174262data2ustar00rootroot00000000000000smenu-0.9.17/tests/gutter/t0004.tst000066400000000000000000000002051400523266500167160ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -g '|: ' t0004.in) \S[150]\s[150]lllllllllllllllhhhhhhhhhhhhhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/gutter/t0005.good000066400000000000000000000002721400523266500170410ustar00rootroot00000000000000$ OUT=$(smenu -c -g '|: ' t0005.in) abcd|efgh:ijkl mnop qrst vwxy zabc defg hijk lmno pqrs tuvw xyza bcde efgh▶ 0:20 1:07 2:07 3:07 4:07 75:20 $ $ echo ":$OUT:" :abcd: $ exit 0 smenu-0.9.17/tests/gutter/t0005.in000077700000000000000000000000001400523266500174272data2ustar00rootroot00000000000000smenu-0.9.17/tests/gutter/t0005.tst000066400000000000000000000002061400523266500167200ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -g '|: ' t0005.in) \S[150]\s[150]lllllllllllllllhhhhhhhhhhhhhhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/ignored_input/000077500000000000000000000000001400523266500167525ustar00rootroot00000000000000smenu-0.9.17/tests/ignored_input/data1000066400000000000000000000001121400523266500176610ustar00rootroot000000000000000 1 10 11 12 13 14 15 16 17 18 19 2 20 3 4 5 6 7 8 9 smenu-0.9.17/tests/ignored_input/data2000066400000000000000000000000451400523266500176670ustar00rootroot00000000000000a±b«c »a¿« «««x»»» «×» smenu-0.9.17/tests/ignored_input/data3000066400000000000000000000000351400523266500176670ustar00rootroot00000000000000a b c d e , f g h i smenu-0.9.17/tests/ignored_input/t0001.good000066400000000000000000000002321400523266500203650ustar00rootroot00000000000000$ OUT=$(smenu -c -z '\u0d' t0001.in) 0 ┐ 4:20 1 ║ 4:20 10 │ 4:20 11 │ 0:07 1:07 4:20 12 ▼ 4:20 $ $ echo ":$OUT:" :11: $ exit 0 smenu-0.9.17/tests/ignored_input/t0001.in000077700000000000000000000000001400523266500207562data1ustar00rootroot00000000000000smenu-0.9.17/tests/ignored_input/t0001.tst000066400000000000000000000001551400523266500202530ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -z '\\u0d' t0001.in) \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/ignored_input/t0002.good000066400000000000000000000002321400523266500203660ustar00rootroot00000000000000$ OUT=$(smenu -c -z '1\u0d' t0002.in) 0 ┐ 4:20 0 ║ 4:20 2 │ 4:20 3 │ 0:07 1:07 4:20 4 ▼ 4:20 $ $ echo ":$OUT:" :3: $ exit 0 smenu-0.9.17/tests/ignored_input/t0002.in000077700000000000000000000000001400523266500207572data1ustar00rootroot00000000000000smenu-0.9.17/tests/ignored_input/t0002.tst000066400000000000000000000001561400523266500202550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -z '1\\u0d' t0002.in) \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/ignored_input/t0003.good000066400000000000000000000003501400523266500203700ustar00rootroot00000000000000$ OUT=$(smenu -zap 02 t0003.in|od -c|tr '\\' '/'|tr -d ' ') \r 1\r 1\r 11\r 1\r 13\r 14\r 15\r 16\r 17\r 18\r 19\r \r \r 3\r 4\r 5\r 6\r 11:07 12:07 13:07 14:07 7\r 8\r 9\r $ $ echo ":$OUT:" :000000011/r 0000004: $ exit 0 smenu-0.9.17/tests/ignored_input/t0003.in000077700000000000000000000000001400523266500207602data1ustar00rootroot00000000000000smenu-0.9.17/tests/ignored_input/t0003.tst000066400000000000000000000002051400523266500202510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -zap 02 t0003.in|od -c|tr '\\\\' '/'|tr -d ' ') \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/ignored_input/t0004.good000066400000000000000000000001411400523266500203670ustar00rootroot00000000000000$ OUT=$(smenu -zap '×\uc2bf«»' t0004.in) a±bc a x 7:07 $ $ echo ":$OUT:" :x: $ exit 0 smenu-0.9.17/tests/ignored_input/t0004.in000077700000000000000000000000001400523266500207622data2ustar00rootroot00000000000000smenu-0.9.17/tests/ignored_input/t0004.tst000066400000000000000000000001641400523266500202560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -zap '×\\uc2bf«»' t0004.in) \S[150]\s[150]lll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/ignored_input/t0005.good000066400000000000000000000001761400523266500204000ustar00rootroot00000000000000$ OUT=$(smenu -c -L, -z '\u0a\u0d ' t0005.in) abcde fghi 0:07 1:07 2:07 3:07 4:07 $ $ echo ":$OUT:" :fghi: $ exit 0 smenu-0.9.17/tests/ignored_input/t0005.in000077700000000000000000000000001400523266500207642data3ustar00rootroot00000000000000smenu-0.9.17/tests/ignored_input/t0005.tst000066400000000000000000000001651400523266500202600ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -L, -z '\\u0a\\u0d ' t0005.in) \S[150]\s[150]j\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/in-ex-clusions/000077500000000000000000000000001400523266500167615ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/data1000066400000000000000000000000631400523266500176750ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 smenu-0.9.17/tests/in-ex-clusions/data2000066400000000000000000000000241400523266500176730ustar00rootroot00000000000000a«bc\u01 a«b»»c smenu-0.9.17/tests/in-ex-clusions/t0001.good000066400000000000000000000002301400523266500203720ustar00rootroot00000000000000$ OUT=$(smenu -e2 t0001.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2:24 14:07 24:24 25:24 48:24 49:24 $ $ echo ":$OUT:" :8: $ exit 0 smenu-0.9.17/tests/in-ex-clusions/t0001.in000077700000000000000000000000001400523266500207652data1ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/t0001.tst000066400000000000000000000001621400523266500202600ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -e2 t0001.in) \S[150]\s[150]llllllllllhhhhhhll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/in-ex-clusions/t0002.good000066400000000000000000000004411400523266500203770ustar00rootroot00000000000000$ OUT=$(smenu -i[2-3] -e1 t0002.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 0:24 2:07 6:24 8:24 10:24 12:24 14:24 16:24 18:24 19:24 21:24 22:24 24:24 25:24 27:24 28:24 30:24 31:24 33:24 34:24 36:24 37:24 39:24 40:24 42:24 43:24 45:24 46:24 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/in-ex-clusions/t0002.in000077700000000000000000000000001400523266500207662data1ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/t0002.tst000066400000000000000000000001551400523266500202630ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -i[2-3] -e1 t0002.in) \S[150]\s[150]lllhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/in-ex-clusions/t0003.good000066400000000000000000000004151400523266500204010ustar00rootroot00000000000000$ OUT=$(smenu -i[2-3] -e3 -i5 t0003.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 0:24 4:24 6:24 8:07 10:24 12:24 14:24 16:24 18:24 19:24 21:24 22:24 27:24 28:24 30:24 31:24 36:24 37:24 39:24 40:24 42:24 43:24 45:24 46:24 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/in-ex-clusions/t0003.in000077700000000000000000000000001400523266500207672data1ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/t0003.tst000066400000000000000000000001611400523266500202610ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -i[2-3] -e3 -i5 t0003.in) \S[150]\s[150]lllhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/in-ex-clusions/t0004.good000066400000000000000000000004361400523266500204050ustar00rootroot00000000000000$ OUT=$(smenu -i[2-3] -e3 -i3 t0004.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 0:24 2:07 4:24 6:24 8:24 10:24 12:24 14:24 16:24 18:24 19:24 21:24 22:24 27:24 28:24 30:24 31:24 33:24 34:24 36:24 37:24 39:24 40:24 42:24 43:24 45:24 46:24 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/in-ex-clusions/t0004.in000077700000000000000000000000001400523266500207702data1ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/t0004.tst000066400000000000000000000001611400523266500202620ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -i[2-3] -e3 -i3 t0004.in) \S[150]\s[150]lllhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/in-ex-clusions/t0005.good000066400000000000000000000007201400523266500204020ustar00rootroot00000000000000$ OUT=$(smenu -i[2-3] -N '2|4' -e3 -i3 t0005.in) 1 1) 2 3 4 5 6 7 8 9 10 5:24 7:01 8:01 9:01 10:01 12:07 19:24 26:24 33:24 40:24 47:24 54:24 61:24 68:24 69:24 11 2) 12 13 14 15 16 17 18 19 5:24 6:24 8:01 9:01 10:01 11:01 21:24 22:24 29:24 30:24 37:24 38:24 45:24 46:24 53:24 54:24 61:24 62:24 69:24 70:24 3) 20 0:01 1:01 2:01 3:01 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/in-ex-clusions/t0005.in000077700000000000000000000000001400523266500207712data1ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/t0005.tst000066400000000000000000000001721400523266500202650ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -i[2-3] -N '2|4' -e3 -i3 t0005.in) \S[150]\s[150]lllhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/in-ex-clusions/t0006.good000066400000000000000000000002311400523266500204000ustar00rootroot00000000000000$ OUT=$(smenu -e\\U0000bb t0006.in) a«bc. a«b»»c 0:07 1:07 2:07 3:07 4:07 6:24 7:24 8:24 9:24 10:24 11:24 $ $ echo ":$OUT:" :a«bc.: $ exit 0 smenu-0.9.17/tests/in-ex-clusions/t0006.in000077700000000000000000000000001400523266500207732data2ustar00rootroot00000000000000smenu-0.9.17/tests/in-ex-clusions/t0006.tst000066400000000000000000000001531400523266500202650ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -e\\\\U0000bb t0006.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/000077500000000000000000000000001400523266500176025ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/data1000066400000000000000000000000641400523266500205170ustar00rootroot00000000000000a b c d e f g h i j k l m n o p q r s t u v w x y z smenu-0.9.17/tests/initial_selection/data2000066400000000000000000000000401400523266500205120ustar00rootroot00000000000000aab abb aa ab ba bb aba bab aaa smenu-0.9.17/tests/initial_selection/t0001.good000066400000000000000000000001751400523266500212230ustar00rootroot00000000000000$ OUT=$(smenu -s h t0001.in) a b c d e f g h i j k l m n o p q r s t u v w x y z 14:07 $ $ echo ":$OUT:" :h: $ exit 0 smenu-0.9.17/tests/initial_selection/t0001.in000077700000000000000000000000001400523266500216062data1ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0001.tst000066400000000000000000000001411400523266500210760ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -s h t0001.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0002.good000066400000000000000000000001731400523266500212220ustar00rootroot00000000000000$ OUT=$(smenu -s5 t0002.in) a b c d e f g h i j k l m n o p q r s t u v w x y z 0:07 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/initial_selection/t0002.in000077700000000000000000000000001400523266500216072data1ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0002.tst000066400000000000000000000001401400523266500210760ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -s5 t0002.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0003.good000066400000000000000000000002001400523266500212120ustar00rootroot00000000000000$ OUT=$(smenu -s "#5" t0003.in) a b c d e f g h i j k l m n o p q r s t u v w x y z 10:07 $ $ echo ":$OUT:" :f: $ exit 0 smenu-0.9.17/tests/initial_selection/t0003.in000077700000000000000000000000001400523266500216102data1ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0003.tst000066400000000000000000000001441400523266500211030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -s "#5" t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0004.good000066400000000000000000000001711400523266500212220ustar00rootroot00000000000000$ OUT=$(smenu -s/a.a t0004.in) aab abb aa ab ba bb aba bab aaa 20:07 21:07 22:07 $ $ echo ":$OUT:" :aba: $ exit 0 smenu-0.9.17/tests/initial_selection/t0004.in000077700000000000000000000000001400523266500216122data2ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0004.tst000066400000000000000000000001431400523266500211030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -s/a.a t0004.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0005.good000066400000000000000000000001651400523266500212260ustar00rootroot00000000000000$ OUT=$(smenu -s/bb t0005.in) aab abb aa ab ba bb aba bab aaa 4:07 5:07 6:07 $ $ echo ":$OUT:" :abb: $ exit 0 smenu-0.9.17/tests/initial_selection/t0005.in000077700000000000000000000000001400523266500216132data2ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0005.tst000066400000000000000000000001421400523266500211030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -s/bb t0005.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0006.good000066400000000000000000000001601400523266500212220ustar00rootroot00000000000000$ OUT=$(smenu -sbb t0006.in) aab abb aa ab ba bb aba bab aaa 17:07 18:07 $ $ echo ":$OUT:" :bb: $ exit 0 smenu-0.9.17/tests/initial_selection/t0006.in000077700000000000000000000000001400523266500216142data2ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0006.tst000066400000000000000000000001411400523266500211030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -sbb t0006.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0007.good000066400000000000000000000003301400523266500212220ustar00rootroot00000000000000$ OUT=$(smenu -eb -saa t0007.in) aab abb aa ab ba bb aba bab aaa 0:24 1:24 2:24 4:24 5:24 6:24 8:07 9:07 11:24 12:24 14:24 15:24 17:24 18:24 20:24 21:24 22:24 24:24 25:24 26:24 $ $ echo ":$OUT:" :aa: $ exit 0 smenu-0.9.17/tests/initial_selection/t0007.in000077700000000000000000000000001400523266500216152data2ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0007.tst000066400000000000000000000001451400523266500211100ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -eb -saa t0007.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0008.good000066400000000000000000000002011400523266500212200ustar00rootroot00000000000000$ OUT=$(smenu -s "#30" t0008.in) a b c d e f g h i j k l m n o p q r s t u v w x y z 50:07 $ $ echo ":$OUT:" :z: $ exit 0 smenu-0.9.17/tests/initial_selection/t0008.in000077700000000000000000000000001400523266500216152data1ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0008.tst000066400000000000000000000001451400523266500211110ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -s "#30" t0008.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/initial_selection/t0009.good000066400000000000000000000002621400523266500212300ustar00rootroot00000000000000$ OUT=$(smenu -iab -s /ba t0009.in) aab abb aa ab ba bb aba bab aaa 8:24 9:24 14:24 15:24 17:24 18:24 20:07 21:07 22:07 28:24 29:24 30:24 $ $ echo ":$OUT:" :aba: $ exit 0 smenu-0.9.17/tests/initial_selection/t0009.in000077700000000000000000000000001400523266500216172data2ustar00rootroot00000000000000smenu-0.9.17/tests/initial_selection/t0009.tst000066400000000000000000000001501400523266500211060ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -iab -s /ba t0009.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/invalid_char/000077500000000000000000000000001400523266500165275ustar00rootroot00000000000000smenu-0.9.17/tests/invalid_char/data1000066400000000000000000000000101400523266500174330ustar00rootroot00000000000000a«b»c smenu-0.9.17/tests/invalid_char/data2000066400000000000000000000000401400523266500174370ustar00rootroot00000000000000a«b»c\u01 a««b»»c\U000001 smenu-0.9.17/tests/invalid_char/data3000066400000000000000000000000241400523266500174420ustar00rootroot00000000000000a«bc\u01 a«b»»c smenu-0.9.17/tests/invalid_char/t0001.good000066400000000000000000000001571400523266500201500ustar00rootroot00000000000000$ OUT=$(LC_ALL=C smenu -. ! t0001.in) a!b!c 0:07 1:07 2:07 3:07 4:07 $ $ echo ":$OUT:" :a!b!c: $ exit 0 smenu-0.9.17/tests/invalid_char/t0001.in000077700000000000000000000000001400523266500205332data1ustar00rootroot00000000000000smenu-0.9.17/tests/invalid_char/t0001.tst000066400000000000000000000001521400523266500200250ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LC_ALL=C smenu -. ! t0001.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/invalid_char/t0002.good000066400000000000000000000002201400523266500201400ustar00rootroot00000000000000$ OUT=$(LC_ALL=C smenu -. ! t0002.in) a!b!c! a!!b!!c! 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 $ $ echo ":$OUT:" :a!!b!!c!: $ exit 0 smenu-0.9.17/tests/invalid_char/t0002.in000077700000000000000000000000001400523266500205352data2ustar00rootroot00000000000000smenu-0.9.17/tests/invalid_char/t0002.tst000066400000000000000000000001531400523266500200270ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LC_ALL=C smenu -. ! t0002.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/invalid_char/t0003.good000066400000000000000000000002431400523266500201460ustar00rootroot00000000000000$ OUT=$(LC_ALL=C smenu -e\\U0000bb -. ! t0003.in) a!bc! a!b!!c 0:07 1:07 2:07 3:07 4:07 6:24 7:24 8:24 9:24 10:24 11:24 $ $ echo ":$OUT:" :a!bc!: $ exit 0 smenu-0.9.17/tests/invalid_char/t0003.in000077700000000000000000000000001400523266500205372data3ustar00rootroot00000000000000smenu-0.9.17/tests/invalid_char/t0003.tst000066400000000000000000000001721400523266500200310ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LC_ALL=C smenu -e\\\\U0000bb -. ! t0003.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/line_mode/000077500000000000000000000000001400523266500160375ustar00rootroot00000000000000smenu-0.9.17/tests/line_mode/data1000066400000000000000000000001211400523266500167460ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 smenu-0.9.17/tests/line_mode/data2000066400000000000000000000001301400523266500167470ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 xxxxx 13 14 15 16 17 18 19 20 21 22 yyyyyy 24 25 26 27 28 29 30 smenu-0.9.17/tests/line_mode/data3000066400000000000000000000001211400523266500167500ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 smenu-0.9.17/tests/line_mode/t0001.good000066400000000000000000000002561400523266500174600ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -l t0001.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 9:07 10:07 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ $ echo ":$OUT:" :14: $ exit 0 smenu-0.9.17/tests/line_mode/t0001.in000077700000000000000000000000001400523266500200432data1ustar00rootroot00000000000000smenu-0.9.17/tests/line_mode/t0001.tst000066400000000000000000000001571400523266500173420ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -l t0001.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/line_mode/t0002.good000066400000000000000000000002661400523266500174620ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -l t0002.in) 1 2 3 4 5 6 7 8 9 10 11 xxxxx 13 14 15 12:07 13:07 16 17 18 19 20 21 22 yyyyyy 24 25 26 27 28 29 30 $ $ echo ":$OUT:" :14: $ exit 0 smenu-0.9.17/tests/line_mode/t0002.in000077700000000000000000000000001400523266500200452data2ustar00rootroot00000000000000smenu-0.9.17/tests/line_mode/t0002.tst000066400000000000000000000001571400523266500173430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -l t0002.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/line_mode/t0003.good000066400000000000000000000002611400523266500174560ustar00rootroot00000000000000$ OUT=$(smenu -n 10 -l t0003.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 3:07 4:07 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ $ echo ":$OUT:" :13: $ exit 0 smenu-0.9.17/tests/line_mode/t0003.in000077700000000000000000000000001400523266500200472data3ustar00rootroot00000000000000smenu-0.9.17/tests/line_mode/t0003.tst000066400000000000000000000001571400523266500173440ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 10 -l t0003.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/line_mode/t0004.good000066400000000000000000000016201400523266500174570ustar00rootroot00000000000000$ OUT=$(smenu -U 3 -n 10 -l t0004.in) 1) 1 2) 2 3 3) 4 4) 5 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 21:01 22:01 23:01 24:01 28:01 29:01 30:01 31:01 5) 6 6) 7 7) 8 8) 9 9) 10 0:01 1:01 2:01 3:01 7:01 8:01 9:01 10:01 14:01 15:01 16:01 17:01 21:01 22:01 23:01 24:01 28:01 29:01 30:01 31:01 10) 11 0:01 1:01 2:01 3:01 11) 12 13 12) 14 13) 15 0:01 1:01 2:01 3:01 13:07 14:07 16:01 17:01 18:01 19:01 24:01 25:01 26:01 27:01 14) 16 15) 17 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16) 18 17) 19 18) 20 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16:01 17:01 18:01 19:01 19) 21 20) 22 23 21) 24 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 24:01 25:01 26:01 27:01 22) 25 23) 26 24) 27 25) 28 26) 29 30 0:01 1:01 2:01 3:01 8:01 9:01 10:01 11:01 16:01 17:01 18:01 19:01 24:01 25:01 26:01 27:01 32:01 33:01 34:01 35:01 $ $ echo ":$OUT:" :13: $ exit 0 smenu-0.9.17/tests/line_mode/t0004.in000077700000000000000000000000001400523266500200502data3ustar00rootroot00000000000000smenu-0.9.17/tests/line_mode/t0004.tst000066400000000000000000000001641400523266500173430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -U 3 -n 10 -l t0004.in) \S[150]\s[150]lljjlljjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/line_separators/000077500000000000000000000000001400523266500172765ustar00rootroot00000000000000smenu-0.9.17/tests/line_separators/data1000066400000000000000000000000701400523266500202100ustar00rootroot00000000000000abc⬇def⬇ghi⬇ ⬇jkl⬇mno⬇pqr ⬇stu⬇vwx⬇yz smenu-0.9.17/tests/line_separators/t0001.good000066400000000000000000000002601400523266500207120ustar00rootroot00000000000000$ OUT=$(smenu -c -L\\ue2ac87 t0001.in) def ▲ 5:20 ghi │ 5:20 jkl ║ 5:20 mno │ 5:20 pqr ▼ 0:07 1:07 2:07 5:20 $ $ printf "%s\n" ":$OUT:" :pqr: $ exit 0 smenu-0.9.17/tests/line_separators/t0001.in000077700000000000000000000000001400523266500213022data1ustar00rootroot00000000000000smenu-0.9.17/tests/line_separators/t0001.tst000066400000000000000000000001661400523266500206010ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -L\\\\ue2ac87 t0001.in) \S[150]\s[150]jjjjj\r \s[150]printf "%s\\n" ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/000077500000000000000000000000001400523266500162355ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/data1000066400000000000000000000007511400523266500171550ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 smenu-0.9.17/tests/long_lines/t0001.good000066400000000000000000000010051400523266500176470ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 4 -l t0001.in) ◀3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ┐ 0:20 79:20 ◀34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58▶ │ 0:20 75:20 79:20 ◀63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87▶ ║ 0:20 75:20 79:20 ◀102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120▶ ▼ 0:20 41:07 42:07 43:07 76:20 79:20 $ $ echo ":$OUT:" :112: $ exit 0 smenu-0.9.17/tests/long_lines/t0001.in000077700000000000000000000000001400523266500202412data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0001.tst000066400000000000000000000003001400523266500175260ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 4 -l t0001.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0002.good000066400000000000000000000007651400523266500176640ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 4 -c t0002.in) ◀12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ┐ 0:20 79:20 ◀43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 │ 0:20 79:20 ◀72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 ▶ ║ 0:20 76:20 79:20 ◀112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 ▼ 0:20 37:07 38:07 39:07 79:20 $ $ echo ":$OUT:" :121: $ exit 0 smenu-0.9.17/tests/long_lines/t0002.in000077700000000000000000000000001400523266500202422data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0002.tst000066400000000000000000000003001400523266500175270ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 4 -c t0002.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0003.good000066400000000000000000000007101400523266500176530ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t -n 4 t0003.in) 20 21 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 ▲ 77:20 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 │ 77:20 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 ║ 77:20 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 ▼ 44:07 45:07 46:07 77:20 $ $ echo ":$OUT:" :89: $ exit 0 smenu-0.9.17/tests/long_lines/t0003.in000077700000000000000000000000001400523266500202432data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0003.tst000066400000000000000000000003001400523266500175300ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t -n 4 t0003.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0004.good000066400000000000000000000006211400523266500176550ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -l -n 4 t0004.in) 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77▶ ▲ 0:20 51:20 54:20 101 102 103 104 105 106 107 108 109 110 111 112 113▶ │ 0:20 45:07 46:07 47:07 52:20 54:20 131 132 133 134 135 136 137 138 139 140 ║ 0:20 54:20 141 142 143 144 145 146 147 148 149 150 ┘ 0:20 54:20 $ $ echo ":$OUT:" :112: $ exit 0 smenu-0.9.17/tests/long_lines/t0004.in000077700000000000000000000000001400523266500202442data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0004.tst000066400000000000000000000003651400523266500175440ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -l -n 4 t0004.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\ \W[75x24]\S[2000]\W[45x24]\S[2000]\W[55x24]\S[2000]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0005.good000066400000000000000000000006311400523266500176570ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -n 4 t0005.in) ◀69 70 71 72 73 74 75 76 77 78 79 80 81 ▶ ▲ 0:20 52:20 54:20 ◀109 110 111 112 113 114 115 116 117 118 119 120 121▶ │ 0:20 49:07 50:07 51:07 52:20 54:20 ◀139 140 ║ 0:20 54:20 ◀149 150 ┘ 0:20 54:20 $ $ echo ":$OUT:" :121: $ exit 0 smenu-0.9.17/tests/long_lines/t0005.in000077700000000000000000000000001400523266500202452data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0005.tst000066400000000000000000000003651400523266500175450ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -n 4 t0005.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\ \W[75x24]\S[2000]\W[45x24]\S[2000]\W[55x24]\S[2000]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0006.good000066400000000000000000000005501400523266500176600ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t -n 4 t0006.in) 67 68 69 70 71 72 73 74 75 76 77 78 79 ▲ 53:20 80 81 82 83 84 85 86 87 88 89 90 91 92 │ 36:07 37:07 38:07 53:20 93 94 95 96 97 98 99 100 101 102 103 104 105 ║ 53:20 106 107 108 109 110 111 112 113 114 115 116 117 118 ▼ 53:20 $ $ echo ":$OUT:" :89: $ exit 0 smenu-0.9.17/tests/long_lines/t0006.in000077700000000000000000000000001400523266500202462data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0006.tst000066400000000000000000000003651400523266500175460ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t -n 4 t0006.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\ \W[75x24]\S[2000]\W[45x24]\S[2000]\W[55x24]\S[2000]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0007.good000066400000000000000000000005461400523266500176660ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 4 t0007.in) 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 ▲ 53:20 105 106 107 108 109 110 111 112 113 114 115 116 117 │ 32:07 33:07 34:07 53:20 118 119 120 121 122 123 124 125 126 127 128 129 130 ║ 53:20 131 132 133 134 135 136 137 138 139 140 141 142 143 ▼ 53:20 $ $ echo ":$OUT:" :113: $ exit 0 smenu-0.9.17/tests/long_lines/t0007.in000077700000000000000000000000001400523266500202472data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_lines/t0007.tst000066400000000000000000000003621400523266500175440ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 4 t0007.in) \S[150]\s[150]hhhhhljjhhjjhhkkhhkkhhjjllkklljjhhhhhjjhhjjllkkhhkkhhjjhhhhhkkhhhhjjjhhhhhh\ \W[75x24]\S[2000]\W[45x24]\S[2000]\W[55x24]\S[2000]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_lines/t0008.in000077700000000000000000000000001400523266500202502data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_words/000077500000000000000000000000001400523266500162615ustar00rootroot00000000000000smenu-0.9.17/tests/long_words/data1000066400000000000000000000007571400523266500172070ustar00rootroot000000000000001 12 123 1234 12345 123456 1234567 12345678 123456789 1234567890 12345678901 123456789012 1234567890123 12345678901234 123456789012345 1234567890123456 12345678901234567 123456789012345678 1234567890123456789 12345678901234567890 123456789012345678901 1234567890123456789012 12345678901234567890123 123456789012345678901234 1234567890123456789012345 12345678901234567890123456 123456789012345678901234567 1234567890123456789012345678 12345678901234567890123456789 123456789012345678901234567890 smenu-0.9.17/tests/long_words/t0001.good000066400000000000000000000017741400523266500177100ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 3 t0001.in) 123456789 1234567890 ▲ 63:20 12345678901 123456789012 │ 63:20 1234567890123 12345678901234 │ 63:20 123456789012345 1234567890123456 │ 63:20 12345678901234567 123456789012345678 │ 63:20 1234567890123456789 12345678901234567890 │ 63:20 123456789012345678901 1234567890123456789012 ║ 63:20 12345678901234567890123 123456789012345678901234 │ 0:07 1:07 2:07 3:07 4:07 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 15:07 16:07 17:07 18:07 19:07 20:07 21:07 22:07 23:07 24:07 25:07 26:07 27:07 28:07 29:07 63:20 1234567890123456789012345 12345678901234567890123456 │ 63:20 123456789012345678901234567 1234567890123456789012345678 ▼ 63:20 $ $ echo ":$OUT:" :12345678901234567890123: $ exit 0 smenu-0.9.17/tests/long_words/t0001.in000077700000000000000000000000001400523266500202652data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_words/t0001.tst000066400000000000000000000002301400523266500175540ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 3 t0001.in) \S[150]\s[150]lljlljlljllkkkhhjjlljjllljjjjkkh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_words/t0002.good000066400000000000000000000013001400523266500176720ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 1 t0002.in) 12345678901 ▲ 32:20 123456789012 │ 32:20 1234567890123 │ 32:20 12345678901234 │ 32:20 123456789012345 │ 32:20 1234567890123456 ║ 32:20 12345678901234567 │ 0:07 1:07 2:07 3:07 4:07 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 15:07 16:07 17:07 18:07 19:07 20:07 21:07 22:07 23:07 24:07 25:07 26:07 27:07 28:07 29:07 32:20 123456789012345678 │ 32:20 1234567890123456789 │ 32:20 12345678901234567890 ▼ 32:20 $ $ echo ":$OUT:" :12345678901234567: $ exit 0 smenu-0.9.17/tests/long_words/t0002.in000077700000000000000000000000001400523266500202662data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_words/t0002.tst000066400000000000000000000002301400523266500175550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 1 t0002.in) \S[150]\s[150]lljlljlljllkkkhhjjlljjllljjjjkkh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_words/t0003.good000066400000000000000000000010521400523266500176770ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 1 t0003.in) 1234567890123 ▲ 23:20 12345678901234 │ 23:20 123456789012345 │ 23:20 1234567890123456 │ 23:20 12345678901234567 │ 0:07 1:07 2:07 3:07 4:07 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 15:07 16:07 17:07 18:07 19:07 23:20 123456789012345678 ║ 23:20 1234567890123456789 │ 23:20 12345678901234567890 │ 23:20 12345678901234567890 │ 23:20 12345678901234567890 ▼ 23:20 $ $ echo ":$OUT:" :12345678901234567: $ exit 0 smenu-0.9.17/tests/long_words/t0003.in000077700000000000000000000000001400523266500202672data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_words/t0003.tst000066400000000000000000000003671400523266500175710ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 1 t0003.in) \S[150]\s[150]lljlljlljllkkkhhjjlljjllljjjjkkh\ \W[22x24]\s[1200]\ \W[21x24]\s[1200]\ \W[20x24]\s[1200]\ \W[22x24]\s[1200]\ \W[24x24]\s[1200]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/long_words/t0004.good000066400000000000000000000013401400523266500177000ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 1 -N. -- t0004.in) 13) 1234567890123 ▲ 0:01 1:01 2:01 3:01 23:20 14) 12345678901234 │ 0:01 1:01 2:01 3:01 23:20 15) 123456789012345 │ 0:01 1:01 2:01 3:01 23:20 16) 123456789012345 │ 0:01 1:01 2:01 3:01 23:20 17) 123456789012345 │ 0:01 1:01 2:01 3:01 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 15:07 16:07 17:07 18:07 19:07 23:20 18) 123456789012345 ║ 0:01 1:01 2:01 3:01 23:20 19) 123456789012345 │ 0:01 1:01 2:01 3:01 23:20 20) 123456789012345 │ 0:01 1:01 2:01 3:01 23:20 21) 123456789012345 │ 0:01 1:01 2:01 3:01 23:20 22) 123456789012345 ▼ 0:01 1:01 2:01 3:01 23:20 $ $ echo ":$OUT:" :12345678901234567: $ exit 0 smenu-0.9.17/tests/long_words/t0004.in000077700000000000000000000000001400523266500202702data1ustar00rootroot00000000000000smenu-0.9.17/tests/long_words/t0004.tst000066400000000000000000000003761400523266500175720ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 10 -t 1 -N. -- t0004.in) \S[150]\s[150]lljlljlljllkkkhhjjlljjllljjjjkkh\ \W[22x24]\s[1200]\ \W[21x24]\s[1200]\ \W[20x24]\s[1200]\ \W[22x24]\s[1200]\ \W[24x24]\s[1200]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/000077500000000000000000000000001400523266500155305ustar00rootroot00000000000000smenu-0.9.17/tests/message/data1000066400000000000000000000000251400523266500164420ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 smenu-0.9.17/tests/message/data2000066400000000000000000000001321400523266500164420ustar00rootroot00000000000000123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 smenu-0.9.17/tests/message/t0001.good000066400000000000000000000002731400523266500171500ustar00rootroot00000000000000$ OUT=$(smenu -m xx -n 10 -M t0001.in) xx 37:01 38:01 1 2 3 4 5 6 7 8 9 10 36:07 $ $ echo ":$OUT:" :5: $ exit 0 smenu-0.9.17/tests/message/t0001.in000077700000000000000000000000001400523266500175342data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0001.tst000066400000000000000000000001611400523266500170260ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -m xx -n 10 -M t0001.in) \S[150]\s[150]llllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0002.good000066400000000000000000000001741400523266500171510ustar00rootroot00000000000000$ OUT=$(smenu -m test t0002.in) test 0:01 1:01 2:01 3:01 1 2 3 4 5 6 7 8 9 10 0:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/message/t0002.in000077700000000000000000000000001400523266500175352data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0002.tst000066400000000000000000000001441400523266500170300ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -m test t0002.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0003.good000066400000000000000000000004311400523266500171460ustar00rootroot00000000000000$ OUT=$(smenu -M -l -m test t0003.in) test 36:01 37:01 38:01 39:01 123456789 123456789 123456789 123456789 123456789 123456789 123456789▶ 0:20 1:07 2:07 3:07 4:07 5:07 6:07 7:07 8:07 9:07 70:20 $ $ echo ":$OUT:" :123456789: $ exit 0 smenu-0.9.17/tests/message/t0003.in000077700000000000000000000000001400523266500175372data2ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0003.tst000066400000000000000000000001521400523266500170300ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -M -l -m test t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0004.good000066400000000000000000000004161400523266500171520ustar00rootroot00000000000000$ OUT=$(smenu -M -m 'xx > yyyy' t0004.in) xx 36:01 37:01 38:01 39:01 yyyy 36:01 37:01 38:01 39:01 1 2 3 4 5 6 7 8 9 10 28:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/message/t0004.in000077700000000000000000000000001400523266500175372data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0004.tst000066400000000000000000000001551400523266500170340ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -M -m 'xx\nyyyy' t0004.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0005.good000066400000000000000000000003041400523266500171470ustar00rootroot00000000000000$ OUT=$(smenu -M -m yyyy t0005.in) yyyy 36:01 37:01 38:01 39:01 1 2 3 4 5 6 7 8 9 10 28:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/message/t0005.in000077700000000000000000000000001400523266500175402data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0005.tst000066400000000000000000000001471400523266500170360ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -M -m yyyy t0005.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0006.good000066400000000000000000000014151400523266500171540ustar00rootroot00000000000000$ OUT=$(smenu -a m:r -M -m "123456789 123456789 123456789 123456789 \ > 123456789 123456789 123456789 123456789 123456789" t0006.in) 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 0:07 1:07 2:07 3:07 4:07 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 15:07 16:07 17:07 18:07 19:07 20:07 21:07 22:07 23:07 24:07 25:07 26:07 27:07 28:07 29:07 30:07 31:07 32:07 33:07 34:07 35:07 36:07 37:07 38:07 39:07 40:07 41:07 42:07 43:07 44:07 45:07 46:07 47:07 48:07 49:07 50:07 51:07 52:07 53:07 54:07 55:07 56:07 57:07 58:07 59:07 60:07 61:07 62:07 63:07 64:07 65:07 66:07 67:07 68:07 69:07 70:07 71:07 72:07 73:07 74:07 75:07 76:07 77:07 78:07 79:07 1 2 3 4 5 6 7 8 9 10 28:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/message/t0006.in000077700000000000000000000000001400523266500175412data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0006.tst000066400000000000000000000003101400523266500170270ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a m:r -M -m "123456789 123456789 123456789 123456789 \\ 123456789 123456789 123456789 123456789 123456789" t0006.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0007.good000066400000000000000000000013461400523266500171600ustar00rootroot00000000000000$ OUT=$(smenu -m "123456789 123456789 123456789 123456789 \ > 123456789 123456789 123456789 123456789 123456789" t0007.in) 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 0:01 1:01 2:01 3:01 4:01 5:01 6:01 7:01 8:01 9:01 10:01 11:01 12:01 13:01 14:01 15:01 16:01 17:01 18:01 19:01 20:01 21:01 22:01 23:01 24:01 25:01 26:01 27:01 28:01 29:01 30:01 31:01 32:01 33:01 34:01 35:01 36:01 37:01 38:01 39:01 40:01 41:01 42:01 43:01 44:01 45:01 46:01 47:01 48:01 49:01 50:01 51:01 52:01 53:01 54:01 55:01 56:01 57:01 58:01 59:01 60:01 61:01 62:01 63:01 64:01 65:01 66:01 67:01 68:01 69:01 70:01 71:01 72:01 73:01 74:01 75:01 76:01 77:01 78:01 79:01 1 2 3 4 5 6 7 8 9 10 0:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/message/t0007.in000077700000000000000000000000001400523266500175422data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0007.tst000066400000000000000000000002761400523266500170430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -m "123456789 123456789 123456789 123456789 \\ 123456789 123456789 123456789 123456789 123456789" t0007.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/message/t0008.good000066400000000000000000000006301400523266500171540ustar00rootroot00000000000000$ OUT=$(smenu -a m:7/5 -M \ > -m '=\uefbcb4\uefbca5\uefbcb3\uefbcb4= > =test=' t0008.in) =TEST= 33:252d 34:252d 35:252d 36:252d 37:252d 38:252d =test= 33:252d 34:252d 35:252d 36:252d 37:252d 38:252d 39:252d 40:252d 41:252d 42:252d 1 2 3 4 5 6 7 8 9 10 28:07 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/message/t0008.in000077700000000000000000000000001400523266500175432data1ustar00rootroot00000000000000smenu-0.9.17/tests/message/t0008.tst000066400000000000000000000002371400523266500170410ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -a m:7/5 -M \\ -m '=\\uefbcb4\\uefbca5\\uefbcb3\\uefbcb4=\n=test=' t0008.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/misc/000077500000000000000000000000001400523266500150375ustar00rootroot00000000000000smenu-0.9.17/tests/misc/data1000066400000000000000000000000061400523266500157500ustar00rootroot00000000000000a b c smenu-0.9.17/tests/misc/t0001.good000066400000000000000000000001701400523266500164530ustar00rootroot00000000000000$ OUT=$(smenu -! "Interrupted by CTRL-C" t0001.in) a b c 2:07 $ $ echo ":$OUT:" :Interrupted by CTRL-C: $ exit 0 smenu-0.9.17/tests/misc/t0001.in000077700000000000000000000000001400523266500170432data1ustar00rootroot00000000000000smenu-0.9.17/tests/misc/t0001.tst000066400000000000000000000001711400523266500163360ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -! "Interrupted by CTRL-C" t0001.in) \S[150]\s[150]l\CC \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/misc/t0002.good000066400000000000000000000001101400523266500164460ustar00rootroot00000000000000$ OUT=$(smenu t0002.in) a b c 2:07 $ $ echo ":$OUT:" :: $ exit 0 smenu-0.9.17/tests/misc/t0002.in000077700000000000000000000000001400523266500170442data1ustar00rootroot00000000000000smenu-0.9.17/tests/misc/t0002.tst000066400000000000000000000001361400523266500163400ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0002.in) \S[150]\s[150]l\CC \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/non_printable/000077500000000000000000000000001400523266500167365ustar00rootroot00000000000000smenu-0.9.17/tests/non_printable/data1000066400000000000000000000000301400523266500176440ustar00rootroot000000000000001 \\u062\\u07 \\u05 3 smenu-0.9.17/tests/non_printable/t0001.good000066400000000000000000000001471400523266500203560ustar00rootroot00000000000000$ OUT=$(smenu t0001.in) .1\a .2\a . 3 0:07 1:07 2:07 3:07 $ $ env echo ":$OUT:" :.1\a: $ exit 0 smenu-0.9.17/tests/non_printable/t0001.in000077700000000000000000000000001400523266500207422data1ustar00rootroot00000000000000smenu-0.9.17/tests/non_printable/t0001.tst000066400000000000000000000001321400523266500202320ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0001.in) \S[150]\s[150]\r \s[150]env echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/non_printable/t0002.good000066400000000000000000000001471400523266500203570ustar00rootroot00000000000000$ OUT=$(smenu -b t0002.in) 1\a 2\a 3 0:07 1:07 2:07 3:07 $ $ env echo ":$OUT:" :1\a: $ exit 0 smenu-0.9.17/tests/non_printable/t0002.in000077700000000000000000000000001400523266500207432data1ustar00rootroot00000000000000smenu-0.9.17/tests/non_printable/t0002.tst000066400000000000000000000001351400523266500202360ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -b t0002.in) \S[150]\s[150]\r \s[150]env echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/rows_cols_in-ex-clusions/000077500000000000000000000000001400523266500210535ustar00rootroot00000000000000smenu-0.9.17/tests/rows_cols_in-ex-clusions/data1000066400000000000000000000001021400523266500217610ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0001.good000066400000000000000000000004061400523266500224710ustar00rootroot00000000000000$ OUT=$(smenu -n 6 -l -R2,3 -R5 -- t0001.in) 1 2 3 4 5 0:24 2:24 4:24 6:24 8:24 6 7 8 9 10 4:07 11 12 13 14 15 16 17 18 19 20 0:24 1:24 3:24 4:24 6:24 7:24 9:24 10:24 12:24 13:24 21 22 23 24 25 0:24 1:24 3:24 4:24 $ $ echo ":$OUT:" :8: $ exit 0 smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0001.in000077700000000000000000000000001400523266500230572data1ustar00rootroot00000000000000smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0001.tst000066400000000000000000000001741400523266500223550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 6 -l -R2,3 -R5 -- t0001.in) \S[150]\s[150]llljljljhkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0002.good000066400000000000000000000003341400523266500224720ustar00rootroot00000000000000$ OUT=$(smenu -n 6 -l -R3-5 -R1 -- t0002.in) 1 2 3 4 5 6 7 8 9 10 0:24 2:24 4:24 6:24 8:24 9:24 11 12 13 14 15 3:07 4:07 16 17 18 19 20 21 22 23 24 25 0:24 1:24 3:24 4:24 $ $ echo ":$OUT:" :12: $ exit 0 smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0002.in000077700000000000000000000000001400523266500230602data1ustar00rootroot00000000000000smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0002.tst000066400000000000000000000001741400523266500223560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 6 -l -R3-5 -R1 -- t0002.in) \S[150]\s[150]llljljljhkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0003.good000066400000000000000000000003321400523266500224710ustar00rootroot00000000000000$ OUT=$(smenu -n 6 -l -R3-5,1 -- t0003.in) 1 2 3 4 5 6 7 8 9 10 0:24 2:24 4:24 6:24 8:24 9:24 11 12 13 14 15 3:07 4:07 16 17 18 19 20 21 22 23 24 25 0:24 1:24 3:24 4:24 $ $ echo ":$OUT:" :12: $ exit 0 smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0003.in000077700000000000000000000000001400523266500230612data1ustar00rootroot00000000000000smenu-0.9.17/tests/rows_cols_in-ex-clusions/t0003.tst000066400000000000000000000001721400523266500223550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 6 -l -R3-5,1 -- t0003.in) \S[150]\s[150]llljljljhkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/000077500000000000000000000000001400523266500161005ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/data1000066400000000000000000000001211400523266500170070ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 smenu-0.9.17/tests/scrolling/data2000066400000000000000000000007031400523266500170160ustar00rootroot00000000000000a a a a a a a a a a a a a a a a a a a a a a a a a b b b b b a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a b b b b b smenu-0.9.17/tests/scrolling/data3000066400000000000000000000010461400523266500170200ustar00rootroot00000000000000 0 a a a a a a a a 1 a a a a a a a a 2 a a a a a a a a 3 a a a a a a a a 4 a a a a a a a a 5 a a a a a a a a 6 a a a a a a a a 7 a a a a a a a a 8 a a a a a a a a 9 a a a a a a a a 10 a a a a a a a a 11 a a a a b b b b 12 b b b b b b b b 13 b b b b b b b b 14 b b b b b b b b 15 b b b b a a a a 16 a a a a a a a a 17 a a a a a a a a 18 a a a a a a a a 19 a a a a a a a a 20 a a a a a a a a 21 a a a a a a a a smenu-0.9.17/tests/scrolling/data4000066400000000000000000000004201400523266500170140ustar00rootroot00000000000000 0 a a a a a 1 a a a a a 2 a a a a a 3 b b b a a 4 a a a a a 5 b b b b b 6 b b b b b 7 b b b b b 8 b b b b b 9 a a a a a 10 b b b b b 11 a a a a a 12 a a a a a 13 a a a a a 14 a a a a a 15 a a a a a smenu-0.9.17/tests/scrolling/data5000066400000000000000000000025001400523266500170160ustar00rootroot00000000000000 0 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 1 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 2 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 3 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 4 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 5 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 6 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 7 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 8 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 9 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 10 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 11 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 01 23 45 67 89 smenu-0.9.17/tests/scrolling/data6000066400000000000000000000025011400523266500170200ustar00rootroot00000000000000 0 abcdefghi xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx 1 xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx defghija 2 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 3 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 4 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 5 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 6 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 7 xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx defghija 8 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 9 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 10 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 11 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 12 abcdefghi jabcdefgh ijabcdefg hijbcdefg hijabcdef ghijabcde fghijabcd efghijabc defghija 13 xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx defghija smenu-0.9.17/tests/scrolling/data7000066400000000000000000000005241400523266500170240ustar00rootroot00000000000000 0 a a a a a 1 a a a a a 2 a a a a a 3 a a a a a 4 a a a a a 5 a a a a a 6 b b b a a 7 a a a a a 8 b b b b b 9 b b b b b 10 b b b b b 11 b b b b b 12 a a a a a 13 b b b b b 14 a a a a a 15 a a a a a 16 a a a a a 17 a a a a a 18 a a a a a 19 a a a a a smenu-0.9.17/tests/scrolling/t0001.good000066400000000000000000000003061400523266500175150ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 4 -l t0001.in) 1 2 3 4 5 ┐ 6:07 16:20 6 7 8 9 10 ║ 16:20 11 12 13 14 15 │ 16:20 16 17 18 19 20 ▼ 16:20 $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/scrolling/t0001.in000077700000000000000000000000001400523266500201042data1ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0001.tst000066400000000000000000000002211400523266500173730ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 4 -l t0001.in) \S[150]\s[150]lljjlljjhhjjhhkkhhkkhhjjllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0002.good000066400000000000000000000002641400523266500175210ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -n 4 -l t0002.in) 1 2 3 4 5 \ 6:07 16:20 6 7 8 9 10 + 16:20 11 12 13 14 15 | 16:20 16 17 18 19 20 v 16:20 $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/scrolling/t0002.in000077700000000000000000000000001400523266500201052data1ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0002.tst000066400000000000000000000002071400523266500174000ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -n 4 -l t0002.in) \S[150]\s[150]lljjlljjhhjjhhkkhhkkhhjjllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0003.good000066400000000000000000000002641400523266500175220ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -n 4 -l t0002.in) 1 2 3 4 5 \ 6:07 16:20 6 7 8 9 10 + 16:20 11 12 13 14 15 | 16:20 16 17 18 19 20 v 16:20 $ $ echo ":$OUT:" :4: $ exit 0 smenu-0.9.17/tests/scrolling/t0003.in000066400000000000000000000007451400523266500172040ustar00rootroot000000000000000 a a a a 1 a a a a 2 a a a a 3 a a a a 4 a a a a 5 b b b b 6 a a a a 7 a a a a 8 a a a a 9 a a a a 10 a a a a 11 a a a a 12 a a a a 13 a a a a 14 a a a a 15 a a a a 16 a a a a 17 a a a a 18 a a a a 19 a a b b 20 b b b b 21 b b b b 22 b b b b 23 b b b b 24 b b b b 25 b b b b 26 b b b b 27 b b b b 28 b b b b 29 b b b b 30 b b b b 31 b b b b 32 b b a a 33 a a a a 34 a a a a 35 a a a a 36 a a a a 37 a a a a 38 a a a a 39 a a a a 40 a a a a 41 a a a a 42 a a a a 43 a a a a 44 b b b b smenu-0.9.17/tests/scrolling/t0003.tst000066400000000000000000000002071400523266500174010ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -n 4 -l t0002.in) \S[150]\s[150]lljjlljjhhjjhhkkhhkkhhjjllkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0004.good000066400000000000000000000006141400523266500175220ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -e [0-9] -e a -c t0004.in) 13 b b b b b b b b ^ 0:24 1:24 9:07 20:20 14 b b b b b b b b | 0:24 1:24 20:20 15 b b b b a a a a + 0:24 1:24 11:24 13:24 15:24 17:24 20:20 16 a a a a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 17 a a a a a a a a v 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 $ $ echo ":$OUT:" :b: $ exit 0 smenu-0.9.17/tests/scrolling/t0004.in000077700000000000000000000000001400523266500201112data3ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0004.tst000066400000000000000000000002061400523266500174010ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -e [0-9] -e a -c t0004.in) \S[150]\s[150]llkkkkjjjjjjjjjjkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0005.good000066400000000000000000000005311400523266500175210ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -R 7,13 -- t0005.in) 11 a a a a a ^ 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 12 a a a a a | 5:07 14:20 13 a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 14 a a a a a + 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 15 a a a a a / 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/scrolling/t0005.in000077700000000000000000000000001400523266500201132data4ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0005.tst000066400000000000000000000002121400523266500173770ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -R 7,13 -- t0005.in) \S[150]\s[150]lljjjjjjjkkkkkkkjjjKKJJKJ\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0006.good000066400000000000000000000007021400523266500175220ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -R 6,18,20 -- t0006.in) 3 a a a a a a a a ^ 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 4 a a a a a a a a + 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 5 a a a a a a a a | 5:07 20:20 6 a a a a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 7 a a a a a a a a v 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/scrolling/t0006.in000077700000000000000000000000001400523266500201132data3ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0006.tst000066400000000000000000000002311400523266500174010ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -R 6,18,20 -- t0006.in) \S[150]\s[150]lljjjjjjjkkkkkkkjjjKKKJJJKJKJjjjkkkJK\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0007.good000066400000000000000000000007041400523266500175250ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -R 4,6,11,16 -- t0007.in) 5 a a a a a a a a ^ 5:07 20:20 6 a a a a a a a a + 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 7 a a a a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 8 a a a a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 9 a a a a a a a a v 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/scrolling/t0007.in000077700000000000000000000000001400523266500201142data3ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0007.tst000066400000000000000000000002331400523266500174040ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -R 4,6,11,16 -- t0007.in) \S[150]\s[150]lljjjjjjjkkkkkkkjjjKKKJJJKJKJjjjkkkJK\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0008.good000066400000000000000000000024571400523266500175350ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -e x -e '[0-9]' t0008.in) \ 0:20 1:07 2:07 3:07 4:07 5:07 6:07 7:07 8:07 9:07 11:24 12:24 13:24 14:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 46:24 47:24 48:24 49:24 51:24 52:24 53:24 54:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 66:24 67:24 68:24 69:24 70:20 79:20 + 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 8:24 9:24 11:24 12:24 13:24 14:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 46:24 47:24 48:24 49:24 51:24 52:24 53:24 54:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 66:24 67:24 68:24 69:24 70:20 79:20 | 0:20 70:20 79:20 | 0:20 70:20 79:20 v 0:20 70:20 79:20 $ $ echo ":$OUT:" :abcdefghi: $ exit 0 smenu-0.9.17/tests/scrolling/t0008.in000077700000000000000000000000001400523266500201202data6ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0008.tst000066400000000000000000000001741400523266500174110ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -e x -e '[0-9]' t0008.in) \S[150]\s[150]JJJKKK\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0009.good000066400000000000000000000005151400523266500175270ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -Re1,22 -e '[0-9]' t0009.in) 0 a a a a a a a a \ 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 1 a a a a a a a a + 0:24 1:24 3:07 20:20 2 a a a a a a a a | 0:24 1:24 20:20 3 a a a a a a a a | 0:24 1:24 20:20 4 a a a a a a a a v 0:24 1:24 20:20 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/scrolling/t0009.in000077700000000000000000000000001400523266500201162data3ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0009.tst000066400000000000000000000002061400523266500174060ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -Re1,22 -e '[0-9]' t0009.in) \S[150]\s[150]jjjjkkkkkJjKK\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0010.good000066400000000000000000000005161400523266500175200ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -Re1,22 -e '[0-9]' t0010.in) 17 a a a a a a a a ^ 0:24 1:24 20:20 18 a a a a a a a a | 0:24 1:24 20:20 19 a a a a a a a a | 0:24 1:24 20:20 20 a a a a a a a a + 0:24 1:24 17:07 20:20 21 a a a a a a a a / 0:24 1:24 3:24 5:24 7:24 9:24 11:24 13:24 15:24 17:24 20:20 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/scrolling/t0010.in000077700000000000000000000000001400523266500201062data3ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0010.tst000066400000000000000000000002111400523266500173720ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -Re1,22 -e '[0-9]' t0010.in) \S[150]\s[150]\CJkkkkjjjjjKkJJ\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/scrolling/t0011.good000066400000000000000000000005631400523266500175230ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -c -e a -e '[0-9]' t0011.in) 2 a a a a a ^ 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 3 a a a a a + 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 4 a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 5 a a a a a | 0:24 1:24 3:24 5:24 7:24 9:24 11:24 14:20 6 b b b a a v 0:24 1:24 3:07 9:24 11:24 14:20 $ $ echo ":$OUT:" :b: $ exit 0 smenu-0.9.17/tests/scrolling/t0011.in000077700000000000000000000000001400523266500201132data7ustar00rootroot00000000000000smenu-0.9.17/tests/scrolling/t0011.tst000066400000000000000000000001771400523266500174060ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -c -e a -e '[0-9]' t0011.in) \S[150]\s[150]JJJJKKKKK\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/000077500000000000000000000000001400523266500153515ustar00rootroot00000000000000smenu-0.9.17/tests/search/FreeBSD.bl000066400000000000000000000000141400523266500170750ustar00rootroot00000000000000t0023 t0024 smenu-0.9.17/tests/search/data1000066400000000000000000000000341400523266500162630ustar00rootroot00000000000000abc ab ab abcabc bca ba bac smenu-0.9.17/tests/search/data2000066400000000000000000000011301400523266500162620ustar00rootroot00000000000000abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab smenu-0.9.17/tests/search/data3000066400000000000000000000016331400523266500162730ustar00rootroot00000000000000"c b bcac" "cabab " "baac" "c" "aaa ab" " a ab " " " " bcaa a bb" "b" "b" "ba" " c" "aa cb" " aaaab aa" "ba" "b" "ab " " aaab" "cbbcaca" "babb" "cabbcaaca" "b" "cba " " babbbbbc" "aababc" "b" "a" "bcabcccc ca ba aca" "a " " " "a ab " " b" "aac bb" "c c" "a a" "b a" "a ba " "acb cabaabcca " "b" "ca" "a" "b" " " "aa" "cbccca a" "a cb" "a" "bb bbbac bbc" "c " "cc" " " "c " "bacb bcacabaa" "ac" "b babaa a a " "cbacac" "a " "a" " aac " "c" " a aaaca bb" "a caa" " " "cba " "b" " b " "abcbb c" "babc" "c a" "c " "b" "b b" "ccca b" " " "ab" "ab ba" "cacc ba" "bcc" "cacbb" " cbba ca" "ca c aaa c cca" " a" "bb" " " " b" "ac" " c" " b" "c" "ca b" " babbc cc a cbab" "baaa cc a" " " "baabbcac" "a" "b" "bbc " "bc" " " "bcbcac" "bba" "bc b" " a b" " cbb" " cbbc" " " "b" "acba " "a" " " "a a " "caabbbbb" "c" "ba" "bcb ca cbccac" " abb" "aba cc bbb" "ba" "cbc cab b" "cbaab " "c b cbb" smenu-0.9.17/tests/search/data4000066400000000000000000000016361400523266500162770ustar00rootroot00000000000000" çàçç" "éùé€ù" "ù€€ùé" "çéççé" "éç退" "ùçàç€" "ç à ç" "à ç" "€à€ à" "ùçùà€" "ùé à€" "€é à€" "ùàààà" "àçé€à" "é€ùàà" "éà€ùé" "çù çç" " ù€çù" "àééùç" "éççàç" "àçç€à" "àùùç " "ùààéé" "ù€çùù" "ùàùùà" "€€ùàà" " €ç à" " €é ç" "ùù退" "€€çùà" "ç€àà " " àééç" "à€ é" "€àé€à" "çà éà" "ç €€" "€àùàç" "ç瀀ç" "ù ùà€" "€ éù€" "€ç€€à" "çàà à" "€€ùùà" " çùùà" " çéùù" "ç éà" "€ç€ é" "à瀀ù" "àà €ç" " ç€é " " ùùçé" "ù ù é" "àùù€ç" "€€çç€" " é " "éù退" "€ùé " "çéé€ù" "é à€à" " ùù é" "àé€ç€" "ààçà " "éàçùç" "ç€ùç€" " € àé" "éàà " "€çéé€" "ù€€ùà" "ç €ù€" " éç€ " smenu-0.9.17/tests/search/data5000066400000000000000000000000511400523266500162660ustar00rootroot00000000000000ab ababab abxab " abab" "abab " " abab " smenu-0.9.17/tests/search/t0001.good000066400000000000000000000002171400523266500167670ustar00rootroot00000000000000$ OUT=$(smenu t0001.in) abc ab ab abcabc bca ba bac 0:0723 1:0723 2:07 4:23 5:23 7:23 8:23 10:23 11:23 $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0001.in000077700000000000000000000000001400523266500173552data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0001.tst000066400000000000000000000001411400523266500166450ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0001.in) \S[150]\s[150]/ab\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0002.good000066400000000000000000000002111400523266500167620ustar00rootroot00000000000000$ OUT=$(smenu t0002.in) abc ab ab abcabc bca ba bac 10:0723 11:0723 12:07 13:07 14:0723 15:07 $ $ echo ":$OUT:" :abcabc: $ exit 0 smenu-0.9.17/tests/search/t0002.in000077700000000000000000000000001400523266500173562data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0002.tst000066400000000000000000000001421400523266500166470ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0002.in) \S[150]\s[150]/abb\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0003.good000066400000000000000000000002231400523266500167660ustar00rootroot00000000000000$ OUT=$(smenu t0003.in) abc ab ab abcabc bca ba bac 0:07 1:0723 2:0723 11:23 12:23 17:23 18:23 24:23 26:23 $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0003.in000077700000000000000000000000001400523266500173572data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0003.tst000066400000000000000000000001411400523266500166470ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0003.in) \S[150]\s[150]/bc\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0004.good000066400000000000000000000002161400523266500167710ustar00rootroot00000000000000$ OUT=$(smenu -/ sub t0004.in) abc ab ab abcabc bca ba bac 0:07 1:0723 2:0723 11:23 12:23 17:23 18:23 $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0004.in000077700000000000000000000000001400523266500173602data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0004.tst000066400000000000000000000001501400523266500166500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -/ sub t0004.in) \S[150]\s[150]/bc\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0005.good000066400000000000000000000001711400523266500167720ustar00rootroot00000000000000$ OUT=$(smenu -/ pre t0005.in) abc ab ab abcabc bca ba bac 17:0723 18:0723 19:07 $ $ echo ":$OUT:" :bca: $ exit 0 smenu-0.9.17/tests/search/t0005.in000077700000000000000000000000001400523266500173612data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0005.tst000066400000000000000000000001501400523266500166510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -/ pre t0005.in) \S[150]\s[150]/bc\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0006.good000066400000000000000000000001771400523266500170010ustar00rootroot00000000000000$ OUT=$(smenu t0006.in) abc ab ab abcabc bca ba bac 0:07 1:07 2:071f 12:1f 18:1f 26:1f $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0006.in000077700000000000000000000000001400523266500173622data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0006.tst000066400000000000000000000001721400523266500166560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0006.in) \S[150]\s[150]/abbbb\b\b\b\b\b\b\bxyzcdddd\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0007.good000066400000000000000000000001671400523266500170010ustar00rootroot00000000000000$ OUT=$(smenu t0007.in) abc ab ab abcabc bca ba bac 21:0723 22:0723 24:23 25:23 $ $ echo ":$OUT:" :ba: $ exit 0 smenu-0.9.17/tests/search/t0007.in000077700000000000000000000000001400523266500173632data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0007.tst000066400000000000000000000001611400523266500166550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0007.in) \S[150]\s[150]/aba\rll*aba\rll"ba\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0008.good000066400000000000000000000001671400523266500170020ustar00rootroot00000000000000$ OUT=$(smenu t0008.in) abc ab ab abcabc bca ba bac 21:0723 22:0723 24:23 25:23 $ $ echo ":$OUT:" :ba: $ exit 0 smenu-0.9.17/tests/search/t0008.in000077700000000000000000000000001400523266500173642data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0008.tst000066400000000000000000000001711400523266500166570ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0008.in) \S[150]\s[150]/\b\babx\bax\rll*aba\rll"ba\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0009.good000066400000000000000000000002171400523266500167770ustar00rootroot00000000000000$ OUT=$(smenu t0009.in) abc ab ab abcabc bca ba bac 10:071f 11:071f 12:071f 13:071f 14:071f 15:071f $ $ echo ":$OUT:" :abcabc: $ exit 0 smenu-0.9.17/tests/search/t0009.in000077700000000000000000000000001400523266500173652data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0009.tst000066400000000000000000000001461400523266500166620ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0009.in) \S[150]\s[150]/abcxabc\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0010.good000066400000000000000000000002071400523266500167660ustar00rootroot00000000000000$ OUT=$(smenu t0010.in) abc ab ab abcabc bca ba bac 0:071f 1:07 2:071f 10:1f 12:1f 25:1f 26:1f $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0010.in000077700000000000000000000000001400523266500173552data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0010.tst000066400000000000000000000001421400523266500166460ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0010.in) \S[150]\s[150]/axc\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0011.good000066400000000000000000000002171400523266500167700ustar00rootroot00000000000000$ OUT=$(smenu t0011.in) abc ab ab abcabc bca ba bac 0:0723 1:07 2:07 4:23 7:23 10:23 19:23 22:23 25:23 $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0011.in000077700000000000000000000000001400523266500173562data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0011.tst000066400000000000000000000001441400523266500166510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0011.in) \S[150]\s[150]/axc\b\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0012.good000066400000000000000000000002711400523266500167710ustar00rootroot00000000000000$ OUT=$(smenu -T, t0012.in) abc ab ab abcabc bca ba bac 0:23 2:23 4:07 5:07 10:0423 11:04 12:0423 13:04 14:04 15:04 24:04 25:0423 26:0423 $ $ echo ":$OUT:" :abcabc,bac: $ exit 0 smenu-0.9.17/tests/search/t0012.in000077700000000000000000000000001400523266500173572data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0012.tst000066400000000000000000000001531400523266500166520ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -T, t0012.in) \S[150]\s[150]/ac\rThhhtl\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0013.good000066400000000000000000000002211400523266500167650ustar00rootroot00000000000000$ OUT=$(smenu -T, t0013.in) abc ab ab abcabc bca ba bac 0:040723 1:0407 2:040723 10:23 12:23 25:23 26:23 $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/search/t0013.in000077700000000000000000000000001400523266500173602data1ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0013.tst000066400000000000000000000001551400523266500166550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -T, t0013.in) \S[150]\s[150]/ac\rthThtUht\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0014.good000066400000000000000000000022261400523266500167750ustar00rootroot00000000000000$ OUT=$(smenu -n 20 -T, t0014.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca 42:040723 43:040723 44:040723 45:040723 46:0407 54:0423 55:04 56:0423 57:0423 58:0423 bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba 18:0423 19:0423 20:0423 21:0423 22:04 aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac 66:0423 67:0423 68:0423 69:0423 70:04 72:0423 73:0423 74:04 75:0423 76:0423 cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac 48:0423 49:0423 50:04 51:0423 52:0423 72:0423 73:04 74:0423 75:0423 76:0423 bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac 42:0423 43:0423 44:0423 45:04 46:0423 accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab 6:0423 7:0423 8:0423 9:0423 10:04 36:0423 37:04 38:0423 39:0423 40:0423 cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab 42:0423 43:04 44:0423 45:0423 46:0423 $ $ echo ":$OUT:" :abaca,acbac,abacc,abaca,abaac,abaac,acbac,ababc,abacc,acbac,aabac: $ exit 0 smenu-0.9.17/tests/search/t0014.in000077700000000000000000000000001400523266500173622data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0014.tst000066400000000000000000000001611400523266500166530ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 -T, t0014.in) \S[150]\s[150]~abac\CA\rT\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0015.good000066400000000000000000000022261400523266500167760ustar00rootroot00000000000000$ OUT=$(smenu -n 20 -T, t0015.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca 30:0407 31:040723 32:040723 33:040723 34:040723 48:04 49:0423 50:0423 51:0423 52:0423 54:0423 55:04 56:0423 57:0423 58:0423 bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba 18:0423 19:0423 20:0423 21:04 22:0423 aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac 72:0423 73:0423 74:04 75:0423 76:0423 cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac 48:0423 49:0423 50:04 51:0423 52:0423 72:0423 73:04 74:0423 75:0423 76:0423 bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac 42:0423 43:0423 44:0423 45:04 46:0423 accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab 6:0423 7:0423 8:0423 9:04 10:0423 36:0423 37:04 38:0423 39:0423 40:0423 cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab 42:04 43:0423 44:0423 45:0423 46:0423 $ $ echo ":$OUT:" :cabac,cabac,acbac,abacc,abaac,abaac,acbac,ababc,abacc,acbac,aabac: $ exit 0 smenu-0.9.17/tests/search/t0015.in000077700000000000000000000000001400523266500173632data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0015.tst000066400000000000000000000001611400523266500166540ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 -T, t0015.in) \S[150]\s[150]~abac\CZ\rT\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0016.good000066400000000000000000000015421400523266500167770ustar00rootroot00000000000000$ OUT=$(smenu -n 20 -T, t0016.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca 42:040723 43:040723 44:040723 45:040723 46:0407 bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba 18:0423 19:0423 20:0423 21:0423 22:04 aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac 66:0423 67:0423 68:0423 69:0423 70:04 cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab 6:0423 7:0423 8:0423 9:0423 10:04 cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab $ $ echo ":$OUT:" :abaca,abacc,abaca,abacc: $ exit 0 smenu-0.9.17/tests/search/t0016.in000077700000000000000000000000001400523266500173642data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0016.tst000066400000000000000000000001611400523266500166550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 -T, t0016.in) \S[150]\s[150]'abac\CA\rT\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0017.good000066400000000000000000000014721400523266500170020ustar00rootroot00000000000000$ OUT=$(smenu -n 20 -T, t0017.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca 30:0407 31:040723 32:040723 33:040723 34:040723 48:04 49:0423 50:0423 51:0423 52:0423 bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab 42:04 43:0423 44:0423 45:0423 46:0423 $ $ echo ":$OUT:" :cabac,cabac,aabac: $ exit 0 smenu-0.9.17/tests/search/t0017.in000077700000000000000000000000001400523266500173652data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0017.tst000066400000000000000000000001611400523266500166560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 -T, t0017.in) \S[150]\s[150]'abac\CZ\rT\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0018.good000066400000000000000000000017341400523266500170040ustar00rootroot00000000000000$ OUT=$(smenu -n 20 t0018.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca 0:0723 1:07 2:07 3:07 4:0723 67:23 70:23 bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba 12:23 16:23 57:23 58:23 67:23 70:23 aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac 13:23 16:23 26:23 28:23 39:23 40:23 45:23 46:23 62:23 64:23 cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac 25:23 28:23 33:23 34:23 bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca 50:23 52:23 69:23 70:23 bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac 14:23 16:23 33:23 34:23 accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab 3:23 4:23 44:23 46:23 67:23 70:23 75:23 76:23 cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab 9:23 10:23 15:23 16:23 27:23 28:23 51:23 52:23 $ $ echo ":$OUT:" :abccb: $ exit 0 smenu-0.9.17/tests/search/t0018.in000077700000000000000000000000001400523266500173662data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0018.tst000066400000000000000000000001521400523266500166570ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 t0018.in) \S[150]\s[150]*ab\CZ\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0019.good000066400000000000000000000015211400523266500167770ustar00rootroot00000000000000$ OUT=$(smenu -n 20 t0019.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba 54:07 55:07 56:07 57:0723 58:0723 aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac 39:23 40:23 45:23 46:23 cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac 33:23 34:23 bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca 69:23 70:23 bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac 33:23 34:23 accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab 3:23 4:23 75:23 76:23 cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab 9:23 10:23 15:23 16:23 27:23 28:23 51:23 52:23 $ $ echo ":$OUT:" :babab: $ exit 0 smenu-0.9.17/tests/search/t0019.in000077700000000000000000000000001400523266500173672data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0019.tst000066400000000000000000000001521400523266500166600ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 t0019.in) \S[150]\s[150]'ab\CZ\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0020.good000066400000000000000000000015271400523266500167750ustar00rootroot00000000000000$ OUT=$(smenu -n 20 t0020.in) abccb aaacc cbaba acbaa baabc cabac ccaac abaca cabac acbac bacbc cacbb acaca 0:0723 1:0723 2:07 3:07 4:07 42:23 43:23 bbaaa aabcc acccb abacc cacac bccbc cccaa abcbc bcccc babab cacba bacbb cbcba 18:23 19:23 42:23 43:23 aaabc bcbba cabbb caaac acacb abbaa acaab ccaab caabc bcacc baabb abaca abaac 30:23 31:23 66:23 67:23 72:23 73:23 cccba bccac bbcca bccac caccb cbbab cbacc cccac abaac bbbcb cbbba bcbcb acbac 48:23 49:23 bcbbb caaca accbc bbccc aacca bbcbc cbbcc ccaaa aaacb caacc accaa cabab accca bcbbb babcc ccabb cacba abbaa cbcab caccc ababc babba ccbca abcba aabca acaac 24:23 25:23 42:23 43:23 60:23 61:23 accab abacc aabaa aaaca aabaa babcc acbac caacb ccbcc bbacc aabaa aabcb ccaab 6:23 7:23 cbbbb abcab bcaab babbc babab ccbcc accbc aabac cbaab 6:23 7:23 $ $ echo ":$OUT:" :abccb: $ exit 0 smenu-0.9.17/tests/search/t0020.in000077700000000000000000000000001400523266500173572data2ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0020.tst000066400000000000000000000001521400523266500166500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 20 t0020.in) \S[150]\s[150]^ab\CZ\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0021.good000066400000000000000000000020321400523266500167660ustar00rootroot00000000000000$ OUT=$(smenu -n 18 t0021.in) c b bcac cabab baac c aaa ab a ab bcaa a bb b b ba c aa cb 10:07 11:07 12:07 13:0723 14:0723 15:07 28:23 29:23 34:23 35:23 47:23 51:23 64:23 69:23 aaaab aa ba b ab aaab cbbcaca babb cabbcaaca b cba babbbbbc aababc b a 15:23 16:23 24:23 25:23 36:23 38:23 bcabcccc ca ba aca a a ab b aac bb c c a a b a a ba acb cabaabcca b 25:23 26:23 34:23 38:23 ca a b aa cbccca a a cb a bb bbbac bbc c cc c bacb bcacabaa ac 19:23 23:23 b babaa a a cbacac a a aac c a aaaca bb a caa cba b b abcbb c 43:23 46:23 babc c a c b b b ccca b ab ab ba cacc ba bcc cacbb cbba ca 23:23 25:23 27:23 28:23 49:23 52:23 ca c aaa c cca a bb b ac c b c ca b babbc cc a cbab 46:23 48:23 66:23 67:23 baaa cc a baabbcac a b bbc bc bcbcac bba bc b a b cbb cbbc b acba a 50:23 52:23 a a caabbbbb c ba bcb ca cbccac abb aba cc bbb ba cbc cab b cbaab 7:23 12:23 36:23 38:23 42:23 50:23 60:23 63:23 68:23 69:23 c b cbb $ $ echo ":$OUT:" :cabab: $ exit 0 smenu-0.9.17/tests/search/t0021.in000077700000000000000000000000001400523266500173612data3ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0021.tst000066400000000000000000000001521400523266500166510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 18 t0021.in) \S[150]\s[150]~ab\CZ\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0022.good000066400000000000000000000017661400523266500170040ustar00rootroot00000000000000$ OUT=$(smenu -n 18 t0022.in) c b bcac cabab baac c aaa ab a ab bcaa a bb b b ba c aa cb 24:0723 25:07 26:07 27:07 28:07 29:0723 32:23 35:23 63:23 69:23 aaaab aa ba b ab aaab cbbcaca babb cabbcaaca b cba babbbbbc aababc b a 1:23 5:23 15:23 16:23 22:23 25:23 67:23 69:23 bcabcccc ca ba aca a a ab b aac bb c c a a b a a ba acb cabaabcca b 23:23 26:23 33:23 37:23 54:23 56:23 60:23 62:23 ca a b aa cbccca a a cb a bb bbbac bbc c cc c bacb bcacabaa ac 19:23 23:23 b babaa a a cbacac a a aac c a aaaca bb a caa cba b b abcbb c 37:23 45:23 66:23 67:23 babc c a c b b b ccca b ab ab ba cacc ba bcc cacbb cbba ca 27:23 28:23 30:23 31:23 ca c aaa c cca a bb b ac c b c ca b babbc cc a cbab baaa cc a baabbcac a b bbc bc bcbcac bba bc b a b cbb cbbc b acba a 50:23 52:23 69:23 71:23 a a caabbbbb c ba bcb ca cbccac abb aba cc bbb ba cbc cab b cbaab 36:23 37:23 40:23 41:23 c b cbb $ $ echo ":$OUT:" :aaa ab: $ exit 0 smenu-0.9.17/tests/search/t0022.in000077700000000000000000000000001400523266500173622data3ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0022.tst000066400000000000000000000001521400523266500166520ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 18 t0022.in) \S[150]\s[150]~ab\CA\r\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0023.good000066400000000000000000000024101400523266500167700ustar00rootroot00000000000000$ OUT=$(smenu -k -n 18 -T \| t0023.in) çàçç éùé€ù ù€€ùé çéççé éç退 ùçàç€ ç à ç à ç €à€ à ùçùà€ ùé à€ €é à€ ùàààà 24:0407 25:0407 26:040723 27:0407 28:040723 60:04 61:0423 62:04 63:04 64:0423 66:04 67:0423 68:04 69:04 70:0423 àçé€à é€ùàà éà€ùé çù çç ù€çù àééùç éççàç àçç€à àùùç ùààéé ù€çùù ùàùùà €€ùàà €ç à €é ç ùù退 €€çùà ç€àà àééç à€ é €àé€à çà éà ç €€ €àùàç ç瀀ç ù ùà€ 12:04 13:04 14:0423 15:04 16:0423 € éù€ €ç€€à çàà à €€ùùà çùùà çéùù ç éà €ç€ é à瀀ù àà €ç ç€é ùùçé ù ù é 0:04 1:04 2:0423 3:04 4:0423 àùù€ç €€çç€ é éù退 €ùé çéé€ù é à€à ùù é àé€ç€ ààçà éàçùç ç€ùç€ € àé 18:04 19:04 20:0423 21:04 22:0423 48:04 49:0423 50:04 51:04 52:0423 éàà €çéé€ ù€€ùà ç €ù€ éç€ 6:04 7:04 8:04 9:0423 10:0423 24:04 25:0423 26:04 27:0423 28:04 $ $ echo ":$OUT:" :éç退|ùé à€|€é à€|ùù退|€ éù€|éù退|àé€ç€|€çéé€| éç€ : $ exit 0 smenu-0.9.17/tests/search/t0023.in000077700000000000000000000000001400523266500173642data4ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0023.tst000066400000000000000000000001701400523266500166530ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -n 18 -T \\| t0023.in) \S[150]\s[150]~é€\CZ\rT\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0024.good000066400000000000000000000022521400523266500167750ustar00rootroot00000000000000$ OUT=$(smenu -k -n 18 -T \| t0024.in) çàçç éùé€ù ù€€ùé çéççé éç退 ùçàç€ ç à ç à ç €à€ à ùçùà€ ùé à€ €é à€ ùàààà 6:040723 7:0407 8:0407 9:040723 10:0407 24:0423 25:04 26:04 27:0423 28:04 àçé€à é€ùàà éà€ùé çù çç ù€çù àééùç éççàç àçç€à àùùç ùààéé ù€çùù ùàùùà €€ùàà 6:0423 7:0423 8:04 9:04 10:04 12:0423 13:04 14:0423 15:04 16:04 €ç à €é ç ùù退 €€çùà ç€àà àééç à€ é €àé€à çà éà ç €€ €àùàç ç瀀ç ù ùà€ € éù€ €ç€€à çàà à €€ùùà çùùà çéùù ç éà €ç€ é à瀀ù àà €ç ç€é ùùçé ù ù é àùù€ç €€çç€ é éù退 €ùé çéé€ù é à€à ùù é àé€ç€ ààçà éàçùç ç€ùç€ € àé 18:0423 19:04 20:04 21:0423 22:04 36:0423 37:04 38:04 39:0423 40:04 éàà €çéé€ ù€€ùà ç €ù€ éç€ 24:04 25:0423 26:04 27:0423 28:04 $ $ echo ":$OUT:" :éùé€ù|éç退|é€ùàà|éà€ùé|éù退|é à€à| éç€ : $ exit 0 smenu-0.9.17/tests/search/t0024.in000077700000000000000000000000001400523266500173652data4ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0024.tst000066400000000000000000000001701400523266500166540ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -n 18 -T \\| t0024.in) \S[150]\s[150]~é€\CA\rT\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0025.good000066400000000000000000000020741400523266500170000ustar00rootroot00000000000000$ OUT=$(smenu -n 18 t0025.in) c b bcac cabab baac c aaa ab a ab bcaa a bb b b ba c aa cb aaaab aa ba b ab aaab cbbcaca babb cabbcaaca b cba babbbbbc aababc b a 41:23 43:23 44:23 59:23 64:23 65:23 70:23 71:23 72:23 bcabcccc ca ba aca a a ab b aac bb c c a a b a a ba acb cabaabcca b 0:07 1:07 2:0723 3:0723 4:0723 5:07 6:07 7:07 8:07 9:07 10:07 11:07 12:07 13:07 14:07 15:07 16:07 17:07 18:07 60:23 62:23 64:23 ca a b aa cbccca a a cb a bb bbbac bbc c cc c bacb bcacabaa ac 33:23 37:23 38:23 51:23 55:23 56:23 b babaa a a cbacac a a aac c a aaaca bb a caa cba b b abcbb c 66:23 67:23 68:23 babc c a c b b b ccca b ab ab ba cacc ba bcc cacbb cbba ca 1:23 2:23 3:23 ca c aaa c cca a bb b ac c b c ca b babbc cc a cbab 52:23 54:23 55:23 baaa cc a baabbcac a b bbc bc bcbcac bba bc b a b cbb cbbc b acba a 12:23 14:23 15:23 a a caabbbbb c ba bcb ca cbccac abb aba cc bbb ba cbc cab b cbaab 26:23 29:23 30:23 40:23 41:23 45:23 c b cbb $ $ echo ":$OUT:" :bcabcccc ca ba aca: $ exit 0 smenu-0.9.17/tests/search/t0025.in000077700000000000000000000000001400523266500173652data3ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0025.tst000066400000000000000000000001621400523266500166560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 18 t0025.in) \S[150]\s[150]~abc\rsssssSSSSs\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0026.good000066400000000000000000000004651400523266500170030ustar00rootroot00000000000000$ OUT=$(smenu -n 0 -N -- t0026.in) 1) ab 2) ababab 3) abxab 4) abab 5) abab 6) abab 0:01 1:01 2:01 4:0723 5:0723 7:01 8:01 9:01 15:23 16:23 18:01 19:01 20:01 25:23 26:23 28:01 29:01 30:01 35:23 36:23 38:01 39:01 40:01 44:23 45:23 48:01 49:01 50:01 55:23 56:23 $ $ echo ":$OUT:" :ab: $ exit 0 smenu-0.9.17/tests/search/t0026.in000077700000000000000000000000001400523266500173702data5ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0026.tst000066400000000000000000000001601400523266500166550ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 0 -N -- t0026.in) \S[150]\s[150]~ab\CZ\rj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/search/t0027.good000066400000000000000000000005101400523266500167730ustar00rootroot00000000000000$ OUT=$(smenu -n 0 -N -c t0027.in) 1) ab 0:01 1:01 2:01 4:23 5:23 2) ababab 0:01 1:01 2:01 4:07 5:07 6:07 7:07 8:0723 9:0723 3) abxab 0:01 1:01 2:01 7:23 8:23 4) abab 0:01 1:01 2:01 7:23 8:23 5) abab 0:01 1:01 2:01 6:23 7:23 6) abab 0:01 1:01 2:01 7:23 8:23 $ $ echo ":$OUT:" :ababab: $ exit 0 smenu-0.9.17/tests/search/t0027.in000077700000000000000000000000001400523266500173712data5ustar00rootroot00000000000000smenu-0.9.17/tests/search/t0027.tst000066400000000000000000000001601400523266500166560ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -n 0 -N -c t0027.in) \S[150]\s[150]~ab\CZ\rj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/spaces/000077500000000000000000000000001400523266500153625ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/data1000066400000000000000000000000251400523266500162740ustar00rootroot00000000000000" 1 2" "3 4 " " 5 6" smenu-0.9.17/tests/spaces/t0001.good000066400000000000000000000001431400523266500167760ustar00rootroot00000000000000$ OUT=$(smenu t0001.in) 1 2 3 4 5 6 0:07 1:07 2:07 3:07 $ $ echo ":$OUT:" :1 2: $ exit 0 smenu-0.9.17/tests/spaces/t0001.in000077700000000000000000000000001400523266500173662data1ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/t0001.tst000066400000000000000000000001341400523266500166600ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0001.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/spaces/t0002.good000066400000000000000000000001431400523266500167770ustar00rootroot00000000000000$ OUT=$(smenu t0002.in) 1 2 3 4 5 6 5:07 6:07 7:07 8:07 $ $ echo ":$OUT:" :3 4: $ exit 0 smenu-0.9.17/tests/spaces/t0002.in000077700000000000000000000000001400523266500173672data1ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/t0002.tst000066400000000000000000000001351400523266500166620ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0002.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/spaces/t0003.good000066400000000000000000000001471400523266500170040ustar00rootroot00000000000000$ OUT=$(smenu t0003.in) 1 2 3 4 5 6 10:07 11:07 12:07 13:07 $ $ echo ":$OUT:" :5 6: $ exit 0 smenu-0.9.17/tests/spaces/t0003.in000077700000000000000000000000001400523266500173702data1ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/t0003.tst000066400000000000000000000001361400523266500166640ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0003.in) \S[150]\s[150]ll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/spaces/t0004.good000066400000000000000000000001471400523266500170050ustar00rootroot00000000000000$ OUT=$(smenu -k t0004.in) 1 2 3 4 5 6 0:07 1:07 2:07 3:07 $ $ echo ":$OUT:" : 1 2: $ exit 0 smenu-0.9.17/tests/spaces/t0004.in000077700000000000000000000000001400523266500173712data1ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/t0004.tst000066400000000000000000000001371400523266500166660ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k t0004.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/spaces/t0005.good000066400000000000000000000001471400523266500170060ustar00rootroot00000000000000$ OUT=$(smenu -k t0005.in) 1 2 3 4 5 6 5:07 6:07 7:07 8:07 $ $ echo ":$OUT:" :3 4 : $ exit 0 smenu-0.9.17/tests/spaces/t0005.in000077700000000000000000000000001400523266500173722data1ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/t0005.tst000066400000000000000000000001401400523266500166610ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k t0005.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/spaces/t0006.good000066400000000000000000000001531400523266500170040ustar00rootroot00000000000000$ OUT=$(smenu -k t0006.in) 1 2 3 4 5 6 10:07 11:07 12:07 13:07 $ $ echo ":$OUT:" : 5 6: $ exit 0 smenu-0.9.17/tests/spaces/t0006.in000077700000000000000000000000001400523266500173732data1ustar00rootroot00000000000000smenu-0.9.17/tests/spaces/t0006.tst000066400000000000000000000001411400523266500166630ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k t0006.in) \S[150]\s[150]ll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/special_levels/000077500000000000000000000000001400523266500170765ustar00rootroot00000000000000smenu-0.9.17/tests/special_levels/data1000066400000000000000000000001211400523266500200050ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 smenu-0.9.17/tests/special_levels/t0001.good000066400000000000000000000007141400523266500205160ustar00rootroot00000000000000$ OUT=$(smenu -1 1 -2 2 -3 3 -4 4 -5 5 -c -- t0001.in) 1 2 3 4 5 ┐ 0:1f 1:1f 3:20 4:20 6:21 7:21 9:23 10:23 12:24 13:24 16:20 6 7 8 9 10 ║ 0:07 1:07 12:1f 13:1f 16:20 11 12 13 14 15 │ 0:1f 1:1f 3:1f 4:1f 6:1f 7:1f 9:1f 10:1f 12:1f 13:1f 16:20 16 17 18 19 20 │ 0:1f 1:1f 3:1f 4:1f 6:1f 7:1f 9:1f 10:1f 12:20 13:20 16:20 21 22 23 24 25 ▼ 0:1f 1:1f 3:20 4:20 6:20 7:20 9:20 10:20 12:20 13:20 16:20 $ $ echo ":$OUT:" :6: $ exit 0 smenu-0.9.17/tests/special_levels/t0001.in000077700000000000000000000000001400523266500211022data1ustar00rootroot00000000000000smenu-0.9.17/tests/special_levels/t0001.tst000066400000000000000000000001741400523266500204000ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -1 1 -2 2 -3 3 -4 4 -5 5 -c -- t0001.in) \S[150]\s[150]j\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/special_levels/t0002.good000066400000000000000000000006241400523266500205170ustar00rootroot00000000000000$ OUT=$(smenu -1 '1$' -2 '2$' -3 '3$' -4 4 -5 5 -c -- t0002.in) 1 2 3 4 5 ┐ 0:1f 1:1f 3:20 4:20 6:21 7:21 9:23 10:23 12:24 13:24 16:20 6 7 8 9 10 ║ 0:07 1:07 16:20 11 12 13 14 15 │ 0:1f 1:1f 3:20 4:20 6:21 7:21 9:23 10:23 12:24 13:24 16:20 16 17 18 19 20 │ 16:20 21 22 23 24 25 ▼ 0:1f 1:1f 3:20 4:20 6:21 7:21 9:23 10:23 12:24 13:24 16:20 $ $ echo ":$OUT:" :6: $ exit 0 smenu-0.9.17/tests/special_levels/t0002.in000077700000000000000000000000001400523266500211032data1ustar00rootroot00000000000000smenu-0.9.17/tests/special_levels/t0002.tst000066400000000000000000000002051400523266500203740ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -1 '1$' -2 '2$' -3 '3$' -4 4 -5 5 -c -- t0002.in) \S[150]\s[150]j\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/special_levels/t0003.good000066400000000000000000000006361400523266500205230ustar00rootroot00000000000000$ OUT=$(smenu -1 1 -level2 2 -c t0003.in) 1 2 3 4 5 ┐ 0:1f 1:1f 3:20 4:20 16:20 6 7 8 9 10 ║ 0:07 1:07 12:1f 13:1f 16:20 11 12 13 14 15 │ 0:1f 1:1f 3:1f 4:1f 6:1f 7:1f 9:1f 10:1f 12:1f 13:1f 16:20 16 17 18 19 20 │ 0:1f 1:1f 3:1f 4:1f 6:1f 7:1f 9:1f 10:1f 12:20 13:20 16:20 21 22 23 24 25 ▼ 0:1f 1:1f 3:20 4:20 6:20 7:20 9:20 10:20 12:20 13:20 16:20 $ $ echo ":$OUT:" :6: $ exit 0 smenu-0.9.17/tests/special_levels/t0003.in000077700000000000000000000000001400523266500211042data1ustar00rootroot00000000000000smenu-0.9.17/tests/special_levels/t0003.tst000066400000000000000000000001571400523266500204030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -1 1 -level2 2 -c t0003.in) \S[150]\s[150]j\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/special_levels/t0004.good000066400000000000000000000007631400523266500205250ustar00rootroot00000000000000$ OUT=$(smenu -1 '1$' b -2 '2$' 7/1,br -3 '3$' 0/5 \ > -4 4 r -5 5 rb -c -- t0004.in) 1 2 3 4 5 ┐ 0:01 1:01 3:01072529 4:01072529 6:1e2d 7:1e2d 9:07 10:07 12:0107 13:0107 16:20 6 7 8 9 10 ║ 0:07 1:07 16:20 11 12 13 14 15 │ 0:01 1:01 3:01072529 4:01072529 6:1e2d 7:1e2d 9:07 10:07 12:0107 13:0107 16:20 16 17 18 19 20 │ 16:20 21 22 23 24 25 ▼ 0:01 1:01 3:01072529 4:01072529 6:1e2d 7:1e2d 9:07 10:07 12:0107 13:0107 16:20 $ $ echo ":$OUT:" :6: $ exit 0 smenu-0.9.17/tests/special_levels/t0004.in000077700000000000000000000000001400523266500211052data1ustar00rootroot00000000000000smenu-0.9.17/tests/special_levels/t0004.tst000066400000000000000000000002461400523266500204030ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -1 '1$' b -2 '2$' 7/1,br -3 '3$' 0/5 \\ -4 4 r -5 5 rb -c -- t0004.in) \S[150]\s[150]j\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/000077500000000000000000000000001400523266500170435ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/data1000066400000000000000000000007571400523266500177710ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 smenu-0.9.17/tests/substitutions/data2000066400000000000000000000000161400523266500177560ustar00rootroot00000000000000a abc bac bca smenu-0.9.17/tests/substitutions/data3000066400000000000000000000000201400523266500177520ustar00rootroot00000000000000abc ABC Aab AAA smenu-0.9.17/tests/substitutions/t0001.good000066400000000000000000000013651400523266500204660ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1/(&)/' -n 15 t0001.in) (1) 2 3 4 5 6 7 8 9 (1)0 (1)1 (1)2 (1)3 (1)4 (1)5 (1)6 (1)7 (1)8 (1)9 20 2(1) 0:07 1:07 2:07 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 4(1) 42 43 44 45 46 47 48 49 50 5(1) 52 53 54 55 56 57 58 59 60 6(1) 62 63 64 65 66 67 68 69 70 7(1) 72 73 74 75 76 77 78 79 80 8(1) 82 83 84 85 86 87 88 89 90 9(1) 92 93 94 95 96 97 98 99 (1)00 (1)01 (1)02 (1)03 (1)04 (1)05 (1)06 (1)07 (1)08 (1)09 (1)10 (1)11 (1)12 (1)13 (1)14 (1)15 (1)16 (1)17 (1)18 (1)19 (1)20 (1)21 (1)22 (1)23 (1)24 (1)25 (1)26 (1)27 (1)28 (1)29 (1)30 (1)31 (1)32 (1)33 (1)34 (1)35 (1)36 (1)37 (1)38 (1)39 (1)40 (1)41 (1)42 (1)43 (1)44 (1)45 (1)46 (1)47 (1)48 (1)49 (1)50 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0001.in000077700000000000000000000000001400523266500210472data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0001.tst000066400000000000000000000001771400523266500203500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1/(&)/' -n 15 t0001.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0002.good000066400000000000000000000016321400523266500204640ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1*/(&)/' -n 15 t0002.in) (1) ()2 ()3 ()4 ()5 ()6 ()7 ()8 ()9 (1)0 (11) (1)2 (1)3 (1)4 (1)5 (1)6 (1)7 0:07 1:07 2:07 (1)8 (1)9 ()20 ()21 ()22 ()23 ()24 ()25 ()26 ()27 ()28 ()29 ()30 ()32 ()33 ()34 ()35 ()36 ()37 ()38 ()39 ()40 ()41 ()42 ()43 ()44 ()45 ()46 ()47 ()48 ()49 ()50 ()51 ()52 ()53 ()54 ()55 ()56 ()57 ()58 ()59 ()60 ()61 ()62 ()63 ()64 ()65 ()66 ()67 ()68 ()69 ()70 ()71 ()72 ()73 ()74 ()75 ()76 ()77 ()78 ()79 ()80 ()81 ()82 ()83 ()84 ()85 ()86 ()87 ()88 ()89 ()90 ()91 ()92 ()93 ()94 ()95 ()96 ()97 ()98 ()99 (1)00 (1)01 (1)02 (1)03 (1)04 (1)05 (1)06 (1)07 (1)08 (1)09 (11)0 (111) (11)2 (11)3 (11)4 (11)5 (11)6 (11)7 (11)8 (11)9 (1)20 (1)21 (1)22 (1)23 (1)24 (1)25 (1)26 (1)27 (1)28 (1)29 (1)30 (1)31 (1)32 (1)33 (1)34 (1)35 (1)36 (1)37 (1)38 (1)39 (1)40 (1)41 (1)42 (1)43 (1)44 (1)45 (1)46 (1)47 (1)48 (1)49 (1)50 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0002.in000077700000000000000000000000001400523266500210502data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0002.tst000066400000000000000000000002001400523266500203340ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1*/(&)/' -n 15 t0002.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0003.good000066400000000000000000000016331400523266500204660ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1*$/(&)/' -n 15 t0003.in) (1) 2() 3() 4() 5() 6() 7() 8() 9() 10() (11) 12() 13() 14() 15() 16() 17() 0:07 1:07 2:07 18() 19() 20() 2(1) 22() 23() 24() 25() 26() 27() 28() 29() 30() 32() 33() 34() 35() 36() 37() 38() 39() 40() 4(1) 42() 43() 44() 45() 46() 47() 48() 49() 50() 5(1) 52() 53() 54() 55() 56() 57() 58() 59() 60() 6(1) 62() 63() 64() 65() 66() 67() 68() 69() 70() 7(1) 72() 73() 74() 75() 76() 77() 78() 79() 80() 8(1) 82() 83() 84() 85() 86() 87() 88() 89() 90() 9(1) 92() 93() 94() 95() 96() 97() 98() 99() 100() 10(1) 102() 103() 104() 105() 106() 107() 108() 109() 110() (111) 112() 113() 114() 115() 116() 117() 118() 119() 120() 12(1) 122() 123() 124() 125() 126() 127() 128() 129() 130() 13(1) 132() 133() 134() 135() 136() 137() 138() 139() 140() 14(1) 142() 143() 144() 145() 146() 147() 148() 149() 150() $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0003.in000077700000000000000000000000001400523266500210512data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0003.tst000066400000000000000000000002011400523266500203360ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1*$/(&)/' -n 15 t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0004.good000066400000000000000000000011601400523266500204620ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/^1+$/(&)/' -n 15 t0004.in) (1) 2 3 4 5 6 7 8 9 10 (11) 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 0:07 1:07 2:07 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 (111) 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0004.in000077700000000000000000000000001400523266500210522data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0004.tst000066400000000000000000000002021400523266500203400ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/^1+$/(&)/' -n 15 t0004.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0005.good000066400000000000000000000013471400523266500204720ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/^1+/(&)/' -n 15 t0005.in) (1) 2 3 4 5 6 7 8 9 (1)0 (11) (1)2 (1)3 (1)4 (1)5 (1)6 (1)7 (1)8 (1)9 20 21 0:07 1:07 2:07 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 (1)00 (1)01 (1)02 (1)03 (1)04 (1)05 (1)06 (1)07 (1)08 (1)09 (11)0 (111) (11)2 (11)3 (11)4 (11)5 (11)6 (11)7 (11)8 (11)9 (1)20 (1)21 (1)22 (1)23 (1)24 (1)25 (1)26 (1)27 (1)28 (1)29 (1)30 (1)31 (1)32 (1)33 (1)34 (1)35 (1)36 (1)37 (1)38 (1)39 (1)40 (1)41 (1)42 (1)43 (1)44 (1)45 (1)46 (1)47 (1)48 (1)49 (1)50 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0005.in000077700000000000000000000000001400523266500210532data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0005.tst000066400000000000000000000002011400523266500203400ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/^1+/(&)/' -n 15 t0005.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0006.good000066400000000000000000000012051400523266500204640ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1+$/(&)/' -n 15 t0006.in) (1) 2 3 4 5 6 7 8 9 10 (11) 12 13 14 15 16 17 18 19 20 2(1) 22 23 24 25 26 27 0:07 1:07 2:07 28 29 30 32 33 34 35 36 37 38 39 40 4(1) 42 43 44 45 46 47 48 49 50 5(1) 52 53 54 55 56 57 58 59 60 6(1) 62 63 64 65 66 67 68 69 70 7(1) 72 73 74 75 76 77 78 79 80 8(1) 82 83 84 85 86 87 88 89 90 9(1) 92 93 94 95 96 97 98 99 100 10(1) 102 103 104 105 106 107 108 109 110 (111) 112 113 114 115 116 117 118 119 120 12(1) 122 123 124 125 126 127 128 129 130 13(1) 132 133 134 135 136 137 138 139 140 14(1) 142 143 144 145 146 147 148 149 150 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0006.in000077700000000000000000000000001400523266500210542data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0006.tst000066400000000000000000000002011400523266500203410ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1+$/(&)/' -n 15 t0006.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0007.good000066400000000000000000000014261400523266500204720ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1/(&)/g' -n 15 t0007.in) (1) 2 3 4 5 6 7 8 9 (1)0 (1)(1) (1)2 (1)3 (1)4 (1)5 (1)6 (1)7 (1)8 (1)9 20 0:07 1:07 2:07 2(1) 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 4(1) 42 43 44 45 46 47 48 49 50 5(1) 52 53 54 55 56 57 58 59 60 6(1) 62 63 64 65 66 67 68 69 70 7(1) 72 73 74 75 76 77 78 79 80 8(1) 82 83 84 85 86 87 88 89 90 9(1) 92 93 94 95 96 97 98 99 (1)00 (1)0(1) (1)02 (1)03 (1)04 (1)05 (1)06 (1)07 (1)08 (1)09 (1)(1)0 (1)(1)(1) (1)(1)2 (1)(1)3 (1)(1)4 (1)(1)5 (1)(1)6 (1)(1)7 (1)(1)8 (1)(1)9 (1)20 (1)2(1) (1)22 (1)23 (1)24 (1)25 (1)26 (1)27 (1)28 (1)29 (1)30 (1)3(1) (1)32 (1)33 (1)34 (1)35 (1)36 (1)37 (1)38 (1)39 (1)40 (1)4(1) (1)42 (1)43 (1)44 (1)45 (1)46 (1)47 (1)48 (1)49 (1)50 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0007.in000077700000000000000000000000001400523266500210552data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0007.tst000066400000000000000000000002001400523266500203410ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1/(&)/g' -n 15 t0007.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0008.good000066400000000000000000000026701400523266500204750ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1*/(&)/g' -n 15 t0008.in) (1) ()2 ()3 ()4 ()5 ()6 ()7 ()8 ()9 (1)()0 (11) (1)()2 (1)()3 (1)()4 (1)()5 ┐ 0:07 1:07 2:07 79:20 (1)()6 (1)()7 (1)()8 (1)()9 ()2()0 ()2(1) ()2()2 ()2()3 ()2()4 ()2()5 ()2()6 ║ 79:20 ()2()7 ()2()8 ()2()9 ()3()0 ()3()2 ()3()3 ()3()4 ()3()5 ()3()6 ()3()7 ()3()8 │ 79:20 ()3()9 ()4()0 ()4(1) ()4()2 ()4()3 ()4()4 ()4()5 ()4()6 ()4()7 ()4()8 ()4()9 │ 79:20 ()5()0 ()5(1) ()5()2 ()5()3 ()5()4 ()5()5 ()5()6 ()5()7 ()5()8 ()5()9 ()6()0 │ 79:20 ()6(1) ()6()2 ()6()3 ()6()4 ()6()5 ()6()6 ()6()7 ()6()8 ()6()9 ()7()0 ()7(1) │ 79:20 ()7()2 ()7()3 ()7()4 ()7()5 ()7()6 ()7()7 ()7()8 ()7()9 ()8()0 ()8(1) ()8()2 │ 79:20 ()8()3 ()8()4 ()8()5 ()8()6 ()8()7 ()8()8 ()8()9 ()9()0 ()9(1) ()9()2 ()9()3 │ 79:20 ()9()4 ()9()5 ()9()6 ()9()7 ()9()8 ()9()9 (1)()0()0 (1)()0(1) (1)()0()2 │ 79:20 (1)()0()3 (1)()0()4 (1)()0()5 (1)()0()6 (1)()0()7 (1)()0()8 (1)()0()9 (11)()0 │ 79:20 (111) (11)()2 (11)()3 (11)()4 (11)()5 (11)()6 (11)()7 (11)()8 (11)()9 │ 79:20 (1)()2()0 (1)()2(1) (1)()2()2 (1)()2()3 (1)()2()4 (1)()2()5 (1)()2()6 │ 79:20 (1)()2()7 (1)()2()8 (1)()2()9 (1)()3()0 (1)()3(1) (1)()3()2 (1)()3()3 │ 79:20 (1)()3()4 (1)()3()5 (1)()3()6 (1)()3()7 (1)()3()8 (1)()3()9 (1)()4()0 │ 79:20 (1)()4(1) (1)()4()2 (1)()4()3 (1)()4()4 (1)()4()5 (1)()4()6 (1)()4()7 ▼ 79:20 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0008.in000077700000000000000000000000001400523266500210562data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0008.tst000066400000000000000000000002011400523266500203430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1*/(&)/g' -n 15 t0008.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0009.good000066400000000000000000000016341400523266500204750ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/1*$/(&)/g' -n 15 t0009.in) (1) 2() 3() 4() 5() 6() 7() 8() 9() 10() (11) 12() 13() 14() 15() 16() 17() 0:07 1:07 2:07 18() 19() 20() 2(1) 22() 23() 24() 25() 26() 27() 28() 29() 30() 32() 33() 34() 35() 36() 37() 38() 39() 40() 4(1) 42() 43() 44() 45() 46() 47() 48() 49() 50() 5(1) 52() 53() 54() 55() 56() 57() 58() 59() 60() 6(1) 62() 63() 64() 65() 66() 67() 68() 69() 70() 7(1) 72() 73() 74() 75() 76() 77() 78() 79() 80() 8(1) 82() 83() 84() 85() 86() 87() 88() 89() 90() 9(1) 92() 93() 94() 95() 96() 97() 98() 99() 100() 10(1) 102() 103() 104() 105() 106() 107() 108() 109() 110() (111) 112() 113() 114() 115() 116() 117() 118() 119() 120() 12(1) 122() 123() 124() 125() 126() 127() 128() 129() 130() 13(1) 132() 133() 134() 135() 136() 137() 138() 139() 140() 14(1) 142() 143() 144() 145() 146() 147() 148() 149() 150() $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0009.in000077700000000000000000000000001400523266500210572data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0009.tst000066400000000000000000000002021400523266500203450ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/1*$/(&)/g' -n 15 t0009.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0010.good000066400000000000000000000012461400523266500204640ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/(.)(.)(.)/\3\2\1/g' \ > -s '#150' -n 15 t0010.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 001 101 201 301 401 501 601 701 801 901 011 111 211 311 411 511 611 711 811 911 021 121 221 321 421 521 621 721 821 921 031 131 231 331 431 531 631 731 831 931 041 141 241 341 441 541 641 741 841 941 051 24:07 25:07 26:07 $ $ echo ":$OUT:" :051: $ exit 0 smenu-0.9.17/tests/substitutions/t0010.in000077700000000000000000000000001400523266500210472data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0010.tst000066400000000000000000000002741400523266500203460ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/(.)(.)(.)/\\3\\2\\1/g' \\ -s '#150' -n 15 t0010.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0011.good000066400000000000000000000016301400523266500204620ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/(.)(.)(.)/\3<-\2->\1/g' \ > -s '#150' -n 15 t0011.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 0<-0->1 1<-0->1 2<-0->1 3<-0->1 4<-0->1 5<-0->1 6<-0->1 7<-0->1 8<-0->1 9<-0->1 0<-1->1 1<-1->1 2<-1->1 3<-1->1 4<-1->1 5<-1->1 6<-1->1 7<-1->1 8<-1->1 9<-1->1 0<-2->1 1<-2->1 2<-2->1 3<-2->1 4<-2->1 5<-2->1 6<-2->1 7<-2->1 8<-2->1 9<-2->1 0<-3->1 1<-3->1 2<-3->1 3<-3->1 4<-3->1 5<-3->1 6<-3->1 7<-3->1 8<-3->1 9<-3->1 0<-4->1 1<-4->1 2<-4->1 3<-4->1 4<-4->1 5<-4->1 6<-4->1 7<-4->1 8<-4->1 9<-4->1 0<-5->1 16:07 17:07 18:07 19:07 20:07 21:07 22:07 $ $ echo ":$OUT:" :0<-5->1: $ exit 0 smenu-0.9.17/tests/substitutions/t0011.in000077700000000000000000000000001400523266500210502data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0011.tst000066400000000000000000000003001400523266500203350ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/(.)(.)(.)/\\3<-\\2->\\1/g' \\ -s '#150' -n 15 t0011.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0012.good000066400000000000000000000025771400523266500204760ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -e 2 -I'/(1+)/(\1)/g' -n 15 \ > t0012.in) (1) 2 3 4 5 6 7 8 9 (1)0 (11) 12 ▶ 0:20 1:07 2:07 3:07 4:07 5:07 6:07 7:07 9:24 10:24 11:24 12:24 13:24 71:24 72:24 73:24 74:24 75:24 76:20 28 29 30 32 33 34 35 36 37 38 39 40 ▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 9:24 10:24 11:24 12:24 13:24 21:24 22:24 23:24 24:24 25:24 76:20 53 54 55 56 57 58 59 60 6(1) 62 63 64 ▶ 0:20 59:24 60:24 61:24 62:24 63:24 76:20 77 78 79 80 8(1) 82 83 84 85 86 87 88 ▶ 0:20 35:24 36:24 37:24 38:24 39:24 76:20 (1)0(1) 102 (1)03 (1)04 (1)05 (1)06 (1)07 (1)08 (1)09 (11)0 (111) 112 ▶ 0:20 9:24 10:24 11:24 12:24 13:24 71:24 72:24 73:24 74:24 75:24 76:20 (11)9 120 121 122 123 124 125 126 127 128 129 (1)30▶ 0:20 9:24 10:24 11:24 12:24 13:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 59:24 60:24 61:24 62:24 63:24 65:24 66:24 67:24 68:24 69:24 76:20 (1)37 (1)38 (1)39 (1)40 (1)4(1) 142 (1)43 (1)44 (1)45 (1)46 (1)47 (1)48▶ 0:20 35:24 36:24 37:24 38:24 39:24 76:20 $ $ echo ":$OUT:" :(1): $ exit 0 smenu-0.9.17/tests/substitutions/t0012.in000077700000000000000000000000001400523266500210512data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0012.tst000066400000000000000000000002201400523266500203370ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -e 2 -I'/(1+)/(\\1)/g' -n 15 \\ t0012.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0013.good000066400000000000000000000053531400523266500204720ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -I'/(1+)/(\1)/g' -n 15 \ > t0013.in) 1 2 3 4 5 6 7 8 9 10 11 (1)2 13 ▶ 0:20 1:24 2:24 3:24 5:07 6:07 7:07 8:07 9:07 11:24 12:24 13:24 14:24 15:24 16:24 17:24 19:24 20:24 21:24 22:24 23:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 73:24 74:24 75:24 76:20 28 29 30 32 33 34 35 36 37 38 39 40 41 ▶ 0:20 11:24 12:24 13:24 14:24 15:24 16:24 17:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 67:24 68:24 69:24 70:24 71:24 73:24 74:24 75:24 76:20 53 54 55 56 57 58 59 60 61 62 63 64 65 ▶ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 8:24 9:24 11:24 12:24 13:24 14:24 15:24 16:24 17:24 19:24 20:24 21:24 22:24 23:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 61:24 62:24 63:24 64:24 65:24 67:24 68:24 69:24 70:24 71:24 73:24 74:24 75:24 76:20 77 78 79 80 81 82 83 84 85 86 87 88 89 ▶ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 8:24 9:24 11:24 12:24 13:24 14:24 15:24 16:24 17:24 19:24 20:24 21:24 22:24 23:24 25:24 26:24 27:24 28:24 29:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 67:24 68:24 69:24 70:24 71:24 73:24 74:24 75:24 76:20 101 (1)02 103 104 105 106 107 108 109 110 111 (11)2 113▶ 0:20 1:24 2:24 3:24 11:24 12:24 13:24 14:24 15:24 16:24 17:24 19:24 20:24 21:24 22:24 23:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 73:24 74:24 75:24 76:20 119 (1)20 (1)2(1) (1)22 (1)23 (1)24 (1)25 (1)26 (1)27 (1)28 (1)29 130 131▶ 0:20 1:24 2:24 3:24 67:24 68:24 69:24 70:24 71:24 73:24 74:24 75:24 76:20 137 138 139 140 141 (1)42 143 144 145 146 147 148 149▶ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 8:24 9:24 11:24 12:24 13:24 14:24 15:24 16:24 17:24 19:24 20:24 21:24 22:24 23:24 25:24 26:24 27:24 28:24 29:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 67:24 68:24 69:24 70:24 71:24 73:24 74:24 75:24 76:20 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/substitutions/t0013.in000077700000000000000000000000001400523266500210522data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0013.tst000066400000000000000000000002201400523266500203400ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -I'/(1+)/(\\1)/g' -n 15 \\ t0013.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0014.good000066400000000000000000000053651400523266500204760ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -E'/(1+)/(\1)/g' -n 15 \ > t0014.in) (1) 2 3 4 5 6 7 8 9 (1)0 (11) 12 ▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 9:07 10:07 11:07 12:07 13:07 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 59:24 60:24 61:24 62:24 63:24 65:24 66:24 67:24 68:24 69:24 76:20 28 29 30 32 33 34 35 36 37 38 39 40 ▶ 0:20 15:24 16:24 17:24 18:24 19:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 59:24 60:24 61:24 62:24 63:24 65:24 66:24 67:24 68:24 69:24 71:24 72:24 73:24 74:24 75:24 76:20 53 54 55 56 57 58 59 60 6(1) 62 63 64 ▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 9:24 10:24 11:24 12:24 13:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 65:24 66:24 67:24 68:24 69:24 71:24 72:24 73:24 74:24 75:24 76:20 77 78 79 80 8(1) 82 83 84 85 86 87 88 ▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 9:24 10:24 11:24 12:24 13:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 59:24 60:24 61:24 62:24 63:24 65:24 66:24 67:24 68:24 69:24 71:24 72:24 73:24 74:24 75:24 76:20 (1)0(1) 102 (1)03 (1)04 (1)05 (1)06 (1)07 (1)08 (1)09 (11)0 (111) 112 ▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 35:24 36:24 37:24 38:24 39:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 59:24 60:24 61:24 62:24 63:24 65:24 66:24 67:24 68:24 69:24 76:20 (11)9 120 121 122 123 124 125 126 127 128 129 (1)30▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 71:24 72:24 73:24 74:24 75:24 76:20 (1)37 (1)38 (1)39 (1)40 (1)4(1) 142 (1)43 (1)44 (1)45 (1)46 (1)47 (1)48▶ 0:20 1:24 2:24 3:24 4:24 5:24 6:24 7:24 9:24 10:24 11:24 12:24 13:24 15:24 16:24 17:24 18:24 19:24 21:24 22:24 23:24 24:24 25:24 27:24 28:24 29:24 30:24 31:24 32:24 33:24 41:24 42:24 43:24 44:24 45:24 47:24 48:24 49:24 50:24 51:24 53:24 54:24 55:24 56:24 57:24 59:24 60:24 61:24 62:24 63:24 65:24 66:24 67:24 68:24 69:24 71:24 72:24 73:24 74:24 75:24 76:20 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/substitutions/t0014.in000077700000000000000000000000001400523266500210532data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0014.tst000066400000000000000000000002201400523266500203410ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -E'/(1+)/(\\1)/g' -n 15 \\ t0014.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0015.good000066400000000000000000000025051400523266500204700ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -e 2 -E'/(1+)/(\1)/g' -n 15 \ > t0015.in) 1 2 3 4 5 6 7 8 9 10 11 (1)2 13 ▶ 0:20 1:07 2:07 3:07 5:24 6:24 7:24 8:24 9:24 67:24 68:24 69:24 70:24 71:24 76:20 28 29 30 32 33 34 35 36 37 38 39 40 41 ▶ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 8:24 9:24 19:24 20:24 21:24 22:24 23:24 76:20 53 54 55 56 57 58 59 60 61 62 63 64 65 ▶ 0:20 55:24 56:24 57:24 58:24 59:24 76:20 77 78 79 80 81 82 83 84 85 86 87 88 89 ▶ 0:20 31:24 32:24 33:24 34:24 35:24 76:20 101 (1)02 103 104 105 106 107 108 109 110 111 (11)2 113▶ 0:20 5:24 6:24 7:24 8:24 9:24 67:24 68:24 69:24 70:24 71:24 76:20 119 (1)20 (1)2(1) (1)22 (1)23 (1)24 (1)25 (1)26 (1)27 (1)28 (1)29 130 131▶ 0:20 5:24 6:24 7:24 8:24 9:24 11:24 12:24 13:24 14:24 15:24 16:24 17:24 19:24 20:24 21:24 22:24 23:24 25:24 26:24 27:24 28:24 29:24 31:24 32:24 33:24 34:24 35:24 37:24 38:24 39:24 40:24 41:24 43:24 44:24 45:24 46:24 47:24 49:24 50:24 51:24 52:24 53:24 55:24 56:24 57:24 58:24 59:24 61:24 62:24 63:24 64:24 65:24 76:20 137 138 139 140 141 (1)42 143 144 145 146 147 148 149▶ 0:20 31:24 32:24 33:24 34:24 35:24 76:20 $ $ echo ":$OUT:" :1: $ exit 0 smenu-0.9.17/tests/substitutions/t0015.in000077700000000000000000000000001400523266500210542data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0015.tst000066400000000000000000000002201400523266500203420ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -e 2 -E'/(1+)/(\\1)/g' -n 15 \\ t0015.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0016.good000066400000000000000000000021561400523266500204730ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -e 2 -E/1/A/g -I/1/B/g -n 6 \ > t0016.in) B 2 3 4 5 6 7 8 9 B0 BB A2 B3 B4 B5 B6 B7 B8 B9 20▶┐ 0:20 1:07 2:07 3:07 5:24 6:24 7:24 45:24 46:24 47:24 76:24 77:24 78:20 79:20 28 29 30 32 33 34 35 36 37 38 39 40 4B 42 43 44 45 46 47 48▶║ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 13:24 14:24 15:24 53:24 54:24 55:24 78:20 79:20 53 54 55 56 57 58 59 60 6B 62 63 64 65 66 67 68 69 70 7B 72▶│ 0:20 37:24 38:24 39:24 76:24 77:24 78:20 79:20 77 78 79 80 8B 82 83 84 85 86 87 88 89 90 9B 92 93 94 95 96▶│ 0:20 21:24 22:24 23:24 61:24 62:24 63:24 78:20 79:20 B0B A02 B03 B04 B05 B06 B07 B08 B09 BB0 BBB AA2 BB3 BB4 BB5 BB6 BB7 BB8 │ 0:20 5:24 6:24 7:24 45:24 46:24 47:24 79:20 BB9 A20 A2A A22 A23 A24 A25 A26 A27 A28 A29 B30 B3B A32 B33 B34 B35 B36 ▼ 0:20 5:24 6:24 7:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 53:24 54:24 55:24 79:20 $ $ echo ":$OUT:" :B: $ exit 0 smenu-0.9.17/tests/substitutions/t0016.in000077700000000000000000000000001400523266500210552data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0016.tst000066400000000000000000000002171400523266500203510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -e 2 -E/1/A/g -I/1/B/g -n 6 \\ t0016.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0017.good000066400000000000000000000044241400523266500204740ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -E/1/A/g -I/1/B/g -n 6 \ > t0017.in) A 2 3 4 5 6 7 8 9 A0 AA B2 A3 A4 A5 A6 A7 A8 A9 20▶┐ 0:20 1:24 2:24 3:24 5:07 6:07 7:07 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 78:20 79:20 28 29 30 32 33 34 35 36 37 38 39 40 4A 42 43 44 45 46 47 48▶║ 0:20 9:24 10:24 11:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 45:24 46:24 47:24 49:24 50:24 51:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 76:24 77:24 78:20 79:20 53 54 55 56 57 58 59 60 6A 62 63 64 65 66 67 68 69 70 7A 72▶│ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 41:24 42:24 43:24 45:24 46:24 47:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 78:20 79:20 77 78 79 80 8A 82 83 84 85 86 87 88 89 90 9A 92 93 94 95 96▶│ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 45:24 46:24 47:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 76:24 77:24 78:20 79:20 A0A B02 A03 A04 A05 A06 A07 A08 A09 AA0 AAA BB2 AA3 AA4 AA5 AA6 AA7 AA8 │ 0:20 1:24 2:24 3:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 79:20 AA9 B20 B2B B22 B23 B24 B25 B26 B27 B28 B29 A30 A3A B32 A33 A34 A35 A36 ▼ 0:20 1:24 2:24 3:24 45:24 46:24 47:24 49:24 50:24 51:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 79:20 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/substitutions/t0017.in000077700000000000000000000000001400523266500210562data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0017.tst000066400000000000000000000002171400523266500203520ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -E/1/A/g -I/1/B/g -n 6 \\ t0017.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0018.good000066400000000000000000000045061400523266500204760ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -E/1/A/g -I/1/B/g \ > -S/1/C/g -n 6 t0018.in) C 2 3 4 5 6 7 8 9 C0 CC C2 C3 C4 C5 C6 C7 C8 C9 20▶┐ 0:20 1:24 2:24 3:24 5:07 6:07 7:07 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 78:20 79:20 28 29 30 32 33 34 35 36 37 38 39 40 4C 42 43 44 45 46 47 48▶║ 0:20 9:24 10:24 11:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 45:24 46:24 47:24 49:24 50:24 51:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 76:24 77:24 78:20 79:20 53 54 55 56 57 58 59 60 6C 62 63 64 65 66 67 68 69 70 7C 72▶│ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 41:24 42:24 43:24 45:24 46:24 47:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 78:20 79:20 77 78 79 80 8C 82 83 84 85 86 87 88 89 90 9C 92 93 94 95 96▶│ 0:20 1:24 2:24 3:24 5:24 6:24 7:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 45:24 46:24 47:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 65:24 66:24 67:24 69:24 70:24 71:24 73:24 74:24 76:24 77:24 78:20 79:20 C0C C02 C03 C04 C05 C06 C07 C08 C09 CC0 CCC CC2 CC3 CC4 CC5 CC6 CC7 CC8 │ 0:20 1:24 2:24 3:24 9:24 10:24 11:24 13:24 14:24 15:24 17:24 18:24 19:24 21:24 22:24 23:24 25:24 26:24 27:24 29:24 30:24 31:24 33:24 34:24 35:24 37:24 38:24 39:24 41:24 42:24 43:24 49:24 50:24 51:24 53:24 54:24 55:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 79:20 CC9 C20 C2C C22 C23 C24 C25 C26 C27 C28 C29 C30 C3C C32 C33 C34 C35 C36 ▼ 0:20 1:24 2:24 3:24 45:24 46:24 47:24 49:24 50:24 51:24 57:24 58:24 59:24 61:24 62:24 63:24 65:24 66:24 67:24 69:24 70:24 71:24 79:20 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/substitutions/t0018.in000077700000000000000000000000001400523266500210572data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0018.tst000066400000000000000000000003011400523266500203450ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c -i 2 -E/1/A/g -I/1/B/g \\ -S/1/C/g -n 6 t0018.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0019.good000066400000000000000000000005531400523266500204750ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -l -S'/1.*//' -n 4 t0019.in) 2 3 4 5 6 7 8 9 20 2 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 4 42 43 44 45 46 47 48 49 50 5 52 53 54 55 56 57 58 59 60 6 62 63 64 65 66 67 68 69 70 7 72 73 74 75 76 77 78 79 80 8 82 83 84 85 86 87 88 89 90 9 92 93 94 95 96 97 98 99 35:07 36:07 $ $ echo ":$OUT:" :89: $ exit 0 smenu-0.9.17/tests/substitutions/t0019.in000077700000000000000000000000001400523266500210602data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0019.tst000066400000000000000000000002221400523266500203500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -l -S'/1.*//' -n 4 t0019.in) \S[150]\s[150]lllllllllljjjlllll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0020.good000066400000000000000000000005721400523266500204660ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t -S'/1.*//' -n 4 t0020.in) 2 3 4 5 6 7 8 9 20 2 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 4 42 43 44 45 46 47 48 49 50 5 52 53 54 55 56 57 58 59 60 6 62 63 64 65 66 67 68 69 70 7 72 73 74 75 76 77 78 79 80 8 82 83 84 85 86 87 88 89 90 45:07 46:07 9 92 93 94 95 96 97 98 99 $ $ echo ":$OUT:" :80: $ exit 0 smenu-0.9.17/tests/substitutions/t0020.in000077700000000000000000000000001400523266500210502data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0020.tst000066400000000000000000000002211400523266500203370ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t -S'/1.*//' -n 4 t0020.in) \S[150]\s[150]lllllllllljjlllll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0021.good000066400000000000000000000023711400523266500204660ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -S'/(1)/\[1 \1 \1\]1/g' \ > -n 20 t0021.in) [1 1 1]1 2 3 4 5 6 7 8 9 [1 1 1]10 [1 1 1]1[1 1 1]1 [1 1 1]12 [1 1 1]13 0:07 1:07 2:07 3:07 4:07 5:07 6:07 7:07 [1 1 1]14 [1 1 1]15 [1 1 1]16 [1 1 1]17 [1 1 1]18 [1 1 1]19 20 2[1 1 1]1 22 23 24 25 26 27 28 29 30 32 33 34 35 36 37 38 39 40 4[1 1 1]1 42 43 44 45 46 47 48 49 50 5[1 1 1]1 52 53 54 55 56 57 58 59 60 6[1 1 1]1 62 63 64 65 66 67 68 69 70 7[1 1 1]1 72 73 74 75 76 77 78 79 80 8[1 1 1]1 82 83 84 85 86 87 88 89 90 9[1 1 1]1 92 93 94 95 96 97 98 99 [1 1 1]100 [1 1 1]10[1 1 1]1 [1 1 1]102 [1 1 1]103 [1 1 1]104 [1 1 1]105 [1 1 1]106 [1 1 1]107 [1 1 1]108 [1 1 1]109 [1 1 1]1[1 1 1]10 [1 1 1]1[1 1 1]1[1 1 1]1 [1 1 1]1[1 1 1]12 [1 1 1]1[1 1 1]13 [1 1 1]1[1 1 1]14 [1 1 1]1[1 1 1]15 [1 1 1]1[1 1 1]16 [1 1 1]1[1 1 1]17 [1 1 1]1[1 1 1]18 [1 1 1]1[1 1 1]19 [1 1 1]120 [1 1 1]12[1 1 1]1 [1 1 1]122 [1 1 1]123 [1 1 1]124 [1 1 1]125 [1 1 1]126 [1 1 1]127 [1 1 1]128 [1 1 1]129 [1 1 1]130 [1 1 1]13[1 1 1]1 [1 1 1]132 [1 1 1]133 [1 1 1]134 [1 1 1]135 [1 1 1]136 [1 1 1]137 [1 1 1]138 [1 1 1]139 [1 1 1]140 [1 1 1]14[1 1 1]1 [1 1 1]142 [1 1 1]143 [1 1 1]144 [1 1 1]145 [1 1 1]146 [1 1 1]147 [1 1 1]148 [1 1 1]149 [1 1 1]150 $ $ echo ":$OUT:" :[1 1 1]1: $ exit 0 smenu-0.9.17/tests/substitutions/t0021.in000077700000000000000000000000001400523266500210512data1ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0021.tst000066400000000000000000000002221400523266500203410ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -S'/(1)/\\[1 \\1 \\1\\]1/g' \\ -n 20 t0021.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0022.good000066400000000000000000000001311400523266500204570ustar00rootroot00000000000000$ OUT=$(smenu -S/a// t0022.in) bc bc bc 3:07 4:07 $ $ echo ":$OUT:" :bc: $ exit 0 smenu-0.9.17/tests/substitutions/t0022.in000077700000000000000000000000001400523266500210532data2ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0022.tst000066400000000000000000000001441400523266500203450ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -S/a// t0022.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0023.good000066400000000000000000000001111400523266500204560ustar00rootroot00000000000000$ OUT=$(smenu -S/a// -c t0023.in) $ $ $ echo ":$OUT:" :: $ exit 0 smenu-0.9.17/tests/substitutions/t0023.in000077700000000000000000000000001400523266500210542data2ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0023.tst000066400000000000000000000001461400523266500203500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -S/a// -c t0023.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0024.good000066400000000000000000000001451400523266500204660ustar00rootroot00000000000000$ OUT=$(smenu '-S/a/ /' t0024.in) bc b c bc 4:07 5:07 6:07 $ $ echo ":$OUT:" :b c: $ exit 0 smenu-0.9.17/tests/substitutions/t0024.in000077700000000000000000000000001400523266500210552data2ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0024.tst000066400000000000000000000001471400523266500203520ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-S/a/ /' t0024.in) \S[150]\s[150]l\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0025.good000066400000000000000000000001351400523266500204660ustar00rootroot00000000000000$ OUT=$(smenu '-S/a/ /' -c t0025.in) bc b c bc 0:07 $ $ echo ":$OUT:" :: $ exit 0 smenu-0.9.17/tests/substitutions/t0025.in000077700000000000000000000000001400523266500210562data2ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0025.tst000066400000000000000000000001511400523266500203460ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-S/a/ /' -c t0025.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0026.good000066400000000000000000000001551400523266500204710ustar00rootroot00000000000000$ OUT=$(smenu '-S/a/X/i' -c t0026.in) Xbc XBC Xab XAA 0:07 1:07 2:07 $ $ echo ":$OUT:" :Xbc: $ exit 0 smenu-0.9.17/tests/substitutions/t0026.in000077700000000000000000000000001400523266500210602data3ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0026.tst000066400000000000000000000001521400523266500203500ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-S/a/X/i' -c t0026.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0027.good000066400000000000000000000001561400523266500204730ustar00rootroot00000000000000$ OUT=$(smenu '-S/a/X/iv' -c t0027.in) Xbc XBC Xab XAA 0:07 1:07 2:07 $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/substitutions/t0027.in000077700000000000000000000000001400523266500210612data3ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0027.tst000066400000000000000000000001531400523266500203520ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-S/a/X/iv' -c t0027.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0028.good000066400000000000000000000001561400523266500204740ustar00rootroot00000000000000$ OUT=$(smenu '-S/a/X/ig' -c t0028.in) Xbc XBC XXb XXX 0:07 1:07 2:07 $ $ echo ":$OUT:" :Xbc: $ exit 0 smenu-0.9.17/tests/substitutions/t0028.in000077700000000000000000000000001400523266500210622data3ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0028.tst000066400000000000000000000001531400523266500203530ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-S/a/X/ig' -c t0028.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0029.good000066400000000000000000000001651400523266500204750ustar00rootroot00000000000000$ OUT=$(smenu -S/a/X/isg -S/b/Y/ -c t0029.in) Xbc XBC XXb XXX 0:07 1:07 2:07 $ $ echo ":$OUT:" :Xbc: $ exit 0 smenu-0.9.17/tests/substitutions/t0029.in000077700000000000000000000000001400523266500210632data3ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0029.tst000066400000000000000000000001621400523266500203540ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -S/a/X/isg -S/b/Y/ -c t0029.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0030.good000066400000000000000000000001641400523266500204640ustar00rootroot00000000000000$ OUT=$(smenu -S/a/X/ig -S/b/Y/ -c t0030.in) XYc XBC XXY XXX 0:07 1:07 2:07 $ $ echo ":$OUT:" :XYc: $ exit 0 smenu-0.9.17/tests/substitutions/t0030.in000077700000000000000000000000001400523266500210532data3ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0030.tst000066400000000000000000000001611400523266500203430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -S/a/X/ig -S/b/Y/ -c t0030.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/substitutions/t0031.good000066400000000000000000000001621400523266500204630ustar00rootroot00000000000000$ OUT=$(smenu -S/a/A/sg -S/A/a/g t0031.in) Abc aBC AAb aaa 0:07 1:07 2:07 $ $ echo ":$OUT:" :Abc: $ exit 0 smenu-0.9.17/tests/substitutions/t0031.in000077700000000000000000000000001400523266500210542data3ustar00rootroot00000000000000smenu-0.9.17/tests/substitutions/t0031.tst000066400000000000000000000001571400523266500203510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -S/a/A/sg -S/A/a/g t0031.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/000077500000000000000000000000001400523266500172425ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/data1000066400000000000000000000000411400523266500201520ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 smenu-0.9.17/tests/tabulating_mode/data2000066400000000000000000000000411400523266500201530ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 smenu-0.9.17/tests/tabulating_mode/data3000066400000000000000000000001121400523266500201530ustar00rootroot00000000000000ab abc éà ùùù €€€€ §§§§ → ↓ ← ¦¦¦ ßßßxßßß smenu-0.9.17/tests/tabulating_mode/data4000066400000000000000000000000411400523266500201550ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 smenu-0.9.17/tests/tabulating_mode/data5000066400000000000000000000000401400523266500201550ustar00rootroot00000000000000ab abc éà ùùù €€€€ smenu-0.9.17/tests/tabulating_mode/data6000066400000000000000000000001431400523266500201620ustar00rootroot000000000000001 2 3 4 5 6 7 8 9 10 11 12 13 14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 smenu-0.9.17/tests/tabulating_mode/t0001.good000066400000000000000000000007021400523266500206570ustar00rootroot00000000000000$ OUT=$(smenu -t 4 -w t0001.in) 1 2 3 4 5 6 7 8 19:07 20:07 21:07 22:07 23:07 24:07 25:07 26:07 27:07 28:07 29:07 30:07 31:07 32:07 33:07 34:07 35:07 36:07 9 10 11 12 13 14 $ $ echo ":$OUT:" :6: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0001.in000077700000000000000000000000001400523266500212462data1ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0001.tst000066400000000000000000000001461400523266500205430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -t 4 -w t0001.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0002.good000066400000000000000000000001751400523266500206640ustar00rootroot00000000000000$ OUT=$(smenu -t 4 t0002.in) 1 2 3 4 5 6 7 8 3:07 4:07 9 10 11 12 13 14 $ $ echo ":$OUT:" :6: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0002.in000077700000000000000000000000001400523266500212472data1ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0002.tst000066400000000000000000000001431400523266500205410ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -t 4 t0002.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0003.good000066400000000000000000000004001400523266500206540ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t 10 t0003.in) ab abc éà ùùù €€€€ §§§§ → ↓ ← 40:07 41:07 42:07 43:07 44:07 45:07 46:07 ¦¦¦ ßßßxßßß $ $ echo ":$OUT:" :§§§§: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0003.in000077700000000000000000000000001400523266500212522data3ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0003.tst000066400000000000000000000001731400523266500205450ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t 10 t0003.in) \S[150]\s[150]lllllkkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0004.good000066400000000000000000000004031400523266500206600ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t 10 -w t0004.in) ab abc éà ùùù €€€€ §§§§ → ↓ ← 40:07 41:07 42:07 43:07 44:07 45:07 46:07 ¦¦¦ ßßßxßßß $ $ echo ":$OUT:" :§§§§: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0004.in000077700000000000000000000000001400523266500212532data3ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0004.tst000066400000000000000000000001761400523266500205510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t 10 -w t0004.in) \S[150]\s[150]lllllkkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0005.good000066400000000000000000000006001400523266500206600ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t 3 -w t0005.in) ab abc éà 26:07 27:07 28:07 29:07 30:07 31:07 32:07 33:07 34:07 35:07 36:07 37:07 38:07 39:07 40:07 41:07 42:07 43:07 44:07 45:07 46:07 47:07 48:07 49:07 50:07 ùùù €€€€ $ $ echo ":$OUT:" :abc: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0005.in000077700000000000000000000000001400523266500212562data5ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0005.tst000066400000000000000000000001751400523266500205510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t 3 -w t0005.in) \S[150]\s[150]lllllkkk\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0006.good000066400000000000000000000002111400523266500206570ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t -- t0006.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 3:07 4:07 $ $ echo ":$OUT:" :2: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0006.in000077700000000000000000000000001400523266500212532data1ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0006.tst000066400000000000000000000001651400523266500205510ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t -- t0006.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0007.good000066400000000000000000000002231400523266500206630ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -t -L'\u0a' t0007.in) 1 2 3 4 5 6 7 8 3:07 4:07 9 10 11 12 13 14 $ $ echo ":$OUT:" :7: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0007.in000077700000000000000000000000001400523266500212542data1ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0007.tst000066400000000000000000000001741400523266500205520ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -t -L'\\u0a' t0007.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0010.good000066400000000000000000000001721400523266500206600ustar00rootroot00000000000000$ OUT=$(smenu -t 9 t0010.in) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 3:07 4:07 $ $ echo ":$OUT:" :11: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0010.in000077700000000000000000000000001400523266500212512data4ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0010.tst000066400000000000000000000001431400523266500205400ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -t 9 t0010.in) \S[150]\s[150]lj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0011.good000066400000000000000000000003511400523266500206600ustar00rootroot00000000000000$ OUT=$(smenu -tab 5 --line-delimiters 6 t0011.in) 1 2 3 4 5 ┐ 16:20 7 8 9 10 11 │ 16:20 12 13 14 1 2 ║ 16:20 3 4 5 │ 16:20 7 8 9 10 11 ▼ 3:07 4:07 16:20 $ $ echo ":$OUT:" :8: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0011.in000077700000000000000000000000001400523266500212542data6ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0011.tst000066400000000000000000000002001400523266500205330ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -tab 5 --line-delimiters 6 t0011.in) \S[150]\s[150]ljljljhj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tabulating_mode/t0012.good000066400000000000000000000003241400523266500206610ustar00rootroot00000000000000$ OUT=$(smenu -tab 5 t0012.in) 1 2 3 4 5 ┐ 16:20 6 7 8 9 10 │ 16:20 11 12 13 14 1 ║ 16:20 2 3 4 5 6 │ 16:20 7 8 9 10 11 ▼ 6:07 7:07 16:20 $ $ echo ":$OUT:" :9: $ exit 0 smenu-0.9.17/tests/tabulating_mode/t0012.in000077700000000000000000000000001400523266500212552data6ustar00rootroot00000000000000smenu-0.9.17/tests/tabulating_mode/t0012.tst000066400000000000000000000001531400523266500205430ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -tab 5 t0012.in) \S[150]\s[150]ljljljhj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/000077500000000000000000000000001400523266500155245ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/data1000066400000000000000000000000301400523266500164320ustar00rootroot00000000000000a b c d e f g h u j k l smenu-0.9.17/tests/tagging/data2000066400000000000000000000000201400523266500164320ustar00rootroot00000000000000" a " "b " " c" smenu-0.9.17/tests/tagging/t0001.good000066400000000000000000000001761400523266500171460ustar00rootroot00000000000000$ OUT=$(smenu -T " " t0001.in) a b c d e f g h u j k l 2:04 6:04 8:07 10:04 14:04 $ $ echo ":$OUT:" :b d f h: $ exit 0 smenu-0.9.17/tests/tagging/t0001.in000077700000000000000000000000001400523266500175302data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0001.tst000066400000000000000000000001611400523266500170220ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -T " " t0001.in) \S[150]\s[150]ltlltlltllthhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0002.good000066400000000000000000000001761400523266500171470ustar00rootroot00000000000000$ OUT=$(smenu -P " " t0002.in) a b c d e f g h u j k l 2:04 6:04 8:07 10:04 14:04 $ $ echo ":$OUT:" :b d f h: $ exit 0 smenu-0.9.17/tests/tagging/t0002.in000077700000000000000000000000001400523266500175312data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0002.tst000066400000000000000000000001611400523266500170230ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -P " " t0002.in) \S[150]\s[150]ltlltlltllthhh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0003.good000066400000000000000000000001421400523266500171410ustar00rootroot00000000000000$ OUT=$(smenu -T " " t0003.in) a b c d e f g h u j k l 0:07 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/tagging/t0003.in000077700000000000000000000000001400523266500175322data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0003.tst000066400000000000000000000001701400523266500170240ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -T " " t0003.in) \S[150]\s[150]ltlltlltthhthhthhthht\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0004.good000066400000000000000000000001421400523266500171420ustar00rootroot00000000000000$ OUT=$(smenu -P " " t0004.in) a b c d e f g h u j k l 0:07 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/tagging/t0004.in000077700000000000000000000000001400523266500175332data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0004.tst000066400000000000000000000001701400523266500170250ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -P " " t0004.in) \S[150]\s[150]ltlltlltthhthhthhthht\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0005.good000066400000000000000000000002211400523266500171410ustar00rootroot00000000000000$ OUT=$(smenu -T\\ue296b8 t0005.in) a b c d e f g h u j k l 0:04 2:07 4:04 6:04 8:04 10:04 $ $ echo ":$OUT:" :a▸c▸d▸e▸f: $ exit 0 smenu-0.9.17/tests/tagging/t0005.in000077700000000000000000000000001400523266500175342data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0005.tst000066400000000000000000000001751400523266500170330ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -T\\\\ue296b8 t0005.in) \S[150]\s[150]ltlltllththhththhtl\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0006.good000066400000000000000000000002211400523266500171420ustar00rootroot00000000000000$ OUT=$(smenu -P\\ue296b8 t0006.in) a b c d e f g h u j k l 0:04 2:07 4:04 6:04 8:04 10:04 $ $ echo ":$OUT:" :d▸f▸e▸c▸a: $ exit 0 smenu-0.9.17/tests/tagging/t0006.in000077700000000000000000000000001400523266500175352data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0006.tst000066400000000000000000000001751400523266500170340ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -P\\\\ue296b8 t0006.in) \S[150]\s[150]ltlltllththhththhtl\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0007.good000066400000000000000000000002021400523266500171420ustar00rootroot00000000000000$ OUT=$(smenu -c -P\\ue296b8 t0007.in) a b c d 6:0407 e f g h u j k l 0:04 2:04 $ $ echo ":$OUT:" :u▸j▸d: $ exit 0 smenu-0.9.17/tests/tagging/t0007.in000077700000000000000000000000001400523266500175362data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0007.tst000066400000000000000000000002041400523266500170260ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -P\\\\ue296b8 t0007.in) \S[150]\s[150]lllltllthhtjtlthhhthhht\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0008.good000066400000000000000000000001631400523266500171510ustar00rootroot00000000000000$ OUT=$(smenu -k -P: t0008.in) a b c 0:0407 1:0407 2:0407 7:04 8:04 $ $ echo ":$OUT:" : c: a : $ exit 0 smenu-0.9.17/tests/tagging/t0008.in000077700000000000000000000000001400523266500175402data2ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0008.tst000066400000000000000000000001561400523266500170350ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -k -P: t0008.in) \S[150]\s[150]llththtlthh\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0009.good000066400000000000000000000001741400523266500171540ustar00rootroot00000000000000$ OUT=$(smenu -c -T " " t0009.in) a b c d e f g h 2:07 4:04 6:04 u j k l 0:04 $ $ echo ":$OUT:" :g h u: $ exit 0 smenu-0.9.17/tests/tagging/t0009.in000077700000000000000000000000001400523266500175402data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0009.tst000066400000000000000000000001561400523266500170360ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -T " " t0009.in) \S[150]\s[150]jjththth\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0010.good000066400000000000000000000001751400523266500171450ustar00rootroot00000000000000$ OUT=$(smenu -c -T -p t0010.in) a b c d e f g h 2:07 4:04 6:04 u j k l 0:04 $ $ echo ":$OUT:" :f g h u: $ exit 0 smenu-0.9.17/tests/tagging/t0010.in000077700000000000000000000000001400523266500175302data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0010.tst000066400000000000000000000001551400523266500170250ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -T -p t0010.in) \S[150]\s[150]jjththth\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0011.good000066400000000000000000000001741400523266500171450ustar00rootroot00000000000000$ OUT=$(smenu -c -P " " t0011.in) a b c d e f g h 2:07 4:04 6:04 u j k l 0:04 $ $ echo ":$OUT:" :u h g: $ exit 0 smenu-0.9.17/tests/tagging/t0011.in000077700000000000000000000000001400523266500175312data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0011.tst000066400000000000000000000001561400523266500170270ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -P " " t0011.in) \S[150]\s[150]jjththth\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0012.good000066400000000000000000000001751400523266500171470ustar00rootroot00000000000000$ OUT=$(smenu -c -P -p t0012.in) a b c d e f g h 2:07 4:04 6:04 u j k l 0:04 $ $ echo ":$OUT:" :u h g f: $ exit 0 smenu-0.9.17/tests/tagging/t0012.in000077700000000000000000000000001400523266500175322data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0012.tst000066400000000000000000000001551400523266500170270ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -P -p t0012.in) \S[150]\s[150]jjththth\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/tagging/t0013.good000066400000000000000000000004111400523266500171410ustar00rootroot00000000000000$ OUT=$(smenu -c -P -N'b|d|g' -- t0013.in) a 1) b c 2) d 7:01 8:01 9:01 10:01 21:01 22:01 23:01 24:01 e f 3) g h 12:07 14:01 15:01 16:01 17:01 19:04 26:04 u j k l 5:04 $ $ echo ":$OUT:" :u h g: $ exit 0 smenu-0.9.17/tests/tagging/t0013.in000077700000000000000000000000001400523266500175332data1ustar00rootroot00000000000000smenu-0.9.17/tests/tagging/t0013.tst000066400000000000000000000001671400523266500170330ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -c -P -N'b|d|g' -- t0013.in) \S[150]\s[150]jjththth\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/test.sh000066400000000000000000000050641400523266500154240ustar00rootroot00000000000000#!/usr/bin/env bash # Find backwards for the directory where test.sh is # """"""""""""""""""""""""""""""""""""""""""""""""" upsearch () { slashes=$(echo $PWD | tr -cd \/) directory="$PWD" n=${#slashes} while [ $n -gt 0 ]; do test -e "$directory/$1" && echo "$directory" && return directory="$directory/.." n=$(expr $n - 1) done } [ -z "$DIR" ] && DIR=$(upsearch test.sh) && export DIR if [ ! -f $1.tst ]; then echo "Unknown test $1" exit 1 fi if [ ! -f $1.in ]; then echo "Unknown input file $1" exit 1 fi LOG=${PWD}.log PTYLIE=${PTYLIE_PATH:+${PTYLIE_PATH}/}ptylie HVLT=${HLVT_PATH:+${HLVT_PATH}/}hlvt BL=$(uname -s).bl # Force a clean locale environment # """""""""""""""""""""""""""""""" export LANG=en_US.UTF-8 export LC_CTYPE= export LC_NUMERIC= export LC_TIME= export LC_COLLATE= export LC_MONETARY= export LC_MESSAGES= export LC_PAPER= export LC_NAME= export LC_ADDRESS= export LC_TELEPHONE= export LC_MEASUREMENT= export LC_IDENTIFICATION= export LC_ALL= # Check for the presence of required programs # """"""""""""""""""""""""""""""""""""""""""" if ! which smenu >/dev/null 2>&1; then echo "smenu was not found, please install it. Aborting." exit 1 fi for PROG in $PTYLIE $HLVT; do if ! which $PROG >/dev/null 2>&1; then echo "The required $PROG program was not found, aborting." exit 1 fi done # Ignore blacklisted tests for this OS. # These tests probably need a fixed version of ptylie to work # """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" if [ -f "$BL" ]; then grep $1 $BL >/dev/null 2>&1 && exit 0 fi # Launch the test # """"""""""""""" clear PS1='$ ' $PTYLIE -i $1.tst -l $1.log -w 80 -h 24 sh $HVLT < $1.log | sed '1,/exit 0/!d' > $1.out rm -f $1.log $1.bad [ -f $LOG ] && touch $LOG # Add the new log entry, # If the .good file exists and the .out and the .good files are identical # then remove the .out file and tag the test as GOOD # else if the .good file does not exist then keep the .out file and tag # the test as UNCHECKED in the log # else the test is a failure and tag it as BAD # """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" if [ -e $1.good ]; then if diff -u $1.out $1.good >/dev/null 2>&1; then ATTR="GOOD " rm $1.out else ATTR="BAD " mv $1.out $1.bad fi else ATTR="UNCHECKED " fi if grep "^$1 " $LOG >/dev/null 2>&1; then RES=$(awk -vt=$1 -vattr="$ATTR" \ '$1 == t {$2 = attr; print t,attr}' $LOG) NEWLOG=$(sed "s/^$1 .*/$RES/" $LOG) [ -n "$NEWLOG" ] && echo "$NEWLOG" > $LOG else echo "$1 $ATTR" >> $LOG fi exit 0 smenu-0.9.17/tests/tests.sh000066400000000000000000000045131400523266500156050ustar00rootroot00000000000000#!/usr/bin/env bash # =========================================================================== # Usage: ./tests.sh [test_directory] # # Is a test_directory is given then the automated testings will be restricted # to the given directory tree # =========================================================================== header1() { printf "%-20s %-5s %s %s\n" Directory Tests States } header2() { printf "%-5s %s %s\n" Tests States } [ -z "$1" ] && TESTDIR="." \ || TESTDIR=$1 [ ! -d $TESTDIR ] && echo "$TESTDIR is not a directory" \ && exit 1 export DIR=${PWD} # Remove the existing .log files # """""""""""""""""""""""""""""" [ "$TESTDIR" == "." ] && rm -f *.log || rm -f ${TESTDIR}.log # Build the list of tests to be performed # """"""""""""""""""""""""""""""""""""""" LIST=$( find $TESTDIR -type f -name 't[0-9][0-9][0-9][0-9].tst' \ | sort ) # Perform the testings # """""""""""""""""""" for INDEX in $LIST; do INDEX=${INDEX#./} SUBDIR=${INDEX%/*} [ $SUBDIR != $INDEX ] && cd $SUBDIR TST=${INDEX##*/} $DIR/test.sh ${TST%.tst} || exit 1 [ $SUBDIR != $INDEX ] && cd - done # Display the results # """"""""""""""""""" echo echo -n "Results" [ "$TESTDIR" != "." ] && echo -n " for the tests in the '$TESTDIR' directory" \ || TESTDIR="" echo : clear RESULTS_BAD=$(grep BAD ${TESTDIR:=*}.log) RESULTS_UNC=$(grep UNCHECKED ${TESTDIR:=*}.log) if [ -z "$RESULTS_BAD" ]; then tput smso echo "All validated tests passed successfully !" tput rmso else tput smso echo "Some tests have failed !" tput rmso if [ -z "$TESTDIR" ]; then header1 printf "%-20s %5s %s\n" $(echo "$RESULTS_BAD" | sed 's/.log:/ /') else header2 printf "%5s %s\n" $(echo "$RESULTS_BAD" | sed 's/.log:/ /') fi echo echo "For each BAD, a diff between the corresponding .bad and .good" echo "files in the specified directory will provide more details on" echo "the failure." fi if [ -n "$RESULTS_UNC" ]; then echo echo "But some tests have not been validated, please provide a .good" echo "file for them. Here is the list:" echo if [ -z "$TESTDIR" ]; then header1 printf "%-20s %5s %s\n" $(echo "$RESULTS_UNC" | sed 's/.log:/ /') else header2 printf "%5s %s\n" $(echo "$RESULTS_UNC" | sed 's/.log:/ /') fi fi echo exit 0 smenu-0.9.17/tests/timeout/000077500000000000000000000000001400523266500155725ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/data1000066400000000000000000000000061400523266500165030ustar00rootroot00000000000000a b c smenu-0.9.17/tests/timeout/t0001.good000066400000000000000000000007111400523266500172070ustar00rootroot00000000000000$ OUT=$(smenu -x cur 5 -- t0001.in) [ 0s before selecting the current highlighted word] 0:01 1:01 2:01 3:01 4:01 5:01 6:01 7:01 8:01 9:01 10:01 11:01 12:01 13:01 14:01 15:01 16:01 17:01 18:01 19:01 20:01 21:01 22:01 23:01 24:01 25:01 26:01 27:01 28:01 29:01 30:01 31:01 32:01 33:01 34:01 35:01 36:01 37:01 38:01 39:01 40:01 41:01 42:01 43:01 44:01 45:01 46:01 47:01 48:01 49:01 50:01 51:01 52:01 53:01 a b c 2:07 $ $ echo ":$OUT:" :b: $ exit 0 smenu-0.9.17/tests/timeout/t0001.in000077700000000000000000000000001400523266500175762data1ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/t0001.tst000066400000000000000000000001571400523266500170750ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -x cur 5 -- t0001.in) \S[150]\s[150]l\S[6000] \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/timeout/t0002.good000066400000000000000000000007111400523266500172100ustar00rootroot00000000000000$ OUT=$(smenu -x cur 5 -- t0002.in) [ 0s before selecting the current highlighted word] 0:01 1:01 2:01 3:01 4:01 5:01 6:01 7:01 8:01 9:01 10:01 11:01 12:01 13:01 14:01 15:01 16:01 17:01 18:01 19:01 20:01 21:01 22:01 23:01 24:01 25:01 26:01 27:01 28:01 29:01 30:01 31:01 32:01 33:01 34:01 35:01 36:01 37:01 38:01 39:01 40:01 41:01 42:01 43:01 44:01 45:01 46:01 47:01 48:01 49:01 50:01 51:01 52:01 53:01 a b c 0:07 $ $ echo ":$OUT:" :a: $ exit 0 smenu-0.9.17/tests/timeout/t0002.in000077700000000000000000000000001400523266500175772data1ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/t0002.tst000066400000000000000000000002021400523266500170650ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -x cur 5 -- t0002.in) \S[150]\s[150]l\S[2000]l\S[2000]hh\S[6000] \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/timeout/t0003.good000066400000000000000000000006611400523266500172150ustar00rootroot00000000000000$ OUT=$(smenu -x q 5 -- t0003.in) [ 0s before quitting without selecting anything] 0:01 1:01 2:01 3:01 4:01 5:01 6:01 7:01 8:01 9:01 10:01 11:01 12:01 13:01 14:01 15:01 16:01 17:01 18:01 19:01 20:01 21:01 22:01 23:01 24:01 25:01 26:01 27:01 28:01 29:01 30:01 31:01 32:01 33:01 34:01 35:01 36:01 37:01 38:01 39:01 40:01 41:01 42:01 43:01 44:01 45:01 46:01 47:01 48:01 49:01 50:01 a b c 2:07 $ $ echo ":$OUT:" :: $ exit 0 smenu-0.9.17/tests/timeout/t0003.in000077700000000000000000000000001400523266500176002data1ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/t0003.tst000066400000000000000000000001551400523266500170750ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -x q 5 -- t0003.in) \S[150]\s[150]l\S[6000] \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/timeout/t0004.good000066400000000000000000000006021400523266500172110ustar00rootroot00000000000000$ OUT=$(smenu -x w 'test\u21' 5 -- t0004.in) [ 0s before selecting the word "test!"] 0:01 1:01 2:01 3:01 4:01 5:01 6:01 7:01 8:01 9:01 10:01 11:01 12:01 13:01 14:01 15:01 16:01 17:01 18:01 19:01 20:01 21:01 22:01 23:01 24:01 25:01 26:01 27:01 28:01 29:01 30:01 31:01 32:01 33:01 34:01 35:01 36:01 37:01 38:01 39:01 40:01 41:01 a b c 2:07 $ $ echo ":$OUT:" :test!: $ exit 0 smenu-0.9.17/tests/timeout/t0004.in000077700000000000000000000000001400523266500176012data1ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/t0004.tst000066400000000000000000000001711400523266500170740ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -x w 'test\\u21' 5 -- t0004.in) \S[150]\s[150]l\S[6000] \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/timeout/t0005.good000066400000000000000000000007111400523266500172130ustar00rootroot00000000000000$ OUT=$(smenu -x cur 5 -- t0005.in) [ 3s before selecting the current highlighted word] 0:01 1:01 2:01 3:01 4:01 5:01 6:01 7:01 8:01 9:01 10:01 11:01 12:01 13:01 14:01 15:01 16:01 17:01 18:01 19:01 20:01 21:01 22:01 23:01 24:01 25:01 26:01 27:01 28:01 29:01 30:01 31:01 32:01 33:01 34:01 35:01 36:01 37:01 38:01 39:01 40:01 41:01 42:01 43:01 44:01 45:01 46:01 47:01 48:01 49:01 50:01 51:01 52:01 53:01 a b c 2:07 $ $ echo ":$OUT:" :b: $ exit 0 smenu-0.9.17/tests/timeout/t0005.in000077700000000000000000000000001400523266500176022data1ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/t0005.tst000066400000000000000000000001611400523266500170740ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -x cur 5 -- t0005.in) \S[150]\s[150]l\S[2000]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/timeout/t0006.good000066400000000000000000000001251400523266500172130ustar00rootroot00000000000000$ OUT=$(smenu -X cur 5 -- t0001.in) a b c 2:07 $ $ echo ":$OUT:" :b: $ exit 0 smenu-0.9.17/tests/timeout/t0006.in000077700000000000000000000000001400523266500176032data1ustar00rootroot00000000000000smenu-0.9.17/tests/timeout/t0006.tst000066400000000000000000000001611400523266500170750ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -X cur 5 -- t0001.in) \S[150]\s[150]l\S[3000]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/000077500000000000000000000000001400523266500147725ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/FreeBSD.bl000066400000000000000000000000061400523266500165170ustar00rootroot00000000000000t0002 smenu-0.9.17/tests/utf8/data1000066400000000000000000000001071400523266500157050ustar00rootroot000000000000000 1 2 3 4 5 6 7 8 9 10 零/〇 一 二 三 四 五 六 七 八 九 十 smenu-0.9.17/tests/utf8/data2000066400000000000000000000004031400523266500157050ustar00rootroot00000000000000*\u3* *\u0a* *\u34* *\u345* *\u3456* *\uc3*4* *\u45* *\u451* *\u4512* *\u45123* *\u45\u46* *\u451\u46* *\uc3\u45* *\uc3a\u45* *\uefb899ø\uf0908589* *ø\uc3a9\uc3aaabø* *\uc3a9*\uf0* *\uc3a9*\uf0aa* *\uc3a9*\uf0aaab* *\uc3a9*\uF09D849E* *\uC3A9*\uF09D84aa* smenu-0.9.17/tests/utf8/data3000066400000000000000000000000441400523266500157070ustar00rootroot00000000000000é\uc3a9€ \uc3a9é€ é€\uc3a9 smenu-0.9.17/tests/utf8/data4000066400000000000000000000000241400523266500157060ustar00rootroot00000000000000EéE€ abc\u45defE smenu-0.9.17/tests/utf8/data5000066400000000000000000000010341400523266500157110ustar00rootroot00000000000000×\\U002581\\U002582\\U002583\\U002584\\U002585\\U002586\\U002587\\U002588× ×\\ue29681\\ue29682\\ue29683\\ue29684\\ue29685\\ue29686\\ue29687\\ue29688× ×\\ue29684×\\U002584× ×\\U002584×\\ue29684× ×\\U\\U0\\U00\\U002\\U0025\\U00258× \\u31\\U002460\\u32 \\U002461\\u32 \\u31\\U002462 \\u31\\U002463\\u32\\U002464\\u33 \\u31\\U00246\\u32 \\U00246\\u32 \\u31\\U00246 \\u31\\U00246\\u32\\U00246\\u33 ×\\U110000× ×é× ×\\uc3a9× ×\\U0000e9× ×\\U000065\\U000301× ×\\U000065\\ucc81× ×\\u\\U000043\\U000033\\U000041\\U000039× smenu-0.9.17/tests/utf8/t0001.good000066400000000000000000000002601400523266500164060ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -c t0001.in) 0 1 2 3 4 5 6 7 8 9 10 零/〇 一 二 三 四 五 六 七 八 九 十 14:07 $ $ echo ":$OUT:" :六: $ exit 0 smenu-0.9.17/tests/utf8/t0001.in000077700000000000000000000000001400523266500167762data1ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0001.tst000066400000000000000000000001671400523266500162760ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -c t0001.in) \S[150]\s[150]jllllll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/t0002.good000066400000000000000000000004711400523266500164130ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -n 7 -c t0002.in) *. *\n* *4* *45* *456* *.*4* *E* *E1* *E12* *E123* *EF* *E1F* *.E* *.aE* *︙ø𐅉* *øéêabø* *é*.* *é*.* *é*.* *é*𝄞* *é*𝄪* 0:07 1:07 2:07 3:07 4:07 5:07 $ $ echo ":$OUT:" :*é*𝄞*: $ exit 0 smenu-0.9.17/tests/utf8/t0002.in000077700000000000000000000000001400523266500170002data2ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0002.tst000066400000000000000000000001731400523266500162740ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -n 7 -c t0002.in) \S[200]\s[200]jjjjjj\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/t0003.good000066400000000000000000000003341400523266500164120ustar00rootroot00000000000000$ OUT=$(LANG=C smenu -M -m «←→» t0003.in) .... 36:01 37:01 38:01 39:01 ... ... ... 33:07 34:07 35:07 $ $ echo ":$OUT:" :...: $ exit 0 smenu-0.9.17/tests/utf8/t0003.in000077700000000000000000000000001400523266500170022data3ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0003.tst000066400000000000000000000001651400523266500162760ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=C smenu -M -m «←→» t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/t0004.good000066400000000000000000000003741400523266500164170ustar00rootroot00000000000000$ OUT=$(LANG=en_US.UTF-8 smenu -M -m «←→» t0003.in) «←→» 36:01 37:01 38:01 39:01 éé€ éé€ é€é 33:07 34:07 35:07 $ $ echo ":$OUT:" :éé€: $ exit 0 smenu-0.9.17/tests/utf8/t0004.in000077700000000000000000000000001400523266500170032data3ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0004.tst000066400000000000000000000001771400523266500163020ustar00rootroot00000000000000\S[150]\s[10]OUT=$(LANG=en_US.UTF-8 smenu -M -m «←→» t0003.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/t0005.good000066400000000000000000000002561400523266500164170ustar00rootroot00000000000000$ OUT=$(smenu '-I/\u45/\ue29782\ue296b8/g' t0005.in) ◂▸é◂▸€ abc◂▸def◂▸ 0:07 1:07 2:07 3:07 4:07 5:07 $ $ echo ":$OUT:" :◂▸é◂▸€: $ exit 0 smenu-0.9.17/tests/utf8/t0005.in000077700000000000000000000000001400523266500170052data4ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0005.tst000066400000000000000000000001741400523266500163000ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-I/\\u45/\\ue29782\\ue296b8/g' t0005.in) \S[250]\s[250]\r \S[250]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/t0006.good000066400000000000000000000002531400523266500164150ustar00rootroot00000000000000$ OUT=$(smenu '-I/E/\ue29782\ue296b8/g' t0006.in) ◂▸é◂▸€ abc◂▸def◂▸ 0:07 1:07 2:07 3:07 4:07 5:07 $ $ echo ":$OUT:" :◂▸é◂▸€: $ exit 0 smenu-0.9.17/tests/utf8/t0006.in000077700000000000000000000000001400523266500170062data4ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0006.tst000066400000000000000000000001701400523266500162750ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu '-I/E/\\ue29782\\ue296b8/g' t0006.in) \S[150]\s[150]\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/utf8/t0007.good000066400000000000000000000004441400523266500164200ustar00rootroot00000000000000$ OUT=$(smenu t0007.in) ×▁▂▃▄▅▆▇█× ×▁▂▃▄▅▆▇█× ×▄×▄× ×▄×▄× ×......× 1①2 ②2 1③ 1④2⑤3 1.2 .2 1. 1.2.3 22:07 23:07 24:07 25:07 26:07 ×.× ×é× ×é× ×é× ×é× ×é× ×é× $ $ echo ":$OUT:" :×▄×▄×: $ exit 0 smenu-0.9.17/tests/utf8/t0007.in000077700000000000000000000000001400523266500170102data5ustar00rootroot00000000000000smenu-0.9.17/tests/utf8/t0007.tst000066400000000000000000000001361400523266500163000ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu t0007.in) \S[150]\s[150]ll\r \S[150]\s[10]echo ":$\s[10]OUT:" exit 0 smenu-0.9.17/tests/word_separators/000077500000000000000000000000001400523266500173225ustar00rootroot00000000000000smenu-0.9.17/tests/word_separators/data1000066400000000000000000000000401400523266500202310ustar00rootroot00000000000000abc»def»ghi» »jkl»mno»pqr smenu-0.9.17/tests/word_separators/t0001.good000066400000000000000000000001661400523266500207430ustar00rootroot00000000000000$ OUT=$(smenu -W» t0001.in) abc def ghi \n jkl mno pqr\n 12:07 13:07 $ $ printf "%s\n" ":$OUT:" :\n: $ exit 0 smenu-0.9.17/tests/word_separators/t0001.in000066400000000000000000000000401400523266500204100ustar00rootroot00000000000000abc»def»ghi» »jkl»mno»pqr smenu-0.9.17/tests/word_separators/t0001.tst000066400000000000000000000001561400523266500206240ustar00rootroot00000000000000\S[150]\s[10]OUT=$(smenu -W» t0001.in) \S[150]\s[150]lll\r \S[150]\s[10]printf "%s\\n" ":$\s[10]OUT:" exit 0 smenu-0.9.17/usage.c000066400000000000000000000256611400523266500142240ustar00rootroot00000000000000/* **************** */ /* Usage functions. */ /* **************** */ #include #include #include #include "usage.h" #include "ctxopt.h" static void common_help(void); /* ======================= */ /* Usage display and exit. */ /* ======================= */ static void common_help(void) { printf("-h|-help\n"); printf(" displays this help.\n"); printf("-u|-usage\n"); printf(" displays the synopsis of the current context.\n"); printf("-i|-in|-inc|-incl|-include\n"); printf(" sets the regex input filter to match the selectable words.\n"); printf("-e|-ex|-exc|-excl|-exclude\n"); printf(" sets the regex input filter to match the non-selectable " "words.\n"); printf("-m|-msg|-message|-title\n"); printf(" displays a one-line message above the window.\n"); printf("-!|-int|-int_string\n"); printf(" outputs an optional string when ^C is typed.\n"); printf("-a|-attr|-attributes\n"); printf(" sets the attributes for the various displayed elements.\n"); printf("-1|-l1|-level1,-2|-l2|-level2,...,-5|-l5|-level5\n"); printf(" gives specific colors to up to 5 classes of " "selectable words.\n"); printf("-z|-zap|-zap_glyphs bytes\n"); printf(" defines a set of glyphs to ignore as input.\n"); printf("-n|-lines|-height\n"); printf(" sets the number of lines in the selection window.\n"); printf("-b|-blank\n"); printf(" displays non printable characters as space.\n"); printf("-.|-dot|-invalid\n"); printf(" defines the substitution character for a non-printable " "character.\n"); printf("-M|-middle|-center\n"); printf(" centers the display if possible.\n"); printf("-d|-restore|-delete|-clean|-delete_window|-clean_window\n"); printf(" clears the lines used by the selection window on exit.\n"); printf("-k|-ks|-keep_spaces\n"); printf(" does not trim spaces surrounding the output string if any.\n"); printf("-W|-ws|-wd|-word_delimiters|-word_separators\n"); printf(" sets the input words separators.\n"); printf("-L|-ls|-ld|-line-delimiters|-line_separators\n"); printf(" sets the input lines separators.\n"); printf("-q|-no_bar|-no-scroll_bar\n"); printf(" prevents the display of the scroll bar.\n"); printf("-S|-subst\n"); printf(" sets the post-processing action to apply to all words.\n"); printf("-I|-si|-subst_included\n"); printf(" sets the post-processing action to apply to selectable " "words only.\n"); printf("-E|-se|-subst_excluded\n"); printf(" sets the post-processing action to apply to non-selectable " "words only.\n"); printf("-/|-search_method\n"); printf(" changes the affectation of the / key (default fuzzy search).\n"); printf("-s|-sp|-start|-start_pattern\n"); printf(" sets the initial cursor position (read the manual for " "more details).\n"); printf("-x|-tmout|-timeout/-X|-htmout|-hidden_timeout\n"); printf(" sets a timeout and specifies what to do when it expires.\n"); printf("-r|-auto_validate\n"); printf(" enables ENTER to validate the selection even in search mode.\n"); printf("-v|-vb|-visual_bell\n"); printf(" makes the bell visual (fuzzy search with error).\n"); printf("-Q|-ignore_quotes\n"); printf(" treats single and double quotes as normal characters.\n"); } void main_help(void) { ctxopt_ctx_disp_usage("Main", continue_after); printf("\n----------------------------------------"); printf("----------------------------------------\n"); printf("\nThis is a filter that gets words from stdin or from a file and "); printf("outputs\n"); printf("the selected words (or nothing) on stdout in a nice selection "); printf("window\n\n"); printf("The selection window appears on /dev/tty "); printf("just below the current line\n"); printf("(no clear screen!).\n\n"); printf("Short description of allowed parameters:\n\n"); common_help(); printf("-V|-version\n"); printf(" displays the current version and quits.\n"); printf("-H|-long_help\n"); printf(" displays a full help and the options available in all " "contexts.\n"); printf("-N|-number/-U|-unnumber\n"); printf(" numbers/un-numbers and provides a direct access to words " "matching\n"); printf(" (or not) a specific regex.\n"); printf("-F|-en|-embedded_number\n"); printf(" numbers and provides a direct access to words by extracting the " "number\n"); printf("-c|-col|-col_mode|-column\n"); printf(" is like|-t without argument but respects end of lines.\n"); printf("-l|-line|-line_mode\n"); printf(" is like|-c without column alignments.\n"); printf("-t|-tab|-tab_mode|-tabulate_mode\n"); printf(" tabulates the items. The number of columns can be limited " "with\n"); printf(" an optional number.\n"); printf("-T|-tm|-tag|-tag_mode/-P|-pm|-pin|-pin_mode\n"); printf(" enables the tagging (multi-selections) mode. "); printf("An optional parameter\n"); printf(" sets the separator string between the selected words "); printf("on the output.\n"); printf(" A single space is the default separator.\n"); printf("\nNavigation keys are:\n"); printf(" - Left/Down/Up/Right arrows or h/j/k/l, H/J/K/L.\n"); printf(" - Home/End, SHIFT|CTRL+Home/End CTRK+J/CTRL+K.\n"); printf(" - Numbers if some words are numbered (-N/-U/-F).\n"); printf(" - SPACE to search for the next match of a previously\n"); printf(" entered search prefix if any, see below.\n\n"); printf("Other useful keys are:\n"); printf(" - Help key (temporary display of a short help line): " "?\n"); printf(" - Exit key without output (do nothing) : " "q\n"); printf(" - Tagging keys: Select/Deselect/Toggle : " "INS/DEL/t\n"); printf(" - Selection key : " "ENTER\n"); printf(" - Cancel key : " "ESC\n"); printf(" - Search key : " "/ or CTRL-F\n\n"); printf("The search key activates a timed search mode in which\n"); printf("you can enter the first letters of the searched word.\n"); printf("When entering this mode you have 7s to start typing\n"); printf("and each entered letter gives you 5 more seconds before\n"); printf("the timeout. After that the search mode is ended.\n\n"); printf("Notes:\n"); printf("- the timer can be cancelled by pressing ESC.\n"); printf("- a bad search letter can be removed with "); printf("CTRL-H or Backspace.\n\n"); printf("(C) Pierre Gentile.\n\n"); exit(EXIT_FAILURE); } void columns_help(void) { ctxopt_ctx_disp_usage("Columns", continue_after); printf("\n----------------------------------------"); printf("----------------------------------------\n"); printf("Short description of allowed parameters:\n\n"); common_help(); printf("-C|-cs|-cols|-cols_select\n"); printf(" sets columns restrictions for selections.\n"); printf("-R|-rs|-rows|-rows_select\n"); printf(" sets rows restrictions for selections.\n"); printf("-w|-wide|-wide_mode\n"); printf(" uses all the terminal width for the columns if their numbers " "is given.\n"); printf("-g|-gutter\n"); printf(" separates columns with a character in column or tabulate " "mode.\n"); printf("-N|-number/-U|-unnumber\n"); printf(" numbers/un-numbers and provides a direct access to words " "matching\n"); printf(" (or not) a specific regex.\n"); printf("-F|-en|-embedded_number\n"); printf(" numbers and provides a direct access to words by extracting the " "number\n"); printf("-T|-tm|-tag|-tag_mode/-P|-pm|-pin|-pin_mode\n"); printf(" enables the tagging (multi-selections) mode. "); printf("An optional parameter\n"); printf(" sets the separator string between the selected words "); printf("on the output.\n"); printf(" A single space is the default separator.\n"); printf("-A|-fc|-first_column\n"); printf(" forces the specified word pattern to start a line.\n"); printf("-Z|-lc|-last_column\n"); printf(" forces the specified word pattern to end a line.\n"); } void lines_help(void) { ctxopt_ctx_disp_usage("Lines", continue_after); printf("\n----------------------------------------"); printf("----------------------------------------\n"); printf("Short description of allowed parameters:\n\n"); common_help(); printf("-R|-rs|-rows|-row_select\n"); printf(" sets rows restrictions for selections.\n"); printf("-N|-number/-U|-unnumber\n"); printf(" numbers/un-numbers and provides a direct access to words " "matching\n"); printf(" (or not) a specific regex.\n"); printf("-F|-en|-embedded_number\n"); printf(" numbers and provides a direct access to words by extracting the " "number\n"); printf("-T|-tm|-tag|-tag_mode/-P|-pm|-pin|-pin_mode\n"); printf(" enables the tagging (multi-selections) mode. "); printf("An optional parameter\n"); printf(" sets the separator string between the selected words "); printf("on the output.\n"); printf(" A single space is the default separator.\n"); printf("-A|-fc|-first_column\n"); printf(" forces the specified word pattern to start a line.\n"); printf("-Z|-lc|-last_column\n"); printf(" forces the specified word pattern to end a line.\n"); } void tabulations_help(void) { ctxopt_ctx_disp_usage("Tabulations", continue_after); printf("\n----------------------------------------"); printf("----------------------------------------\n"); printf("Short description of allowed parameters:\n\n"); common_help(); printf("-w|-wide|-wide_mode\n"); printf(" uses all the terminal width for the columns if their numbers " "is given.\n"); printf("-g|-gutter\n"); printf(" separates columns with a character in column or tabulate " "mode.\n"); printf("-N|-number/-U|-unnumber\n"); printf(" numbers/un-numbers and provides a direct access to words " "matching\n"); printf(" (or not) a specific regex.\n"); printf("-F|-en|-embedded_number\n"); printf(" numbers and provides a direct access to words by extracting the " "number\n"); printf("-T|-tm|-tag|-tag_mode/-P|-pm|-pin|-pin_mode\n"); printf(" enables the tagging (multi-selections) mode. "); printf("An optional parameter\n"); printf(" sets the separator string between the selected words "); printf("on the output.\n"); printf(" A single space is the default separator.\n"); printf("-A|-fc|-first_column\n"); printf(" forces the specified word pattern to start a line.\n"); printf("-Z|-lc|-last_column\n"); printf(" forces the specified word pattern to end a line.\n"); } void tagging_help(void) { ctxopt_ctx_disp_usage("Tagging", continue_after); printf("\n----------------------------------------"); printf("----------------------------------------\n"); printf("The following parameters are available in this context:\n\n"); common_help(); printf("-p|-at|-auto_tag\n"); printf(" activates the auto-tagging.\n"); exit(EXIT_FAILURE); } smenu-0.9.17/usage.h000066400000000000000000000007221400523266500142200ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ #ifndef USAGE_H #define USAGE_H void main_help(void); void columns_help(void); void lines_help(void); void tabulations_help(void); void direct_access_help(void); void tagging_help(void); #endif smenu-0.9.17/utf8.c000066400000000000000000000406351400523266500140040ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html. */ /* ########################################################### */ /* ************************************* */ /* Various UTF-8 manipulation functions. */ /* ************************************* */ #include #include #include #include #include #include #include #include "xmalloc.h" #include "utf8.h" /* =========================================================== */ /* UTF-8 byte sequence generation from a given UCS-4 codepoint */ /* utf8_str must be preallocated with a size of at least 5 */ /* bytes. */ /* return the length of the generated sequence or 0 if c is */ /* not a valid codepoint. */ /* =========================================================== */ int cptoutf8(char * utf8_str, uint32_t c) { int len = 0; int first = 0; int i; if (c < 0x80) { first = 0; len = 1; } else if (c < 0x800) { first = 0xc0; len = 2; } else if (c < 0x10000) { first = 0xe0; len = 3; } else if (c < 0x200000) { first = 0xf0; len = 4; } if (utf8_str) { for (i = len - 1; i > 0; --i) { utf8_str[i] = (c & 0x3f) | 0x80; c >>= 6; } utf8_str[0] = c | first; } return len; } /* ======================================================================= */ /* Unicode (UTF-8) ASCII representation interpreter. */ /* The string passed will be altered but its address will not change. */ /* All hexadecimal sequences of \uxx, \uxxxx, \uxxxxxx and \uxxxxxxxx will */ /* be replaced by the corresponding UTF-8 character when possible. */ /* All hexadecimal sequences of \Uxxxxxx will be replaced with the UTF-8 */ /* sequence corresponding to the given UCS-4 codepoint. */ /* When not possible the substitution character is substituted in place. */ /* Returns 0 if the conversion has failed else 1. */ /* ======================================================================= */ int utf8_interpret(char * s, langinfo_t * langinfo, char substitute) { char * utf8_str; /* \uxx... */ size_t utf8_to_eos_len; /* bytes in s starting from the first * * occurrence of \u. */ size_t init_len; /* initial lengths of the string to interpret */ size_t utf8_ascii_len; /* 2,4,6 or 8 bytes. */ size_t len_to_remove = 0; /* number of bytes to remove after the * | conversion. */ char tmp[9]; /* temporary string. */ int rc = 1; /* return code, 0: error, 1: fine. */ /* Guard against the case where s is NULL. */ /* """"""""""""""""""""""""""""""""""""""" */ if (s == NULL) return 0; init_len = strlen(s); /* Manage \U codepoints. */ /* """"""""""""""""""""" */ while ((utf8_str = strstr(s, "\\U")) != NULL) { char str[7]; int utf8_str_len; int len; int n; uint32_t cp; int subst; /* 0, the \U sequence is valid, else 1. */ utf8_to_eos_len = strlen(utf8_str); utf8_str_len = 0; n = sscanf(utf8_str + 2, "%6[" "0123456789" "abcdef" "ABCDEF" "]%n", tmp, &utf8_str_len); subst = 0; if (n == 1 && utf8_str_len == 6) { sscanf(tmp, "%x", &cp); if (cp > 0x10FFFF) subst = 1; /* Invalid range. */ else { len = cptoutf8(str, cp); str[len] = '\0'; *(utf8_str + 1) = 'u'; memmove(utf8_str, str, len); memmove(utf8_str + len, utf8_str + 8, utf8_to_eos_len - 8); len_to_remove += 8 - len; } } else subst = 1; /* Invalid sequence. */ /* In case of invalid \U sequence, replace it with the */ /* substitution character. */ /* ''''''''''''''''''''''''''''''''''''''''''''''''''' */ if (subst) { *utf8_str = substitute; memmove(utf8_str + 1, utf8_str + 2 + utf8_str_len, utf8_to_eos_len - (utf8_str_len + 2 - 1)); len_to_remove += utf8_str_len + 2 - 1; } } /* Make sure that the string is well terminated. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ *(s + init_len - len_to_remove) = '\0'; /* Manage \u UTF-8 byte sequences. */ /* """"""""""""""""""""""""""""""" */ while ((utf8_str = strstr(s, "\\u")) != NULL) { utf8_to_eos_len = strlen(utf8_str); if (utf8_to_eos_len < 4) /* string too short to contain * | a valid UTF-8 char. */ { *utf8_str = substitute; *(utf8_str + 1) = '\0'; rc = 0; } else /* s is long enough. */ { unsigned byte; char * utf8_seq_offset = utf8_str + 2; /* Get the first 2 UTF-8 bytes. */ /* """""""""""""""""""""""""""" */ *tmp = *utf8_seq_offset; *(tmp + 1) = *(utf8_seq_offset + 1); *(tmp + 2) = '\0'; /* If they are invalid, replace the \u sequence by the */ /* substitute character. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ if (!isxdigit(tmp[0]) || !isxdigit(tmp[1])) { *utf8_str = substitute; if (4 >= utf8_to_eos_len) *(utf8_str + 1) = '\0'; else { /* Do not forget the training \0. */ /* """""""""""""""""""""""""""""" */ memmove(utf8_str + 1, utf8_str + 4, utf8_to_eos_len - 4 + 1); } rc = 0; } else { int n; char end; size_t i; char b[3] = { ' ', ' ', '\0' }; /* They are valid, deduce from them the length of the sequence. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ sscanf(tmp, "%2x", &byte); utf8_ascii_len = utf8_get_length(byte) * 2; /* replace the \u sequence by the bytes forming the UTF-8 char. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ /* Put the bytes in the tmp string. */ /* '''''''''''''''''''''''''''''''' */ *tmp = byte; /* Reuse the tmp array. */ for (i = 1; i < utf8_ascii_len / 2; i++) { int good = 1; n = sscanf(utf8_seq_offset + 2 * i, "%c%c", &b[0], &b[1]); if (n == 2) { byte = 0; end = '\0'; sscanf(b, "%x%c", &byte, &end); if (byte == 0 || end != '\0' || (byte & 0xc0) != 0x80) good = 0; } else good = 0; if (!good) utf8_ascii_len = 2 * i; /* Force the new length according to the * | number of valid UTF-8 bytes read. */ else *(tmp + i) = byte; } tmp[utf8_ascii_len / 2] = '\0'; /* Does they form a valid UTF-8 char? */ /* '''''''''''''''''''''''''''''''''' */ if (utf8_validate(tmp, utf8_ascii_len / 2)) { /* Put them back in the original string and move */ /* the remaining bytes after them. */ /* ''''''''''''''''''''''''''''''''''''''''''''' */ memmove(utf8_str, tmp, utf8_ascii_len / 2); if (utf8_to_eos_len < utf8_ascii_len) *(utf8_str + utf8_ascii_len / 2 + 1) = '\0'; else memmove(utf8_str + utf8_ascii_len / 2, utf8_seq_offset + utf8_ascii_len, utf8_to_eos_len - utf8_ascii_len - 2 + 1); } else { /* The invalid sequence is replaced by a */ /* substitution character. */ /* ''''''''''''''''''''''''''''''''''''' */ *utf8_str = substitute; if (utf8_to_eos_len < utf8_ascii_len) *(utf8_str + 1) = '\0'; else memmove(utf8_str + 1, utf8_seq_offset + utf8_ascii_len, utf8_to_eos_len - utf8_ascii_len - 2 + 1); utf8_ascii_len = 2; rc = 0; } /* Update the number of bytes to remove at the end */ /* of the initial string. */ /* """"""""""""""""""""""""""""""""""""""""""""""" */ len_to_remove += 2 + utf8_ascii_len / 2; } } } /* Make sure that the string is well terminated. */ /* """"""""""""""""""""""""""""""""""""""""""""" */ *(s + init_len - len_to_remove) = '\0'; return rc; } /* ========================================================= */ /* Decodes the number of bytes taken by a UTF-8 glyph. */ /* It is the length of the leading sequence of bits set to 1 */ /* in the first byte. */ /* ========================================================= */ int utf8_get_length(unsigned char c) { if (c < 0x80) return 1; else if (c < 0xe0) return 2; else if (c < 0xf0) return 3; else return 4; } /* ==================================================== */ /* Returns the byte offset of the nth UTF-8 glyph in s. */ /* ==================================================== */ size_t utf8_offset(char * s, size_t n) { size_t i = 0; while (n > 0) { if (s[i++] & 0x80) { (void)(((s[++i] & 0xc0) != 0x80) || ((s[++i] & 0xc0) != 0x80) || ++i); } n--; } return i; } /* ============================================== */ /* Points to the previous UTF-8 glyph in a string */ /* from the given position. */ /* ============================================== */ char * utf8_prev(const char * str, const char * p) { while ((*p & 0xc0) == 0x80) p--; for (--p; p >= str; --p) { if ((*p & 0xc0) != 0x80) return (char *)p; } return NULL; } /* ========================================== */ /* Points to the next UTF-8 glyph in a string */ /* from the current position. */ /* ========================================== */ char * utf8_next(char * p) { if (*p) { for (++p; (*p & 0xc0) == 0x80; ++p) ; } return (*p == '\0' ? NULL : p); } /* ============================================================= */ /* Replaces any UTF-8 glyph present in s by a substitution */ /* character in-place. */ /* s will be modified but its address in memory will not change. */ /* ============================================================= */ void utf8_sanitize(char * s, char substitute) { char * p = s; int n; size_t len; len = strlen(s); while (*p) { n = utf8_get_length(*p); if (n > 1) { *p = substitute; memmove(p + 1, p + n, len - (p - s) - n + 1); len -= (n - 1); } p++; } } static const char trailing_bytes_for_utf8[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 }; /* =================================================================== */ /* UTF-8 validation routine inspired by Jeff Bezanson */ /* placed in the public domain Fall 2005 */ /* (https://github.com/JeffBezanson/cutef8). */ /* */ /* Returns 1 if str contains a valid UTF-8 byte sequence, 0 otherwise. */ /* =================================================================== */ int utf8_validate(const char * str, size_t length) { const unsigned char *p, *pend = (const unsigned char *)str + length; unsigned char c; size_t ab; for (p = (const unsigned char *)str; p < pend; p++) { c = *p; if (c < 128) continue; if ((c & 0xc0) != 0xc0) return 0; ab = trailing_bytes_for_utf8[c]; if (length < ab) return 0; length -= ab; p++; /* Check top bits in the second byte. */ /* """""""""""""""""""""""""""""""""" */ if ((*p & 0xc0) != 0x80) return 0; /* Check for overlong sequences for each different length. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */ switch (ab) { /* Check for xx00 000x. */ /* """""""""""""""""""" */ case 1: if ((c & 0x3e) == 0) return 0; continue; /* We know there aren't any more bytes to check. */ /* Check for 1110 0000, xx0x xxxx. */ /* """"""""""""""""""""""""""""""" */ case 2: if (c == 0xe0 && (*p & 0x20) == 0) return 0; break; /* Check for 1111 0000, xx00 xxxx. */ /* """"""""""""""""""""""""""""""" */ case 3: if (c == 0xf0 && (*p & 0x30) == 0) return 0; break; /* Check for 1111 1000, xx00 0xxx. */ /* """"""""""""""""""""""""""""""" */ case 4: if (c == 0xf8 && (*p & 0x38) == 0) return 0; break; /* Check for leading 0xfe or 0xff, */ /* and then for 1111 1100, xx00 00xx. */ /* """""""""""""""""""""""""""""""""" */ case 5: if (c == 0xfe || c == 0xff || (c == 0xfc && (*p & 0x3c) == 0)) return 0; break; } /* Check for valid bytes after the 2nd, if any; all must start with 10. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ while (--ab > 0) { if ((*(++p) & 0xc0) != 0x80) return 0; } } return 1; } /* ======================= */ /* Multibyte UTF-8 strlen. */ /* ======================= */ size_t utf8_strlen(char * str) { size_t i = 0, j = 0; while (str[i]) { if ((str[i] & 0xc0) != 0x80) j++; i++; } return j; } /* =================================================================== */ /* Multibytes extraction of the prefix of n UTF-8 glyphs from a string */ /* The destination string d must have been allocated before. */ /* pos is updated to reflect the position AFTER the prefix. */ /* =================================================================== */ char * utf8_strprefix(char * d, char * s, long n, long * pos) { long i = 0; long j = 0; *pos = 0; while (s[i] && j < n) { d[i] = s[i]; i++; j++; while (s[i] && (s[i] & 0xC0) == 0x80) { d[i] = s[i]; i++; } } *pos = i; d[i] = '\0'; return d; } /* ================================================== */ /* Converts a UTF-8 glyph string to a wchar_t string. */ /* The returned string must be freed by the caller. */ /* ================================================== */ wchar_t * utf8_strtowcs(char * s) { int converted = 0; unsigned char * ch; wchar_t * wptr, *w; size_t size; size = (long)strlen(s); w = xmalloc((size + 1) * sizeof(wchar_t)); w[0] = L'\0'; wptr = w; for (ch = (unsigned char *)s; *ch; ch += converted) { if ((converted = mbtowc(wptr, (char *)ch, 4)) > 0) wptr++; else { *wptr++ = (wchar_t)*ch; converted = 1; } } *wptr = L'\0'; return w; } /* ============================================================== */ /* Replaces all ASCII characters in src by its lowercase version. */ /* dst must be preallocated before the call. */ /* ============================================================== */ void utf8_strtolower(char * dst, char * src) { unsigned char c; while ((c = *src)) { if (c >= 0x80) *dst = c; else *dst = tolower(c); src++; dst++; } *dst = '\0'; } smenu-0.9.17/utf8.h000066400000000000000000000020611400523266500140000ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ #ifndef UTF8_H #define UTF8_H #include typedef struct langinfo_s langinfo_t; /* Locale informations */ /* """"""""""""""""""" */ struct langinfo_s { int utf8; /* charset is UTF-8 */ int bits; /* number of bits in the charset */ }; int utf8_get_length(unsigned char c); size_t utf8_offset(char *, size_t); char * utf8_strprefix(char * d, char * s, long n, long * pos); size_t utf8_strlen(char * str); wchar_t * utf8_strtowcs(char * s); void utf8_sanitize(char * s, char sc); int cptoutf8(char * utf8_str, uint32_t c); int utf8_interpret(char * s, langinfo_t * langinfo, char sc); int utf8_validate(const char * str, size_t length); char * utf8_prev(const char * str, const char * p); char * utf8_next(char * p); void utf8_strtolower(char * dst, char * src); #endif smenu-0.9.17/utils.c000066400000000000000000000166571400523266500142650ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html. */ /* ########################################################### */ /* ******************************** */ /* Various small utility functions. */ /* ******************************** */ #include "config.h" #include #include #include #include #include #include #include "xmalloc.h" #include "list.h" #include "utils.h" /* ******************* */ /* Interval functions. */ /* ******************* */ /* ======================= */ /* Creates a new interval. */ /* ======================= */ interval_t * interval_new(void) { interval_t * ret = xmalloc(sizeof(interval_t)); return ret; } /* ======================================= */ /* Compares 2 intervals as integer couples */ /* same return values as for strcmp. */ /* ======================================= */ int interval_comp(void * a, void * b) { interval_t * ia = (interval_t *)a; interval_t * ib = (interval_t *)b; if (ia->low < ib->low) /* ia: [... */ /* ib: [... */ return -1; if (ia->low > ib->low) /* ia: [... */ /* ib: [... */ return 1; if (ia->high < ib->high) /* ia: ...] */ /* ib: ...] */ return -1; if (ia->high > ib->high) /* ia: ...] */ /* ib: ...] */ return 1; return 0; } /* ================================== */ /* Swaps the values of two intervals. */ /* ================================== */ void interval_swap(void * a, void * b) { interval_t * ia = (interval_t *)a; interval_t * ib = (interval_t *)b; long tmp; tmp = ia->low; ia->low = ib->low; ib->low = tmp; tmp = ia->high; ia->high = ib->high; ib->high = tmp; } /* ====================================================================== */ /* Merges the intervals from an interval list in order to get the minimum */ /* number of intervals to consider. */ /* ====================================================================== */ void merge_intervals(ll_t * list) { ll_node_t * node1, *node2; interval_t *data1, *data2; if (!list || list->len < 2) return; else { /* Step 1: sort the intervals list. */ /* """""""""""""""""""""""""""""""" */ ll_sort(list, interval_comp, interval_swap); /* Step 2: merge the list by merging the consecutive intervals. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ node1 = list->head; node2 = node1->next; while (node2) { data1 = (interval_t *)(node1->data); data2 = (interval_t *)(node2->data); if (data1->high >= data2->low - 1) { /* Interval 1 overlaps interval 2. */ /* ''''''''''''''''''''''''''''''' */ if (data2->high >= data1->high) data1->high = data2->high; ll_delete(list, node2); free(data2); node2 = node1->next; } else { /* No overlap. */ /* ''''''''''' */ node1 = node2; node2 = node2->next; } } } } /* ****************** */ /* Strings functions. */ /* ****************** */ /* ========================================================================= */ /* Allocates memory and safely concatenate strings. Stolen from a public */ /* domain implementation which can be found here: */ /* http://openwall.info/wiki/people/solar/software/public-domain-source-code */ /* ========================================================================= */ char * concat(const char * s1, ...) { va_list args; const char * s; char * p, *result; size_t l, m, n; m = n = strlen(s1); va_start(args, s1); while ((s = va_arg(args, char *))) { l = strlen(s); if ((m += l) < l) break; } va_end(args); if (s || m >= INT_MAX) return NULL; result = (char *)xmalloc(m + 1); memcpy(p = result, s1, n); p += n; va_start(args, s1); while ((s = va_arg(args, char *))) { l = strlen(s); if ((n += l) < l || n > m) break; memcpy(p, s, l); p += l; } va_end(args); if (s || m != n || p != result + n) { free(result); return NULL; } *p = 0; return result; } /* =============================================== */ /* Is the string str2 a prefix of the string str1? */ /* Returns 1 if true, else 0. */ /* =============================================== */ int strprefix(char * str1, char * str2) { while (*str1 != '\0' && *str1 == *str2) { str1++; str2++; } return *str2 == '\0'; } /* ========================= */ /* Trims leading characters. */ /* ========================= */ void ltrim(char * str, const char * trim_str) { size_t len = strlen(str); size_t begin = strspn(str, trim_str); size_t i; if (begin > 0) for (i = begin; i <= len; ++i) str[i - begin] = str[i]; } /* ================================================= */ /* Trims trailing characters. */ /* The resulting string will have at least min bytes */ /* even if trailing spaces remain. */ /* ================================================= */ void rtrim(char * str, const char * trim_str, size_t min) { size_t len = strlen(str); while (len > min && strchr(trim_str, str[len - 1])) str[--len] = '\0'; } /* ========================================= */ /* Case insensitive strcmp. */ /* from http://c.snippets.org/code/stricmp.c */ /* ========================================= */ int my_strcasecmp(const char * str1, const char * str2) { #ifdef HAVE_STRCASECMP return strcasecmp(str1, str2); #else int retval = 0; while (1) { retval = tolower(*str1++) - tolower(*str2++); if (retval) break; if (*str1 && *str2) continue; else break; } return retval; #endif } /* ============================================= */ /* memmove based strcpy (tolerates overlapping). */ /* ============================================= */ char * my_strcpy(char * str1, char * str2) { if (str1 == NULL || str2 == NULL) return NULL; memmove(str1, str2, strlen(str2) + 1); return str1; } /* ================================ */ /* 7 bits aware version of isprint. */ /* ================================ */ int isprint7(int i) { return (i >= 0x20 && i <= 0x7e); } /* ================================ */ /* 8 bits aware version of isprint. */ /* ================================ */ int isprint8(int i) { unsigned char c = i & (unsigned char)0xff; return (c >= 0x20 && c < 0x7f) || (c >= (unsigned char)0xa0); } /* ==================================================== */ /* Private implementation of wcscasecmp missing in c99. */ /* ==================================================== */ int xwcscasecmp(const wchar_t * s1, const wchar_t * s2) { wchar_t c1, c2; while (*s1) { c1 = towlower(*s1); c2 = towlower(*s2); if (c1 != c2) return (int)(c1 - c2); s1++; s2++; } return (-*s2); } /* ====================================== */ /* Returns 1 if s represents an integer */ /* else 0. */ /* s != NULL is assumed. */ /* 0 and 0x prefixes are not understood. */ /* ====================================== */ int is_integer(const char * const s) { char * end; strtol(s, &end, 10); return (*end == '\0'); } smenu-0.9.17/utils.h000066400000000000000000000023161400523266500142550ustar00rootroot00000000000000/* ########################################################### */ /* This Software is licensed under the GPL licensed Version 2, */ /* please read http://www.gnu.org/copyleft/gpl.html */ /* ########################################################### */ #ifndef UTILS_H #define UTILS_H # include # include typedef struct interval_s interval_t; typedef struct range_s range_t; struct interval_s { long low; long high; }; /* Structure used by the replace function to delimit matches */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ struct range_s { size_t start; size_t end; }; interval_t * interval_new(void); int interval_comp(void * a, void * b); void interval_swap(void * a, void * b); void merge_intervals(ll_t * list); char * concat(const char * str1, ...); int strprefix(char * str1, char * str2); void ltrim(char * str, const char * trim); void rtrim(char * str, const char * trim, size_t min_len); int my_strcasecmp(const char * str1, const char * str2); char * my_strcpy(char * dst, char * src); int isprint7(int i); int isprint8(int i); int xwcscasecmp(const wchar_t * w1s, const wchar_t * w2s); int is_integer(const char * const s); #endif smenu-0.9.17/version000066400000000000000000000000071400523266500143470ustar00rootroot000000000000000.9.17 smenu-0.9.17/xmalloc.c000066400000000000000000000074111400523266500145500ustar00rootroot00000000000000/* **************************** */ /* Memory management functions. */ /* **************************** */ /* Created by Kevin Locke (from numerous canonical examples). */ /* */ /* Adapted for use by smenu. */ /* */ /* I hereby place this file in the public domain. It may be freely */ /* reproduced, distributed, used, modified, built upon, or otherwise */ /* employed by anyone for any purpose without restriction. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ #include #include #include #include #include "config.h" #include "xmalloc.h" /* The following rpl_* function are necessary for AIX which doesn't */ /* provide 'GNU compatible' allocation functions. */ /* Every call to malloc()/realloc() is then replaced by a call to */ /* rpl_malloc()/rpl_realloc() as defined in the GNU generated config.h. */ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ #ifdef malloc #undef malloc extern void * malloc(size_t); void * rpl_malloc(size_t size) { if (!size) size++; return malloc(size); } #undef realloc extern void * realloc(void *, size_t); void * rpl_realloc(void * ptr, size_t size) { if (!size) size++; return (ptr ? realloc(ptr, size) : malloc(size)); } #endif /* ================== */ /* Customized malloc. */ /* ================== */ void * xmalloc(size_t size) { void * allocated; size_t real_size; real_size = (size > 0) ? size : 1; allocated = malloc(real_size); if (allocated == NULL) { fprintf(stderr, "Error: Insufficient memory (attempt to malloc %lu bytes)\n", (unsigned long int)size); exit(EXIT_FAILURE); } return allocated; } /* ================== */ /* Customized calloc. */ /* ================== */ void * xcalloc(size_t n, size_t size) { void * allocated; n = (n > 0) ? n : 1; size = (size > 0) ? size : 1; allocated = calloc(n, size); if (allocated == NULL) { fprintf(stderr, "Error: Insufficient memory (attempt to calloc %lu bytes)\n", (unsigned long int)size); exit(EXIT_FAILURE); } return allocated; } /* =================== */ /* Customized realloc. */ /* =================== */ void * xrealloc(void * p, size_t size) { void * allocated; allocated = realloc(p, size); if (allocated == NULL && size > 0) { fprintf(stderr, "Error: Insufficient memory (attempt to xrealloc %lu bytes)\n", (unsigned long int)size); exit(EXIT_FAILURE); } return allocated; } /* ==================================== */ /* strdup implementation using xmalloc. */ /* ==================================== */ char * xstrdup(const char * p) { char * allocated; #ifdef HAVE_STRDUP allocated = strdup(p); if (allocated == NULL) { fprintf(stderr, "Error: Insufficient memory for strdup.\n"); exit(EXIT_FAILURE); } #else allocated = xmalloc(strlen(p) + 1); strcpy(allocated, p); #endif return allocated; } /* =================================================== */ /* strndup implementation using xmalloc. */ /* This version guarantees that there is a final '\0'. */ /* =================================================== */ char * xstrndup(const char * str, size_t len) { char * p; #ifdef HAVE_STRNDUP p = strndup(str, len); if (p == NULL) { fprintf(stderr, "Error: Insufficient memory for strndup.\n"); exit(EXIT_FAILURE); } #else p = memchr(str, '\0', len); if (p) len = p - str; p = xmalloc(len + 1); memcpy(p, str, len); p[len] = '\0'; #endif return p; } smenu-0.9.17/xmalloc.h000066400000000000000000000004771400523266500145620ustar00rootroot00000000000000#ifndef XMALLOC_H #define XMALLOC_H void * rpl_malloc(size_t size); void * rpl_realloc(void * ptr, size_t size); void * xmalloc(size_t size); void * xcalloc(size_t num, size_t size); void * xrealloc(void * ptr, size_t size); char * xstrdup(const char * p); char * xstrndup(const char * str, size_t len); #endif