[2] | 1 | $Id: README.developer 3417 2015-05-25 01:35:59Z peter $ |
---|
| 2 | |
---|
[1674] | 3 | = Coding Style = |
---|
[1605] | 4 | |
---|
[1674] | 5 | We follow the coding style described in |
---|
| 6 | [http://cbbp.thep.lu.se/~jari/documents/c++_coding_guidelines/index.html C++ coding guidelines] |
---|
[2711] | 7 | [http://cbbp.thep.lu.se/~jari/documents/c++_coding_guidelines/c++_coding_guidelines.pdf pdf] |
---|
[1674] | 8 | [http://cbbp.thep.lu.se/~jari/documents/c++_coding_guidelines/c++_coding_guidelines.ps postscript] |
---|
| 9 | with the additions described here. |
---|
| 10 | |
---|
[1721] | 11 | === Subversion usage === |
---|
| 12 | |
---|
| 13 | Commits should be minimalistic and the project should always compile |
---|
| 14 | (`make` and `make check`) when someone makes a clean checkout. There |
---|
| 15 | is a short introduction to subversion and its usage available as |
---|
[2711] | 16 | [http://cbbp.thep.lu.se/~jari/documents/subversion_guidelines/index.html Subversion guidelines]. |
---|
[2404] | 17 | We follow these guidelines. |
---|
[1721] | 18 | |
---|
[1674] | 19 | === Testing === |
---|
| 20 | |
---|
[1721] | 21 | The test suite is run with `make check` at the project root directory |
---|
| 22 | level. |
---|
[1674] | 23 | |
---|
[1721] | 24 | The test suite should at minimum include creation of all classes (to |
---|
| 25 | catch linking errors) and calls to template functions (as template |
---|
| 26 | functions are not compiled until they are needed). There is a test |
---|
[2500] | 27 | that checks that minimum amount of documentation is written. This test |
---|
| 28 | is skipped if doxygen is not available and for that reason it is |
---|
| 29 | recommended to have doxygen available if you modify header files. |
---|
[1721] | 30 | |
---|
| 31 | For more details on writing and running tests, see file |
---|
| 32 | [source:trunk/test/README test/README]. |
---|
| 33 | |
---|
[1674] | 34 | === Interfacing [http://www.gnu.org/software/gsl/ Gnu Scientific Library, GSL] === |
---|
| 35 | |
---|
| 36 | The GSL documentation describes how |
---|
[2404] | 37 | [http://www.gnu.org/software/gsl/manual/html_node/Error-Handling.html GSL error handling] |
---|
[1674] | 38 | works. The GSL library follows the thread-safe |
---|
| 39 | error reporting conventions of the posix Threads library. That is, |
---|
| 40 | functions return a non-zero error code to indicate an error. In most |
---|
| 41 | cases yat just returns whatever the underlying GSL library calls |
---|
| 42 | returns. If GSL errors occur in constructors yat handles them |
---|
| 43 | accordingly. If GSL reports errors that cannot be resolved by yat a |
---|
| 44 | [http://cbbp.thep.lu.se/~jari/documents/yat/classtheplu_1_1yat_1_1utility_1_1GSL__error.html GSL_error] |
---|
| 45 | exception will be thrown. However, the default behaviour of |
---|
| 46 | GSL library is to call abort() when unrecoverable errors occur and |
---|
| 47 | puts the yat (and any other) GSL error treatment out of play. For |
---|
[2067] | 48 | production environments, yat and GSL users should turn off the default |
---|
[1674] | 49 | GSL error treatment by calling gsl_set_error_handler_off(), but also |
---|
| 50 | when yat's GSL error treatment is preferred. |
---|
| 51 | |
---|
| 52 | When new GSL functionality is introduced to yat, it is the |
---|
[1721] | 53 | responsibility of the programmer to make sure that GSL errors are |
---|
[1674] | 54 | treated properly. Proper GSL error treatment is very important in |
---|
| 55 | cases when yat users turn off the default GSL error handler since: |
---|
| 56 | |
---|
| 57 | yat aims at treating GSL errors appropriately in an |
---|
| 58 | [http://www.gotw.ca/gotw/008.htm exception safe and neutral] |
---|
| 59 | way but there is still some work to do before we do exceptions in a neutral way. |
---|
| 60 | |
---|
[2943] | 61 | === Samtools === |
---|
| 62 | |
---|
| 63 | Code that depends on samtools API should be excluded from the build |
---|
| 64 | when configured --without-samtools, i.e., put files within |
---|
| 65 | `HAVE_LIBBAM` conditionals (or alternatively put code inside `#ifdef |
---|
| 66 | HAVE_SAMTOOL` preprocessor conditionals). In order to support multiple |
---|
| 67 | inclusion styles we do not include <bam.h> directly, but `#include |
---|
| 68 | <config_bam.h>` and `#include YAT_BAM_HEADER`. Similarly, for `<sam.h>` |
---|
| 69 | include `YAT_SAM_HEADER`. For more details on this, refer to |
---|
| 70 | `yat/omic/config_bam.h`. |
---|
| 71 | |
---|
[1674] | 72 | === Doxygen === |
---|
[2071] | 73 | We generate our documentation using [http://www.doxygen.org Doxygen] |
---|
| 74 | (version 1.5 or later). Doxygen allows several different styles. We |
---|
| 75 | try to use the following style as we have found this minimizes parsing |
---|
| 76 | problems: |
---|
[1674] | 77 | |
---|
| 78 | {{{ |
---|
| 79 | /** |
---|
| 80 | \brief My class |
---|
| 81 | |
---|
| 82 | Some text documenting the class MyClass |
---|
| 83 | */ |
---|
| 84 | class MyClass |
---|
| 85 | }}} |
---|
| 86 | |
---|
[2711] | 87 | or similarly |
---|
[1674] | 88 | |
---|
| 89 | {{{ |
---|
| 90 | /** |
---|
| 91 | \brief magic function |
---|
| 92 | |
---|
| 93 | Some text documenting my_function |
---|
| 94 | */ |
---|
| 95 | void my_function(void); |
---|
| 96 | }}} |
---|
| 97 | |
---|
[2071] | 98 | We use doxygen keywords preceded by `\` such as `\brief`, |
---|
| 99 | `\return`. All classes and functions have a brief description, which |
---|
| 100 | increases clarity on summary pages. |
---|
[1674] | 101 | |
---|
[2071] | 102 | Try to keep comment line lengths within the terminal character limit, |
---|
| 103 | in other words, less than 80 characters per line. This makes the |
---|
| 104 | comments more readable. |
---|
[1674] | 105 | |
---|
| 106 | '''Internal Interface''' |
---|
| 107 | |
---|
[3188] | 108 | Helper functions and classes that are not part of yat API should |
---|
| 109 | either be labeled with doxygen flag `\internal` or placed in |
---|
| 110 | sub-namespace `detail`. Functionality placed in namespace `detail` |
---|
| 111 | should be excluded from doxygen input using a pattern like this: |
---|
[1674] | 112 | |
---|
[3188] | 113 | /// \cond IGNORE_DOXYGEN |
---|
| 114 | namespace detail { |
---|
| 115 | |
---|
| 116 | <Some very detailed code here> |
---|
| 117 | |
---|
| 118 | } |
---|
| 119 | /// \endcode |
---|
| 120 | |
---|
[1674] | 121 | = Build = |
---|
| 122 | |
---|
| 123 | == Requirements == |
---|
| 124 | |
---|
[2404] | 125 | To build from a subversion checkout, you will need GNU Autotools. More |
---|
[2711] | 126 | specifically |
---|
[2404] | 127 | * Automake 1.11 (or later), http://www.gnu.org/software/automake/ |
---|
[3367] | 128 | * Autoconf 2.64 (or later), http://www.gnu.org/software/autoconf/ |
---|
[2404] | 129 | * Libtool 1.5 (or later), http://www.gnu.org/software/libtool/ |
---|
[1605] | 130 | |
---|
[1674] | 131 | == Disable shared library == |
---|
[573] | 132 | |
---|
[2404] | 133 | yat uses GNU Libtool in order to build shared libraries on a variety |
---|
[1368] | 134 | of systems. While this is very nice for making usable binaries, it |
---|
| 135 | can be a pain when trying to debug a program. For that reason, |
---|
| 136 | compilation of shared libraries can be turned off by specifying the |
---|
| 137 | `--disable-shared` option to configure. |
---|
| 138 | |
---|
[1674] | 139 | == Debugging using GDB == |
---|
[1372] | 140 | |
---|
[2404] | 141 | If shared library is enabled (default), Libtool creates wrapper |
---|
| 142 | scripts in directory `test/` that call the test programs located in |
---|
| 143 | directory `test/.libs/`. While this allows us to dynamically link against |
---|
| 144 | the temporary library in `yat/`, it makes straightforward usage of GDB |
---|
[1372] | 145 | impossible. For that reason libtool provides a wrapper: |
---|
| 146 | |
---|
| 147 | `#> libtool --mode=execute gdb foo_test` |
---|
| 148 | |
---|
| 149 | that sets the necessary environment variables. For more detailed |
---|
| 150 | discussion, please refer to the libtool manual: |
---|
| 151 | |
---|
| 152 | http://www.gnu.org/software/libtool/manual/libtool.html#Debugging-executables |
---|
| 153 | |
---|
[3144] | 154 | |
---|
| 155 | = Release Procedure = |
---|
| 156 | |
---|
| 157 | These instructions cover how to release minor and patch releases in a |
---|
| 158 | project that uses trac/subversion for revision control and project |
---|
| 159 | management. How to release major releases is not covered yet since we |
---|
| 160 | have not done that (with the exception of the first release). Release |
---|
| 161 | numbering follows the normal convention of major.minor.patch and the |
---|
| 162 | APR (see http://apr.apache.org/versioning.html) guidelines for |
---|
| 163 | releases are used. |
---|
| 164 | |
---|
| 165 | The main development is performed in the trunk branch of the |
---|
| 166 | repository. A new release branch is created for each minor release |
---|
| 167 | from the trunk and patch releases are snapshots of the minor release |
---|
| 168 | branch. This implies that patch work is performed in the minor release |
---|
| 169 | branch, and changes made release branch is transferred to the trunk |
---|
| 170 | every time a new patch release is made. Remember, patch work should be |
---|
| 171 | limited to bug fixes and important fixes only leaving development of |
---|
| 172 | new features and designs to the trunk branch. |
---|
| 173 | |
---|
| 174 | Releases should only be performed by an appointed member of the team, |
---|
| 175 | the Release Manager. |
---|
| 176 | |
---|
| 177 | |
---|
| 178 | === Creating a release branch === |
---|
| 179 | |
---|
| 180 | Once people agree that a new release branch should be made, the |
---|
| 181 | Release Manager creates it with the following procedure |
---|
| 182 | (substitute A.B with the version you are preparing, e.g. 0.3) |
---|
| 183 | |
---|
| 184 | 1. Check that 'YAT_LT_VERSION_INFO' is set correcly |
---|
| 185 | otherwise update following line in 'm4/version.m4' |
---|
| 186 | |
---|
| 187 | 8<---- |
---|
| 188 | m4_define([YAT_LT_VERSION_INFO], [c:r:a]) |
---|
| 189 | 8<---- |
---|
| 190 | |
---|
| 191 | 2. Add a line in NEWS |
---|
| 192 | 8<---- |
---|
| 193 | See the end for copyrights and conditions. |
---|
| 194 | |
---|
| 195 | +yat A.B.x series from http://dev.thep.lu.se/yat/svn/branches/A.B-stable |
---|
| 196 | + |
---|
| 197 | Version A.B (released NOT YET) |
---|
| 198 | 8<---- |
---|
| 199 | |
---|
| 200 | 3. Commit the changes with |
---|
| 201 | |
---|
| 202 | #> svn ci -m "Prepare A.B-stable branch" |
---|
| 203 | |
---|
| 204 | 4. For this step svncopyright is needed, http://dev.thep.lu.se/svndigest. |
---|
| 205 | Update copyright statements with command: |
---|
| 206 | |
---|
| 207 | #> make copyright |
---|
| 208 | |
---|
| 209 | Examine the updates and commit changes with |
---|
| 210 | |
---|
| 211 | #> svn ci -m "updating copyright statements"`. |
---|
| 212 | |
---|
| 213 | 5. Create a new stable branch with |
---|
| 214 | |
---|
| 215 | #> make svn-stable-branch |
---|
| 216 | |
---|
| 217 | 6. Prepare the trunk for the next minor release |
---|
| 218 | |
---|
| 219 | a) Update version number in 'm4/version.m4'. Locate and change the |
---|
| 220 | below lines |
---|
| 221 | |
---|
| 222 | 8<---- |
---|
| 223 | MY_VERSION_early([A], [B+1], [0], [true]) |
---|
| 224 | m4_define([YAT_LT_VERSION_INFO], [c+1:0:0]) |
---|
| 225 | 8<---- |
---|
| 226 | |
---|
| 227 | b) Add an entry in `NEWS` |
---|
| 228 | |
---|
| 229 | 8<---- |
---|
| 230 | version A.[B+1] (released NOT YET) |
---|
| 231 | 8<---- |
---|
| 232 | |
---|
| 233 | The date is set when version A.[B+1] is released. [[br]][[br]] |
---|
| 234 | |
---|
| 235 | c) Commit changes to the repository: |
---|
| 236 | |
---|
| 237 | #> svn ci -m "Bumping VERSION to A.[B+1]pre" |
---|
| 238 | |
---|
| 239 | 7. When someone with access to documentation site has time available, |
---|
| 240 | they will upgrade to the new branch. This person is usually not the |
---|
| 241 | release manager, so please send a reminder. |
---|
| 242 | |
---|
| 243 | === Rolling a minor release === |
---|
| 244 | |
---|
| 245 | These instructions describe how to make a release. Replace A.B.C |
---|
| 246 | with current VERSION (A.B if this is not a patch release). |
---|
| 247 | |
---|
| 248 | 1. Update version number in 'm4/version.m4'. Locate and change the |
---|
| 249 | below line |
---|
| 250 | |
---|
| 251 | 8<---- |
---|
| 252 | MY_VERSION_early([A], [B], [C], [false]) |
---|
| 253 | 8<---- |
---|
| 254 | |
---|
| 255 | |
---|
| 256 | 2. Update the interface version number in 'm4/version.m4'. Locate and |
---|
| 257 | set the version in the below line |
---|
| 258 | |
---|
| 259 | 8<---- |
---|
| 260 | m4_define([YAT_LT_VERSION_INFO], [c:r:a]) |
---|
| 261 | 8<---- |
---|
| 262 | |
---|
| 263 | appropriately. Refer to file 'm4/version.m4' for details on how to |
---|
| 264 | decide triplet 'c:r:a'. |
---|
| 265 | |
---|
| 266 | |
---|
| 267 | 3. Set the date for the new release in 'NEWS'. |
---|
| 268 | |
---|
| 269 | 8<---- |
---|
| 270 | version A.B.C (released 26 June 2007) |
---|
| 271 | 8<---- |
---|
| 272 | |
---|
| 273 | |
---|
| 274 | 4. Make sure that the items in 'NEWS' cover the new features of the |
---|
| 275 | release. |
---|
| 276 | |
---|
| 277 | |
---|
| 278 | 5. Commit changes to the repository: |
---|
| 279 | |
---|
| 280 | #> svn ci -m "Preparing release A.B.C" |
---|
| 281 | |
---|
| 282 | |
---|
| 283 | 6. For this step svncopyright is needed, http://dev.thep.lu.se/svndigest. |
---|
| 284 | Update copyright statements with command: |
---|
| 285 | |
---|
| 286 | #> make copyright |
---|
| 287 | |
---|
| 288 | Examine the updates and commit changes with |
---|
| 289 | |
---|
| 290 | #> svn ci -m "updating copyright statements" |
---|
| 291 | |
---|
| 292 | |
---|
| 293 | 7. Now it's time to create a tarball, an svn tag, and upload the |
---|
| 294 | tarball to sourceforge. For this to work you need to hold write |
---|
| 295 | permissions at libyat project page at sourceforge. If your sf user |
---|
| 296 | id is different from the one defined in 'Makefile.am', you can |
---|
| 297 | override the default with 'sf_user=<your id>'. Issue the |
---|
| 298 | convenience target: |
---|
| 299 | |
---|
[3248] | 300 | #> make release-tag-upload sf_user=<sourceforge user id> |
---|
[3144] | 301 | |
---|
| 302 | This will run some sanity checks, run maintainer-check and |
---|
| 303 | distcheck, create an svn tag, and upload the newly created tarball |
---|
| 304 | to sourceforge. The last step requires that you provide your SF password. |
---|
| 305 | |
---|
| 306 | |
---|
| 307 | 8. On WikiStart update links |
---|
| 308 | '[source:tags/A.B.C/NEWS NEWS]' and |
---|
| 309 | '[source:branches/A.B-stable/README README]' |
---|
| 310 | |
---|
| 311 | 9. Update SubversionCheckout |
---|
| 312 | |
---|
| 313 | a) In section 'yat latest release' update command to |
---|
| 314 | 'svn checkout http://dev.thep.lu.se/yat/svn/tags/A.B.C yat-A.B.C |
---|
| 315 | and link to |
---|
| 316 | '[source:tags/A.B.C/NEWS NEWS]' |
---|
| 317 | If this is a patch release jump to point 10). |
---|
| 318 | |
---|
| 319 | b) In section 'yat stable' update command to |
---|
| 320 | 'svn checkout http://dev.thep.lu.se/yat/svn/branches/A.B-stable yat-A.B.x |
---|
| 321 | and link to |
---|
| 322 | '[source:branches/A.B-stable/NEWS NEWS]' |
---|
| 323 | |
---|
| 324 | |
---|
| 325 | 10. Close the milestone associated with this release. |
---|
| 326 | |
---|
| 327 | |
---|
| 328 | 11. Update the version list in Trac using the trac-admin tool. |
---|
| 329 | |
---|
| 330 | |
---|
| 331 | 12. Use file 'announcement.txt' as template and send email to |
---|
| 332 | libyat-users@lists.sourceforge.net |
---|
| 333 | |
---|
| 334 | |
---|
| 335 | 13. Merge the release into the trunk. |
---|
| 336 | |
---|
| 337 | a) Go to a pristine trunk WC: |
---|
| 338 | |
---|
| 339 | #> cd /path/to/yat-trunk/ |
---|
| 340 | #> make check-svn-diff |
---|
| 341 | |
---|
| 342 | b) Merge changes into trunk: |
---|
| 343 | |
---|
| 344 | #> svn merge ^/branches/A.B-stable |
---|
| 345 | |
---|
| 346 | c) Resolve potential conflicts. Run tests and perform all other |
---|
| 347 | appropriate tests to make sure that the merge does not create |
---|
| 348 | havoc. Typically changes in `m4/version.m4` are problematic so |
---|
| 349 | check this file extra carefully. |
---|
| 350 | |
---|
| 351 | d) Commit changes to the trunk branch. |
---|
| 352 | |
---|
| 353 | #> svn commit -m "Merged release A.B.C into trunk." |
---|
| 354 | |
---|
| 355 | |
---|
| 356 | 14. Prepare the stable branch for the next patch release. |
---|
| 357 | |
---|
| 358 | a) Update version number in 'm4/version.m4'. Locate and change the |
---|
| 359 | below line |
---|
| 360 | |
---|
| 361 | 8<--- |
---|
| 362 | MY_VERSION_early([A], [B], [C+1], [true]) |
---|
| 363 | 8<--- |
---|
| 364 | |
---|
| 365 | Run 'make all' and while waiting finalize item b) below |
---|
| 366 | |
---|
| 367 | b) Add an entry in 'NEWS' |
---|
| 368 | |
---|
| 369 | 8<---- |
---|
| 370 | version A.B.[C+1] (released NOT YET) |
---|
| 371 | 8<---- |
---|
| 372 | |
---|
| 373 | The date is set when version A.B.[C+1] is released. |
---|
| 374 | |
---|
| 375 | |
---|
| 376 | 15. Commit changes to the repository: |
---|
| 377 | |
---|
| 378 | #> svn ci -m "Bumping VERSION to A.B.[C+1]pre" |
---|
| 379 | |
---|
| 380 | |
---|
[1674] | 381 | = Versioning = |
---|
| 382 | |
---|
[2711] | 383 | We use a softened version of |
---|
[2404] | 384 | [http://apr.apache.org/versioning.html APR guidelines] which in short implies |
---|
[1674] | 385 | |
---|
| 386 | ''"The basic intent is that '''`MAJOR`''' versions are incompatible, |
---|
[2404] | 387 | large-scale upgrades of the API. '''`MINOR`''' versions retain |
---|
| 388 | compatibility with older minor versions, and changes in the |
---|
| 389 | '''`PATCH`''' level are perfectly compatible, forwards and |
---|
| 390 | backwards."'' |
---|
[1674] | 391 | |
---|
[2711] | 392 | == '''`MAJOR`''' Releases == |
---|
[1674] | 393 | |
---|
| 394 | No compatibility is guaranteed between '''`MAJOR`''' versions. |
---|
| 395 | |
---|
| 396 | == '''`MINOR`''' Releases == |
---|
| 397 | |
---|
| 398 | '''`MINOR`''' versions should be compatible with earlier minor |
---|
| 399 | versions. However, in the `0.x` line we may allow exceptions to this |
---|
[2711] | 400 | rule, if developers agree the gain of change is sufficient. Binary compatibility is typically not guaranteed between '''`MINOR`''' versions. The `YAT_LT_VERSION` in [source:trunk/build_support/version.m4 version.m4] should reflect which versions are binary compatible. |
---|
| 401 | |
---|
[1674] | 402 | == '''`PATCH`''' Releases == |
---|
| 403 | |
---|
| 404 | Versions with same '''`MAJOR.MINOR`''' are perfectly compatible, |
---|
| 405 | forwards and backwards. |
---|
[2711] | 406 | |
---|
[1674] | 407 | This implies that only implementations can be modified in a `PATCH` |
---|
| 408 | release. You cannot change the API, not even add functions or |
---|
| 409 | classes because it will break forward compatibility for the previous |
---|
| 410 | `PATCH` version. A `PATCH` release is a pure bug fix release |
---|
| 411 | |
---|
| 412 | === Backward Source Compatibility === |
---|
| 413 | |
---|
| 414 | Backward Source Compatibility means that an application that could build |
---|
| 415 | against version `x.y` shall also build without error against |
---|
| 416 | `x.y+1`. An application that compiled against header files from |
---|
| 417 | previous `MINOR` version shall also compile without errors against the |
---|
| 418 | header files of the new version. |
---|
| 419 | |
---|
| 420 | Specifically this implies: |
---|
| 421 | - Do not remove any public, protected, or free functions. |
---|
| 422 | - If you modify a function, its signature must be compatible with |
---|
| 423 | previous signature, e.g., new parameters with default values may |
---|
[1721] | 424 | be added to signature. |
---|
[1674] | 425 | - Do not remove any class or inheritance for a class. |
---|
| 426 | |
---|
| 427 | === Backward Binary Compatibility === |
---|
| 428 | |
---|
| 429 | Backward Binary Compatibility means that an application that has been |
---|
| 430 | compiled against version `x.y` can be linked against version |
---|
[2711] | 431 | `x.y+1`. |
---|
[1674] | 432 | |
---|
| 433 | Specifically this implies: |
---|
| 434 | |
---|
| 435 | - Do not remove or modify any function (except private), not even |
---|
| 436 | add a parameter with default value because it will make the |
---|
| 437 | function incompatible with earlier header files. |
---|
| 438 | |
---|
| 439 | - Do not add, remove, or modify member variables, because that will |
---|
| 440 | change the allocated size of the class. Therefore, to allow |
---|
| 441 | modifications of the internal representation, it is preferable to |
---|
| 442 | hold member variable is a ''pimpl'' that is allocated privately. |
---|
| 443 | http://developer.gnome.org/doc/guides/programming-guidelines/binary.html |
---|
| 444 | |
---|
| 445 | - Do not add or change order among virtual functions because it will |
---|
| 446 | change the layout of the virtual table. |
---|
| 447 | |
---|
| 448 | |
---|
| 449 | |
---|
| 450 | |
---|
[1262] | 451 | ---------------------------------------------------------------------- |
---|
| 452 | {{{ |
---|
[2119] | 453 | Copyright (C) 2003 Jari Häkkinen, Peter Johansson |
---|
| 454 | Copyright (C) 2004 Jari Häkkinen |
---|
| 455 | Copyright (C) 2006, 2007, 2008, 2009 Jari Häkkinen, Peter Johansson |
---|
[3417] | 456 | Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Peter Johansson |
---|
[1262] | 457 | |
---|
[1469] | 458 | This file is part of yat library, http://dev.thep.lu.se/yat |
---|
[1262] | 459 | |
---|
| 460 | The yat library is free software; you can redistribute it and/or |
---|
| 461 | modify it under the terms of the GNU General Public License as |
---|
[1486] | 462 | published by the Free Software Foundation; either version 3 of the |
---|
[1262] | 463 | License, or (at your option) any later version. |
---|
| 464 | |
---|
| 465 | The yat library is distributed in the hope that it will be useful, but |
---|
| 466 | WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 467 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
| 468 | General Public License for more details. |
---|
| 469 | |
---|
| 470 | You should have received a copy of the GNU General Public License |
---|
[1487] | 471 | along with yat. If not, see <http://www.gnu.org/licenses/>. |
---|
[1262] | 472 | }}} |
---|