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
- branch=trunk inherited from [f1bea87b3b]
- sym-trunk inherited from [f1bea87b3b]
Changes
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, "<", 4 ); | ||
| > | 459 | break; | ||
| > | 460 | case '&': ret += pf( pfArg, "&", 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_ */ | ||