diff options
author | Antti-Juhani Kaijanaho <ajk@debian.org> | 2006-01-28 21:10:55 +0100 |
---|---|---|
committer | Antti-Juhani Kaijanaho <ajk@debian.org> | 2006-01-28 21:10:55 +0100 |
commit | 4c90b78306e1334e1bd6dcb105d9bb4d5f53a845 (patch) | |
tree | 65b3c9e54508bd4f800ae6caed260c85a29248ce | |
download | dctrl-tools-4c90b78306e1334e1bd6dcb105d9bb4d5f53a845.tar.gz |
Import 1.100
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | Compatibility | 18 | ||||
-rw-r--r-- | License-Blurb | 13 | ||||
-rw-r--r-- | Makefile | 31 | ||||
-rw-r--r-- | NEWS | 23 | ||||
-rw-r--r-- | PROJECT | 1 | ||||
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | debian/README.build-system | 6 | ||||
-rw-r--r-- | debian/changelog | 282 | ||||
-rw-r--r-- | debian/conffiles | 1 | ||||
-rw-r--r-- | debian/control | 26 | ||||
-rw-r--r-- | debian/copyright | 36 | ||||
-rw-r--r-- | debian/librules-manual.txt | 131 | ||||
-rw-r--r-- | debian/librules.mk | 180 | ||||
-rw-r--r-- | debian/rules | 54 | ||||
-rw-r--r-- | fieldtrie.c | 75 | ||||
-rw-r--r-- | fieldtrie.h | 52 | ||||
-rw-r--r-- | fsaf.c | 230 | ||||
-rw-r--r-- | fsaf.h | 80 | ||||
-rw-r--r-- | grep-dctrl.1.cp | 388 | ||||
-rw-r--r-- | grep-dctrl.c | 548 | ||||
-rw-r--r-- | grep-dctrl.rc | 15 | ||||
-rw-r--r-- | i18n.h | 32 | ||||
-rw-r--r-- | msg.c | 93 | ||||
-rw-r--r-- | msg.h | 133 | ||||
-rw-r--r-- | paragraph.c | 135 | ||||
-rw-r--r-- | paragraph.h | 54 | ||||
-rw-r--r-- | predicate.c | 173 | ||||
-rw-r--r-- | predicate.h | 88 | ||||
-rw-r--r-- | rc.c | 130 | ||||
-rw-r--r-- | rc.h | 30 | ||||
-rw-r--r-- | strutil.c | 110 | ||||
-rw-r--r-- | strutil.h | 43 | ||||
-rw-r--r-- | util.c | 48 | ||||
-rw-r--r-- | util.h | 29 |
37 files changed, 3643 insertions, 0 deletions
@@ -0,0 +1,2 @@ +Antti-Juhani Kaijanaho + @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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. + + GNU GENERAL PUBLIC LICENSE + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) 19yy 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. + + <signature of Ty Coon>, 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 Library General +Public License instead of this License. diff --git a/Compatibility b/Compatibility new file mode 100644 index 0000000..07898d4 --- /dev/null +++ b/Compatibility @@ -0,0 +1,18 @@ +If you use grep-dctrl in a Debian package, you should depend on the +grep-dctrl package and heed the following compatibility notes: + + * Always call only the "grep-dctrl" executable. + Although the "grep-status" and "grep-available" symlinks + are installed by default, this may change in the future. + Those symlinks are meant for manual - not scripted - use. + + * Always specify an explicit file name + Don't rely on the implicit file name feature. The system + administrator may have changed the default file name. + + * Not all features have been with us in every version + Check if any of the features you use is mentioned in the + changelog. Use a versioned dependency on grep-dctrl, if it + is necessary. + + - ajk diff --git a/License-Blurb b/License-Blurb new file mode 100644 index 0000000..1379f1c --- /dev/null +++ b/License-Blurb @@ -0,0 +1,13 @@ + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4ea9c7d --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ + +sysconf = /etc + +CC = gcc -std=gnu99 +CFLAGS = -O2 -g -Wall -DENABLE_L_DEBUG -D_GNU_SOURCE -DSYSCONF=\"$(sysconf)\" + +CFLAGS += -DVERSION=\"$(shell dpkg-parsechangelog | grep '^Version' | cut -b10-)\" +CFLAGS += -DMAINTAINER='"$(shell grep ^Maintainer: debian/control | cut -b13-)"' + +#CFLAGS += -pg +#LDFLAGS += -pg + +LDLIBS = -lpub + +all : grep-dctrl grep-dctrl.1 + +grep-dctrl : grep-dctrl.o msg.o predicate.o util.o fsaf.o paragraph.o \ + fieldtrie.o rc.o strutil.o + +%.test : %.test.o + +%.test.o : %.c + $(CC) -c $(CFLAGS) -DTESTMAIN $< -o $@ + +%.1 : %.1.cp + sed 's*SYSCONF*$(sysconf)*' $< > $@ + +fsaf.test : fsaf.test.o msg.o + +clean : + $(RM) core grep-dctrl grep-dctrl.1 *.o @@ -0,0 +1,23 @@ +1.100 - a total rewrite + new feature: boolean queries + known regressions: + + unacceptably slow search in full paragraph + + no -Ffoo,bar,baz (equivalent boolean q available) + + no internationalization + +1.11 - added the -s option + +1.10 - made -c synonymous with --count + +1.7 - allowed several -F options and comma-separated list of + fields as -F's argument + +1.6 - disabled the -c option + +1.3 - fixed a segfault related to the -c option + deprecated the short -c option (use the long option instead) + +1.2 - added the -v option (see manpage for details) + New documentation file Compatibility. + +1.0 - no news is good news @@ -0,0 +1 @@ +dctrl-tools - Debian control file inspection tools @@ -0,0 +1,5 @@ +grep-dctrl is a command-line tool for searching and manipulating +certain Debian-specific files. It's not much use on other systems, +but it should still compile on a non-Debian system. You need Lars +Wirzenius' publib library to compile it (you should be able to find it +from the Debian distribution or at http://www.iki.fi/liw/programs/). @@ -0,0 +1,8 @@ +Things left to be done on grep-dctrl: + * Write a good Texinfo manual. + * Do translations of the messages to other languages + (we now have English). + * Fix any bugs. + +If you want to help with one of these (or you have some other ideas +for grep-dctrl), contact <ajk@debian.org>. diff --git a/debian/README.build-system b/debian/README.build-system new file mode 100644 index 0000000..3dd5cb9 --- /dev/null +++ b/debian/README.build-system @@ -0,0 +1,6 @@ + +$Id: README.build-system,v 1.4 2003/08/10 16:43:16 ajk Exp $ + +This package uses a new experimental debian/rules helper, librules.mk, +written by Antti-Juhani Kaijanaho <ajk@debian.org>. Documentation for +it is available in the file librules-manual.txt. diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c0f19d1 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,282 @@ +grep-dctrl (1.100) unstable; urgency=low + + * A (nearly) full rewrite (bumped minor version number to match) + * Includes an annoying one-time-per-user banner asking for testing (will + be removed in the future). + * debian/control [Standards-Version]: Upgrade to 3.6.0. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sun, 10 Aug 2003 18:33:05 +0300 + +grep-dctrl (1.12) unstable; urgency=low + + * matcher.c (find_field): Simplify code (this seems + to be a bit faster, too). + * This version was never uploaded. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Tue, 22 Apr 2003 19:33:09 +0300 + +grep-dctrl (1.11) unstable; urgency=low + + * The four-year near-anniversary overhaul. + * debian/copyright: Add copyright years. + * debian/copyright: Fix my snailmail address. + * debian/{prerm,postinst}: Remove (they handled only the FHS transition). + * debian/rules: Rewrote using my modernish rules helper. Closes: #164652. + * grep-dctrl.c: Don't use perror to report errors; instead use fprintf + and strerror so that the file name is reported. Closes: #162072. + * grep-dctrl.1.cp: Fix manpage syntax error, thanks to Bill Allombert. + Closes: #160521. + * grep-dctrl.c, matcher.h, matcher.c, buffer.h, buffer.c: + Implement -d switch, suggested by Chris Waters. Closes: #106175. + * po/fi.po: Updated + * matcher.c: Don't display a blank field when fields are selected, as + suggested by Horms. Closes: #167365. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sun, 16 Feb 2003 18:48:11 +0200 + +grep-dctrl (1.10) unstable; urgency=low + + * grep-dctrl.c, grep-dctrl.1.cp: Make -c synonymous with --count. + * grep-dctrl.1.cp: Add Bill Allombert's example. Closes: #145301. + * debian/control [Standards-Version]: Upgrade to 3.5.6 + + debian/rules: Implement debug & nostrip + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Thu, 25 Jul 2002 21:44:28 +0300 + +grep-dctrl (1.9) unstable; urgency=low + + * intl/Makefile.in: We don't have a ../config.h. Closes: #106001 + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Mon, 30 Jul 2001 20:09:18 +0300 + +grep-dctrl (1.8) unstable; urgency=low + + * Fix manpage, closes: #102021 + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Thu, 19 Jul 2001 19:40:55 +0300 + +grep-dctrl (1.7) unstable; urgency=low + + * Added copyright blurb to some source files that missed it. + * grep-dctrl.c, matcher.[ch]: Implement multiple -F options, + allows search in several fields at once. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sat, 20 May 2000 18:32:00 +0300 + +grep-dctrl (1.6) unstable; urgency=low + + * Disable the -c switch to allow its meaning to be changed + in woody+1. + * grep-dctrl.1.cp: Added COMPATIBILITY section, based on + the file Compatibility. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Wed, 10 May 2000 15:29:02 +0300 + +grep-dctrl (1.5) unstable; urgency=low + + * Incorporate bugfix release 1.3a into the development branch. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sun, 5 Mar 2000 14:23:07 +0200 + +grep-dctrl (1.4) unstable; urgency=low + + * debian/control [Standards-Version]: 3.1.1 + + debian/control [Build-Depends]: Added + * debian/control [Description]: Improved. + * debian/check-sourcedeps: Removed. + * debian/rules [debian/build-depends.stamp]: Removed. + * buffer.c, buffer.h: Make buffer_clear() an inline function. + * grep-dctrl.c (main), matcher.h (struct matcher_t), + matcher.c (grep_control): Implement the --count option + suggested by Dirk Eddelbuettel. + * configure.in, msg.h: Added a --enable-debug-level switch + * matcher.c (slurp_paragraph): Rewrote for speed. + * Versions 1.3 and 1.4 together closes: #57144. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sun, 6 Feb 2000 21:42:30 +0200 + +grep-dctrl (1.3a) frozen; urgency=low + + * matcher.c (find_field): Unroll the first iteration of the first loop + and then remove the special-case p==s if in the loop body. + Closes: bug#59455. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sun, 5 Mar 2000 14:21:41 +0200 + +grep-dctrl (1.3) frozen; urgency=low + + * grep-dctrl.c (main): Add a colon after c in getopt's + argument, fixing the segfault in bug#57144. This fix is meant + for frozen and is minimal; I will upload a more complicated fix + (but more correct in the long run) separately to unstable, since + the better fix requires feature changes. + * grep-dctrl.c (print_usage, main), grep-dctrl.1.cp, po/fi.po: + Deprecated short option "-c" to allow its meaning to be changed later + in woody. Functionality is not changed in this version; only + messages about the deprecation have been added. This must go to + potato to allow a smooth transition to the better fix for bug#57144. + * debian/copyright: Updated copyright years (added 2000). + * debian/NEWS: documented this release's changes + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sun, 6 Feb 2000 14:50:06 +0200 + +grep-dctrl (1.2) unstable; urgency=low + + * grep-dctrl.c (main), matcher.h (struct matcher_t), matcher.c + (grep_control): Implement the -v option suggested by David Coe. + Closes: #45115. + * debian/rules: Modernize. + + Factor install into a variable. + + Don't use install_gzip. + + Use stamp files. + + Split clean into {build,binary}-clean + + Use a separate target for the configure call. + + Don't test for rootness. + + Remove $(rootdir) at start of binary targets. + * grep-dctrl.1.cp: Documented the -v option. + * debian/{prerm,postinst,rules}: Implement the /usr/doc transition method. + * po/fi.po: Updated. + * Compatibility: New file. + * debian/rules: Install Compatibility. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Wed, 15 Sep 1999 20:06:20 +0300 + +grep-dctrl (1.1) unstable; urgency=low + + * matcher.c (grep_control): Only return on feof if the para is empty. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Mon, 2 Aug 1999 21:42:53 +0300 + +grep-dctrl (1.0) unstable; urgency=low + + * New major version. No major changes, just polishing - we have + been converging to 1.0 for some time now. + * grep-dctrl.c (main): Don't allow -s to be used many times, + as it does not work in the obvious way. + * Updated the Finnish translation. + * grep-dctrl.1.cp: Updated the DIAGNOSTICS section. + * Added files TODO, NEWS and README to the source distribution. + Only README is not relevant to Debian users, so not installing it. + * configure.in: Check whether we have dpkg-parsechangelog, and + use a default dummy version number if we don't. This allows + the package to build more easily on a non-Debian system. + * Unsymlink things that had symlinks outside the source. + * Added getopt source for the benefit of broken systems. + * configure.in: Use /usr/share/common-licenses/GPL as a default for + the copying file location. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sat, 10 Jul 1999 20:58:46 +0300 + +grep-dctrl (0.16) unstable; urgency=low + + * Upgraded Standards-Version to 3.0.0.0, with necessary + changes to debian/rules and debian/copyright. + * configure.in: Added an anchor to the grep in the version number, + finder, and reran autoconf + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Fri, 2 Jul 1999 10:42:24 +0300 + +grep-dctrl (0.15) unstable; urgency=low + + * Removed the file called "1" from the source package. + Closes: bug#40358. + * debian/dpkg-sourcedeps: New file. + * debian/rules: Converted the source dependency check to use + debian/dpkg-sourcedeps + * grep-dctrl.1.cp: Wrote an EXAMPLES section. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Mon, 28 Jun 1999 18:02:36 +0300 + +grep-dctrl (0.14) unstable; urgency=low + + * matcher.c (grep_control): Test for EOF before a paragraph + is processed, not after. This fixes an unreported bug + that caused grep-dctrl -sPackage '' output a spurious + empty Package: line. + * debian/rules: Added a simple source dependency check. + * debian/rules: Use -isp with dpkg-gencontrol. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Sat, 26 Jun 1999 03:21:20 +0300 + +grep-dctrl (0.13) unstable; urgency=low + + * buffer.c (buffer_trim): I had ">=" in the loop + condition, should be "<". Corrected that; this + fixes bug #38047. + * Added debug_messages and asserts all over buffer.c + while hunting bug #38047. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Thu, 20 May 1999 21:47:31 +0300 + +grep-dctrl (0.12) unstable; urgency=low + + * Removed old-Makefile.in from the tarball. + * Updated Finnish translation. + * Made field name matching ignore case. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Tue, 18 May 1999 08:53:42 +0300 + +grep-dctrl (0.11) unstable; urgency=low + + * Added shorthand option -P. + * Fixed a typo in config file name in the manual page. + * grep_dctrl (set_match_field): New function. + * Fixed some -Wall warnings in matcher.c. + * rc.c, line 107: Had forgotten the `++' in front of lineno. + Corrected that. + * Added the option -n for suppressing the field names on output. + * Added a some informational messages to rcfile parsing. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Fri, 9 Apr 1999 20:24:30 +0300 + +grep-dctrl (0.10) unstable; urgency=low + + * Got rid of version.h. The defines are now done on the + compiler command line. This will avoid the harmful rebuild of + grep-dctrl.o in Makefile's install target. Fixes bug#35527. + * Added the generated manual page to CLEANFILES, so that the + manpage gets rebuilt. + * Clean off backup files on debian/rules clean. + * rc.c: Search user's rcfile first. + * rc.c: Upgrade the "reading config file" message from debug message + to informational. + * Updated the Finnish translation. + * Prettified the long description in debian/control. + * matcher.c: Downgraded several messages to the debug level `debug' so that + the level `informational' becomes much less verbose. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Mon, 5 Apr 1999 23:35:39 +0300 + +grep-dctrl (0.9) unstable; urgency=low + + * Introduced a config file system for specifying default + input file names based on the base name of argv[0]. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Wed, 24 Mar 1999 22:02:49 +0200 + +grep-dctrl (0.8) unstable; urgency=low + + * Rewrote build system to use autoconf & automake. + * Internationalized. Finnish translation is included. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Fri, 19 Mar 1999 11:07:15 +0200 + +grep-dctrl (0.7) unstable; urgency=low + + * Added an option for exact matches. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Tue, 9 Mar 1999 02:58:30 +0200 + +grep-dctrl (0.6) unstable; urgency=low + + * Strip whitespace at the start of a field body before searching in it. + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Mon, 8 Mar 1999 22:28:23 +0200 + +grep-dctrl (0.5) unstable; urgency=low + + * First released version. + * This time the uploaded changes and .dsc are signed :-( + + -- Antti-Juhani Kaijanaho <ajk@debian.org> Mon, 1 Mar 1999 22:10:01 +0200 + diff --git a/debian/conffiles b/debian/conffiles new file mode 100644 index 0000000..d5c1f12 --- /dev/null +++ b/debian/conffiles @@ -0,0 +1 @@ +/etc/grep-dctrl.rc diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..2b2684d --- /dev/null +++ b/debian/control @@ -0,0 +1,26 @@ +Source: grep-dctrl +Section: utils +Priority: optional +Maintainer: Antti-Juhani Kaijanaho <ajk@debian.org> +Standards-Version: 3.6.0 +Build-Depends: publib-dev + +Package: grep-dctrl +Architecture: any +Depends: ${shlibs:Depends} +Description: Grep Debian package information + The grep-dctrl program can answer such questions as + * "What is the Debian package foo?" + * "Which version of the Debian package bar is now current?" + * "Which Debian packages does John Doe maintain?" + * "Which Debian packages are somehow related to the Scheme + programming language?" + and with some help + * "Who maintain the essential packages of a Debian system?" + given a useful input file. + . + It is a specialised grep program that is meant for processing any + file which has the general format of a Debian package control file. + These include the dpkg available file, the dpkg status file, and the + Packages files on a distribution medium (such as a Debian CD-ROM or + an FTP site carrying Debian). diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..e193d9c --- /dev/null +++ b/debian/copyright @@ -0,0 +1,36 @@ +This package and the program in it were written and debianized by +Antti-Juhani Kaijanaho <ajk@debian.org>. + +Copyright: + + Copyright (C) 1999, 2000, 2001, 2002, 2003 Antti-Juhani Kaijanaho + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + The author can be reached via mail at (ISO 8859-1 charset for the city) + Antti-Juhani Kaijanaho + Helokantie 1 A 16 + FIN-40640 JYVÄSKYLÄ + FINLAND + EUROPE + and via electronic mail from + gaia@iki.fi + If you have a choice, use the email address; it is more likely to + stay current. + + +In Debian systems, the GNU GPL version 2 is available at +/usr/share/common-licenses/GPL . diff --git a/debian/librules-manual.txt b/debian/librules-manual.txt new file mode 100644 index 0000000..f577112 --- /dev/null +++ b/debian/librules-manual.txt @@ -0,0 +1,131 @@ +Manual for the librules helper -*- Text -*- +------------------------------ +Last modified: 2002-10-16 + +This file documents an experimental new debian/rules helper, a +makefile called "librules.mk", which does all the boring work of +building a package. + +Usage: + +The very first non-comment thing in your debian/rules should be the +following line: +librules_interface = 2 +This helps to spot incompatibilities with debian/rules and the +librules.mk file currently in use. +(See the section "Incompatible changes" for what to look for when +upgrading from an old version.) + +Include "debian/librules.mk" just after that line. Precede it with a +variable definition "librules_native_pkg=yes" if the package you are building +is a Debian native package. + +Define a target debian/stamp/build that builds the package (like the +build target does in conventional debian/rules files). Put "touch $@" +as the last action in that rule. + +For every binary package <package> you want to build: + + - If the package is "arch: all", make debian/stamp/binary/indep depend + on debian/stamp/binary/<package>; otherwise make debian/stamp/binary/arch + depend on that target + + - Write a target debian/stamp/binary/<package> using the following template: + +debian/stamp/binary/<package>: package=<package> +debian/stamp/binary/<package>: debian/stamp/build + $(prebinary) + # Add here your own commands + $(postbinary) + touch $@ + + The $(prebinary) macro will create a skeletal build tree for the + package. It also install the copyright file (debian/copyright) + and the Debian changelog file (debian/changelog). + + See below for instructions about how to write your own install commands. + + The $(postbinary) macro fixes directory permissions, generates the binary + control file and builds the package. + + - You may want to define targets "clean", "clean-binary" and "clean-build" + to reverse the effects of your own commands in the build and binary targets. + The librules.mk file cleans up for itself, you don't need to worry about that. + + +How to write your own commands for binary targets: + +Use the following macros to install files: + + $(install_exec) SOURCE TARGET + $(install_exec) SOURCE SOURCE ... DIRECTORY + installs one or more binary executables + (TARGET need not be a directory name) + + $(install_nonex) SOURCE TARGET + $(install_nonex) SOURCE SOURCE ... DIRECTORY + install one or more non-executable files + (TARGET need not be a directory name) + + $(install_dir) DIRECTORY + create the directory + + $(install_script) SOURCE TARGET + $(install_script) SOURCE SOURCE ... DIRECTORY + install one or more executable scripts + (TARGET need not be a directory name) + + $(install_prerm) + $(install_postrm) + $(install_preinst) + $(install_postinst) + install debian/prerm.$(package) etc. + to DEBIAN using the appropriate name + +The macros above are wrappers around the "install" utility. + + $(install_symlink) SOURCE [TARGET] + Install a symlink from SOURCE to TARGET + (This macro is a wrapper around ln -s) + + $(gzip) FILE ... + Compress the given files + (This is a wrapper around gzip) + + $(strip_lib) FILE ... + Strip the given files the way shared libraries are stripped + (This is a wrapper around strip) + + +*Never* refer to a file in the install target tree by their real name. +Use the following macros instead: + + $(rootdir) - the directory that masquerades as / in the target tree + (usually a subdirectory under debian/tmp) + $(ctldir) - the directory where control files are installed + (usually $(rootdir)/DEBIAN) + $(bindir) - the main binary directory + (usually $(rootdir)/usr/bin) + $(docdir) - the main doc directory + (usually $(rootdir)/usr/share/doc/<package>) + ... +(see librules.mk for what's available) + + +If your debian/rules needs the dpkg-architecture variables, add the +definition "librules_need_archvars=yes" before the include at the top +of the file. If you use this feature, you need to Build-Depend on +"dpkg-dev (>= 1.4.1.5)". + +If you want to patch/unpatch the package, add the definitions +"librules_patch_support=yes" and "librules_patches=file1.diff +file2.diff ... filen.diff" before the include at the top of the file. +If you use this, you need to Build-Depend on "patch". + + +Incompatible changes +-------------------- + +From 1 to 2: + - {pre,post}{rm,inst} scripts are not installed by default + (previously prerm and postinst were unconditionally installed) diff --git a/debian/librules.mk b/debian/librules.mk new file mode 100644 index 0000000..c5fa631 --- /dev/null +++ b/debian/librules.mk @@ -0,0 +1,180 @@ +# librules.mk - a library of convenient rules and macros for debian/rules files +# +# Copyright © 1999, 2000, 2002, 2003 Antti-Juhani Kaijanaho. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this file, to deal in this file without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of this file, and to permit persons to whom this file is furnished +# to do so, subject to the following condition: The above copyright +# notice and this permission notice shall be included in all copies or +# substantial portions of this file. +# +# THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FIT- NESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL SOFTWARE IN THE PUBLIC INTEREST, +# INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +# IN CONNECTION WITH THIS FILE OR THE USE OR OTHER DEALINGS IN THIS +# FILE. +# +# Except as contained in this notice, the name of the author(s) of +# this file shall not be used in advertising or otherwise to promote +# the sale, use or other dealings in this file without prior written +# authorization from the author(s). + +# This file is set up to be compliant with Debian Standards Version +# 3.6.0. + +# Changes: +# 2003-08-10 ajk Add $(etcdir) +# 2002-10-16 ajk Don't force installing the prerm/postinst scripts +# Instead, install them if present. +# INCOMPATIBLE CHANGE; updated interface to 2 + +default: + @echo You need to specify a target. + @exit 1 + +librules_a_variable_just_to_run_the_commands1 := $(shell mkdir debian/stamp) +librules_a_variable_just_to_run_the_commands2 := $(shell mkdir debian/stamp/binary) + +# Make sure we don't get used by an incompatible debian/rules +# WHEN YOU MAKE INCOMPATIBLE CHANGES, EDIT THIS! +ifneq ($(librules_interface),2) +$(error incompatible debian/rules) +endif + +# Standard interface targets +build: debian/stamp/build +binary: binary-indep binary-arch +binary-arch: debian/stamp/binary/arch +binary-indep: debian/stamp/binary/indep +clean: clean-build clean-binary clean-std + + +# Nonstandard interface targets +clean-build: clean-build-std +clean-binary: clean-binary-std + +# Stamp targets for the standard binary targets +debian/stamp/binary/arch: debian/stamp/build + touch $@ + +debian/stamp/binary/indep: debian/stamp/build + touch $@ + +.PHONY: default build binary binary-arch binary-indep \ + clean clean-build clean-binary + +ifeq ($(librules_need_archvars),yes) +DEB_BUILD_ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH) +DEB_BUILD_GNU_TYPE = $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +DEB_BUILD_GNU_CPU = $(shell dpkg-architecture -qDEB_BUILD_GNU_CPU) +DEB_BUILD_GNU_SYSTEM = $(shell dpkg-architecture -qDEB_BUILD_GNU_SYSTEM) +DEB_HOST_ARCH = $(shell dpkg-architecture -qDEB_HOST_ARCH) +DEB_HOST_GNU_TYPE = $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_HOST_GNU_CPU = $(shell dpkg-architecture -qDEB_HOST_GNU_CPU) +DEB_HOST_GNU_SYSTEM = $(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM) +endif + +CFLAGS = -O2 -Wall +STRIP = +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) +CFLAGS += -g +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) +STRIP = -s +endif + +export CFLAGS + +install := install -o root -g root +install_exec := $(install) -m 0755 $(STRIP) +install_nonex := $(install) -m 0644 +install_dir := $(install) -m 0755 -d +install_script := $(install) -m 0755 +install_symlink := ln -s +gzip := gzip -9 +strip_lib := strip --strip-unneeded + +tmpdir := $(shell pwd)/debian/tmp + +# These must not be :='s! +rootdir = $(tmpdir)/$(package) +ctldir = $(rootdir)/DEBIAN +etcdir = $(rootdir)/etc +bindir = $(rootdir)/usr/bin +sbindir = $(rootdir)/usr/sbin +docdir = $(rootdir)/usr/share/doc/$(package) +exampledir = $(docdir)/examples +mandir = $(rootdir)/usr/share/man +elispdir = $(rootdir)/usr/share/emacs/site-lisp +emacs_d_dir = $(etcdir)/emacs/site-start.d +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +man3dir = $(mandir)/man3 +man4dir = $(mandir)/man4 +man5dir = $(mandir)/man5 +man6dir = $(mandir)/man6 +man7dir = $(mandir)/man7 +man8dir = $(mandir)/man8 +sharedir = $(rootdir)/usr/share/$(package) +libdir = $(rootdir)/usr/lib/$(package) +docbasedir = $(rootdir)/usr/share/doc-base +usrlib = $(rootdir)/usr/lib +includedir = $(rootdir)/usr/include + +ifeq ($(librules_native_pkg),yes) +librules_changelog=changelog +else +librules_changelog=changelog.Debian +endif + +install_prerm = $(install_script) debian/prerm.$(package) $(ctldir)/prerm +install_postrm = $(install_script) debian/postrm.$(package) $(ctldir)/postrm +install_preinst = $(install_script) debian/preinst.$(package) $(ctldir)/preinst +install_postinst = $(install_script) debian/postinst.$(package) $(ctldir)/postinst + + +define prebinary + $(RM) -r $(rootdir) + $(install_dir) $(ctldir) + $(install_dir) $(docdir) + $(install_nonex) debian/copyright $(docdir) + $(install_nonex) debian/changelog $(docdir)/$(librules_changelog) + $(gzip) $(docdir)/$(librules_changelog) +endef + +define postbinary + chmod -R g-s $(rootdir) + dpkg-gencontrol -isp -p$(package) -P$(rootdir) $(gencontrol_options) + dpkg --build $(rootdir) .. +endef + +clean-build-std: + rm -f debian/stamp/build + +clean-binary-std: + rm -f debian/stamp/binary/* + rm -f debian/files debian/substvars + rm -rf $(tmpdir) + +clean-std: + rm -rf debian/stamp/ + +# Patching support +ifeq ($(librules_patch_support),yes) +debian/stamp/build: debian/stamp/patch +clean-build: unpatch + +debian/stamp/patch: + $(foreach patch, $(librules_patches), patch -fs < $(patch) && )true + touch $@ + +unpatch: debian/stamp/patch + $(foreach patch, $(librules_patches), patch -fsR < $(patch) && )true + rm -f debian/stamp/patch +endif diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..71ed474 --- /dev/null +++ b/debian/rules @@ -0,0 +1,54 @@ +#!/usr/bin/make -f +# Written by Antti-Juhani Kaijanaho <ajk@debian.org>. +# You may treat this file as if it were in the public domain. + +librules_interface = 2 +librules_native_pkg=yes +include debian/librules.mk + +debian/stamp/build: #debian/stamp/build-configure + $(MAKE) + touch $@ + +#debian/stamp/build-configure: +# ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share +# touch $@ + +clean-build: + -$(MAKE) clean + +debian/stamp/binary/arch: debian/stamp/binary/grep-dctrl + +debian/stamp/binary/grep-dctrl: package=grep-dctrl +debian/stamp/binary/grep-dctrl: debian/stamp/build + $(prebinary) +# Install by the master makefile +# $(MAKE) prefix=$(rootdir)/usr sysconfdir=$(rootdir)/etc \ +# mandir=$(mandir) install +# Install configuration file + $(install_dir) $(etcdir) + $(install_nonex) grep-dctrl.rc $(etcdir) +# Install the binary. + $(install_dir) $(bindir) + $(install_exec) grep-dctrl $(bindir) + set -e ; for dest in grep-status grep-available ; do \ + $(install_symlink) grep-dctrl $(bindir)/$$dest ; \ + done +# Zip the manual page. + $(install_dir) $(man1dir) + $(install_nonex) grep-dctrl.1 $(man1dir)/ + $(gzip) $(man1dir)/grep-dctrl.1 + set -e ; for dest in grep-status grep-available ; do \ + $(install_symlink) grep-dctrl.1.gz $(man1dir)/$$dest.1.gz ; \ + done +# Install the supporting documentation. + $(install_nonex) TODO NEWS Compatibility $(docdir) +# Install config file information + $(install_nonex) debian/conffiles $(rootdir)/DEBIAN +# Get the shared library deps + dpkg-shlibdeps $(bindir)/grep-dctrl + $(postbinary) + touch $@ + +clean-binary: + $(RM) *~ diff --git a/fieldtrie.c b/fieldtrie.c new file mode 100644 index 0000000..3d6019a --- /dev/null +++ b/fieldtrie.c @@ -0,0 +1,75 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <assert.h> +#include <ctype.h> +#include <string.h> +#include "fieldtrie.h" +#include "msg.h" + +void fieldtrie_init(fieldtrie_t * trie) +{ + assert(trie != 0); + for (size_t i = 0; i < UCHAR_MAX; i++) { + trie->fields[i] = 0; + } + trie->nextfree = 0; +} + +size_t fieldtrie_insert(fieldtrie_t * trie, char const * s) +{ + size_t slen = strlen(s); + size_t r = fieldtrie_lookup(trie, s, slen); + if (r != -1) return r; + struct field_bucket * b = malloc(sizeof *b); + if (b == 0) fatal_enomem(0); + b->name = malloc(slen+1); + if (b->name == 0) fatal_enomem(0); + strcpy((char*)b->name, s); + b->namelen = slen; + b->inx = trie->nextfree++; + unsigned char c = tolower((unsigned char)(b->name[0])); + b->next = trie->fields[c]; + trie->fields[c] = b; + return b->inx; +} + +size_t fieldtrie_lookup(fieldtrie_t * trie, char const * s, size_t n) +{ + for (struct field_bucket * b = trie->fields[tolower((unsigned char)s[0])]; + b != 0; + b = b->next) { + if (n == b->namelen && + strncasecmp(s, b->name, n) == 0) return b->inx; + } + return (size_t)(-1); +} + +void fieldtrie_clear(fieldtrie_t * trie) +{ + for (size_t i = 0; i < UCHAR_MAX; i++) { + struct field_bucket * b = trie->fields[i]; + while (b != 0) { + struct field_bucket * bn = b->next; + free(b); + b = bn; + } + trie->fields[i] = 0; + } + trie->nextfree = 0; +} diff --git a/fieldtrie.h b/fieldtrie.h new file mode 100644 index 0000000..7ae7d8c --- /dev/null +++ b/fieldtrie.h @@ -0,0 +1,52 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FIELDTRIE_H +#define FIELDTRIE_H + +#include <limits.h> +#include <stddef.h> + +struct field_bucket { + char const * name; + size_t namelen; + size_t inx; + struct field_bucket * next; +}; + +struct fieldtrie_private { + size_t nextfree; + /* A one-level trie listing all field names occurring in the + * atomic predicates. */ + struct field_bucket * fields[UCHAR_MAX]; +}; + +typedef struct fieldtrie_private fieldtrie_t; + +void fieldtrie_init(fieldtrie_t *); + +// case-insensitive +size_t fieldtrie_insert(fieldtrie_t *, char const *); + +// case-insensitive +// (size_t)(-1) if failed +size_t fieldtrie_lookup(fieldtrie_t *, char const *, size_t n); + +void fieldtrie_clear(fieldtrie_t *); + +#endif /* FIELDTRIE_H */ @@ -0,0 +1,230 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "fsaf.h" +#include "msg.h" + +#if !defined(_POSIX_MAPPED_FILES) || _POSIX_MAPPED_FILES == -1 +# warning "No mmap support detected." +#endif + +#define READAHEAD 1 + +static size_t pagesize; + +static inline +size_t align(size_t offset, bool ceil) +{ + return (offset / pagesize + (ceil && offset % pagesize != 0)) * pagesize; +} + +FSAF * fsaf_fdopen(int fd) +{ + pagesize = (size_t) sysconf (_SC_PAGESIZE); + FSAF * rv = malloc(sizeof *rv); + if (rv == 0) { errno = ENOMEM; return 0; } + + rv->fd = fd; + rv->eof_mark = (size_t)(-1); + rv->buf = 0; + rv->buf_capacity = 0; + rv->buf_offset = 0; + rv->buf_size = 0; + rv->invalid_mark = 0; +#ifdef _POSIX_MAPPED_FILES + rv->mapped = false; + rv->topread = 0; +#endif + + struct stat stat; + int res = fstat(fd, &stat); + if (res == -1) goto fail; + + if (S_ISREG(stat.st_mode)) { + rv->eof_mark = stat.st_size; +#ifdef _POSIX_MAPPED_FILES + /* try mmapping, it is a regular file */ + size_t eof_pagebound = align(rv->eof_mark, true); + char * buf = mmap(0, eof_pagebound, PROT_READ, MAP_SHARED, fd, 0); + if (buf != MAP_FAILED) { + debug_message("mmapping", 0); + rv->mapped = 1; + rv->buf = buf; + rv->buf_capacity = eof_pagebound; + rv->buf_offset = 0; + rv->buf_size = rv->eof_mark; + //madvise(rv->buf, rv->buf_capacity, MADV_SEQUENTIAL); + return rv; + } +#endif + } + + return rv; +fail: + free(rv); + return 0; +} + +void fsaf_close(FSAF * fp) +{ + assert(fp != 0); +#if _POSIX_MAPPED_FILES + if (fp->mapped) { + munmap(fp->buf, fp->buf_capacity); + free(fp); + return; + } +#endif + free(fp->buf); + free(fp); +} + +static void slurp(FSAF * fp, size_t len) +{ + assert(fp != 0); + assert(len > 0); + if (fp->buf_size + len > fp->buf_capacity) { + size_t nc = fp->buf_capacity; + if (nc == 0) nc = 256; + while (nc < fp->buf_size + len) nc *= 2; + char * nb = realloc(fp->buf, nc); + if (nb != 0) { + fp->buf = nb; + fp->buf_capacity = nc; + } else { + assert(fp->invalid_mark >= fp->buf_offset); + size_t delta = fp->invalid_mark - fp->buf_offset; + if (delta == 0) { + /* Cannot move needed stuff... */ + fatal_enomem(0); + } + memmove(fp->buf, fp->buf + delta, fp->buf_size - delta); + fp->buf_offset += delta; + fp->buf_size -= delta; + if (fp->buf_size + len > fp->buf_capacity) { + len = fp->buf_capacity - fp->buf_size; + } + } + } + assert(len > 0); + assert(fp->buf_size + len <= fp->buf_capacity); + + ssize_t res; + do { +// res = read(fp->fd, fp->buf + fp->buf_size, len); + res = read(fp->fd, fp->buf + fp->buf_size, fp->buf_capacity - fp->buf_size); + } while (res == -1 && errno == EINTR); + if (res == 0) { + fp->eof_mark = fp->buf_offset + fp->buf_size; + } + fp->buf_size += res; +} + +//static inline +struct fsaf_read_rv fsaf_read(FSAF * fp, size_t offset, size_t len) +{ + struct fsaf_read_rv rv; + + /* Make sure we don't read past the EOF mark. */ + if (offset + len > fp->eof_mark) len = fp->eof_mark - offset; + +#if _POSIX_MAPPED_FILES + if (fp->mapped) { +#if 0 /* madvise seems not to give a noteworthy efficiency boost */ + /* Notify the kernel that we will soon want more of + * the data, but do this only once for each page! */ + if (offset + len >= fp->topread) { + size_t base = align(offset - fp->buf_offset, 1); + size_t rl = READAHEAD * pagesize; + madvise(fp->buf + base, rl, MADV_WILLNEED); + fp->topread += rl; + } +#endif + } else +#endif + { + /* Ensure that we have enough data in the buffer. + * This is only executed if we are not dealing with a + * mapped file. */ + assert(offset >= fp->buf_offset); + if (offset - fp->buf_offset + len > fp->buf_size) { + slurp(fp, offset - fp->buf_offset + len - fp->buf_size); + if (offset - fp->buf_offset + len > fp->buf_size) { + len = fp->buf_size - (offset - fp->buf_offset); + } + } + + } + + assert(offset - fp->buf_offset + len <= fp->buf_size); + assert(offset + len <= fp->eof_mark); + rv.b = fp->buf + (offset - fp->buf_offset); + rv.len = len; + return rv; +} + +void fsaf_invalidate(FSAF * fp, size_t offset) +{ + if (fp->eof_mark >= offset) return; + +#ifdef _POSIX_MAPPED_FILES + if (fp->mapped) { + size_t old = align(fp->eof_mark - fp->buf_offset, 0); + size_t new = align(offset - fp->buf_offset, 0); + madvise(fp->buf + old, new - old, MADV_DONTNEED); + } +#endif + + fp->eof_mark = offset; +} + +#ifdef TESTMAIN +#include <stdio.h> +volatile char c; +int main(int argc, char * argv[]) +{ + if (argc == 1) { + set_loglevel(L_DEBUG); + FSAF * fp = fsaf_fdopen(STDIN_FILENO); + assert(fp != 0); + size_t i = 0; + while (i < fsaf_eof(fp)) { + struct fsaf_read_rv rr = fsaf_read(fp, i, 1); + //fwrite(rr.b, 1, rr.len, stdout); + c = rr.b[0]; + i += rr.len; + } + fsaf_close(fp); + } else { + int ch; + while ((ch = getchar()) != EOF) { + c = ch; + } + } + return 0; +} +#endif @@ -0,0 +1,80 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef FSAF_H +#define FSAF_H + +#include <assert.h> +#include <stdbool.h> + +/* FAST (MOSTLY) SEQUENTIAL-ACCESS FILE LAYER */ + +struct fsaf_private { + int fd; + char * buf; + size_t buf_capacity; + size_t buf_offset; + size_t buf_size; + size_t invalid_mark; + size_t eof_mark; /* can be (size_t)(-1) if not reached yet */ +#ifdef _POSIX_MAPPED_FILES + bool mapped; + size_t topread; /* marks the top of what has been read ahead */ +#endif +}; + +typedef struct fsaf_private FSAF; + +/* Open a FSAF for the given fd. Only read access is supported for + * now. The whole file is initially valid. */ +FSAF * fsaf_fdopen(int fd); + +/* Close the given FSAF. This DOES NOT close the underlying fd. */ +void fsaf_close(FSAF *); + +/* Return a pointer to a buffer containing len bytes from the FSAF + * starting at offset. Note that if offset is below the invalid mark, + * we return b = NULL. This is a CHEAP operation, if the full range + * has already been accessed. The buffer may be invalidated by any + * subsequent call to this function. */ +struct fsaf_read_rv { + char const * b; + size_t len; +} fsaf_read(FSAF *, size_t offset, size_t len); + +static inline +int fsaf_getc(FSAF * fp, size_t offset) +{ + if (offset >= fp->eof_mark) return -1; + struct fsaf_read_rv r = fsaf_read(fp, offset, 1); + if (offset >= fp->eof_mark) return -1; + assert(r.len == 1); + return (unsigned char)r.b[0]; +} + + +/* Invalidate all bytes in FSAF up to and excluding offset. */ +void fsaf_invalidate(FSAF *, size_t offset); + +/* Return an upper bound for the end of file, either the smallest + * offset beyond eof or (size_t)(-1). */ +static inline +size_t fsaf_eof(FSAF * fp) { return fp->eof_mark; } + + +#endif /* FSAF_H */ diff --git a/grep-dctrl.1.cp b/grep-dctrl.1.cp new file mode 100644 index 0000000..ac4fbee --- /dev/null +++ b/grep-dctrl.1.cp @@ -0,0 +1,388 @@ +.TH GREP-DCTRL 1 2003-08-10 "Debian Project" "Debian user's manual" +\" Copyright (C) 1999, 2000, 2001, 2002, 2003 Antti-Juhani Kaijanaho +\" <gaia@iki.fi> +\" Permission is granted to make and distribute verbatim copies of +\" this manual provided the copyright notice and this permission notice +\" are preserved on all copies. +\" +\" Permission is granted to copy and distribute modified versions of this +\" manual under the conditions for verbatim copying, provided that the +\" entire resulting derived work is distributed under the terms of a +\" permission notice identical to this one. +\" +\" Permission is granted to copy and distribute translations of this +\" manual into another language, under the above conditions for modified +\" versions, except that this permission notice may be included in +\" translations approved by the authors of this manual instead of in +\" the original English. +\" +.SH NAME +grep-dctrl \- grep Debian control files +.SH SYNOPSIS +.B grep-dctrl +[options] predicate +[ +.IR file " ..." +] +.sp +.B grep-dctrl +--copying | --help | --version | -ChV +.SH DESCRIPTION +The grep-dctrl program can answer such questions as +.IR "What is the Debian package foo?" , +.IR "Which version of the Debian package bar is now current?" , +.IR "Which Debian packages does John Doe maintain?" , +.I "Which Debian packages are somehow related to the Scheme" +.IR " programming language?" , +and with some help, +.IR "Who maintain the essential packages of a Debian system?" , +given a useful input file. +.PP +It is a specialised grep program that is meant for processing any file +which has the general format of a Debian package control file, as +described in the Debian Packaging Manual. These include the dpkg +available file, the dpkg status file, and the Packages files on a +distribution medium (such as a Debian CD-ROM or an FTP site carrying +Debian). +.PP +You must give a search predicate on the command line. The predicate +defines which kind of paragraphs (aka package records) are output. An +atomic predicate is a search pattern along with any options that +modify it. Possible modifiers are --eregex, --field, --ignore-case, +-P, --regex and --exact-match, along with their single-letter +equivalents. An atomic predicate gives a pattern to search for. By +default, the search is a case-sensitive fixed substring match on each +paragraph (in other words, package record) in the input. With +suitable modifiers, this can be changed: the search can be +case-insensitive and the pattern can be seen as an extended POSIX +regular expression. Predicates can be combined using the connectives +--and, --or and --not. Predicates can be grouped using parentheses. +.PP +By default, the full matching paragraphs are printed on the standard +output; specific fields can be selected for output with the -s option. +.PP +After the predicate comes zero or more file names. If no file names +are specified, the file name is searched in configuration files. The +input file from the first program name \- input file association with +the correct program name is used. The program names are matched with +the base form of the name of the current program (the 0'th command +line argument, if you will). The file name "-" is taken to mean the +standard input stream. The files are searched in order but +separately; they are +.B not +concatenated together. In other words, the end of a file always +implies the end of the current paragraph. +.PP +There is one exception to the above: if the program name is +.BR grep-dctrl , +the default input source is always standard input; this cannot be +overridden by the configuration file. +.SH OPTIONS +.SS Atomic predicate modifiers +.IP "-F FIELD,FIELD,...; --field=FIELD,FIELD,..." +Restrict pattern matching to the FIELDs given. +.B Multiple fields in one -F is broken currently. +Use the -o option in the mean time. +.IP -P +Shorthand for "-FPackage". +.IP "-e, --eregex" +Regard the pattern of the current atomic predicate as an extended +POSIX regular expression +.IP "-r, --regex" +The pattern of the current atomic predicate is a standard POSIX regular expression. +.IP "-i, --ignore-case" +Ignore case when looking for a match in the current atomic predicate. +.IP "-X, --exact-match" +Do an exact match (as opposed to a substring match) in the current +atomic predicate. +.SS Predicate connectives +.IP "-!, --not, !" +Negate the following predicate. +.IP "-o, --or" +Disjunct the preceding and the following predicate. +.IP "-a, --and" +Conjunct the preceding and the following predicate. +.IP "( ... )" +Parentheses can be used for grouping. Note that they need to be +escaped for most shells. +.SS Output format modifiers +.IP "-s FIELD,FIELD,...; --show-field=FIELD,FIELD,..." +Show only the body of these fields from the matching paragraphs. The +field names must not include any colons or commas. Commas are used to +delimit field names in the argument to this option. The fields are +shown in the order given here. +.IP "-d" +Show only the first line of the Description field from the matching +paragraphs. If no "-s" option is specified, this option also effects +"-s Description"; if there is a "-s" option but it does not include +the Description field name, one is appended to the option. Thus the +Description field's location in the output is determined by the "-s" +option, if any, the last field being the default. +.IP "-n, --no-field-names" +Suppress field names when showing specified fields, only their bodies +are shown. Each field is printed in its original form without the +field name, the colon after it and any whitespace predecing the start +of the body. +.IP "-v, --invert-match" +Instead of showing all the paragraphs that match, show those paragraphs +that do +.I not +match. +.IP "-c, --count" +Instead of showing the paragraphs that match (or, with -v, that don't +match), show the count of those paragraphs. +.SS Miscellaneous +.IP "--config-file=FNAME" +Use FNAME as the config file instead of the defaults. +.IP "-l LEVEL, --errorlevel=LEVEL" +Set debugging level to LEVEL. LEVEL is one of "fatal", "important", +"informational" and "debug", but the last may not be available, +depending on the compile-time options. These categories are given +here in order; every message that is emitted when "fatal" is in +effect, will be emitted in the "important" error level, and so on. +The default is "important". +.IP "-V, --version" +Print out version information. +.IP "-C, --copying" +Print out the copyright license. This produces much output; be sure +to redirect or pipe it somewhere (such as your favourite pager). +.IP "-h, --help" +Print out a help summary. +.SH EXAMPLES +The following example queries assume that the default configuration is +in effect. +.PP +The almost simplest use of this program is to print out the status or +available record of a package. In this respect, +.B grep-dctrl +is like +.B "dpkg -s" +or +.BR "dpkg --print-avail". +To print out the status record of the package "mixal", do +.nf +% grep-status -PX mixal +.fi +and to get its available record, use +.nf +% grep-available -PX mixal +.fi +In fact, you can ask for the record of the "mixal" package +from any Debian control file. Say, you have the Debian 2.2 +CD-ROM's Packages file in the current directory; now you +can do a +.nf +% grep-dctrl -PX mixal Packages +.fi +.PP +But +.B grep-dctrl +can do more than just emulate +.BR dpkg . +It can more-or-less emulate +.BR apt-cache ! +That program has a search feature that searches package descriptions. +But we can do that too: +.nf +% grep-available -F Description foo +.fi +searches for the string "foo" case-sensitively in the descriptions of +all available packages. If you want case-insensitivity, use +.nf +% grep-available -F Description -i foo +.fi +Truth to be told, +.B apt-cache +searches package names, too. We can separately search in the names; +to do so, do +.nf +% grep-available -F Package foo +.fi +or +.nf +% grep-available -P foo +.fi +which is pretty much the same thing. We can also search in both +descriptions and names; if match is found in either, the package +record is printed: +.nf +% grep-available -P -F Description foo +.fi +or +.nf +% grep-available -F Package -F Description foo +.fi +This kind of search is the exactly same that +.B apt-cache +does. +.PP +Here's one thing neither +.B dpkg +nor +.B apt-cache +do. Search for a string in the whole status or available file (or +any Debian control file, for that matter) and print out all package +records where we have a match. Try +.nf +% grep-available dpkg +.fi +sometime and watch how thoroughly +.B dpkg +has infiltrated Debian. +.PP +All the above queries were based on simple substring searches. +But +.B grep-dctrl +can handle regular expressions in the search pattern. For example, +to see the status records of all packages with either "apt" or +"dpkg" in their names, use +.nf +% grep-status -P -e 'apt|dpkg' +.fi +.PP +Now that we have seen all these fine and dandy queries, you might +begin to wonder whether it is necessary to always see the whole +paragraph. You may be, for example, interest only in the dependency +information of the packages involved. Fine. To show the depends +lines of all packages maintained by me, do a +.nf +% grep-available -F Maintainer -s Depends 'ajk@debian.org' +.fi +If you want to see the packages' names, too, use +.nf +% grep-available -F Maintainer -s Package,Depends \\ + 'ajk@debian.org' +.fi +Note that there must be no spaces in the argument to the -s switch. +.PP +More complex queries are also possible. For example, to see the list of packages +maintained by me and depending on libc6, do +.nf +% grep-available -F Maintainer 'ajk@debian.org' \\ + -a -F Depends libc6 -s Package,Depends +.fi +Remember that you can use other Unix filters to help you, too. Ever +wondered, who's the most active Debian developer based on the number +of source packages being maintained? Easy. You just need to have a +copy of the most recent Sources file from any Debian mirror. +.nf +% grep-dctrl -n -s Maintainer '' Sources | sort | + uniq -c | sort -nr +.fi +This example shows a neat trick: if you want to selectively +show only some field of +.I all +packages, just supply an empty pattern. +.PP +The term "bogopackage" means the count of the packages that a Debian +developer maintains. To get the bogopackage count for the maintainer +of +.BR grep-dctrl , +say +.nf +% grep-available -c -FMaintainer \\ + "`grep-available -sMaintainer -n -PX grep-dctrl`" +.fi +.PP +Sometimes it is useful to output the data of several fields on the +same line. For example, the following command outputs the list of +installed packages, sorted by their Installed-Size. +.nf +% grep-status -FStatus -sInstalled-Size,Package -n \\ + "install ok installed" | paste -sd " \\n" | sort -n +.fi +Note that there should be exactly 2 spaces in the " \n" string. +.PP +These examples cover a lot of typical uses of this utility, but not +all possible uses. Use your imagination! The building blocks are +there, and if something's missing, let me know. +.SH DIAGNOSTICS +These messages are emitted in log levels "fatal" and "important". +.B This list is out of date. +.IP "you can only use -s once" +You must give all fields to show in one -s command. Usually many -s's +are typos anyway, so heed this message: remove one of the -s's or +merge all of them into one -s. +.IP "no such log level" +The argument to -l was invalid. +.IP "cumulative field name exceeds maximum length" +The combined length of the argument to all -F options given may not +exceed 512 bytes. Longer arguments cannot be used. +.IP "too many fields to search in" +Too many fields were specified for searchin in. This number is +limited to 256. +.IP "output field spec exceeds maximum length" +The argument to -s was too long; it is restricted to 512 bytes. +Longer arguments cannot be used. +.IP "too many output fields" +The argument to -s had too many field names in it. This number is +limited to 256. +.IP "do not use both -e and -r options" +The pattern cannot be both a standard POSIX regular expression and an +extended POSIX regular expression at the same time. You must use at +most one of the options -e and -r; using both does not make sense. +.IP "I'm broken - please report this to <gaia@iki.fi>" +An internal consistency check failed. Please, report this bug. +.IP "a pattern is mandatory" +You must specify a pattern to be searched. +.IP "cannot find enough memory" +More memory was needed than was available. This error may be +transient, that is, if you try again, all may go well. +.IP "don't know how to do an exact regex match" +Currently you cannot do exact match searches with regular expressions. +.IP "cannot suppress field names when showing whole paragraphs" +When you do not use the -s switch, +.B grep-dctrl +just passes the matching paragraphs through, not touching them any +way. This means, for example, that you can only use -n when you use +-s. +.IP "need a file name to grep" +For some reason no file name is available. This means that the configuration +file did not list a default file name for this name of the program, and no +file name was given on the command line. +.IP "syntax error: need a executable name" +There is a problem in the configuration file. Look, and you shall find it. +.IP "syntax error: need an input file name" +There is a problem in the configuration file. Look, and you shall find it. +.SH COMPATIBILITY +If you use grep-dctrl in a Debian package, you should depend on the +grep-dctrl package and heed the following compatibility notes: +.PP +.IP "Always call only the \fBgrep-dctrl\fR executable." +Although the \fBgrep-status\fR and \fBgrep-available\fR symlinks are installed +by default, this may change in the future. Those symlinks are meant +for manual and not scripted use. +.IP "Always specify an explicit file name" +Don't rely on the implicit file name feature. The system +administrator may have changed the default file name. You should +always specify the "-" file, too. +.IP "Not all features have been with us in every version" +Check if any of the features you use is mentioned in the changelog. +Use a versioned dependency on grep-dctrl, if it is necessary. +.SH FILES +.IP SYSCONF/grep-dctrl.rc +See the next file. +.IP ~/.grep-dctrlrc +These files are the default configuration files for +.BR grep-dctrl . +The format is line-based, with `#' introducing a comment that lasts to +the end of the line. Each line defines one association between a +program name and a default input file. These two things are listed in +the line in order, separated by whitespace. Empty lines are ignored. +.SH AUTHOR +The program and this manual page were written by Antti-Juhani +Kaijanaho <gaia@iki.fi>. Bill Allombert <ballombe@debian.org> +provided one of the examples in the manual page. +.SH "SEE ALSO" +Ian Jackson et al.: Debian Packaging Manual. Published as the Debian +package packaging-manual. Also available in the Debian website. The +Debian project, 2003. +.PP +.BR apt-cache (1), +.BR dpkg (1), +.BR dpkg-awk (1), +.BR sgrep (1) +\" Local variables: +\" mode: nroff +\" End: + diff --git a/grep-dctrl.c b/grep-dctrl.c new file mode 100644 index 0000000..e2b7e53 --- /dev/null +++ b/grep-dctrl.c @@ -0,0 +1,548 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 1999, 2000, 2001, 2002, 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <argp.h> +#include <assert.h> +#include <fcntl.h> +#include <publib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "fsaf.h" +#include "msg.h" +#include "paragraph.h" +#include "predicate.h" +#include "rc.h" +#include "util.h" + +const char * argp_program_version = "grep-dctrl (dctrl-tools) " VERSION; +const char * argp_program_bug_address = MAINTAINER; + +const char description [] = "Description"; +size_t description_inx; + +static char progdoc [] = "grep-dctrl -- grep Debian control files"; + +#define OPT_CONFIG 256 +#define OPT_OPTPARSE 257 + +void banner(bool automatic) +{ + char * fname = fnqualify_xalloc("~/.grep-dctrl-banner-shown"); + struct stat st; + if (automatic) { + int r = stat(fname, &st); + if (r == 0) goto end; + } + FILE * fp = fopen("/dev/tty", "w"); + if (fp == 0) { + perror("/dev/tty"); + goto end; + } + fprintf(fp, + "==========================================================================\n" + " NOTE \n" + " grep-dctrl has been rewritten from scratch. Although this does add new \n" + " features, regressions are certainly possible. Please watch for them and \n" + " report them to the BTS. \n" + "==========================================================================\n" + "(The above annoying banner will not be shown to you again, unless you\n" + "request it with the -B switch. It will also be removed entirely soon.)\n"); + + int r = creat(fname, 0644); + if (r == -1) perror(fname); + + if (!automatic) exit(EXIT_SUCCESS); + + for (int i = 15; i > 0; i--) { + fprintf(fp, "%2d seconds until program is resumed...\r", i); + fflush(fp); + sleep(1); + } + fprintf(fp, " \r"); + fflush(fp); +end: + free(fname); +} + +static struct argp_option options[] = { + { "banner", 'B', 0, 0, "Show the testing banner." }, + { "errorlevel", 'l', "LEVEL", 0, "Set debugging level to LEVEL." }, + { "field", 'F', "FIELD,FIELD,...", 0, "Restrict pattern matching to the FIELDs given." }, + { 0, 'P', 0, 0, "Shorthand for -FPackage" }, + { "show-field", 's', "FIELD,FIELD,...", 0, "Show only the body of these fields from the matching paragraphs." }, + { 0, 'd', 0, 0, "Show only the first line of the Description field from the matching paragraphs." }, + { "no-field-names", 'n', 0, 0, "Suppress field names when showing specified fields." }, + { "eregex", 'e', 0, 0, "Regard the pattern as an extended POSIX regular expression." }, + { "regex", 'r', 0, 0, "The pattern is a standard POSIX regular expression." }, + { "ignore-case", 'i', 0, 0, "Ignore case when looking for a match." }, + { "invert-match", 'v', 0, 0, "Show only paragraphs that do not match." }, + { "count", 'c', 0, 0, "Show only the count of matching paragraphs." }, + { "config-file", OPT_CONFIG, "FNAME", 0, "Use FNAME as the config file." }, + { "exact-match", 'X', 0, 0, "Do an exact match." }, + { "copying", 'C', 0, 0, "Print out the copyright license." }, + { "and", 'a', 0, 0, "Conjunct predicates." }, + { "or", 'o', 0, 0, "Disjunct predicates." }, + { "not", '!', 0, 0, "Negate the following predicate." }, + { "debug-optparse", OPT_OPTPARSE, 0, 0, "Debug option parsing." }, + { 0 } +}; + + +enum state { STATE_ATOM, STATE_NEG, STATE_CONJ, STATE_DISJ, STATE_PAREN, + STATE_START, STATE_FINISHED }; + +#define MAX_FNAMES 4096 + +static int debug_optparse = 0; + +struct arguments { + /* Parser state, used when parsing the predicate. */ + enum state state; + /* Top of the parser stack. */ + size_t top; + /* Number of file names seen. */ + size_t num_fnames; + /**/ + size_t num_show_fields; + /* A machine-readable representation of the predicate. */ + struct predicate p; + /* Configuration file name */ + char const * rcname; + /* Do show field names? */ + bool show_field_name; + /* Do show (only) first line of Description? */ + bool short_descr; + /* Does show_fields contain Description? */ + bool description_selected; + /* Count matching paragraphs? */ + bool count; + /* Invert match? */ + bool invert_match; + /* Parser stack. */ + struct { + enum state state; + int insn; + } stack[MAX_OPS]; + /* File names seen on the command line. */ + char const * fname[MAX_FNAMES]; + /**/ + struct show_fields { + char const * name; + size_t inx; + } show_fields[MAX_FIELDS]; +}; + +static void finish_atom(struct arguments * args) +{ + struct atom * atom = get_current_atom(&args->p); + if (atom->pat == 0) { + message(L_FATAL, "A pattern is mandatory.", 0); + exit(EXIT_FAILURE); + } + predicate_finish_atom(&args->p); +} + +/* Pop off one stack state, inserting the associated instruction to + * the predicate program. If paren is true, current state must be + * STATE_PAREN, and if paren is false, it must not be STATE_PAREN. */ +static void leave(struct arguments * args, int paren) +{ + debug_message("leaving...", 0); + assert(paren == (args->state == STATE_PAREN)); + if (args->state == STATE_ATOM) finish_atom(args); + assert(args->top > 0); + --args->top; + addinsn(&args->p, args->stack[args->top].insn); + args->state = args->stack[args->top].state; +} + +#define ENTER(state,insn) do { enter(args, (state), (insn)); } while (0) + +static void prim_enter(struct arguments * args, const enum state state, const int insn) +{ + if (args->top >= MAX_OPS) { + message(L_FATAL, "predicate is too complex", 0); + exit(EXIT_FAILURE); + } + args->stack[args->top].insn = insn; + args->stack[args->top].state = args->state; + ++args->top; + args->state = state; +} + +/* Push current state along with the given instruction to stack and + * enter the given state. + */ +static void enter(struct arguments * args, const enum state state, const int insn) +{ + if (args->state == STATE_FINISHED) { + message(L_FATAL, "syntax error in command line", 0); + exit(EXIT_FAILURE); + } + while (args->state < state || (state != STATE_NEG && args->state == state)) { + leave(args, 0); + } + prim_enter(args, state, insn); + debug_message("entering...", 0); +} + +#define FINISH do { finish(args); } while (0) + +/* Flush the state stack. */ +static void finish(struct arguments * args) +{ + while (args->top > 0) { + if (args->state == STATE_PAREN) { + message(L_FATAL, "missing ')' in command line", 0); + exit(EXIT_FAILURE); + } + leave(args, 0); + } + assert(args->state == STATE_START); + args->state = STATE_FINISHED; +} + +#define ENTER_ATOM (enter_atom((args))) + +/* If necessary, enter STATE_ATOM and allocate a new atom, pushing + * along with the old state a PUSH instruction for the new atom to the + * parser stack. If we are already in STATE_ATOM, reuse the current + * atom. */ +static struct atom * enter_atom(struct arguments * args) +{ + struct atom * rv; + if (args->state == STATE_ATOM || args->state == STATE_FINISHED) { + assert(args->p.num_atoms > 0); + return &args->p.atoms[args->p.num_atoms-1]; + } + if (args->p.num_atoms >= MAX_ATOMS) { + message(L_FATAL, "predicate is too complex", 0); + exit(EXIT_FAILURE); + } + ENTER(STATE_ATOM, I_PUSH(args->p.num_atoms)); + rv = &args->p.atoms[args->p.num_atoms++]; + rv->field_name = 0; + rv->field_inx = -1; + rv->mode = M_SUBSTR; + rv->ignore_case = 0; + rv->pat = 0; + rv->patlen = 0; + return rv; +} + +static error_t parse_opt (int key, char * arg, struct argp_state * state) +{ + struct arguments * args = state->input; + struct atom * atom; + debug_message("parse_opt", 0); + switch (key) { + case 'B': + banner(false); + case 'v': + args->invert_match = true; + break; + case 'c': + args->count = true; + break; + case 'n': + debug_message("parse_opt: n", 0); + args->show_field_name = false; + break; + case 'd': + args->short_descr = true; + break; + case 's': { + char * carg = strdup(arg); + if (carg == 0) fatal_enomem(0); + for (char * s = strtok(carg, ","); s != 0; s = strtok(0, ",")) { + struct show_fields * sf = &args->show_fields[args->num_show_fields]; + sf->name = strdup(s); + if (sf->name == 0) fatal_enomem(0); + sf->inx = fieldtrie_insert(&args->p.trie, s); + if (sf->inx == description_inx) { + args->description_selected = true; + } + ++args->num_show_fields; + } + } + break; + case 'l': { + int ll = str2loglevel(optarg); + if (ll < 0) + { + message(L_FATAL, _("no such log level"), optarg); + exit(EXIT_FAILURE); + } + set_loglevel(ll); + debug_message("parse_opt: l", 0); + } + break; + case '!': + debug_message("parse_opt: !", 0); + ENTER(STATE_NEG, I_NEG); + break; + case 'a': + debug_message("parse_opt: a", 0); + ENTER(STATE_CONJ, I_AND); + break; + case 'o': + debug_message("parse_opt: o", 0); + ENTER(STATE_DISJ, I_OR); + break; + case 'P': + debug_message("parse_opt: P", 0); + arg = "Package"; + /* pass through */ + case 'F': + debug_message("parse_opt: F", 0); + atom = ENTER_ATOM; + assert(atom->field_name == 0); /* FIXME */ + atom->field_name = strdup(arg); + if (atom->field_name == 0) fatal_enomem(0); + break; + case 'X': + debug_message("parse_opt: X", 0); + atom = ENTER_ATOM; + assert(atom->mode == M_SUBSTR); /* FIXME */ + atom->mode = M_EXACT; + break; + case 'r': + debug_message("parse_opt: r", 0); + atom = ENTER_ATOM; + assert(atom->mode == M_SUBSTR); /* FIXME */ + atom->mode = M_REGEX; + break; + case 'e': + debug_message("parse_opt: e", 0); + atom = ENTER_ATOM; + assert(atom->mode == M_SUBSTR); /* FIXME */ + atom->mode = M_EREGEX; + break; + case 'i': + debug_message("parse_opt: i", 0); + atom = ENTER_ATOM; + atom->ignore_case = 1; + break; + case OPT_OPTPARSE: + debug_message("parse_opt: optparse", 0); + debug_optparse = 1; + break; + case ARGP_KEY_ARG: + debug_message("parse_opt: argument", 0); + redo: + debug_message("!!!", 0); + if (strcmp(arg, "!") == 0) { + debug_message("parse_opt: !", 0); + ENTER(STATE_NEG, I_NEG); + break; + } + if (strcmp(arg, "(") == 0) { + debug_message("parse_opt: (", 0); + prim_enter(args, STATE_PAREN, I_NOP); + break; + } + if (strcmp(arg, ")") == 0) { + debug_message("parse_opt: )", 0); + while (args->state != STATE_PAREN) { + if (args->top == 0) { + message(L_FATAL, "unexpected ')' in command line", 0); + exit(EXIT_FAILURE); + } + leave(args, 0); + } + leave(args, 1); + break; + } + if (args->state == STATE_FINISHED) { + char const * s; + if (args->num_fnames >= MAX_FNAMES) { + message(L_FATAL, "too many file names", 0); + exit(EXIT_FAILURE); + } + s = strdup(arg); + if (s == 0) fatal_enomem(0); + args->fname[args->num_fnames++] = s; + break; + } + if (strcmp(arg, "--") == 0) { FINISH; break; } + atom = ENTER_ATOM; + if (atom->pat != 0) { FINISH; goto redo; } + atom->patlen = strlen(arg); + atom->pat = malloc(atom->patlen+1); + if (atom->pat == 0) fatal_enomem(0); + strcpy((char*)atom->pat, arg); + break; + case ARGP_KEY_END: + debug_message("parse_opt: end", 0); + if (args->state != STATE_FINISHED) FINISH; + break; + case ARGP_KEY_ARGS: case ARGP_KEY_INIT: case ARGP_KEY_SUCCESS: + case ARGP_KEY_ERROR: case ARGP_KEY_FINI: case ARGP_KEY_NO_ARGS: + debug_message("parse_opt: ignored", 0); + break; + case OPT_CONFIG: + debug_message("parse_opt: --config-file", 0); + args->rcname = strdup(arg); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static void dump_args(struct arguments * args) +{ + size_t i; + assert(args->state == STATE_FINISHED); + assert(args->top == 0); + printf("num_atoms = %i\n", args->p.num_atoms); + for (i = 0; i < args->p.num_atoms; i++) { + printf("atoms[%i].field_name = %s\n", i, args->p.atoms[i].field_name); + printf("atoms[%i].mode = %i\n", i, args->p.atoms[i].mode); + printf("atoms[%i].ignore_case = %i\n", i, args->p.atoms[i].ignore_case); + printf("atoms[%i].pat = %s\n", i, args->p.atoms[i].pat); + } + printf("proglen = %i\n", args->p.proglen); + for (i = 0; i < args->p.proglen; i++) { + int op = args->p.program[i]; + printf("program[%i] = ", i); + switch (op) { + case I_NOP: puts("NOP"); break; + case I_NEG: puts("NEG"); break; + case I_AND: puts("AND"); break; + case I_OR: puts("OR"); break; + default: + printf("PUSH(%i)\n", op - I_PUSH(0)); + } + } + printf("num_fnames = %i\n", args->num_fnames); + for (i = 0; i < args->num_fnames; i++) { + printf("fname[%i] = %s\n", i, args->fname[i]); + } +} + +static struct argp argp = { options, parse_opt, 0, progdoc }; + +int main (int argc, char * argv[]) +{ + static struct arguments args; + args.state = STATE_START; + args.show_field_name = true; + msg_set_progname(argv[0]); + init_predicate(&args.p); + description_inx = fieldtrie_insert(&args.p.trie, description); + argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, &args); + banner(true); + + if (debug_optparse) { dump_args(&args); return 0; } + + if (args.short_descr && !args.description_selected) { + if (args.num_show_fields >= MAX_FIELDS) { + message(L_FATAL, _("too many output fields"), 0); + exit(EXIT_FAILURE); + } + message(L_INFORMATIONAL, + _("Adding Description to selected output fields because of -d"), + 0); + args.show_fields[args.num_show_fields].name = description; + args.show_fields[args.num_show_fields].inx = description_inx; + ++args.num_show_fields; + } + + if (!args.show_field_name && args.num_show_fields == 0) { + message(L_FATAL, + _("cannot suppress field names when showing whole paragraphs"), + 0); + exit(EXIT_FAILURE); + } + + size_t count = 0; + for (size_t i = 0; i < args.num_fnames || (i == 0 && args.num_fnames == 0); ++i) { + int fd; + const char * fname; + if (args.num_fnames == 0) { + // Hardcode grep-dctrl <-> "-" mapping so that + // Debian packages can genuinely depend on it. + char * argv0 = fnbase(argv[0]); + if (strcmp(argv0, "grep-dctrl") == 0) { + fname = "-"; + } else { + fname = find_ifile_by_exename(argv0, args.rcname); + } + } else { + fname = args.fname[i]; + } + + if (strcmp(fname, "-") == 0) { + fd = STDIN_FILENO; + fname = "stdin"; + } else { + fd = open(fname, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "%s: %s: %s\n", argv[0], fname, strerror(errno)); + break; + } + } + + FSAF * fp = fsaf_fdopen(fd); + para_t para; + for (para_init(¶, fp, &args.p.trie); + !para_eof(¶); + para_parse_next(¶)) { + if ((args.invert_match || !does_para_satisfy(&args.p, ¶)) + && (!args.invert_match || does_para_satisfy(&args.p, ¶))) { + continue; + } + if (args.count) { + ++count; + continue; + } + if (args.num_show_fields == 0) { + struct fsaf_read_rv r = fsaf_read(fp, para.start, para.end - para.start); + fwrite(r.b, 1, r.len, stdout); + putchar('\n'); + continue; + } + for (size_t j = 0; j < args.num_show_fields; j++) { + if (args.show_field_name) { + printf("%s: ", args.show_fields[j].name); + } + struct field_data * fd = ¶.fields[args.show_fields[j].inx]; + struct fsaf_read_rv r = fsaf_read(fp, fd->start, fd->end - fd->start); + if (args.short_descr && + args.show_fields[j].inx == description_inx) { + char * nl = memchr(r.b, '\n', r.len); + if (nl != 0) r.len = nl - r.b; + } + fwrite(r.b, 1, r.len, stdout); + puts(""); + continue; + } + if (args.num_show_fields > 1) puts(""); + + } + + if (fd != STDIN_FILENO) close(fd); + } + if (count) printf("%d\n", count); + return 0; +} + diff --git a/grep-dctrl.rc b/grep-dctrl.rc new file mode 100644 index 0000000..f73f5e3 --- /dev/null +++ b/grep-dctrl.rc @@ -0,0 +1,15 @@ +# Configuration for grep-dctrl. The config line format is +# line-oriented. Each line defines one executable name - default +# input file pair; the elements of the pair are in order and separated +# by whitespace. The hash '#' begins a comment that lasts to the end +# of line. Empty lines are ignored. + +# Template: +# <executable name> <default input file name> + +# The following line used to be required, but it is now hardcoded. +# grep-dctrl - + +# The following two pairs define common aliases for grep-dctrl. +grep-status /var/lib/dpkg/status +grep-available /var/lib/dpkg/available @@ -0,0 +1,32 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 1999, 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef I18N_H__ +#define I18N_H__ + +#ifdef HAVE_GETTEXT +#include <libintl.h> +#define _(String) gettext(String) +#else +#define _(String) (String) +#define textdomain(Domain) +#define bindtextdomain(Package, Directory) +#endif + +#endif /* I18N_H__ */ @@ -0,0 +1,93 @@ +/* grep-dctrl - grep Debian control files + Copyright (C) 1999 Antti-Juhani Kaijanaho + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + The author can be reached via mail at (ISO 8859-1 charset for the city) + Antti-Juhani Kaijanaho + Helvintie 2 e as 9 + FIN-40500 JYVÄSKYLÄ + FINLAND + EUROPE + and via electronic mail from + gaia@iki.fi + If you have a choice, use the email address; it is more likely to + stay current. + +*/ + + +#define MSG_C__ + +#include <assert.h> +#include <string.h> +#include "msg.h" + +struct str2int_avec_t { + const char * str; + int integer; +}; + +int +within_interval (int n, int a, int b) +{ + if (a > b) + { + int tmp; + tmp = b; + b = a; + a = tmp; + } + + assert (a <= b); + + return (a <= n && n <= b); +} + +void +msg_set_progname (const char * pn) +{ + strncpy (progname, pn, PROGNAME_MAXLEN); + progname [PROGNAME_MAXLEN - 1] = 0; +} + +void +set_loglevel (int ll) +{ + assert (within_interval (loglevel, L_FATAL, L_DEBUG)); + + loglevel = ll; +} + +int +str2loglevel (const char * s) +{ + static struct str2int_avec_t avec [] = { + { "fatal", L_FATAL }, + { "important", L_IMPORTANT }, + { "informational", L_INFORMATIONAL }, +#if !defined(NDEBUG) && defined(ENABLE_L_DEBUG) + { "debug", L_DEBUG }, +#endif + { 0, 0 } }; + + int i; + + for (i = 0; avec [i].str != 0; i++) + if (strcasecmp (avec [i].str, s) == 0) + return avec[i].integer; + return -1; +} @@ -0,0 +1,133 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 1999 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MSG_H__ +#define MSG_H__ + +#include <stdio.h> +#include <stdlib.h> +#include "i18n.h" + +/* log levels */ +#define L_FATAL 3 +#define L_IMPORTANT 2 +#define L_INFORMATIONAL 1 +#define L_DEBUG 0 + +#define PROGNAME_MAXLEN 64 + +#if !defined(NDEBUG) && !defined(TEST_NODEBUG) && defined(ENABLE_L_DEBUG) +# define INCLUDE_DEBUG_MSGS +#endif + +#ifdef MSG_C__ +int loglevel = L_IMPORTANT; +char progname [PROGNAME_MAXLEN]; +#endif + +inline static int +do_msg(int severity) +{ +#ifndef MSG_C__ + extern int loglevel; +#endif + +#if defined(TEST_NODEBUG) + if (severity == L_DEBUG) + { + line_message (L_INFORMATIONAL, _("Got a L_DEBUG while TEST_NODEBUG " + "is defined"), 0, 0); + message (L_FATAL, _("I'm broken - please report this " + "to <gaia@iki.fi>"), 0, 0); + abort (); + } +#endif + + return severity >= loglevel; +} + +inline static void +line_message (int severity, const char * s, const char * fname, int line) +{ + if (do_msg(severity)) { +#ifndef MSG_C__ + extern const char progname [PROGNAME_MAXLEN]; +#endif + + if (fname == 0) { + fprintf (stderr, "%s: %s.\n", progname, s); + } else { + if (line > 0) { + fprintf (stderr, "%s: %s: %i: %s.\n", progname, fname, line, s); + } else { + fprintf (stderr, "%s: %s: %s.\n", progname, fname, s); + } + } + } +} + +inline static void +message (int severity, const char * s, const char * fname) +{ + line_message (severity, s, fname, 0); +} + +#ifndef MSG_C__ +#undef PROGNAME_MAXLEN +#endif + +inline static void +debug_message (const char * s, const char * fname) +{ +#ifdef INCLUDE_DEBUG_MSGS + message (L_DEBUG, s, fname); +#endif +} + +#define enomem_msg _("cannot find enough memory") + +inline static void +enomem (const char * fname) +{ + message (L_IMPORTANT, enomem_msg, fname); +} + +inline static void +fatal_enomem (const char * fname) +{ + message (L_FATAL, enomem_msg, fname); + exit (EXIT_FAILURE); +} + +#undef enomem_msg + +/* Given a string that represents a log level, return the number that + repsesents that loglevel. A negative return value means that the + string is not a valid log level. */ +int +str2loglevel (const char * s); + +/* Set current log level to ll. */ +void +set_loglevel (int ll); + +/* Set program name to pn. */ +void +msg_set_progname (const char * pn); + +#endif /* MSG_H__ */ diff --git a/paragraph.c b/paragraph.c new file mode 100644 index 0000000..a6d1145 --- /dev/null +++ b/paragraph.c @@ -0,0 +1,135 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "msg.h" +#include "paragraph.h" + +void para_init(para_t * para, FSAF * fp, fieldtrie_t * trie) +{ + para->fp = fp; + para->trie = trie; + para->start = 0; + para->end = 0; + para->eof = false; + para_parse_next(para); +} + +void para_parse_next(para_t * para) +{ + debug_message("para_parse_next", 0); + para->start = para->end; + fsaf_invalidate(para->fp, para->start); + register enum { START, FIELD_NAME, BODY, BODY_NEWLINE, + BODY_SKIPBLANKS, END } state = START; + register size_t pos = para->start; + register FSAF * fp = para->fp; + size_t field_start = 0; + struct field_data * field_data = 0; + while (state != END) { + int c = fsaf_getc(fp, pos++); + switch (state) { + case START: + switch (c) { + case -1: + para->eof = true; + state = END; + break; + case '\n': + para->start++; + break; + default: + field_start = --pos; + state = FIELD_NAME; + } + break; + case FIELD_NAME: + switch (c) { + case -1: + message(L_FATAL, "unexpected end of file", 0); + exit(EXIT_FAILURE); + case ':': { + size_t len = (pos-1) - field_start; + struct fsaf_read_rv r = fsaf_read(fp, field_start, len); + assert(r.len == len); + size_t inx = fieldtrie_lookup(para->trie, r.b, len); + if (inx == -1) { + field_data = 0; + } else { + assert(inx < MAX_FIELDS); + field_data = ¶->fields[inx]; + field_data->start = pos; + } + state = BODY; + } + break; + case '\n': + message(L_FATAL, "unexpected end of line", 0); + exit(EXIT_FAILURE); + } + break; + case BODY: + switch (c) { + case -1: + message(L_FATAL, "unexpected end of file", 0); + exit(EXIT_FAILURE); + case '\n': + if (field_data != 0) { + field_data->end = pos-1; + while (field_data->start < field_data->end + && fsaf_getc(fp, field_data->start) == ' ') { + ++field_data->start; + } + } + state = BODY_NEWLINE; + break; + } + break; + case BODY_NEWLINE: + switch (c) { + case -1: + para->eof = true; + /* pass through */ + case '\n': + state = END; + break; + case ' ': case '\t': + state = BODY_SKIPBLANKS; + break; + default: + field_start = --pos; + state = FIELD_NAME; + } + break; + case BODY_SKIPBLANKS: + switch (c) { + case -1: + /* pass through */ + case '\n': + state = END; + break; + case ' ': case '\t': + break; + default: + state = BODY; + } + break; + case END: assert(0); + } + } + para->end = pos-1; +} diff --git a/paragraph.h b/paragraph.h new file mode 100644 index 0000000..a4e15fc --- /dev/null +++ b/paragraph.h @@ -0,0 +1,54 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PARAGRAPH_H +#define PARAGRAPH_H + +#define MAX_FIELDS 100 + +#include <stddef.h> +#include "fsaf.h" +#include "fieldtrie.h" + +struct field_data { + size_t start, end; /* offsets to the file; [start,end) is the body */ +}; + +struct paragraph_private { + FSAF * fp; + fieldtrie_t * trie; + bool eof; + + // CURRENT PARAGRAPH PARSED + + size_t start, end; /* offsets to the file; [start,end) is the paragraph */ + struct field_data fields[MAX_FIELDS]; +}; + +typedef struct paragraph_private para_t; + +/* Initialize the given para_t, associating with it the given + * FSAF and the field trie. */ +void para_init(para_t *, FSAF *, fieldtrie_t *); + +void para_parse_next(para_t *); + +static inline +bool para_eof(para_t * para) { return para->eof; } + +#endif /* PARAGRAPH_H */ diff --git a/predicate.c b/predicate.c new file mode 100644 index 0000000..e0a5dec --- /dev/null +++ b/predicate.c @@ -0,0 +1,173 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <ctype.h> +#include <stdlib.h> +#include <regex.h> +#include <string.h> +#include "fsaf.h" +#include "msg.h" +#include "util.h" +#include "predicate.h" + +void init_predicate(struct predicate * p) +{ + p->num_atoms = 0; + p->proglen = 0; + fieldtrie_init(&p->trie); +} + +void addinsn(struct predicate * p, int insn) +{ + if (insn == I_NOP) return; + if (p->proglen >= MAX_OPS) { + message(L_FATAL, "predicate is too complex", 0); + exit(EXIT_FAILURE); + } + p->program[p->proglen++] = insn; +} + +void predicate_finish_atom(struct predicate * p) +{ + struct atom * atom = get_current_atom(p); + if (atom->field_name == 0) return; + atom->field_inx = fieldtrie_insert(&p->trie, atom->field_name); + + if (atom->mode == M_REGEX || atom->mode == M_EREGEX) { + int rerr = regcomp(&atom->regex, atom->pat, + (atom->mode == M_EREGEX ? REG_EXTENDED : 0) + | REG_NOSUB + | (atom->ignore_case ? REG_ICASE : 0)); + if (rerr != 0) { + char * s; + s = get_regerror(rerr, &atom->regex); + if (s == 0) fatal_enomem(0); + message(L_FATAL, s, 0); + free(s); + exit(EXIT_FAILURE); + } + } +} + +static bool verify_atom(struct atom * atom, para_t * para) +{ + size_t start, end; + if (atom->field_inx == -1) { + /* Take the full paragraph */ + start = para->start; + end = para->end; + } else { + /* Take the field */ + struct field_data * fd = ¶->fields[atom->field_inx]; + start = fd->start; + end = fd->end; + } + size_t len = end - start; + struct fsaf_read_rv r = fsaf_read(para->fp, start, len); + assert(r.len == len); + switch (atom->mode) { + case M_EXACT: + if (len != atom->patlen) return false; + if (atom->ignore_case) { + return strncasecmp(atom->pat, r.b, len) == 0; + } else { + return strncmp(atom->pat, r.b, len) == 0; + } + case M_SUBSTR: { +#if 0 + if (atom->ignore_case) { + return strncasestr(r.b, atom->pat, len); + } else { + return strnstr(r.b, atom->pat, len); + } +#else + bool rv; + char * s = strndup(r.b, len); + if (s == 0) fatal_enomem(0); + if (atom->ignore_case) { + rv = strcasestr(s, atom->pat) != 0; + } else { + rv = strstr(s, atom->pat) != 0; + } + free(s); + return rv; +#endif + } + case M_REGEX: case M_EREGEX: { + char * s = strndup(r.b, len); + if (s == 0) fatal_enomem(0); + int regex_errcode = regexec(&atom->regex, s, 0, 0, 0); + free(s); + if (regex_errcode == 0 || regex_errcode == REG_NOMATCH) { + return (regex_errcode == 0); + } + /* Error handling be here. */ + assert(regex_errcode != 0 && regex_errcode != REG_NOMATCH); + s = get_regerror (regex_errcode, &atom->regex); + if (s == 0) { enomem (0); return false; } + message(L_IMPORTANT, s, 0); + free(s); + return false; + } + } + assert(0); +} + +bool does_para_satisfy(struct predicate * p, para_t * para) +{ + assert(para->trie == & p->trie); + + bool sat_atom[MAX_ATOMS]; + bool stack[MAX_OPS]; + size_t sp = 0; + + /* Verify atoms. */ + for (size_t i = 0; i < p->num_atoms; i++) { + sat_atom[i] = verify_atom(&p->atoms[i], para); + } + + /* Run the program. */ + for (size_t i = 0; i < p->proglen; i++) { + switch (p->program[i]) { + case I_NOP: break; + case I_NEG: + assert(sp >= 1); + stack[sp-1] = !stack[sp-1]; + break; + case I_AND: + assert(sp >= 2); + stack[sp-2] = stack[sp-2] && stack[sp-1]; + --sp; + break; + case I_OR: + assert(sp >= 2); + stack[sp-2] = stack[sp-2] || stack[sp-1]; + --sp; + break; + default: + { + int atom = p->program[i] - I_PUSH(0); + assert(atom <= p->num_atoms); + stack[sp] = sat_atom[atom]; + ++sp; + } + } + } + assert(sp == 1); + return stack[0]; +} diff --git a/predicate.h b/predicate.h new file mode 100644 index 0000000..f60a6ea --- /dev/null +++ b/predicate.h @@ -0,0 +1,88 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PREDICATE_H +#define PREDICATE_H + +#include <assert.h> +#include <regex.h> +#include "fieldtrie.h" +#include "paragraph.h" + +#define MAX_OPS 4096 +#define MAX_ATOMS 4096 + +#define I_NOP 0 +#define I_NEG 1 /* --not; 1-1 */ +#define I_AND 2 /* --and; 2-1 */ +#define I_OR 3 /* --or; 2-1 */ +#define I_PUSH(n) (4+(n)) /* push result of nth atomic proposition */ + +/* An atomic predicate. */ +struct atom { + /* The name of field to which matching is limited. Empty + * field_name specifies the whole paragraph (in which case + * field_inx is -1. */ + char const * field_name; size_t field_inx; + /* Matching mode */ + enum { M_SUBSTR, /* substring matching */ + M_REGEX, /* POSIX regular expression match */ + M_EREGEX, /* POSIX extended regular expression matching */ + M_EXACT /* exact match */ + } mode; + /* Flag: should matching ignore case */ + unsigned ignore_case; + /* The pattern as given on the command line; interpretation + * depends on matching mode. */ + char const * pat; size_t patlen; + /* A compiled version of pat; valid only when mode is M_REGEX + * or M_EREGEX. */ + regex_t regex; +}; + +/* A predicate is represented as a set of atomic predicates and a + * program - a sequence of stack-based "bytecode" instructions - that + * specifies the structure of the combined predicate. */ +struct predicate { + /* Number of atomic predicates. */ + size_t num_atoms; + /* Length of the program */ + size_t proglen; + /* The program */ + int program[MAX_OPS]; + /* The atomic predicates */ + struct atom atoms[MAX_ATOMS]; + fieldtrie_t trie; +}; + +void init_predicate(struct predicate * p); + +static inline +struct atom * get_current_atom(struct predicate * p) +{ + assert(p->num_atoms > 0); + return &p->atoms[p->num_atoms-1]; +} + +void predicate_finish_atom(struct predicate *); + +void addinsn(struct predicate * p, int insn); + +bool does_para_satisfy(struct predicate * p, para_t *); + +#endif /* PREDICATE_H */ @@ -0,0 +1,130 @@ +/* grep-dctrl - grep Debian control files + Copyright (C) 1999, 2003 Antti-Juhani Kaijanaho + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + The author can be reached via mail at (ISO 8859-1 charset for the city) + Antti-Juhani Kaijanaho + Helokantie 1 A 16 + FIN-40640 JYVÄSKYLÄ + FINLAND + EUROPE + and via electronic mail from + gaia@iki.fi + If you have a choice, use the email address; it is more likely to + stay current. + +*/ + +#include <assert.h> +#include <errno.h> +#include <publib.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "msg.h" +#include "rc.h" +#include "strutil.h" + + +const char * find_ifile_by_exename(const char * exename, const char * rcfname) +{ + static const char * default_rcfiles [] = { + /* Order is significant: earlier files override later ones. */ + "~/.grep-dctrlrc", + SYSCONF "/grep-dctrl.rc", + 0 }; + int i; + const char * rv = 0; + char * fname; + int lineno; + FILE * f; + + assert(exename != 0); + + if (rcfname == 0) { + for (i = 0; rv == 0 && default_rcfiles [i] != 0; i++) { + rv = find_ifile_by_exename(exename, default_rcfiles [i]); + } + return rv; + } + + assert(rcfname != 0); + + fname = fnqualify_xalloc(rcfname); + + message(L_INFORMATIONAL, _("reading config file"), fname); + + f = fopen(fname, "r"); + if (f == 0) { + message(L_INFORMATIONAL, strerror(errno), fname); + return 0; + } + + lineno = 0; + while (1) { + static char * line = 0; + char * line_exe; + char * line_ifile; + + /* If this is not the first call, line may be non-null + and must be freed. It must be freed on all + non-first iterations, too. */ + free(line); + + line = xgetaline (f); + ++lineno; + if (line == 0) { + rv = 0; + break; + } + + chop_comment(line, '#'); + + if (left_trimmed(line) [0] == 0) { + continue; + } + + line_exe = strtok(line, " \t"); + if (line_exe == 0) { + line_message(L_IMPORTANT, + _("syntax error: need a executable name"), + fname, lineno); + continue; + } + + line_ifile = strtok(0, " \t"); + if (line_ifile == 0) { + line_message(L_IMPORTANT, + _("syntax error: need an input file name"), + fname, lineno); + continue; + } + + message(L_INFORMATIONAL, _("considering executable name"), line_exe); + if (strcmp (exename, line_exe) == 0) { + message(L_INFORMATIONAL, _("yes, will use executable name"), line_exe); + rv = line_ifile; + message(L_INFORMATIONAL, _("default input file"), rv); + break; + } + } + + fclose(f); + free(fname); + return rv; +} + @@ -0,0 +1,30 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 1999, 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef RC_H__ +#define RC_H__ + +/* Search for exename (only basename, though) in rcfname (or if it is + null, in default rc files) and return the found corresponding + default input file name, or null, if not found or other error + occurred. The returned pointer will be invalidated by the next + call to this function. */ +const char * +find_ifile_by_exename (const char * exename, const char * rcfname); + +#endif diff --git a/strutil.c b/strutil.c new file mode 100644 index 0000000..2160993 --- /dev/null +++ b/strutil.c @@ -0,0 +1,110 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 1999, 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <ctype.h> +#include "strutil.h" + +const char * left_trimmed(const char * s) +{ + const char * p; + + for (p = s; *p != 0 && isspace (*p); p++); + + return p; +} + +void trim_right (char * s) +{ + char * p; + char * herep; + enum { BLANKS, NONBLANKS } state = NONBLANKS; + + for (herep = 0, p = s; *p != 0; p++) { + switch (state) { + case BLANKS: + if (!isspace (*p)) { + state = NONBLANKS; + } + break; + case NONBLANKS: + if (isspace (*p)) { + herep = p; + state = BLANKS; + } + } + } + if (state == BLANKS) *herep = 0; +} + +#ifdef TESTMAIN + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void +printout (const char * s) +{ + printf("\"%s\"\n", s); +} + +int +main (void) +{ + static const char * teststrings [] = { + "autoksiko", + " autoksiko", + "autoksiko ", + " autoksiko ", + "autoksiko teen", + " autoksiko teen", + "autoksiko teen ", + " autoksiko teen ", + " miljoona miljoona ruusua ", + 0 }; + int i; + + for (i = 0; teststrings [i] != 0; i++) + { + char * ts; + char * orig_ts; + + orig_ts = ts = strdup (teststrings [i]); + if (ts == 0) + exit (EXIT_FAILURE); + + printf ("Plain: "); + printout (ts); + + printf ("Left-trimmed: "); + printout (left_trimmed (ts)); + + printf ("Right-trimmed: "); + trim_right (ts); + printout (ts); + + printf ("Completely trimmed: "); + printout (left_trimmed (ts)); + + puts (""); + free (orig_ts); + } + return 0; +} +#endif /* TESTMAIN */ diff --git a/strutil.h b/strutil.h new file mode 100644 index 0000000..862e721 --- /dev/null +++ b/strutil.h @@ -0,0 +1,43 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 1999, 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef STRUTIL_H__ +#define STRUTIL_H__ + +#include <string.h> + +/* Return a pointer to first nonblank character in s. */ +const char * left_trimmed(const char * s); + +/* Mutate s and trim whitespace off its right end. */ +void trim_right(char * s); + +/* Chop off everything after and including the first comchar in line. + This mutates line! */ +static inline void chop_comment(char * line, char comchar) +{ + char * comstart; + + comstart = strchr (line, comchar); + + if (comstart != 0) + *comstart = 0; +} + +#endif /* STRUTIL_H__ */ @@ -0,0 +1,48 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <publib.h> +#include <stdlib.h> +#include <regex.h> +#include "util.h" + +char * get_regerror (int errcode, regex_t *compiled) +{ + size_t length = regerror (errcode, compiled, NULL, 0); + char * buffer = malloc (length); + + if (buffer == 0) + return 0; + + (void) regerror (errcode, compiled, buffer, length); + return buffer; +} + +char * fnqualify_xalloc(const char * fname) +{ + char * rv = 0; + size_t rv_len = 0; + int actual_len = 0; + + while (actual_len >= rv_len) { + rv = xrealloc(rv, rv_len += 64); + actual_len = fnqualify(rv, fname, rv_len); + } + + return rv; +} @@ -0,0 +1,29 @@ +/* dctrl-tools - Debian control file inspection tools + Copyright (C) 2003 Antti-Juhani Kaijanaho + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UTIL_H +#define UTIL_H + +#include <regex.h> + +char * get_regerror (int errcode, regex_t *compiled); + + +char * fnqualify_xalloc(const char * fname); + +#endif /* UTIL_H */ |