Check-in [763711687e]

Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1 Hash:763711687ebdb47db16afb257bfd6d3c2c19be53
Date: 2008-12-26 12:19:52
User: stephan
Comment:egg
Tags And Properties
Changes
hide diffs unified diffs patch

Added Doxyfile.at

Old () New (3361fe1bc8534a7e)
> 1 # Doxyfile 1.5.5
> 2
> 3 # This file describes the settings to be used by the documentation system
> 4 # doxygen (www.doxygen.org) for a project
> 5 #
> 6 # All text after a hash (#) is considered a comment and will be ignored
> 7 # The format is:
> 8 # TAG = value [value, ...]
> 9 # For lists items can also be appended using:
> 10 # TAG += value [value, ...]
> 11 # Values that contain spaces should be placed between quotes (" ")
> 12
> 13 #---------------------------------------------------------------------------
> 14 # Project related configuration options
> 15 #---------------------------------------------------------------------------
> 16
> 17 # This tag specifies the encoding used for all characters in the config file
> 18 # that follow. The default is UTF-8 which is also the encoding used for all
> 19 # text before the first occurrence of this tag. Doxygen uses libiconv (or the
> 20 # iconv built into libc) for the transcoding. See
> 21 # http://www.gnu.org/software/libiconv for the list of possible encodings.
> 22
> 23 DOXYFILE_ENCODING = UTF-8
> 24
> 25 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded
> 26 # by quotes) that should identify the project.
> 27
> 28 PROJECT_NAME = WanderingHorse.netClibs # @PACKAGE_NAME@
> 29
> 30 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
> 31 # This could be handy for archiving the generated documentation or
> 32 # if some version control system is used.
> 33
> 34 PROJECT_NUMBER = # @PACKAGE_VERSION@
> 35
> 36 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
> 37 # base path where the generated documentation will be put.
> 38 # If a relative path is entered, it will be relative to the location
> 39 # where doxygen was started. If left blank the current directory will be used.
> 40
> 41 OUTPUT_DIRECTORY =
> 42
> 43 # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
> 44 # 4096 sub-directories (in 2 levels) under the output directory of each output
> 45 # format and will distribute the generated files over these directories.
> 46 # Enabling this option can be useful when feeding doxygen a huge amount of
> 47 # source files, where putting all generated files in the same directory would
> 48 # otherwise cause performance problems for the file system.
> 49
> 50 CREATE_SUBDIRS = NO
> 51
> 52 # The OUTPUT_LANGUAGE tag is used to specify the language in which all
> 53 # documentation generated by doxygen is written. Doxygen will use this
> 54 # information to generate all constant output in the proper language.
> 55 # The default language is English, other supported languages are:
> 56 # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
> 57 # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
> 58 # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
> 59 # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
> 60 # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
> 61 # and Ukrainian.
> 62
> 63 OUTPUT_LANGUAGE = English
> 64
> 65 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
> 66 # include brief member descriptions after the members that are listed in
> 67 # the file and class documentation (similar to JavaDoc).
> 68 # Set to NO to disable this.
> 69
> 70 BRIEF_MEMBER_DESC = YES
> 71
> 72 # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
> 73 # the brief description of a member or function before the detailed description.
> 74 # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
> 75 # brief descriptions will be completely suppressed.
> 76
> 77 REPEAT_BRIEF = YES
> 78
> 79 # This tag implements a quasi-intelligent brief description abbreviator
> 80 # that is used to form the text in various listings. Each string
> 81 # in this list, if found as the leading text of the brief description, will be
> 82 # stripped from the text and the result after processing the whole list, is
> 83 # used as the annotated text. Otherwise, the brief description is used as-is.
> 84 # If left blank, the following values are used ("$name" is automatically
> 85 # replaced with the name of the entity): "The $name class" "The $name widget"
> 86 # "The $name file" "is" "provides" "specifies" "contains"
> 87 # "represents" "a" "an" "the"
> 88
> 89 ABBREVIATE_BRIEF =
> 90
> 91 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
> 92 # Doxygen will generate a detailed section even if there is only a brief
> 93 # description.
> 94
> 95 ALWAYS_DETAILED_SEC = NO
> 96
> 97 # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
> 98 # inherited members of a class in the documentation of that class as if those
> 99 # members were ordinary class members. Constructors, destructors and assignment
> 100 # operators of the base classes will not be shown.
> 101
> 102 INLINE_INHERITED_MEMB = NO
> 103
> 104 # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
> 105 # path before files name in the file list and in the header files. If set
> 106 # to NO the shortest path that makes the file name unique will be used.
> 107
> 108 FULL_PATH_NAMES = NO
> 109
> 110 # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
> 111 # can be used to strip a user-defined part of the path. Stripping is
> 112 # only done if one of the specified strings matches the left-hand part of
> 113 # the path. The tag can be used to show relative paths in the file list.
> 114 # If left blank the directory from which doxygen is run is used as the
> 115 # path to strip.
> 116
> 117 STRIP_FROM_PATH =
> 118
> 119 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
> 120 # the path mentioned in the documentation of a class, which tells
> 121 # the reader which header file to include in order to use a class.
> 122 # If left blank only the name of the header file containing the class
> 123 # definition is used. Otherwise one should specify the include paths that
> 124 # are normally passed to the compiler using the -I flag.
> 125
> 126 STRIP_FROM_INC_PATH =
> 127
> 128 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
> 129 # (but less readable) file names. This can be useful is your file systems
> 130 # doesn't support long names like on DOS, Mac, or CD-ROM.
> 131
> 132 SHORT_NAMES = NO
> 133
> 134 # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
> 135 # will interpret the first line (until the first dot) of a JavaDoc-style
> 136 # comment as the brief description. If set to NO, the JavaDoc
> 137 # comments will behave just like regular Qt-style comments
> 138 # (thus requiring an explicit @brief command for a brief description.)
> 139
> 140 JAVADOC_AUTOBRIEF = YES
> 141
> 142 # If the QT_AUTOBRIEF tag is set to YES then Doxygen will
> 143 # interpret the first line (until the first dot) of a Qt-style
> 144 # comment as the brief description. If set to NO, the comments
> 145 # will behave just like regular Qt-style comments (thus requiring
> 146 # an explicit \brief command for a brief description.)
> 147
> 148 QT_AUTOBRIEF = NO
> 149
> 150 # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
> 151 # treat a multi-line C++ special comment block (i.e. a block of //! or ///
> 152 # comments) as a brief description. This used to be the default behaviour.
> 153 # The new default is to treat a multi-line C++ comment block as a detailed
> 154 # description. Set this tag to YES if you prefer the old behaviour instead.
> 155
> 156 MULTILINE_CPP_IS_BRIEF = NO
> 157
> 158 # If the DETAILS_AT_TOP tag is set to YES then Doxygen
> 159 # will output the detailed description near the top, like JavaDoc.
> 160 # If set to NO, the detailed description appears after the member
> 161 # documentation.
> 162
> 163 DETAILS_AT_TOP = NO
> 164
> 165 # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
> 166 # member inherits the documentation from any documented member that it
> 167 # re-implements.
> 168
> 169 INHERIT_DOCS = NO
> 170
> 171 # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
> 172 # a new page for each member. If set to NO, the documentation of a member will
> 173 # be part of the file/class/namespace that contains it.
> 174
> 175 SEPARATE_MEMBER_PAGES = NO
> 176
> 177 # The TAB_SIZE tag can be used to set the number of spaces in a tab.
> 178 # Doxygen uses this value to replace tabs by spaces in code fragments.
> 179
> 180 TAB_SIZE = 4
> 181
> 182 # This tag can be used to specify a number of aliases that acts
> 183 # as commands in the documentation. An alias has the form "name=value".
> 184 # For example adding "sideeffect=\par Side Effects:\n" will allow you to
> 185 # put the command \sideeffect (or @sideeffect) in the documentation, which
> 186 # will result in a user-defined paragraph with heading "Side Effects:".
> 187 # You can put \n's in the value part of an alias to insert newlines.
> 188
> 189 ALIASES =
> 190
> 191 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
> 192 # sources only. Doxygen will then generate output that is more tailored for C.
> 193 # For instance, some of the names that are used will be different. The list
> 194 # of all members will be omitted, etc.
> 195
> 196 OPTIMIZE_OUTPUT_FOR_C = YES
> 197
> 198 # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
> 199 # sources only. Doxygen will then generate output that is more tailored for
> 200 # Java. For instance, namespaces will be presented as packages, qualified
> 201 # scopes will look different, etc.
> 202
> 203 OPTIMIZE_OUTPUT_JAVA = NO
> 204
> 205 # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
> 206 # sources only. Doxygen will then generate output that is more tailored for
> 207 # Fortran.
> 208
> 209 OPTIMIZE_FOR_FORTRAN = NO
> 210
> 211 # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
> 212 # sources. Doxygen will then generate output that is tailored for
> 213 # VHDL.
> 214
> 215 OPTIMIZE_OUTPUT_VHDL = NO
> 216
> 217 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
> 218 # to include (a tag file for) the STL sources as input, then you should
> 219 # set this tag to YES in order to let doxygen match functions declarations and
> 220 # definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
> 221 # func(std::string) {}). This also make the inheritance and collaboration
> 222 # diagrams that involve STL classes more complete and accurate.
> 223
> 224 BUILTIN_STL_SUPPORT = NO
> 225
> 226 # If you use Microsoft's C++/CLI language, you should set this option to YES to
> 227 # enable parsing support.
> 228
> 229 CPP_CLI_SUPPORT = NO
> 230
> 231 # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
> 232 # Doxygen will parse them like normal C++ but will assume all classes use public
> 233 # instead of private inheritance when no explicit protection keyword is present.
> 234
> 235 SIP_SUPPORT = NO
> 236
> 237 # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
> 238 # tag is set to YES, then doxygen will reuse the documentation of the first
> 239 # member in the group (if any) for the other members of the group. By default
> 240 # all members of a group must be documented explicitly.
> 241
> 242 DISTRIBUTE_GROUP_DOC = NO
> 243
> 244 # Set the SUBGROUPING tag to YES (the default) to allow class member groups of
> 245 # the same type (for instance a group of public functions) to be put as a
> 246 # subgroup of that type (e.g. under the Public Functions section). Set it to
> 247 # NO to prevent subgrouping. Alternatively, this can be done per class using
> 248 # the \nosubgrouping command.
> 249
> 250 SUBGROUPING = YES
> 251
> 252 # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
> 253 # is documented as struct, union, or enum with the name of the typedef. So
> 254 # typedef struct TypeS {} TypeT, will appear in the documentation as a struct
> 255 # with name TypeT. When disabled the typedef will appear as a member of a file,
> 256 # namespace, or class. And the struct will be named TypeS. This can typically
> 257 # be useful for C code in case the coding convention dictates that all compound
> 258 # types are typedef'ed and only the typedef is referenced, never the tag name.
> 259
> 260 TYPEDEF_HIDES_STRUCT = NO
> 261
> 262 #---------------------------------------------------------------------------
> 263 # Build related configuration options
> 264 #---------------------------------------------------------------------------
> 265
> 266 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
> 267 # documentation are documented, even if no documentation was available.
> 268 # Private class members and static file members will be hidden unless
> 269 # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
> 270
> 271 EXTRACT_ALL = YES
> 272
> 273 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class
> 274 # will be included in the documentation.
> 275
> 276 EXTRACT_PRIVATE = NO
> 277
> 278 # If the EXTRACT_STATIC tag is set to YES all static members of a file
> 279 # will be included in the documentation.
> 280
> 281 EXTRACT_STATIC = NO
> 282
> 283 # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
> 284 # defined locally in source files will be included in the documentation.
> 285 # If set to NO only classes defined in header files are included.
> 286
> 287 EXTRACT_LOCAL_CLASSES = NO
> 288
> 289 # This flag is only useful for Objective-C code. When set to YES local
> 290 # methods, which are defined in the implementation section but not in
> 291 # the interface are included in the documentation.
> 292 # If set to NO (the default) only methods in the interface are included.
> 293
> 294 EXTRACT_LOCAL_METHODS = NO
> 295
> 296 # If this flag is set to YES, the members of anonymous namespaces will be
> 297 # extracted and appear in the documentation as a namespace called
> 298 # 'anonymous_namespace{file}', where file will be replaced with the base
> 299 # name of the file that contains the anonymous namespace. By default
> 300 # anonymous namespace are hidden.
> 301
> 302 EXTRACT_ANON_NSPACES = NO
> 303
> 304 # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
> 305 # undocumented members of documented classes, files or namespaces.
> 306 # If set to NO (the default) these members will be included in the
> 307 # various overviews, but no documentation section is generated.
> 308 # This option has no effect if EXTRACT_ALL is enabled.
> 309
> 310 HIDE_UNDOC_MEMBERS = NO
> 311
> 312 # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
> 313 # undocumented classes that are normally visible in the class hierarchy.
> 314 # If set to NO (the default) these classes will be included in the various
> 315 # overviews. This option has no effect if EXTRACT_ALL is enabled.
> 316
> 317 HIDE_UNDOC_CLASSES = NO
> 318
> 319 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
> 320 # friend (class|struct|union) declarations.
> 321 # If set to NO (the default) these declarations will be included in the
> 322 # documentation.
> 323
> 324 HIDE_FRIEND_COMPOUNDS = NO
> 325
> 326 # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
> 327 # documentation blocks found inside the body of a function.
> 328 # If set to NO (the default) these blocks will be appended to the
> 329 # function's detailed documentation block.
> 330
> 331 HIDE_IN_BODY_DOCS = YES
> 332
> 333 # The INTERNAL_DOCS tag determines if documentation
> 334 # that is typed after a \internal command is included. If the tag is set
> 335 # to NO (the default) then the documentation will be excluded.
> 336 # Set it to YES to include the internal documentation.
> 337
> 338 INTERNAL_DOCS = NO
> 339
> 340 # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
> 341 # file names in lower-case letters. If set to YES upper-case letters are also
> 342 # allowed. This is useful if you have classes or files whose names only differ
> 343 # in case and if your file system supports case sensitive file names. Windows
> 344 # and Mac users are advised to set this option to NO.
> 345
> 346 CASE_SENSE_NAMES = YES
> 347
> 348 # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
> 349 # will show members with their full class and namespace scopes in the
> 350 # documentation. If set to YES the scope will be hidden.
> 351
> 352 HIDE_SCOPE_NAMES = NO
> 353
> 354 # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
> 355 # will put a list of the files that are included by a file in the documentation
> 356 # of that file.
> 357
> 358 SHOW_INCLUDE_FILES = YES
> 359
> 360 # If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
> 361 # is inserted in the documentation for inline members.
> 362
> 363 INLINE_INFO = YES
> 364
> 365 # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
> 366 # will sort the (detailed) documentation of file and class members
> 367 # alphabetically by member name. If set to NO the members will appear in
> 368 # declaration order.
> 369
> 370 SORT_MEMBER_DOCS = YES
> 371
> 372 # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
> 373 # brief documentation of file, namespace and class members alphabetically
> 374 # by member name. If set to NO (the default) the members will appear in
> 375 # declaration order.
> 376
> 377 SORT_BRIEF_DOCS = YES
> 378
> 379 # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
> 380 # hierarchy of group names into alphabetical order. If set to NO (the default)
> 381 # the group names will appear in their defined order.
> 382
> 383 SORT_GROUP_NAMES = NO
> 384
> 385 # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
> 386 # sorted by fully-qualified names, including namespaces. If set to
> 387 # NO (the default), the class list will be sorted only by class name,
> 388 # not including the namespace part.
> 389 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
> 390 # Note: This option applies only to the class list, not to the
> 391 # alphabetical list.
> 392
> 393 SORT_BY_SCOPE_NAME = NO
> 394
> 395 # The GENERATE_TODOLIST tag can be used to enable (YES) or
> 396 # disable (NO) the todo list. This list is created by putting \todo
> 397 # commands in the documentation.
> 398
> 399 GENERATE_TODOLIST = YES
> 400
> 401 # The GENERATE_TESTLIST tag can be used to enable (YES) or
> 402 # disable (NO) the test list. This list is created by putting \test
> 403 # commands in the documentation.
> 404
> 405 GENERATE_TESTLIST = YES
> 406
> 407 # The GENERATE_BUGLIST tag can be used to enable (YES) or
> 408 # disable (NO) the bug list. This list is created by putting \bug
> 409 # commands in the documentation.
> 410
> 411 GENERATE_BUGLIST = YES
> 412
> 413 # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
> 414 # disable (NO) the deprecated list. This list is created by putting
> 415 # \deprecated commands in the documentation.
> 416
> 417 GENERATE_DEPRECATEDLIST= YES
> 418
> 419 # The ENABLED_SECTIONS tag can be used to enable conditional
> 420 # documentation sections, marked by \if sectionname ... \endif.
> 421
> 422 ENABLED_SECTIONS =
> 423
> 424 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines
> 425 # the initial value of a variable or define consists of for it to appear in
> 426 # the documentation. If the initializer consists of more lines than specified
> 427 # here it will be hidden. Use a value of 0 to hide initializers completely.
> 428 # The appearance of the initializer of individual variables and defines in the
> 429 # documentation can be controlled using \showinitializer or \hideinitializer
> 430 # command in the documentation regardless of this setting.
> 431
> 432 MAX_INITIALIZER_LINES = 30
> 433
> 434 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated
> 435 # at the bottom of the documentation of classes and structs. If set to YES the
> 436 # list will mention the files that were used to generate the documentation.
> 437
> 438 SHOW_USED_FILES = YES
> 439
> 440 # If the sources in your project are distributed over multiple directories
> 441 # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
> 442 # in the documentation. The default is NO.
> 443
> 444 SHOW_DIRECTORIES = YES
> 445
> 446 # The FILE_VERSION_FILTER tag can be used to specify a program or script that
> 447 # doxygen should invoke to get the current version for each file (typically from
> 448 # the version control system). Doxygen will invoke the program by executing (via
> 449 # popen()) the command <command> <input-file>, where <command> is the value of
> 450 # the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
> 451 # provided by doxygen. Whatever the program writes to standard output
> 452 # is used as the file version. See the manual for examples.
> 453
> 454 FILE_VERSION_FILTER =
> 455
> 456 #---------------------------------------------------------------------------
> 457 # configuration options related to warning and progress messages
> 458 #---------------------------------------------------------------------------
> 459
> 460 # The QUIET tag can be used to turn on/off the messages that are generated
> 461 # by doxygen. Possible values are YES and NO. If left blank NO is used.
> 462
> 463 QUIET = YES
> 464
> 465 # The WARNINGS tag can be used to turn on/off the warning messages that are
> 466 # generated by doxygen. Possible values are YES and NO. If left blank
> 467 # NO is used.
> 468
> 469 WARNINGS = YES
> 470
> 471 # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
> 472 # for undocumented members. If EXTRACT_ALL is set to YES then this flag will
> 473 # automatically be disabled.
> 474
> 475 WARN_IF_UNDOCUMENTED = YES
> 476
> 477 # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
> 478 # potential errors in the documentation, such as not documenting some
> 479 # parameters in a documented function, or documenting parameters that
> 480 # don't exist or using markup commands wrongly.
> 481
> 482 WARN_IF_DOC_ERROR = YES
> 483
> 484 # This WARN_NO_PARAMDOC option can be abled to get warnings for
> 485 # functions that are documented, but have no documentation for their parameters
> 486 # or return value. If set to NO (the default) doxygen will only warn about
> 487 # wrong or incomplete parameter documentation, but not about the absence of
> 488 # documentation.
> 489
> 490 WARN_NO_PARAMDOC = NO
> 491
> 492 # The WARN_FORMAT tag determines the format of the warning messages that
> 493 # doxygen can produce. The string should contain the $file, $line, and $text
> 494 # tags, which will be replaced by the file and line number from which the
> 495 # warning originated and the warning text. Optionally the format may contain
> 496 # $version, which will be replaced by the version of the file (if it could
> 497 # be obtained via FILE_VERSION_FILTER)
> 498
> 499 WARN_FORMAT = "$file:$line: $text "
> 500
> 501 # The WARN_LOGFILE tag can be used to specify a file to which warning
> 502 # and error messages should be written. If left blank the output is written
> 503 # to stderr.
> 504
> 505 WARN_LOGFILE =
> 506
> 507 #---------------------------------------------------------------------------
> 508 # configuration options related to the input files
> 509 #---------------------------------------------------------------------------
> 510
> 511 # The INPUT tag can be used to specify the files and/or directories that contain
> 512 # documented source files. You may enter file names like "myfile.cpp" or
> 513 # directories like "/usr/src/myproject". Separate the files or directories
> 514 # with spaces.
> 515
> 516 INPUT = @DOXYGEN_INPUT@
> 517
> 518 # This tag can be used to specify the character encoding of the source files
> 519 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
> 520 # also the default input encoding. Doxygen uses libiconv (or the iconv built
> 521 # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
> 522 # the list of possible encodings.
> 523
> 524 INPUT_ENCODING = UTF-8
> 525
> 526 # If the value of the INPUT tag contains directories, you can use the
> 527 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
> 528 # and *.h) to filter out the source-files in the directories. If left
> 529 # blank the following patterns are tested:
> 530 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
> 531 # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
> 532
> 533 FILE_PATTERNS = *.h
> 534
> 535 # The RECURSIVE tag can be used to turn specify whether or not subdirectories
> 536 # should be searched for input files as well. Possible values are YES and NO.
> 537 # If left blank NO is used.
> 538
> 539 RECURSIVE = YES
> 540
> 541 # The EXCLUDE tag can be used to specify files and/or directories that should
> 542 # excluded from the INPUT source files. This way you can easily exclude a
> 543 # subdirectory from a directory tree whose root is specified with the INPUT tag.
> 544
> 545 EXCLUDE =
> 546
> 547 # The EXCLUDE_SYMLINKS tag can be used select whether or not files or
> 548 # directories that are symbolic links (a Unix filesystem feature) are excluded
> 549 # from the input.
> 550
> 551 EXCLUDE_SYMLINKS = YES
> 552
> 553 # If the value of the INPUT tag contains directories, you can use the
> 554 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
> 555 # certain files from those directories. Note that the wildcards are matched
> 556 # against the file with absolute path, so to exclude all test directories
> 557 # for example use the pattern */test/*
> 558
> 559 EXCLUDE_PATTERNS = */b64/* \
> 560 whgc.* \
> 561 My*.* test*.*
> 562
> 563 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
> 564 # (namespaces, classes, functions, etc.) that should be excluded from the
> 565 # output. The symbol name can be a fully qualified name, a word, or if the
> 566 # wildcard * is used, a substring. Examples: ANamespace, AClass,
> 567 # AClass::ANamespace, ANamespace::*Test
> 568
> 569 EXCLUDE_SYMBOLS = *_INCLUDED_*
> 570
> 571 # The EXAMPLE_PATH tag can be used to specify one or more files or
> 572 # directories that contain example code fragments that are included (see
> 573 # the \include command).
> 574
> 575 EXAMPLE_PATH =
> 576
> 577 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
> 578 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
> 579 # and *.h) to filter out the source-files in the directories. If left
> 580 # blank all files are included.
> 581
> 582 EXAMPLE_PATTERNS =
> 583
> 584 # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
> 585 # searched for input files to be used with the \include or \dontinclude
> 586 # commands irrespective of the value of the RECURSIVE tag.
> 587 # Possible values are YES and NO. If left blank NO is used.
> 588
> 589 EXAMPLE_RECURSIVE = NO
> 590
> 591 # The IMAGE_PATH tag can be used to specify one or more files or
> 592 # directories that contain image that are included in the documentation (see
> 593 # the \image command).
> 594
> 595 IMAGE_PATH =
> 596
> 597 # The INPUT_FILTER tag can be used to specify a program that doxygen should
> 598 # invoke to filter for each input file. Doxygen will invoke the filter program
> 599 # by executing (via popen()) the command <filter> <input-file>, where <filter>
> 600 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
> 601 # input file. Doxygen will then use the output that the filter program writes
> 602 # to standard output. If FILTER_PATTERNS is specified, this tag will be
> 603 # ignored.
> 604
> 605 INPUT_FILTER =
> 606
> 607 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
> 608 # basis. Doxygen will compare the file name with each pattern and apply the
> 609 # filter if there is a match. The filters are a list of the form:
> 610 # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
> 611 # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
> 612 # is applied to all files.
> 613
> 614 FILTER_PATTERNS =
> 615
> 616 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
> 617 # INPUT_FILTER) will be used to filter the input files when producing source
> 618 # files to browse (i.e. when SOURCE_BROWSER is set to YES).
> 619
> 620 FILTER_SOURCE_FILES = NO
> 621
> 622 #---------------------------------------------------------------------------
> 623 # configuration options related to source browsing
> 624 #---------------------------------------------------------------------------
> 625
> 626 # If the SOURCE_BROWSER tag is set to YES then a list of source files will
> 627 # be generated. Documented entities will be cross-referenced with these sources.
> 628 # Note: To get rid of all source code in the generated output, make sure also
> 629 # VERBATIM_HEADERS is set to NO.
> 630
> 631 SOURCE_BROWSER = YES
> 632
> 633 # Setting the INLINE_SOURCES tag to YES will include the body
> 634 # of functions and classes directly in the documentation.
> 635
> 636 INLINE_SOURCES = NO
> 637
> 638 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
> 639 # doxygen to hide any special comment blocks from generated source code
> 640 # fragments. Normal C and C++ comments will always remain visible.
> 641
> 642 STRIP_CODE_COMMENTS = NO
> 643
> 644 # If the REFERENCED_BY_RELATION tag is set to YES (the default)
> 645 # then for each documented function all documented
> 646 # functions referencing it will be listed.
> 647
> 648 REFERENCED_BY_RELATION = YES
> 649
> 650 # If the REFERENCES_RELATION tag is set to YES (the default)
> 651 # then for each documented function all documented entities
> 652 # called/used by that function will be listed.
> 653
> 654 REFERENCES_RELATION = YES
> 655
> 656 # If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
> 657 # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
> 658 # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
> 659 # link to the source code. Otherwise they will link to the documentstion.
> 660
> 661 REFERENCES_LINK_SOURCE = YES
> 662
> 663 # If the USE_HTAGS tag is set to YES then the references to source code
> 664 # will point to the HTML generated by the htags(1) tool instead of doxygen
> 665 # built-in source browser. The htags tool is part of GNU's global source
> 666 # tagging system (see http://www.gnu.org/software/global/global.html). You
> 667 # will need version 4.8.6 or higher.
> 668
> 669 USE_HTAGS = NO
> 670
> 671 # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
> 672 # will generate a verbatim copy of the header file for each class for
> 673 # which an include is specified. Set to NO to disable this.
> 674
> 675 VERBATIM_HEADERS = YES
> 676
> 677 #---------------------------------------------------------------------------
> 678 # configuration options related to the alphabetical class index
> 679 #---------------------------------------------------------------------------
> 680
> 681 # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
> 682 # of all compounds will be generated. Enable this if the project
> 683 # contains a lot of classes, structs, unions or interfaces.
> 684
> 685 ALPHABETICAL_INDEX = YES
> 686
> 687 # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
> 688 # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
> 689 # in which this list will be split (can be a number in the range [1..20])
> 690
> 691 COLS_IN_ALPHA_INDEX = 5
> 692
> 693 # In case all classes in a project start with a common prefix, all
> 694 # classes will be put under the same header in the alphabetical index.
> 695 # The IGNORE_PREFIX tag can be used to specify one or more prefixes that
> 696 # should be ignored while generating the index headers.
> 697
> 698 IGNORE_PREFIX =
> 699
> 700 #---------------------------------------------------------------------------
> 701 # configuration options related to the HTML output
> 702 #---------------------------------------------------------------------------
> 703
> 704 # If the GENERATE_HTML tag is set to YES (the default) Doxygen will
> 705 # generate HTML output.
> 706
> 707 GENERATE_HTML = YES
> 708
> 709 # The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
> 710 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> 711 # put in front of it. If left blank `html' will be used as the default path.
> 712
> 713 HTML_OUTPUT = @HTML_OUTPUT@
> 714
> 715 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for
> 716 # each generated HTML page (for example: .htm,.php,.asp). If it is left blank
> 717 # doxygen will generate files with .html extension.
> 718
> 719 HTML_FILE_EXTENSION = .html
> 720
> 721 # The HTML_HEADER tag can be used to specify a personal HTML header for
> 722 # each generated HTML page. If it is left blank doxygen will generate a
> 723 # standard header.
> 724
> 725 HTML_HEADER =
> 726
> 727 # The HTML_FOOTER tag can be used to specify a personal HTML footer for
> 728 # each generated HTML page. If it is left blank doxygen will generate a
> 729 # standard footer.
> 730
> 731 HTML_FOOTER =
> 732
> 733 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading
> 734 # style sheet that is used by each HTML page. It can be used to
> 735 # fine-tune the look of the HTML output. If the tag is left blank doxygen
> 736 # will generate a default style sheet. Note that doxygen will try to copy
> 737 # the style sheet file to the HTML output directory, so don't put your own
> 738 # stylesheet in the HTML output directory as well, or it will be erased!
> 739
> 740 HTML_STYLESHEET =
> 741
> 742 # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
> 743 # files or namespaces will be aligned in HTML using tables. If set to
> 744 # NO a bullet list will be used.
> 745
> 746 HTML_ALIGN_MEMBERS = YES
> 747
> 748 # If the GENERATE_HTMLHELP tag is set to YES, additional index files
> 749 # will be generated that can be used as input for tools like the
> 750 # Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
> 751 # of the generated HTML documentation.
> 752
> 753 GENERATE_HTMLHELP = NO
> 754
> 755 # If the GENERATE_DOCSET tag is set to YES, additional index files
> 756 # will be generated that can be used as input for Apple's Xcode 3
> 757 # integrated development environment, introduced with OSX 10.5 (Leopard).
> 758 # To create a documentation set, doxygen will generate a Makefile in the
> 759 # HTML output directory. Running make will produce the docset in that
> 760 # directory and running "make install" will install the docset in
> 761 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
> 762 # it at startup.
> 763
> 764 GENERATE_DOCSET = NO
> 765
> 766 # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
> 767 # feed. A documentation feed provides an umbrella under which multiple
> 768 # documentation sets from a single provider (such as a company or product suite)
> 769 # can be grouped.
> 770
> 771 DOCSET_FEEDNAME = "Doxygen generated docs"
> 772
> 773 # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
> 774 # should uniquely identify the documentation set bundle. This should be a
> 775 # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
> 776 # will append .docset to the name.
> 777
> 778 DOCSET_BUNDLE_ID = org.doxygen.Project
> 779
> 780 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
> 781 # documentation will contain sections that can be hidden and shown after the
> 782 # page has loaded. For this to work a browser that supports
> 783 # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
> 784 # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
> 785
> 786 HTML_DYNAMIC_SECTIONS = NO
> 787
> 788 # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
> 789 # be used to specify the file name of the resulting .chm file. You
> 790 # can add a path in front of the file if the result should not be
> 791 # written to the html output directory.
> 792
> 793 CHM_FILE =
> 794
> 795 # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
> 796 # be used to specify the location (absolute path including file name) of
> 797 # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
> 798 # the HTML help compiler on the generated index.hhp.
> 799
> 800 HHC_LOCATION =
> 801
> 802 # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
> 803 # controls if a separate .chi index file is generated (YES) or that
> 804 # it should be included in the master .chm file (NO).
> 805
> 806 GENERATE_CHI = NO
> 807
> 808 # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
> 809 # controls whether a binary table of contents is generated (YES) or a
> 810 # normal table of contents (NO) in the .chm file.
> 811
> 812 BINARY_TOC = NO
> 813
> 814 # The TOC_EXPAND flag can be set to YES to add extra items for group members
> 815 # to the contents of the HTML help documentation and to the tree view.
> 816
> 817 TOC_EXPAND = NO
> 818
> 819 # The DISABLE_INDEX tag can be used to turn on/off the condensed index at
> 820 # top of each HTML page. The value NO (the default) enables the index and
> 821 # the value YES disables it.
> 822
> 823 DISABLE_INDEX = NO
> 824
> 825 # This tag can be used to set the number of enum values (range [1..20])
> 826 # that doxygen will group on one line in the generated HTML documentation.
> 827
> 828 ENUM_VALUES_PER_LINE = 1
> 829
> 830 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
> 831 # generated containing a tree-like index structure (just like the one that
> 832 # is generated for HTML Help). For this to work a browser that supports
> 833 # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
> 834 # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
> 835 # probably better off using the HTML help feature.
> 836
> 837 GENERATE_TREEVIEW = YES
> 838
> 839 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
> 840 # used to set the initial width (in pixels) of the frame in which the tree
> 841 # is shown.
> 842
> 843 TREEVIEW_WIDTH = 300
> 844
> 845 #---------------------------------------------------------------------------
> 846 # configuration options related to the LaTeX output
> 847 #---------------------------------------------------------------------------
> 848
> 849 # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
> 850 # generate Latex output.
> 851
> 852 GENERATE_LATEX = @GENERATE_LATEX@
> 853
> 854 # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
> 855 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> 856 # put in front of it. If left blank `latex' will be used as the default path.
> 857
> 858 LATEX_OUTPUT = @LATEX_OUTPUT@
> 859
> 860 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
> 861 # invoked. If left blank `latex' will be used as the default command name.
> 862
> 863 LATEX_CMD_NAME = latex
> 864
> 865 # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
> 866 # generate index for LaTeX. If left blank `makeindex' will be used as the
> 867 # default command name.
> 868
> 869 MAKEINDEX_CMD_NAME = makeindex
> 870
> 871 # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
> 872 # LaTeX documents. This may be useful for small projects and may help to
> 873 # save some trees in general.
> 874
> 875 COMPACT_LATEX = NO
> 876
> 877 # The PAPER_TYPE tag can be used to set the paper type that is used
> 878 # by the printer. Possible values are: a4, a4wide, letter, legal and
> 879 # executive. If left blank a4wide will be used.
> 880
> 881 PAPER_TYPE = a4wide
> 882
> 883 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
> 884 # packages that should be included in the LaTeX output.
> 885
> 886 EXTRA_PACKAGES =
> 887
> 888 # The LATEX_HEADER tag can be used to specify a personal LaTeX header for
> 889 # the generated latex document. The header should contain everything until
> 890 # the first chapter. If it is left blank doxygen will generate a
> 891 # standard header. Notice: only use this tag if you know what you are doing!
> 892
> 893 LATEX_HEADER =
> 894
> 895 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
> 896 # is prepared for conversion to pdf (using ps2pdf). The pdf file will
> 897 # contain links (just like the HTML output) instead of page references
> 898 # This makes the output suitable for online browsing using a pdf viewer.
> 899
> 900 PDF_HYPERLINKS = YES
> 901
> 902 # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
> 903 # plain latex in the generated Makefile. Set this option to YES to get a
> 904 # higher quality PDF documentation.
> 905
> 906 USE_PDFLATEX = YES
> 907
> 908 # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
> 909 # command to the generated LaTeX files. This will instruct LaTeX to keep
> 910 # running if errors occur, instead of asking the user for help.
> 911 # This option is also used when generating formulas in HTML.
> 912
> 913 LATEX_BATCHMODE = NO
> 914
> 915 # If LATEX_HIDE_INDICES is set to YES then doxygen will not
> 916 # include the index chapters (such as File Index, Compound Index, etc.)
> 917 # in the output.
> 918
> 919 LATEX_HIDE_INDICES = NO
> 920
> 921 #---------------------------------------------------------------------------
> 922 # configuration options related to the RTF output
> 923 #---------------------------------------------------------------------------
> 924
> 925 # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
> 926 # The RTF output is optimized for Word 97 and may not look very pretty with
> 927 # other RTF readers or editors.
> 928
> 929 GENERATE_RTF = NO
> 930
> 931 # The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
> 932 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> 933 # put in front of it. If left blank `rtf' will be used as the default path.
> 934
> 935 RTF_OUTPUT = rtf
> 936
> 937 # If the COMPACT_RTF tag is set to YES Doxygen generates more compact
> 938 # RTF documents. This may be useful for small projects and may help to
> 939 # save some trees in general.
> 940
> 941 COMPACT_RTF = NO
> 942
> 943 # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
> 944 # will contain hyperlink fields. The RTF file will
> 945 # contain links (just like the HTML output) instead of page references.
> 946 # This makes the output suitable for online browsing using WORD or other
> 947 # programs which support those fields.
> 948 # Note: wordpad (write) and others do not support links.
> 949
> 950 RTF_HYPERLINKS = NO
> 951
> 952 # Load stylesheet definitions from file. Syntax is similar to doxygen's
> 953 # config file, i.e. a series of assignments. You only have to provide
> 954 # replacements, missing definitions are set to their default value.
> 955
> 956 RTF_STYLESHEET_FILE =
> 957
> 958 # Set optional variables used in the generation of an rtf document.
> 959 # Syntax is similar to doxygen's config file.
> 960
> 961 RTF_EXTENSIONS_FILE =
> 962
> 963 #---------------------------------------------------------------------------
> 964 # configuration options related to the man page output
> 965 #---------------------------------------------------------------------------
> 966
> 967 # If the GENERATE_MAN tag is set to YES (the default) Doxygen will
> 968 # generate man pages
> 969
> 970 GENERATE_MAN = NO
> 971
> 972 # The MAN_OUTPUT tag is used to specify where the man pages will be put.
> 973 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> 974 # put in front of it. If left blank `man' will be used as the default path.
> 975
> 976 MAN_OUTPUT = man
> 977
> 978 # The MAN_EXTENSION tag determines the extension that is added to
> 979 # the generated man pages (default is the subroutine's section .3)
> 980
> 981 MAN_EXTENSION = .3
> 982
> 983 # If the MAN_LINKS tag is set to YES and Doxygen generates man output,
> 984 # then it will generate one additional man file for each entity
> 985 # documented in the real man page(s). These additional files
> 986 # only source the real man page, but without them the man command
> 987 # would be unable to find the correct page. The default is NO.
> 988
> 989 MAN_LINKS = NO
> 990
> 991 #---------------------------------------------------------------------------
> 992 # configuration options related to the XML output
> 993 #---------------------------------------------------------------------------
> 994
> 995 # If the GENERATE_XML tag is set to YES Doxygen will
> 996 # generate an XML file that captures the structure of
> 997 # the code including all documentation.
> 998
> 999 GENERATE_XML = NO
> 1000
> 1001 # The XML_OUTPUT tag is used to specify where the XML pages will be put.
> 1002 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
> 1003 # put in front of it. If left blank `xml' will be used as the default path.
> 1004
> 1005 XML_OUTPUT = xml
> 1006
> 1007 # The XML_SCHEMA tag can be used to specify an XML schema,
> 1008 # which can be used by a validating XML parser to check the
> 1009 # syntax of the XML files.
> 1010
> 1011 XML_SCHEMA =
> 1012
> 1013 # The XML_DTD tag can be used to specify an XML DTD,
> 1014 # which can be used by a validating XML parser to check the
> 1015 # syntax of the XML files.
> 1016
> 1017 XML_DTD =
> 1018
> 1019 # If the XML_PROGRAMLISTING tag is set to YES Doxygen will
> 1020 # dump the program listings (including syntax highlighting
> 1021 # and cross-referencing information) to the XML output. Note that
> 1022 # enabling this will significantly increase the size of the XML output.
> 1023
> 1024 XML_PROGRAMLISTING = YES
> 1025
> 1026 #---------------------------------------------------------------------------
> 1027 # configuration options for the AutoGen Definitions output
> 1028 #---------------------------------------------------------------------------
> 1029
> 1030 # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
> 1031 # generate an AutoGen Definitions (see autogen.sf.net) file
> 1032 # that captures the structure of the code including all
> 1033 # documentation. Note that this feature is still experimental
> 1034 # and incomplete at the moment.
> 1035
> 1036 GENERATE_AUTOGEN_DEF = NO
> 1037
> 1038 #---------------------------------------------------------------------------
> 1039 # configuration options related to the Perl module output
> 1040 #---------------------------------------------------------------------------
> 1041
> 1042 # If the GENERATE_PERLMOD tag is set to YES Doxygen will
> 1043 # generate a Perl module file that captures the structure of
> 1044 # the code including all documentation. Note that this
> 1045 # feature is still experimental and incomplete at the
> 1046 # moment.
> 1047
> 1048 GENERATE_PERLMOD = NO
> 1049
> 1050 # If the PERLMOD_LATEX tag is set to YES Doxygen will generate
> 1051 # the necessary Makefile rules, Perl scripts and LaTeX code to be able
> 1052 # to generate PDF and DVI output from the Perl module output.
> 1053
> 1054 PERLMOD_LATEX = NO
> 1055
> 1056 # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
> 1057 # nicely formatted so it can be parsed by a human reader. This is useful
> 1058 # if you want to understand what is going on. On the other hand, if this
> 1059 # tag is set to NO the size of the Perl module output will be much smaller
> 1060 # and Perl will parse it just the same.
> 1061
> 1062 PERLMOD_PRETTY = YES
> 1063
> 1064 # The names of the make variables in the generated doxyrules.make file
> 1065 # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
> 1066 # This is useful so different doxyrules.make files included by the same
> 1067 # Makefile don't overwrite each other's variables.
> 1068
> 1069 PERLMOD_MAKEVAR_PREFIX =
> 1070
> 1071 #---------------------------------------------------------------------------
> 1072 # Configuration options related to the preprocessor
> 1073 #---------------------------------------------------------------------------
> 1074
> 1075 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
> 1076 # evaluate all C-preprocessor directives found in the sources and include
> 1077 # files.
> 1078
> 1079 ENABLE_PREPROCESSING = YES
> 1080
> 1081 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
> 1082 # names in the source code. If set to NO (the default) only conditional
> 1083 # compilation will be performed. Macro expansion can be done in a controlled
> 1084 # way by setting EXPAND_ONLY_PREDEF to YES.
> 1085
> 1086 MACRO_EXPANSION = NO
> 1087
> 1088 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
> 1089 # then the macro expansion is limited to the macros specified with the
> 1090 # PREDEFINED and EXPAND_AS_DEFINED tags.
> 1091
> 1092 EXPAND_ONLY_PREDEF = YES
> 1093
> 1094 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
> 1095 # in the INCLUDE_PATH (see below) will be search if a #include is found.
> 1096
> 1097 SEARCH_INCLUDES = YES
> 1098
> 1099 # The INCLUDE_PATH tag can be used to specify one or more directories that
> 1100 # contain include files that are not input files but should be processed by
> 1101 # the preprocessor.
> 1102
> 1103 INCLUDE_PATH =
> 1104
> 1105 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
> 1106 # patterns (like *.h and *.hpp) to filter out the header-files in the
> 1107 # directories. If left blank, the patterns specified with FILE_PATTERNS will
> 1108 # be used.
> 1109
> 1110 INCLUDE_FILE_PATTERNS =
> 1111
> 1112 # The PREDEFINED tag can be used to specify one or more macro names that
> 1113 # are defined before the preprocessor is started (similar to the -D option of
> 1114 # gcc). The argument of the tag is a list of macros of the form: name
> 1115 # or name=definition (no spaces). If the definition and the = are
> 1116 # omitted =1 is assumed. To prevent a macro definition from being
> 1117 # undefined via #undef or recursively expanded use the := operator
> 1118 # instead of the = operator.
> 1119
> 1120 # this __cplusplus define is a kludge to get doxygen to hide my
> 1121 # 'bool' stuff from the docs.
> 1122 PREDEFINED = __cplusplus
> 1123
> 1124 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
> 1125 # this tag can be used to specify a list of macro names that should be expanded.
> 1126 # The macro definition that is found in the sources will be used.
> 1127 # Use the PREDEFINED tag if you want to use a different macro definition.
> 1128
> 1129 EXPAND_AS_DEFINED =
> 1130
> 1131 # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
> 1132 # doxygen's preprocessor will remove all function-like macros that are alone
> 1133 # on a line, have an all uppercase name, and do not end with a semicolon. Such
> 1134 # function macros are typically used for boiler-plate code, and will confuse
> 1135 # the parser if not removed.
> 1136
> 1137 SKIP_FUNCTION_MACROS = NO
> 1138
> 1139 #---------------------------------------------------------------------------
> 1140 # Configuration::additions related to external references
> 1141 #---------------------------------------------------------------------------
> 1142
> 1143 # The TAGFILES option can be used to specify one or more tagfiles.
> 1144 # Optionally an initial location of the external documentation
> 1145 # can be added for each tagfile. The format of a tag file without
> 1146 # this location is as follows:
> 1147 # TAGFILES = file1 file2 ...
> 1148 # Adding location for the tag files is done as follows:
> 1149 # TAGFILES = file1=loc1 "file2 = loc2" ...
> 1150 # where "loc1" and "loc2" can be relative or absolute paths or
> 1151 # URLs. If a location is present for each tag, the installdox tool
> 1152 # does not have to be run to correct the links.
> 1153 # Note that each tag file must have a unique name
> 1154 # (where the name does NOT include the path)
> 1155 # If a tag file is not located in the directory in which doxygen
> 1156 # is run, you must also specify the path to the tagfile here.
> 1157
> 1158 TAGFILES =
> 1159
> 1160 # When a file name is specified after GENERATE_TAGFILE, doxygen will create
> 1161 # a tag file that is based on the input files it reads.
> 1162
> 1163 GENERATE_TAGFILE =
> 1164
> 1165 # If the ALLEXTERNALS tag is set to YES all external classes will be listed
> 1166 # in the class index. If set to NO only the inherited external classes
> 1167 # will be listed.
> 1168
> 1169 ALLEXTERNALS = NO
> 1170
> 1171 # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
> 1172 # in the modules index. If set to NO, only the current project's groups will
> 1173 # be listed.
> 1174
> 1175 EXTERNAL_GROUPS = YES
> 1176
> 1177 # The PERL_PATH should be the absolute path and name of the perl script
> 1178 # interpreter (i.e. the result of `which perl').
> 1179
> 1180 PERL_PATH = @PERL@
> 1181
> 1182 #---------------------------------------------------------------------------
> 1183 # Configuration options related to the dot tool
> 1184 #---------------------------------------------------------------------------
> 1185
> 1186 # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
> 1187 # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
> 1188 # or super classes. Setting the tag to NO turns the diagrams off. Note that
> 1189 # this option is superseded by the HAVE_DOT option below. This is only a
> 1190 # fallback. It is recommended to install and use dot, since it yields more
> 1191 # powerful graphs.
> 1192
> 1193 CLASS_DIAGRAMS = YES
> 1194
> 1195 # You can define message sequence charts within doxygen comments using the \msc
> 1196 # command. Doxygen will then run the mscgen tool (see
> 1197 # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
> 1198 # documentation. The MSCGEN_PATH tag allows you to specify the directory where
> 1199 # the mscgen tool resides. If left empty the tool is assumed to be found in the
> 1200 # default search path.
> 1201
> 1202 MSCGEN_PATH =
> 1203
> 1204 # If set to YES, the inheritance and collaboration graphs will hide
> 1205 # inheritance and usage relations if the target is undocumented
> 1206 # or is not a class.
> 1207
> 1208 HIDE_UNDOC_RELATIONS = YES
> 1209
> 1210 # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
> 1211 # available from the path. This tool is part of Graphviz, a graph visualization
> 1212 # toolkit from AT&T and Lucent Bell Labs. The other options in this section
> 1213 # have no effect if this option is set to NO (the default)
> 1214
> 1215 HAVE_DOT = @USE_DOT@
> 1216
> 1217 # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
> 1218 # will generate a graph for each documented class showing the direct and
> 1219 # indirect inheritance relations. Setting this tag to YES will force the
> 1220 # the CLASS_DIAGRAMS tag to NO.
> 1221
> 1222 CLASS_GRAPH = YES
> 1223
> 1224 # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
> 1225 # will generate a graph for each documented class showing the direct and
> 1226 # indirect implementation dependencies (inheritance, containment, and
> 1227 # class references variables) of the class with other documented classes.
> 1228
> 1229 COLLABORATION_GRAPH = YES
> 1230
> 1231 # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
> 1232 # will generate a graph for groups, showing the direct groups dependencies
> 1233
> 1234 GROUP_GRAPHS = YES
> 1235
> 1236 # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
> 1237 # collaboration diagrams in a style similar to the OMG's Unified Modeling
> 1238 # Language.
> 1239
> 1240 UML_LOOK = YES
> 1241
> 1242 # If set to YES, the inheritance and collaboration graphs will show the
> 1243 # relations between templates and their instances.
> 1244
> 1245 TEMPLATE_RELATIONS = YES
> 1246
> 1247 # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
> 1248 # tags are set to YES then doxygen will generate a graph for each documented
> 1249 # file showing the direct and indirect include dependencies of the file with
> 1250 # other documented files.
> 1251
> 1252 INCLUDE_GRAPH = YES
> 1253
> 1254 # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
> 1255 # HAVE_DOT tags are set to YES then doxygen will generate a graph for each
> 1256 # documented header file showing the documented files that directly or
> 1257 # indirectly include this file.
> 1258
> 1259 INCLUDED_BY_GRAPH = YES
> 1260
> 1261 # If the CALL_GRAPH and HAVE_DOT options are set to YES then
> 1262 # doxygen will generate a call dependency graph for every global function
> 1263 # or class method. Note that enabling this option will significantly increase
> 1264 # the time of a run. So in most cases it will be better to enable call graphs
> 1265 # for selected functions only using the \callgraph command.
> 1266
> 1267 CALL_GRAPH = NO
> 1268
> 1269 # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
> 1270 # doxygen will generate a caller dependency graph for every global function
> 1271 # or class method. Note that enabling this option will significantly increase
> 1272 # the time of a run. So in most cases it will be better to enable caller
> 1273 # graphs for selected functions only using the \callergraph command.
> 1274
> 1275 CALLER_GRAPH = NO
> 1276
> 1277 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
> 1278 # will graphical hierarchy of all classes instead of a textual one.
> 1279
> 1280 GRAPHICAL_HIERARCHY = YES
> 1281
> 1282 # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
> 1283 # then doxygen will show the dependencies a directory has on other directories
> 1284 # in a graphical way. The dependency relations are determined by the #include
> 1285 # relations between the files in the directories.
> 1286
> 1287 DIRECTORY_GRAPH = YES
> 1288
> 1289 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
> 1290 # generated by dot. Possible values are png, jpg, or gif
> 1291 # If left blank png will be used.
> 1292
> 1293 DOT_IMAGE_FORMAT = png
> 1294
> 1295 # The tag DOT_PATH can be used to specify the path where the dot tool can be
> 1296 # found. If left blank, it is assumed the dot tool can be found in the path.
> 1297
> 1298 DOT_PATH =
> 1299
> 1300 # The DOTFILE_DIRS tag can be used to specify one or more directories that
> 1301 # contain dot files that are included in the documentation (see the
> 1302 # \dotfile command).
> 1303
> 1304 DOTFILE_DIRS =
> 1305
> 1306 # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
> 1307 # nodes that will be shown in the graph. If the number of nodes in a graph
> 1308 # becomes larger than this value, doxygen will truncate the graph, which is
> 1309 # visualized by representing a node as a red box. Note that doxygen if the
> 1310 # number of direct children of the root node in a graph is already larger than
> 1311 # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
> 1312 # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
> 1313
> 1314 DOT_GRAPH_MAX_NODES = 50
> 1315
> 1316 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
> 1317 # graphs generated by dot. A depth value of 3 means that only nodes reachable
> 1318 # from the root by following a path via at most 3 edges will be shown. Nodes
> 1319 # that lay further from the root node will be omitted. Note that setting this
> 1320 # option to 1 or 2 may greatly reduce the computation time needed for large
> 1321 # code bases. Also note that the size of a graph can be further restricted by
> 1322 # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
> 1323
> 1324 MAX_DOT_GRAPH_DEPTH = 0
> 1325
> 1326 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
> 1327 # background. This is enabled by default, which results in a transparent
> 1328 # background. Warning: Depending on the platform used, enabling this option
> 1329 # may lead to badly anti-aliased labels on the edges of a graph (i.e. they
> 1330 # become hard to read).
> 1331
> 1332 DOT_TRANSPARENT = NO
> 1333
> 1334 # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
> 1335 # files in one run (i.e. multiple -o and -T options on the command line). This
> 1336 # makes dot run faster, but since only newer versions of dot (>1.8.10)
> 1337 # support this, this feature is disabled by default.
> 1338
> 1339 DOT_MULTI_TARGETS = NO
> 1340
> 1341 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
> 1342 # generate a legend page explaining the meaning of the various boxes and
> 1343 # arrows in the dot generated graphs.
> 1344
> 1345 GENERATE_LEGEND = YES
> 1346
> 1347 # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
> 1348 # remove the intermediate dot files that are used to generate
> 1349 # the various graphs.
> 1350
> 1351 DOT_CLEANUP = YES
> 1352
> 1353 #---------------------------------------------------------------------------
> 1354 # Configuration::additions related to the search engine
> 1355 #---------------------------------------------------------------------------
> 1356
> 1357 # The SEARCHENGINE tag specifies whether or not a search engine should be
> 1358 # used. If set to NO the values of all tags below this one will be ignored.
> 1359
> 1360 SEARCHENGINE = NO

Added Makefile

Old () New (15a5cdeb79ea48b8)
> 1 #!/usr/bin/make -f
> 2 # Requires GNU Make 3.80+!
> 3 default: all
> 4
> 5 ifeq (1,$(TCC))
> 6 # If you have (want to use) tcc, try this:
> 7 CC := tcc
> 8 CXX := tcc
> 9 CPPFLAGS += -gb -bt 10 \
> 10 -Wimplicit-function-declaration \
> 11 -Wwrite-strings \
> 12 -Wunsupported \
> 13 -Wall
> 14 else
> 15 # Assume gcc-compatible flags:
> 16 CXXFLAGS += -g
> 17 # CXXFLAGS += -Os
> 18 CFLAGS += \
> 19 -Wimplicit-function-declaration \
> 20 -Wall \
> 21 -g
> 22 endif
> 23
> 24 PACKAGE.NAME = libwhprintf
> 25 PACKAGE.VERSION := $(shell date +%Y%m%d)
> 26 ShakeNMake.DOXYGEN.GENERATE_LATEX := NO
> 27 ShakeNMake.DOXYGEN.USE_DOT := 0
> 28 include shake-n-make.make
> 29
> 30 INCLUDES += -I.
> 31
> 32 ########################################################################
> 33 # lib:
> 34 WHPRINTF_OBJ := whprintf.o
> 35 libwhprintf.LIB.OBJECTS = $(WHPRINTF_OBJ)
> 36 $(call ShakeNMake.CALL.RULES.LIBS,libwhprintf)
> 37 libs: $(libwhprintf.LIB)
> 38
> 39 ########################################################################
> 40 # test bin
> 41 test.BIN.LDFLAGS := $(libwhprintf.LIB)
> 42 test.BIN.OBJECTS := test.o
> 43 $(call ShakeNMake.CALL.RULES.BINS,test)
> 44 $(test.BIN): $(libwhprintf.LIB)
> 45 bins: $(test.BIN)
> 46
> 47 CLEAN_FILES += *~ *.valgrind *.a
> 48 PACKAGE.DIST_FILES += $(wildcard *.c *.h)
> 49
> 50 .PHONY: tcc
> 51 tcc:
> 52 $(MAKE) TCC=1
> 53
> 54 all: libs bins

Added shake-n-make.make

Old () New (81dbd3be3a8a77ea)
> 1 #!/usr/bin/make -f
> 2 all:
> 3 SHELL=/bin/bash
> 4 MAKE_REQUIRED_VERSION := 380# MAKE_VERSION stripped of any dots
> 5 VERSION_CHECK := \
> 6 $(shell \
> 7 test $$(echo $(MAKE_VERSION) | sed -e 's/\.//g') -ge \
> 8 "$(MAKE_REQUIRED_VERSION)" 2>/dev/null \
> 9 && echo 1 || echo 0)
> 10
> 11 ifneq (1,$(VERSION_CHECK))
> 12 $(error Your version of Make ($(MAKE_VERSION)) is too old to use this code!)
> 13 endif
> 14
> 15
> 16 ########################################################################
> 17 # This file defines a set of basic targets for single-dir C++ projects
> 18 # trees, designed for GNU make and gcc. The code in this file is
> 19 # intended to remain project-neutral. Add your project-specific stuff
> 20 # in higher-level makefiles and include this one from there.
> 21 #
> 22 # The shell code in this makefile assumes GNU Make, GNU Bash and GNU
> 23 # versions several other common system tools, like mkdir, tar, sed,
> 24 # etc.
> 25 #
> 26 ########################################################################
> 27 # Distribution policy:
> 28 #
> 29 # Public Domain, of course. No warranties at all: if it destroys your
> 30 # data or your marriage, it's your faul (or at least it's not MY fault).
> 31 #
> 32 # i ACTUALLY DO use this code in several source trees, so please send
> 33 # in improvements: http://wanderinghorse.net/computing/make/
> 34 #
> 35 ########################################################################
> 36 # Main features:
> 37 #
> 38 # - Rules for compiling C/C++ sources.
> 39 #
> 40 # - Rules for building binaries from C/C++ sources.
> 41 #
> 42 # - Rules for building shared/static libraries and binaries.
> 43 #
> 44 # - Rules for building a tarred or zipped distribution file.
> 45 #
> 46 # - Rules for installation of arbitrary file sets.
> 47 #
> 48 # - Transparent and automatic (and *fast*) dependencies generation for
> 49 # C/C++ files.
> 50 #
> 51 ########################################################################
> 52 # Ultra-quick usage overview:
> 53 #
> 54 # Include it from your Makefile like so:
> 55 #
> 56 # PACKAGE.NAME = single-token name of your project (e.g., libfoo)
> 57 # PACKAGE.VERSION = project version number, in an arbitrary format.
> 58 # include shake-n-make.mk
> 59 #
> 60 # Using spaces or special shell characters in .NAME and .VERSION may
> 61 # cause problems in this code.
> 62 #
> 63 # PACKAGE.* are used when building a distribution tarball.
> 64 #
> 65 # You can optionally define the following variables:
> 66 # CLEAN_FILES += list of files/dirs to delete during 'make clean'
> 67 # DISTCLEAN_FILES += list of files/dirs to delete during 'make distclean'
> 68 # PACKAGE.DIST_FILES += list of files/dirs to include in distribution
> 69 # tarball/zip file.
> 70 #
> 71 #
> 72 # Achtung:
> 73 # ***** Note the use of "+=" on several of those variables!!!! *****
> 74 # ***** BE CAREFUL WHEN USING [DIST]CLEAN_FILES!!!! *****
> 75 #
> 76 # The rules for bins, shared libs, etc., have to be installed by the
> 77 # user, but it's really simple. The subsections below explain how to
> 78 # use the various features.
> 79 #
> 80 # To install your package do:
> 81 #
> 82 # make install prefix=/install/prefix
> 83 #
> 84 # where $(prefix) normally defaults to /usr/local. (Setting prefix
> 85 # to $HOME is often useful.)
> 86 #
> 87 ########################################################################
> 88 # Compiling .o files from *.cpp and *.c:
> 89 #
> 90 # This file provides flexible rules for building these. See the %.o
> 91 # targets for all of the accepted flags.
> 92 #
> 93 ########################################################################
> 94 # Building a binary executable:
> 95 #
> 96 # mybin.BIN.OBJECTS = foo.o bar.o
> 97 # mybin.BIN.LDFLAGS = -ldl -lstdc++
> 98 # $(call ShakeNMake.CALL.RULES.BINS,mybin)
> 99 #
> 100 # You may pass an arbitrary number of binary names to CALL.RULES.BINS.
> 101 # See ShakeNMake.EVAL.RULES.BINS for the full list of configuration
> 102 # vars it accepts.
> 103 #
> 104 # A target named mybin.BIN is created for building the binary and
> 105 # $(mybin.BIN) holds the name of the compiled binary (typically
> 106 # "mybin").
> 107 #
> 108 ########################################################################
> 109 # Building a shared library:
> 110 #
> 111 # myDLL.DLL.OBJECTS = foo.o bar.o
> 112 # myDLL.LDFLAGS = -L/a/lib/path -lmylib
> 113 # $(call ShakeNMake.CALL.RULES.DLLS,myDLL)
> 114 #
> 115 # Like CALL.RULES.BINS, you may pass an arbitrary number of DLL names to
> 116 # CALL.RULES.DLLS. See EVAL.RULES.DLLS for the full list of configuration
> 117 # vars it accepts.
> 118 #
> 119 # A target named myDLL.DLL is created for building the library and
> 120 # $(myDLL.DLL) holds the name of the compiled DLL (typically
> 121 # "myDLL.so").
> 122 #
> 123 ########################################################################
> 124 # Building a static library is trival:
> 125 #
> 126 # myLib.LIB.OBJECTS = foo.o bar.o
> 127 # $(call ShakeNMake.CALL.RULES.LIBS,myLib)
> 128 #
> 129 # A target named myLib.LIB is created for building the library and
> 130 # $(myLib.LIB) holds the name of the compiled lib (typically
> 131 # "myLib.a").
> 132 #
> 133 ########################################################################
> 134 # Installing files:
> 135 #
> 136 # To install files you have to define "install sets", where a "set" is
> 137 # simply a collection of files which all have the same destination.
> 138 # An example:
> 139 #
> 140 # INSTALL.STUFF = $(myLib.LIB) $(myDLL.DLL) $(mybin.BIN)
> 141 # INSTALL.STUFF.DEST = $(prefix)/$(PACKAGE.NAME)
> 142 # $(call ShakeNMake.CALL.RULES.INSTALL,STUFF)
> 143 #
> 144 # That creates install rules named install-STUFF and uninstall-STUFF,
> 145 # which are called by the install and uninstall targets, respectively.
> 146 #
> 147 # You may pass an arbitrary number of install set names to
> 148 # CALL.RULES.INSTALL.
> 149 #
> 150 # Install notes:
> 151 #
> 152 # - There is nothing magical about the word STUFF: any single token can
> 153 # be used. If INSTALL.xxx.DEST is not set then [un]install-xxx will
> 154 # cause an error.
> 155 #
> 156 # - The installation rules are quite braindead, and simply use cp to
> 157 # install files.
> 158 #
> 159 ########################################################################
> 160 # Distribution tarball:
> 161 #
> 162 # To build a dist tarball:
> 163 #
> 164 # PACKAGE.DIST_FILES += list of files
> 165 #
> 166 # Then:
> 167 # make dist
> 168 #
> 169 # That builds a file named $(PACKAGE.NAME)-$(PACKAGE.VERSION).tar.gz and,
> 170 # if 'zip' is found in your $(PATH) then a zip file is created as well.
> 171 #
> 172 # Note that GNUmakefile and shake-n-make.make are added to DIST_FILES by
> 173 # default, so you don't need to add those. If shake-n-make.make is using
> 174 # mkdep.c to generate C/C++ dependencies than that file is also
> 175 # automatically included in the distribution.
> 176 #
> 177 # If you want to use a non-GNU tar or change the compression type
> 178 # (defaults to gzip) then change the ShakeNMake.TARBALL.FLAGS variable
> 179 # in this file (not in your Makefile).
> 180 # The ShakeNMake.TARBALL.XFLAGS is a special case var which has flags
> 181 # for tar which go AFTER the target filename. e.g. you can set it to
> 182 # --exclude=MySubDir to exclude files from a certain dir.
> 183 #
> 184 ########################################################################
> 185 # Eye candy:
> 186 #
> 187 # If you want the compiler/linker output to be less verbose, try:
> 188 #
> 189 # ShakeNMake.QUIET = 1
> 190 #
> 191 # BEFORE including this file.
> 192 #
> 193 ########################################################################
> 194 # Maintainer's/hacker's notes:
> 195 #
> 196 # Vars names starting with ShakeNMake are mostly internal to this
> 197 # makefile and are considered "private" unless documented otherwise.
> 198 # Notable exceptions are most of the ShakeNMake.CALL entries, which
> 199 # are $(call)able functions, and ShakeNMake.EVAL entries, which are
> 200 # $(eval)able code.
> 201 #
> 202 ########################################################################
> 203
> 204 ifneq (,$(COMSPEC))
> 205 $(warning Setting ShakeNMake.SMELLS.LIKE.WINDOWS to 1)
> 206 ShakeNMake.SMELLS.LIKE.WINDOWS := 1
> 207 ShakeNMake.EXTENSIONS.DLL = .DLL# maintenance reminder: this must stay upper-case!
> 208 ShakeNMake.EXTENSIONS.EXE = .EXE# maintenance reminder: this must stay upper-case!
> 209 else
> 210 ShakeNMake.SMELLS.LIKE.WINDOWS := 0
> 211 ShakeNMake.EXTENSIONS.DLL = .so
> 212 ShakeNMake.EXTENSIONS.EXE =# no whitespace, please
> 213 endif
> 214
> 215
> 216 ShakeNMake.MAKEFILE = shake-n-make.make
> 217 $(ShakeNMake.MAKEFILE):# avoid breaking some deps checks if someone renames this file (been there, done that)
> 218
> 219 ########################################################################
> 220 # Core information:
> 221
> 222 ifeq (,$(PACKAGE.NAME))
> 223 $(error You must set PACKAGE.NAME to a single-token name for your prject, e.g., libMyStuff)
> 224 endif
> 225
> 226 ifeq (,$(PACKAGE.VERSION))
> 227 $(error You must set PACKAGE.VERSION to a version number for your project, e.g., 1.3.5.7-beta9 or 1.0 or 2007-02-14)
> 228 endif
> 229
> 230
> 231 ########################################################################
> 232 # auto-add the makefiles to DIST_FILES, filtering out any which start
> 233 # with a dot because we use such files for temp/volitile files which
> 234 # contain Make rules (C/C++ deps, for example).
> 235 PACKAGE.MAKEFILE = $(firstword $(MAKEFILE_LIST))# normally either Makefile or GNUmakefile
> 236 $(PACKAGE.MAKEFILE):
> 237 PACKAGE.DIST_FILES += $(filter-out .%,$(MAKEFILE_LIST))
> 238
> 239
> 240 ShakeNMake.FORCE: ; @true
> 241
> 242 ########################################################################
> 243 # DESTDIR is for GNU Autotools compatibility...
> 244 DESTDIR ?=
> 245 prefix ?= /usr/local
> 246 ShakeNMake.INSTALL.DESTDIR = $(DESTDIR)
> 247 ShakeNMake.INSTALL.PREFIX = $(prefix)
> 248 ShakeNMake.INSTALL_ROOT=$(DESTDIR)$(prefix)/
> 249
> 250 ########################################################################
> 251 # ShakeNMake.CALL.FIND_BIN call()able function:
> 252 # $1 = app name
> 253 # $2 = optional path
> 254 ShakeNMake.CALL.FIND_BIN = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(2) $(PATH)))))
> 255 ########################################################################
> 256
> 257 ########################################################################
> 258 # Find some common binaries...
> 259 ShakeNMake.BINS.TAR := $(call ShakeNMake.CALL.FIND_BIN,tar)
> 260 ifeq (,$(ShakeNMake.BINS.TAR))
> 261 ShakeNMake.BINS.TAR := $(call ShakeNMake.CALL.FIND_BIN,gtar)
> 262 endif
> 263 ShakeNMake.BINS.ZIP := $(call ShakeNMake.CALL.FIND_BIN,zip)
> 264 ShakeNMake.BINS.RM := $(call ShakeNMake.CALL.FIND_BIN,rm)
> 265 ShakeNMake.BINS.GCC := $(call ShakeNMake.CALL.FIND_BIN,gcc)
> 266 #
> 267 ########################################################################
> 268
> 269 ########################################################################
> 270 # An internal hack to enable "quiet" output. $(1) is a string which
> 271 # is shown ONLY if ShakeNMake.QUIET!=1
> 272 ShakeNMake.QUIET ?= 0
> 273 define ShakeNMake.CALL.SETX
> 274 if [[ x1 = "x$(ShakeNMake.QUIET)" ]]; then echo $(1); else set -x; fi
> 275 endef
> 276 ########################################################################
> 277
> 278 ########################################################################
> 279 # PACKAGE.DIST_FILES stuff...
> 280 ifeq (,$(ShakeNMake.BINS.TAR))
> 281 dist:
> 282 @echo "'tar' was not found in the PATH, so i cannot build a dist tarball :(."
> 283 else
> 284 ShakeNMake.TARBALL.FLAGS ?= czf
> 285 ShakeNMake.TARBALL.XFLAGS ?=
> 286 ShakeNMake.TARBALL.BASENAME = $(PACKAGE.NAME)-$(PACKAGE.VERSION)
> 287 ShakeNMake.TARBALL.FILE = $(ShakeNMake.TARBALL.BASENAME).tar.gz
> 288 ShakeNMake.TARBALL.ZIPFILE = $(ShakeNMake.TARBALL.BASENAME).zip
> 289 DISTCLEAN_FILES += $(ShakeNMake.TARBALL.FILE) $(ShakeNMake.TARBALL.ZIPFILE)
> 290
> 291 dist-cleanup:
> 292 @rm -fr $(ShakeNMake.TARBALL.BASENAME); true
> 293 dist-target-implementation:
> 294 @-if test -d $(ShakeNMake.TARBALL.BASENAME); then rm -fr $(ShakeNMake.TARBALL.BASENAME) || exit $$?; fi
> 295 @echo "Creating $(ShakeNMake.TARBALL.FILE)..."
> 296 @mkdir $(ShakeNMake.TARBALL.BASENAME)
> 297 @cp --parents -r $(PACKAGE.DIST_FILES) $(ShakeNMake.TARBALL.BASENAME)
> 298 @find $(ShakeNMake.TARBALL.BASENAME) -name CVS -o -name .svn -type d | xargs rm -fr; true
> 299 @$(ShakeNMake.BINS.TAR) \
> 300 $(ShakeNMake.TARBALL.FLAGS) \
> 301 $(ShakeNMake.TARBALL.FILE) \
> 302 $(ShakeNMake.TARBALL.XFLAGS) \
> 303 $(ShakeNMake.TARBALL.BASENAME)
> 304 @ls -la $(ShakeNMake.TARBALL.FILE)
> 305 ifneq (,$(ShakeNMake.BINS.ZIP))
> 306 @test -e $(ShakeNMake.TARBALL.ZIPFILE) && rm -f $(ShakeNMake.TARBALL.ZIPFILE); true
> 307 @$(ShakeNMake.BINS.ZIP) -q -r $(ShakeNMake.TARBALL.ZIPFILE) $(ShakeNMake.TARBALL.BASENAME)
> 308 @ls -la $(ShakeNMake.TARBALL.BASENAME).zip
> 309 endif
> 310 dist:
> 311 @$(MAKE) --no-print-directory dist-target-implementation; err=$$?; \
> 312 $(MAKE) --no-print-directory dist-cleanup; echo $$err
> 313 clean: dist-cleanup
> 314 endif # if $(ShakeNMake.BINS.TAR)
> 315 # end dist
> 316 ########################################################################
> 317
> 318
> 319 ########################################################################
> 320 # ShakeNMake.CALL.INSTALL: $(call)able function:
> 321 # $1 = destination dir.
> 322 # $2 = list of source files or directories
> 323 # Copies $2 to $1.
> 324 ShakeNMake.CALL.INSTALL = { \
> 325 test x = "x$(1)" && { echo "Install path is empty!"; exit 1; }; \
> 326 test -d $(1) || mkdir -p $(1) || exit; \
> 327 for x in $(2); do \
> 328 echo -e '\t--> '$$x; \
> 329 cp -rp $$x $(1) || { err=$$?; echo "Copy failed!"; exit $$?; }; \
> 330 done; \
> 331 }
> 332 # ShakeNMake.CALL.UNINSTALL: $(call)able function:
> 333 # $1 = destination dir.
> 334 # $2 = list of files (not directories!) to delete
> 335 # Removes $2 from $1. It tries to rmdir $1 when it is done, but that will
> 336 # only work if $1 is empty. Such a failure is silently ignored.
> 337 ShakeNMake.CALL.UNINSTALL = { \
> 338 test -d $(1) || exit 0; \
> 339 for x in $(2); do \
> 340 echo -e "\t<-- " $(1)/$$x; \
> 341 rm -f $(1)/$$x || exit; \
> 342 done; \
> 343 }; \
> 344 rmdir $(1) 2>/dev/null || true;
> 345 # Trivia: i actually did delete all files in my home dir
> 346 # once while testing the uninstall code. Luckily, -r wasn't
> 347 # in effect.
> 348 ########################################################################
> 349
> 350 ########################################################################
> 351 # install-% installs files listed in $(INSTALL.%) to $(INSTALL.%.DEST),
> 352 # which defaults to %. $(ShakeNMake.INSTALL.DESTDIR) is automatically
> 353 # prefixed to installation paths, for compatibility with the GNU
> 354 # Autotools and Debian-preferred install methods.
> 355 # When specifying install paths for client code, like so:
> 356 #
> 357 # INSTALL.MYSTUFF = list of files
> 358 # INSTALL.MYSTUFF.DEST = $(prefix)/$(PACKAGE.NAME)
> 359 #
> 360 # the path should always be relative to $(prefix), with the assumption that
> 361 # $(prefix) is an absolute path without a trailing backslash. The install
> 362 # path should NOT take into accont $(DESTDIR), because that is handled
> 363 # transparently at a deeper level.
> 364 ShakeNMake.CALL.GET_INSTALL_DEST = $(ShakeNMake.INSTALL.DESTDIR)$(INSTALL.$(1).DEST)
> 365 install-%:
> 366 @echo "Installing \$$(INSTALL.$(*)) files to $(call ShakeNMake.CALL.GET_INSTALL_DEST,$(*))..."; \
> 367 $(call ShakeNMake.CALL.INSTALL,$(call ShakeNMake.CALL.GET_INSTALL_DEST,$(*)),$(INSTALL.$(*)))
> 368 # Maintenance note: don't break the $(call) args onto separate lines because
> 369 # that introduces a whitespace char which can screw up the install code. :(
> 370 ########################################################################
> 371 # uninstall-% deletes INSTALL.% from INSTALL.%.DEST, which defaults to
> 372 # $(ShakeNMake.INSTALL_ROOT)%.
> 373 uninstall-%:
> 374 @echo "Uninstalling \$$(INSTALL.$(*)) files from $(call ShakeNMake.CALL.GET_INSTALL_DEST,$(*))..."; \
> 375 $(call ShakeNMake.CALL.UNINSTALL,$(call ShakeNMake.CALL.GET_INSTALL_DEST,$(*)),$(INSTALL.$(*)))
> 376 # Maintenance note: don't break the $(call) args onto separate lines because
> 377 # that introduces a whitespace char which can screw up the uninstall code. :(
> 378 ########################################################################
> 379
> 380 ########################################################################
> 381 # ShakeNMake.EVAL.RULES.INSTALL adds [un]install-$(1) as prerequisites
> 382 # of the [un]install targets, so that they get called by
> 383 # 'make [un]install'.
> 384 define ShakeNMake.EVAL.RULES.INSTALL
> 385 INSTALL.$(1).DEST ?= $(prefix)/$(1)
> 386 install: install-$(1)
> 387 uninstall: uninstall-$(1)
> 388 endef
> 389 ########################################################################
> 390 # $(call ShakeNMake.CALL.RULES.INSTALL,[list]) calls and $(eval)s
> 391 # ShakeNMake.EVAL.RULES.INSTALL one time for each item in $(1).
> 392 define ShakeNMake.CALL.RULES.INSTALL
> 393 $(foreach proggy,$(1),$(eval $(call ShakeNMake.EVAL.RULES.INSTALL,$(proggy))))
> 394 endef
> 395 # end ShakeNMake.EVAL.RULES.INSTALL
> 396 ########################################################################
> 397
> 398
> 399 ########################################################################
> 400 # builds %.o from %.c using $(CC).
> 401 # Passes on flags from these vars:
> 402 # CFLAGS, %.CFLAGS
> 403 # INCLUDES, %.OBJ.INCLUDES
> 404 # CPPFLAGS, %.OBJ.CPPFLAGS
> 405 %.o: %.c $(ShakeNMake.MAKEFILE) $(PACKAGE.MAKEFILE)
> 406 @$(call ShakeNMake.CALL.SETX,"CC [$@] ..."); \
> 407 $(CC) $(CFLAGS) $($(*).OBJ.CFLAGS) \
> 408 $(INCLUDES) $($(*).OBJ.INCLUDES) \
> 409 $(CPPFLAGS) $($(*).OBJ.CPPFLAGS) \
> 410 -c -o $@ $<
> 411 ########################################################################
> 412
> 413 ########################################################################
> 414 # build %.o from %.cpp using $(CXX).
> 415 # Passes on flags from these vars:
> 416 # CXXFLAGS, %.OBJ.CXXFLAGS
> 417 # INCLUDES, %.OBJ.INCLUDES
> 418 # CPPFLAGS, %.OBJ.CPPFLAGS
> 419 %.o: %.cpp $(ShakeNMake.MAKEFILE) $(PACKAGE.MAKEFILE)
> 420 @$(call ShakeNMake.CALL.SETX,"CXX [$@] ..."); \
> 421 $(CXX) $(CXXFLAGS) $($(*).OBJ.CXXFLAGS) \
> 422 $(INCLUDES) $($(*).OBJ.INCLUDES) \
> 423 $(CPPFLAGS) $($(*).OBJ.CPPFLAGS) \
> 424 -c -o $@ $<
> 425 # end %.o: %.cpp rules
> 426 ########################################################################
> 427
> 428
> 429 ########################################################################
> 430 # ShakeNMake.EVAL.RULES.BIN is intended to be called like so:
> 431 # $(eval $(call ShakeNMake.EVAL.RULES.BIN,MyApp))
> 432 #
> 433 # It builds a binary named $(1) by running $(CC) and passing it:
> 434 #
> 435 # INCLUDES, $(1).BIN.INCLUDES
> 436 # CFLAGS, $(1).BIN.CFLAGS
> 437 # CXXFLAGS, $(1).BIN.CXXFLAGS
> 438 # CPPFLAGS, $(1).BIN.CPPFLAGS
> 439 # LDFLAGS, $(1).BIN.LDFLAGS
> 440 # $(1).BIN.OBJECTS $(1).BIN.SOURCES
> 441 #
> 442 # Note that we have to pass both CFLAGS and CPPFLAGS because .SOURCES might
> 443 # contain either of C or C++ files.
> 444 define ShakeNMake.EVAL.RULES.BIN
> 445 $(1).BIN = $(1)$(ShakeNMake.EXTENSIONS.EXE)
> 446 $(1).BIN: $$($(1).BIN)
> 447 # Many developers feel that bins should not be cleaned by 'make
> 448 # clean', but instead by distclean, but i'm not one of those
> 449 # developers. i subscribe more to the school of thought that distclean
> 450 # is for cleaning up configure-created files. That said, shake-n-make
> 451 # isn't designed to use a configure-like process, so that is probably
> 452 # moot here and we probably (maybe?) should clean up bins only in
> 453 # distclean. As always: hack it to suit your preference:
> 454 CLEAN_FILES += $$($(1).BIN)
> 455 $$($(1).BIN): $$($(1).BIN.OBJECTS) $$($(1).BIN.SOURCES)
> 456 @test x = "x$$($(1).BIN.OBJECTS)$$($(1).BIN.SOURCES)" && { \
> 457 echo "$(1).BIN.OBJECTS and/or $(1).BIN.SOURCES is undefined!"; exit 1; }; \
> 458 $(call ShakeNMake.CALL.SETX,"CXX [$$@] ..."); \
> 459 $$(CXX) -o $$@ \
> 460 $$(INCLUDES) $$($(1).BIN.INCLUDES) \
> 461 $$(CFLAGS) $$($(1).BIN.CFLAGS) \
> 462 $$(CXXFLAGS) $$($(1).BIN.CXXFLAGS) \
> 463 $$(CPPFLAGS) $$($(1).BIN.CPPFLAGS) \
> 464 $$($(1).BIN.OBJECTS) $$($(1).BIN.SOURCES) \
> 465 $$(LDFLAGS) $$($(1).BIN.LDFLAGS)
> 466 # note about 'set -x': i do this because it normalizes backslashed
> 467 # newline, extra spaces, and other oddities of formatting.
> 468 endef
> 469 ########################################################################
> 470 # $(call ShakeNMake.CALL.RULES.BINS,[list]) calls and $(eval)s
> 471 # ShakeNMake.EVAL.RULES.BIN for each entry in $(1)
> 472 define ShakeNMake.CALL.RULES.BINS
> 473 $(foreach bin,$(1),$(eval $(call ShakeNMake.EVAL.RULES.BIN,$(bin))))
> 474 endef
> 475 # end ShakeNMake.CALL.RULES.BIN and friends
> 476 ########################################################################
> 477
> 478
> 479 ########################################################################
> 480 # ShakeNMake.EVAL.RULES.DLL builds builds $(1)$(ShakeNMake.EXTENSIONS.DLL) from object files
> 481 # defined by $(1).DLL.OBJECTS and $(1).DLL.SOURCES. Flags passed on
> 482 # to the linker include:
> 483 # LDFLAGS, $(1).DLL.LDFLAGS, LDADD, -shared -export-dynamic
> 484 # $(1).DLL.CPPFLAGS
> 485 #
> 486 # Also defines the var $(1).DLL, which expands to the filename of the DLL,
> 487 # (normally $(1)$(ShakeNMake.EXTENSIONS.DLL)).
> 488 define ShakeNMake.EVAL.RULES.DLL
> 489 $(1).DLL = $(1)$(ShakeNMake.EXTENSIONS.DLL)
> 490 ifneq (.DLL,$(ShakeNMake.EXTENSIONS.DLL))
> 491 $(1).DLL: $$($(1).DLL)
> 492 endif
> 493 CLEAN_FILES += $$($(1).DLL)
> 494 $$($(1).DLL): $$($(1).DLL.SOURCES) $$($(1).DLL.OBJECTS)
> 495 @test x = "x$$($(1).DLL.OBJECTS)$$($(1).DLL.SOURCES)" && { \
> 496 echo "$(1).DLL.OBJECTS and/or $(1).DLL.SOURCES are/is undefined!"; exit 1; }; \
> 497 $(call ShakeNMake.CALL.SETX,"CXX [$$@] ..."); \
> 498 $$(CXX) -o $$@ -shared -export-dynamic $$(LDFLAGS) \
> 499 $$($(1).DLL.LDFLAGS) $$($(1).DLL.OBJECTS) $$($(1).DLL.SOURCES) \
> 500 $$($(1).DLL.CPPFLAGS)
> 501 endef
> 502 ########################################################################
> 503 # $(call ShakeNMake.CALL.RULES.DLLS,[list]) calls and $(eval)s
> 504 # ShakeNMake.EVAL.RULES.DLL for each entry in $(1)
> 505 define ShakeNMake.CALL.RULES.DLLS
> 506 $(foreach dll,$(1),$(eval $(call ShakeNMake.EVAL.RULES.DLL,$(dll))))
> 507 endef
> 508 # end ShakeNMake.CALL.RULES.DLLS and friends
> 509 ########################################################################
> 510
> 511 ########################################################################
> 512 # ShakeNMake.EVAL.RULES.LIB creates rules to build static library
> 513 # $(1).a
> 514 define ShakeNMake.EVAL.RULES.LIB
> 515 $(1).LIB = $(1).a
> 516 $(1).LIB: $$($(1).LIB)
> 517 CLEAN_FILES += $$($(1).LIB)
> 518 $$($(1).LIB): $$($(1).LIB.OBJECTS)
> 519 @$(call ShakeNMake.CALL.SETX,"AR [$$@] ..."); \
> 520 $$(AR) crs $$@ $$($(1).LIB.OBJECTS)
> 521 endef
> 522 define ShakeNMake.CALL.RULES.LIBS
> 523 $(foreach liba,$(1),$(eval $(call ShakeNMake.EVAL.RULES.LIB,$(liba))))
> 524 endef
> 525 # end ShakeNMake.EVAL.RULES.LIB
> 526 ########################################################################
> 527
> 528 ########################################################################
> 529 # [DIST]CLEAN_FILES support...
> 530 ########################################################################
> 531 CLEAN_FILES += *.o
> 532 DISTCLEAN_FILES += *~
> 533 clean: ShakeNMake.FORCE
> 534 @fl="$(sort $(wildcard $(CLEAN_FILES)))"; \
> 535 test x = "x$$fl" && { echo "Nothing to clean!"; exit 0; }; \
> 536 $(call ShakeNMake.CALL.SETX,"Cleaning up ..."); \
> 537 $(ShakeNMake.BINS.RM) -fr $$fl
> 538 distclean: ShakeNMake.FORCE
> 539 @fl="$(sort $(wildcard $(CLEAN_FILES) $(DISTCLEAN_FILES)))"; \
> 540 test x = "x$$fl" && { echo "Nothing to clean!"; exit 0; }; \
> 541 $(call ShakeNMake.CALL.SETX,"Cleaning up ..."); \
> 542 $(ShakeNMake.BINS.RM) -fr $$fl
> 543 # end [DIST]CLEAN_FILES
> 544 ########################################################################
> 545
> 546
> 547 ########################################################################
> 548 # Automatic dependencies generation for C/C++ code...
> 549 # To disable deps generation, set ShakeNMake.USE_MKDEPS=0 *before*
> 550 # including this file.
> 551 ifeq (,$(ShakeNMake.BINS.GCC))
> 552 ShakeNMake.USE_MKDEPS ?= 0
> 553 else
> 554 ShakeNMake.USE_MKDEPS ?= 1
> 555 endif
> 556 #$(warning ShakeNMake.USE_MKDEPS=$(ShakeNMake.USE_MKDEPS));
> 557 ifeq (1,$(ShakeNMake.USE_MKDEPS))
> 558 ShakeNMake.CISH_SOURCES += $(wildcard *.cpp *.c *.c++ *.h *.hpp *.h++ *.hh)
> 559 #$(warning ShakeNMake.CISH_SOURCES=$(ShakeNMake.CISH_SOURCES))
> 560 ifneq (,$(ShakeNMake.CISH_SOURCES))
> 561 ShakeNMake.CISH_DEPS_FILE := .make.c_deps
> 562 ShakeNMake.BINS.MKDEP = gcc -E -MM $(INCLUDES)
> 563 CLEAN_FILES += $(ShakeNMake.CISH_DEPS_FILE)
> 564 $(ShakeNMake.CISH_DEPS_FILE): $(PACKAGE.MAKEFILE) $(ShakeNMake.MAKEFILE) $(ShakeNMake.CISH_SOURCES)
> 565 @$(ShakeNMake.BINS.MKDEP) $(ShakeNMake.CISH_SOURCES) 2>/dev/null > $@ || \
> 566 $(ShakeNMake.BINS.RM) -f $@ 2>/dev/null
> 567 # ^^^^ We rm -f the deps file if mkdep fails because we don't want a bad generated makefile
> 568 # to kill the build.
> 569
> 570 ifneq (,$(strip $(filter distclean clean,$(MAKECMDGOALS))))
> 571 #$(warning Skipping C/C++ deps generation.)
> 572 ABSOLUTEBOGO := $(shell $(ShakeNMake.BINS.RM) -f $(ShakeNMake.CISH_DEPS_FILE))
> 573 else
> 574 #$(warning Including C/C++ deps.)
> 575 -include $(ShakeNMake.CISH_DEPS_FILE)
> 576 endif
> 577
> 578 endif
> 579 # ^^^^ ifneq(,$(ShakeNMake.CISH_SOURCES))
> 580 endif
> 581 # ^^^^ end $(ShakeNMake.USE_MKDEPS)
> 582 ########################################################################
> 583
> 584 ########################################################################
> 585 # Doxygen
> 586 ShakeNMake.BINS.SED := $(call ShakeNMake.CALL.FIND_BIN,sed)
> 587 ShakeNMake.BINS.PERL := $(call ShakeNMake.CALL.FIND_BIN,perl)
> 588 ShakeNMake.BINS.LATEX := $(call ShakeNMake.CALL.FIND_BIN,latex)
> 589 ifneq (,$(ShakeNMake.BINS.PERL))
> 590 ShakeNMake.BINS.DOXYGEN := $(call ShakeNMake.CALL.FIND_BIN,doxygen)
> 591 ifneq (,$(ShakeNMake.BINS.DOXYGEN))
> 592 ShakeNMake.DOXYGEN.DOXYFILE_TEMPLATE = Doxyfile.at
> 593 ifneq (,$(wildcard $(ShakeNMake.DOXYGEN.DOXYFILE_TEMPLATE)))
> 594 ShakeNMake.DOXYGEN.INDEX := $(wildcard Doxygen-index.txt)
> 595 #ifneq (,$(wildcard $(ShakeNMake.DOXYGEN.INDEX)))
> 596 ########################################################################
> 597 # let's try to do doxygen stuff...
> 598 ########################################################################
> 599 # Set ShakeNMake.DOXYGEN.USE_DOT to 1 if you have 'dot' and want to
> 600 # use it in the doxygen stuff. It slows down the doc gen process
> 601 # significantly, but it looks nice.
> 602 ShakeNMake.DOXYGEN.USE_DOT ?= 0
> 603 ##################################################
> 604 PACKAGE.DIST_FILES += $(ShakeNMake.DOXYGEN.DOXYFILE_TEMPLATE) $(ShakeNMake.DOXYGEN.INDEX)
> 605
> 606 ShakeNMake.DOXYGEN.INCLUDE_DIRS = .
> 607
> 608 ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML = $(PACKAGE.NAME)-$(PACKAGE.VERSION)-doxygen-html
> 609 ShakeNMake.DOXYGEN.OUTPUT_DIR.LATEX = $(PACKAGE.NAME)-$(PACKAGE.VERSION)-doxygen-latex
> 610
> 611
> 612 ifneq (,$(ShakeNMake.BINS.LATEX))
> 613 ShakeNMake.DOXYGEN.GENERATE_LATEX ?= YES
> 614 else
> 615 ShakeNMake.DOXYGEN.GENERATE_LATEX ?= NO
> 616 endif
> 617
> 618 Doxyfile: $(ShakeNMake.DOXYGEN.DOXYFILE_TEMPLATE) $(ShakeNMake.MAKEFILE) $(PACKAGE.MAKEFILE)
> 619 @$(ShakeNMake.BINS.SED) -e 's,@PACKAGE_NAME@,$(PACKAGE.NAME),' \
> 620 -e 's,@PACKAGE_VERSION@,$(PACKAGE.VERSION),' \
> 621 -e 's,@DOXYGEN_INPUT@,$(ShakeNMake.DOXYGEN.INDEX) $(ShakeNMake.DOXYGEN.INCLUDE_DIRS),' \
> 622 -e 's,@HTML_OUTPUT@,$(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML),' \
> 623 -e 's,@LATEX_OUTPUT@,$(ShakeNMake.DOXYGEN.OUTPUT_DIR.LATEX),' \
> 624 -e 's,@GENERATE_LATEX@,$(ShakeNMake.DOXYGEN.GENERATE_LATEX),' \
> 625 -e 's,@PERL@,$(ShakeNMake.BINS.PERL),' \
> 626 -e 's,@USE_DOT@,$(ShakeNMake.DOXYGEN.USE_DOT),' \
> 627 < $(ShakeNMake.DOXYGEN.DOXYFILE_TEMPLATE) > $@
> 628
> 629 doxygen-clean:
> 630 @test -d $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML) && rm -fr $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML); \
> 631 rm -f Doxyfile; \
> 632 true
> 633
> 634 .PHONY: $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML)
> 635 $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML): Doxyfile
> 636 @echo "Building docs from headers"
> 637 $(ShakeNMake.BINS.DOXYGEN)
> 638 @echo "Output should be in the directory '$@'."
> 639 ifneq (NO,$(ShakeNMake.DOXYGEN.GENERATE_LATEX))
> 640 @echo "Latex output (if any) is in '$(ShakeNMake.DOXYGEN.OUTPUT_DIR.LATEX)'."
> 641 endif
> 642
> 643 doxygen: $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML)
> 644
> 645 doxygen-dist: doxygen
> 646 tar czf $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML).tar.gz $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML)
> 647 @ls -la $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML).tar.gz
> 648
> 649 dist: doxygen-dist
> 650 CLEAN_FILES += Doxyfile $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML) latex
> 651
> 652
> 653 INSTALL_DOXYGEN = $(ShakeNMake.DOXYGEN.OUTPUT_DIR.HTML)
> 654 INSTALL_DOXYGEN_DEST = $(prefix)/share/doc/$(PACKAGE.NAME)
> 655 install: doxygen
> 656 $(call ShakeNMake.CALL.RULES.INSTALL,DOXYGEN)
> 657
> 658 ##################################################
> 659 #endif # $(ShakeNMake.DOXYGEN.INDEX)
> 660 endif # $(ShakeNMake.DOXYGEN.DOXYFILE_TEMPLATE)
> 661 endif # $(ShakeNMake.BINS.DOXYGEN)
> 662 endif # $(ShakeNMake.BINS.PERL)
> 663 # end Doxygen
> 664 ########################################################################
> 665

Added test.c

Old () New (1c6347ab86cce2b5)
> 1 #include <stdio.h>
> 2 #include <stdlib.h>
> 3 #include "whprintf.h"
> 4
> 5 long my_fprintf_appender( void * arg, char const * data, long n )
> 6 {
> 7 FILE * fp = arg ? (FILE*)arg : 0;
> 8 if( ! fp || (n<0) ) return -1;
> 9 else if( ! n ) return 0;
> 10 //printf("Writing %ld bytes\n",n);
> 11 long ret = (long) fwrite( data, sizeof(char), n, fp );
> 12 return ret;
> 13 }
> 14
> 15 void my_printfv(char const * fmt, va_list vargs )
> 16 {
> 17 whprintfv( my_fprintf_appender, stdout, fmt, vargs );
> 18 }
> 19
> 20 void my_printf(char const * fmt, ...)
> 21 {
> 22 va_list vargs;
> 23 va_start(vargs,fmt);
> 24 //whprintf( my_fprintf_appender, stdout, fmt, vargs );
> 25 my_printfv( fmt, vargs );
> 26 va_end(vargs);
> 27 }
> 28
> 29 //#define MARKER my_printf("MARKER: %s:%d:%s():\n",__FILE__,__LINE__,__func__); my_printf
> 30 #define MARKER my_printf("MARKER: %s:%d:%s():\n",__FILE__,__LINE__,__func__); my_printf
> 31
> 32
> 33 int main( int argc, char ** argv )
> 34 {
> 35 MARKER("This output is created by whprintf(), redirected to stdout.\n");
> 36 MARKER("Done!");
> 37 return 0;
> 38 }

Added whprintf.c

Old () New (6f9af523c5dde2ed)
> 1 /************************************************************************
> 2 The printf-like implementation in this file is based on the one found
> 3 in the sqlite3 distribution is in the Public Domain.
> 4
> 5 This copy was forked for use with the clob API in Feb 2008 by Stephan
> 6 Beal (http://wanderinghorse.net/home/stephan/) and modified to send
> 7 its output to arbitrary targets via a callback mechanism. Also
> 8 refactored the %X specifier handlers a bit to make adding/removing
> 9 specific handlers easier.
> 10
> 11 All code in this file is released into the Public Domain.
> 12
> 13 The printf implementation (whprintfv()) is pretty easy to extend
> 14 (e.g. adding or removing %-specifiers for whprintfv()) if you're
> 15 willing to poke around a bit and see how the specifiers are declared
> 16 and dispatched. For an example, grep for 'etSTRING' and follow it
> 17 through the process of declaration to implementation.
> 18
> 19 See below for several WHPRINTF_OMIT_xxx macros which can be set to
> 20 remove certain features/extensions.
> 21 ************************************************************************/
> 22
> 23 #include <stdio.h> /* FILE */
> 24 #include <string.h> /* strlen() */
> 25 #include <stdlib.h> /* free/malloc() */
> 26 #include <ctype.h>
> 27
> 28 #include "vappendf.h"
> 29 typedef long double LONGDOUBLE_TYPE;
> 30
> 31 /*
> 32 If WHPRINTF_OMIT_FLOATING_POINT is defined to a true value, then
> 33 floating point conversions are disabled.
> 34 */
> 35 #ifndef WHPRINTF_OMIT_FLOATING_POINT
> 36 # define WHPRINTF_OMIT_FLOATING_POINT 0
> 37 #endif
> 38
> 39 /*
> 40 If WHPRINTF_OMIT_SIZE is defined to a true value, then
> 41 the %n specifier is disabled.
> 42 */
> 43 #ifndef WHPRINTF_OMIT_SIZE
> 44 # define WHPRINTF_OMIT_SIZE 0
> 45 #endif
> 46
> 47 /*
> 48 If WHPRINTF_OMIT_SQL is defined to a true value, then
> 49 the %q and %Q specifiers are disabled.
> 50 */
> 51 #ifndef WHPRINTF_OMIT_SQL
> 52 # define WHPRINTF_OMIT_SQL 0
> 53 #endif
> 54
> 55 /*
> 56 If WHPRINTF_OMIT_HTML is defined to a true value then the %h (HTML
> 57 escape), %t (URL escape), and %T (URL unescape) specifiers are
> 58 disabled.
> 59 */
> 60 #ifndef WHPRINTF_OMIT_HTML
> 61 # define WHPRINTF_OMIT_HTML 0
> 62 #endif
> 63
> 64 /*
> 65 Most C compilers handle variable-sized arrays, so we enable
> 66 that by default. Some (e.g. tcc) do not, so we provide a way
> 67 to disable it: set WHPRINTF_HAVE_VARARRAY to 0
> 68
> 69 One approach would be to look at:
> 70
> 71 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
> 72
> 73 but some compilers support variable-sized arrays even when not
> 74 explicitly running in c99 mode.
> 75 */
> 76 #if !defined(WHPRINTF_HAVE_VARARRAY)
> 77 # if defined(__TINYC__)
> 78 # define WHPRINTF_HAVE_VARARRAY 0
> 79 # else
> 80 # define WHPRINTF_HAVE_VARARRAY 1
> 81 # endif
> 82 #endif
> 83
> 84 /**
> 85 WHPRINTF_CHARARRAY is a helper to allocate variable-sized arrays.
> 86 This exists mainly so this code can compile with the tcc compiler.
> 87 */
> 88 #if WHPRINTF_HAVE_VARARRAY
> 89 # define WHPRINTF_CHARARRAY(V,N) char V[N+1]; memset(V,0,N+1);
> 90 # define WHPRINTF_CHARARRAY_FREE(V)
> 91 #else
> 92 # define WHPRINTF_CHARARRAY(V,N) char * V = (char *)malloc(N+1); memset(V,0,N+1);
> 93 # define WHPRINTF_CHARARRAY_FREE(V) free(V)
> 94 #endif
> 95
> 96 /*
> 97 Conversion types fall into various categories as defined by the
> 98 following enumeration.
> 99 */
> 100 enum PrintfCategory {etRADIX = 1, /* Integer types. %d, %x, %o, and so forth */
> 101 etFLOAT = 2, /* Floating point. %f */
> 102 etEXP = 3, /* Exponentional notation. %e and %E */
> 103 etGENERIC = 4, /* Floating or exponential, depending on exponent. %g */
> 104 etSIZE = 5, /* Return number of characters processed so far. %n */
> 105 etSTRING = 6, /* Strings. %s */
> 106 etDYNSTRING = 7, /* Dynamically allocated strings. %z */
> 107 etPERCENT = 8, /* Percent symbol. %% */
> 108 etCHARX = 9, /* Characters. %c */
> 109 /* The rest are extensions, not normally found in printf() */
> 110 etCHARLIT = 10, /* Literal characters. %' */
> 111 #if !WHPRINTF_OMIT_SQL
> 112 etSQLESCAPE = 11, /* Strings with '\'' doubled. %q */
> 113 etSQLESCAPE2 = 12, /* Strings with '\'' doubled and enclosed in '',
> 114 NULL pointers replaced by SQL NULL. %Q */
> 115 etSQLESCAPE3 = 16, /* %w -> Strings with '\"' doubled */
> 116 #endif /* !WHPRINTF_OMIT_SQL */
> 117 etPOINTER = 15, /* The %p conversion */
> 118 etORDINAL = 17, /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
> 119 #if ! WHPRINTF_OMIT_HTML
> 120 etHTML = 18, /* %h -> basic HTML escaping. */
> 121 etURLENCODE = 19, /* %t -> URL encoding. */
> 122 etURLDECODE = 20, /* %T -> URL decoding. */
> 123 #endif
> 124 etPLACEHOLDER = 100
> 125 };
> 126
> 127 /*
> 128 An "etByte" is an 8-bit unsigned value.
> 129 */
> 130 typedef unsigned char etByte;
> 131
> 132 /*
> 133 Each builtin conversion character (ex: the 'd' in "%d") is described
> 134 by an instance of the following structure
> 135 */
> 136 typedef struct et_info { /* Information about each format field */
> 137 char fmttype; /* The format field code letter */
> 138 etByte base; /* The base for radix conversion */
> 139 etByte flags; /* One or more of FLAG_ constants below */
> 140 etByte type; /* Conversion paradigm */
> 141 etByte charset; /* Offset into aDigits[] of the digits string */
> 142 etByte prefix; /* Offset into aPrefix[] of the prefix string */
> 143 } et_info;
> 144
> 145 /*
> 146 Allowed values for et_info.flags
> 147 */
> 148 enum et_info_flags { FLAG_SIGNED = 1, /* True if the value to convert is signed */
> 149 FLAG_EXTENDED = 2, /* True if for internal/extended use only. */
> 150 FLAG_STRING = 4 /* Allow infinity precision */
> 151 };
> 152
> 153 /*
> 154 Historically, the following table was searched linearly, so the most
> 155 common conversions were kept at the front.
> 156
> 157 Change 2008 Oct 31 by Stephan Beal: we reserve an array or ordered
> 158 entries for all chars in the range [32..126]. Format character
> 159 checks can now be done in constant time by addressing that array
> 160 directly. This takes more static memory, but reduces the time and
> 161 per-call overhead costs of whprintfv().
> 162 */
> 163 static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
> 164 static const char aPrefix[] = "-x0\000X0";
> 165 static const et_info fmtinfo[] = {
> 166 /**
> 167 If WHPRINTF_FMTINFO_FIXED is 1 then we use the original
> 168 implementation: a linear list of entries. Search time is linear. If
> 169 WHPRINTF_FMTINFO_FIXED is 0 then we use a fixed-size array which
> 170 we index directly using the format char as the key.
> 171 */
> 172 #define WHPRINTF_FMTINFO_FIXED 0
> 173 #if WHPRINTF_FMTINFO_FIXED
> 174 { 'd', 10, FLAG_SIGNED, etRADIX, 0, 0 },
> 175 { 's', 0, FLAG_STRING, etSTRING, 0, 0 },
> 176 { 'g', 0, FLAG_SIGNED, etGENERIC, 30, 0 },
> 177 { 'z', 0, FLAG_STRING, etDYNSTRING, 0, 0 },
> 178 { 'c', 0, 0, etCHARX, 0, 0 },
> 179 { 'o', 8, 0, etRADIX, 0, 2 },
> 180 { 'u', 10, 0, etRADIX, 0, 0 },
> 181 { 'x', 16, 0, etRADIX, 16, 1 },
> 182 { 'X', 16, 0, etRADIX, 0, 4 },
> 183 { 'i', 10, FLAG_SIGNED, etRADIX, 0, 0 },
> 184 #if !WHPRINTF_OMIT_FLOATING_POINT
> 185 { 'f', 0, FLAG_SIGNED, etFLOAT, 0, 0 },
> 186 { 'e', 0, FLAG_SIGNED, etEXP, 30, 0 },
> 187 { 'E', 0, FLAG_SIGNED, etEXP, 14, 0 },
> 188 { 'G', 0, FLAG_SIGNED, etGENERIC, 14, 0 },
> 189 #endif /* !WHPRINTF_OMIT_FLOATING_POINT */
> 190 { '%', 0, 0, etPERCENT, 0, 0 },
> 191 { 'p', 16, 0, etPOINTER, 0, 1 },
> 192 { 'r', 10, (FLAG_EXTENDED|FLAG_SIGNED), etORDINAL, 0, 0 },
> 193 #if ! WHPRINTF_OMIT_SQL
> 194 { 'q', 0, FLAG_STRING, etSQLESCAPE, 0, 0 },
> 195 { 'Q', 0, FLAG_STRING, etSQLESCAPE2, 0, 0 },
> 196 { 'w', 0, FLAG_STRING, etSQLESCAPE3, 0, 0 },
> 197 #endif /* !WHPRINTF_OMIT_SQL */
> 198 #if ! WHPRINTF_OMIT_HTML
> 199 { 'h', 0, FLAG_STRING, etHTML, 0, 0 },
> 200 { 't', 0, FLAG_STRING, etURLENCODE, 0, 0 },
> 201 { 'T', 0, FLAG_STRING, etURLDECODE, 0, 0 },
> 202 #endif /* !WHPRINTF_OMIT_HTML */
> 203 #if !WHPRINTF_OMIT_SIZE
> 204 { 'n', 0, 0, etSIZE, 0, 0 },
> 205 #endif
> 206 #else /* WHPRINTF_FMTINFO_FIXED */
> 207 /*
> 208 These entries MUST stay in ASCII order, sorted
> 209 on their fmttype member!
> 210 */
> 211 {' '/*32*/, 0, 0, 0, 0, 0 },
> 212 {'!'/*33*/, 0, 0, 0, 0, 0 },
> 213 {'"'/*34*/, 0, 0, 0, 0, 0 },
> 214 {'#'/*35*/, 0, 0, 0, 0, 0 },
> 215 {'$'/*36*/, 0, 0, 0, 0, 0 },
> 216 {'%'/*37*/, 0, 0, etPERCENT, 0, 0 },
> 217 {'&'/*38*/, 0, 0, 0, 0, 0 },
> 218 {'\''/*39*/, 0, 0, 0, 0, 0 },
> 219 {'('/*40*/, 0, 0, 0, 0, 0 },
> 220 {')'/*41*/, 0, 0, 0, 0, 0 },
> 221 {'*'/*42*/, 0, 0, 0, 0, 0 },
> 222 {'+'/*43*/, 0, 0, 0, 0, 0 },
> 223 {','/*44*/, 0, 0, 0, 0, 0 },
> 224 {'-'/*45*/, 0, 0, 0, 0, 0 },
> 225 {'.'/*46*/, 0, 0, 0, 0, 0 },
> 226 {'/'/*47*/, 0, 0, 0, 0, 0 },
> 227 {'0'/*48*/, 0, 0, 0, 0, 0 },
> 228 {'1'/*49*/, 0, 0, 0, 0, 0 },
> 229 {'2'/*50*/, 0, 0, 0, 0, 0 },
> 230 {'3'/*51*/, 0, 0, 0, 0, 0 },
> 231 {'4'/*52*/, 0, 0, 0, 0, 0 },
> 232 {'5'/*53*/, 0, 0, 0, 0, 0 },
> 233 {'6'/*54*/, 0, 0, 0, 0, 0 },
> 234 {'7'/*55*/, 0, 0, 0, 0, 0 },
> 235 {'8'/*56*/, 0, 0, 0, 0, 0 },
> 236 {'9'/*57*/, 0, 0, 0, 0, 0 },
> 237 {':'/*58*/, 0, 0, 0, 0, 0 },
> 238 {';'/*59*/, 0, 0, 0, 0, 0 },
> 239 {'<'/*60*/, 0, 0, 0, 0, 0 },
> 240 {'='/*61*/, 0, 0, 0, 0, 0 },
> 241 {'>'/*62*/, 0, 0, 0, 0, 0 },
> 242 {'?'/*63*/, 0, 0, 0, 0, 0 },
> 243 {'@'/*64*/, 0, 0, 0, 0, 0 },
> 244 {'A'/*65*/, 0, 0, 0, 0, 0 },
> 245 {'B'/*66*/, 0, 0, 0, 0, 0 },
> 246 {'C'/*67*/, 0, 0, 0, 0, 0 },
> 247 {'D'/*68*/, 0, 0, 0, 0, 0 },
> 248 {'E'/*69*/, 0, FLAG_SIGNED, etEXP, 14, 0 },
> 249 {'F'/*70*/, 0, 0, 0, 0, 0 },
> 250 {'G'/*71*/, 0, FLAG_SIGNED, etGENERIC, 14, 0 },
> 251 {'H'/*72*/, 0, 0, 0, 0, 0 },
> 252 {'I'/*73*/, 0, 0, 0, 0, 0 },
> 253 {'J'/*74*/, 0, 0, 0, 0, 0 },
> 254 {'K'/*75*/, 0, 0, 0, 0, 0 },
> 255 {'L'/*76*/, 0, 0, 0, 0, 0 },
> 256 {'M'/*77*/, 0, 0, 0, 0, 0 },
> 257 {'N'/*78*/, 0, 0, 0, 0, 0 },
> 258 {'O'/*79*/, 0, 0, 0, 0, 0 },
> 259 {'P'/*80*/, 0, 0, 0, 0, 0 },
> 260 {'Q'/*81*/, 0, FLAG_STRING, etSQLESCAPE2, 0, 0 },
> 261 {'R'/*82*/, 0, 0, 0, 0, 0 },
> 262 {'S'/*83*/, 0, 0, 0, 0, 0 },
> 263 {'T'/*84*/, 0, FLAG_STRING, etURLDECODE, 0, 0 },
> 264 {'U'/*85*/, 0, 0, 0, 0, 0 },
> 265 {'V'/*86*/, 0, 0, 0, 0, 0 },
> 266 {'W'/*87*/, 0, 0, 0, 0, 0 },
> 267 {'X'/*88*/, 16, 0, etRADIX, 0, 4 },
> 268 {'Y'/*89*/, 0, 0, 0, 0, 0 },
> 269 {'Z'/*90*/, 0, 0, 0, 0, 0 },
> 270 {'['/*91*/, 0, 0, 0, 0, 0 },
> 271 {'\\'/*92*/, 0, 0, 0, 0, 0 },
> 272 {']'/*93*/, 0, 0, 0, 0, 0 },
> 273 {'^'/*94*/, 0, 0, 0, 0, 0 },
> 274 {'_'/*95*/, 0, 0, 0, 0, 0 },
> 275 {'`'/*96*/, 0, 0, 0, 0, 0 },
> 276 {'a'/*97*/, 0, 0, 0, 0, 0 },
> 277 {'b'/*98*/, 0, 0, 0, 0, 0 },
> 278 {'c'/*99*/, 0, 0, etCHARX, 0, 0 },
> 279 {'d'/*100*/, 10, FLAG_SIGNED, etRADIX, 0, 0 },
> 280 {'e'/*101*/, 0, FLAG_SIGNED, etEXP, 30, 0 },
> 281 {'f'/*102*/, 0, FLAG_SIGNED, etFLOAT, 0, 0},
> 282 {'g'/*103*/, 0, FLAG_SIGNED, etGENERIC, 30, 0 },
> 283 {'h'/*104*/, 0, FLAG_STRING, etHTML, 0, 0 },
> 284 {'i'/*105*/, 10, FLAG_SIGNED, etRADIX, 0, 0},
> 285 {'j'/*106*/, 0, 0, 0, 0, 0 },
> 286 {'k'/*107*/, 0, 0, 0, 0, 0 },
> 287 {'l'/*108*/, 0, 0, 0, 0, 0 },
> 288 {'m'/*109*/, 0, 0, 0, 0, 0 },
> 289 {'n'/*110*/, 0, 0, etSIZE, 0, 0 },
> 290 {'o'/*111*/, 8, 0, etRADIX, 0, 2 },
> 291 {'p'/*112*/, 16, 0, etPOINTER, 0, 1 },
> 292 {'q'/*113*/, 0, FLAG_STRING, etSQLESCAPE, 0, 0 },
> 293 {'r'/*114*/, 10, (FLAG_EXTENDED|FLAG_SIGNED), etORDINAL, 0, 0},
> 294 {'s'/*115*/, 0, FLAG_STRING, etSTRING, 0, 0 },
> 295 {'t'/*116*/, 0, FLAG_STRING, etURLENCODE, 0, 0 },
> 296 {'u'/*117*/, 10, 0, etRADIX, 0, 0 },
> 297 {'v'/*118*/, 0, 0, 0, 0, 0 },
> 298 {'w'/*119*/, 0, FLAG_STRING, etSQLESCAPE3, 0, 0 },
> 299 {'x'/*120*/, 16, 0, etRADIX, 16, 1 },
> 300 {'y'/*121*/, 0, 0, 0, 0, 0 },
> 301 {'z'/*122*/, 0, FLAG_STRING, etDYNSTRING, 0, 0},
> 302 {'{'/*123*/, 0, 0, 0, 0, 0 },
> 303 {'|'/*124*/, 0, 0, 0, 0, 0 },
> 304 {'}'/*125*/, 0, 0, 0, 0, 0 },
> 305 {'~'/*126*/, 0, 0, 0, 0, 0 },
> 306 #endif /* WHPRINTF_FMTINFO_FIXED */
> 307 };
> 308 #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
> 309
> 310 #if ! WHPRINTF_OMIT_FLOATING_POINT
> 311 /*
> 312 "*val" is a double such that 0.1 <= *val < 10.0
> 313 Return the ascii code for the leading digit of *val, then
> 314 multiply "*val" by 10.0 to renormalize.
> 315 **
> 316 Example:
> 317 input: *val = 3.14159
> 318 output: *val = 1.4159 function return = '3'
> 319 **
> 320 The counter *cnt is incremented each time. After counter exceeds
> 321 16 (the number of significant digits in a 64-bit float) '0' is
> 322 always returned.
> 323 */
> 324 static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
> 325 int digit;
> 326 LONGDOUBLE_TYPE d;
> 327 if( (*cnt)++ >= 16 ) return '0';
> 328 digit = (int)*val;
> 329 d = digit;
> 330 digit += '0';
> 331 *val = (*val - d)*10.0;
> 332 return digit;
> 333 }
> 334 #endif /* !WHPRINTF_OMIT_FLOATING_POINT */
> 335
> 336 /*
> 337 On machines with a small(?) stack size, you can redefine the
> 338 WHPRINTF_BUF_SIZE to be less than 350. But beware - for smaller
> 339 values some %f conversions may go into an infinite loop.
> 340 */
> 341 #ifndef WHPRINTF_BUF_SIZE
> 342 # define WHPRINTF_BUF_SIZE 350 /* Size of the output buffer for numeric conversions */
> 343 #endif
> 344
> 345 #ifdef WHPRINTF_INT64_TYPE
> 346 typedef WHPRINTF_INT64_TYPE int64_t;
> 347 typedef unsigned WHPRINTF_INT64_TYPE uint64_t;
> 348 #elif defined(_MSC_VER) || defined(__BORLANDC__)
> 349 typedef __int64 int64_t;
> 350 typedef unsigned __int64 uint64_t;
> 351 #else
> 352 typedef long long int int64_t;
> 353 typedef unsigned long long int uint64_t;
> 354 #endif
> 355
> 356 #if 0
> 357 / Not yet used. */
> 358 enum PrintfArgTypes {
> 359 TypeInt = 0,
> 360 TypeIntP = 1,
> 361 TypeFloat = 2,
> 362 TypeFloatP = 3,
> 363 TypeCString = 4
> 364 };
> 365 #endif
> 366
> 367
> 368 #if 0
> 369 / Not yet used. */
> 370 typedef struct whprintf_spec_handler_def
> 371 {
> 372 char letter; / e.g. %s */
> 373 int xtype; /* reference to the etXXXX values, or fmtinfo[*].type. */
> 374 int ntype; /* reference to PrintfArgTypes enum. */
> 375 } spec_handler;
> 376 #endif
> 377
> 378 /**
> 379 whprintf_spec_handler is an almost-generic interface for farming
> 380 work out of whprintfv()'s code into external functions. It doesn't
> 381 actually save much (if any) overall code, but it makes the whprintfv()
> 382 code more manageable.
> 383
> 384
> 385 REQUIREMENTS of implementations:
> 386
> 387 - Expects an implementation-specific vargp pointer.
> 388 whprintfv() passes a pointer to the converted value of
> 389 an entry from the format va_list. If it passes a type
> 390 other than the expected one, undefined results.
> 391
> 392 - If it calls pf then it must return the return value
> 393 from that function.
> 394
> 395 - If it calls pf it must do: pf( pfArg, D, N ), where D is
> 396 the data to export and N is the number of bytes to export.
> 397 It may call pf() an arbitrary number of times
> 398
> 399 - If pf() successfully is called, the return value must be the
> 400 accumulated totals of its return value(s), plus (possibly, but
> 401 unlikely) an imnplementation-specific amount.
> 402
> 403 - If it does not call pf() then it must return 0 (success)
> 404 or a negative number (an error) or do all of the export
> 405 processing itself and return the number of bytes exported.
> 406
> 407
> 408 SIGNIFICANT LIMITATIONS:
> 409
> 410 - Has no way of iterating over the format string,
> 411 so handling precisions and such here can't work too
> 412 well.
> 413 */
> 414 typedef long (*whprintf_spec_handler)( whprintf_appender pf,
> 415 void * pfArg,
> 416 void * vargp );
> 417
> 418
> 419 /**
> 420 whprintf_spec_handler for etSTRING types. It assumes that varg is a
> 421 null-terminated (char [const] *)
> 422 */
> 423 static long spech_string( whprintf_appender pf,
> 424 void * pfArg,
> 425 void * varg )
> 426 {
> 427 char const * ch = (char const *) varg;
> 428 return ch ? pf( pfArg, ch, strlen(ch) ) : 0;
> 429 }
> 430
> 431 /**
> 432 whprintf_spec_handler for etDYNSTRING types. It assumes that varg
> 433 is a non-const (char *). It behaves identically to spec_string() and
> 434 then calls free() on that (char *).
> 435 */
> 436 static long spech_dynstring( whprintf_appender pf,
> 437 void * pfArg,
> 438 void * varg )
> 439 {
> 440 long ret = spech_string( pf, pfArg, varg );
> 441 free( (char *) varg );
> 442 return ret;
> 443 }
> 444
> 445 #if !WHPRINTF_OMIT_HTML
> 446 static long spech_string_to_html( whprintf_appender pf,
> 447 void * pfArg,
> 448 void * varg )
> 449 {
> 450 char const * ch = (char const *) varg;
> 451 long ret = 0;
> 452 if( ! ch ) return 0;
> 453 ret = 0;
> 454 for( ; *ch; ++ch )
> 455 {
> 456 switch( *ch )
> 457 {
> 458 case '<': ret += pf( pfArg, "&lt;", 4 );
> 459 break;
> 460 case '&': ret += pf( pfArg, "&amp;", 5 );
> 461 break;
> 462 default:
> 463 ret += pf( pfArg, ch, 1 );
> 464 break;
> 465 };
> 466 }
> 467 return ret;
> 468 }
> 469
> 470 static int httpurl_needs_escape( int c )
> 471 {
> 472 /*
> 473 Definition of "safe" and "unsafe" chars
> 474 was taken from:
> 475
> 476 http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4029/
> 477 */
> 478 return ( (c >= 32 && c <=47)
> 479 || ( c>=58 && c<=64)
> 480 || ( c>=91 && c<=96)
> 481 || ( c>=123 && c<=126)
> 482 || ( c<32 || c>=127)
> 483 );
> 484 }
> 485
> 486 /**
> 487 The handler for the etURLENCODE specifier.
> 488
> 489 It expects varg to be a string value, which it will preceed to
> 490 encode using an URL encoding algothrim (certain characters are
> 491 converted to %XX, where XX is their hex value) and passes the
> 492 encoded string to pf(). It returns the total length of the output
> 493 string.
> 494 */
> 495 static long spech_urlencode( whprintf_appender pf,
> 496 void * pfArg,
> 497 void * varg )
> 498 {
> 499 char const * str = (char const *) varg;
> 500 long ret = 0;
> 501 char ch = 0;
> 502 char const * hex = "0123456789ABCDEF";
> 503 #define xbufsz 10
> 504 char xbuf[xbufsz];
> 505 int slen = 0;
> 506 if( ! str ) return 0;
> 507 memset( xbuf, 0, xbufsz );
> 508 ch = *str;
> 509 #define xbufsz 10
> 510 slen = 0;
> 511 for( ; ch; ch = *(++str) )
> 512 {
> 513 if( ! httpurl_needs_escape( ch ) )
> 514 {
> 515 ret += pf( pfArg, str, 1 );
> 516 continue;
> 517 }
> 518 else {
> 519 slen = snprintf( xbuf, xbufsz, "%%%c%c",
> 520 hex[((ch>>4)&0xf)],
> 521 hex[(ch&0xf)]);
> 522 ret += pf( pfArg, xbuf, slen );
> 523 }
> 524 }
> 525 #undef xbufsz
> 526 return ret;
> 527 }
> 528
> 529 /*
> 530 hexchar_to_int():
> 531
> 532 For 'a'-'f', 'A'-'F' and '0'-'9', returns the appropriate decimal
> 533 number. For any other character it returns -1.
> 534 */
> 535 static int hexchar_to_int( int ch )
> 536 {
> 537 if( (ch>='a' && ch<='f') ) return ch-'a'+10;
> 538 else if( (ch>='A' && ch<='F') ) return ch-'A'+10;
> 539 else if( (ch>='0' && ch<='9') ) return ch-'0';
> 540 return -1;
> 541 }
> 542
> 543 /**
> 544 The handler for the etURLDECODE specifier.
> 545
> 546 It expects varg to be a ([const] char *), possibly encoded
> 547 with URL encoding. It decodes the string using a URL decode
> 548 algorithm and passes the decoded string to
> 549 pf(). It returns the total length of the output string.
> 550 If the input string contains malformed %XX codes then this
> 551 function will return prematurely.
> 552 */
> 553 static long spech_urldecode( whprintf_appender pf,
> 554 void * pfArg,
> 555 void * varg )
> 556 {
> 557 char const * str = (char const *) varg;
> 558 if( ! str ) return 0;
> 559 long ret = 0;
> 560 char ch = 0;
> 561 char ch2 = 0;
> 562 char xbuf[4];
> 563 int decoded;
> 564 ch = *str;
> 565 while( ch )
> 566 {
> 567 if( ch == '%' )
> 568 {
> 569 ch = *(++str);
> 570 ch2 = *(++str);
> 571 if( isxdigit(ch) &&
> 572 isxdigit(ch2) )
> 573 {
> 574 decoded = (hexchar_to_int( ch ) * 16)
> 575 + hexchar_to_int( ch2 );
> 576 //printf("DECODED: %s, %d, %c\n", xbuf, decoded, (char) decoded );
> 577 xbuf[0] = (char)decoded;
> 578 xbuf[1] = 0;
> 579 ret += pf( pfArg, xbuf, 1 );
> 580 ch = *(++str);
> 581 continue;
> 582 }
> 583 else
> 584 {
> 585 xbuf[0] = '%';
> 586 xbuf[1] = ch;
> 587 xbuf[2] = ch2;
> 588 xbuf[3] = 0;
> 589 ret += pf( pfArg, xbuf, 3 );
> 590 ch = *(++str);
> 591 continue;
> 592 }
> 593 }
> 594 else if( ch == '+' )
> 595 {
> 596 xbuf[0] = ' ';
> 597 xbuf[1] = 0;
> 598 ret += pf( pfArg, xbuf, 1 );
> 599 ch = *(++str);
> 600 continue;
> 601 }
> 602 xbuf[0] = ch;
> 603 xbuf[1] = 0;
> 604 ret += pf( pfArg, xbuf, 1 );
> 605 ch = *(++str);
> 606 }
> 607 return ret;
> 608 }
> 609
> 610 #endif /* !WHPRINTF_OMIT_HTML */
> 611
> 612
> 613 #if !WHPRINTF_OMIT_SQL
> 614 /**
> 615 Quotes the (char *) varg as an SQL string 'should'
> 616 be quoted. The exact type of the conversion
> 617 is specified by xtype, which must be one of
> 618 etSQLESCAPE, etSQLESCAPE2, or etSQLESCAPE3.
> 619
> 620 Search this file for those constants to find
> 621 the associated documentation.
> 622 */
> 623 static long spech_sqlstring_main( int xtype,
> 624 whprintf_appender pf,
> 625 void * pfArg,
> 626 void * varg )
> 627 {
> 628 int i, j, n, ch, isnull;
> 629 int needQuote;
> 630 char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
> 631 char const * escarg = (char const *) varg;
> 632 char * bufpt = 0;
> 633 isnull = escarg==0;
> 634 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
> 635 for(i=n=0; (ch=escarg[i])!=0; i++){
> 636 if( ch==q ) n++;
> 637 }
> 638 needQuote = !isnull && xtype==etSQLESCAPE2;
> 639 n += i + 1 + needQuote*2;
> 640 bufpt = (char *)malloc( n );
> 641 if( ! bufpt ) return -1;
> 642 j = 0;
> 643 if( needQuote ) bufpt[j++] = q;
> 644 for(i=0; (ch=escarg[i])!=0; i++){
> 645 bufpt[j++] = ch;
> 646 if( ch==q ) bufpt[j++] = ch;
> 647 }
> 648 if( needQuote ) bufpt[j++] = q;
> 649 bufpt[j] = 0;
> 650 long ret = pf( pfArg, bufpt, j );
> 651 free( bufpt );
> 652 return ret;
> 653 }
> 654
> 655 static long spech_sqlstring1( whprintf_appender pf,
> 656 void * pfArg,
> 657 void * varg )
> 658 {
> 659 return spech_sqlstring_main( etSQLESCAPE, pf, pfArg, varg );
> 660 }
> 661
> 662 static long spech_sqlstring2( whprintf_appender pf,
> 663 void * pfArg,
> 664 void * varg )
> 665 {
> 666 return spech_sqlstring_main( etSQLESCAPE2, pf, pfArg, varg );
> 667 }
> 668
> 669 static long spech_sqlstring3( whprintf_appender pf,
> 670 void * pfArg,
> 671 void * varg )
> 672 {
> 673 return spech_sqlstring_main( etSQLESCAPE3, pf, pfArg, varg );
> 674 }
> 675
> 676 #endif /* !WHPRINTF_OMIT_SQL */
> 677
> 678
> 679
> 680 /*
> 681 The root printf program. All variations call this core. It
> 682 implements most of the common printf behaviours plus (optionally)
> 683 some extended ones.
> 684
> 685 INPUTS:
> 686
> 687 pfAppend : The is a whprintf_appender function which is responsible
> 688 for accumulating the output. If pfAppend returns a negative integer
> 689 then processing stops immediately.
> 690
> 691 pfAppendArg : is ignored by this function but passed as the first
> 692 argument to pfAppend. pfAppend will presumably use it as a data
> 693 store for accumulating its string.
> 694
> 695 fmt : This is the format string, as in the usual printf().
> 696
> 697 ap : This is a pointer to a list of arguments. Same as in
> 698 vprintf() and friends.
> 699
> 700 OUTPUTS:
> 701
> 702 The return value is the total number of characters sent to the
> 703 function "func". Returns -1 on a error.
> 704
> 705 Note that the order in which automatic variables are declared below
> 706 seems to make a big difference in determining how fast this beast
> 707 will run.
> 708
> 709 Much of this code dates back to the early 1980's, supposedly.
> 710
> 711 Known change history (most historic info has been lost):
> 712
> 713 10 Feb 2008 by Stephan Beal: refactored to remove the 'useExtended'
> 714 flag (which is now always on). Added the whprintf_appender typedef to
> 715 make this function generic enough to drop into other source trees
> 716 without much work.
> 717
> 718 31 Oct 2008 by Stephan Beal: refactored the et_info lookup to be
> 719 constant-time instead of linear.
> 720 */
> 721 long whprintfv(
> 722 whprintf_appender pfAppend, /* Accumulate results here */
> 723 void * pfAppendArg, /* Passed as first arg to pfAppend. */
> 724 const char *fmt, /* Format string */
> 725 va_list ap /* arguments */
> 726 ){
> 727 /**
> 728 HISTORIC NOTE (author and year unknown):
> 729
> 730 Note that the order in which automatic variables are declared below
> 731 seems to make a big difference in determining how fast this beast
> 732 will run.
> 733 */
> 734
> 735 #if WHPRINTF_FMTINFO_FIXED
> 736 const int useExtended = 1; /* Allow extended %-conversions */
> 737 #endif
> 738 long outCount = 0; /* accumulated output count */
> 739 int pfrc = 0; /* result from calling pfAppend */
> 740 int c; /* Next character in the format string */
> 741 char *bufpt = 0; /* Pointer to the conversion buffer */
> 742 int precision; /* Precision of the current field */
> 743 int length; /* Length of the field */
> 744 int idx; /* A general purpose loop counter */
> 745 int width; /* Width of the current field */
> 746 etByte flag_leftjustify; /* True if "-" flag is present */
> 747 etByte flag_plussign; /* True if "+" flag is present */
> 748 etByte flag_blanksign; /* True if " " flag is present */
> 749 etByte flag_alternateform; /* True if "#" flag is present */
> 750 etByte flag_altform2; /* True if "!" flag is present */
> 751 etByte flag_zeropad; /* True if field width constant starts with zero */
> 752 etByte flag_long; /* True if "l" flag is present */
> 753 etByte flag_longlong; /* True if the "ll" flag is present */
> 754 etByte done; /* Loop termination flag */
> 755 uint64_t longvalue; /* Value for integer types */
> 756 LONGDOUBLE_TYPE realvalue; /* Value for real types */
> 757 const et_info *infop = 0; /* Pointer to the appropriate info structure */
> 758 char buf[WHPRINTF_BUF_SIZE]; /* Conversion buffer */
> 759 char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
> 760 etByte errorflag = 0; /* True if an error is encountered */
> 761 etByte xtype; /* Conversion paradigm */
> 762 char * zExtra = 0; /* Extra memory used for etTCLESCAPE conversions */
> 763 #if ! WHPRINTF_OMIT_FLOATING_POINT
> 764 int exp, e2; /* exponent of real numbers */
> 765 double rounder; /* Used for rounding floating point values */
> 766 etByte flag_dp; /* True if decimal point should be shown */
> 767 etByte flag_rtz; /* True if trailing zeros should be removed */
> 768 etByte flag_exp; /* True to force display of the exponent */
> 769 int nsd; /* Number of significant digits returned */
> 770 #endif
> 771
> 772
> 773 /* WHPRINTF_RETURN, WHPRINTF_CHECKERR, and WHPRINTF_SPACES
> 774 are internal helpers.
> 775 */
> 776 #define WHPRINTF_RETURN if( zExtra ) free(zExtra); return outCount;
> 777 #define WHPRINTF_CHECKERR(FREEME) if( pfrc<0 ) { WHPRINTF_CHARARRAY_FREE(FREEME); WHPRINTF_RETURN; } else outCount += pfrc;
> 778 #define WHPRINTF_SPACES(N) \
> 779 if(1){ \
> 780 WHPRINTF_CHARARRAY(zSpaces,N); \
> 781 memset( zSpaces,' ',N); \
> 782 pfrc = pfAppend(pfAppendArg, zSpaces, N); \
> 783 WHPRINTF_CHECKERR(zSpaces); \
> 784 WHPRINTF_CHARARRAY_FREE(zSpaces); \
> 785 }
> 786
> 787 length = 0;
> 788 bufpt = 0;
> 789 for(; (c=(*fmt))!=0; ++fmt){
> 790 if( c!='%' ){
> 791 int amt;
> 792 bufpt = (char *)fmt;
> 793 amt = 1;
> 794 while( (c=(*++fmt))!='%' && c!=0 ) amt++;
> 795 pfrc = pfAppend( pfAppendArg, bufpt, amt);
> 796 WHPRINTF_CHECKERR(0);
> 797 if( c==0 ) break;
> 798 }
> 799 if( (c=(*++fmt))==0 ){
> 800 errorflag = 1;
> 801 pfrc = pfAppend( pfAppendArg, "%", 1);
> 802 WHPRINTF_CHECKERR(0);
> 803 break;
> 804 }
> 805 /* Find out what flags are present */
> 806 flag_leftjustify = flag_plussign = flag_blanksign =
> 807 flag_alternateform = flag_altform2 = flag_zeropad = 0;
> 808 done = 0;
> 809 do{
> 810 switch( c ){
> 811 case '-': flag_leftjustify = 1; break;
> 812 case '+': flag_plussign = 1; break;
> 813 case ' ': flag_blanksign = 1; break;
> 814 case '#': flag_alternateform = 1; break;
> 815 case '!': flag_altform2 = 1; break;
> 816 case '0': flag_zeropad = 1; break;
> 817 default: done = 1; break;
> 818 }
> 819 }while( !done && (c=(*++fmt))!=0 );
> 820 /* Get the field width */
> 821 width = 0;
> 822 if( c=='*' ){
> 823 width = va_arg(ap,int);
> 824 if( width<0 ){
> 825 flag_leftjustify = 1;
> 826 width = -width;
> 827 }
> 828 c = *++fmt;
> 829 }else{
> 830 while( c>='0' && c<='9' ){
> 831 width = width*10 + c - '0';
> 832 c = *++fmt;
> 833 }
> 834 }
> 835 if( width > WHPRINTF_BUF_SIZE-10 ){
> 836 width = WHPRINTF_BUF_SIZE-10;
> 837 }
> 838 /* Get the precision */
> 839 if( c=='.' ){
> 840 precision = 0;
> 841 c = *++fmt;
> 842 if( c=='*' ){
> 843 precision = va_arg(ap,int);
> 844 if( precision<0 ) precision = -precision;
> 845 c = *++fmt;
> 846 }else{
> 847 while( c>='0' && c<='9' ){
> 848 precision = precision*10 + c - '0';
> 849 c = *++fmt;
> 850 }
> 851 }
> 852 }else{
> 853 precision = -1;
> 854 }
> 855 /* Get the conversion type modifier */
> 856 if( c=='l' ){
> 857 flag_long = 1;
> 858 c = *++fmt;
> 859 if( c=='l' ){
> 860 flag_longlong = 1;
> 861 c = *++fmt;
> 862 }else{
> 863 flag_longlong = 0;
> 864 }
> 865 }else{
> 866 flag_long = flag_longlong = 0;
> 867 }
> 868 /* Fetch the info entry for the field */
> 869 infop = 0;
> 870 #if WHPRINTF_FMTINFO_FIXED
> 871 for(idx=0; idx<etNINFO; idx++){
> 872 if( c==fmtinfo[idx].fmttype ){
> 873 infop = &fmtinfo[idx];
> 874 if( useExtended || (infop->flags & FLAG_EXTENDED)==0 ){
> 875 xtype = infop->type;
> 876 }else{
> 877 WHPRINTF_RETURN;
> 878 }
> 879 break;
> 880 }
> 881 }
> 882 #else
> 883 #define FMTNDX(N) (N - fmtinfo[0].fmttype)
> 884 #define FMTINFO(N) (fmtinfo[ FMTNDX(N) ])
> 885 infop = ((c>=(fmtinfo[0].fmttype)) && (c<fmtinfo[etNINFO-1].fmttype))
> 886 ? &FMTINFO(c)
> 887 : 0;
> 888 //fprintf(stderr,"char '%c'/%d @ %d, type=%c/%d\n",c,c,FMTNDX(c),infop->fmttype,infop->type);
> 889 if( infop ) xtype = infop->type;
> 890 #undef FMTINFO
> 891 #undef FMTNDX
> 892 #endif /* WHPRINTF_FMTINFO_FIXED */
> 893 zExtra = 0;
> 894 if( (!infop) || (!infop->type) ){
> 895 WHPRINTF_RETURN;
> 896 }
> 897
> 898
> 899 /* Limit the precision to prevent overflowing buf[] during conversion */
> 900 if( precision>WHPRINTF_BUF_SIZE-40 && (infop->flags & FLAG_STRING)==0 ){
> 901 precision = WHPRINTF_BUF_SIZE-40;
> 902 }
> 903
> 904 /*
> 905 At this point, variables are initialized as follows:
> 906 **
> 907 flag_alternateform TRUE if a '#' is present.
> 908 flag_altform2 TRUE if a '!' is present.
> 909 flag_plussign TRUE if a '+' is present.
> 910 flag_leftjustify TRUE if a '-' is present or if the
> 911 field width was negative.
> 912 flag_zeropad TRUE if the width began with 0.
> 913 flag_long TRUE if the letter 'l' (ell) prefixed
> 914 the conversion character.
> 915 flag_longlong TRUE if the letter 'll' (ell ell) prefixed
> 916 the conversion character.
> 917 flag_blanksign TRUE if a ' ' is present.
> 918 width The specified field width. This is
> 919 always non-negative. Zero is the default.
> 920 precision The specified precision. The default
> 921 is -1.
> 922 xtype The class of the conversion.
> 923 infop Pointer to the appropriate info struct.
> 924 */
> 925 switch( xtype ){
> 926 case etPOINTER:
> 927 flag_longlong = sizeof(char*)==sizeof(int64_t);
> 928 flag_long = sizeof(char*)==sizeof(long int);
> 929 /* Fall through into the next case */
> 930 case etORDINAL:
> 931 case etRADIX:
> 932 if( infop->flags & FLAG_SIGNED ){
> 933 int64_t v;
> 934 if( flag_longlong ) v = va_arg(ap,int64_t);
> 935 else if( flag_long ) v = va_arg(ap,long int);
> 936 else v = va_arg(ap,int);
> 937 if( v<0 ){
> 938 longvalue = -v;
> 939 prefix = '-';
> 940 }else{
> 941 longvalue = v;
> 942 if( flag_plussign ) prefix = '+';
> 943 else if( flag_blanksign ) prefix = ' ';
> 944 else prefix = 0;
> 945 }
> 946 }else{
> 947 if( flag_longlong ) longvalue = va_arg(ap,uint64_t);
> 948 else if( flag_long ) longvalue = va_arg(ap,unsigned long int);
> 949 else longvalue = va_arg(ap,unsigned int);
> 950 prefix = 0;
> 951 }
> 952 if( longvalue==0 ) flag_alternateform = 0;
> 953 if( flag_zeropad && precision<width-(prefix!=0) ){
> 954 precision = width-(prefix!=0);
> 955 }
> 956 bufpt = &buf[WHPRINTF_BUF_SIZE-1];
> 957 if( xtype==etORDINAL ){
> 958 /** i sure would like to shake the hand of whoever figured this out: */
> 959 static const char zOrd[] = "thstndrd";
> 960 int x = longvalue % 10;
> 961 if( x>=4 || (longvalue/10)%10==1 ){
> 962 x = 0;
> 963 }
> 964 buf[WHPRINTF_BUF_SIZE-3] = zOrd[x*2];
> 965 buf[WHPRINTF_BUF_SIZE-2] = zOrd[x*2+1];
> 966 bufpt -= 2;
> 967 }
> 968 {
> 969 const char *cset;
> 970 int base;
> 971 cset = &aDigits[infop->charset];
> 972 base = infop->base;
> 973 do{ /* Convert to ascii */
> 974 *(--bufpt) = cset[longvalue%base];
> 975 longvalue = longvalue/base;
> 976 }while( longvalue>0 );
> 977 }
> 978 length = &buf[WHPRINTF_BUF_SIZE-1]-bufpt;
> 979 for(idx=precision-length; idx>0; idx--){
> 980 *(--bufpt) = '0'; /* Zero pad */
> 981 }
> 982 if( prefix ) *(--bufpt) = prefix; /* Add sign */
> 983 if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
> 984 const char *pre;
> 985 char x;
> 986 pre = &aPrefix[infop->prefix];
> 987 if( *bufpt!=pre[0] ){
> 988 for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
> 989 }
> 990 }
> 991 length = &buf[WHPRINTF_BUF_SIZE-1]-bufpt;
> 992 break;
> 993 case etFLOAT:
> 994 case etEXP:
> 995 case etGENERIC:
> 996 realvalue = va_arg(ap,double);
> 997 #if ! WHPRINTF_OMIT_FLOATING_POINT
> 998 if( precision<0 ) precision = 6; /* Set default precision */
> 999 if( precision>WHPRINTF_BUF_SIZE/2-10 ) precision = WHPRINTF_BUF_SIZE/2-10;
> 1000 if( realvalue<0.0 ){
> 1001 realvalue = -realvalue;
> 1002 prefix = '-';
> 1003 }else{
> 1004 if( flag_plussign ) prefix = '+';
> 1005 else if( flag_blanksign ) prefix = ' ';
> 1006 else prefix = 0;
> 1007 }
> 1008 if( xtype==etGENERIC && precision>0 ) precision--;
> 1009 #if 0
> 1010 /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
> 1011 for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
> 1012 #else
> 1013 /* It makes more sense to use 0.5 */
> 1014 for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
> 1015 #endif
> 1016 if( xtype==etFLOAT ) realvalue += rounder;
> 1017 /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
> 1018 exp = 0;
> 1019 #if 1
> 1020 if( (realvalue)!=(realvalue) ){
> 1021 /* from sqlite3: #define sqlite3_isnan(X) ((X)!=(X)) */
> 1022 /* This weird array thing is to avoid constness violations
> 1023 when assinging, e.g. "NaN" to bufpt.
> 1024 */
> 1025 static char NaN[4] = {'N','a','N','\0'};
> 1026 bufpt = NaN;
> 1027 length = 3;
> 1028 break;
> 1029 }
> 1030 #endif
> 1031 if( realvalue>0.0 ){
> 1032 while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
> 1033 while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
> 1034 while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
> 1035 while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
> 1036 while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
> 1037 if( exp>350 || exp<-350 ){
> 1038 if( prefix=='-' ){
> 1039 static char Inf[5] = {'-','I','n','f','\0'};
> 1040 bufpt = Inf;
> 1041 }else if( prefix=='+' ){
> 1042 static char Inf[5] = {'+','I','n','f','\0'};
> 1043 bufpt = Inf;
> 1044 }else{
> 1045 static char Inf[4] = {'I','n','f','\0'};
> 1046 bufpt = Inf;
> 1047 }
> 1048 length = strlen(bufpt);
> 1049 break;
> 1050 }
> 1051 }
> 1052 bufpt = buf;
> 1053 /*
> 1054 If the field type is etGENERIC, then convert to either etEXP
> 1055 or etFLOAT, as appropriate.
> 1056 */
> 1057 flag_exp = xtype==etEXP;
> 1058 if( xtype!=etFLOAT ){
> 1059 realvalue += rounder;
> 1060 if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
> 1061 }
> 1062 if( xtype==etGENERIC ){
> 1063 flag_rtz = !flag_alternateform;
> 1064 if( exp<-4 || exp>precision ){
> 1065 xtype = etEXP;
> 1066 }else{
> 1067 precision = precision - exp;
> 1068 xtype = etFLOAT;
> 1069 }
> 1070 }else{
> 1071 flag_rtz = 0;
> 1072 }
> 1073 if( xtype==etEXP ){
> 1074 e2 = 0;
> 1075 }else{
> 1076 e2 = exp;
> 1077 }
> 1078 nsd = 0;
> 1079 flag_dp = (precision>0) | flag_alternateform | flag_altform2;
> 1080 /* The sign in front of the number */
> 1081 if( prefix ){
> 1082 *(bufpt++) = prefix;
> 1083 }
> 1084 /* Digits prior to the decimal point */
> 1085 if( e2<0 ){
> 1086 *(bufpt++) = '0';
> 1087 }else{
> 1088 for(; e2>=0; e2--){
> 1089 *(bufpt++) = et_getdigit(&realvalue,&nsd);
> 1090 }
> 1091 }
> 1092 /* The decimal point */
> 1093 if( flag_dp ){
> 1094 *(bufpt++) = '.';
> 1095 }
> 1096 /* "0" digits after the decimal point but before the first
> 1097 significant digit of the number */
> 1098 for(e2++; e2<0 && precision>0; precision--, e2++){
> 1099 *(bufpt++) = '0';
> 1100 }
> 1101 /* Significant digits after the decimal point */
> 1102 while( (precision--)>0 ){
> 1103 *(bufpt++) = et_getdigit(&realvalue,&nsd);
> 1104 }
> 1105 /* Remove trailing zeros and the "." if no digits follow the "." */
> 1106 if( flag_rtz && flag_dp ){
> 1107 while( bufpt[-1]=='0' ) *(--bufpt) = 0;
> 1108 /* assert( bufpt>buf ); */
> 1109 if( bufpt[-1]=='.' ){
> 1110 if( flag_altform2 ){
> 1111 *(bufpt++) = '0';
> 1112 }else{
> 1113 *(--bufpt) = 0;
> 1114 }
> 1115 }
> 1116 }
> 1117 /* Add the "eNNN" suffix */
> 1118 if( flag_exp || (xtype==etEXP && exp) ){
> 1119 *(bufpt++) = aDigits[infop->charset];
> 1120 if( exp<0 ){
> 1121 *(bufpt++) = '-'; exp = -exp;
> 1122 }else{
> 1123 *(bufpt++) = '+';
> 1124 }
> 1125 if( exp>=100 ){
> 1126 *(bufpt++) = (exp/100)+'0'; /* 100's digit */
> 1127 exp %= 100;
> 1128 }
> 1129 *(bufpt++) = exp/10+'0'; /* 10's digit */
> 1130 *(bufpt++) = exp%10+'0'; /* 1's digit */
> 1131 }
> 1132 *bufpt = 0;
> 1133
> 1134 /* The converted number is in buf[] and zero terminated. Output it.
> 1135 Note that the number is in the usual order, not reversed as with
> 1136 integer conversions. */
> 1137 length = bufpt-buf;
> 1138 bufpt = buf;
> 1139
> 1140 /* Special case: Add leading zeros if the flag_zeropad flag is
> 1141 set and we are not left justified */
> 1142 if( flag_zeropad && !flag_leftjustify && length < width){
> 1143 int i;
> 1144 int nPad = width - length;
> 1145 for(i=width; i>=nPad; i--){
> 1146 bufpt[i] = bufpt[i-nPad];
> 1147 }
> 1148 i = prefix!=0;
> 1149 while( nPad-- ) bufpt[i++] = '0';
> 1150 length = width;
> 1151 }
> 1152 #endif /* !WHPRINTF_OMIT_FLOATING_POINT */
> 1153 break;
> 1154 #if !WHPRINTF_OMIT_SIZE
> 1155 case etSIZE:
> 1156 *(va_arg(ap,int*)) = outCount;
> 1157 length = width = 0;
> 1158 break;
> 1159 #endif
> 1160 case etPERCENT:
> 1161 buf[0] = '%';
> 1162 bufpt = buf;
> 1163 length = 1;
> 1164 break;
> 1165 case etCHARLIT:
> 1166 case etCHARX:
> 1167 c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
> 1168 if( precision>=0 ){
> 1169 for(idx=1; idx<precision; idx++) buf[idx] = c;
> 1170 length = precision;
> 1171 }else{
> 1172 length =1;
> 1173 }
> 1174 bufpt = buf;
> 1175 break;
> 1176 case etSTRING:
> 1177 case etDYNSTRING: {
> 1178 bufpt = va_arg(ap,char*);
> 1179 whprintf_spec_handler spf = (xtype==etSTRING)
> 1180 ? spech_string : spech_dynstring;
> 1181 pfrc = spf( pfAppend, pfAppendArg, bufpt );
> 1182 WHPRINTF_CHECKERR(0);
> 1183 length = 0;
> 1184 if( precision>=0 && precision<length ) length = precision;
> 1185 }
> 1186 break;
> 1187 #if ! WHPRINTF_OMIT_HTML
> 1188 case etHTML:
> 1189 bufpt = va_arg(ap,char*);
> 1190 pfrc = spech_string_to_html( pfAppend, pfAppendArg, bufpt );
> 1191 WHPRINTF_CHECKERR(0);
> 1192 length = 0;
> 1193 break;
> 1194 case etURLENCODE:
> 1195 bufpt = va_arg(ap,char*);
> 1196 pfrc = spech_urlencode( pfAppend, pfAppendArg, bufpt );
> 1197 WHPRINTF_CHECKERR(0);
> 1198 length = 0;
> 1199 break;
> 1200 case etURLDECODE:
> 1201 bufpt = va_arg(ap,char *);
> 1202 pfrc = spech_urldecode( pfAppend, pfAppendArg, bufpt );
> 1203 WHPRINTF_CHECKERR(0);
> 1204 length = 0;
> 1205 break;
> 1206 #endif /* WHPRINTF_OMIT_HTML */
> 1207 #if ! WHPRINTF_OMIT_SQL
> 1208 case etSQLESCAPE:
> 1209 case etSQLESCAPE2:
> 1210 case etSQLESCAPE3: {
> 1211 whprintf_spec_handler spf =
> 1212 (xtype==etSQLESCAPE)
> 1213 ? spech_sqlstring1
> 1214 : ((xtype==etSQLESCAPE2)
> 1215 ? spech_sqlstring2
> 1216 : spech_sqlstring3
> 1217 );
> 1218 bufpt = va_arg(ap,char*);
> 1219 pfrc = spf( pfAppend, pfAppendArg, bufpt );
> 1220 WHPRINTF_CHECKERR(0);
> 1221 length = 0;
> 1222 if( precision>=0 && precision<length ) length = precision;
> 1223 }
> 1224 #endif /* !WHPRINTF_OMIT_SQL */
> 1225 }/* End switch over the format type */
> 1226 /*
> 1227 The text of the conversion is pointed to by "bufpt" and is
> 1228 "length" characters long. The field width is "width". Do
> 1229 the output.
> 1230 */
> 1231 if( !flag_leftjustify ){
> 1232 int nspace;
> 1233 nspace = width-length;
> 1234 if( nspace>0 ){
> 1235 WHPRINTF_SPACES(nspace);
> 1236 }
> 1237 }
> 1238 if( length>0 ){
> 1239 pfrc = pfAppend( pfAppendArg, bufpt, length);
> 1240 WHPRINTF_CHECKERR(0);
> 1241 }
> 1242 if( flag_leftjustify ){
> 1243 int nspace;
> 1244 nspace = width-length;
> 1245 if( nspace>0 ){
> 1246 WHPRINTF_SPACES(nspace);
> 1247 }
> 1248 }
> 1249 if( zExtra ){
> 1250 free(zExtra);
> 1251 zExtra = 0;
> 1252 }
> 1253 }/* End for loop over the format string */
> 1254 WHPRINTF_RETURN;
> 1255 } /* End of function */
> 1256
> 1257
> 1258 #undef WHPRINTF_SPACES
> 1259 #undef WHPRINTF_CHECKERR
> 1260 #undef WHPRINTF_RETURN
> 1261 #undef WHPRINTF_OMIT_FLOATING_POINT
> 1262 #undef WHPRINTF_OMIT_SIZE
> 1263 #undef WHPRINTF_OMIT_SQL
> 1264 #undef WHPRINTF_BUF_SIZE
> 1265 #undef WHPRINTF_OMIT_HTML
> 1266
> 1267 long whprintf(whprintf_appender pfAppend, /* Accumulate results here */
> 1268 void * pfAppendArg, /* Passed as first arg to pfAppend. */
> 1269 const char *fmt, /* Format string */
> 1270 ... )
> 1271 {
> 1272 va_list vargs;
> 1273 va_start( vargs, fmt );
> 1274 long ret = whprintfv( pfAppend, pfAppendArg, fmt, vargs );
> 1275 va_end(vargs);
> 1276 return ret;
> 1277 }
> 1278
> 1279
> 1280 long whprintf_FILE_appender( void * a, char const * s, long n )
> 1281 {
> 1282 FILE * fp = (FILE *)a;
> 1283 if( ! fp ) return -1;
> 1284 long ret = fwrite( s, sizeof(char), n, fp );
> 1285 return (ret >= 0) ? ret : -2;
> 1286 }
> 1287
> 1288
> 1289 long whprintf_file( FILE * fp, char const * fmt, ... )
> 1290 {
> 1291 va_list vargs;
> 1292 va_start( vargs, fmt );
> 1293 int ret = whprintfv( whprintf_FILE_appender, fp, fmt, vargs );
> 1294 va_end(vargs);
> 1295 return ret;
> 1296 }
> 1297
> 1298 /**
> 1299 Internal implementation details for whprintfv_appender_stringbuf.
> 1300 */
> 1301 typedef struct whprintfv_stringbuf
> 1302 {
> 1303 /** dynamically allocated buffer */
> 1304 char * buffer;
> 1305 /** bytes allocated to buffer */
> 1306 size_t alloced;
> 1307 /** Current position within buffer. */
> 1308 size_t pos;
> 1309 } whprintfv_stringbuf;
> 1310 static const whprintfv_stringbuf whprintfv_stringbuf_init = { 0, 0, 0 };
> 1311
> 1312 /**
> 1313 A whprintfv_appender implementation which requires arg to be a
> 1314 (whprintfv_stringbuf*). It appends n bytes of data to the
> 1315 whprintfv_stringbuf object's buffer, reallocating it as
> 1316 needed. Returns less than 0 on error, else the number of bytes
> 1317 appended to the buffer. The buffer will always be null terminated.
> 1318 */
> 1319 static long whprintfv_appender_stringbuf( void * arg, char const * data, long n )
> 1320 {
> 1321 whprintfv_stringbuf * sb = (whprintfv_stringbuf*)arg;
> 1322 if( ! sb || (n<0) ) return -1;
> 1323 if( ! n ) return 0;
> 1324 size_t npos = sb->pos + n;
> 1325 if( npos >= sb->alloced )
> 1326 {
> 1327 const size_t asz = (npos * 1.5) + 1;
> 1328 if( asz < npos ) return -1; /* overflow */
> 1329 char * buf = realloc( sb->buffer, asz );
> 1330 if( ! buf ) return -1;
> 1331 memset( buf + sb->pos, 0, (npos + 1 - sb->pos) ); // the +1 adds our \0 for us
> 1332 sb->buffer = buf;
> 1333 sb->alloced = asz;
> 1334 }
> 1335 long rc = 0;
> 1336 for( ; rc < n; ++rc, ++sb->pos )
> 1337 {
> 1338 sb->buffer[sb->pos] = data[rc];
> 1339 }
> 1340 return rc;
> 1341 }
> 1342
> 1343
> 1344 char * whprintfv_str( char const * fmt, va_list vargs )
> 1345 {
> 1346 if( ! fmt ) return 0;
> 1347 whprintfv_stringbuf sb = whprintfv_stringbuf_init;
> 1348 long rc = whprintfv( whprintfv_appender_stringbuf, &sb, fmt, vargs );
> 1349 if( rc <= 0 )
> 1350 {
> 1351 free( sb.buffer );
> 1352 sb.buffer = 0;
> 1353 }
> 1354 return sb.buffer;
> 1355 }
> 1356
> 1357 char * whprintf_str( char const * fmt, ... )
> 1358 {
> 1359 va_list vargs;
> 1360 va_start( vargs, fmt );
> 1361 char * ret = whprintfv_str( fmt, vargs );
> 1362 va_end( vargs );
> 1363 return ret;
> 1364 }

