1
/* GLROUTINES.C - general library routines
2
* Copyright 1998-2002 Stephen C. Grubb (ploticus.sourceforge.net) .
3
* This code is covered under the GNU General Public License (GPL);
4
* see the file ./Copyright for details. */
6
/* OS-specific #defines in rand() below. */
12
#define stricmp( s, t ) strcasecmp( s, t )
13
#define strnicmp( s, t, n ) strncasecmp( s, t, n )
15
#define DATAMAXLEN 256
20
static int getdecplaces();
23
static char Sep = ','; /* separator character for lists */
24
static int domember();
25
static char Gettok_buf[256];
26
static char starsym = '*';
27
static int Maxlen = 99999;
30
/* ================================= */
31
/* thanks to Markus Hoenicka for this more portable sysdate and systime code */
32
/* SYSDATE - get today's date */
34
GL_sysdate( mon, day, yr )
40
ltime = localtime(&clock);
41
*mon = ltime->tm_mon + 1;
42
*day = ltime->tm_mday;
44
if( (*yr) >= 100 ) (*yr) = (*yr) % 100; /* scg y2k 11/10/98 */
48
/* ================================= */
49
/* SYSTIME - get current time */
50
GL_systime( hour, min, sec )
51
int *hour, *min, *sec ;
56
ltime = localtime(&clock);
57
*hour = ltime->tm_hour;
64
/* ===================================================== */
65
/* RAND returns a "random" number between 0.0 and 1.0 */
71
srand( getpid() % 1000 );
74
r = rand() / (double)(RAND_MAX);
75
if( r < 0.0 || r > 1.0 ) { printf( "%f: rand return out of range\n", r ); exit(1); }
80
/* ============================================= */
81
/* GETOK - copied so that buffer size could be increased.. */
83
char *GL_getok( string, index )
88
while( GL_member( string[(*index)], " \t\n" ) ) (*index)++;
91
string[*index] != ' ' &&
92
string[*index] != '\t' &&
93
string[*index] != '\n' &&
94
string[*index] != '\0' ;
95
Gettok_buf[n++] = string[(*index)++] ) ;
96
Gettok_buf[n] = '\0' ;
100
/* ===================================================================== */
101
/* SMEMBER - look for s in list t (white-space delimited). Case sensitive.
102
If found return 1 else 0. */
107
char tok[DATAMAXLEN+1], *GL_getok();
111
strcpy( tok, GL_getok( t, &i ) );
112
if( tok[0] == '\0' ) break;
113
if( strcmp( tok, s ) == 0 ) return( 1 );
117
/* ===================================================================== */
118
/* SMEMBERI - look for s in list t (white-space delimited). Case insensitive.
119
If found return 1 else 0. */
124
char tok[DATAMAXLEN+1], *GL_getok();
128
strcpy( tok, GL_getok( t, &i ) );
129
if( tok[0] == '\0' ) break;
130
if( stricmp( tok, s ) == 0 ) return( 1 );
135
/* =========================================== */
136
/* SLMEMBER - Return 1 if str is matches any items in list.
137
List is a space-delimited list of tokens. The tokens in the
138
list may contain ? or * wildcard characters. The match is
143
GL_slmember( str, list )
147
char tok[100], *GL_getok();
151
strcpy( tok, GL_getok( list, &i ) );
152
if( tok[0] == '\0' ) break;
153
if( GL_wildcmp( str, tok, strlen(tok), 0 ) == 0 ) return( 1 );
159
/* ====================================================================== */
160
/* MEMBER - returns char position if character c is a member of string s,
161
0 otherwise. Char positions start with 1 for this purpose. */
166
for( i = 0, len = strlen( s ); i < len; i++ ) if( s[i] == c ) return( i+1 );
171
/* ===================================================================== */
172
/* GOODNUM - checks a token to see if it is a legal number. Returns 1 = yes 0 = no.
173
'prec' is returned.. and is the precision of the number (position of decimal point).
175
Number may contain unary + or -, and one decimal point.
176
Leading and trailing whitespace are discarded before determining
177
whether the case is a valid number or not.
180
GL_goodnum( str, prec )
184
int i, start, len, p, bad;
189
/* find limit of trailing whitespace.. */
190
for( i = len-1; i >= 0; i-- ) if( !isspace( str[i] ) ) break;
193
/* skip over leading whitespace.. */
194
for( i = 0; i < len; i++ ) if( !isspace( str[i] ) ) break;
197
/* screen out degenerate cases.. */
198
if( len < 1 ) return( 0 ); /* degenerate case "" */
199
if( len-start == 1 && ( str[start] == '.' || str[start] == '+' || str[start] == '-' ) )
200
return( 0 ); /* degenerate case; ".", "+", "-" */
202
/* check invididual characters.. */
203
for( p = start; p < len; p++ ) {
204
if( str[p] == '.' ) {
205
if( *prec == -1 ) *prec = p;
208
else if( p == start && ( str[p] == '-' || str[p] == '+' ) );
209
else if( ! isdigit( str[p]) ) bad=1;
213
if( bad ) return( 0 );
217
/* =========================================== */
218
/* GETSEG - Get fields, which are delimited by any member of sepstring.
219
Similar to GL_getchunk(); however
220
Whereas GL_getchunk() skips over adjacent separators,
221
this routine delimits on EACH separator character encountered,
222
Also, separator character is ignored if preceded in inbuf by a backslash(\).
224
Returns 1 when end-of-line is reached and no token is being returned.
230
GL_getseg( rtn, inbuf, i, sep )
245
if( inbuf[*i] == '\0' ) {
246
if( n == 0 ) eol = 1;
249
else if( GL_member( inbuf[*i], sep ) && !escaping ) { (*i)++; break; }
250
else if( inbuf[*i] == '\\' && GL_member( inbuf[(*i)+1], sep ) ) {
255
else rtn[n++] = inbuf[(*i)++];
256
if( n >= 511 ) break; /* 512 max */
263
/* ==================================================================== */
264
/* GETCHUNK - Get tokens, which are separated by any member of sepstring */
266
GL_getchunk( rtn, line, i, sepstring )
275
while( GL_member( line[(*i)], sepstring ) ) (*i)++;
279
if( GL_member( line[*i], sepstring ) || line[*i] == '\0' ) break;
280
else rtn[n++] = line[(*i)++];
281
if( n >= (Maxlen-1) ) break;
286
/* ==================================================================== */
287
/* SETMAXLEN - set maximum token length for GETSEG (future: others) */
289
GL_setmaxlen( maxlen )
292
if( maxlen == 0 ) Maxlen = 99999;
293
else Maxlen = maxlen;
298
/* ===================================================================== */
299
/* WILDCMP - compare two strings s1 and s2. S2 may contain
302
Function returns 0 on a match; < 0 if s1 < s2; > 0 if s1 > s2
303
Prints an error message and returns -999 on error.
305
* wildcard limited to the following uses: *ppp; ppp*; pp*pp; *ppp*
306
? can be used anywhere.
308
Double asterisks at beginning and end are also handled (means the
309
same as single asterisk).
311
scg 3-4-96 (written elsewhere)
316
GL_wildcmp( char *s1, char *s2, int len, int casecare )
318
s2 = query value which can contain wildcards - not null terminated.
320
casecare = 0 for case-insensitive, 1 for case-sensitive
323
int i, nwc, wcp, stat, stat2;
326
if( len == 0 ) return( strlen( s1 ) );
327
else if( s2[0] == starsym ) {
328
if( len == 1 ) return( 0 ); /* everything matches */
330
else if( s2[0] == '?' ) ; /* can't tell yet */
331
else if( tolower( s1[0] ) < tolower( s2[0] ) ) return( -1 ); /* way off */
332
else if( tolower( s1[0] ) > tolower( s2[0] ) ) return( 1 ); /* way off */
334
/* strip off extraneous * at beginning and end.. */
335
if( s2[0] == starsym && s2[1] == starsym ) { s2 = &s2[1]; len--; }
336
if( s2[len-1] == starsym && s2[len-2] == starsym ) len--;
338
/* see if any wild cards were used.. */
340
for( i = 0; i < len; i++ ) if( s2[i] == starsym ) { nwc++; wcp = i; }
342
if( nwc < 1 ) { /* straight match */
343
if( strlen( s1 ) > len ) return( wcmp( s1, s2, strlen( s1 ), casecare));
344
else return( wcmp( s1, s2, len, casecare ) );
347
else if( nwc == 1 ) { /* wildcard match */
348
/* find beginning of what we need to compare */
349
i = strlen( s1 ) - (len - (wcp+1) );
351
/* case 1: wc at end.. */
353
return( wcmp( s1, s2, len-1, casecare ) );
356
/* case 2: wc at beginning.. */
358
return( wcmp( &s1[i], &s2[ 1 ], len-1, casecare ) );
361
/* case 3: wc in middle.. */
363
int frontlen, backlen;
367
/* do front compare.. */
368
stat = wcmp( s1, s2, frontlen, casecare );
369
if( stat != 0 ) return( stat );
371
backlen = strlen( s2 ) - (frontlen + 1);
372
if( strlen( s1 ) < frontlen + backlen ) return( 1 ); /* fail if s1 too short */
374
/* do back compare.. */
375
stat = wcmp( &s1[ strlen( s1 ) - backlen ], &s2[ strlen( s2 ) - backlen ], backlen, casecare );
381
else if( nwc == 2 ) {
383
/* case 4: wc at beginning and end.. */
384
if( wcp != (len-1) ) goto ERR;
385
else if( s2[0] != starsym ) goto ERR;
386
stop = ( strlen( s1 ) - len ) + 2;
387
for( i = 0; i <= stop; i++ ) {
388
if( wcmp( &s1[i], &s2[1], len-2, casecare ) == 0 ) return( 0 );
395
fprintf( stderr, "Wild card match error (%s vs %s).\n", s1, s2 );
400
/* WCMP - compare two strings. S2 may contain ? wildcards which matches any
401
single character. Len is the # of characters to check.
404
wcmp( char *s1, char *s2, int len, int casecare )
407
for( i = 0; i < len; i++ ) {
409
if( tolower(s1[i]) < tolower(s2[i]) && s2[i] != '?' )
411
else if( tolower(s1[i]) > tolower(s2[i]) && s2[i] != '?' )
415
if( s1[i] < s2[i] && s2[i] != '?' ) return( -1 );
416
else if( s1[i] > s2[i] && s2[i] != '?' ) return( 1 );
422
/* WILDCHAR - set the wildcard symbol to be used instead of '*' */
430
/* ===================================================================== */
431
/* FUZZYMATCH - Do a 'fuzzy' match. See if s1 is similar to s2.
433
This routine may alter s1 and s2.
435
A wildcard character '*' at the beginning or end of s2 indicates
436
that a match can occur anywhere within s1 (eg. smith* would match
437
smithington and *smith would match harrowsmith; *smith* would match
438
both). If there are no asterisks, lengths
439
of the two strings must be similar.
441
Degree changes the 'looseness' of the match.
442
5 = strict, 4 = medium-strict, 3 = medium 2= loose, 1 = very loose.
444
Returns 1 on a match, 0 not.
449
GL_fuzzymatch( s1, s2, len2, degree )
450
char *s1; /* data value */
451
char *s2; /* query value */
452
int len2; /* length of s2 */
453
int degree; /* dgree of tightness */
455
int i, j, k, len1, pts;
458
int openfront, openend, goal;
460
/* exact match.. no need to do more.. */
461
if( strcmp( s2, s1 ) ==0 ) return( 1 );
465
/* see what type of match, open or closed */
466
if( s2[0] == '*' ) { openfront = 1; s2 = &s2[1]; len2--; }
468
if( s2[ len2-1 ] == '*' ) { openend = 1; len2--; }
472
if( len2 < 4 )goal = len2 * degree;
473
else if( len2 < 10 ) goal = (len2 -2) * degree;
474
else goal = (len2 -3) * degree;
477
/* reject disparate lengths if doing a closed match */
478
if( !openfront && !openend && len1 - len2 > 3 ) return( 0 );
480
/* truncate end of s1 if openended match */
481
if( openend && !openfront && len1 > len2+2 ) len1 = len2+2;
483
/* chop of front of s1 if openfronted match */
484
if( openfront && !openend && len1 > len2+2 ) s1 = &s1[ len1-(len2+2) ];
486
/* printf( "[%d-%d]", openfront, openend ); */
490
for( i = 0; i < len2; i++ ) {
493
/* find each occurrence of c in s1.. */
496
for( j = 0; j < len1; j++ ) {
500
/* check adjacent characters, count matches.. */
503
if( i + j == 0 ) pts+=2; /* both 1st char */
506
for( k = 1; k <= 4; k++ ) {
507
if( j-k < 0 || i-k < 0 ) break;
508
else if( s1[j-k] == s2[i-k] ) pts++;
511
if( i == len2-1 && j == len1-1 )
512
pts+=2; /* both last char */
514
else /* go right.. */
515
for( k = 1; k <= 4; k++ ) {
516
if( j+k > len1-1 || i+k > len2-1 ) break;
517
else if( s1[j+k] == s2[i+k] ) pts++;
521
if( pts > bestpts )bestpts = pts;
523
if( bestpts > 6 ) score += 6;
524
else score += bestpts;
525
/* printf( "[%c:%d]", c, bestpts ); */
526
if( score > goal ) return( 1 ); /* optimize */
528
/* printf( "<%s v. %s : %d>\n", s2, s1, score ); */
529
if( score > goal ) return( 1 );
534
/* ============================================= */
535
/* EXPAND_TABS Takes a string parameter 'in' and expands tabs into spaces, placing the
536
result into parameter 'out'.
538
GL_expand_tabs( out, in )
545
for( i = 0, len = strlen( in ); i < len; i++ ) {
546
if( in[i] == '\t' ) {
547
j = 8 - ( k % 8 ); /* 1 to 8 spaces needed */
548
for( l = 0; l < j; l++ ) out[k++] = ' ';
550
else out[k++] = in[i];
556
/* ============================================= */
557
/* MAKE_UNIQUE_STRING - generate an identifier using date, time, and pid */
559
GL_make_unique_string( s, i )
561
int i; /* may be sent as an integer.. if 0 getpid() will be used.. */
563
int mon, day, yr, hr, min, sec, pid, a, b, c;
564
GL_sysdate( &mon, &day, &yr );
565
GL_systime( &hr, &min, &sec );
566
s[0] = encode( yr % 100 );
567
s[1] = encode( mon );
568
s[2] = encode( day );
570
s[4] = encode( min );
571
s[5] = encode( sec );
572
if( i == 0 ) pid = getpid();
574
s[6] = encode( pid % 62 );
576
s[7] = encode( pid % 62 );
577
s[8] = encode( pid / 62 );
583
/* encode - derive a character representation of a number */
584
static int encode( a )
587
if( a >= 0 && a <= 9 ) return( a + '0' );
588
else if( a > 35 ) return( (a-36) + 'A' ); /* A-Z 26 letters + 9 = 35 */
589
else if( a > 9 ) return( (a-10) + 'a' ); /* a-z */
593
/* ============================================= */
594
/* ADDMEMBER - append a new member to the end of a comma-delimited list */
595
GL_addmember( newmem, list )
599
if( list[0] == '\0' ) strcpy( list, newmem );
602
strcat( list, newmem );
607
/* ============================================= */
608
/* CONTAINS - if string s contains any of chars in clist, return position (1=first)
609
of first occurance in list. 0 if not found at all.
610
example: contains( "\"*'", "'hello'" ) -> 1
612
GL_contains( clist, s )
618
for( i = 0, len = strlen( s ); i < len; i++ ) {
619
if( GL_member( s[i], clist )) return( i+1 );
623
/* ============================================= */
624
/* SUBST - change all occurances of s1 to s2, in t.
626
Max length of t is 255.
627
Returns 0 if successful, 1 if no occurance of s1 found. */
629
GL_substitute( s1, s2, t )
633
int i, j, len1, buflen, found;
636
if( len1 < 1 ) return( 1 );
638
buflen = strlen( buf );
639
if( buflen < 1 ) return( 1 );
643
for( i = 0; i < buflen; i++ ) {
644
/* printf( "[%s|%s|%d]", &buf[i], s1, len1 ); */
646
if( strncmp( &buf[i], s1, len1 )==0 ) {
652
else t[j++] = buf[i];
655
if( found ) return( 0 );
659
/* ============================================= */
660
/* CHANGECHARS - go through string s and if any characters in clist found, change
661
the character to newchar */
662
GL_changechars( clist, s, newchar )
663
char *clist, *s, *newchar;
668
for( i = 0, len = strlen( s ); i < len; i++ ) {
669
if( GL_member( s[i], clist )) s[i] = newchar[0];
674
/* ============================================= */
675
/* DELETECHARS - go through string s and if any characters in clist found, delete
677
GL_deletechars( clist, s )
684
if( s[i] == '\0' ) break;
685
if( GL_member( s[i], clist )) {
686
strcpy( &s[i], &s[i+1] );
693
/* ======================================================================== */
695
GL_substring( result, str, fromchar, nchar )
696
char *result; // substring is copied into this variable
697
char *str; // the original string
698
int fromchar; // starting point from which to take the substring
699
int nchar; // length of the substring
701
In all cases the first char is 1, not 0.
703
Two ways it can operate:
704
If <fromchar> is greater than 0, the result will be the portion of <string>
705
beginning at position <fromchar>, for a length of <nchar>, or until
707
If <fromchar> is less than 0, and <nchar> is greater than 0:
708
we will begin counting from the end of <string>,
709
leftward. for (abs)<fromchar> characters. Then, we will take the
710
substring beginning from that character
711
for a length of <nchar>, or until the end is reached.
713
Examples: substring( result, "02001.fv02", 7, 4 ) -- result would be "fv02"
714
substring( result, "02001.fv02", -4, 99 ) -- result would be "fv02"
717
GL_substring( result, str, fromchar, nchar )
727
if( fromchar > 0 ) fromchar -= 1;
728
else if( fromchar < 0 ) fromchar += len;
730
for( i = fromchar, j = 0; i < fromchar + nchar; i++ ) {
731
if( i > len-1 ) break;
732
result[j++] = str[i];
738
/* ===================================================================== */
739
/* VARSUB - given string s, find every occurance
740
of symbol (case-sensitive) and change it to value.
741
-Copies result into s.
742
-Returns number of times a substitution was made, 0 if none.
743
-This routine is not sophisticated about delimiting the symbol;
744
e.g. if s contains $NUMBER and varsub() is looking for $NUM it will find it.
746
GL_varsub( s, symbol, value )
747
char *s, *symbol, *value;
749
int i, j, len, found;
753
len = strlen( symbol );
756
for( i = 0, j = 0; i < slen; i++, j++ ) {
757
if( strncmp( &s[i], symbol, len )==0 ) {
758
strcpy( &rtnbuf[j], value );
759
j = strlen( rtnbuf ) - 1;
763
else rtnbuf[j] = s[i];
772
/* ============================================= */
773
/* AUTOROUND - round the decimal portion a number reasonably based on its magnitude.
774
val is the value, represented as a string.
775
decoffset controls the precision of the rounded result as follows:
776
If decoffset = 0 then nothing happens.
777
If decoffset = 1 then rounding will go to 1 additional decimal place.
778
decoffset = -1 then rounding will go to one less decimal place than normal.
780
The rounded result is copied back into val.
782
If val is non-numeric or a whole number then it is left unchanged.
784
GL_autoround( val, decoffset )
788
int precision, decplaces, stat;
789
char roundingfmt[50];
792
stat = GL_goodnum( val, &precision );
793
if( stat && precision > 0 ) {
795
decplaces = getdecplaces( g );
796
if( decplaces > -99 ) {
797
if( decplaces < 0 ) decplaces = 0;
798
sprintf( roundingfmt, "%%.%df", decplaces + decoffset );
799
sprintf( val, roundingfmt, g );
805
/* ============================================= */
806
/* AUTOROUNDF - variant of autoround(), takes val as a double, return value is character rep..*/
808
GL_autoroundf( val, decoffset )
812
int precision, decplaces, stat;
813
char roundingfmt[50];
814
static char result[50];
816
sprintf( result, "%g", val ); /* fallback */
817
decplaces = getdecplaces( val );
818
if( decplaces > -99 ) {
819
if( decplaces < 0 ) decplaces = 0;
820
sprintf( roundingfmt, "%%.%df", decplaces + decoffset );
821
sprintf( result, roundingfmt, val );
826
static int getdecplaces( val )
834
if( g >= 1000 ) decplaces = 0;
835
else if( g >= 100 ) decplaces = 0;
836
else if( g >= 10 ) decplaces = 1;
837
else if( g >= 1.0 ) decplaces = 2;
838
else if( g >= 0.1 ) decplaces = 3;
839
else if( g >= 0.01 ) decplaces = 4;
840
else if( g >= 0.001 ) decplaces = 5;
841
else if( g >= 0.0001 ) decplaces = 6;
846
/* ======================== */
859
/* ======================================================================== */
860
/* RANGER - take a range specification of integers and return an enumeration of all members.
861
* Examples: "3-8" would return in list array: 3,4,5,6,7,8
862
* "4,5,7-9,12-last" would return (for a 15 member list): 4,5,7,8,9,12,13,14,15
863
* "4,5 7-9 12-last" would be equivalent to the above example.
864
* "1-last" would return (for an 8 member list): 1,2,3,4,5,6,7,8
866
* There may be no embedded spaces within the dash construct.
869
GL_ranger( spec, list, n )
871
int *list; /* array */
872
int *n; /* in: size of list (max number of members)
873
out: number of members in list that have been filled */
875
int i, ix, p, j, lo, hi;
876
char tok[80], histr[80];
882
/* split up on commas or spaces */
883
GL_getchunk( tok, spec, &ix, ", " );
884
if( tok[0] == '\0' ) break;
886
if( GL_goodnum( tok, &p ) ) {
887
list[i] = atoi( tok );
891
sscanf( tok, "%d-%s", &lo, histr );
892
if( stricmp( histr, "last" )==0 ) hi = *n;
893
else hi = atoi( histr );
895
fprintf( stderr, "bad range specification: %s\n", tok );
898
for( j = lo; j <= hi; j++ ) {
909
/* ============================== */
910
/* CLOSE_TO - test two floating point numbers to see if
911
they are within a small tolerance. */
913
GL_close_to( a, b, tol )
917
if( a == b ) return( 1 );
918
else if( a > b && a - b < tol ) return( 1 );
919
else if( b > a && b - a < tol ) return( 1 );
924
/* ================================= */
925
/* CHECKSUM FUNCTIONS */
927
/* CHECKDIG - returns the check digit for the number in aptr with length l.
928
NOTE: when the check digit is computed to be 10 an `x' is returned.
930
This algorithm protects against interchanged digits.
935
char GL_checkdig(aptr,l)
939
int i,odds,evens,checkdigit;
945
if (i % 2 == 0) { evens += (*(aptr+i) - '0'); }
946
else { odds += (*(aptr+i) - '0'); }
949
checkdigit = (odds + (3 * evens)) % 11;
951
/* if the checkdigit is 10 then return the character to be used in place of ten */
952
if ( checkdigit == 10 ) return ( TEN );
953
else return(checkdigit+'0');
958
/* script entry point for checksum functions */
959
GL_checksum_functions( hash, name, arg, nargs, result, typ )
969
if( hash == 2182 ) { /* $checksumvalid(s) - validate s which is an integer containing a trailing check digit,
970
using the algorithm in $ps/clibx/checkdig */
972
i = GL_checkdig( arg[0], strlen( arg[0] ) -1 );
973
if( i == arg[0][ strlen( arg[0] ) -1 ] ) sprintf( result, "1" );
974
else sprintf( result, "0" );
979
if( hash == 2412 ) { /* $checksumencode(i) - result is i with checksum digit appended. */
984
sprintf( tmp, "%ld", i );
985
cs = GL_checkdig( tmp, strlen( tmp ) );
986
sprintf( result, "%s%c", tmp, cs );
991
if( hash == 2155 ) { /* $checksumnext(s) take s which is a number including trailing checksum
992
digit, increment number and recompute new checksum digit. */
997
s[ strlen( s ) - 1 ] = '\0'; /* strip off existing checksum digit */
1000
sprintf( tmp, "%ld", i );
1001
cs = GL_checkdig( tmp, strlen( tmp ) );
1002
sprintf( result, "%s%c", tmp, cs );
1007
fprintf( stderr, "unrecognized function: %s\n", name ); /* not found */
1012
/* ============================= */
1013
/* COMMONMEMBERS - compare two commalists and return number of members
1014
that are in common.. */
1016
GL_commonmembers( list1, list2, mode )
1019
int mode; /* 0 = return a count; 1 = quit when one found */
1021
int i, j, ii, ij, count;
1023
char tok1[DATAMAXLEN+1], tok2[DATAMAXLEN+1];
1026
len1 = strlen( list1 );
1027
len2 = strlen( list2 );
1028
for( i = 0, ii = 0; ; i++ ) {
1029
if( ii >= len1 ) break;
1030
GL_getseg( tok1, list1, &ii, "," );
1031
for( j = 0, ij = 0; ; j++ ) {
1032
if( ij >= len2 ) break;
1033
GL_getseg( tok2, list2, &ij, "," );
1034
if( stricmp( tok1, tok2 )==0 ) {
1035
if( mode == 1 ) return( 1 );
1043
/* ==================================== */
1044
/* LISTMEMBER - see if s is in list (comma-delimited);
1045
if so return 1 and list position (first=1) and string position (first=0) */
1046
GL_listmember( s, list, memnum, pos )
1052
int ix, i, lastix, len;
1057
len = strlen( list );
1059
for( i = 1, ix = 0; ; i++ ) {
1060
if( ix >= len ) break;
1062
GL_getseg( tok, list, &ix, "," );
1063
if( strcmp( tok, s )==0 ) {
1072
/* ===================================== */
1073
/* GETCGIARG - get next arg from CGI REQUEST_URI string (escape constructs are converted) */
1074
GL_getcgiarg( arg, uri, pos, maxlen )
1076
int *pos; /* current position */
1077
int maxlen; /* max size of string, including terminator */
1083
if( *pos == 0 ) { /* scan to '?'.. */
1084
for( i = 0; ; i++ ) {
1085
if( uri[i] == '?' || uri[i] == '\0' ) {
1086
strncpy( arg, uri, i );
1088
if( uri[i] == '\0' ) *pos = i;
1095
for( i = *pos, j = 0; j < maxlen; i++ ) {
1096
if( uri[i] == '&' || uri[i] == '\0' || j >= maxlen ) {
1098
if( uri[i] == '\0' ) *pos = i;
1102
else if( uri[i] == '%' && isxdigit( uri[i+1] ) && isxdigit( uri[i+2] ) ) {
1103
sprintf( hex, "%c%c", uri[i+1], uri[i+2] );
1104
sscanf( hex, "%x", &val );
1105
arg[j++] = (char) val;
1108
else arg[j++] = uri[i];