source: git/factory/ftest/ftest_util.cc @ 341696

spielwiese
Last change on this file since 341696 was 341696, checked in by Hans Schönemann <hannes@…>, 14 years ago
Adding Id property to all files git-svn-id: file:///usr/local/Singular/svn/trunk@12231 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 26.8 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id$ */
3
4//{{{ docu
5//
6// ftest_util.cc - some utilities for the factory test environment.
7//
8//}}}
9
10#include <stdio.h>
11#include <stdarg.h>
12#include <stdlib.h>
13#include <signal.h>
14#include <string.h>
15#include <ctype.h>
16#include <errno.h>
17#include <unistd.h>
18#include <iostream.h>
19#include <fstream.h>
20
21// we include timing.h for calculation of HZ only
22#define TIMING
23#include <timing.h>
24
25#include <factory.h>
26
27// we include `cf_switches.h' for the maximum number of switches
28// and hope that we will not get any conflicts
29#include <cf_switches.h>
30
31#include "ftest_util.h"
32#include "ftest_io.h"
33
34//{{{ struct varSpecT
35struct varSpecT
36{
37    char variable;
38    CanonicalForm mipo;
39    varSpecT * next;
40};
41//}}}
42
43//{{{ struct ftestEnvT
44//{{{ docu
45//
46// struct ftestEnvT - factory environment.
47//
48//}}}
49struct ftestEnvT
50{
51    int seed;
52    bool seedSet;
53    int characteristic;
54    int extDegree;
55    char extGen;
56    varSpecT * varSpec;
57    bool switches[CFSwitchesMax];
58};
59//}}}
60
61//{{{ external variables
62//{{{ docu
63//
64// - external variables.
65//
66// ftestCircle: set by ftestGetOpts() from commandline, read by
67//   main().  Number of test circles.
68// ftestAlarm: set by ftestGetOpts() from commandline, read by
69//   main().
70// ftestCheckFlag: set by ftestGetOpts() from commandline, read by
71//   main().  False iff checks should not be executed.
72// ftestPrintFlag: set by ftestParseOutputType() from
73//   commandline, read by ftestPrintResult().  True iff there was
74//   some output type specifier on commandline.
75// ftestPrintResultFlag: set by ftestParseOutputType() from
76//   commandline, read by output routines.  Whether to print result
77//   or not.
78//
79//}}}
80int ftestCircle = 1;
81int ftestAlarm = 0;
82
83int ftestCheckFlag = 1;
84
85int ftestPrintFlag = 0;
86int ftestPrintResultFlag = 0;
87//}}}
88
89//{{{ static variables
90//{{{ docu
91//
92// - static variables.
93//
94// ftestPrint*Flag: set by ftestParseOutputType() from
95//   commandline, read by output routines.  Things to print/not to
96//   print.  Note that we need `ftestPrintFlag' and
97//   `ftestPrintResultFlag' to be external.
98// ftestExecName, ftestAlgorithmName: set by ftestSetName(), read
99//   by output routines.  Name of executable and algorithm.
100// ftestUsage: set by ftestSetName(), read by ftestUsagePrint().
101//   Algorithm-specific usage information.
102// ftestEnv: factory environment specification.  Set by
103//   ftestGetEnv(), read by ftestPrintEnv() function.  This
104//   variable is quite spurious, but I keep it for future use.
105// ftestSwitchNames: symbolic names of switches
106// ftestSeedFile: file where to read/to which to print the random
107//   generator seed.  Set by ftestParseRandom(), read by
108//   ftestWriteSeed().
109//
110//}}}
111static int ftestPrintTimingFlag = 0;
112static int ftestPrintCheckFlag = 0;
113static int ftestPrintEnvFlag = 0;
114
115const char * ftestExecName = 0;
116const char * ftestAlgorithmName = 0;
117const char * ftestUsage = 0;
118
119static ftestEnvT ftestEnv;
120
121const char * ftestSwitchNames[] =
122{
123    "RATIONAL",
124    "QUOTIENT",
125    "SYMMETRIC_FF",
126    "BERLEKAMP",
127    "FAC_USE_BIG_PRIMES",
128    "FAC_QUADRATICLIFT",
129    "USE_EZGCD",
130    "USE_SPARSEMOD"
131};
132
133static char * ftestSeedFile = 0;
134//}}}
135
136//
137// - static functions.
138//
139
140//{{{ static char * ftestConcatEnv ( char ** argv, int & optind )
141//{{{ docu
142//
143// ftestConcatEnv() - concatenate all environment information
144//   together and return the result.
145//
146// The new index into the commandline is returned in optind.
147//
148//}}}
149static char *
150ftestConcatEnv ( char ** argv, int & optind )
151{
152    // first get length
153    int i = optind;
154    int len = 0;
155    const char * envString = getenv( "FTEST_ENV" );
156    if ( envString )
157        len = strlen( envString );
158
159    while ( (argv[i] != 0) && (*ftestSkipBlancs( argv[i] ) == '/') ) {
160        len += strlen( argv[i] );
161        i++;
162    }
163
164    char * fEnvString = new char[len+1];
165
166    // now build string
167    fEnvString[0] = '\0';
168    if ( envString )
169        strcat( fEnvString, envString );
170
171    while ( optind < i ) {
172        strcat( fEnvString, argv[optind] );
173        optind++;
174    }
175
176    return fEnvString;
177}
178//}}}
179
180//{{{ static const char * ftestParseRandom ( const char * tokenString )
181//{{{ docu
182//
183// ftestParseRandom() - parse random specification and set factory's
184//   random generator seed.
185//
186// The results are also stored in global variable `ftestEnv'.
187// Returns pointer behind last parsed character in tokenString.
188//
189//}}}
190static const char *
191ftestParseRandom ( const char * tokenString )
192{
193    int seed = 0;
194    bool seedSet = false;
195
196    do {
197        const char * tokenCursor;
198
199        // we skip either `@' or `,'
200        tokenString = ftestSkipBlancs( tokenString+1 );
201        if ( isdigit( *tokenString ) ) {
202            // read seed specification from command line
203            seed = (int)strtol( tokenString, (char **)&tokenCursor, 0 );
204            if ( tokenCursor == tokenString )
205                ftestError( EnvSyntaxError,
206                            "bad seed specification `%s'\n",
207                            tokenString );
208            seedSet = true;
209        } else if ( isalpha( *tokenString ) ) {
210            // read seed specification from file
211            tokenCursor = strpbrk( tokenString, ",/" );
212            if ( ! tokenCursor )
213                tokenCursor = strchr( tokenString, '\0' );
214
215            // store file name
216            int nameLen = tokenCursor-tokenString;
217            ftestSeedFile = new char[nameLen+1];
218            strncpy( ftestSeedFile, tokenString, nameLen );
219            ftestSeedFile[nameLen] = '\0';
220
221            // open file, read seed, close file
222            ifstream seedStream( ftestSeedFile );
223            if ( ! seedStream ) {
224                if ( errno != ENOENT )
225                    ftestError( FileError,
226                                "failed to open `%s' for reading: %s\n", ftestSeedFile,
227                                strerror( errno ) );
228                else if ( ! (ftestEnv.seedSet || seedSet) ) {
229                    // if file does not exist, set seed to some
230                    // default value if it has not been set before
231                    seed = 0;
232                    seedSet = true;
233                }
234            } else {
235                // if file exists, read seed
236                seedStream >> seed;
237                if ( ! seedStream )
238                    ftestError( FileError,
239                                "garbled seed in seed file `%s'\n", ftestSeedFile );
240
241                seedSet = true;
242            }
243        } else
244            ftestError( EnvSyntaxError,
245                        "bad random specification `%s'\n", tokenString );
246
247        tokenString = ftestSkipBlancs( tokenCursor );
248    } while ( *tokenString == ',' );
249
250    // set seed
251    ftestEnv.seedSet = seedSet;
252    if ( seedSet ) {
253        ftestEnv.seed = seed;
254        factoryseed( seed );
255    }
256
257    return tokenString;
258}
259//}}}
260
261//{{{ static const char * ftestParseChar ( const char * tokenString )
262//{{{ docu
263//
264// ftestParseChar() - parse characteristic specification and set factory's
265//   characteristic.
266//
267// The results are also stored in global variable `ftestEnv'.
268// Returns pointer behind last parsed character in tokenString.
269//
270//}}}
271static const char *
272ftestParseChar ( const char * tokenString )
273{
274    const char * tokenCursor;
275    int characteristic = 0;
276    int extDegree = 0;
277    char extGen = 'Z';
278
279    characteristic = (int)strtol( tokenString, (char **)&tokenCursor, 0 );
280    tokenString = ftestSkipBlancs( tokenCursor );
281
282    // look for exponent
283    if ( *tokenString == '^' ) {
284        tokenString++;
285        extDegree = (int)strtol( tokenString, (char **)&tokenCursor, 0 );
286        if ( tokenCursor == tokenString )
287            ftestError( EnvSyntaxError,
288                        "bad exponent in char specification `%s'\n",
289                        tokenString );
290        tokenString = ftestSkipBlancs( tokenCursor );
291        // look for generator
292        if ( *tokenString == ',' ) {
293            tokenString = ftestSkipBlancs( tokenString+1 );
294            if ( isalpha( *tokenString ) ) {
295                extGen = *tokenString;
296                tokenString++;
297            } else
298                ftestError( EnvSyntaxError,
299                            "bad generator in char specification `%s'\n",
300                            tokenString );
301        }
302    }
303
304    // set characteristic
305    ftestEnv.characteristic = characteristic;
306    if ( extDegree ) {
307        ftestEnv.extDegree = extDegree;
308        ftestEnv.extGen = extGen;
309        setCharacteristic( characteristic, extDegree, extGen );
310    } else
311        setCharacteristic( characteristic );
312
313    return tokenString;
314}
315//}}}
316
317//{{{ static const char * ftestParseSwitches ( const char * tokenString )
318//{{{ docu
319//
320// ftestParseSwitches() - parse switch specification and set factory's
321//   switches.
322//
323// The results are also stored in global variable `ftestEnv'.
324// Returns pointer behind last parsed character in tokenString.
325//
326//}}}
327static const char *
328ftestParseSwitches ( const char * tokenString )
329{
330    unsigned int switchNumber;
331    bool switchSetting;
332
333    while ( *tokenString == '+' || *tokenString == '-' ) {
334        const char * tokenCursor;
335        if ( *tokenString == '+' )
336            switchSetting = true;
337        else
338            switchSetting = false;
339        tokenString = ftestSkipBlancs( tokenString+1 );
340
341        // skip optional leading "SW_"
342        tokenString = ftestSubStr( "SW_", tokenString );
343
344        // now search name of switch
345        for ( switchNumber = 0;
346              switchNumber < sizeof( ftestSwitchNames ) / sizeof( char* );
347              switchNumber++ )
348            if ( (tokenCursor = ftestSubStr( ftestSwitchNames[switchNumber], tokenString ))
349                 != tokenString )
350                break;
351
352        if ( tokenCursor == tokenString )
353            ftestError( EnvSyntaxError,
354                        "unknown switch `%s'\n", tokenString );
355
356        // set switch
357        ftestEnv.switches[switchNumber] = switchSetting;
358        if ( switchSetting )
359            On( switchNumber );
360        else
361            Off( switchNumber );
362
363        tokenString = ftestSkipBlancs( tokenCursor );
364    }
365
366    return tokenString;
367}
368//}}}
369
370//{{{ static const char * ftestParseVars ( const char * tokenString )
371//{{{ docu
372//
373// ftestParseVars() - parse variable specification and set factory's
374//   variable.
375//
376// The results are also stored in global variable `ftestEnv'.
377// Returns pointer behind last parsed character in tokenString.
378//
379//}}}
380static const char *
381ftestParseVars ( const char * tokenString )
382{
383    char variable;
384    CanonicalForm mipo = 0;
385    Variable * dummy;
386
387    // we append at end of list
388    static varSpecT * endOfVarSpec = 0;
389    varSpecT * varSpec;
390
391    while ( isalpha( *tokenString ) ) {
392        variable = *tokenString;
393        mipo = 0;
394
395        tokenString = ftestSkipBlancs( tokenString+1 );
396
397        // look for mipo
398        if ( *tokenString == '=' ) {
399            const char * tokenCursor;
400            tokenString = ftestSkipBlancs( tokenString+1 );
401
402            // search for end of mipo
403            tokenCursor = strpbrk( tokenString, ",/" );
404            if ( ! tokenCursor )
405                tokenCursor = strchr( tokenString, '\0' );
406
407            // copy mipo to new string and read it
408            int mipoLen = tokenCursor-tokenString;
409            char * mipoString = new char[mipoLen+1];
410            strncpy( mipoString, tokenString, mipoLen );
411            mipoString[mipoLen] = '\0';
412            ftestReadString( mipoString, mipo );
413            delete [] mipoString;
414
415            tokenString = ftestSkipBlancs( tokenCursor );
416        }
417        if ( *tokenString == ',' )
418            // skip optional separator
419            tokenString = ftestSkipBlancs( tokenString+1 );
420
421        // store information in ftestEnv
422        varSpec = new varSpecT;
423        varSpec->variable = variable;
424        varSpec->mipo = mipo;
425        varSpec->next = 0;
426        if ( ftestEnv.varSpec )
427            endOfVarSpec->next = varSpec;
428        else
429            ftestEnv.varSpec = varSpec;
430        endOfVarSpec = varSpec;
431
432        // set variable
433        if ( mipo.isZero() )
434            // polynomial variable
435            dummy = new Variable( variable );
436        else
437            dummy = new Variable( rootOf( mipo, variable ) );
438        // we only need the global information
439        delete dummy;
440    }
441
442    return tokenString;
443}
444//}}}
445
446//{{{ static void ftestParseEnv ( const char * tokenString )
447//{{{ docu
448//
449// ftestParseEnv() - parse environment specification and set factory's
450//   environment.
451//
452// The results are also stored in global variable `ftestEnv'.
453//
454// The parser is quite simple.  As long as `tokenString' starts
455// with a `/', he looks up the next character to determine which
456// token follows and parses it.  The functions used to do this
457// should leave `tokenString' behind the last character it
458// succeeded to read.
459//
460//}}}
461static void
462ftestParseEnv ( const char * tokenString )
463{
464    // read list of environment specifications
465    tokenString = ftestSkipBlancs( tokenString );
466    while ( *tokenString == '/' ) {
467        tokenString = ftestSkipBlancs( tokenString+1 );
468
469        if ( *tokenString == '@' ) {
470            // random specification
471            tokenString = ftestParseRandom( tokenString );
472        } else if ( isdigit( *tokenString ) ) {
473            // specification of characteristics
474            tokenString = ftestParseChar( tokenString );
475        } else if ( *tokenString == '+' || *tokenString == '-' ) {
476            // specification of switches
477            tokenString = ftestParseSwitches( tokenString );
478        } else if ( isalpha( *tokenString ) ) {
479            // specification of variables
480            tokenString = ftestParseVars( tokenString );
481        }
482        tokenString = ftestSkipBlancs( tokenString );
483    }
484   
485    // check if we reached end
486    if ( *tokenString )
487        ftestError( EnvSyntaxError,
488                    "extra characters in environment specification list `%s'\n",
489                    tokenString );
490}
491//}}}
492
493//{{{ static void ftestParseOutputType ( const char * outputType )
494//{{{ docu
495//
496// ftestParseOutputType() - parse output type and set ftestPrint*Flags.
497//
498//}}}
499static void
500ftestParseOutputType ( const char * outputType )
501{
502    ftestPrintFlag = 1;
503    while ( *outputType ) {
504        switch ( *outputType ) {
505        case 'r': ftestPrintResultFlag = 1; break;
506        case 't': ftestPrintTimingFlag = 1; break;
507        case 'c': ftestPrintCheckFlag = 1; break;
508        case 'e': ftestPrintEnvFlag = 1; break;
509        case 'a':
510            ftestPrintResultFlag = 1;
511            ftestPrintCheckFlag = 1;
512            ftestPrintTimingFlag = 1;
513            ftestPrintEnvFlag = 1; break;
514        default: ftestError( CommandlineError, "unknown output type specifier `%c'\n", *outputType );
515        }
516        outputType++;
517    }
518}
519//}}}
520
521//{{{ static void ftestSignalHandler ( int signal ), static void ftestAlarmlHandler ( int )
522//{{{ docu
523//
524// ftestSignalHandler(), ftestAlarmHandler() - signal handlers.
525//
526// Blocks new signals, flushes `cout', and calls `ftestError()'.
527//
528//}}}
529static void
530ftestSignalHandler ( int signal )
531{
532    ftestSignalCatch( true );
533    cout.flush();
534    ftestError( (ftestErrorT)((int)SignalError + signal ),
535                "received signal %d\n", signal );
536}
537static void
538ftestAlarmHandler ( int )
539{
540    ftestSignalCatch( true );
541    cout.flush();
542    ftestError( TimeoutError, "timeout after %d secs\n", ftestAlarm );
543}
544//}}}
545
546//
547// - external functions.
548//
549
550//{{{ const char * ftestSkipBlancs ( const char * string )
551//{{{ docu
552//
553// ftestSkipBlancs() - skip all leading blancs in string.
554//
555// Return new position.
556//
557//}}}
558const char *
559ftestSkipBlancs ( const char * string )
560{
561    while ( *string && isspace( *string ) )
562        string++;
563    return string;
564}
565//}}}
566
567//{{{ char * ftestCutBlancs ( char * string )
568//{{{ docu
569//
570// ftestCutBlancs() - cut off all trailing blancs in `string'.
571//
572// Returns `string' unchanged.
573//
574//}}}
575char *
576ftestCutBlancs ( char * string )
577{
578    char * stringCursor = string + strlen( string );
579
580    while ( (string != stringCursor)
581            && isspace( *(stringCursor-1) ) )
582        stringCursor--;
583
584    *stringCursor = '\0';
585    return string;
586}
587//}}}
588
589//{{{ const char * ftestSubStr ( const char * subString, const char * string )
590//{{{ docu
591//
592// ftestSubStr() - check whether subString is a substring of string.
593//
594// If so, return index behind subString in string, otherwise
595// string.
596//
597//}}}
598const char *
599ftestSubStr ( const char * subString, const char * string )
600{
601    const char * stringStart = string;
602
603    while ( *subString && *subString == *string ) {
604        subString++; string++;
605    }
606
607    if ( *subString )
608        return stringStart;
609    else
610        return string;
611}
612//}}}
613
614//{{{ void ftestError ( ftestErrorT errno, const char * format ... )
615//{{{ docu
616//
617// ftestError() - main error handler.
618//
619// Prints error message consisting of formatString and following
620// arguments, some additional information, and exits with errno.
621// In case of an `CheckError', does not exit but returns to the
622// caller.
623//
624//}}}
625void
626ftestError ( ftestErrorT errno, const char * format ... )
627{
628    // print error message
629    if ( format ) {
630        if ( errno != CheckError )
631            fprintf( stderr, "%s: ", ftestExecName );
632        else
633            fprintf( stderr, "%s(CheckError): ", ftestExecName );
634        va_list ap;
635        va_start( ap, format );
636        vfprintf( stderr, format, ap );
637        va_end( ap );
638    }
639
640    switch ( errno ) {
641    case noError:
642        return;
643    case CommandlineError:
644    case EnvSyntaxError: 
645    case CanFormSpecError:
646        ftestUsagePrint();
647        break;
648    case FileError:
649        break;
650    case CheckError:
651        return;
652    case TimeoutError:
653        if ( ftestPrintTimingFlag )
654            cout << "Time:\t\t> " << (float)ftestAlarm << endl;
655        if ( ftestPrintCheckFlag )
656            cout << "Check:\t\tTime Out" << endl;
657        break;
658    default:
659        if ( ftestPrintCheckFlag )
660            cout << "Check:\t\tReceived Signal " << (int)errno-(int)SignalError << endl;
661    }
662    exit( errno );
663}
664//}}}
665
666//{{{ void ftestUsagePrint ( const char * additionalUsage )
667//{{{ docu
668//
669// ftestUsagePrint() - print usage message to stderr.
670//
671// We use the static variable `ftestUsage' to do so.  If
672// `additionalUsage' is non-zero, we print it after
673// `ftestUsage', otherwise some short reference where to find
674// more information.
675//
676//}}}
677void
678ftestUsagePrint ( const char * additionalUsage )
679{
680    cerr << ftestUsage << flush;
681    if ( ! additionalUsage )
682        cerr << "
683For a descriptions of the features common to all programs of the
684Factory Test Environment, call `feval -?' (exactly in this way).
685" << endl;
686    else
687        cerr << additionalUsage << endl;
688}
689//}}}
690
691//{{{ void ftestSignalCatch ( bool block )
692//{{{ docu
693//
694// ftestSignalCatch() - set signal and alarm handlers.
695//
696// If block is true block the signals instead.
697//
698//}}}
699void
700ftestSignalCatch ( bool block )
701{
702    void (*signalHandler)( int );
703    void (*alarmHandler)( int );
704
705    if ( block ) {
706        signalHandler = 0;
707        alarmHandler = 0;
708    } else {
709        signalHandler = ftestSignalHandler;
710        alarmHandler = ftestAlarmHandler;
711    }
712
713#ifdef SIGHUP
714    signal( SIGHUP, signalHandler );
715#endif
716#ifdef SIGINT
717    signal( SIGINT, signalHandler );
718#endif
719#ifdef SIGQUIT
720    signal( SIGQUIT, signalHandler );
721#endif
722#ifdef SIGILL
723    signal( SIGILL, signalHandler );
724#endif
725#ifdef SIGIOT
726    signal( SIGIOT, signalHandler );
727#endif
728#ifdef SIGFPE
729    signal( SIGFPE, signalHandler );
730#endif
731#ifdef SIGBUS
732    signal( SIGBUS, signalHandler );
733#endif
734#ifdef SIGSEGV
735    signal( SIGSEGV, signalHandler );
736#endif
737#ifdef SIGTERM
738    signal( SIGTERM, signalHandler );
739#endif
740
741    // alarm handler
742    signal( SIGALRM, alarmHandler );
743}
744//}}}
745
746//{{{ void ftestSetName ( const char * execName, const char * algorithmName, const char * usage )
747//{{{ docu
748//
749// ftestSetName() - set name of executable and algorithm.
750//
751//}}}
752void
753ftestSetName ( const char * execName, const char * algorithmName, const char * usage )
754{
755    ftestExecName = execName;
756    ftestAlgorithmName = algorithmName;
757    ftestUsage = usage;
758}
759//}}}
760
761//{{{ void ftestGetOpts ( int argc, char ** argv, int & optind )
762//{{{ docu
763//
764// ftestGetOpts() - read options from commandline.
765//
766// Returns new index into commandline in `optind'.
767//
768//}}}
769void
770ftestGetOpts ( int argc, char ** argv, int & optind )
771{
772    // parse command line
773    int optionChar;
774    const char * outputType = 0;
775    const char * envString = 0;
776
777    // read from environment first
778    envString = getenv( "FTEST_ALARM" );
779    if ( envString )
780        ftestAlarm = (int)strtol( envString, 0, 0 );
781    envString = getenv( "FTEST_CIRCLE" );
782    if ( envString )
783        ftestCircle = (int)strtol( envString, 0, 0 );
784
785    // parse options
786    while ( (optionChar = getopt( argc, argv, "a:o:c:t" )) != -1 ) {
787        switch ( optionChar ) {
788        case 'a': ftestAlarm = (int)strtol( optarg, 0, 0 ); break;
789        case 'c': ftestCircle = (int)strtol( optarg, 0, 0 ); break;
790        case 'o': outputType = optarg; break;
791        case 't': ftestCheckFlag = false; break;
792        default: ftestError( CommandlineError, 0 );
793        }
794    }
795    optind = ::optind;
796
797    if ( outputType )
798        ftestParseOutputType( outputType );
799}
800//}}}
801
802//{{{ void ftestGetEnv ( int, char ** argv, int & optind )
803//{{{ docu
804//
805// ftestGetEnv() - read factory environment specs, set environment.
806//
807// The new index into the commandline is returned in optind.
808// The results are stored in global variable `ftestEnv'.
809//
810//}}}
811void
812ftestGetEnv ( int, char ** argv, int & optind )
813{
814    // initialize environment
815    ftestEnv.seed = 0;
816    ftestEnv.seedSet = false;
817    ftestEnv.characteristic = 0;
818    ftestEnv.extDegree = 0;
819    ftestEnv.extGen = 'Z';
820    ftestEnv.varSpec = 0;
821    for ( int i = 0; i < CFSwitchesMax; i++ )
822        ftestEnv.switches[i] = false;
823
824    char * envString = ftestConcatEnv( argv, optind );
825    ftestParseEnv( envString );
826    delete [] envString;
827}
828//}}}
829
830//{{{ bool ftestSearchTaggedArg ( int, char ** argv, int & optind, const char * optionTag )
831//{{{ docu
832//
833// ftestSearchTaggedArg() - search for tagged argument.
834//
835// If the current argument (`argv[ optind ]') is of the form
836// `<tag>=<value>', where `<tag>' is a substring of
837// `<optionTag>', the current argument is modified to point
838// directly after the `=' sign and `true' is returned.
839//
840// Otherwise, `false' is returned.
841//
842// Note: There may be arbitrary white-space between the several
843// tokens of the tagged argument, but the tokens must not span
844// more than one argument.
845//
846//}}}
847bool
848ftestSearchTaggedArg ( int, char ** argv, int & optind, const char * optionTag )
849{
850    const char * tokenCursor;
851    const char * tokenString = argv[ optind ];
852    int tokenLen;
853
854    // check for end of argument list
855    if ( ! tokenString )
856        return false;
857
858    // skip leading blancs
859    tokenString = ftestSkipBlancs( tokenString );
860
861    // check whether it is a tagged argument
862    tokenCursor = strchr( tokenString, '=' );
863    if ( ! tokenCursor )
864        return false;
865    tokenLen = tokenCursor - tokenString;
866
867    // isolate possible keyword
868    char * keyword = new char[ tokenLen+1 ];
869    strncpy( keyword, tokenString, tokenLen );
870    keyword[ tokenLen ] = '\0';
871    ftestCutBlancs( keyword );
872
873    // advance tokenString after `=' sign
874    tokenString = tokenCursor+1;
875
876    // check whether keyword is a substring of `optionTag'
877    tokenCursor = ftestSubStr( keyword, optionTag );
878    if ( tokenCursor == optionTag ) {
879        // optionTag not found
880        delete [] keyword;
881        return false;
882    } else {
883        argv[ optind ] = (char *)tokenString;
884        return true;
885    }
886}
887//}}}
888
889//{{{ void ftestWriteSeed ()
890//{{{ docu
891//
892// ftestWriteSeed() - write current seed to seed file.
893//
894//}}}
895void
896ftestWriteSeed ()
897{
898    if ( ftestSeedFile ) {
899        ofstream seedStream( ftestSeedFile );
900        if ( ! seedStream )
901            ftestError( FileError,
902                        "failed to open `%s' for writing: %s\n", ftestSeedFile,
903                        strerror( errno ) );
904        seedStream << factoryrandom( 0 ) << endl;
905    }
906}
907//}}}
908
909//{{{ void ftestPrintTimer ( long timer )
910//{{{ docu
911//
912// ftestPrintTimer() - print value of timer.
913//
914//}}}
915void
916ftestPrintTimer ( long timer )
917{
918    if ( ftestPrintTimingFlag )
919        cout << "Time:\t\t" << (float)timer / HZ << endl;
920}
921//}}}
922
923//{{{ void ftestPrintCheck ( ftestSatusT check )
924//{{{ docu
925//
926// ftestPrintCheck() - print status of checks.
927//
928//}}}
929void
930ftestPrintCheck ( ftestStatusT check )
931{
932    if ( ftestPrintCheckFlag ) {
933        char * checkStr = 0;
934
935        switch (check) {
936        case Passed: checkStr = "Passed"; break;
937        case Failed: checkStr = "Failed"; break;
938        case UndefinedResult: checkStr = "Undefined"; break;
939        default: checkStr = "Error!";
940        }
941
942        cout << "Check:\t\t" << checkStr << endl;
943    }
944}
945//}}}
946
947//{{{ void ftestPrintEnv ()
948//{{{ docu
949//
950// ftestPrintEnv() - print current factory environment.
951//
952// The environment ist read from `ftestEnv'.
953//
954//}}}
955void
956ftestPrintEnv ()
957{
958    if ( ftestPrintEnvFlag ) {
959        // characteristic
960        if ( ftestEnv.extDegree )
961            cout << "Characteristic:\t" << ftestEnv.characteristic
962                 << '^' << ftestEnv.extDegree
963                 << '(' << ftestEnv.extGen << ')' << endl;
964        else
965            cout << "Characteristic:\t" << ftestEnv.characteristic << endl;
966
967        // switches
968        bool switchSet = false;
969        cout << "Switches:\t";
970        for ( int i = 0; i < CFSwitchesMax; i++ )
971            if ( ftestEnv.switches[i] ) {
972                switchSet = true;
973                cout << ftestSwitchNames[i] << ' ';
974            }
975        if ( ! switchSet )
976            cout << "(not set)" << endl;
977        else
978            cout << endl;
979
980        // variables
981        varSpecT * varSpec = ftestEnv.varSpec;
982        cout << "Variables:\t";
983        if ( ! varSpec )
984            cout << "(not specified)" << endl;
985        else {
986            while ( varSpec ) {
987                if ( varSpec->mipo.isZero() )
988                    cout << varSpec->variable
989                         << "(" << Variable( varSpec->variable ).level() << ") ";
990                else {
991                    cout << varSpec->variable
992                         << "(" << Variable( varSpec->variable ).level()
993                         << ", " << varSpec->mipo << ") ";
994                }
995                varSpec = varSpec->next;
996            }
997            cout << endl;
998        }
999
1000        // number of repetitions
1001        cout << "Circles:\t" << ftestCircle << endl;
1002
1003        // random generator seed
1004        if ( ftestEnv.seedSet )
1005            cout << "Seed:\t\t" << ftestEnv.seed << endl;
1006        else
1007            cout << "Seed:\t\t(not set)" << endl;
1008
1009        // factory version
1010        const char * version;
1011        version = strchr( factoryVersion, '=' )+2;
1012        cout << "Version:\t" << version << endl;
1013    }
1014}
1015//}}}
1016
1017//
1018// - garbage.
1019//
1020
1021#if 0
1022//{{{ static size_t ftestStrLen( const char * string )
1023//{{{ docu
1024//
1025// ftestStrLen() - return length of string, 0 for zero pointer.
1026//
1027//}}}
1028static size_t
1029ftestStrLen( const char * string )
1030{
1031    return string ? strlen( string ) : 0;
1032}
1033//}}}
1034
1035//{{{ static char * ftestStrCat (char * to, const char * from)
1036//{{{ docu
1037//
1038// ftestStrCat() - concatenate (maybe empty) from and to.
1039//
1040//}}}
1041static char *
1042ftestStrCat (char * to, const char * from)
1043{
1044    if ( from )
1045        strcat( to, from );
1046    return to;
1047}
1048//}}}
1049
1050//{{{ static void ftestSetRandom ()
1051//{{{ docu
1052//
1053// ftestSetRandom() - set random generator seed from `ftestEnv'.
1054//
1055// This function is quite spurious, but I keep it for future
1056// use.
1057//
1058//}}}
1059static void
1060ftestSetRandom ()
1061{
1062    if ( ftestEnv.seedSet )
1063        factoryseed( ftestEnv.seed );
1064}
1065//}}}
1066
1067//{{{ static void ftestSetChar ( bool reset = false )
1068//{{{ docu
1069//
1070// ftestSetChar() - set characteristic from `ftestEnv'.
1071//
1072// If reset is true, reset characteristic to default.
1073//
1074// This function is quite spurious, but I keep it for future
1075// use.
1076//
1077//}}}
1078static void
1079ftestSetChar ( bool reset = false )
1080{
1081    if ( reset )
1082        setCharacteristic( 0 );
1083    else
1084        if ( ftestEnv.extDegree )
1085            setCharacteristic( ftestEnv.characteristic,
1086                               ftestEnv.extDegree,
1087                               ftestEnv.extGen );
1088        else
1089            setCharacteristic( ftestEnv.characteristic );
1090}
1091//}}}
1092
1093//{{{ static void ftestSetSwitches ( bool reset = false )
1094//{{{ docu
1095//
1096// ftestSetSwitches() - set switches from `ftestEnv'.
1097//
1098// If reset is true, reset switches to default.
1099//
1100// This function is quite spurious, but I keep it for future
1101// use.
1102//
1103//}}}
1104static void
1105ftestSetSwitches ( bool reset = false )
1106{
1107    int i;
1108
1109    if ( reset )
1110        for ( i = 0; i < CFSwitchesMax; i ++ )
1111            Off( i );
1112    else
1113        for ( i = 0; i < CFSwitchesMax; i ++ )
1114            if ( ftestEnv.switches[i] )
1115                On( i );
1116}
1117//}}}
1118
1119//{{{ static void ftestSetVars ()
1120//{{{ docu
1121//
1122// ftestSetVars() - set variables from `ftestEnv'.
1123//
1124// This function is quite spurious, but I keep it for future
1125// use.
1126//
1127//}}}
1128static void
1129ftestSetVars ()
1130{
1131    varSpecT * varSpec = ftestEnv.varSpec;
1132    Variable * dummy;
1133
1134    while ( varSpec ) {
1135        if ( varSpec->mipo.isZero() )
1136            // polynomial variable
1137            dummy = new Variable( varSpec->variable );
1138        else
1139            dummy = new Variable( rootOf( varSpec->mipo, varSpec->variable ) );
1140
1141        varSpec = varSpec->next;
1142    }
1143}
1144//}}}
1145
1146//{{{ void ftestSetEnv ()
1147//{{{ docu
1148//
1149// ftestSetEnv() - set environment from `ftestEnv'.
1150//
1151// This function is quite spurious, but I keep it for future
1152// use.
1153//
1154//}}}
1155void
1156ftestSetEnv ()
1157{
1158    ftestSetRandom();
1159    ftestSetSwitches();
1160    ftestSetChar();
1161    ftestSetVars();
1162}
1163//}}}
1164#endif
Note: See TracBrowser for help on using the repository browser.