├── COPYING ├── ChangeLog ├── FAQ ├── INSTALL ├── Makefile.am ├── Makefile.in ├── README ├── aclocal.m4 ├── compile ├── config.guess ├── config.sub ├── configure ├── configure.ac ├── csv.3 ├── csv.h ├── csv.pdf ├── depcomp ├── examples ├── csvfix.c ├── csvinfo.c ├── csvtest.c └── csvvalid.c ├── fix-timestamps.sh ├── install-sh ├── libcsv.c ├── ltmain.sh ├── m4 ├── libtool.m4 ├── ltoptions.m4 ├── ltsugar.m4 ├── ltversion.m4 └── lt~obsolete.m4 ├── missing ├── test-driver ├── test_csv.c └── tests ├── test_01.csv ├── test_02.csv ├── test_03.csv ├── test_04.csv ├── test_05.csv ├── test_06.csv ├── test_07.csv ├── test_08.csv ├── test_10.csv ├── test_11.csv ├── test_12.csv └── test_13.csv /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | (This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.) 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Fri Oct 13 08:40:13 EDT 2006 2 | libcsv version 0.9.0 released - initial public release 3 | 4 | Tue Oct 24 08:22:56 EDT 2006 5 | libcsv version 0.9.1 released 6 | * Fixed LICENSE file to include LGPL text instead of GPL text, thanks to Alejandro Mery for pointing this out 7 | * Included a Makefile for platforms supporting make, thanks to Alejandro Mery for creating the initial Makefile 8 | * Updated INSTALL file to include Makefile directions 9 | 10 | 11 | Thu Mar 1 10:27:30 EST 2007 12 | libcsv version 0.9.5 released 13 | * Fixed a bug in which the closing quote of a quoted field, along with any 14 | trailing spaces, would be included as part of the field data for the last field when csv_fini was called if the last record did not end with a newline sequence. This was discovered while testing the Text-CSV-LibCSV Perl wrapper for libcsv created by Jiro Nishiguchi 15 | * Fixed incorrect prototype for csv_fini in the README file, thanks to Edd Edmondson for pointing this out 16 | * Minor modifications to clean up pedantic compiler warnings 17 | * Added "Interfaces for other languages" to the README file 18 | 19 | Sun Mar 4 14:25:07 EST 2007 20 | libcsv version 1.0.0 released 21 | * Changed the interface to allow arbitrary user data to be passed between the parser function and the callback functions via a void pointer eliminating the need for file-scope variables in cases where data needs to be shared and making it considerably easier to create interfaces to the library in other languages. This change makes this version of the library incompatible with previous versions. Thanks to Jiro Nishiguchi for suggesting this change 22 | * man page is now included which obsoletes the old README, pdf version also included 23 | * Updated examples to use new interface 24 | * Updated documentation to reflect interface changes 25 | * Cleaned up INSTALL file 26 | * Included license statement in example programs 27 | 28 | Sun May 20 11:44:09 EDT 2007 29 | libcsv version 1.0.1 released 30 | * Added CSV_STRICT_FINI option which can be used to cause csv_fini() to return an error when the quoted data being parsed doesn't contain a terminating quote character 31 | * Added a test program to test the parsing and writer functions 32 | 33 | Fri Jun 1 11:18:28 EDT 2007 34 | libcsv version 2.0.0 released 35 | * This major release contains features that break binary compatibility with earlier libcsv versions. The interface is backwards compatible with 1.x so existing programs only need to be recompiled to work with the new version, no source code modifications need to be made. 36 | * Added csv_set_delim()/csv_get_delim() and csv_set_quote()/csv_get_quote() functions to set and get the field delimeter and quote characters respectively. Thanks to Martin Ugarte for his input 37 | * Added csv_set_space_func() and csv_set_term_func() functions that allow a user provided function to specify which characters should be considered spaces and line terminators respectively 38 | * Updated documentation to include new functions 39 | * Included FAQ document to answer common questions about using libcsv to solve specific problems 40 | * Updated test program to include ability to test new features 41 | * Updated csvinfo to show the use of some of the new functions 42 | * Added csv_write2 and csv_fwrite2 which allow the quote character to be specified 43 | 44 | Thu Jun 7 14:44:23 EDT 2007 45 | libcsv version 2.0.1 released 46 | * Fixed bug in Makefile causing library to be installed as libcsv.so.0 instead of libcsv.so.2 47 | * Fixed bug in csvvalid example program where location of malformed bytes past byte 1023 were misreported 48 | 49 | Fri Jul 25 22:17:35 EDT 2008 50 | libcsv version 3.0.0 released 51 | * This release contains interface changes that are not compatible with 52 | previous versions. Callback functions now use void * parameters 53 | instead of char *, this eliminates the need to cast data read into a buffer 54 | of unsigned char which is the proper way to read binary data, data is also 55 | treated as an array of unsigned char internally. The cb2 callback function 56 | now uses int instead of char, char has changed to unsigned char in several 57 | places, csv_opts has been replaced with csv_get_opts and csv_set_opts, and 58 | csv_fini returns -1 instead of 0 when no newline if present at the end of 59 | the last record. New features also make this version binary-incompatible 60 | with previous versions. 61 | * Added CSV_APPEND_NULL option which will null-terminate all collected 62 | fields making it easier to treat data as C strings when desired. 63 | * Added C++ wrapper in csv.h to make it easier to call functions from C++. 64 | * Added functions to change the memory allocation functions used, get the 65 | size of the internal buffer, and get and set the size of the amount of 66 | memory requested when the internal buffer gets too large. 67 | 68 | Thu Apr 14 14:17:58 EDT 2011 69 | libcsv version 3.0.1 released 70 | * This version includes a fix for a defect where using csv_parse in 71 | conjunction with the CSV_APPEND_NULL flag could result in an extraneous 72 | byte being added to the end of the data before the nul-terminator was added. 73 | Thanks to Evan Miller for finding and reporting this issue. 74 | * The -fPIC switch, which is needed for several platforms, is now 75 | included in the Makefile. If your compiler complains about this option, 76 | try removing it or replacing it with the equivalent option to generate 77 | position-independent code. 78 | 79 | Tue May 1 11:20:47 EDT 2012 80 | libcsv version 3.0.2 released 81 | * This version addresses an issue encountered when parsing empty fields of 82 | tab-delimited file (sourceforge Issue ID 3513234). 83 | Thanks to Paul Fitzpatrick for reporting this and suggesting a fix. 84 | * libcsv now contains a properly configured autotools build system. 85 | Thanks to Christopher Howard who 86 | did all of the legwork setting this up. 87 | 88 | Wed Jan 9 19:07:20 EST 2013 89 | libcsv version 3.0.3 released 90 | * This version includes a new option, CSV_EMPTY_IS_NULL, to distinguish 91 | between empty, unquoted fields and quoted fields that contain no data. 92 | Thanks to Artur Pyrogovskyi for the suggestion. 93 | -------------------------------------------------------------------------------- /FAQ: -------------------------------------------------------------------------------- 1 | My data contains unescaped quotes within quoted fields or quote 2 | characters in unquoted field. 3 | 4 | libcsv handles such malformed data by default, no special configuration 5 | is required. There are cases where such malformed data is ambigous and 6 | might not be parsed the way you would like, see the man page for libcsv 7 | for details. The csvfix and csvtest programs in the example directory 8 | may be useful when trying to determine how libcsv will parse your data. 9 | The csvvalid program can also be used to check for malformed data files. 10 | 11 | 12 | 13 | My csv file contains comments that should not be parsed as csv data, 14 | how can I handle this? 15 | 16 | Although there is no direct support for comment handling in libcsv you 17 | can preprocess the data before sending it to libcsv. For example, say 18 | that you wish to ignore all lines whose first non-space, non-tab 19 | character is a hash (#), you could use the following piece of code to 20 | accomplish that: 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | int in_comment, in_record; 28 | 29 | void cb1(void *d, char *s, size_t size) { /* Data processing here */ } 30 | void cb2(void *d, char c) { in_record = 0; /* Record handling here */ } 31 | 32 | int main (void) { 33 | int c; 34 | char ch; 35 | struct csv_parser *p; 36 | if (csv_init(&p, 0)) 37 | return EXIT_FAILURE; 38 | 39 | while ((c = getchar()) != EOF) { 40 | ch = c; 41 | if (in_comment) { 42 | if (ch == '\012' || ch == '\015') { 43 | in_comment = 0; 44 | } 45 | } else if (!in_record) { 46 | if (ch == ' ' || ch == '\t') { 47 | ; 48 | } else if (ch == '#') { 49 | in_comment = 1; 50 | } else { 51 | in_record = 1; 52 | csv_parse(p, &ch, 1, cb1, cb2); 53 | } 54 | } else { 55 | csv_parse(p, &ch, 1, cb1, cb2); 56 | } 57 | } 58 | csv_fini(p, ...); 59 | return 0; 60 | } 61 | 62 | If you determine that calling csv_parse for each character takes too 63 | much overhead (do some tests before making this decision, it usually 64 | doesn't) you can optimize this by processing a larger number of 65 | characters and calling csv_parse on a larger resulting buffer. 66 | If you know that your data is text-only, you can simplify this by 67 | reading one line at a time, checking the first non-space character, 68 | skipping the line if it is a comment character and calling csv_parse 69 | if it isn't. 70 | 71 | 72 | 73 | My data uses a semicolon as a delimiter instead of comma but otherwise 74 | follows CSV conventions, how can I use libcsv to read my data? 75 | 76 | Use the csv_set_delim function introduced in libcsv 2.0.0: 77 | struct csv_parser *p; 78 | csv_init(&p); 79 | csv_set_delim(p, ';'); 80 | ... 81 | 82 | You can use csv_set_delim to set the delimiter to any character. Any 83 | field that contains the delimiter must be quoted when using strict 84 | mode. Be careful not to set the delimiter to the same character used 85 | as the quote character, a space character or a line terminator 86 | character though as libcsv won't be able to determine if the character 87 | is a field delimiter or a quote, etc. 88 | 89 | 90 | 91 | My data uses a single quotes instead of double quotes for quoted 92 | fields, how can I accomidate this? 93 | 94 | Use the csv_set_quote function introduced in libcsv 2.0.0: 95 | struct csv_parser *p; 96 | csv_init(&p); 97 | csv_set_quote(p, '\''); 98 | ... 99 | 100 | As with csv_set_delim you can set the quote character to any character 101 | but fields containing the quote character must still be quoted and are 102 | expected to be escaped by an instance of itself. For example, if you 103 | use csv_set_quote to change the quote character to a single quote, 104 | instances of a single quote in field data should be escaped by a 105 | preceding single quote. 106 | 107 | 108 | 109 | How can I preserve leading and trailing whitespace from non-quoted 110 | fields? 111 | 112 | By default libcsv ignores leading and trailing spaces and tabs from 113 | non-quoted fields as this is the most common practice and expected by 114 | many applications. The csv_set_space_func function introduced in 115 | libcsv 2.0.0 allows you to specify a function that will return 1 if 116 | the provided character should be considered a space character and 0 117 | otherwise. This allows you to change the characters that libcsv 118 | ignores around unquoted fields. If you create a function that always 119 | returns 0 then no character will be recognized as a space character 120 | and all characters will be preserved: 121 | 122 | int my_space(char c) { return 0;} 123 | 124 | struct csv_parser *p; 125 | csv_init(&p); 126 | csv_set_space_func(p, my_space); 127 | ... 128 | 129 | 130 | How can I remove leading and trailing whitespace from quoted fields? 131 | 132 | By default libcsv removes surrounding space and tab characters from 133 | unquoted fields but not from quoted fields. The easiest way to remove 134 | unwanted characters from a quoted field is inside the field callback 135 | function, simply take the data provided to the callback function and 136 | perform any manipulations directly on it. 137 | 138 | 139 | 140 | I want to be able to do things like extract or search on specific 141 | fields from a CSV file, sort a CSV file, etc. but the common UNIX 142 | utilities (cut, grep, sort, etc.) don't work on CSV data that contains 143 | fields with embedded commas or newlines, etc. Are there any tools 144 | like this for managing CSV files? 145 | 146 | Take a look at csvutils at https://github.com/rgamble/csvutils. 147 | This package uses libcsv to provide a number of useful CSV utilities 148 | including csvcut, csvgrep, and others with option syntax resembling 149 | their non-CSV counterparts. 150 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | [Installing on systems with make(1)] 2 | 3 | On systems with make, the installation process consists of: 4 | 5 | ./configure 6 | make 7 | make check 8 | make install 9 | 10 | You may need to run ldconfig or a similiar command before dynamically 11 | linking your program to libcsv. 12 | 13 | This will install the csv.h header, libcsv shared and static libraries, 14 | and the csv(3) manual page. Run ./configure --help for other options. 15 | 16 | If you receive an error about files being out of date or automake not installed 17 | when running make, run the fix-timestamps.sh script and try again. 18 | 19 | [Installing on systems without make] 20 | 21 | libcsv is written in pure ANSI C89 and does not have any prerequisites aside 22 | from a compiler and the Standard C library, it should compile on any 23 | conforming implementation. Below are examples of how to compile this on gcc, 24 | see your compiler's documentation for other compilers. 25 | 26 | libcsv can be installed as a shared library on systems that support it: 27 | gcc -shared libcsv.c -o libcsv.so 28 | 29 | or simply compiled into object code an linked into your program: 30 | gcc libcsv.c -c -o libcsv.o 31 | gcc myproject.c libcsv.o -o myproject 32 | 33 | you can also compile libcsv as a static library: 34 | gcc libcsv.c -c -o libcsv.o 35 | ar -rc libcsv.a libcsv.o 36 | ar -s libcsv.a 37 | 38 | 39 | The examples can be compiled with gcc like this: 40 | gcc csvinfo.c libcsv.o -o csvinfo 41 | 42 | or using a shared library like this: 43 | gcc csvinfo.c -lcsv -o csvinfo 44 | 45 | 46 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libcsv.la 2 | libcsv_la_SOURCES = libcsv.c 3 | libcsv_la_LDFLAGS = -version-info 3:3:0 4 | libcsv_la_CFLAGS = -Wall -Wextra 5 | libcsv_includedir = $(includedir) 6 | nobase_libcsv_include_HEADERS = csv.h 7 | dist_man_MANS = csv.3 8 | EXTRA_DIST = FAQ \ 9 | README \ 10 | test_csv.c \ 11 | tests \ 12 | examples \ 13 | csv.pdf \ 14 | COPYING 15 | TESTS = check_csv 16 | check_PROGRAMS = check_csv 17 | check_csv_SOURCES = test_csv.c 18 | check_csv_LDADD = -lcsv 19 | ACLOCAL_AMFLAGS = -I m4 20 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Installation 2 | ------------ 3 | The libcsv library may be installed using the package management software included 4 | with many operating systems. The relevant packages are typically named libcsv3 5 | and libcsv-dev. See the documentation of your operating system's package management 6 | software for details on fetching and installing the appropriate package. 7 | 8 | Installation from source usually consists of: 9 | 10 | ./configure && make && make check && make install 11 | 12 | see the INSTALL file for details and instructions on other systems. 13 | 14 | 15 | License 16 | ------- 17 | The libcsv library is licensed under the LGPL, see the COPYING file for details. 18 | The example programs are not covered under a license and can be used without restriction. 19 | 20 | 21 | Documentation 22 | ------------- 23 | See the accompanying man pages or pdf documentation 24 | 25 | 26 | libcsv interfaces for other programming languages 27 | ------------------------------------------------- 28 | Ruby - Rcsv by Artur Pyrogovskyi 29 | https://github.com/fiksu/rcsv 30 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2012-10-14.11; # UTC 5 | 6 | # Copyright (C) 1999-2013 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) 259 | func_cl_wrapper "$@" # Doesn't return... 260 | ;; 261 | esac 262 | 263 | ofile= 264 | cfile= 265 | 266 | for arg 267 | do 268 | if test -n "$eat"; then 269 | eat= 270 | else 271 | case $1 in 272 | -o) 273 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 274 | # So we strip '-o arg' only if arg is an object. 275 | eat=1 276 | case $2 in 277 | *.o | *.obj) 278 | ofile=$2 279 | ;; 280 | *) 281 | set x "$@" -o "$2" 282 | shift 283 | ;; 284 | esac 285 | ;; 286 | *.c) 287 | cfile=$1 288 | set x "$@" "$1" 289 | shift 290 | ;; 291 | *) 292 | set x "$@" "$1" 293 | shift 294 | ;; 295 | esac 296 | fi 297 | shift 298 | done 299 | 300 | if test -z "$ofile" || test -z "$cfile"; then 301 | # If no '-o' option was seen then we might have been invoked from a 302 | # pattern rule where we don't need one. That is ok -- this is a 303 | # normal compilation that the losing compiler can handle. If no 304 | # '.c' file was seen then we are probably linking. That is also 305 | # ok. 306 | exec "$@" 307 | fi 308 | 309 | # Name of file we expect compiler to create. 310 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 311 | 312 | # Create the lock directory. 313 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 314 | # that we are using for the .o file. Also, base the name on the expected 315 | # object file name, since that is what matters with a parallel build. 316 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 317 | while true; do 318 | if mkdir "$lockdir" >/dev/null 2>&1; then 319 | break 320 | fi 321 | sleep 1 322 | done 323 | # FIXME: race condition here if user kills between mkdir and trap. 324 | trap "rmdir '$lockdir'; exit 1" 1 2 15 325 | 326 | # Run the compile. 327 | "$@" 328 | ret=$? 329 | 330 | if test -f "$cofile"; then 331 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 332 | elif test -f "${cofile}bj"; then 333 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 334 | fi 335 | 336 | rmdir "$lockdir" 337 | exit $ret 338 | 339 | # Local Variables: 340 | # mode: shell-script 341 | # sh-indentation: 2 342 | # eval: (add-hook 'write-file-hooks 'time-stamp) 343 | # time-stamp-start: "scriptversion=" 344 | # time-stamp-format: "%:y-%02m-%02d.%02H" 345 | # time-stamp-time-zone: "UTC" 346 | # time-stamp-end: "; # UTC" 347 | # End: 348 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([libcsv], [3.0.3], [rgamble99@gmail.com], 2 | [libcsv], [https://github.com/rgamble/libcsv]) 3 | AC_PREREQ([2.65]) 4 | AM_INIT_AUTOMAKE([foreign]) 5 | AC_PROG_CC 6 | 7 | LT_INIT 8 | 9 | AC_CONFIG_SRCDIR([libcsv.c]) 10 | AC_CONFIG_FILES([Makefile]) 11 | 12 | AC_OUTPUT 13 | 14 | AC_CONFIG_MACRO_DIR([m4]) 15 | -------------------------------------------------------------------------------- /csv.3: -------------------------------------------------------------------------------- 1 | .TH CSV 3 "20 August 2021" 2 | .SH NAME 3 | csv \- CSV parser and writer library 4 | .SH SYNOPSIS 5 | .nf 6 | .ft B 7 | #include 8 | .LP 9 | .fi 10 | .ft B 11 | int csv_init(struct csv_parser *\fIp\fB, unsigned char \fIoptions\fB); 12 | .nf 13 | .fi 14 | size_t csv_parse(struct csv_parser *\fIp\fB, 15 | .ti +8 16 | const void *\fIs\fB, 17 | .ti +8 18 | size_t \fIlen\fB, 19 | .ti +8 20 | void (*\fIcb1\fB)(void *, size_t, void *), 21 | .ti +8 22 | void (*\fIcb2\fB)(int, void *), 23 | .ti +8 24 | void *\fIdata\fB); 25 | .nf 26 | .fi 27 | int csv_fini(struct csv_parser *\fIp\fB, 28 | .ti +8 29 | void (*\fIcb1\fB)(void *, size_t, void *), 30 | .ti +8 31 | void (*\fIcb2\fB)(int, void *), 32 | .ti +8 33 | void *\fIdata\fB); 34 | .nf 35 | void csv_free(struct csv_parser *\fIp\fB); 36 | 37 | unsigned char csv_get_delim(struct csv_parser *\fIp\fB); 38 | unsigned char csv_get_quote(struct csv_parser *\fIp\fB); 39 | void csv_set_space_func(struct csv_parser *\fIp\fB, int (*\fIf\fB)(unsigned char)); 40 | void csv_set_term_func(struct csv_parser *\fIp\fB, int (*\fIf\fB)(unsigned char)); 41 | 42 | int csv_get_opts(struct csv_parser *\fIp\fB); 43 | int csv_set_opts(struct csv_parser *\fIp\fB, unsigned char \fIoptions\fB); 44 | int csv_error(struct csv_parser *\fIp\fB); 45 | char * csv_strerror(int \fIerror\fB); 46 | 47 | size_t csv_write(void *\fIdest\fB, size_t \fIdest_size\fB, const void *\fIsrc\fB, 48 | .ti +8 49 | size_t \fIsrc_size\fB); 50 | int csv_fwrite(FILE *\fIfp\fB, const void *\fIsrc\fB, size_t \fIsrc_size\fB); 51 | 52 | size_t csv_write2(void *\fIdest\fB, size_t \fIdest_size\fB, const void *\fIsrc\fB, 53 | .ti +8 54 | size_t \fIsrc_size\fB, unsigned char \fIquote\fB); 55 | int csv_fwrite2(FILE *\fIfp\fB, const void *\fIsrc\fB, size_t \fIsrc_size\fB, unsigned char \fIquote\fB); 56 | 57 | void csv_set_realloc_func(struct csv_parser *\fIp\fB, void *(*\fIfunc\fB)(void *, size_t)); 58 | void csv_set_free_func(struct csv_parser *\fIp\fB, void (*\fIfunc\fB)(void *)); 59 | void csv_set_blk_size(struct csv_parser *\fIp\fB, size_t \fIsize\fB); 60 | size_t csv_get_blk_size(struct csv_parser *\fIp\fB); 61 | size_t csv_get_buffer_size(struct csv_parser *\fIp\fB); 62 | 63 | .SH DESCRIPTION 64 | .ft 65 | .ft 66 | .fi 67 | The CSV library provides a flexible, intuitive interface for parsing and writing 68 | csv data. 69 | 70 | .SH OVERVIEW 71 | 72 | The idea behind parsing with \fBlibcsv\fP is straight-forward: you initialize a parser object with 73 | \fBcsv_init()\fP and feed data to the parser over one or more calls to 74 | \fBcsv_parse()\fP providing callback functions that handle end-of-field and 75 | end-of-row events. \fBcsv_parse()\fP parses the data provided calling the 76 | user-defined callback functions as it reads fields and rows. 77 | When complete, \fBcsv_fini()\fP is called to finish processing the current 78 | field and make a final call to the callback functions if necessary. 79 | \fBcsv_free()\fP is then called to free the parser object. 80 | \fBcsv_error()\fP and \fBcsv_strerror()\fP provide information about errors 81 | encountered by the functions. 82 | \fBcsv_write()\fP and \fBcsv_fwrite()\fP provide a simple interface for 83 | converting raw data into CSV data and storing the result into a buffer or 84 | file respectively. 85 | 86 | CSV is a binary format allowing the storage of arbitrary binary data, files 87 | opened for reading or writing CSV data should be opened in binary mode. 88 | 89 | \fBlibcsv\fP provides a default mode in which the parser will happily 90 | process any data as CSV without complaint, this is useful for parsing files 91 | which don't adhere to all the traditional rules. A strict mode is also supported 92 | which will cause any violation of the imposed rules to cause a parsing failure. 93 | 94 | .SH ROUTINES 95 | .ti -4 96 | PARSING DATA 97 | .br 98 | .B csv_init() 99 | initializes a pointer to a \fBcsv_parser\fP structure. 100 | This structure contains housekeeping information 101 | such as the current state of the parser, 102 | the buffer, current size and position, etc. 103 | The \fBcsv_init()\fP function returns 0 on success and a non-zero value 104 | upon failure. \fBcsv_init()\fP will fail if the pointer passed to it is 105 | a null pointer. The \fIoptions\fP argument specifies the 106 | parser options, these may be changed later with the \fBcsv_set_opts()\fP 107 | function. 108 | .PP 109 | \fIOPTIONS\fP 110 | .RS 111 | .TP 112 | \fBCSV_STRICT\fP 113 | Enables strict mode. 114 | .TP 115 | \fBCSV_REPALL_NL\fP 116 | Causes each instance of a carriage return or linefeed outside of a record to be reported. 117 | .TP 118 | \fBCSV_STRICT_FINI\fP 119 | Causes unterminated quoted fields encountered in \fBcsv_fini()\fP to cause a parsing error (see below). 120 | .TP 121 | \fBCSV_APPEND_NULL\fP 122 | Will cause all fields to be nul-terminated when provided to \fIcb1\fP, introduced in 3.0.0. 123 | .TP 124 | \fBCSV_EMPTY_IS_NULL\fP 125 | Will cause NULL to be passed as the first argument to \fIcb1\fP for empty, unquoted, fields. Empty means consisting only of either spaces and tabs or the values defined by the a custom function registered via \fBcsv_set_space_func()\fP. Added in 3.0.3. 126 | .PP 127 | .RE 128 | Multiple options can be specified by OR-ing them together. 129 | .PP 130 | \fBcsv_parse()\fP is the function that does the actual parsing, it takes 131 | 6 arguments: 132 | .RS 133 | .TP 134 | \fIp\fP is a pointer to an initialized \fBstruct csv_parser\fP. 135 | .TP 136 | \fIs\fP is a pointer to the data to read in, such as a dynamically allocated region of memory containing data read in from a call to \fBfread()\fP. 137 | .TP 138 | \fIlen\fP is the number of bytes of data to process. 139 | .TP 140 | \fIcb1\fP is a pointer to the callback function that will be called from \fBcsv_parse()\fP after an entire field has been read. \fIcb1\fP will be called with a pointer to the parsed data (which is NOT nul-terminated unless the CSV_APPEND_NULL option is set), the number of bytes in the data, and the pointer that was passed to \fBcsv_parse()\fP. 141 | .TP 142 | \fIcb2\fP is a pointer to the callback function that will be called when the end of a record is encountered, it will be called with the character that caused the record to end, cast to an unsigned char, or -1 if called from csv_fini, and the pointer that was passed to \fBcsv_parse()\fP. 143 | .TP 144 | \fIdata\fP is a pointer to user-defined data that will be passed to the callback functions when invoked. 145 | .TP 146 | \fIcb1\fP and/or \fIcb2\fP may be \fBNULL\fP in which case no function will be called for the associated actions. \fIdata\fP may also be \fBNULL\fP but the callback functions must be prepared to handle receiving a null pointer. 147 | .RE 148 | 149 | By default \fIcb2\fP is not called when rows that do not contain any fields 150 | are encountered. This behavior is meant to accommodate files using 151 | only either a linefeed or a carriage return as a record separator to 152 | be parsed properly while at the same time being able to parse files with rows 153 | terminated by multiple characters from resulting in blank rows after 154 | each actual row of data (for example, processing a text CSV file 155 | created that was created on a Windows machine on a Unix machine). 156 | The \fBCSV_REPALL_NL\fP option will cause \fBcb2\fP to be called 157 | once for every carriage return or linefeed encountered outside of a field. 158 | \fIcb2\fP is called with the character that prompted the call to the function, 159 | , cast to an unsigned char, either \fBCSV_CR\fP for carriage return, \fBCSV_LF\fP for linefeed, or \fB-1\fP 160 | for record termination from a call to \fBcsv_fini()\fP (see below). 161 | A carriage return or linefeed within a non-quoted field always 162 | marks both the end of the field and the row. Other characters can be used as row terminators and thus be provided as 163 | an argument to \fIcb2\fP using \fBcsv_set_space_func()\fP. 164 | .PP 165 | .B Note: 166 | The first parameter of the \fIcb1\fP function is \fBvoid *\fP, not 167 | \fBconst void *\fP; the pointer passed to the callback function is 168 | actually a pointer to the entry buffer inside the \fBcsv_parser struct\fP, 169 | this data may safely be modified from the callback function (or any 170 | function that the callback function calls) but you must not attempt 171 | to access more than \fIlen\fP bytes and you should not access the data 172 | after the callback function returns as the buffer is dynamically 173 | allocated and its location and size may change during calls to \fBcsv_parse()\fP. 174 | .PP 175 | \fBNote:\fP Different callback functions may safely be specified during each 176 | call to \fBcsv_parse()\fP but keep in mind that the callback 177 | functions may be called many times during a single call to \fBcsv_parse()\fP 178 | depending on the amount of data being processed in a given call. 179 | .PP 180 | \fBcsv_parse()\fP returns the number of bytes processed, on a successful 181 | call this will be \fIlen\fP, if it is less than len an error has occurred. 182 | An error can occur, for example, if there is insufficient memory 183 | to store the contents of the current field in the entry buffer. 184 | An error can also occur if malformed data is encountered while running 185 | in strict mode. 186 | .PP 187 | The \fBcsv_error()\fP function can be used to determine what the error is and 188 | the \fBcsv_strerror()\fP function can be used to provide a textual description 189 | of the error. \fBcsv_error()\fP takes a single argument, a pointer to a 190 | \fBstruct csv_parser\fP, and returns one of the following values defined in 191 | \fBcsv.h\fP: 192 | .PP 193 | .RS 194 | .TP 195 | \fBCSV_EPARSE\fP\ \ \ A parse error has occurred while in strict mode 196 | .TP 197 | \fBCSV_ENOMEM\fP\ \ \ There was not enough memory while attempting to increase the entry buffer for the current field 198 | .TP 199 | \fBCSV_ETOOBIG\fP\ \ Continuing to process the current field would require a buffer of more than SIZE_MAX bytes 200 | .RE 201 | .PP 202 | The value passed to \fBcsv_strerror()\fP should be one returned from 203 | \fBcsv_error()\fP. The return value of \fBcsv_strerror()\fP is a pointer to a 204 | static string. The pointer may be used for the entire 205 | lifetime of the program and the contents will not change during 206 | execution but you must not attempt to modify the string it points to. 207 | .PP 208 | When you have finished submitting data to \fBcsv_parse()\fP, you need 209 | to call the \fBcsv_fini()\fP function. This function will call the \fIcb1\fP 210 | function with any remaining data in the entry buffer (if there is 211 | any) and call the \fIcb2\fP function unless we are already at the end of a row 212 | (the last byte processed was a newline character for example). 213 | It is necessary to call this function because the file being 214 | processed might not end with a carriage return or newline but the 215 | data that has been read in to this point still needs to be 216 | submitted to the callback routines. 217 | If \fIcb2\fP is called from within \fBcsv_fini()\fP it will be because the row was 218 | not terminated with a newline sequence, in this case \fIcb2\fP will be 219 | called with an argument of -1. 220 | 221 | \fBNote:\fP A call to \fBcsv_fini\fP implicitly ends the field current field 222 | and row. If the last field processed is a quoted field that ends before a 223 | closing quote is encountered, no error will be reported by default, even if 224 | CSV_STRICT is specified. To cause \fBcsv_fini()\fP to report an error in such a 225 | case, set the CSV_STRICT_FINI option (new in version 1.0.1) in addition to 226 | the CSV_STRICT option. 227 | 228 | \fBcsv_fini()\fP also reinitializes the parser state so that it is ready to 229 | be used on the next file or set of data. \fBcsv_fini()\fP does not alter 230 | the current buffer size. If the last set of data that was being parsed 231 | contained a very large field that increased the size of the buffer, 232 | and you need to free that memory before continuing, you must call 233 | \fBcsv_free()\fP, you do not need to call \fBcsv_init()\fP again after \fBcsv_free()\fP. 234 | Like csv_parse, the callback 235 | functions provided to \fBcsv_fini()\fP may be NULL. \fBcsv_fini()\fP returns 0 236 | on success and a non-zero value if you pass it a null pointer. 237 | 238 | After calling \fBcsv_fini()\fP you may continue to use the same struct 239 | csv_parser pointer without reinitializing it (in fact you must not call 240 | \fBcsv_init()\fP with an initialized csv_parser object or the memory 241 | allocated for the original structure will be lost). 242 | 243 | When you are finished using the csv_parser object you can free any 244 | dynamically allocated memory associated with it by calling \fBcsv_free()\fP. 245 | You may call \fBcsv_free()\fP at any time, it need not be preceded by a call 246 | to \fBcsv_fini()\fP. You must only call \fBcsv_free()\fP on a csv_parser object 247 | that has been initialized with a successful call to \fBcsv_init()\fP. 248 | 249 | .ti -4 250 | WRITING DATA 251 | .br 252 | \fBlibcsv\fP provides two functions to transform raw data into CSV formatted data: the 253 | \fBcsv_write()\fP function which writes the result to a provided buffer, and 254 | the \fBcsv_fwrite()\fP function which writes the result to a file. 255 | The functionality of both functions is straight-forward, they write 256 | out a single field including the opening and closing quotes and 257 | escape each encountered quote with another quote. 258 | 259 | The \fBcsv_write()\fP function takes a pointer to a source buffer (\fIsrc\fP) 260 | and processes at most \fIsrc_size\fP characters from \fIsrc\fP. 261 | \fBcsv_write()\fP will write at most \fIdest_size\fP characters to \fIdest\fP 262 | and returns the number of characters that would have been written if \fIdest\fP 263 | was large enough. This can be used to determine if all the characters 264 | were written and, if not, how large \fIdest\fP needs to be to write out all of 265 | the data. 266 | \fBcsv_write()\fP may be called with a null pointer for the \fIdest\fP argument 267 | in which case no data is written but the size required to write 268 | out the data will be returned. The space needed to write out the 269 | data is the size of the data + number of quotes appearing in data 270 | (each one will be escaped) + 2 (the leading and terminating quotes). 271 | \fIcsv_write()\fP and \fIcsv_fwrite()\fP always surround the output data with 272 | quotes. 273 | If \fIsrc_size\fP is very large (SIZE_MAX/2 or greater) it is possible that 274 | the number of bytes needed to represent the data, after inserting 275 | escaping quotes, will be greater than SIZE_MAX. In such a case, 276 | csv_write will return SIZE_MAX which should be interpreted as meaning 277 | the data is too large to write to a single field. The \fBcsv_fwrite()\fP 278 | function is not similarly limited. 279 | 280 | \fBcsv_fwrite()\fP takes a FILE pointer (which should have been opened in 281 | binary mode) and converts and writes the data pointed to by \fIsrc\fP 282 | of size \fIsrc_size\fP. It returns \fB0\fP on success and \fBEOF\fP if 283 | there was an error writing to the file. 284 | \fBcsv_fwrite()\fP doesn't provide the number of 285 | characters processed or written. If this functionality is required, 286 | use the \fBcsv_write()\fP function combined with \fBfwrite()\fP. 287 | 288 | \fBcsv_write2()\fP and \fBcsv_fwrite2()\fP work similarly but take an 289 | additional argument, the quote character to use when composing the field. 290 | 291 | .ti -4 292 | CUSTOMIZING THE PARSER 293 | .br 294 | The \fBcsv_set_delim()\fP and \fBcsv_set_quote()\fP functions provide a 295 | means to change the characters that the parser will consider the delimiter 296 | and quote characters respetively, cast to unsigned char. \fBcsv_get_delim()\fP and \fBcsv_get_quote()\fP 297 | return the current delimiter and quote characters respectively. When 298 | \fBcsv_init()\fP is called the delimiter is set to \fBCSV_COMMA\fP and the quote 299 | to \fBCSV_QUOTE\fP. Note that the rest of the CSV conventions still apply 300 | when these functions are used to change the delimiter and/or quote characters, 301 | fields containing the new quote character or delimiter must be quoted and quote 302 | characters must be escaped with an immediately preceding instance of the same 303 | character. 304 | Additionally, the \fBcsv_set_space_func()\fP and \fBcsv_set_term_func()\fP 305 | allow a user-defined function to be provided which will be used determine 306 | what constitutes a space character and what constitutes a record terminator 307 | character. The space characters determine which characters are removed from 308 | the beginning and end of non-quoted fields and the terminator characters 309 | govern when a record ends. When \fBcsv_init()\fP is called, the effect is 310 | as if these functions were each called with a NULL argument in which case 311 | no function is called and CSV_SPACE and CSV_TAB are used for space characters, 312 | and CSV_CR and CSV_LF are used for terminator characters. 313 | 314 | \fBcsv_set_realloc_func()\fP can be used to set the function that is called 315 | when the internal buffer needs to be resized, only realloc, not malloc, is used 316 | internally; the default is to use the standard realloc function. 317 | Likewise, \fBcsv_set_free_func()\fP is used to set the function called to free 318 | the internal buffer, the default is the standard free function. 319 | 320 | \fBcsv_get_blk_size()\fP and \fBcsv_set_blk_size()\fP can be used to get and set 321 | the block size of the parser respectively. The block size if the amount of 322 | extra memory allocated every time the internal buffer needs to be increased, 323 | the default is 128. \fBcsv_get_buffer_size()\fP will return the current 324 | number of bytes allocated for the internal buffer. 325 | 326 | .PP 327 | .SH THE CSV FORMAT 328 | Although quite prevelant there is no standard for 329 | the CSV format. There are however, a set of traditional conventions used by 330 | many applications. \fBlibcsv\fP follows the conventions described at 331 | http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm which seem to 332 | reflect the most common usage of the format, namely: 333 | .PP 334 | .RS 335 | .TP 336 | Fields are separated with commas. 337 | .TP 338 | Rows are delimited by newline sequences (see below). 339 | .TP 340 | Fields may be surrounded with quotes. 341 | .TP 342 | Fields that contain comma, quote, or newline characters MUST be quoted. 343 | .TP 344 | Each instance of a quote character must be escaped with an immediately preceding quote character. 345 | .TP 346 | Leading and trailing spaces and tabs are removed from non-quoted fields. 347 | .TP 348 | The final line need not contain a newline sequence. 349 | .RE 350 | .PP 351 | In strict mode, any detectable violation of these rules results in an error. 352 | .PP 353 | RFC 4180 is an informational memo which attempts to document the 354 | CSV format, especially with regards to its use as a MIME type. 355 | There are a several parts of the description documented in this memo 356 | which either do not accurately reflect widely used conventions or 357 | artificially limit the usefulness of the format. The differences 358 | between the RFC and \fBlibcsv\fP are: 359 | .PP 360 | .RS 361 | .TP 362 | "Each line should contain the same number of fields throughout the file" 363 | \fBlibcsv\fP doesn't care if every record contains a different number of fields, such a restriction could easily be enforced by the application itself if desired. 364 | .TP 365 | "Spaces are considered part of a field and should not be ignored" 366 | Leading and trailing spaces that are part of non-quoted fields are ignored as this is by far the most common behavior and expected by many applications. 367 | 368 | \fBabc , def\fP 369 | 370 | is considered equivalent to: 371 | 372 | \fB"abc", "def"\fP 373 | .TP 374 | "The last field in the record must not be followed by a comma" 375 | The meaning of this statement is not clear but if the last character 376 | of a record is a comma, \fBlibcsv\fP will interpret that as a final empty 377 | field, i.e.: 378 | 379 | \fB"abc", "def",\fP 380 | 381 | will be interpreted as 3 fields, equivalent to: 382 | 383 | \fB"abc", "def", ""\fP 384 | .PP 385 | RFC 4180 limits the allowable characters in a CSV field, \fBlibcsv\fP 386 | allows any character to be present in a field provided it adheres 387 | to the conventions mentioned above. This makes it possible to 388 | store binary data in CSV format, an attribute that many application rely on. 389 | .PP 390 | RFC 4180 states that a Carriage Return plus Linefeed combination is 391 | used to delimit records, \fBlibcsv\fP allows any combination of Carriage 392 | Returns and Linefeeds to signify the end of a record. This is to 393 | increase portability among systems that use different combinations 394 | to denote a newline sequence. 395 | .PP 396 | .SH PARSING MALFORMED DATA 397 | \fBlibcsv\fP should correctly parse any CSV data that conforms to the rules 398 | discussed above. By default, however, \fBlibcsv\fP will also attempt to 399 | parse malformed CSV data such as data containing unescaped quotes 400 | or quotes within non-quoted fields. For example: 401 | .nf 402 | 403 | \fBa"c, "d"f"\fP 404 | 405 | would be parsed equivalently to the correct form: 406 | 407 | \fB"a""c", "d""f"\fP 408 | 409 | .fi 410 | This is often desirable as there are some applications that do 411 | not adhere to the specifications previously discussed. However, 412 | there are instances where malformed CSV data is ambiguous, namely 413 | when a comma or newline is the next non-space character following 414 | a quote such as: 415 | .nf 416 | 417 | \fB"Sally said "Hello", Wally said "Goodbye""\fP 418 | 419 | This could either be parsed as a single field containing the data: 420 | 421 | \fBSally said "Hello", Wally said "Goodbye"\fP 422 | 423 | or as 2 separate fields: 424 | 425 | .fi 426 | \fBSally said "Hello\fP 427 | and 428 | \fBWally said "Goodbye""\fP 429 | 430 | Since the data is malformed, there is no way to know if the quote 431 | before the comma is meant to be a literal quote or if it signifies 432 | the end of the field. This is of course not an issue for properly 433 | formed data as all quotes must be escaped. \fBlibcsv\fP will parse this 434 | example as 2 separate fields. 435 | 436 | \fBlibcsv\fP provides a strict mode that will return with a parse error 437 | if a quote is seen inside a non-quoted field or if a non-escaped 438 | quote is seen whose next non-space character isn't a comma or 439 | newline sequence. 440 | 441 | .PP 442 | .SH PARSER DETAILS 443 | 444 | A field is considered quoted if the first non-space character for a 445 | new field is a quote. 446 | 447 | If a quote is encountered in a quoted field and the next non-space 448 | character is a comma, the field ends at the closed quote and the 449 | field data is submitted when the comma is encountered. If the next 450 | non-space character after a quote is a newline character, the row 451 | has ended and the field data is submitted and the end of row is 452 | signalled (via the appropriate callback function). If two quotes 453 | are immediately adjacent, the first one is interpreted as escaping 454 | the second one and one quote is written to the field buffer. If the 455 | next non-space character following a quote is anything else, the 456 | quote is interpreted as a non-escaped literal quote and it and what 457 | follows are written to the field buffer, this would cause a parse 458 | error in strict mode. 459 | 460 | .nf 461 | Example 1 462 | \fB"abc"""\fP 463 | Parses as: \fBabc"\fP 464 | .fi 465 | The first quote marks the field as quoted, the second quote escapes 466 | the following quote and the last quote ends the field. This is 467 | valid in both strict and non-strict modes. 468 | 469 | .nf 470 | Example 2 471 | \fB"ab"c\fP 472 | Parses as: \fBab"c\fP 473 | .fi 474 | The first qute marks the field as quoted, the second quote is taken 475 | as a literal quote since the next non-space character is not a 476 | comma, or newline and the quote is not escaped. The last quote ends 477 | the field (assuming there is a newline character following). 478 | A parse error would result upon seeing the character c in strict 479 | mode. 480 | 481 | .nf 482 | Example 3 483 | \fB"abc" "\fP 484 | Parses as: \fBabc"\fP 485 | .fi 486 | In this case, since the next non-space character following the second 487 | quote is not a comma or newline character, a literal quote is 488 | written, the space character after is part of the field, and the last 489 | quote terminated the field. This demonstrates the fact that a quote 490 | must immediately precede another quote to escape it. This would be a 491 | strict-mode violation as all quotes are required to be escaped. 492 | .PP 493 | If the field is not quoted, any quote character is taken as part of 494 | the field data, any comma terminated the field, and any newline 495 | character terminated the field and the record. 496 | 497 | .nf 498 | Example 4 499 | \fBab""c\fP 500 | Parses as: \fBab""c\fP 501 | .fi 502 | Quotes are not considered special in non-quoted fields. This would 503 | be a strict mode violation since quotes may not exist in non-quoted 504 | fields in strict mode. 505 | 506 | .SH EXAMPLES 507 | The following example prints the number of fields and rows in a file. 508 | This is a simplified version of the csvinfo program provided in the 509 | examples directory. Error checking not related to \fBlibcsv\fP has been removed 510 | for clarity, the csvinfo program also provides an option for enabling strict 511 | mode and handles multiple files. 512 | .nf 513 | .PP 514 | .RS 515 | #include 516 | #include 517 | #include 518 | #include 519 | #include 520 | 521 | struct counts { 522 | long unsigned fields; 523 | long unsigned rows; 524 | }; 525 | 526 | void cb1 (void *s, size_t len, void *data) { 527 | ((struct counts *)data)->fields++; } 528 | void cb2 (int c, void *data) { 529 | ((struct counts *)data)->rows++; } 530 | 531 | int main (int argc, char *argv[]) { 532 | FILE *fp; 533 | struct csv_parser p; 534 | char buf[1024]; 535 | size_t bytes_read; 536 | struct counts c = {0, 0}; 537 | 538 | if (csv_init(&p, 0) != 0) exit(EXIT_FAILURE); 539 | fp = fopen(argv[1], "rb"); 540 | if (!fp) exit(EXIT_FAILURE); 541 | 542 | while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) 543 | if (csv_parse(&p, buf, bytes_read, cb1, cb2, &c) != bytes_read) { 544 | fprintf(stderr, "Error while parsing file: %s\\n", 545 | csv_strerror(csv_error(&p)) ); 546 | exit(EXIT_FAILURE); 547 | } 548 | 549 | csv_fini(&p, cb1, cb2, &c); 550 | 551 | fclose(fp); 552 | printf("%lu fields, %lu rows\\n", c.fields, c.rows); 553 | 554 | csv_free(&p); 555 | exit(EXIT_SUCCESS); 556 | } 557 | .PP 558 | .RE 559 | .fi 560 | See the examples directory for several complete example programs. 561 | 562 | .SH AUTHOR 563 | Written by Robert Gamble. 564 | 565 | .SH BUGS 566 | Please send questions, comments, bugs, etc. to: 567 | .PP 568 | .ti +8 569 | rgamble99@gmail.com 570 | -------------------------------------------------------------------------------- /csv.h: -------------------------------------------------------------------------------- 1 | /* 2 | libcsv - parse and write csv data 3 | Copyright (C) 2008-2021 Robert Gamble 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef LIBCSV_H__ 21 | #define LIBCSV_H__ 22 | #include 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #define CSV_MAJOR 3 30 | #define CSV_MINOR 0 31 | #define CSV_RELEASE 3 32 | 33 | /* Error Codes */ 34 | #define CSV_SUCCESS 0 35 | #define CSV_EPARSE 1 /* Parse error in strict mode */ 36 | #define CSV_ENOMEM 2 /* Out of memory while increasing buffer size */ 37 | #define CSV_ETOOBIG 3 /* Buffer larger than SIZE_MAX needed */ 38 | #define CSV_EINVALID 4 /* Invalid code,should never be received from csv_error*/ 39 | 40 | 41 | /* parser options */ 42 | #define CSV_STRICT 1 /* enable strict mode */ 43 | #define CSV_REPALL_NL 2 /* report all unquoted carriage returns and linefeeds */ 44 | #define CSV_STRICT_FINI 4 /* causes csv_fini to return CSV_EPARSE if last 45 | field is quoted and doesn't containg ending 46 | quote */ 47 | #define CSV_APPEND_NULL 8 /* Ensure that all fields are null-terminated */ 48 | #define CSV_EMPTY_IS_NULL 16 /* Pass null pointer to cb1 function when 49 | empty, unquoted fields are encountered */ 50 | 51 | 52 | /* Character values */ 53 | #define CSV_TAB 0x09 54 | #define CSV_SPACE 0x20 55 | #define CSV_CR 0x0d 56 | #define CSV_LF 0x0a 57 | #define CSV_COMMA 0x2c 58 | #define CSV_QUOTE 0x22 59 | 60 | struct csv_parser { 61 | int pstate; /* Parser state */ 62 | int quoted; /* Is the current field a quoted field? */ 63 | size_t spaces; /* Number of continious spaces after quote or in a non-quoted field */ 64 | unsigned char * entry_buf; /* Entry buffer */ 65 | size_t entry_pos; /* Current position in entry_buf (and current size of entry) */ 66 | size_t entry_size; /* Size of entry buffer */ 67 | int status; /* Operation status */ 68 | unsigned char options; 69 | unsigned char quote_char; 70 | unsigned char delim_char; 71 | int (*is_space)(unsigned char); 72 | int (*is_term)(unsigned char); 73 | size_t blk_size; 74 | void *(*malloc_func)(size_t); /* not used */ 75 | void *(*realloc_func)(void *, size_t); /* function used to allocate buffer memory */ 76 | void (*free_func)(void *); /* function used to free buffer memory */ 77 | }; 78 | 79 | /* Function Prototypes */ 80 | int csv_init(struct csv_parser *p, unsigned char options); 81 | int csv_fini(struct csv_parser *p, void (*cb1)(void *, size_t, void *), void (*cb2)(int, void *), void *data); 82 | void csv_free(struct csv_parser *p); 83 | int csv_error(const struct csv_parser *p); 84 | const char * csv_strerror(int error); 85 | size_t csv_parse(struct csv_parser *p, const void *s, size_t len, void (*cb1)(void *, size_t, void *), void (*cb2)(int, void *), void *data); 86 | size_t csv_write(void *dest, size_t dest_size, const void *src, size_t src_size); 87 | int csv_fwrite(FILE *fp, const void *src, size_t src_size); 88 | size_t csv_write2(void *dest, size_t dest_size, const void *src, size_t src_size, unsigned char quote); 89 | int csv_fwrite2(FILE *fp, const void *src, size_t src_size, unsigned char quote); 90 | int csv_get_opts(const struct csv_parser *p); 91 | int csv_set_opts(struct csv_parser *p, unsigned char options); 92 | void csv_set_delim(struct csv_parser *p, unsigned char c); 93 | void csv_set_quote(struct csv_parser *p, unsigned char c); 94 | unsigned char csv_get_delim(const struct csv_parser *p); 95 | unsigned char csv_get_quote(const struct csv_parser *p); 96 | void csv_set_space_func(struct csv_parser *p, int (*f)(unsigned char)); 97 | void csv_set_term_func(struct csv_parser *p, int (*f)(unsigned char)); 98 | void csv_set_realloc_func(struct csv_parser *p, void *(*)(void *, size_t)); 99 | void csv_set_free_func(struct csv_parser *p, void (*)(void *)); 100 | void csv_set_blk_size(struct csv_parser *p, size_t); 101 | size_t csv_get_buffer_size(const struct csv_parser *p); 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /csv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rgamble/libcsv/b1d5212831842ee5869d99bc208a21837e4037d5/csv.pdf -------------------------------------------------------------------------------- /depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2013-05-30.07; # UTC 5 | 6 | # Copyright (C) 1999-2013 Free Software Foundation, Inc. 7 | 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2, or (at your option) 11 | # any later version. 12 | 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # As a special exception to the GNU General Public License, if you 22 | # distribute this file as part of a program that contains a 23 | # configuration script generated by Autoconf, you may include it under 24 | # the same distribution terms that you use for the rest of that program. 25 | 26 | # Originally written by Alexandre Oliva . 27 | 28 | case $1 in 29 | '') 30 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 31 | exit 1; 32 | ;; 33 | -h | --h*) 34 | cat <<\EOF 35 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 36 | 37 | Run PROGRAMS ARGS to compile a file, generating dependencies 38 | as side-effects. 39 | 40 | Environment variables: 41 | depmode Dependency tracking mode. 42 | source Source file read by 'PROGRAMS ARGS'. 43 | object Object file output by 'PROGRAMS ARGS'. 44 | DEPDIR directory where to store dependencies. 45 | depfile Dependency file to output. 46 | tmpdepfile Temporary file to use when outputting dependencies. 47 | libtool Whether libtool is used (yes/no). 48 | 49 | Report bugs to . 50 | EOF 51 | exit $? 52 | ;; 53 | -v | --v*) 54 | echo "depcomp $scriptversion" 55 | exit $? 56 | ;; 57 | esac 58 | 59 | # Get the directory component of the given path, and save it in the 60 | # global variables '$dir'. Note that this directory component will 61 | # be either empty or ending with a '/' character. This is deliberate. 62 | set_dir_from () 63 | { 64 | case $1 in 65 | */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; 66 | *) dir=;; 67 | esac 68 | } 69 | 70 | # Get the suffix-stripped basename of the given path, and save it the 71 | # global variable '$base'. 72 | set_base_from () 73 | { 74 | base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` 75 | } 76 | 77 | # If no dependency file was actually created by the compiler invocation, 78 | # we still have to create a dummy depfile, to avoid errors with the 79 | # Makefile "include basename.Plo" scheme. 80 | make_dummy_depfile () 81 | { 82 | echo "#dummy" > "$depfile" 83 | } 84 | 85 | # Factor out some common post-processing of the generated depfile. 86 | # Requires the auxiliary global variable '$tmpdepfile' to be set. 87 | aix_post_process_depfile () 88 | { 89 | # If the compiler actually managed to produce a dependency file, 90 | # post-process it. 91 | if test -f "$tmpdepfile"; then 92 | # Each line is of the form 'foo.o: dependency.h'. 93 | # Do two passes, one to just change these to 94 | # $object: dependency.h 95 | # and one to simply output 96 | # dependency.h: 97 | # which is needed to avoid the deleted-header problem. 98 | { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" 99 | sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" 100 | } > "$depfile" 101 | rm -f "$tmpdepfile" 102 | else 103 | make_dummy_depfile 104 | fi 105 | } 106 | 107 | # A tabulation character. 108 | tab=' ' 109 | # A newline character. 110 | nl=' 111 | ' 112 | # Character ranges might be problematic outside the C locale. 113 | # These definitions help. 114 | upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ 115 | lower=abcdefghijklmnopqrstuvwxyz 116 | digits=0123456789 117 | alpha=${upper}${lower} 118 | 119 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 120 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 121 | exit 1 122 | fi 123 | 124 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 125 | depfile=${depfile-`echo "$object" | 126 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 127 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 128 | 129 | rm -f "$tmpdepfile" 130 | 131 | # Avoid interferences from the environment. 132 | gccflag= dashmflag= 133 | 134 | # Some modes work just like other modes, but use different flags. We 135 | # parameterize here, but still list the modes in the big case below, 136 | # to make depend.m4 easier to write. Note that we *cannot* use a case 137 | # here, because this file can only contain one case statement. 138 | if test "$depmode" = hp; then 139 | # HP compiler uses -M and no extra arg. 140 | gccflag=-M 141 | depmode=gcc 142 | fi 143 | 144 | if test "$depmode" = dashXmstdout; then 145 | # This is just like dashmstdout with a different argument. 146 | dashmflag=-xM 147 | depmode=dashmstdout 148 | fi 149 | 150 | cygpath_u="cygpath -u -f -" 151 | if test "$depmode" = msvcmsys; then 152 | # This is just like msvisualcpp but w/o cygpath translation. 153 | # Just convert the backslash-escaped backslashes to single forward 154 | # slashes to satisfy depend.m4 155 | cygpath_u='sed s,\\\\,/,g' 156 | depmode=msvisualcpp 157 | fi 158 | 159 | if test "$depmode" = msvc7msys; then 160 | # This is just like msvc7 but w/o cygpath translation. 161 | # Just convert the backslash-escaped backslashes to single forward 162 | # slashes to satisfy depend.m4 163 | cygpath_u='sed s,\\\\,/,g' 164 | depmode=msvc7 165 | fi 166 | 167 | if test "$depmode" = xlc; then 168 | # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. 169 | gccflag=-qmakedep=gcc,-MF 170 | depmode=gcc 171 | fi 172 | 173 | case "$depmode" in 174 | gcc3) 175 | ## gcc 3 implements dependency tracking that does exactly what 176 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 177 | ## it if -MD -MP comes after the -MF stuff. Hmm. 178 | ## Unfortunately, FreeBSD c89 acceptance of flags depends upon 179 | ## the command line argument order; so add the flags where they 180 | ## appear in depend2.am. Note that the slowdown incurred here 181 | ## affects only configure: in makefiles, %FASTDEP% shortcuts this. 182 | for arg 183 | do 184 | case $arg in 185 | -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; 186 | *) set fnord "$@" "$arg" ;; 187 | esac 188 | shift # fnord 189 | shift # $arg 190 | done 191 | "$@" 192 | stat=$? 193 | if test $stat -ne 0; then 194 | rm -f "$tmpdepfile" 195 | exit $stat 196 | fi 197 | mv "$tmpdepfile" "$depfile" 198 | ;; 199 | 200 | gcc) 201 | ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. 202 | ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. 203 | ## (see the conditional assignment to $gccflag above). 204 | ## There are various ways to get dependency output from gcc. Here's 205 | ## why we pick this rather obscure method: 206 | ## - Don't want to use -MD because we'd like the dependencies to end 207 | ## up in a subdir. Having to rename by hand is ugly. 208 | ## (We might end up doing this anyway to support other compilers.) 209 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 210 | ## -MM, not -M (despite what the docs say). Also, it might not be 211 | ## supported by the other compilers which use the 'gcc' depmode. 212 | ## - Using -M directly means running the compiler twice (even worse 213 | ## than renaming). 214 | if test -z "$gccflag"; then 215 | gccflag=-MD, 216 | fi 217 | "$@" -Wp,"$gccflag$tmpdepfile" 218 | stat=$? 219 | if test $stat -ne 0; then 220 | rm -f "$tmpdepfile" 221 | exit $stat 222 | fi 223 | rm -f "$depfile" 224 | echo "$object : \\" > "$depfile" 225 | # The second -e expression handles DOS-style file names with drive 226 | # letters. 227 | sed -e 's/^[^:]*: / /' \ 228 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 229 | ## This next piece of magic avoids the "deleted header file" problem. 230 | ## The problem is that when a header file which appears in a .P file 231 | ## is deleted, the dependency causes make to die (because there is 232 | ## typically no way to rebuild the header). We avoid this by adding 233 | ## dummy dependencies for each header file. Too bad gcc doesn't do 234 | ## this for us directly. 235 | ## Some versions of gcc put a space before the ':'. On the theory 236 | ## that the space means something, we add a space to the output as 237 | ## well. hp depmode also adds that space, but also prefixes the VPATH 238 | ## to the object. Take care to not repeat it in the output. 239 | ## Some versions of the HPUX 10.20 sed can't process this invocation 240 | ## correctly. Breaking it into two sed invocations is a workaround. 241 | tr ' ' "$nl" < "$tmpdepfile" \ 242 | | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ 243 | | sed -e 's/$/ :/' >> "$depfile" 244 | rm -f "$tmpdepfile" 245 | ;; 246 | 247 | hp) 248 | # This case exists only to let depend.m4 do its work. It works by 249 | # looking at the text of this script. This case will never be run, 250 | # since it is checked for above. 251 | exit 1 252 | ;; 253 | 254 | sgi) 255 | if test "$libtool" = yes; then 256 | "$@" "-Wp,-MDupdate,$tmpdepfile" 257 | else 258 | "$@" -MDupdate "$tmpdepfile" 259 | fi 260 | stat=$? 261 | if test $stat -ne 0; then 262 | rm -f "$tmpdepfile" 263 | exit $stat 264 | fi 265 | rm -f "$depfile" 266 | 267 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 268 | echo "$object : \\" > "$depfile" 269 | # Clip off the initial element (the dependent). Don't try to be 270 | # clever and replace this with sed code, as IRIX sed won't handle 271 | # lines with more than a fixed number of characters (4096 in 272 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 273 | # the IRIX cc adds comments like '#:fec' to the end of the 274 | # dependency line. 275 | tr ' ' "$nl" < "$tmpdepfile" \ 276 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ 277 | | tr "$nl" ' ' >> "$depfile" 278 | echo >> "$depfile" 279 | # The second pass generates a dummy entry for each header file. 280 | tr ' ' "$nl" < "$tmpdepfile" \ 281 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 282 | >> "$depfile" 283 | else 284 | make_dummy_depfile 285 | fi 286 | rm -f "$tmpdepfile" 287 | ;; 288 | 289 | xlc) 290 | # This case exists only to let depend.m4 do its work. It works by 291 | # looking at the text of this script. This case will never be run, 292 | # since it is checked for above. 293 | exit 1 294 | ;; 295 | 296 | aix) 297 | # The C for AIX Compiler uses -M and outputs the dependencies 298 | # in a .u file. In older versions, this file always lives in the 299 | # current directory. Also, the AIX compiler puts '$object:' at the 300 | # start of each line; $object doesn't have directory information. 301 | # Version 6 uses the directory in both cases. 302 | set_dir_from "$object" 303 | set_base_from "$object" 304 | if test "$libtool" = yes; then 305 | tmpdepfile1=$dir$base.u 306 | tmpdepfile2=$base.u 307 | tmpdepfile3=$dir.libs/$base.u 308 | "$@" -Wc,-M 309 | else 310 | tmpdepfile1=$dir$base.u 311 | tmpdepfile2=$dir$base.u 312 | tmpdepfile3=$dir$base.u 313 | "$@" -M 314 | fi 315 | stat=$? 316 | if test $stat -ne 0; then 317 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 318 | exit $stat 319 | fi 320 | 321 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 322 | do 323 | test -f "$tmpdepfile" && break 324 | done 325 | aix_post_process_depfile 326 | ;; 327 | 328 | tcc) 329 | # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 330 | # FIXME: That version still under development at the moment of writing. 331 | # Make that this statement remains true also for stable, released 332 | # versions. 333 | # It will wrap lines (doesn't matter whether long or short) with a 334 | # trailing '\', as in: 335 | # 336 | # foo.o : \ 337 | # foo.c \ 338 | # foo.h \ 339 | # 340 | # It will put a trailing '\' even on the last line, and will use leading 341 | # spaces rather than leading tabs (at least since its commit 0394caf7 342 | # "Emit spaces for -MD"). 343 | "$@" -MD -MF "$tmpdepfile" 344 | stat=$? 345 | if test $stat -ne 0; then 346 | rm -f "$tmpdepfile" 347 | exit $stat 348 | fi 349 | rm -f "$depfile" 350 | # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. 351 | # We have to change lines of the first kind to '$object: \'. 352 | sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" 353 | # And for each line of the second kind, we have to emit a 'dep.h:' 354 | # dummy dependency, to avoid the deleted-header problem. 355 | sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" 356 | rm -f "$tmpdepfile" 357 | ;; 358 | 359 | ## The order of this option in the case statement is important, since the 360 | ## shell code in configure will try each of these formats in the order 361 | ## listed in this file. A plain '-MD' option would be understood by many 362 | ## compilers, so we must ensure this comes after the gcc and icc options. 363 | pgcc) 364 | # Portland's C compiler understands '-MD'. 365 | # Will always output deps to 'file.d' where file is the root name of the 366 | # source file under compilation, even if file resides in a subdirectory. 367 | # The object file name does not affect the name of the '.d' file. 368 | # pgcc 10.2 will output 369 | # foo.o: sub/foo.c sub/foo.h 370 | # and will wrap long lines using '\' : 371 | # foo.o: sub/foo.c ... \ 372 | # sub/foo.h ... \ 373 | # ... 374 | set_dir_from "$object" 375 | # Use the source, not the object, to determine the base name, since 376 | # that's sadly what pgcc will do too. 377 | set_base_from "$source" 378 | tmpdepfile=$base.d 379 | 380 | # For projects that build the same source file twice into different object 381 | # files, the pgcc approach of using the *source* file root name can cause 382 | # problems in parallel builds. Use a locking strategy to avoid stomping on 383 | # the same $tmpdepfile. 384 | lockdir=$base.d-lock 385 | trap " 386 | echo '$0: caught signal, cleaning up...' >&2 387 | rmdir '$lockdir' 388 | exit 1 389 | " 1 2 13 15 390 | numtries=100 391 | i=$numtries 392 | while test $i -gt 0; do 393 | # mkdir is a portable test-and-set. 394 | if mkdir "$lockdir" 2>/dev/null; then 395 | # This process acquired the lock. 396 | "$@" -MD 397 | stat=$? 398 | # Release the lock. 399 | rmdir "$lockdir" 400 | break 401 | else 402 | # If the lock is being held by a different process, wait 403 | # until the winning process is done or we timeout. 404 | while test -d "$lockdir" && test $i -gt 0; do 405 | sleep 1 406 | i=`expr $i - 1` 407 | done 408 | fi 409 | i=`expr $i - 1` 410 | done 411 | trap - 1 2 13 15 412 | if test $i -le 0; then 413 | echo "$0: failed to acquire lock after $numtries attempts" >&2 414 | echo "$0: check lockdir '$lockdir'" >&2 415 | exit 1 416 | fi 417 | 418 | if test $stat -ne 0; then 419 | rm -f "$tmpdepfile" 420 | exit $stat 421 | fi 422 | rm -f "$depfile" 423 | # Each line is of the form `foo.o: dependent.h', 424 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 425 | # Do two passes, one to just change these to 426 | # `$object: dependent.h' and one to simply `dependent.h:'. 427 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 428 | # Some versions of the HPUX 10.20 sed can't process this invocation 429 | # correctly. Breaking it into two sed invocations is a workaround. 430 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ 431 | | sed -e 's/$/ :/' >> "$depfile" 432 | rm -f "$tmpdepfile" 433 | ;; 434 | 435 | hp2) 436 | # The "hp" stanza above does not work with aCC (C++) and HP's ia64 437 | # compilers, which have integrated preprocessors. The correct option 438 | # to use with these is +Maked; it writes dependencies to a file named 439 | # 'foo.d', which lands next to the object file, wherever that 440 | # happens to be. 441 | # Much of this is similar to the tru64 case; see comments there. 442 | set_dir_from "$object" 443 | set_base_from "$object" 444 | if test "$libtool" = yes; then 445 | tmpdepfile1=$dir$base.d 446 | tmpdepfile2=$dir.libs/$base.d 447 | "$@" -Wc,+Maked 448 | else 449 | tmpdepfile1=$dir$base.d 450 | tmpdepfile2=$dir$base.d 451 | "$@" +Maked 452 | fi 453 | stat=$? 454 | if test $stat -ne 0; then 455 | rm -f "$tmpdepfile1" "$tmpdepfile2" 456 | exit $stat 457 | fi 458 | 459 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" 460 | do 461 | test -f "$tmpdepfile" && break 462 | done 463 | if test -f "$tmpdepfile"; then 464 | sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" 465 | # Add 'dependent.h:' lines. 466 | sed -ne '2,${ 467 | s/^ *// 468 | s/ \\*$// 469 | s/$/:/ 470 | p 471 | }' "$tmpdepfile" >> "$depfile" 472 | else 473 | make_dummy_depfile 474 | fi 475 | rm -f "$tmpdepfile" "$tmpdepfile2" 476 | ;; 477 | 478 | tru64) 479 | # The Tru64 compiler uses -MD to generate dependencies as a side 480 | # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. 481 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 482 | # dependencies in 'foo.d' instead, so we check for that too. 483 | # Subdirectories are respected. 484 | set_dir_from "$object" 485 | set_base_from "$object" 486 | 487 | if test "$libtool" = yes; then 488 | # Libtool generates 2 separate objects for the 2 libraries. These 489 | # two compilations output dependencies in $dir.libs/$base.o.d and 490 | # in $dir$base.o.d. We have to check for both files, because 491 | # one of the two compilations can be disabled. We should prefer 492 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 493 | # automatically cleaned when .libs/ is deleted, while ignoring 494 | # the former would cause a distcleancheck panic. 495 | tmpdepfile1=$dir$base.o.d # libtool 1.5 496 | tmpdepfile2=$dir.libs/$base.o.d # Likewise. 497 | tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 498 | "$@" -Wc,-MD 499 | else 500 | tmpdepfile1=$dir$base.d 501 | tmpdepfile2=$dir$base.d 502 | tmpdepfile3=$dir$base.d 503 | "$@" -MD 504 | fi 505 | 506 | stat=$? 507 | if test $stat -ne 0; then 508 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 509 | exit $stat 510 | fi 511 | 512 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 513 | do 514 | test -f "$tmpdepfile" && break 515 | done 516 | # Same post-processing that is required for AIX mode. 517 | aix_post_process_depfile 518 | ;; 519 | 520 | msvc7) 521 | if test "$libtool" = yes; then 522 | showIncludes=-Wc,-showIncludes 523 | else 524 | showIncludes=-showIncludes 525 | fi 526 | "$@" $showIncludes > "$tmpdepfile" 527 | stat=$? 528 | grep -v '^Note: including file: ' "$tmpdepfile" 529 | if test $stat -ne 0; then 530 | rm -f "$tmpdepfile" 531 | exit $stat 532 | fi 533 | rm -f "$depfile" 534 | echo "$object : \\" > "$depfile" 535 | # The first sed program below extracts the file names and escapes 536 | # backslashes for cygpath. The second sed program outputs the file 537 | # name when reading, but also accumulates all include files in the 538 | # hold buffer in order to output them again at the end. This only 539 | # works with sed implementations that can handle large buffers. 540 | sed < "$tmpdepfile" -n ' 541 | /^Note: including file: *\(.*\)/ { 542 | s//\1/ 543 | s/\\/\\\\/g 544 | p 545 | }' | $cygpath_u | sort -u | sed -n ' 546 | s/ /\\ /g 547 | s/\(.*\)/'"$tab"'\1 \\/p 548 | s/.\(.*\) \\/\1:/ 549 | H 550 | $ { 551 | s/.*/'"$tab"'/ 552 | G 553 | p 554 | }' >> "$depfile" 555 | echo >> "$depfile" # make sure the fragment doesn't end with a backslash 556 | rm -f "$tmpdepfile" 557 | ;; 558 | 559 | msvc7msys) 560 | # This case exists only to let depend.m4 do its work. It works by 561 | # looking at the text of this script. This case will never be run, 562 | # since it is checked for above. 563 | exit 1 564 | ;; 565 | 566 | #nosideeffect) 567 | # This comment above is used by automake to tell side-effect 568 | # dependency tracking mechanisms from slower ones. 569 | 570 | dashmstdout) 571 | # Important note: in order to support this mode, a compiler *must* 572 | # always write the preprocessed file to stdout, regardless of -o. 573 | "$@" || exit $? 574 | 575 | # Remove the call to Libtool. 576 | if test "$libtool" = yes; then 577 | while test "X$1" != 'X--mode=compile'; do 578 | shift 579 | done 580 | shift 581 | fi 582 | 583 | # Remove '-o $object'. 584 | IFS=" " 585 | for arg 586 | do 587 | case $arg in 588 | -o) 589 | shift 590 | ;; 591 | $object) 592 | shift 593 | ;; 594 | *) 595 | set fnord "$@" "$arg" 596 | shift # fnord 597 | shift # $arg 598 | ;; 599 | esac 600 | done 601 | 602 | test -z "$dashmflag" && dashmflag=-M 603 | # Require at least two characters before searching for ':' 604 | # in the target name. This is to cope with DOS-style filenames: 605 | # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. 606 | "$@" $dashmflag | 607 | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" 608 | rm -f "$depfile" 609 | cat < "$tmpdepfile" > "$depfile" 610 | # Some versions of the HPUX 10.20 sed can't process this sed invocation 611 | # correctly. Breaking it into two sed invocations is a workaround. 612 | tr ' ' "$nl" < "$tmpdepfile" \ 613 | | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ 614 | | sed -e 's/$/ :/' >> "$depfile" 615 | rm -f "$tmpdepfile" 616 | ;; 617 | 618 | dashXmstdout) 619 | # This case only exists to satisfy depend.m4. It is never actually 620 | # run, as this mode is specially recognized in the preamble. 621 | exit 1 622 | ;; 623 | 624 | makedepend) 625 | "$@" || exit $? 626 | # Remove any Libtool call 627 | if test "$libtool" = yes; then 628 | while test "X$1" != 'X--mode=compile'; do 629 | shift 630 | done 631 | shift 632 | fi 633 | # X makedepend 634 | shift 635 | cleared=no eat=no 636 | for arg 637 | do 638 | case $cleared in 639 | no) 640 | set ""; shift 641 | cleared=yes ;; 642 | esac 643 | if test $eat = yes; then 644 | eat=no 645 | continue 646 | fi 647 | case "$arg" in 648 | -D*|-I*) 649 | set fnord "$@" "$arg"; shift ;; 650 | # Strip any option that makedepend may not understand. Remove 651 | # the object too, otherwise makedepend will parse it as a source file. 652 | -arch) 653 | eat=yes ;; 654 | -*|$object) 655 | ;; 656 | *) 657 | set fnord "$@" "$arg"; shift ;; 658 | esac 659 | done 660 | obj_suffix=`echo "$object" | sed 's/^.*\././'` 661 | touch "$tmpdepfile" 662 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 663 | rm -f "$depfile" 664 | # makedepend may prepend the VPATH from the source file name to the object. 665 | # No need to regex-escape $object, excess matching of '.' is harmless. 666 | sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" 667 | # Some versions of the HPUX 10.20 sed can't process the last invocation 668 | # correctly. Breaking it into two sed invocations is a workaround. 669 | sed '1,2d' "$tmpdepfile" \ 670 | | tr ' ' "$nl" \ 671 | | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ 672 | | sed -e 's/$/ :/' >> "$depfile" 673 | rm -f "$tmpdepfile" "$tmpdepfile".bak 674 | ;; 675 | 676 | cpp) 677 | # Important note: in order to support this mode, a compiler *must* 678 | # always write the preprocessed file to stdout. 679 | "$@" || exit $? 680 | 681 | # Remove the call to Libtool. 682 | if test "$libtool" = yes; then 683 | while test "X$1" != 'X--mode=compile'; do 684 | shift 685 | done 686 | shift 687 | fi 688 | 689 | # Remove '-o $object'. 690 | IFS=" " 691 | for arg 692 | do 693 | case $arg in 694 | -o) 695 | shift 696 | ;; 697 | $object) 698 | shift 699 | ;; 700 | *) 701 | set fnord "$@" "$arg" 702 | shift # fnord 703 | shift # $arg 704 | ;; 705 | esac 706 | done 707 | 708 | "$@" -E \ 709 | | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 710 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 711 | | sed '$ s: \\$::' > "$tmpdepfile" 712 | rm -f "$depfile" 713 | echo "$object : \\" > "$depfile" 714 | cat < "$tmpdepfile" >> "$depfile" 715 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 716 | rm -f "$tmpdepfile" 717 | ;; 718 | 719 | msvisualcpp) 720 | # Important note: in order to support this mode, a compiler *must* 721 | # always write the preprocessed file to stdout. 722 | "$@" || exit $? 723 | 724 | # Remove the call to Libtool. 725 | if test "$libtool" = yes; then 726 | while test "X$1" != 'X--mode=compile'; do 727 | shift 728 | done 729 | shift 730 | fi 731 | 732 | IFS=" " 733 | for arg 734 | do 735 | case "$arg" in 736 | -o) 737 | shift 738 | ;; 739 | $object) 740 | shift 741 | ;; 742 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 743 | set fnord "$@" 744 | shift 745 | shift 746 | ;; 747 | *) 748 | set fnord "$@" "$arg" 749 | shift 750 | shift 751 | ;; 752 | esac 753 | done 754 | "$@" -E 2>/dev/null | 755 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" 756 | rm -f "$depfile" 757 | echo "$object : \\" > "$depfile" 758 | sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" 759 | echo "$tab" >> "$depfile" 760 | sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" 761 | rm -f "$tmpdepfile" 762 | ;; 763 | 764 | msvcmsys) 765 | # This case exists only to let depend.m4 do its work. It works by 766 | # looking at the text of this script. This case will never be run, 767 | # since it is checked for above. 768 | exit 1 769 | ;; 770 | 771 | none) 772 | exec "$@" 773 | ;; 774 | 775 | *) 776 | echo "Unknown depmode $depmode" 1>&2 777 | exit 1 778 | ;; 779 | esac 780 | 781 | exit 0 782 | 783 | # Local Variables: 784 | # mode: shell-script 785 | # sh-indentation: 2 786 | # eval: (add-hook 'write-file-hooks 'time-stamp) 787 | # time-stamp-start: "scriptversion=" 788 | # time-stamp-format: "%:y-%02m-%02d.%02H" 789 | # time-stamp-time-zone: "UTC" 790 | # time-stamp-end: "; # UTC" 791 | # End: 792 | -------------------------------------------------------------------------------- /examples/csvfix.c: -------------------------------------------------------------------------------- 1 | /* 2 | csvfix - reads (possibly malformed) CSV data from input file 3 | and writes properly formed CSV to output file 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void cb1 (void *s, size_t i, void *outfile) { 13 | csv_fwrite((FILE *)outfile, s, i); 14 | fputc(',',(FILE *)outfile); 15 | } 16 | 17 | void cb2 (int c, void *outfile) { 18 | fseek((FILE *)outfile, -1, SEEK_CUR); 19 | fputc('\n', (FILE *)outfile); 20 | } 21 | 22 | int main (int argc, char *argv[]) { 23 | char buf[1024]; 24 | size_t i; 25 | struct csv_parser p; 26 | FILE *infile, *outfile; 27 | csv_init(&p, 0); 28 | 29 | if (argc != 3) { 30 | fprintf(stderr, "Usage: csv_fix infile outfile\n"); 31 | return EXIT_FAILURE; 32 | } 33 | 34 | if (!strcmp(argv[1], argv[2])) { 35 | fprintf(stderr, "Input file and output file must not be the same!\n"); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | infile = fopen(argv[1], "rb"); 40 | if (infile == NULL) { 41 | fprintf(stderr, "Failed to open file %s: %s\n", argv[1], strerror(errno)); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | outfile = fopen(argv[2], "wb"); 46 | if (outfile == NULL) { 47 | fprintf(stderr, "Failed to open file %s: %s\n", argv[2], strerror(errno)); 48 | fclose(infile); 49 | exit(EXIT_FAILURE); 50 | } 51 | 52 | while ((i=fread(buf, 1, 1024, infile)) > 0) { 53 | if (csv_parse(&p, buf, i, cb1, cb2, outfile) != i) { 54 | fprintf(stderr, "Error parsing file: %s\n", csv_strerror(csv_error(&p))); 55 | fclose(infile); 56 | fclose(outfile); 57 | remove(argv[2]); 58 | exit(EXIT_FAILURE); 59 | } 60 | } 61 | 62 | csv_fini(&p, cb1, cb2, outfile); 63 | csv_free(&p); 64 | 65 | if (ferror(infile)) { 66 | fprintf(stderr, "Error reading from input file"); 67 | fclose(infile); 68 | fclose(outfile); 69 | remove(argv[2]); 70 | exit(EXIT_FAILURE); 71 | } 72 | 73 | fclose(infile); 74 | fclose(outfile); 75 | return EXIT_SUCCESS; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /examples/csvinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | csvinfo - reads CSV data from input file(s) and reports the number 3 | of fields and rows encountered in each file 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | struct counts { 13 | long unsigned fields; 14 | long unsigned rows; 15 | }; 16 | 17 | void cb1 (void *s, size_t len, void *data) { ((struct counts *)data)->fields++; } 18 | void cb2 (int c, void *data) { ((struct counts *)data)->rows++; } 19 | 20 | static int is_space(unsigned char c) { 21 | if (c == CSV_SPACE || c == CSV_TAB) return 1; 22 | return 0; 23 | } 24 | 25 | static int is_term(unsigned char c) { 26 | if (c == CSV_CR || c == CSV_LF) return 1; 27 | return 0; 28 | } 29 | 30 | 31 | int 32 | main (int argc, char *argv[]) 33 | { 34 | FILE *fp; 35 | struct csv_parser p; 36 | char buf[1024]; 37 | size_t bytes_read; 38 | unsigned char options = 0; 39 | struct counts c = {0, 0}; 40 | 41 | if (argc < 2) { 42 | fprintf(stderr, "Usage: csvinfo [-s] files\n"); 43 | exit(EXIT_FAILURE); 44 | } 45 | 46 | if (csv_init(&p, options) != 0) { 47 | fprintf(stderr, "Failed to initialize csv parser\n"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | csv_set_space_func(&p, is_space); 52 | csv_set_term_func(&p, is_term); 53 | 54 | while (*(++argv)) { 55 | if (strcmp(*argv, "-s") == 0) { 56 | options = CSV_STRICT; 57 | csv_set_opts(&p, options); 58 | continue; 59 | } 60 | 61 | fp = fopen(*argv, "rb"); 62 | if (!fp) { 63 | fprintf(stderr, "Failed to open %s: %s\n", *argv, strerror(errno)); 64 | continue; 65 | } 66 | 67 | while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) { 68 | if (csv_parse(&p, buf, bytes_read, cb1, cb2, &c) != bytes_read) { 69 | fprintf(stderr, "Error while parsing file: %s\n", csv_strerror(csv_error(&p))); 70 | } 71 | } 72 | 73 | csv_fini(&p, cb1, cb2, &c); 74 | 75 | if (ferror(fp)) { 76 | fprintf(stderr, "Error while reading file %s\n", *argv); 77 | fclose(fp); 78 | continue; 79 | } 80 | 81 | fclose(fp); 82 | printf("%s: %lu fields, %lu rows\n", *argv, c.fields, c.rows); 83 | } 84 | 85 | csv_free(&p); 86 | exit(EXIT_SUCCESS); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /examples/csvtest.c: -------------------------------------------------------------------------------- 1 | /* 2 | csvtest - reads CSV data from stdin and output properly formed equivalent 3 | useful for testing the library 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static int put_comma; 14 | 15 | void cb1 (void *s, size_t i, void *p) { 16 | if (put_comma) 17 | putc(',', stdout); 18 | csv_fwrite(stdout, s, i); 19 | put_comma = 1; 20 | } 21 | 22 | void cb2 (int c, void *p) { 23 | put_comma = 0; 24 | putc('\n', stdout); 25 | } 26 | 27 | int main (void) { 28 | struct csv_parser p; 29 | int i; 30 | char c; 31 | 32 | csv_init(&p, 0); 33 | 34 | while ((i=getc(stdin)) != EOF) { 35 | c = i; 36 | if (csv_parse(&p, &c, 1, cb1, cb2, NULL) != 1) { 37 | fprintf(stderr, "Error: %s\n", csv_strerror(csv_error(&p))); 38 | exit(EXIT_FAILURE); 39 | } 40 | } 41 | 42 | csv_fini(&p, cb1, cb2, NULL); 43 | csv_free(&p); 44 | 45 | return EXIT_SUCCESS; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /examples/csvvalid.c: -------------------------------------------------------------------------------- 1 | /* 2 | csvvalid - determine if files are properly formed CSV files and display 3 | position of first offending byte if not 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int 13 | main (int argc, char *argv[]) 14 | { 15 | FILE *fp; 16 | int i; 17 | struct csv_parser p; 18 | char buf[1024]; 19 | size_t bytes_read; 20 | size_t pos; 21 | size_t retval; 22 | 23 | if (argc < 2) { 24 | fprintf(stderr, "Usage: csvvalid files\n"); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | if (csv_init(&p, CSV_STRICT) != 0) { 29 | fprintf(stderr, "Failed to initialize csv parser\n"); 30 | exit(EXIT_FAILURE); 31 | } 32 | 33 | for (i = 1; i < argc; i++) { 34 | pos = 0; 35 | fp = fopen(argv[i], "rb"); 36 | if (!fp) { 37 | fprintf(stderr, "Failed to open %s: %s, skipping\n", argv[i], strerror(errno)); 38 | continue; 39 | } 40 | while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) { 41 | if ((retval = csv_parse(&p, buf, bytes_read, NULL, NULL, NULL)) != bytes_read) { 42 | if (csv_error(&p) == CSV_EPARSE) { 43 | printf("%s: malformed at byte %lu\n", argv[i], (unsigned long)pos + retval + 1); 44 | goto end; 45 | } else { 46 | printf("Error while processing %s: %s\n", argv[i], csv_strerror(csv_error(&p))); 47 | goto end; 48 | } 49 | } 50 | pos += bytes_read; 51 | } 52 | printf("%s well-formed\n", argv[i]); 53 | 54 | end: 55 | fclose(fp); 56 | csv_fini(&p, NULL, NULL, NULL); 57 | pos = 0; 58 | } 59 | 60 | csv_free(&p); 61 | return EXIT_SUCCESS; 62 | } 63 | -------------------------------------------------------------------------------- /fix-timestamps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sleep 1 4 | touch aclocal.m4 5 | sleep 1 6 | touch configure 7 | touch Makefile.in 8 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2011-11-20.07; # UTC 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # 'make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | nl=' 45 | ' 46 | IFS=" "" $nl" 47 | 48 | # set DOITPROG to echo to test this script 49 | 50 | # Don't use :- since 4.3BSD and earlier shells don't like it. 51 | doit=${DOITPROG-} 52 | if test -z "$doit"; then 53 | doit_exec=exec 54 | else 55 | doit_exec=$doit 56 | fi 57 | 58 | # Put in absolute file names if you don't have them in your path; 59 | # or use environment vars. 60 | 61 | chgrpprog=${CHGRPPROG-chgrp} 62 | chmodprog=${CHMODPROG-chmod} 63 | chownprog=${CHOWNPROG-chown} 64 | cmpprog=${CMPPROG-cmp} 65 | cpprog=${CPPROG-cp} 66 | mkdirprog=${MKDIRPROG-mkdir} 67 | mvprog=${MVPROG-mv} 68 | rmprog=${RMPROG-rm} 69 | stripprog=${STRIPPROG-strip} 70 | 71 | posix_glob='?' 72 | initialize_posix_glob=' 73 | test "$posix_glob" != "?" || { 74 | if (set -f) 2>/dev/null; then 75 | posix_glob= 76 | else 77 | posix_glob=: 78 | fi 79 | } 80 | ' 81 | 82 | posix_mkdir= 83 | 84 | # Desired mode of installed file. 85 | mode=0755 86 | 87 | chgrpcmd= 88 | chmodcmd=$chmodprog 89 | chowncmd= 90 | mvcmd=$mvprog 91 | rmcmd="$rmprog -f" 92 | stripcmd= 93 | 94 | src= 95 | dst= 96 | dir_arg= 97 | dst_arg= 98 | 99 | copy_on_change=false 100 | no_target_directory= 101 | 102 | usage="\ 103 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104 | or: $0 [OPTION]... SRCFILES... DIRECTORY 105 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106 | or: $0 [OPTION]... -d DIRECTORIES... 107 | 108 | In the 1st form, copy SRCFILE to DSTFILE. 109 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110 | In the 4th, create DIRECTORIES. 111 | 112 | Options: 113 | --help display this help and exit. 114 | --version display version info and exit. 115 | 116 | -c (ignored) 117 | -C install only if different (preserve the last data modification time) 118 | -d create directories instead of installing files. 119 | -g GROUP $chgrpprog installed files to GROUP. 120 | -m MODE $chmodprog installed files to MODE. 121 | -o USER $chownprog installed files to USER. 122 | -s $stripprog installed files. 123 | -t DIRECTORY install into DIRECTORY. 124 | -T report an error if DSTFILE is a directory. 125 | 126 | Environment variables override the default commands: 127 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128 | RMPROG STRIPPROG 129 | " 130 | 131 | while test $# -ne 0; do 132 | case $1 in 133 | -c) ;; 134 | 135 | -C) copy_on_change=true;; 136 | 137 | -d) dir_arg=true;; 138 | 139 | -g) chgrpcmd="$chgrpprog $2" 140 | shift;; 141 | 142 | --help) echo "$usage"; exit $?;; 143 | 144 | -m) mode=$2 145 | case $mode in 146 | *' '* | *' '* | *' 147 | '* | *'*'* | *'?'* | *'['*) 148 | echo "$0: invalid mode: $mode" >&2 149 | exit 1;; 150 | esac 151 | shift;; 152 | 153 | -o) chowncmd="$chownprog $2" 154 | shift;; 155 | 156 | -s) stripcmd=$stripprog;; 157 | 158 | -t) dst_arg=$2 159 | # Protect names problematic for 'test' and other utilities. 160 | case $dst_arg in 161 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 162 | esac 163 | shift;; 164 | 165 | -T) no_target_directory=true;; 166 | 167 | --version) echo "$0 $scriptversion"; exit $?;; 168 | 169 | --) shift 170 | break;; 171 | 172 | -*) echo "$0: invalid option: $1" >&2 173 | exit 1;; 174 | 175 | *) break;; 176 | esac 177 | shift 178 | done 179 | 180 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 181 | # When -d is used, all remaining arguments are directories to create. 182 | # When -t is used, the destination is already specified. 183 | # Otherwise, the last argument is the destination. Remove it from $@. 184 | for arg 185 | do 186 | if test -n "$dst_arg"; then 187 | # $@ is not empty: it contains at least $arg. 188 | set fnord "$@" "$dst_arg" 189 | shift # fnord 190 | fi 191 | shift # arg 192 | dst_arg=$arg 193 | # Protect names problematic for 'test' and other utilities. 194 | case $dst_arg in 195 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 196 | esac 197 | done 198 | fi 199 | 200 | if test $# -eq 0; then 201 | if test -z "$dir_arg"; then 202 | echo "$0: no input file specified." >&2 203 | exit 1 204 | fi 205 | # It's OK to call 'install-sh -d' without argument. 206 | # This can happen when creating conditional directories. 207 | exit 0 208 | fi 209 | 210 | if test -z "$dir_arg"; then 211 | do_exit='(exit $ret); exit $ret' 212 | trap "ret=129; $do_exit" 1 213 | trap "ret=130; $do_exit" 2 214 | trap "ret=141; $do_exit" 13 215 | trap "ret=143; $do_exit" 15 216 | 217 | # Set umask so as not to create temps with too-generous modes. 218 | # However, 'strip' requires both read and write access to temps. 219 | case $mode in 220 | # Optimize common cases. 221 | *644) cp_umask=133;; 222 | *755) cp_umask=22;; 223 | 224 | *[0-7]) 225 | if test -z "$stripcmd"; then 226 | u_plus_rw= 227 | else 228 | u_plus_rw='% 200' 229 | fi 230 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 231 | *) 232 | if test -z "$stripcmd"; then 233 | u_plus_rw= 234 | else 235 | u_plus_rw=,u+rw 236 | fi 237 | cp_umask=$mode$u_plus_rw;; 238 | esac 239 | fi 240 | 241 | for src 242 | do 243 | # Protect names problematic for 'test' and other utilities. 244 | case $src in 245 | -* | [=\(\)!]) src=./$src;; 246 | esac 247 | 248 | if test -n "$dir_arg"; then 249 | dst=$src 250 | dstdir=$dst 251 | test -d "$dstdir" 252 | dstdir_status=$? 253 | else 254 | 255 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 256 | # might cause directories to be created, which would be especially bad 257 | # if $src (and thus $dsttmp) contains '*'. 258 | if test ! -f "$src" && test ! -d "$src"; then 259 | echo "$0: $src does not exist." >&2 260 | exit 1 261 | fi 262 | 263 | if test -z "$dst_arg"; then 264 | echo "$0: no destination specified." >&2 265 | exit 1 266 | fi 267 | dst=$dst_arg 268 | 269 | # If destination is a directory, append the input filename; won't work 270 | # if double slashes aren't ignored. 271 | if test -d "$dst"; then 272 | if test -n "$no_target_directory"; then 273 | echo "$0: $dst_arg: Is a directory" >&2 274 | exit 1 275 | fi 276 | dstdir=$dst 277 | dst=$dstdir/`basename "$src"` 278 | dstdir_status=0 279 | else 280 | # Prefer dirname, but fall back on a substitute if dirname fails. 281 | dstdir=` 282 | (dirname "$dst") 2>/dev/null || 283 | expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 284 | X"$dst" : 'X\(//\)[^/]' \| \ 285 | X"$dst" : 'X\(//\)$' \| \ 286 | X"$dst" : 'X\(/\)' \| . 2>/dev/null || 287 | echo X"$dst" | 288 | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 289 | s//\1/ 290 | q 291 | } 292 | /^X\(\/\/\)[^/].*/{ 293 | s//\1/ 294 | q 295 | } 296 | /^X\(\/\/\)$/{ 297 | s//\1/ 298 | q 299 | } 300 | /^X\(\/\).*/{ 301 | s//\1/ 302 | q 303 | } 304 | s/.*/./; q' 305 | ` 306 | 307 | test -d "$dstdir" 308 | dstdir_status=$? 309 | fi 310 | fi 311 | 312 | obsolete_mkdir_used=false 313 | 314 | if test $dstdir_status != 0; then 315 | case $posix_mkdir in 316 | '') 317 | # Create intermediate dirs using mode 755 as modified by the umask. 318 | # This is like FreeBSD 'install' as of 1997-10-28. 319 | umask=`umask` 320 | case $stripcmd.$umask in 321 | # Optimize common cases. 322 | *[2367][2367]) mkdir_umask=$umask;; 323 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 324 | 325 | *[0-7]) 326 | mkdir_umask=`expr $umask + 22 \ 327 | - $umask % 100 % 40 + $umask % 20 \ 328 | - $umask % 10 % 4 + $umask % 2 329 | `;; 330 | *) mkdir_umask=$umask,go-w;; 331 | esac 332 | 333 | # With -d, create the new directory with the user-specified mode. 334 | # Otherwise, rely on $mkdir_umask. 335 | if test -n "$dir_arg"; then 336 | mkdir_mode=-m$mode 337 | else 338 | mkdir_mode= 339 | fi 340 | 341 | posix_mkdir=false 342 | case $umask in 343 | *[123567][0-7][0-7]) 344 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 345 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 346 | ;; 347 | *) 348 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 349 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 350 | 351 | if (umask $mkdir_umask && 352 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 353 | then 354 | if test -z "$dir_arg" || { 355 | # Check for POSIX incompatibilities with -m. 356 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 357 | # other-writable bit of parent directory when it shouldn't. 358 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 359 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 360 | case $ls_ld_tmpdir in 361 | d????-?r-*) different_mode=700;; 362 | d????-?--*) different_mode=755;; 363 | *) false;; 364 | esac && 365 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 366 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 367 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 368 | } 369 | } 370 | then posix_mkdir=: 371 | fi 372 | rmdir "$tmpdir/d" "$tmpdir" 373 | else 374 | # Remove any dirs left behind by ancient mkdir implementations. 375 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 376 | fi 377 | trap '' 0;; 378 | esac;; 379 | esac 380 | 381 | if 382 | $posix_mkdir && ( 383 | umask $mkdir_umask && 384 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 385 | ) 386 | then : 387 | else 388 | 389 | # The umask is ridiculous, or mkdir does not conform to POSIX, 390 | # or it failed possibly due to a race condition. Create the 391 | # directory the slow way, step by step, checking for races as we go. 392 | 393 | case $dstdir in 394 | /*) prefix='/';; 395 | [-=\(\)!]*) prefix='./';; 396 | *) prefix='';; 397 | esac 398 | 399 | eval "$initialize_posix_glob" 400 | 401 | oIFS=$IFS 402 | IFS=/ 403 | $posix_glob set -f 404 | set fnord $dstdir 405 | shift 406 | $posix_glob set +f 407 | IFS=$oIFS 408 | 409 | prefixes= 410 | 411 | for d 412 | do 413 | test X"$d" = X && continue 414 | 415 | prefix=$prefix$d 416 | if test -d "$prefix"; then 417 | prefixes= 418 | else 419 | if $posix_mkdir; then 420 | (umask=$mkdir_umask && 421 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 422 | # Don't fail if two instances are running concurrently. 423 | test -d "$prefix" || exit 1 424 | else 425 | case $prefix in 426 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 427 | *) qprefix=$prefix;; 428 | esac 429 | prefixes="$prefixes '$qprefix'" 430 | fi 431 | fi 432 | prefix=$prefix/ 433 | done 434 | 435 | if test -n "$prefixes"; then 436 | # Don't fail if two instances are running concurrently. 437 | (umask $mkdir_umask && 438 | eval "\$doit_exec \$mkdirprog $prefixes") || 439 | test -d "$dstdir" || exit 1 440 | obsolete_mkdir_used=true 441 | fi 442 | fi 443 | fi 444 | 445 | if test -n "$dir_arg"; then 446 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 447 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 448 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 449 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 450 | else 451 | 452 | # Make a couple of temp file names in the proper directory. 453 | dsttmp=$dstdir/_inst.$$_ 454 | rmtmp=$dstdir/_rm.$$_ 455 | 456 | # Trap to clean up those temp files at exit. 457 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 458 | 459 | # Copy the file name to the temp name. 460 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 461 | 462 | # and set any options; do chmod last to preserve setuid bits. 463 | # 464 | # If any of these fail, we abort the whole thing. If we want to 465 | # ignore errors from any of these, just make sure not to ignore 466 | # errors from the above "$doit $cpprog $src $dsttmp" command. 467 | # 468 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 469 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 470 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 471 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 472 | 473 | # If -C, don't bother to copy if it wouldn't change the file. 474 | if $copy_on_change && 475 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 476 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 477 | 478 | eval "$initialize_posix_glob" && 479 | $posix_glob set -f && 480 | set X $old && old=:$2:$4:$5:$6 && 481 | set X $new && new=:$2:$4:$5:$6 && 482 | $posix_glob set +f && 483 | 484 | test "$old" = "$new" && 485 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 486 | then 487 | rm -f "$dsttmp" 488 | else 489 | # Rename the file to the real destination. 490 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 491 | 492 | # The rename failed, perhaps because mv can't rename something else 493 | # to itself, or perhaps because mv is so ancient that it does not 494 | # support -f. 495 | { 496 | # Now remove or move aside any old file at destination location. 497 | # We try this two ways since rm can't unlink itself on some 498 | # systems and the destination file might be busy for other 499 | # reasons. In this case, the final cleanup might fail but the new 500 | # file should still install successfully. 501 | { 502 | test ! -f "$dst" || 503 | $doit $rmcmd -f "$dst" 2>/dev/null || 504 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 505 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 506 | } || 507 | { echo "$0: cannot unlink or rename $dst" >&2 508 | (exit 1); exit 1 509 | } 510 | } && 511 | 512 | # Now rename the file to the real destination. 513 | $doit $mvcmd "$dsttmp" "$dst" 514 | } 515 | fi || exit 1 516 | 517 | trap '' 0 518 | fi 519 | done 520 | 521 | # Local variables: 522 | # eval: (add-hook 'write-file-hooks 'time-stamp) 523 | # time-stamp-start: "scriptversion=" 524 | # time-stamp-format: "%:y-%02m-%02d.%02H" 525 | # time-stamp-time-zone: "UTC" 526 | # time-stamp-end: "; # UTC" 527 | # End: 528 | -------------------------------------------------------------------------------- /libcsv.c: -------------------------------------------------------------------------------- 1 | /* 2 | libcsv - parse and write csv data 3 | Copyright (C) 2008 Robert Gamble 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | 22 | #if __STDC_VERSION__ >= 199901L 23 | # include 24 | #else 25 | # define SIZE_MAX ((size_t)-1) /* C89 doesn't have stdint.h or SIZE_MAX */ 26 | #endif 27 | 28 | #include "csv.h" 29 | 30 | #define VERSION "3.0.3" 31 | 32 | #define ROW_NOT_BEGUN 0 33 | #define FIELD_NOT_BEGUN 1 34 | #define FIELD_BEGUN 2 35 | #define FIELD_MIGHT_HAVE_ENDED 3 36 | 37 | /* 38 | Explanation of states 39 | ROW_NOT_BEGUN There have not been any fields encountered for this row 40 | FIELD_NOT_BEGUN There have been fields but we are currently not in one 41 | FIELD_BEGUN We are in a field 42 | FIELD_MIGHT_HAVE_ENDED 43 | We encountered a double quote inside a quoted field, the 44 | field is either ended or the quote is literal 45 | */ 46 | 47 | #define MEM_BLK_SIZE 128 48 | 49 | #define SUBMIT_FIELD(p) \ 50 | do { \ 51 | if (!quoted) \ 52 | entry_pos -= spaces; \ 53 | if (p->options & CSV_APPEND_NULL) \ 54 | ((p)->entry_buf[entry_pos]) = '\0'; \ 55 | if (cb1 && (p->options & CSV_EMPTY_IS_NULL) && !quoted && entry_pos == 0) \ 56 | cb1(NULL, entry_pos, data); \ 57 | else if (cb1) \ 58 | cb1(p->entry_buf, entry_pos, data); \ 59 | pstate = FIELD_NOT_BEGUN; \ 60 | entry_pos = quoted = spaces = 0; \ 61 | } while (0) 62 | 63 | #define SUBMIT_ROW(p, c) \ 64 | do { \ 65 | if (cb2) \ 66 | cb2(c, data); \ 67 | pstate = ROW_NOT_BEGUN; \ 68 | entry_pos = quoted = spaces = 0; \ 69 | } while (0) 70 | 71 | #define SUBMIT_CHAR(p, c) ((p)->entry_buf[entry_pos++] = (c)) 72 | 73 | static const char *csv_errors[] = {"success", 74 | "error parsing data while strict checking enabled", 75 | "memory exhausted while increasing buffer size", 76 | "data size too large", 77 | "invalid status code"}; 78 | 79 | int 80 | csv_error(const struct csv_parser *p) 81 | { 82 | assert(p && "received null csv_parser"); 83 | 84 | /* Return the current status of the parser */ 85 | return p->status; 86 | } 87 | 88 | const char * 89 | csv_strerror(int status) 90 | { 91 | /* Return a textual description of status */ 92 | if (status >= CSV_EINVALID || status < 0) 93 | return csv_errors[CSV_EINVALID]; 94 | else 95 | return csv_errors[status]; 96 | } 97 | 98 | int 99 | csv_get_opts(const struct csv_parser *p) 100 | { 101 | /* Return the currently set options of parser */ 102 | if (p == NULL) 103 | return -1; 104 | 105 | return p->options; 106 | } 107 | 108 | int 109 | csv_set_opts(struct csv_parser *p, unsigned char options) 110 | { 111 | /* Set the options */ 112 | if (p == NULL) 113 | return -1; 114 | 115 | p->options = options; 116 | return 0; 117 | } 118 | 119 | int 120 | csv_init(struct csv_parser *p, unsigned char options) 121 | { 122 | /* Initialize a csv_parser object returns 0 on success, -1 on error */ 123 | if (p == NULL) 124 | return -1; 125 | 126 | p->entry_buf = NULL; 127 | p->pstate = ROW_NOT_BEGUN; 128 | p->quoted = 0; 129 | p->spaces = 0; 130 | p->entry_pos = 0; 131 | p->entry_size = 0; 132 | p->status = 0; 133 | p->options = options; 134 | p->quote_char = CSV_QUOTE; 135 | p->delim_char = CSV_COMMA; 136 | p->is_space = NULL; 137 | p->is_term = NULL; 138 | p->blk_size = MEM_BLK_SIZE; 139 | p->malloc_func = NULL; 140 | p->realloc_func = realloc; 141 | p->free_func = free; 142 | 143 | return 0; 144 | } 145 | 146 | void 147 | csv_free(struct csv_parser *p) 148 | { 149 | /* Free the entry_buffer of csv_parser object */ 150 | if (p == NULL) 151 | return; 152 | 153 | if (p->entry_buf && p->free_func) 154 | p->free_func(p->entry_buf); 155 | 156 | p->entry_buf = NULL; 157 | p->entry_size = 0; 158 | 159 | return; 160 | } 161 | 162 | int 163 | csv_fini(struct csv_parser *p, void (*cb1)(void *, size_t, void *), void (*cb2)(int c, void *), void *data) 164 | { 165 | if (p == NULL) 166 | return -1; 167 | 168 | /* Finalize parsing. Needed, for example, when file does not end in a newline */ 169 | int quoted = p->quoted; 170 | int pstate = p->pstate; 171 | size_t spaces = p->spaces; 172 | size_t entry_pos = p->entry_pos; 173 | 174 | if ((pstate == FIELD_BEGUN) && p->quoted && (p->options & CSV_STRICT) && (p->options & CSV_STRICT_FINI)) { 175 | /* Current field is quoted, no end-quote was seen, and CSV_STRICT_FINI is set */ 176 | p->status = CSV_EPARSE; 177 | return -1; 178 | } 179 | 180 | switch (pstate) { 181 | case FIELD_MIGHT_HAVE_ENDED: 182 | p->entry_pos -= p->spaces + 1; /* get rid of spaces and original quote */ 183 | entry_pos = p->entry_pos; 184 | /*lint -fallthrough */ 185 | case FIELD_NOT_BEGUN: 186 | case FIELD_BEGUN: 187 | /* Unnecessary: 188 | quoted = p->quoted, pstate = p->pstate; 189 | spaces = p->spaces, entry_pos = p->entry_pos; 190 | */ 191 | SUBMIT_FIELD(p); 192 | SUBMIT_ROW(p, -1); 193 | break; 194 | case ROW_NOT_BEGUN: /* Already ended properly */ 195 | ; 196 | } 197 | 198 | /* Reset parser */ 199 | p->spaces = p->quoted = p->entry_pos = p->status = 0; 200 | p->pstate = ROW_NOT_BEGUN; 201 | 202 | return 0; 203 | } 204 | 205 | void 206 | csv_set_delim(struct csv_parser *p, unsigned char c) 207 | { 208 | /* Set the delimiter */ 209 | if (p) p->delim_char = c; 210 | } 211 | 212 | void 213 | csv_set_quote(struct csv_parser *p, unsigned char c) 214 | { 215 | /* Set the quote character */ 216 | if (p) p->quote_char = c; 217 | } 218 | 219 | unsigned char 220 | csv_get_delim(const struct csv_parser *p) 221 | { 222 | assert(p && "received null csv_parser"); 223 | 224 | /* Get the delimiter */ 225 | return p->delim_char; 226 | } 227 | 228 | unsigned char 229 | csv_get_quote(const struct csv_parser *p) 230 | { 231 | assert(p && "received null csv_parser"); 232 | 233 | /* Get the quote character */ 234 | return p->quote_char; 235 | } 236 | 237 | void 238 | csv_set_space_func(struct csv_parser *p, int (*f)(unsigned char)) 239 | { 240 | /* Set the space function */ 241 | if (p) p->is_space = f; 242 | } 243 | 244 | void 245 | csv_set_term_func(struct csv_parser *p, int (*f)(unsigned char)) 246 | { 247 | /* Set the term function */ 248 | if (p) p->is_term = f; 249 | } 250 | 251 | void 252 | csv_set_realloc_func(struct csv_parser *p, void *(*f)(void *, size_t)) 253 | { 254 | /* Set the realloc function used to increase buffer size */ 255 | if (p && f) p->realloc_func = f; 256 | } 257 | 258 | void 259 | csv_set_free_func(struct csv_parser *p, void (*f)(void *)) 260 | { 261 | /* Set the free function used to free the buffer */ 262 | if (p && f) p->free_func = f; 263 | } 264 | 265 | void 266 | csv_set_blk_size(struct csv_parser *p, size_t size) 267 | { 268 | /* Set the block size used to increment buffer size */ 269 | if (p) p->blk_size = size; 270 | } 271 | 272 | size_t 273 | csv_get_buffer_size(const struct csv_parser *p) 274 | { 275 | /* Get the size of the entry buffer */ 276 | if (p) 277 | return p->entry_size; 278 | return 0; 279 | } 280 | 281 | static int 282 | csv_increase_buffer(struct csv_parser *p) 283 | { 284 | if (p == NULL) return 0; 285 | if (p->realloc_func == NULL) return 0; 286 | 287 | /* Increase the size of the entry buffer. Attempt to increase size by 288 | * p->blk_size, if this is larger than SIZE_MAX try to increase current 289 | * buffer size to SIZE_MAX. If allocation fails, try to allocate halve 290 | * the size and try again until successful or increment size is zero. 291 | */ 292 | 293 | size_t to_add = p->blk_size; 294 | void *vp; 295 | 296 | if ( p->entry_size >= SIZE_MAX - to_add ) 297 | to_add = SIZE_MAX - p->entry_size; 298 | 299 | if (!to_add) { 300 | p->status = CSV_ETOOBIG; 301 | return -1; 302 | } 303 | 304 | while ((vp = p->realloc_func(p->entry_buf, p->entry_size + to_add)) == NULL) { 305 | to_add /= 2; 306 | if (!to_add) { 307 | p->status = CSV_ENOMEM; 308 | return -1; 309 | } 310 | } 311 | 312 | /* Update entry buffer pointer and entry_size if successful */ 313 | p->entry_buf = vp; 314 | p->entry_size += to_add; 315 | return 0; 316 | } 317 | 318 | size_t 319 | csv_parse(struct csv_parser *p, const void *s, size_t len, void (*cb1)(void *, size_t, void *), void (*cb2)(int c, void *), void *data) 320 | { 321 | assert(p && "received null csv_parser"); 322 | 323 | if (s == NULL) return 0; 324 | 325 | unsigned const char *us = s; /* Access input data as array of unsigned char */ 326 | unsigned char c; /* The character we are currently processing */ 327 | size_t pos = 0; /* The number of characters we have processed in this call */ 328 | 329 | /* Store key fields into local variables for performance */ 330 | unsigned char delim = p->delim_char; 331 | unsigned char quote = p->quote_char; 332 | int (*is_space)(unsigned char) = p->is_space; 333 | int (*is_term)(unsigned char) = p->is_term; 334 | int quoted = p->quoted; 335 | int pstate = p->pstate; 336 | size_t spaces = p->spaces; 337 | size_t entry_pos = p->entry_pos; 338 | 339 | 340 | if (!p->entry_buf && pos < len) { 341 | /* Buffer hasn't been allocated yet and len > 0 */ 342 | if (csv_increase_buffer(p) != 0) { 343 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos; 344 | return pos; 345 | } 346 | } 347 | 348 | while (pos < len) { 349 | /* Check memory usage, increase buffer if necessary */ 350 | if (entry_pos == ((p->options & CSV_APPEND_NULL) ? p->entry_size - 1 : p->entry_size) ) { 351 | if (csv_increase_buffer(p) != 0) { 352 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos; 353 | return pos; 354 | } 355 | } 356 | 357 | c = us[pos++]; 358 | 359 | switch (pstate) { 360 | case ROW_NOT_BEGUN: 361 | case FIELD_NOT_BEGUN: 362 | if ((is_space ? is_space(c) : c == CSV_SPACE || c == CSV_TAB) && c!=delim) { /* Space or Tab */ 363 | continue; 364 | } else if (is_term ? is_term(c) : c == CSV_CR || c == CSV_LF) { /* Carriage Return or Line Feed */ 365 | if (pstate == FIELD_NOT_BEGUN) { 366 | SUBMIT_FIELD(p); 367 | SUBMIT_ROW(p, c); 368 | } else { /* ROW_NOT_BEGUN */ 369 | /* Don't submit empty rows by default */ 370 | if (p->options & CSV_REPALL_NL) { 371 | SUBMIT_ROW(p, c); 372 | } 373 | } 374 | continue; 375 | } else if (c == delim) { /* Comma */ 376 | SUBMIT_FIELD(p); 377 | break; 378 | } else if (c == quote) { /* Quote */ 379 | pstate = FIELD_BEGUN; 380 | quoted = 1; 381 | } else { /* Anything else */ 382 | pstate = FIELD_BEGUN; 383 | quoted = 0; 384 | SUBMIT_CHAR(p, c); 385 | } 386 | break; 387 | case FIELD_BEGUN: 388 | if (c == quote) { /* Quote */ 389 | if (quoted) { 390 | SUBMIT_CHAR(p, c); 391 | pstate = FIELD_MIGHT_HAVE_ENDED; 392 | } else { 393 | /* STRICT ERROR - double quote inside non-quoted field */ 394 | if (p->options & CSV_STRICT) { 395 | p->status = CSV_EPARSE; 396 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos; 397 | return pos-1; 398 | } 399 | SUBMIT_CHAR(p, c); 400 | spaces = 0; 401 | } 402 | } else if (c == delim) { /* Comma */ 403 | if (quoted) { 404 | SUBMIT_CHAR(p, c); 405 | } else { 406 | SUBMIT_FIELD(p); 407 | } 408 | } else if (is_term ? is_term(c) : c == CSV_CR || c == CSV_LF) { /* Carriage Return or Line Feed */ 409 | if (!quoted) { 410 | SUBMIT_FIELD(p); 411 | SUBMIT_ROW(p, c); 412 | } else { 413 | SUBMIT_CHAR(p, c); 414 | } 415 | } else if (!quoted && (is_space? is_space(c) : c == CSV_SPACE || c == CSV_TAB)) { /* Tab or space for non-quoted field */ 416 | SUBMIT_CHAR(p, c); 417 | spaces++; 418 | } else { /* Anything else */ 419 | SUBMIT_CHAR(p, c); 420 | spaces = 0; 421 | } 422 | break; 423 | case FIELD_MIGHT_HAVE_ENDED: 424 | /* This only happens when a quote character is encountered in a quoted field */ 425 | if (c == delim) { /* Comma */ 426 | entry_pos -= spaces + 1; /* get rid of spaces and original quote */ 427 | SUBMIT_FIELD(p); 428 | } else if (is_term ? is_term(c) : c == CSV_CR || c == CSV_LF) { /* Carriage Return or Line Feed */ 429 | entry_pos -= spaces + 1; /* get rid of spaces and original quote */ 430 | SUBMIT_FIELD(p); 431 | SUBMIT_ROW(p, c); 432 | } else if (is_space ? is_space(c) : c == CSV_SPACE || c == CSV_TAB) { /* Space or Tab */ 433 | SUBMIT_CHAR(p, c); 434 | spaces++; 435 | } else if (c == quote) { /* Quote */ 436 | if (spaces) { 437 | /* STRICT ERROR - unescaped double quote */ 438 | if (p->options & CSV_STRICT) { 439 | p->status = CSV_EPARSE; 440 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos; 441 | return pos-1; 442 | } 443 | spaces = 0; 444 | SUBMIT_CHAR(p, c); 445 | } else { 446 | /* Two quotes in a row */ 447 | pstate = FIELD_BEGUN; 448 | } 449 | } else { /* Anything else */ 450 | /* STRICT ERROR - unescaped double quote */ 451 | if (p->options & CSV_STRICT) { 452 | p->status = CSV_EPARSE; 453 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos; 454 | return pos-1; 455 | } 456 | pstate = FIELD_BEGUN; 457 | spaces = 0; 458 | SUBMIT_CHAR(p, c); 459 | } 460 | break; 461 | default: 462 | break; 463 | } 464 | } 465 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos; 466 | return pos; 467 | } 468 | 469 | size_t 470 | csv_write (void *dest, size_t dest_size, const void *src, size_t src_size) 471 | { 472 | return csv_write2(dest, dest_size, src, src_size, CSV_QUOTE); 473 | } 474 | 475 | int 476 | csv_fwrite (FILE *fp, const void *src, size_t src_size) 477 | { 478 | return csv_fwrite2(fp, src, src_size, CSV_QUOTE); 479 | } 480 | 481 | size_t 482 | csv_write2 (void *dest, size_t dest_size, const void *src, size_t src_size, unsigned char quote) 483 | { 484 | unsigned char *cdest = dest; 485 | const unsigned char *csrc = src; 486 | size_t chars = 0; 487 | 488 | if (src == NULL) 489 | return 0; 490 | 491 | if (dest == NULL) 492 | dest_size = 0; 493 | 494 | if (dest_size > 0) 495 | *cdest++ = quote; 496 | chars++; 497 | 498 | while (src_size) { 499 | if (*csrc == quote) { 500 | if (dest_size > chars) 501 | *cdest++ = quote; 502 | if (chars < SIZE_MAX) chars++; 503 | } 504 | if (dest_size > chars) 505 | *cdest++ = *csrc; 506 | if (chars < SIZE_MAX) chars++; 507 | src_size--; 508 | csrc++; 509 | } 510 | 511 | if (dest_size > chars) 512 | *cdest = quote; 513 | if (chars < SIZE_MAX) chars++; 514 | 515 | return chars; 516 | } 517 | 518 | int 519 | csv_fwrite2 (FILE *fp, const void *src, size_t src_size, unsigned char quote) 520 | { 521 | const unsigned char *csrc = src; 522 | 523 | if (fp == NULL || src == NULL) 524 | return 0; 525 | 526 | if (fputc(quote, fp) == EOF) 527 | return EOF; 528 | 529 | while (src_size) { 530 | if (*csrc == quote) { 531 | if (fputc(quote, fp) == EOF) 532 | return EOF; 533 | } 534 | if (fputc(*csrc, fp) == EOF) 535 | return EOF; 536 | src_size--; 537 | csrc++; 538 | } 539 | 540 | if (fputc(quote, fp) == EOF) { 541 | return EOF; 542 | } 543 | 544 | return 0; 545 | } 546 | -------------------------------------------------------------------------------- /m4/ltoptions.m4: -------------------------------------------------------------------------------- 1 | # Helper functions for option handling. -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, 4 | # Inc. 5 | # Written by Gary V. Vaughan, 2004 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # serial 7 ltoptions.m4 12 | 13 | # This is to help aclocal find these macros, as it can't see m4_define. 14 | AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) 15 | 16 | 17 | # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) 18 | # ------------------------------------------ 19 | m4_define([_LT_MANGLE_OPTION], 20 | [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) 21 | 22 | 23 | # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) 24 | # --------------------------------------- 25 | # Set option OPTION-NAME for macro MACRO-NAME, and if there is a 26 | # matching handler defined, dispatch to it. Other OPTION-NAMEs are 27 | # saved as a flag. 28 | m4_define([_LT_SET_OPTION], 29 | [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl 30 | m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), 31 | _LT_MANGLE_DEFUN([$1], [$2]), 32 | [m4_warning([Unknown $1 option `$2'])])[]dnl 33 | ]) 34 | 35 | 36 | # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) 37 | # ------------------------------------------------------------ 38 | # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. 39 | m4_define([_LT_IF_OPTION], 40 | [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) 41 | 42 | 43 | # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) 44 | # ------------------------------------------------------- 45 | # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME 46 | # are set. 47 | m4_define([_LT_UNLESS_OPTIONS], 48 | [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 49 | [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), 50 | [m4_define([$0_found])])])[]dnl 51 | m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 52 | ])[]dnl 53 | ]) 54 | 55 | 56 | # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) 57 | # ---------------------------------------- 58 | # OPTION-LIST is a space-separated list of Libtool options associated 59 | # with MACRO-NAME. If any OPTION has a matching handler declared with 60 | # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about 61 | # the unknown option and exit. 62 | m4_defun([_LT_SET_OPTIONS], 63 | [# Set options 64 | m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 65 | [_LT_SET_OPTION([$1], _LT_Option)]) 66 | 67 | m4_if([$1],[LT_INIT],[ 68 | dnl 69 | dnl Simply set some default values (i.e off) if boolean options were not 70 | dnl specified: 71 | _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no 72 | ]) 73 | _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no 74 | ]) 75 | dnl 76 | dnl If no reference was made to various pairs of opposing options, then 77 | dnl we run the default mode handler for the pair. For example, if neither 78 | dnl `shared' nor `disable-shared' was passed, we enable building of shared 79 | dnl archives by default: 80 | _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) 81 | _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) 82 | _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) 83 | _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], 84 | [_LT_ENABLE_FAST_INSTALL]) 85 | ]) 86 | ])# _LT_SET_OPTIONS 87 | 88 | 89 | ## --------------------------------- ## 90 | ## Macros to handle LT_INIT options. ## 91 | ## --------------------------------- ## 92 | 93 | # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) 94 | # ----------------------------------------- 95 | m4_define([_LT_MANGLE_DEFUN], 96 | [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) 97 | 98 | 99 | # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) 100 | # ----------------------------------------------- 101 | m4_define([LT_OPTION_DEFINE], 102 | [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl 103 | ])# LT_OPTION_DEFINE 104 | 105 | 106 | # dlopen 107 | # ------ 108 | LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes 109 | ]) 110 | 111 | AU_DEFUN([AC_LIBTOOL_DLOPEN], 112 | [_LT_SET_OPTION([LT_INIT], [dlopen]) 113 | AC_DIAGNOSE([obsolete], 114 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 115 | put the `dlopen' option into LT_INIT's first parameter.]) 116 | ]) 117 | 118 | dnl aclocal-1.4 backwards compatibility: 119 | dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) 120 | 121 | 122 | # win32-dll 123 | # --------- 124 | # Declare package support for building win32 dll's. 125 | LT_OPTION_DEFINE([LT_INIT], [win32-dll], 126 | [enable_win32_dll=yes 127 | 128 | case $host in 129 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) 130 | AC_CHECK_TOOL(AS, as, false) 131 | AC_CHECK_TOOL(DLLTOOL, dlltool, false) 132 | AC_CHECK_TOOL(OBJDUMP, objdump, false) 133 | ;; 134 | esac 135 | 136 | test -z "$AS" && AS=as 137 | _LT_DECL([], [AS], [1], [Assembler program])dnl 138 | 139 | test -z "$DLLTOOL" && DLLTOOL=dlltool 140 | _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl 141 | 142 | test -z "$OBJDUMP" && OBJDUMP=objdump 143 | _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl 144 | ])# win32-dll 145 | 146 | AU_DEFUN([AC_LIBTOOL_WIN32_DLL], 147 | [AC_REQUIRE([AC_CANONICAL_HOST])dnl 148 | _LT_SET_OPTION([LT_INIT], [win32-dll]) 149 | AC_DIAGNOSE([obsolete], 150 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 151 | put the `win32-dll' option into LT_INIT's first parameter.]) 152 | ]) 153 | 154 | dnl aclocal-1.4 backwards compatibility: 155 | dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) 156 | 157 | 158 | # _LT_ENABLE_SHARED([DEFAULT]) 159 | # ---------------------------- 160 | # implement the --enable-shared flag, and supports the `shared' and 161 | # `disable-shared' LT_INIT options. 162 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 163 | m4_define([_LT_ENABLE_SHARED], 164 | [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl 165 | AC_ARG_ENABLE([shared], 166 | [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], 167 | [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], 168 | [p=${PACKAGE-default} 169 | case $enableval in 170 | yes) enable_shared=yes ;; 171 | no) enable_shared=no ;; 172 | *) 173 | enable_shared=no 174 | # Look at the argument we got. We use all the common list separators. 175 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 176 | for pkg in $enableval; do 177 | IFS="$lt_save_ifs" 178 | if test "X$pkg" = "X$p"; then 179 | enable_shared=yes 180 | fi 181 | done 182 | IFS="$lt_save_ifs" 183 | ;; 184 | esac], 185 | [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) 186 | 187 | _LT_DECL([build_libtool_libs], [enable_shared], [0], 188 | [Whether or not to build shared libraries]) 189 | ])# _LT_ENABLE_SHARED 190 | 191 | LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) 192 | LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) 193 | 194 | # Old names: 195 | AC_DEFUN([AC_ENABLE_SHARED], 196 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) 197 | ]) 198 | 199 | AC_DEFUN([AC_DISABLE_SHARED], 200 | [_LT_SET_OPTION([LT_INIT], [disable-shared]) 201 | ]) 202 | 203 | AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) 204 | AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) 205 | 206 | dnl aclocal-1.4 backwards compatibility: 207 | dnl AC_DEFUN([AM_ENABLE_SHARED], []) 208 | dnl AC_DEFUN([AM_DISABLE_SHARED], []) 209 | 210 | 211 | 212 | # _LT_ENABLE_STATIC([DEFAULT]) 213 | # ---------------------------- 214 | # implement the --enable-static flag, and support the `static' and 215 | # `disable-static' LT_INIT options. 216 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 217 | m4_define([_LT_ENABLE_STATIC], 218 | [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl 219 | AC_ARG_ENABLE([static], 220 | [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], 221 | [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], 222 | [p=${PACKAGE-default} 223 | case $enableval in 224 | yes) enable_static=yes ;; 225 | no) enable_static=no ;; 226 | *) 227 | enable_static=no 228 | # Look at the argument we got. We use all the common list separators. 229 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 230 | for pkg in $enableval; do 231 | IFS="$lt_save_ifs" 232 | if test "X$pkg" = "X$p"; then 233 | enable_static=yes 234 | fi 235 | done 236 | IFS="$lt_save_ifs" 237 | ;; 238 | esac], 239 | [enable_static=]_LT_ENABLE_STATIC_DEFAULT) 240 | 241 | _LT_DECL([build_old_libs], [enable_static], [0], 242 | [Whether or not to build static libraries]) 243 | ])# _LT_ENABLE_STATIC 244 | 245 | LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) 246 | LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) 247 | 248 | # Old names: 249 | AC_DEFUN([AC_ENABLE_STATIC], 250 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) 251 | ]) 252 | 253 | AC_DEFUN([AC_DISABLE_STATIC], 254 | [_LT_SET_OPTION([LT_INIT], [disable-static]) 255 | ]) 256 | 257 | AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) 258 | AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) 259 | 260 | dnl aclocal-1.4 backwards compatibility: 261 | dnl AC_DEFUN([AM_ENABLE_STATIC], []) 262 | dnl AC_DEFUN([AM_DISABLE_STATIC], []) 263 | 264 | 265 | 266 | # _LT_ENABLE_FAST_INSTALL([DEFAULT]) 267 | # ---------------------------------- 268 | # implement the --enable-fast-install flag, and support the `fast-install' 269 | # and `disable-fast-install' LT_INIT options. 270 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 271 | m4_define([_LT_ENABLE_FAST_INSTALL], 272 | [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl 273 | AC_ARG_ENABLE([fast-install], 274 | [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], 275 | [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], 276 | [p=${PACKAGE-default} 277 | case $enableval in 278 | yes) enable_fast_install=yes ;; 279 | no) enable_fast_install=no ;; 280 | *) 281 | enable_fast_install=no 282 | # Look at the argument we got. We use all the common list separators. 283 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 284 | for pkg in $enableval; do 285 | IFS="$lt_save_ifs" 286 | if test "X$pkg" = "X$p"; then 287 | enable_fast_install=yes 288 | fi 289 | done 290 | IFS="$lt_save_ifs" 291 | ;; 292 | esac], 293 | [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) 294 | 295 | _LT_DECL([fast_install], [enable_fast_install], [0], 296 | [Whether or not to optimize for fast installation])dnl 297 | ])# _LT_ENABLE_FAST_INSTALL 298 | 299 | LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) 300 | LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) 301 | 302 | # Old names: 303 | AU_DEFUN([AC_ENABLE_FAST_INSTALL], 304 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) 305 | AC_DIAGNOSE([obsolete], 306 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 307 | the `fast-install' option into LT_INIT's first parameter.]) 308 | ]) 309 | 310 | AU_DEFUN([AC_DISABLE_FAST_INSTALL], 311 | [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) 312 | AC_DIAGNOSE([obsolete], 313 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 314 | the `disable-fast-install' option into LT_INIT's first parameter.]) 315 | ]) 316 | 317 | dnl aclocal-1.4 backwards compatibility: 318 | dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) 319 | dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) 320 | 321 | 322 | # _LT_WITH_PIC([MODE]) 323 | # -------------------- 324 | # implement the --with-pic flag, and support the `pic-only' and `no-pic' 325 | # LT_INIT options. 326 | # MODE is either `yes' or `no'. If omitted, it defaults to `both'. 327 | m4_define([_LT_WITH_PIC], 328 | [AC_ARG_WITH([pic], 329 | [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], 330 | [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], 331 | [lt_p=${PACKAGE-default} 332 | case $withval in 333 | yes|no) pic_mode=$withval ;; 334 | *) 335 | pic_mode=default 336 | # Look at the argument we got. We use all the common list separators. 337 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 338 | for lt_pkg in $withval; do 339 | IFS="$lt_save_ifs" 340 | if test "X$lt_pkg" = "X$lt_p"; then 341 | pic_mode=yes 342 | fi 343 | done 344 | IFS="$lt_save_ifs" 345 | ;; 346 | esac], 347 | [pic_mode=default]) 348 | 349 | test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) 350 | 351 | _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl 352 | ])# _LT_WITH_PIC 353 | 354 | LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) 355 | LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) 356 | 357 | # Old name: 358 | AU_DEFUN([AC_LIBTOOL_PICMODE], 359 | [_LT_SET_OPTION([LT_INIT], [pic-only]) 360 | AC_DIAGNOSE([obsolete], 361 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 362 | put the `pic-only' option into LT_INIT's first parameter.]) 363 | ]) 364 | 365 | dnl aclocal-1.4 backwards compatibility: 366 | dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) 367 | 368 | ## ----------------- ## 369 | ## LTDL_INIT Options ## 370 | ## ----------------- ## 371 | 372 | m4_define([_LTDL_MODE], []) 373 | LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], 374 | [m4_define([_LTDL_MODE], [nonrecursive])]) 375 | LT_OPTION_DEFINE([LTDL_INIT], [recursive], 376 | [m4_define([_LTDL_MODE], [recursive])]) 377 | LT_OPTION_DEFINE([LTDL_INIT], [subproject], 378 | [m4_define([_LTDL_MODE], [subproject])]) 379 | 380 | m4_define([_LTDL_TYPE], []) 381 | LT_OPTION_DEFINE([LTDL_INIT], [installable], 382 | [m4_define([_LTDL_TYPE], [installable])]) 383 | LT_OPTION_DEFINE([LTDL_INIT], [convenience], 384 | [m4_define([_LTDL_TYPE], [convenience])]) 385 | -------------------------------------------------------------------------------- /m4/ltsugar.m4: -------------------------------------------------------------------------------- 1 | # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. 4 | # Written by Gary V. Vaughan, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 6 ltsugar.m4 11 | 12 | # This is to help aclocal find these macros, as it can't see m4_define. 13 | AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) 14 | 15 | 16 | # lt_join(SEP, ARG1, [ARG2...]) 17 | # ----------------------------- 18 | # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their 19 | # associated separator. 20 | # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier 21 | # versions in m4sugar had bugs. 22 | m4_define([lt_join], 23 | [m4_if([$#], [1], [], 24 | [$#], [2], [[$2]], 25 | [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) 26 | m4_define([_lt_join], 27 | [m4_if([$#$2], [2], [], 28 | [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) 29 | 30 | 31 | # lt_car(LIST) 32 | # lt_cdr(LIST) 33 | # ------------ 34 | # Manipulate m4 lists. 35 | # These macros are necessary as long as will still need to support 36 | # Autoconf-2.59 which quotes differently. 37 | m4_define([lt_car], [[$1]]) 38 | m4_define([lt_cdr], 39 | [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], 40 | [$#], 1, [], 41 | [m4_dquote(m4_shift($@))])]) 42 | m4_define([lt_unquote], $1) 43 | 44 | 45 | # lt_append(MACRO-NAME, STRING, [SEPARATOR]) 46 | # ------------------------------------------ 47 | # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. 48 | # Note that neither SEPARATOR nor STRING are expanded; they are appended 49 | # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). 50 | # No SEPARATOR is output if MACRO-NAME was previously undefined (different 51 | # than defined and empty). 52 | # 53 | # This macro is needed until we can rely on Autoconf 2.62, since earlier 54 | # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. 55 | m4_define([lt_append], 56 | [m4_define([$1], 57 | m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) 58 | 59 | 60 | 61 | # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) 62 | # ---------------------------------------------------------- 63 | # Produce a SEP delimited list of all paired combinations of elements of 64 | # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list 65 | # has the form PREFIXmINFIXSUFFIXn. 66 | # Needed until we can rely on m4_combine added in Autoconf 2.62. 67 | m4_define([lt_combine], 68 | [m4_if(m4_eval([$# > 3]), [1], 69 | [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl 70 | [[m4_foreach([_Lt_prefix], [$2], 71 | [m4_foreach([_Lt_suffix], 72 | ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, 73 | [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) 74 | 75 | 76 | # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) 77 | # ----------------------------------------------------------------------- 78 | # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited 79 | # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. 80 | m4_define([lt_if_append_uniq], 81 | [m4_ifdef([$1], 82 | [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], 83 | [lt_append([$1], [$2], [$3])$4], 84 | [$5])], 85 | [lt_append([$1], [$2], [$3])$4])]) 86 | 87 | 88 | # lt_dict_add(DICT, KEY, VALUE) 89 | # ----------------------------- 90 | m4_define([lt_dict_add], 91 | [m4_define([$1($2)], [$3])]) 92 | 93 | 94 | # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) 95 | # -------------------------------------------- 96 | m4_define([lt_dict_add_subkey], 97 | [m4_define([$1($2:$3)], [$4])]) 98 | 99 | 100 | # lt_dict_fetch(DICT, KEY, [SUBKEY]) 101 | # ---------------------------------- 102 | m4_define([lt_dict_fetch], 103 | [m4_ifval([$3], 104 | m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), 105 | m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) 106 | 107 | 108 | # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) 109 | # ----------------------------------------------------------------- 110 | m4_define([lt_if_dict_fetch], 111 | [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], 112 | [$5], 113 | [$6])]) 114 | 115 | 116 | # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) 117 | # -------------------------------------------------------------- 118 | m4_define([lt_dict_filter], 119 | [m4_if([$5], [], [], 120 | [lt_join(m4_quote(m4_default([$4], [[, ]])), 121 | lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), 122 | [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl 123 | ]) 124 | -------------------------------------------------------------------------------- /m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # @configure_input@ 11 | 12 | # serial 3337 ltversion.m4 13 | # This file is part of GNU Libtool 14 | 15 | m4_define([LT_PACKAGE_VERSION], [2.4.2]) 16 | m4_define([LT_PACKAGE_REVISION], [1.3337]) 17 | 18 | AC_DEFUN([LTVERSION_VERSION], 19 | [macro_version='2.4.2' 20 | macro_revision='1.3337' 21 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 22 | _LT_DECL(, macro_revision, 0) 23 | ]) 24 | -------------------------------------------------------------------------------- /m4/lt~obsolete.m4: -------------------------------------------------------------------------------- 1 | # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004. 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 5 lt~obsolete.m4 11 | 12 | # These exist entirely to fool aclocal when bootstrapping libtool. 13 | # 14 | # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) 15 | # which have later been changed to m4_define as they aren't part of the 16 | # exported API, or moved to Autoconf or Automake where they belong. 17 | # 18 | # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN 19 | # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us 20 | # using a macro with the same name in our local m4/libtool.m4 it'll 21 | # pull the old libtool.m4 in (it doesn't see our shiny new m4_define 22 | # and doesn't know about Autoconf macros at all.) 23 | # 24 | # So we provide this file, which has a silly filename so it's always 25 | # included after everything else. This provides aclocal with the 26 | # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything 27 | # because those macros already exist, or will be overwritten later. 28 | # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 29 | # 30 | # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. 31 | # Yes, that means every name once taken will need to remain here until 32 | # we give up compatibility with versions before 1.7, at which point 33 | # we need to keep only those names which we still refer to. 34 | 35 | # This is to help aclocal find these macros, as it can't see m4_define. 36 | AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) 37 | 38 | m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) 39 | m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) 40 | m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) 41 | m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) 42 | m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) 43 | m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) 44 | m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) 45 | m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) 46 | m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) 47 | m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) 48 | m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) 49 | m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) 50 | m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) 51 | m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) 52 | m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) 53 | m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) 54 | m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) 55 | m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) 56 | m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) 57 | m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) 58 | m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) 59 | m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) 60 | m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) 61 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) 62 | m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) 63 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) 64 | m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) 65 | m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) 66 | m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) 67 | m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) 68 | m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) 69 | m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) 70 | m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) 71 | m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) 72 | m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) 73 | m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) 74 | m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) 75 | m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) 76 | m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) 77 | m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) 78 | m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) 79 | m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) 80 | m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) 81 | m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) 82 | m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) 83 | m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) 84 | m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) 85 | m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) 86 | m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) 87 | m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) 88 | m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) 89 | m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) 90 | m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) 91 | m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) 92 | m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) 93 | m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) 94 | m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) 95 | m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) 96 | m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) 97 | m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) 98 | m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) 99 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2013-10-28.13; # UTC 5 | 6 | # Copyright (C) 1996-2013 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=http://www.perl.org/ 105 | flex_URL=http://flex.sourceforge.net/ 106 | gnu_software_URL=http://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'write-file-hooks 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /test-driver: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # test-driver - basic testsuite driver script. 3 | 4 | scriptversion=2013-07-13.22; # UTC 5 | 6 | # Copyright (C) 2011-2013 Free Software Foundation, Inc. 7 | # 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2, or (at your option) 11 | # any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | # As a special exception to the GNU General Public License, if you 22 | # distribute this file as part of a program that contains a 23 | # configuration script generated by Autoconf, you may include it under 24 | # the same distribution terms that you use for the rest of that program. 25 | 26 | # This file is maintained in Automake, please report 27 | # bugs to or send patches to 28 | # . 29 | 30 | # Make unconditional expansion of undefined variables an error. This 31 | # helps a lot in preventing typo-related bugs. 32 | set -u 33 | 34 | usage_error () 35 | { 36 | echo "$0: $*" >&2 37 | print_usage >&2 38 | exit 2 39 | } 40 | 41 | print_usage () 42 | { 43 | cat <$log_file 2>&1 108 | estatus=$? 109 | if test $enable_hard_errors = no && test $estatus -eq 99; then 110 | estatus=1 111 | fi 112 | 113 | case $estatus:$expect_failure in 114 | 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 115 | 0:*) col=$grn res=PASS recheck=no gcopy=no;; 116 | 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 117 | 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; 118 | *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; 119 | *:*) col=$red res=FAIL recheck=yes gcopy=yes;; 120 | esac 121 | 122 | # Report outcome to console. 123 | echo "${col}${res}${std}: $test_name" 124 | 125 | # Register the test result, and other relevant metadata. 126 | echo ":test-result: $res" > $trs_file 127 | echo ":global-test-result: $res" >> $trs_file 128 | echo ":recheck: $recheck" >> $trs_file 129 | echo ":copy-in-global-log: $gcopy" >> $trs_file 130 | 131 | # Local Variables: 132 | # mode: shell-script 133 | # sh-indentation: 2 134 | # eval: (add-hook 'write-file-hooks 'time-stamp) 135 | # time-stamp-start: "scriptversion=" 136 | # time-stamp-format: "%:y-%02m-%02d.%02H" 137 | # time-stamp-time-zone: "UTC" 138 | # time-stamp-end: "; # UTC" 139 | # End: 140 | -------------------------------------------------------------------------------- /test_csv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "./csv.h" 6 | 7 | #define CSV_END 0 8 | #define CSV_COL 1 9 | #define CSV_ROW 2 10 | #define CSV_ERR 3 11 | 12 | #define DO_TEST(name, options) test_parser("test" #name, options, test ## name ## _data, \ 13 | sizeof(test ## name ## _data) - 1, test ## name ## _results, \ 14 | CSV_COMMA, CSV_QUOTE, NULL, NULL) 15 | 16 | #define DO_TEST_CUSTOM(name, options, d, q, s, t) test_parser("custom" #name, options, custom ## name ## _data, \ 17 | sizeof(custom ## name ## _data) - 1, custom ## name ## _results, d, q, s, t) 18 | 19 | struct event { 20 | int event_type; 21 | int retval; 22 | size_t size; /* Number of bytes in this event or return value from csv_fini */ 23 | char *data; /* Data for this event */ 24 | }; 25 | 26 | struct event *event_ptr; 27 | int event_idx; 28 | size_t row, col; 29 | 30 | void 31 | fail_parser (char * test_name, char * message) 32 | { 33 | fprintf(stderr, "Parser test %s failed on event %d: %s\n", test_name, event_idx, message); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | void 38 | fail_writer (char * test_name, char * message) 39 | { 40 | fprintf(stderr, "Writer test %s failed: %s\n", test_name, message); 41 | exit(EXIT_FAILURE); 42 | } 43 | 44 | void 45 | cb1 (void *data, size_t len, void *t) 46 | { 47 | char * test_name = t; 48 | 49 | /* Make sure we were expecting a column */ 50 | if (event_ptr->event_type != CSV_COL) 51 | fail_parser(test_name, "didn't expect a column"); 52 | 53 | /* Check the actual size against the expected size */ 54 | if (event_ptr->size != len) 55 | fail_parser(test_name, "actual data length doesn't match expected data length"); 56 | 57 | /* Check the actual data against the expected data */ 58 | if ((event_ptr->data == NULL || data == NULL)) { 59 | if (event_ptr->data != data) 60 | fail_parser(test_name, "actual data doesn't match expected data"); 61 | } 62 | else if (memcmp(event_ptr->data, data, len) != 0) 63 | fail_parser(test_name, "actual data doesn't match expected data"); 64 | 65 | event_idx++; 66 | event_ptr++; 67 | col++; 68 | } 69 | 70 | void 71 | cb2 (int c, void *t) 72 | { 73 | char * test_name = t; 74 | 75 | /* Make sure we were expecting an the end of a row */ 76 | if (event_ptr->event_type != CSV_ROW) 77 | fail_parser(test_name, "didn't expect end of row"); 78 | 79 | /* Check that the row ended with the character we expected */ 80 | if (event_ptr->retval != c) 81 | fail_parser(test_name, "row ended with unexpected character"); 82 | 83 | event_idx++; 84 | event_ptr++; 85 | col = 1; 86 | row++; 87 | } 88 | 89 | void 90 | test_parser (char *test_name, unsigned char options, void *input, size_t len, struct event expected[], 91 | char delimiter, char quote, int (*space_func)(unsigned char), int (*term_func)(unsigned char)) 92 | { 93 | int result = 0; 94 | size_t retval; 95 | struct csv_parser p; 96 | size_t size; 97 | 98 | for (size = 1; size <= len; size++) { 99 | size_t bytes_processed = 0; 100 | csv_init(&p, options); 101 | csv_set_delim(&p, delimiter); 102 | csv_set_quote(&p, quote); 103 | csv_set_space_func(&p, space_func); 104 | csv_set_term_func(&p, term_func); 105 | 106 | row = col = 1; 107 | event_ptr = &expected[0]; 108 | event_idx = 1; 109 | 110 | do { 111 | size_t bytes = size < len - bytes_processed ? size : len - bytes_processed; 112 | retval = csv_parse(&p, input + bytes_processed, bytes, cb1, cb2, test_name); 113 | if (retval != bytes) { 114 | if (event_ptr->event_type != CSV_ERR) { 115 | fail_parser(test_name, "unexpected parse error occurred"); 116 | } else { 117 | csv_free(&p); 118 | return; 119 | } 120 | } 121 | bytes_processed += bytes; 122 | } while (bytes_processed < len); 123 | 124 | result = csv_fini(&p, cb1, cb2, test_name); 125 | 126 | if (result != 0) { 127 | if (event_ptr->event_type != CSV_ERR) { 128 | fail_parser(test_name, "unexpected parse error occurred"); 129 | } else { 130 | csv_free(&p); 131 | return; 132 | } 133 | } 134 | 135 | csv_free(&p); 136 | 137 | if (event_ptr->event_type != CSV_END) 138 | fail_parser(test_name, "unexpected end of input"); 139 | } 140 | } 141 | 142 | void 143 | test_writer (char * test_name, char *input, size_t input_len, char *expected, size_t expected_len) 144 | { 145 | size_t actual_len; 146 | char *temp = malloc(input_len*2 + 2); 147 | if (!temp) { 148 | fprintf(stderr, "Failed to allocate memory in test_writer!\n"); 149 | exit(EXIT_FAILURE); 150 | } 151 | 152 | actual_len = csv_write(temp, input_len*2 + 2, input, input_len); 153 | if (actual_len != expected_len) 154 | fail_writer(test_name, "actual length doesn't match expected length"); 155 | if (memcmp(temp, expected, actual_len) != 0) 156 | fail_writer(test_name, "actual data doesn't match expected data"); 157 | } 158 | 159 | void 160 | test_writer2 (char * test_name, char *input, size_t input_len, char *expected, size_t expected_len, char quote) 161 | { 162 | size_t actual_len; 163 | char *temp = malloc(input_len*2 + 2); 164 | if (!temp) { 165 | fprintf(stderr, "Failed to allocate memory in test_writer!\n"); 166 | exit(EXIT_FAILURE); 167 | } 168 | 169 | actual_len = csv_write2(temp, input_len*2 + 2, input, input_len, quote); 170 | if (actual_len != expected_len) 171 | fail_writer(test_name, "actual length doesn't match expected length"); 172 | if (memcmp(temp, expected, actual_len) != 0) 173 | fail_writer(test_name, "actual data doesn't match expected data"); 174 | } 175 | 176 | 177 | int main (void) { 178 | 179 | /* Parser Tests */ 180 | 181 | /* Parser tests presented here consist of two parts: 182 | 1. the raw data to be parsed as an array of char 183 | 2. the behavior expected from attempting to parse the data 184 | 185 | The latter is encapsulated into an array of struct event, each event 186 | described the type of event that was expected at that point and details 187 | of the event. There are four event types: 188 | 1. CSV_END - signifies the successful end of parsing, no events should 189 | follow in this test 190 | 2. CSV_COL - signifies that a column or CSV element is expected to be 191 | submitted to the appropriate callback function 192 | 3. CSV_ROW - specifies the end of a row has been reached 193 | 4. CSV_ERR - signifies that an error is expected at this point, no 194 | further events should follow in this test 195 | 196 | In addition to the event type, an event is also characterized by a size 197 | and a data member in the event structure. The meaning of these fields 198 | depends on the event type. 199 | 200 | The size member for CSV_COL is the size of the expected data column, 201 | for CSV_ROW is it the size of the terminating character which should 202 | always be 1. The size for CSV_END should always be zero, for CSV_ERR 203 | the size is not used. 204 | 205 | The data member represents the actual data after parsing for a CSV_COL, 206 | the terminating character for CSV_ROW (the first character of the provided 207 | char array is the one used), and is not used for CSV_END or CSV_ERR, it 208 | should be NULL in these cases. 209 | */ 210 | 211 | 212 | char test01_data[] = " 1,2 , 3 ,4,5\x0d\x0a"; 213 | char test02_data[] = ",,,,,\x0a"; 214 | char test03_data[] = "\",\",\",\",\"\""; 215 | char test04_data[] = "\"I call our world Flatland,\x0a" 216 | "not because we call it so,\x0a" 217 | "but to make its nature clearer\x0a" 218 | "to you, my happy readers,\x0a" 219 | "who are privileged to live in Space.\""; 220 | char test05_data[] = "\"\"\"a,b\"\"\",,\" \"\"\"\" \",\"\"\"\"\" \",\" \"\"\"\"\",\"\"\"\"\"\""; 221 | char test06_data[] = "\" a, b ,c \", a b c,"; 222 | char test07_data[] = "\" \"\" \" \" \"\" \""; 223 | char test07b_data[] = "\" \"\" \" \" \"\" \""; 224 | char test08_data[] = "\" abc\" " 225 | " " 226 | " " 227 | " " 228 | " " 229 | " " 230 | " " 231 | " " 232 | " \", \"123\""; 233 | char test09_data[] = ""; 234 | char test10_data[] = "a\x0a"; 235 | char test11_data[] = "1,2 ,3,4\x0a"; 236 | char test12_data[] = "\x0a\x0a\x0a\x0a"; 237 | char test12b_data[] = "\x0a\x0a\x0a\x0a"; 238 | char test13_data[] = "\"abc\""; 239 | char test14_data[] = "1, 2, 3,\x0a\x0d\x0a \"4\", \x0d,"; 240 | char test15_data[] = "1, 2, 3,\x0a\x0d\x0a \"4\", \x0d\"\""; 241 | char test16_data[] = "\"1\",\"2\",\" 3 "; 242 | char test16b_data[] = "\"1\",\"2\",\" 3 "; 243 | char test17_data[] = " a\0b\0c "; 244 | char test18_data[] = "12345678901234567890123456789012"; 245 | char test19_data[] = " , \"\" ,"; 246 | 247 | /* Custom tests */ 248 | char custom01_data[] = "'''a;b''';;' '''' ';''''' ';' ''''';''''''"; 249 | 250 | /* |1|2|3|4|5| */ 251 | struct event test01_results[] = 252 | { {CSV_COL, 0, 1, "1"}, 253 | {CSV_COL, 0, 1, "2"}, 254 | {CSV_COL, 0, 1, "3"}, 255 | {CSV_COL, 0, 1, "4"}, 256 | {CSV_COL, 0, 1, "5"}, 257 | {CSV_ROW, '\x0d', 1, NULL}, {CSV_END, 0, 0, NULL} }; 258 | 259 | /* ||||||| */ 260 | struct event test02_results[] = 261 | { {CSV_COL, 0, 0, ""}, 262 | {CSV_COL, 0, 0, ""}, 263 | {CSV_COL, 0, 0, ""}, 264 | {CSV_COL, 0, 0, ""}, 265 | {CSV_COL, 0, 0, ""}, 266 | {CSV_COL, 0, 0, ""}, 267 | {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} }; 268 | 269 | /* |,|,|| */ 270 | struct event test03_results[] = 271 | { {CSV_COL, 0, 1, ","}, 272 | {CSV_COL, 0, 1, ","}, 273 | {CSV_COL, 0, 0, ""}, 274 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 275 | 276 | struct event test04_results[] = 277 | { {CSV_COL, 0, 147, "I call our world Flatland,\x0a" 278 | "not because we call it so,\x0a" 279 | "but to make its nature clearer\x0a" 280 | "to you, my happy readers,\x0a" 281 | "who are privileged to live in Space."}, 282 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 283 | 284 | /* |"a,b"|| "" |"" | ""|""| */ 285 | struct event test05_results[] = 286 | { {CSV_COL, 0, 5, "\"a,b\""}, 287 | {CSV_COL, 0, 0, ""}, 288 | {CSV_COL, 0, 4, " \"\" "}, 289 | {CSV_COL, 0, 3, "\"\" "}, 290 | {CSV_COL, 0, 3, " \"\""}, 291 | {CSV_COL, 0, 2, "\"\""}, 292 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 293 | 294 | /* | a, b ,c |a b c|| */ 295 | struct event test06_results[] = 296 | { {CSV_COL, 0, 9, " a, b ,c "}, 297 | {CSV_COL, 0, 6, "a b c"}, 298 | {CSV_COL, 0, 0, ""}, 299 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 300 | 301 | /* | " " " " | */ 302 | struct event test07_results[] = 303 | { {CSV_COL, 0, 9, " \" \" \" \" "}, 304 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 305 | 306 | /* Will cause error with CSV_STRICT set */ 307 | struct event test07b_results[] = 308 | { {CSV_ERR, 0, 0, NULL} }; 309 | 310 | struct event test08_results[] = 311 | { {CSV_COL, 0, 463, " abc\" " 312 | " " 313 | " " 314 | " " 315 | " " 316 | " " 317 | " " 318 | " " 319 | " "}, 320 | {CSV_COL, 0, 3, "123"}, 321 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 322 | 323 | /* empty */ 324 | struct event test09_results[] = 325 | { {CSV_END, 0, 0, NULL} }; 326 | 327 | /* |a| */ 328 | struct event test10_results[] = 329 | { {CSV_COL, 0, 1, "a"}, 330 | {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} }; 331 | 332 | /* |1|2|3|4| */ 333 | struct event test11_results[] = 334 | { {CSV_COL, 0, 1, "1"}, 335 | {CSV_COL, 0, 1, "2"}, 336 | {CSV_COL, 0, 1, "3"}, 337 | {CSV_COL, 0, 1, "4"}, 338 | {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} }; 339 | 340 | /* empty */ 341 | struct event test12_results[] = 342 | { {CSV_END, 0, 0, NULL} }; 343 | 344 | /* Test CSV_REPALL_NL */ 345 | struct event test12b_results[] = 346 | { {CSV_ROW, '\x0a', 1, NULL}, 347 | {CSV_ROW, '\x0a', 1, NULL}, 348 | {CSV_ROW, '\x0a', 1, NULL}, 349 | {CSV_ROW, '\x0a', 1, NULL}, {CSV_END, 0, 0, NULL} }; 350 | 351 | /* |abc| */ 352 | struct event test13_results[] = 353 | { {CSV_COL, 0, 3, "abc"}, 354 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 355 | 356 | /* |1|2|3|| 357 | |4|| 358 | ||| */ 359 | struct event test14_results[] = 360 | { {CSV_COL, 0, 1, "1"}, 361 | {CSV_COL, 0, 1, "2"}, 362 | {CSV_COL, 0, 1, "3"}, 363 | {CSV_COL, 0, 0, ""}, 364 | {CSV_ROW, '\x0a', 1, NULL}, 365 | {CSV_COL, 0, 1, "4"}, 366 | {CSV_COL, 0, 0, ""}, 367 | {CSV_ROW, '\x0d', 1, NULL}, 368 | {CSV_COL, 0, 0, ""}, 369 | {CSV_COL, 0, 0, ""}, 370 | {CSV_ROW, -1, 0, NULL}, {CSV_END, 0, 0, NULL} }; 371 | 372 | /* |1|2|3|| 373 | |4|| 374 | || */ 375 | struct event test15_results[] = 376 | { {CSV_COL, 0, 1, "1"}, 377 | {CSV_COL, 0, 1, "2"}, 378 | {CSV_COL, 0, 1, "3"}, 379 | {CSV_COL, 0, 0, ""}, 380 | {CSV_ROW, '\x0a', 1, NULL}, 381 | {CSV_COL, 0, 1, "4"}, 382 | {CSV_COL, 0, 0, ""}, 383 | {CSV_ROW, '\x0d', 1, NULL}, 384 | {CSV_COL, 0, 0, ""}, 385 | {CSV_ROW, -1, 0, NULL}, {CSV_END, 0, 0, NULL} }; 386 | 387 | 388 | /* |1|2| 3 | */ 389 | struct event test16_results[] = 390 | { {CSV_COL, 0, 1, "1"}, 391 | {CSV_COL, 0, 1, "2"}, 392 | {CSV_COL, 0, 3, " 3 "}, 393 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 394 | 395 | /* Will cause an error with CSV_STRICT_FINI set */ 396 | struct event test16b_results[] = 397 | { {CSV_COL, 0, 1, "1"}, 398 | {CSV_COL, 0, 1, "2"}, 399 | {CSV_ERR, 0, 0, NULL} }; 400 | 401 | /* |a\0b\0c| */ 402 | struct event test17_results[] = 403 | { {CSV_COL, 0, 5, "a\0b\0c"}, 404 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 405 | 406 | /* Test CSV_EMPTY_IS_NULL */ 407 | struct event test19_results[] = 408 | { {CSV_COL, 0, 0, NULL}, 409 | {CSV_COL, 0, 0, ""}, 410 | {CSV_COL, 0, 0, NULL}, 411 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 412 | 413 | /* |'a;b'|| '' |'' | ''|''| */ 414 | struct event custom01_results[] = 415 | { {CSV_COL, 0, 5, "'a;b'"}, 416 | {CSV_COL, 0, 0, ""}, 417 | {CSV_COL, 0, 4, " '' "}, 418 | {CSV_COL, 0, 3, "'' "}, 419 | {CSV_COL, 0, 3, " ''"}, 420 | {CSV_COL, 0, 2, "''"}, 421 | {CSV_ROW, -1, 1, NULL}, {CSV_END, 0, 0, NULL} }; 422 | 423 | DO_TEST(01, 0); 424 | DO_TEST(01, CSV_STRICT); 425 | DO_TEST(01, CSV_STRICT | CSV_EMPTY_IS_NULL); 426 | DO_TEST(02, 0); 427 | DO_TEST(02, CSV_STRICT); 428 | DO_TEST(03, 0); 429 | DO_TEST(03, CSV_STRICT); 430 | DO_TEST(04, 0); 431 | DO_TEST(04, CSV_STRICT); 432 | DO_TEST(05, 0); 433 | DO_TEST(05, CSV_STRICT); 434 | DO_TEST(05, CSV_STRICT | CSV_STRICT_FINI); 435 | DO_TEST(06, 0); 436 | DO_TEST(06, CSV_STRICT); 437 | DO_TEST(07, 0); 438 | DO_TEST(07b, CSV_STRICT); 439 | DO_TEST(08, 0); 440 | DO_TEST(09, 0); 441 | DO_TEST(09, CSV_EMPTY_IS_NULL); 442 | DO_TEST(10, 0); 443 | DO_TEST(11, 0); 444 | DO_TEST(11, CSV_EMPTY_IS_NULL); 445 | DO_TEST(12, 0); 446 | DO_TEST(12, CSV_EMPTY_IS_NULL); 447 | DO_TEST(12b, CSV_REPALL_NL); 448 | DO_TEST(12b, CSV_REPALL_NL | CSV_EMPTY_IS_NULL); 449 | DO_TEST(13, 0); 450 | DO_TEST(14, 0); 451 | DO_TEST(14, CSV_STRICT); 452 | DO_TEST(15, 0); 453 | DO_TEST(15, CSV_STRICT); 454 | DO_TEST(16, 0); 455 | DO_TEST(16, CSV_STRICT); 456 | DO_TEST(16b, CSV_STRICT | CSV_STRICT_FINI); 457 | DO_TEST(16, 0); 458 | DO_TEST(16, CSV_STRICT); 459 | DO_TEST(17, 0); 460 | DO_TEST(17, CSV_STRICT); 461 | DO_TEST(17, CSV_STRICT | CSV_EMPTY_IS_NULL); 462 | DO_TEST(19, CSV_EMPTY_IS_NULL); 463 | 464 | DO_TEST_CUSTOM(01, 0, ';', '\'', NULL, NULL); 465 | 466 | /* Writer Tests */ 467 | 468 | /* The writer tests are simpler, the test_writer function is used to 469 | test the csv_write function and takes five arguments: the name of 470 | the test, the data to convert, the length of that data, the expected 471 | resulting CSV data, and the expected length of the result. 472 | */ 473 | 474 | test_writer("1", "abc", 3, "\"abc\"", 5); 475 | test_writer("2", "\"\"\"\"\"\"\"\"", 8, "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"", 18); 476 | 477 | test_writer2("1", "abc", 3, "'abc'", 5, '\''); 478 | test_writer2("2", "''''''''", 8, "''''''''''''''''''", 18, '\''); 479 | 480 | puts("All tests passed"); 481 | return 0; 482 | } 483 | -------------------------------------------------------------------------------- /tests/test_01.csv: -------------------------------------------------------------------------------- 1 | 1,2 , 3 ,4,5 2 | -------------------------------------------------------------------------------- /tests/test_02.csv: -------------------------------------------------------------------------------- 1 | ,,,,, 2 | -------------------------------------------------------------------------------- /tests/test_03.csv: -------------------------------------------------------------------------------- 1 | ",",",","" 2 | -------------------------------------------------------------------------------- /tests/test_04.csv: -------------------------------------------------------------------------------- 1 | "I call our world Flatland, 2 | not because we call it so, 3 | but to make its nature clearer 4 | to you, my happy readers, 5 | who are privileged to live in Space." 6 | -------------------------------------------------------------------------------- /tests/test_05.csv: -------------------------------------------------------------------------------- 1 | """a,b""",," """" ",""""" "," """"","""""" 2 | -------------------------------------------------------------------------------- /tests/test_06.csv: -------------------------------------------------------------------------------- 1 | " a, b ,c ", a b c, 2 | -------------------------------------------------------------------------------- /tests/test_07.csv: -------------------------------------------------------------------------------- 1 | " "" " " "" " 2 | -------------------------------------------------------------------------------- /tests/test_08.csv: -------------------------------------------------------------------------------- 1 | " abc" ", "123" 2 | -------------------------------------------------------------------------------- /tests/test_10.csv: -------------------------------------------------------------------------------- 1 | a 2 | -------------------------------------------------------------------------------- /tests/test_11.csv: -------------------------------------------------------------------------------- 1 | 1,2 ,3,4 2 | -------------------------------------------------------------------------------- /tests/test_12.csv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tests/test_13.csv: -------------------------------------------------------------------------------- 1 | "abc" --------------------------------------------------------------------------------