annotate src/libsndfile-1.0.27/regtest/database.c @ 84:08ae793730bd

Add null config files
author Chris Cannam
date Mon, 02 Mar 2020 14:03:47 +0000
parents 1df64224f5ac
children
rev   line source
Chris@40 1 /*
Chris@40 2 ** Copyright (C) 2005-2011 Erik de Castro Lopo
Chris@40 3 **
Chris@40 4 ** This program is free software; you can redistribute it and/or modify
Chris@40 5 ** it under the terms of the GNU General Public License as published by
Chris@40 6 ** the Free Software Foundation; either version 2 of the License, or
Chris@40 7 ** (at your option) any later version.
Chris@40 8 **
Chris@40 9 ** This program is distributed in the hope that it will be useful,
Chris@40 10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@40 11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@40 12 ** GNU General Public License for more details.
Chris@40 13 **
Chris@40 14 ** You should have received a copy of the GNU General Public License
Chris@40 15 ** along with this program; if not, write to the Free Software
Chris@40 16 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Chris@40 17 */
Chris@40 18
Chris@40 19 #include "config.h"
Chris@40 20
Chris@40 21 #include <stdio.h>
Chris@40 22 #include <stdlib.h>
Chris@40 23 #include <unistd.h>
Chris@40 24 #include <string.h>
Chris@40 25 #include <fcntl.h>
Chris@40 26 #include <sys/stat.h>
Chris@40 27
Chris@40 28 #include <sndfile.h>
Chris@40 29
Chris@40 30 #include "regtest.h"
Chris@40 31
Chris@40 32 #if HAVE_SQLITE3
Chris@40 33
Chris@40 34 #include <sqlite3.h>
Chris@40 35
Chris@40 36 typedef struct
Chris@40 37 { sqlite3 *sql ;
Chris@40 38
Chris@40 39 int count ;
Chris@40 40 int ekey_max ;
Chris@40 41
Chris@40 42 /* Filename and pathname for file. */
Chris@40 43 char filename [256] ;
Chris@40 44 char pathname [512] ;
Chris@40 45
Chris@40 46 /* Storage for createding SQL commands. Must be larger than logbuf below. */
Chris@40 47 char cmdbuf [1 << 15] ;
Chris@40 48
Chris@40 49 /* Storage for log buffer retrieved from SNDFILE* .*/
Chris@40 50 char logbuf [1 << 14] ;
Chris@40 51
Chris@40 52 } REGTEST_DB ;
Chris@40 53
Chris@40 54 /* In checksum.c */
Chris@40 55 int calc_checksum (SNDFILE * file, const SF_INFO * info) ;
Chris@40 56
Chris@40 57 static void get_filename_pathname (REGTEST_DB * db, const char *filepath) ;
Chris@40 58 static void single_quote_replace (char * buf) ;
Chris@40 59
Chris@40 60 static int get_ekey_from_filename (REGTEST_DB * db, const char *filepath) ;
Chris@40 61 static int get_filename_pathname_by_ekey (REGTEST_DB * db, int ekey) ;
Chris@40 62 static int check_file_by_ekey (REGTEST_DB * db, int ekey) ;
Chris@40 63
Chris@40 64 static int count_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ;
Chris@40 65 static int ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ;
Chris@40 66 static int callback (void *unused, int argc, char **argv, char **colname) ;
Chris@40 67
Chris@40 68 REG_DB *
Chris@40 69 db_open (const char * db_name)
Chris@40 70 { REGTEST_DB * db ;
Chris@40 71 int err ;
Chris@40 72
Chris@40 73 if ((db = malloc (sizeof (REGTEST_DB))) == NULL)
Chris@40 74 { perror ("malloc") ;
Chris@40 75 exit (1) ;
Chris@40 76 } ;
Chris@40 77
Chris@40 78 if ((err = sqlite3_open (db_name, &(db->sql))) != 0)
Chris@40 79 { printf ("Can't open database: %s\n", sqlite3_errmsg (db->sql)) ;
Chris@40 80 sqlite3_close (db->sql) ;
Chris@40 81 free (db) ;
Chris@40 82 exit (1) ;
Chris@40 83 } ;
Chris@40 84
Chris@40 85 return (REG_DB *) db ;
Chris@40 86 } /* db_open */
Chris@40 87
Chris@40 88 int
Chris@40 89 db_create (const char * db_name)
Chris@40 90 { REGTEST_DB * db ;
Chris@40 91 const char *cmd ;
Chris@40 92 char * errmsg = NULL ;
Chris@40 93 int err ;
Chris@40 94
Chris@40 95 db = (REGTEST_DB *) db_open (db_name) ;
Chris@40 96
Chris@40 97 cmd = "create table sndfile (ekey INTEGER PRIMARY KEY,"
Chris@40 98 "fname VARCHAR(1),"
Chris@40 99 "fpath VARCHAR(1),"
Chris@40 100 "srate INTEGER,"
Chris@40 101 "frames VARCHAR(1),"
Chris@40 102 "channels INTEGER,"
Chris@40 103 "format VARCHAR(1),"
Chris@40 104 "checksum VARCHAR(1),"
Chris@40 105 "logbuf VARCHAR(1)"
Chris@40 106 ");" ;
Chris@40 107
Chris@40 108 err = sqlite3_exec (db->sql, cmd, callback, 0, &errmsg) ;
Chris@40 109 if (err != SQLITE_OK)
Chris@40 110 printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
Chris@40 111
Chris@40 112 sqlite3_close (db->sql) ;
Chris@40 113 free (db) ;
Chris@40 114
Chris@40 115 return 0 ;
Chris@40 116 } /* db_create */
Chris@40 117
Chris@40 118 int
Chris@40 119 db_close (REG_DB * db_handle)
Chris@40 120 { REGTEST_DB * db ;
Chris@40 121
Chris@40 122 db = (REGTEST_DB *) db_handle ;
Chris@40 123
Chris@40 124 sqlite3_close (db->sql) ;
Chris@40 125 free (db) ;
Chris@40 126
Chris@40 127 return 0 ;
Chris@40 128 } /* db_close */
Chris@40 129
Chris@40 130 /*==============================================================================
Chris@40 131 */
Chris@40 132
Chris@40 133 int
Chris@40 134 db_file_exists (REG_DB * db_handle, const char * filename)
Chris@40 135 { REGTEST_DB * db ;
Chris@40 136 const char * cptr ;
Chris@40 137 char * errmsg ;
Chris@40 138 int err ;
Chris@40 139
Chris@40 140 db = (REGTEST_DB *) db_handle ;
Chris@40 141
Chris@40 142 if ((cptr = strrchr (filename, '/')) != NULL)
Chris@40 143 filename = cptr + 1 ;
Chris@40 144
Chris@40 145 snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname from sndfile where fname='%s'", filename) ;
Chris@40 146
Chris@40 147 db->count = 0 ;
Chris@40 148 err = sqlite3_exec (db->sql, db->cmdbuf, (sqlite3_callback) count_callback, db, &errmsg) ;
Chris@40 149 if (err == 0 && db->count == 1)
Chris@40 150 return 1 ;
Chris@40 151
Chris@40 152 return 0 ;
Chris@40 153 } /* db_file_exists */
Chris@40 154
Chris@40 155 int
Chris@40 156 db_add_file (REG_DB * db_handle, const char * filepath)
Chris@40 157 { REGTEST_DB * db ;
Chris@40 158 SNDFILE * sndfile ;
Chris@40 159 SF_INFO info ;
Chris@40 160 char * errmsg ;
Chris@40 161 int err, checksum ;
Chris@40 162
Chris@40 163 db = (REGTEST_DB *) db_handle ;
Chris@40 164
Chris@40 165 get_filename_pathname (db, filepath) ;
Chris@40 166
Chris@40 167 if (db_file_exists (db_handle, filepath))
Chris@40 168 { printf (" %s : already in database\n", db->filename) ;
Chris@40 169 return 0 ;
Chris@40 170 } ;
Chris@40 171
Chris@40 172 memset (&info, 0, sizeof (info)) ;
Chris@40 173 sndfile = sf_open (db->pathname, SFM_READ, &info) ;
Chris@40 174 sf_command (sndfile, SFC_GET_LOG_INFO, db->logbuf, sizeof (db->logbuf)) ;
Chris@40 175 checksum = (sndfile == NULL) ? 0 : calc_checksum (sndfile, &info) ;
Chris@40 176 sf_close (sndfile) ;
Chris@40 177
Chris@40 178 if (sndfile == NULL)
Chris@40 179 { printf (" %s : could not open : %s\n", db->filename, sf_strerror (NULL)) ;
Chris@40 180 puts (db->logbuf) ;
Chris@40 181 return 1 ;
Chris@40 182 } ;
Chris@40 183
Chris@40 184 single_quote_replace (db->logbuf) ;
Chris@40 185
Chris@40 186 snprintf (db->cmdbuf, sizeof (db->cmdbuf), "insert into sndfile "
Chris@40 187 "(fname, fpath, srate, frames, channels, format, checksum, logbuf) values"
Chris@40 188 "('%s','%s',%d,'%ld', %d, '0x%08x', '0x%08x', '%s');",
Chris@40 189 db->filename, db->pathname, info.samplerate, (long) info.frames, info.channels, info.format, checksum, db->logbuf) ;
Chris@40 190
Chris@40 191 if (strlen (db->cmdbuf) >= sizeof (db->cmdbuf) - 1)
Chris@40 192 { printf ("strlen (db->cmdbuf) too long.\n") ;
Chris@40 193 exit (1) ;
Chris@40 194 } ;
Chris@40 195
Chris@40 196 err = sqlite3_exec (db->sql, db->cmdbuf, callback, 0, &errmsg) ;
Chris@40 197 if (err != SQLITE_OK)
Chris@40 198 { printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
Chris@40 199 puts (db->cmdbuf) ;
Chris@40 200 } ;
Chris@40 201
Chris@40 202 return 0 ;
Chris@40 203 } /* db_add_file */
Chris@40 204
Chris@40 205 int
Chris@40 206 db_check_file (REG_DB * db_handle, const char * filepath)
Chris@40 207 { REGTEST_DB * db ;
Chris@40 208 int ekey ;
Chris@40 209
Chris@40 210 if (db_file_exists (db_handle, filepath) == 0)
Chris@40 211 { printf ("\nFile not in database.\n\n") ;
Chris@40 212 exit (0) ;
Chris@40 213 } ;
Chris@40 214
Chris@40 215 db = (REGTEST_DB *) db_handle ;
Chris@40 216
Chris@40 217 ekey = get_ekey_from_filename (db, filepath) ;
Chris@40 218
Chris@40 219 return check_file_by_ekey (db, ekey) ;
Chris@40 220 } /* db_check_file */
Chris@40 221
Chris@40 222 /*==============================================================================
Chris@40 223 */
Chris@40 224
Chris@40 225 int
Chris@40 226 db_check_all (REG_DB * db_handle)
Chris@40 227 { REGTEST_DB * db ;
Chris@40 228 char * errmsg ;
Chris@40 229 int err, ekey ;
Chris@40 230
Chris@40 231 db = (REGTEST_DB *) db_handle ;
Chris@40 232
Chris@40 233 db->ekey_max = 0 ;
Chris@40 234
Chris@40 235 snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select ekey from sndfile") ;
Chris@40 236
Chris@40 237 err = sqlite3_exec (db->sql, db->cmdbuf, (sqlite3_callback) ekey_max_callback, db, &errmsg) ;
Chris@40 238 if (err != SQLITE_OK)
Chris@40 239 { printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
Chris@40 240 puts (db->cmdbuf) ;
Chris@40 241 } ;
Chris@40 242
Chris@40 243 for (ekey = 1 ; ekey <= db->ekey_max ; ekey++)
Chris@40 244 if (get_filename_pathname_by_ekey (db, ekey) != 0)
Chris@40 245 check_file_by_ekey (db, ekey) ;
Chris@40 246
Chris@40 247 return 0 ;
Chris@40 248 } /* db_check_all */
Chris@40 249
Chris@40 250
Chris@40 251 int
Chris@40 252 db_list_all (REG_DB * db_handle)
Chris@40 253 {
Chris@40 254 printf ("%s : %p\n", __func__, db_handle) ;
Chris@40 255 return 0 ;
Chris@40 256 } /* db_list_all */
Chris@40 257
Chris@40 258 int
Chris@40 259 db_del_entry (REG_DB * db_handle, const char * entry)
Chris@40 260 {
Chris@40 261 printf ("%s : %p %s\n", __func__, db_handle, entry) ;
Chris@40 262 return 0 ;
Chris@40 263 } /* db_del_entry */
Chris@40 264
Chris@40 265 /*==============================================================================
Chris@40 266 */
Chris@40 267
Chris@40 268 static int
Chris@40 269 get_ekey_from_filename (REGTEST_DB * db, const char *filepath)
Chris@40 270 { char * errmsg, **result ;
Chris@40 271 int err, ekey = 0, rows, cols ;
Chris@40 272
Chris@40 273 get_filename_pathname (db, filepath) ;
Chris@40 274
Chris@40 275 snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select ekey from sndfile where fname='%s'", db->filename) ;
Chris@40 276
Chris@40 277 err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ;
Chris@40 278 if (err != SQLITE_OK)
Chris@40 279 { printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
Chris@40 280 puts (db->cmdbuf) ;
Chris@40 281 } ;
Chris@40 282
Chris@40 283 if (cols != 1 || rows != 1)
Chris@40 284 { printf ("Bad juju!! rows = %d cols = %d\n", rows, cols) ;
Chris@40 285 exit (1) ;
Chris@40 286 } ;
Chris@40 287
Chris@40 288 ekey = strtol (result [1], NULL, 10) ;
Chris@40 289
Chris@40 290 sqlite3_free_table (result) ;
Chris@40 291
Chris@40 292 return ekey ;
Chris@40 293 } /* get_ekey_from_filename */
Chris@40 294
Chris@40 295 static int
Chris@40 296 get_filename_pathname_by_ekey (REGTEST_DB * db, int ekey)
Chris@40 297 { char *errmsg, **result ;
Chris@40 298 int err, rows, cols ;
Chris@40 299
Chris@40 300 snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname,fpath from sndfile where ekey='%d'", ekey) ;
Chris@40 301
Chris@40 302 err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ;
Chris@40 303 if (err != SQLITE_OK)
Chris@40 304 { printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
Chris@40 305 puts (db->cmdbuf) ;
Chris@40 306 return 0 ;
Chris@40 307 } ;
Chris@40 308
Chris@40 309 if (cols != 2 || rows != 1)
Chris@40 310 { printf ("\nError (%s %d) : rows = %d cols = %d\n", __func__, __LINE__, rows, cols) ;
Chris@40 311 exit (1) ;
Chris@40 312 } ;
Chris@40 313
Chris@40 314 snprintf (db->filename, sizeof (db->filename), "%s", result [2]) ;
Chris@40 315 snprintf (db->pathname, sizeof (db->pathname), "%s", result [3]) ;
Chris@40 316
Chris@40 317 sqlite3_free_table (result) ;
Chris@40 318
Chris@40 319 return 1 ;
Chris@40 320 } /* get_filename_pathname_by_ekey */
Chris@40 321
Chris@40 322 static int
Chris@40 323 check_file_by_ekey (REGTEST_DB * db, int ekey)
Chris@40 324 { SNDFILE * sndfile ;
Chris@40 325 SF_INFO info ;
Chris@40 326 char * errmsg, **result ;
Chris@40 327 int err, k, rows, cols, checksum ;
Chris@40 328
Chris@40 329 printf (" %s : ", db->filename) ;
Chris@40 330 fflush (stdout) ;
Chris@40 331
Chris@40 332 memset (&info, 0, sizeof (info)) ;
Chris@40 333 sndfile = sf_open (db->pathname, SFM_READ, &info) ;
Chris@40 334 sf_command (sndfile, SFC_GET_LOG_INFO, db->logbuf, sizeof (db->logbuf)) ;
Chris@40 335 checksum = (sndfile == NULL) ? 0 : calc_checksum (sndfile, &info) ;
Chris@40 336 sf_close (sndfile) ;
Chris@40 337
Chris@40 338 if (sndfile == NULL)
Chris@40 339 { printf ("\n\nError : Could not open '%s' : %s\n", db->pathname, sf_strerror (NULL)) ;
Chris@40 340 puts (db->logbuf) ;
Chris@40 341 exit (1) ;
Chris@40 342 } ;
Chris@40 343
Chris@40 344 single_quote_replace (db->logbuf) ;
Chris@40 345
Chris@40 346 snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname,srate,frames,channels,format,"
Chris@40 347 "checksum,logbuf from sndfile where ekey='%d'", ekey) ;
Chris@40 348
Chris@40 349 err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ;
Chris@40 350 if (err != SQLITE_OK)
Chris@40 351 { printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ;
Chris@40 352 puts (db->cmdbuf) ;
Chris@40 353 } ;
Chris@40 354
Chris@40 355 for (k = 0 ; k < cols ; k++)
Chris@40 356 { if (strcmp (result [k], "fname") == 0)
Chris@40 357 { if (strcmp (result [k + cols], db->filename) == 0)
Chris@40 358 continue ;
Chris@40 359 printf ("\n\nError : fname doesn't match : %s != %s\n", result [k + cols], db->filename) ;
Chris@40 360 } ;
Chris@40 361
Chris@40 362 if (strcmp (result [k], "srate") == 0)
Chris@40 363 { if (strtol (result [k + cols], NULL, 10) == info.samplerate)
Chris@40 364 continue ;
Chris@40 365 printf ("\n\nError : srate doesn't match : %s == %d\n", result [k + cols], info.samplerate) ;
Chris@40 366 } ;
Chris@40 367
Chris@40 368 if (strcmp (result [k], "frames") == 0)
Chris@40 369 { if (strtoll (result [k + cols], NULL, 10) == info.frames)
Chris@40 370 continue ;
Chris@40 371 printf ("\n\nError : frames doesn't match : %s == %ld\n", result [k + cols], (long) info.frames) ;
Chris@40 372 } ;
Chris@40 373
Chris@40 374 if (strcmp (result [k], "channels") == 0)
Chris@40 375 { if (strtol (result [k + cols], NULL, 10) == info.channels)
Chris@40 376 continue ;
Chris@40 377 printf ("\n\nError : channels doesn't match : %s == %d\n", result [k + cols], info.channels) ;
Chris@40 378 } ;
Chris@40 379
Chris@40 380 if (strcmp (result [k], "format") == 0)
Chris@40 381 { if (strtol (result [k + cols], NULL, 16) == info.format)
Chris@40 382 continue ;
Chris@40 383 printf ("\n\nError : format doesn't match : %s == 0x%08x\n", result [k + cols], info.format) ;
Chris@40 384 } ;
Chris@40 385
Chris@40 386 if (strcmp (result [k], "checksum") == 0)
Chris@40 387 { int db_val = (int) strtoll (result [k + cols], NULL, 16) ;
Chris@40 388
Chris@40 389 if (db_val == checksum)
Chris@40 390 continue ;
Chris@40 391 printf ("\n\nError : checksum doesn't match : 0x%08x == 0x%08x\n", db_val, checksum) ;
Chris@40 392 } ;
Chris@40 393
Chris@40 394 if (strcmp (result [k], "logbuf") == 0)
Chris@40 395 continue ;
Chris@40 396
Chris@40 397 printf ("\nHere is the old logubuffer :\n\n%s\n\nand the new :\n\n%s\n\n", result [2 * cols - 1], db->logbuf) ;
Chris@40 398 exit (1) ;
Chris@40 399 } ;
Chris@40 400
Chris@40 401 sqlite3_free_table (result) ;
Chris@40 402
Chris@40 403 puts ("ok") ;
Chris@40 404
Chris@40 405 return 0 ;
Chris@40 406 } /* check_file_by_ekey */
Chris@40 407
Chris@40 408 /*==============================================================================
Chris@40 409 */
Chris@40 410
Chris@40 411 static void
Chris@40 412 get_filename_pathname (REGTEST_DB * db, const char *filepath)
Chris@40 413 { const char * cptr ;
Chris@40 414 int slen ;
Chris@40 415
Chris@40 416 if (filepath [0] != '/')
Chris@40 417 { memset (db->pathname, 0, sizeof (db->pathname)) ;
Chris@40 418 if (getcwd (db->pathname, sizeof (db->pathname)) == NULL)
Chris@40 419 { perror ("\ngetcwd failed") ;
Chris@40 420 exit (1) ;
Chris@40 421 } ;
Chris@40 422
Chris@40 423 slen = strlen (db->pathname) ;
Chris@40 424 db->pathname [slen ++] = '/' ;
Chris@40 425 snprintf (db->pathname + slen, sizeof (db->pathname) - slen, "%s", filepath) ;
Chris@40 426 }
Chris@40 427 else
Chris@40 428 snprintf (db->pathname, sizeof (db->pathname), "%s", filepath) ;
Chris@40 429
Chris@40 430 if ((cptr = strrchr (db->pathname, '/')) == NULL)
Chris@40 431 { printf ("\nError : bad pathname %s\n", filepath) ;
Chris@40 432 exit (1) ;
Chris@40 433 } ;
Chris@40 434
Chris@40 435 snprintf (db->filename, sizeof (db->filename), "%s", cptr + 1) ;
Chris@40 436 } /* get filename_pathname */
Chris@40 437
Chris@40 438 static void
Chris@40 439 single_quote_replace (char * buf)
Chris@40 440 { while ((buf = strchr (buf, '\'')) != 0)
Chris@40 441 buf [0] = '"' ;
Chris@40 442 } /* single_quote_replace */
Chris@40 443
Chris@40 444 static int
Chris@40 445 count_callback (REGTEST_DB * db, int argc, char **argv, char **colname)
Chris@40 446 { db->count ++ ;
Chris@40 447
Chris@40 448 (void) argc ;
Chris@40 449 (void) argv ;
Chris@40 450 (void) colname ;
Chris@40 451 return 0 ;
Chris@40 452 } /* count_callback */
Chris@40 453
Chris@40 454 static int
Chris@40 455 ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **unused)
Chris@40 456 { int ekey ;
Chris@40 457
Chris@40 458 (void) argc ;
Chris@40 459 (void) unused ;
Chris@40 460
Chris@40 461 ekey = strtol (argv [0], NULL, 10) ;
Chris@40 462 if (ekey > db->ekey_max)
Chris@40 463 db->ekey_max = ekey ;
Chris@40 464
Chris@40 465 return 0 ;
Chris@40 466 } /* ekey_max_callback */
Chris@40 467
Chris@40 468 static int
Chris@40 469 callback (void *unused, int argc, char **argv, char **colname)
Chris@40 470 { int k ;
Chris@40 471
Chris@40 472 (void) unused ;
Chris@40 473
Chris@40 474 for (k = 0 ; k < argc ; k++)
Chris@40 475 printf ("%s = %s\n", colname [k], argv [k] ? argv [k] : "NULL") ;
Chris@40 476
Chris@40 477 printf ("\n") ;
Chris@40 478
Chris@40 479 return 0 ;
Chris@40 480 } /* callback */
Chris@40 481
Chris@40 482 #else
Chris@40 483
Chris@40 484 int dummy (void) ;
Chris@40 485
Chris@40 486 int
Chris@40 487 dummy (void)
Chris@40 488 { /*
Chris@40 489 ** Empty dummy fnction so tha compiler doesn't winge about an
Chris@40 490 ** empty file.
Chris@40 491 */
Chris@40 492 return 0 ;
Chris@40 493 } /* dummy */
Chris@40 494
Chris@40 495 #endif