Added whprintf.h

Old () New (3f753713796eea59)
> 1 #ifndef WHPRINTF_H_INCLUDED_
> 2 #define WHPRINTF_H_INCLUDED_ 1
> 3 #include <stdarg.h>
> 4 #ifdef __cplusplus
> 5 extern "C" {
> 6 #endif
> 7 /**@page whprintf_page_main whprintf: generic printf-like utilities
> 8
> 9 This API contains a printf-like implementation which supports
> 10 aribtrary data destinations.
> 11
> 12 Authors: many, probably. This code supposedly goes back to the
> 13 early 1980's.
> 14
> 15 Current maintainer: Stephan Beal (http://wanderinghorse.net/home/stephan)
> 16
> 17 License: Public Domain.
> 18
> 19 The primary functions of interest are whprintfv() and whprintf(), which works
> 20 similarly to printf() except that they take a callback function which they
> 21 use to send the generated output to arbitrary destinations. e.g. one can
> 22 supply a callback to output formatted text to a UI widget or a C++ stream
> 23 object.
> 24 */
> 25
> 26 /**
> 27 @typedef long (*whprintf_appender)( void * arg, char const * data, long n )
> 28
> 29
> 30 The whprintf_appender typedef is used to provide whprintfv()
> 31 with a flexible output routine, so that it can be easily
> 32 send its output to arbitrary targets.
> 33
> 34 The policies which implementations need to follow are:
> 35
> 36 - arg is an implementation-specific pointer (may be 0) which is
> 37 passed to vappendf. whprintfv() doesn't know what this argument is
> 38 but passes it to its whprintf_appender. Typically it will be an
> 39 object or resource handle to which string data is pushed or output.
> 40
> 41 - The 'data' parameter is the data to append. If it contains
> 42 embedded nulls, this function will stop at the first one. Thus
> 43 it is not binary-safe.
> 44
> 45 - n is the number of bytes to read from data. If n<0 then
> 46 strlen(data) should be used.
> 47
> 48 - Returns, on success, the number of bytes appended (may be 0).
> 49
> 50 - Returns, on error, an implementation-specified negative number.
> 51 Returning a negative error code will cause whprintfv() to stop the
> 52 processing of that string. Note that 0 is a success value (some
> 53 printf format specifiers do not add anything to the output).
> 54 */
> 55 typedef long (*whprintf_appender)( void * arg,
> 56 char const * data,
> 57 long n );
> 58
> 59
> 60 /**
> 61 This function works similarly to classical printf implementations,
> 62 but instead of outputing somewhere specific, it uses a callback
> 63 function to push its output somewhere. This allows it to be used for
> 64 arbitrary external representations. It can be used, for example, to
> 65 output to an external string, a UI widget, or file handle (it can
> 66 also emulate printf by outputing to stdout this way).
> 67
> 68 INPUTS:
> 69
> 70 pfAppend : The is a whprintf_appender function which is responsible
> 71 for accumulating the output. If pfAppend returns a negative integer
> 72 then processing stops immediately.
> 73
> 74 pfAppendArg : is ignored by this function but passed as the first
> 75 argument to pfAppend. pfAppend will presumably use it as a data
> 76 store for accumulating its string.
> 77
> 78 fmt : This is the format string, as in the usual printf().
> 79
> 80 ap : This is a pointer to a list of arguments. Same as in
> 81 vprintf() and friends.
> 82
> 83
> 84 OUTPUTS:
> 85
> 86 The return value is the total number of characters sent to the
> 87 function "func", or a negative number on a pre-output error. If this
> 88 function returns an integer greater than 1 it is in general
> 89 impossible to know if all of the elements were output. As such
> 90 failure can only happen if the callback function returns an error,
> 91 and this type of error is very rare in a printf-like context, this is
> 92 not considered to be a significant problem. (The same is true for any
> 93 classical printf implementations, as far as i'm aware.)
> 94
> 95
> 96 CURRENT (documented) PRINTF EXTENSIONS:
> 97
> 98 %%z works like %%s, but takes a non-const (char *) and vappendf
> 99 deletes the string (using free()) after appending it to the output.
> 100
> 101 %%h (HTML) works like %s but converts certain characters (like '<' and '&' to
> 102 their HTML escaped equivalents.
> 103
> 104 %%t (URL encode) works like %%s but converts certain characters into a representation
> 105 suitable for use in an HTTP URL. (e.g. ' ' gets converted to %%20)
> 106
> 107 %%T (URL decode) does the opposite of %t - it decodes URL-encoded
> 108 strings.
> 109
> 110 %%r requires an int and renders it in "ordinal form". That is,
> 111 the number 1 converts to "1st" and 398 converts to "398th".
> 112
> 113 %%q quotes a string as required for SQL. That is, '\'' characters get
> 114 doubled.
> 115
> 116 %%Q as %%q, but includes the outer '\'' characters and null pointers
> 117 replaced by SQL NULL.
> 118
> 119 (The %%q and %%Q specifiers are options inherited from this printf
> 120 implementation's sqlite3 genes.)
> 121
> 122 These extensions may be disabled by setting certain macros when
> 123 compiling vappendf.c (see that file for details).
> 124 */
> 125 long whprintfv(
> 126 whprintf_appender pfAppend, /* Accumulate results here */
> 127 void * pfAppendArg, /* Passed as first arg to pfAppend. */
> 128 const char *fmt, /* Format string */
> 129 va_list ap /* arguments */
> 130 );
> 131
> 132 /**
> 133 Identical to whprintfv() but takes a (...) ellipses list instead of a
> 134 va_list.
> 135 */
> 136 long whprintf(whprintf_appender pfAppend,
> 137 void * pfAppendArg,
> 138 const char *fmt,
> 139 ... );
> 140
> 141 /**
> 142 Emulates fprintf() using whprintfv().
> 143 */
> 144 long whprintf_file( FILE * fp, char const * fmt, ... );
> 145
> 146
> 147 /**
> 148 Works like whprintfv(), but appends all output to a
> 149 dynamically-allocated string, expanding the string as necessary to
> 150 collect all formatted data. The returned null-terminated string is
> 151 owned by the caller and it must be cleaned up using free(). If !fmt
> 152 or if the expanded string evaluates to empty, null is returned, not
> 153 a 0-byte string.
> 154 */
> 155 char * whprintfv_str( char const * fmt, va_list vargs );
> 156
> 157 /**
> 158 Equivalent to whprintfv_str(), but takes elipsis arguments instead
> 159 of a va_list.
> 160 */
> 161 char * whprintf_str( char const * fmt, ... );
> 162
> 163 #ifdef __cplusplus
> 164 } /* extern "C" */
> 165 #endif
> 166 #endif /* WHPRINTF_H_INCLUDED_ */