/*** analog 4.13 http://www.analog.cx/ ***/ /*** This program is copyright (c) Stephen R. E. Turner 1995 - 2000 except as *** stated otherwise. Distribution, usage and modification of this program is *** subject to the conditions of the Licence which you should have received *** with it. This program comes with no warranty, expressed or implied. ***/ /*** anlghea3.h: third header file ***/ /*** The things in this file are not user-definable; user-definable options *** can be found in anlghead.h ***/ #ifndef ANLGHEAD3 #define ANLGHEAD3 /*** OS specific things ***/ #define VNUMBER "4.13" /* the version number of this program */ #undef VERSION /* If no OS set, compilation will fail by not knowing VERSION */ #ifdef __MWERKS__ #undef MAC #define MAC /* So MWERKS compiler automatically switches to Mac */ #endif #ifdef __BEOS__ #undef MAC #define BEOS #endif #ifdef _WIN32 #ifndef UNIX /* So as to signal CYGWIN */ #undef WIN32 #define WIN32 #endif #endif #ifdef MAC #define MAC_EVENTS #define NOPIPES #define MACDIRENT #define NOOPEN #define LINE_PARSER #define USE_ZLIB #include #include #define DIRSEP ':' #define EXTSEP "." #define VERSION VNUMBER"/Mac" #endif #ifdef DOS #define NODNS #define DIRSEP '\\' #define EXTSEP "." #define VERSION VNUMBER"/DOS" #endif #ifdef VMS #define NOPIPES #define VMSDIRENT #ifdef __VMS_VER #if (__VMS_VER < 70000000) #define NOGMTIME #endif #endif #define DIRSEP '/' #define EXTSEP "." #include /* old DEC C (v4.x?) was missing these two defines */ #ifndef S_IWUSR #define S_IWUSR 0000200 /* write permission, owner */ #endif #ifndef S_IRUSR #define S_IRUSR 0000400 /* read permission, owner */ #endif #define cma$tis_errno_get_addr CMA$TIS_ERRNO_GET_ADDR #define FOPENR(s) fopen(s, "r", "shr=upd") #define VERSION VNUMBER"/OpenVMS" #endif #ifdef UNIX #define DIRSEP '/' #define EXTSEP "." #define VERSION VNUMBER"/Unix" #endif #ifdef WIN32 #define popen _popen #define pclose _pclose extern void Win32Init(void); extern void Win32Cleanup(void); #define WIN32DIRENT /* can comment out if POSIX dirent present, eg Borland */ #define FOPENR_BINARY #define POPENR_BINARY #define DIRSEP '\\' #define EXTSEP "." #define VERSION VNUMBER"/Win32" #endif #ifdef OS2 #define DIRSEP '\\' #define EXTSEP "." #define VERSION VNUMBER"/OS2" #endif #ifdef RISCOS #define NODNS #define NOPIPES #define NODIRENT #define DIRSEP '.' #define EXTSEP "/" #define VERSION VNUMBER"/RISCOS" #endif #ifdef NEXTSTEP #define DIRSEP '/' #define EXTSEP "." #ifndef S_IWUSR #define S_IWUSR 0000200 /* write permission, owner */ #endif #ifndef S_IRUSR #define S_IRUSR 0000400 /* read permission, owner */ #endif #define VERSION VNUMBER"/NeXTSTEP" #endif #ifdef BEOS #define DIRSEP '/' #define EXTSEP "." #define VERSION VNUMBER"/BeOS" #endif #ifdef BS2000 #define EBCDIC #define DIRSEP '/' #define EXTSEP "." #define VERSION VNUMBER"/BS2000/OSD" #endif #ifdef AS400 #define EBCDIC #define DIRSEP '/' #define EXTSEP "." #define ALIGNMENT (16) #define NOPIPES #define FOPENR(s) fopen(s, "r,ccsid=37") #define FOPENW(s) fopen(s, "w,ccsid=37") #define FOPENA(s) fopen(s, "a,ccsid=37") #define VERSION VNUMBER"/AS400" #endif /*** ANSI header files ***/ #include #include #include #include #include #include #include #include #include #include #include /*** system dependent header files ***/ #include "pcre.h" #ifdef WIN32 #include #endif #ifdef MAC #ifdef LINE_PARSER #ifndef REAL_STDIO #define fopen(name,mode) mac_fopen((name),(mode)) #define fread(ptr,siz,num,file) mac_fread(ptr,siz,num,file) #undef getc #define getc(file) mac_getc(file) #define fclose(file) mac_fclose((file)) #undef feof #define feof(file) mac_feof(file) #endif extern FILE *mac_fopen(const char *name,const char *mode); extern size_t mac_fread(void *ptr, size_t size, size_t num, FILE *file); extern int mac_getc(FILE *file); extern int mac_fclose(FILE *file); extern int mac_feof(FILE *file); #endif #ifndef REAL_ALLOC #define malloc(size) mac_malloc((size)) #define calloc(num,size) mac_calloc((num),(size)) #define realloc(ptr,size) mac_realloc((ptr),(size)) #define free(ptr) mac_free((ptr)) #endif extern void *mac_malloc(size_t size); extern void *mac_calloc(size_t num, size_t size); extern void *mac_realloc(void *ptr, size_t size); extern void mac_free(void *ptr); #endif #ifdef NEED_FLOATINGPOINT_H #include #endif #ifndef NOOPEN #include #include #include #ifdef WIN32 #include #define OPEN_MODE (S_IREAD | S_IWRITE) #else #define OPEN_MODE (S_IRUSR | S_IWUSR) /* Most systems will accept the above too, but this is POSIXly correct. */ #endif #endif /* I assume the header files are well enough behaved that we can include them twice without harm, so that we can just do !NOSTAT and !NODIRENT indep. */ #ifndef NODIRENT #ifndef VMSDIRENT #ifndef MACDIRENT #ifndef WIN32DIRENT #include /* POSIX dirent */ #include #include #else #include /* Win32 dirent */ #include #include #endif #else #include "macdir.h" /* Mac dirent */ #endif #else #define VMS_FSPEC_MAX 256 /* VMS dirent */ #include #endif #endif #ifndef NODNS #ifdef MAC #include /* Mac DNS */ #include #include #include #include #else #ifdef HAVE_ADDR_T /* Win32 and normal DNS */ #define IN_ADDR_T in_addr_t #else typedef unsigned long IN_ADDR_T; #endif #ifdef WIN32 /* Win32 DNS: NB windows.h above includes winsock.h */ #define INET_ADDR_ERR ((IN_ADDR_T)(INADDR_NONE)) #else #include /* Normal DNS */ #include #include #ifndef BEOS #include #endif #define INET_ADDR_ERR ((IN_ADDR_T)(-1)) #endif #endif #endif /*** User-definable header file ***/ #include "anlghead.h" /*** definitions ***/ #undef TRUE #define TRUE (1) #undef FALSE #define FALSE (0) #undef OK #define OK (0) #undef ERR #define ERR (-1) #undef UNSET #define UNSET (-1) #ifndef EXIT_SUCCESS #define EXIT_SUCCESS (0) /* ANSI, but some broken implementations lack it. */ #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE (1) #endif #define EXIT_SIGNAL ((EXIT_FAILURE) + 1) #ifdef WIN32 #define ERRBUFMODE (_IONBF) /* on Windows, _IOLBF causes full buffering */ #else #define ERRBUFMODE (_IOLBF) #endif #define FEW (2) #define NEWLOGFMT (2) #define BADLOGFMT (3) #define CONTINUATION (-1) /* used in warn() in utils.c */ #define REGEX_INC (2) /* next four used in (struct include).type */ #define NORMAL_INC (1) /* see also IS_REGEXT(), IS_INC() macros below */ #define NORMAL_EXC (-1) #define REGEX_EXC (-2) #define BLOCK_EPSILON (30) #define MIN_SC (100) /* see parsescode() in input.c */ #define SC_NUMBER (600) #define IGNORE_CODE (1000) #define EPSILON (1e-8) #define MINS_IN_WEEK (10080) #define HASHSIZE (8) /* initial size of hash table; a power of 2 */ #define TREEHASHSIZE (3) /* a power of 2 plus 1 */ #define SIZEBINS (11) /* in sizescore() */ #define ITEMFNS_NUMBER ((ITEM_NUMBER) + 2) /* in inpfns[] in globals.c */ #define ANALOGURL "http://www.analog.cx/" #define FIRST_TIME (0) #define LAST_TIME (ULONG_MAX) #define WHITESPACE ((char)(-1)) #define DOMLEVEL_NUMBER (677) /* 26^2 + 1 */ #define PMATCH_SIZE (30) /* This allows PCRE to capture 9 subexpressions */ #ifdef MAC_EVENTS #define MAC_IDLE_FREQ (200) #endif /*** logfile line types ***/ #define LOG_COMMON1 "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%j%w%r%wHTTP%j\" %c %b" #define LOG_COMMON2 "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%j%w%r\" %c %b" #define LOG_COMMON3 "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%r\" %c %b" #define LOG_MS_COMMON1 "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%j%w%r%w\"HTTP%j\" %c %b" #define LOG_COMBINED1 \ "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%j%w%r%wHTTP%j\" %c %b \"%f\" \"%B\"" #define LOG_COMBINED2 \ "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%j%w%r\" %c %b \"%f\" \"%B\"" #define LOG_COMBINED3 \ "%S %j %u [%d/%M/%Y:%h:%n:%j] \"%r\" %c %b \"%f\" \"%B\"" #define LOG_MS_INT1 "%S, %u, %d/%m/%y, %h:%n:%j, W3SVC%j, %j, %v, %T, %j, %b, %c, %j, %j, %r, %q," #define LOG_MS_INT2 "%*S, %*u, %d/%m/%y, %h:%n:%j, %j" #define LOG_MS_NA1 "%S, %u, %m/%d/%y, %h:%n:%j, W3SVC%j, %j, %v, %T, %j, %b, %c, %j, %j, %r, %q," #define LOG_MS_NA2 "%*S, %*u, %m/%d/%y, %h:%n:%j, %j" #define LOG_WEBSTAR1 "!!LOG_FORMAT%x2" #define LOG_WEBSTAR2 "!!%j" #define LOG_EXTENDED1 "#Fields:%x3" #define LOG_EXTENDED2 "#%j" #define LOG_MS_EXTENDED1 "#Fields:%x5" #define LOG_WEBSTAR_EXTENDED1 "#Fields:%x6" #define LOG_WEBSITE_NA \ "%m/%d/%y %h:%n:%j\t%S\t%v\t%j\t%u\t%j\t%r\t%f\t%j\t%B\t%c\t%b\t%T" #define LOG_WEBSITE_INT \ "%d/%m/%y %h:%n:%j\t%S\t%v\t%j\t%u\t%j\t%r\t%f\t%j\t%B\t%c\t%b\t%T" #define LOG_NETSCAPE "format=%x4" #define LOG_REFERRER1 "[%d/%M/%Y:%h:%n:%j] %F -> %*r" #define LOG_REFERRER2 "%F -> %*r" #define LOG_BROWSER "[%d/%M/%Y:%h:%n:%j] %B" /*** enums ***/ /* Types of item and other inputs: must have ITEMs in process_data() order: code, bytes, proctime, unixtime, am, date in some order (these are INPUT_NUMBER, not to be confused with INP_NUMBER): then rest in some order. NB I don't know if changing process_data() order would have side-effects. */ /* See also item_type in globals.c */ enum {ITEM_VHOST, ITEM_FILE, ITEM_USER, ITEM_REFERRER, ITEM_BROWSER, ITEM_HOST, INP_CODE, INP_BYTES, INP_PROCTIME, INP_UNIXTIME, INP_AM, INP_DATE, INP_YEAR, INP_MONTH, INP_HOUR, INP_MIN, INP_QUERY, INP_IP, INP_NUMBER}; #define ITEM_NUMBER (INP_CODE) #define INPUT_NUMBER (INP_YEAR) /* NB There is INP_NUMBER and INPUT_NUMBER */ /* Types of report: must have date reports then GENSUM then other reports, finishing with derv(tree)reps, then SIZE, CODE, PROCTIME in some order. */ /* See also repcodes, anchorname and repname in globals.c */ enum {REP_MONTH, REP_WEEK, REP_DAYREP, REP_DAYSUM, REP_HOURREP, REP_HOURSUM, REP_QUARTER, REP_FIVE, REP_GENSUM, REP_REQ, REP_REDIR, REP_FAIL, REP_TYPE, REP_DIR, REP_HOST, REP_DOM, REP_REF, REP_REFSITE, REP_REDIRREF, REP_FAILREF, REP_BROWREP, REP_VHOST, REP_USER, REP_FAILUSER, REP_ORG, REP_SEARCHREP, REP_SEARCHSUM, REP_BROWSUM, REP_OS, REP_SIZE, REP_CODE, REP_PROCTIME, REP_NUMBER}; #define DATEREP_NUMBER (REP_GENSUM) #define FIRST_GENREP (REP_GENSUM + 1) #define GENREP_NUMBER (REP_NUMBER - FIRST_GENREP) #define FIRST_DERVREP (REP_SEARCHREP) #define DERVREP_NUMBER (4) #define FIRST_ARRAYREP (REP_SIZE) #define ARRAYREP_NUMBER (3) #define LAST_NORMALREP (REP_OS) /* Types of status code. Order insignificant. */ enum {SUCCESS, FAILURE, REDIRECT, INFO, UNWANTED}; /* Counts then dates collected about each item, and then other floor/sort criteria: order otherwise insignificant. See also methodname in globals.c */ enum {REQUESTS, PAGES, REDIR, FAIL, SUCCDATE, REDIRDATE, FAILDATE, BYTES, ALPHABETICAL, RANDOM, METHOD_NUMBER}; #define COUNT_NUMBER (SUCCDATE) #define DATESORT (SUCCDATE) #define DATA_NUMBER (BYTES) /* Data collected about total requests etc. in each logfile */ enum {LOGDATA_UNWANTED, LOGDATA_UNKNOWN, LOGDATA_UNKNOWN7, LOGDATA_INFO, LOGDATA_INFO7, LOGDATA_SUCC, LOGDATA_SUCC7, LOGDATA_PAGES, LOGDATA_PAGES7, LOGDATA_REDIR, LOGDATA_REDIR7, LOGDATA_FAIL, LOGDATA_FAIL7, LOGDATA_CORRUPT, LOGDATA_NUMBER}; /* Poss. columns: COL_TITLE must be first; see also configcols() in init2.c */ enum {COL_TITLE, COL_REQS, COL_PAGES, COL_BYTES, COL_PREQS, COL_PPAGES, COL_PBYTES, COL_DATE, COL_TIME, COL_INDEX, COL_NUMBER}; /* Levels of DNS lookup */ enum {DNS_NONE, DNS_READ, DNS_LOOKUP, DNS_WRITE}; /* Output types: start with HTML then PLAIN */ enum {HTML, PLAIN, ASCII, COMPUTER, OUT_NONE}; /* days of the week */ enum {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}; /* languages; see also country in globals.c */ enum {ARMENIAN, BOSNIAN, BULGARIAN, CATALAN, SIMP_CHINESE, TRAD_CHINESE, CROATIAN, CZECH, DANISH, DUTCH, ENGLISH, US_ENGLISH, FINNISH, FRENCH, GERMAN, GREEK, HUNGARIAN, ICELANDIC, ITALIAN, JAPANESE, KOREAN, NORWEGIAN, NYNORSK, POLISH, PORTUGUESE, BR_PORTUGUESE, ROMANIAN, RUSSIAN, SERBIAN, SLOVAK, SLOVENE, SPANISH, SWEDISH, TURKISH, UKRAINIAN}; /* lngstrs; charset_ must be first */ enum {charset_, weekbeg_, month_, day_, days_, hr_, minute_, minutes_, second_, seconds_, byte_, bytes_, request_, requests_, date_, datetime_, firstdate_, firsttime_, lastdate_, lasttime_, file_, files_, host_, hosts_, vhost_, vhosts_, dir_, dirs_, dom_, doms_, org_, orgs_, ext_, exts_, url_, urls_, browser_, browsers_, os_, oss_, size_, search_, searches_, site_, sites_, user_, users_, code_, codes_, webstatsfor_, gensum_, monthrep_, busymonth_, weekrep_, busyweek_, daysum_, dayrep_, busyday_, hourrep_, hoursum_, busyhour_, quarter_, busyquarter_, five_, busyfive_, hostrep_, hostgs_, hostgp_, hostgen_, dirrep_, dirgs_, dirgp_, dirgen_, typerep_, extgs_, extgp_, extgen_, reqrep_, filegs_, filegp_, filegen_, redirrep_, redirgs_, redirgp_, redirgen_, failrep_, failgs_, failgp_, failgen_, refrep_, refgs_, refgp_, refgen_, refsiterep_, refsitegs_, refsitegp_, refsitegen_, redirrefrep_, redirrefgs_, redirrefgp_, redirrefgen_, failrefrep_, failrefgs_, failrefgp_, failrefgen_, searchrep_, searchrepgs_, searchrepgp_, searchrepgen_, searchsum_, searchsumgs_, searchsumgp_, searchsumgen_, vhostrep_, vhostgs_, vhostgp_, vhostgen_, userrep_, usergs_, usergp_, usergen_, failuserrep_, failusergs_, failusergp_, failusergen_, browsum_, browgs_, browgp_, browgen_, browrep_, browrepgs_, browrepgp_, browrepgen_, osrep_, osgs_, osgp_, osgen_, domrep_, domgs_, domgp_, domgen_, orgrep_, orggs_, orggp_, orggen_, statrep_, codegs_, codegp_, codegen_, proctimerep_, sizerep_, credit_, runtime_, lessone_, eachunit_, represents_, partof_, pagereq_, pagereqs_, notlistedm_, notlistedf_, notlistedn_, progstart_, reqstart_, to_, succreqs_, avereqs_, totpages_, avepages_, totunknown_, totfails_, totredirs_, inforeqs_, distfiles_, disthosts_, corrupt_, unwanted_, totdata_, avedata_, brackets_, sevendaysto_, lastsevendays_, goto_, top_, unresolved_, nodomain_, unkdomain_, rootdir_, nodir_, noext_, brkdirs_, unkwin_, unkmac_, unkux_, unkos_, nreqs_, preqs_, npgs_, ppgs_, nbytes_, pbytes_, index_, firstsm_, firstsf_, firstsn_, firstdsm_, firstdsf_, firstdsn_, allsm_, allsf_, allsn_, floorby_, atleast_, redirreq_, redirreqs_, failreq_, failreqs_, ptraffic_, pmtraffic_, btraffic_, sincedate_, sinceredirdate_, sincefaildate_, sortedm_, sortedf_, sortedn_, traffic_, prequests_, pmrequests_, nrequests_, ppages_, pmpages_, npages_, predirs_, pmredirs_, nredirs_, pfails_, pmfails_, nfails_, succdate_, redirdate_, faildate_, alphasortm_, alphasortf_, alphasortn_, numsortm_, numsortf_, numsortn_, unsortedm_, unsortedf_, unsortedn_, colon_, datefmt1_, datefmt2_, dayrepfmt_, hourrepfmt_, quarterfmt_, weekfmt_, monthfmt_, genrepdate_, genreptime_, whatincfmt_, code100_, code101_, code199_, code200_, code201_, code202_, code203_, code204_, code205_, code206_, code299_, code300_, code301_, code302_, code303_, code304_, code_305, code306_, code307_, code399_, code400_, code401_, code402_, code403_, code404_, code405_, code406_, code407_, code408_, code409_, code410_, code411_, code412_, code413_, code414_, code415_, code416_, code417_, code418_, code419_, code499_, code500_, code501_, code502_, code503_, code504_, code505_, code506_, code599_, code999_, LNGSTR_NUMBER}; /* return codes from strtoinfmt() */ /* see also configlogfmt() in init2.c */ enum {FMT_OK, FMT_NOPC, FMT_DUP, FMT_BADCHAR, FMT_NOTERM, FMT_BADBUILTIN, FMT_BADPC, FMT_PARTTIME, FMT_QBUTNOR}; /*** typedefs ***/ typedef unsigned char logical; typedef signed char choice; typedef unsigned int datecode_t; typedef unsigned long timecode_t; /*** structs used in next section */ typedef struct { unsigned long data[DATA_NUMBER]; /* some are really timecode_t */ double bytes; logical last7; choice ispage; } Hashentry; typedef struct hashindex { char *name; Hashentry *own; void *other; struct hashindex *next; } Hashindex; typedef struct aliasto { char *string; choice after; struct aliasto *next; } AliasTo; typedef struct alias { char *from; pcre *pattern; AliasTo *to; logical isregex; struct alias *next; } Alias; /* For a normal pattern, nmatch is no. of *'s. For a regular expression, it's -3 * (no. of capturing subexpressions): this is what pcre_exec needs. */ typedef struct strpair { char *name, *data; struct strpair *next; } Strpair; /*** typedef function pointers ***/ typedef void (*cutfnp)(char **, char **, char *, logical); typedef void (*dcutfnp)(char **, char **, char *, struct strpair *); typedef struct hashindex *(*mergefnp)(struct hashindex *, struct hashindex *, unsigned long, unsigned long, choice); typedef void (*conffnp)(void *, char *, char *, char *, int); typedef choice (*inputfnp)(FILE *, void *, char); /*** rest of structs ***/ typedef struct { char *name; conffnp fn; void *opt; } Configfns; typedef struct { char code; choice type; inputfnp fn; void *opt; } Inputfns; typedef struct inputformat { Inputfns *inpfns; char sep; struct inputformat *next; } Inputformat; typedef struct inputformatlist { Inputformat *form; choice count[INPUT_NUMBER]; /* 0 = not present, 1 = starred, 2 = unstarred */ logical used; struct inputformatlist *next; } Inputformatlist; typedef struct filelist { char *name; Inputformatlist *format; timecode_t from, to; unsigned long data[LOGDATA_NUMBER]; double bytes, bytes7; char *prefix; size_t prefixlen; int pvpos, tz; logical ispipe; struct filelist *next; } Filelist; typedef struct mmlist { void *pos; struct mmlist *next; } Mmlist; typedef struct { void *block_end, *curr_pos, *next_pos; Mmlist *first, *last; unsigned short alignment; } Memman; typedef struct daysdata { unsigned long *reqs, *pages; double *bytes; struct daysdata *prev, *next; } Daysdata; typedef struct { char *fromstr, *tostr; timecode_t from, to, last7from, last7to, firsttime, lasttime; datecode_t firstdate, lastdate, currdate; /* perhaps bad name: currdate is date of current logfile entry */ Daysdata *firstdp, *lastdp, *currdp; } Dateman; typedef struct timerep { unsigned long reqs, pages; double bytes; datecode_t date; struct timerep *prev, *next; } Timerep; typedef struct { double threshold; unsigned long reqs, pages; double bytes; timecode_t lastdate; } Arraydata; typedef struct { Hashindex **head; unsigned long size; unsigned long n; } Hashtable; typedef struct { Hashtable *tree; cutfnp cutfn; Memman *space; } Tree; typedef struct { Hashtable *table; dcutfnp cutfn; Memman *space; Strpair **list; } Derv; typedef struct strlist { char *name; struct strlist *next; } Strlist; typedef struct include { char *name; pcre *pattern; choice type; struct include *next; } Include; typedef struct { double min; char qual; choice floorby; } Floor; typedef struct { choice code; char *file; } Lang; typedef struct { char *outfile, *cacheoutfile, *domainsfile, *headerfile, *footerfile; choice outstyle, gotos; logical multibyte, html; choice reporder[REP_NUMBER + 1]; logical cgi, repq[REP_NUMBER], last7, runtime; choice cols[REP_NUMBER][COL_NUMBER]; unsigned int rows[DATEREP_NUMBER]; char graph[DATEREP_NUMBER]; logical back[DATEREP_NUMBER]; choice sortby[GENREP_NUMBER], subsortby[GENREP_NUMBER]; Floor floor[GENREP_NUMBER], subfloor[GENREP_NUMBER]; Lang lang; char **dayname, **monthname, **lngstr; size_t daylen, plaindaylen, monthlen, plainmonthlen; char *hostname, *hosturl, *logo, *imagedir, *stylesheet; char markchar; logical rawbytes; logical norobots; choice weekbeginson; unsigned int plainpagewidth, htmlpagewidth, pagewidth, mingraphwidth; char sepchar, repsepchar, decpt, barstyle; char *compsep; Tree *tree[GENREP_NUMBER]; Strlist *suborgs; Derv *derv[DERVREP_NUMBER]; choice *alltrees, *alldervs; Include *wanthead[GENREP_NUMBER]; Alias *aliashead[GENREP_NUMBER]; Include *link, *reflink; char *baseurl; logical searchconv; unsigned char convfloor; } Outchoices; typedef struct { Filelist *logfile; Filelist *cachefile; unsigned long data[LOGDATA_NUMBER]; double bytes, bytes7; char *dirsuffix; unsigned int dirsufflength; choice lowmem[ITEM_NUMBER]; logical case_insensitive, usercase_insensitive; unsigned int granularity; } Miscoptions; typedef struct { Hashtable *hash[ITEM_NUMBER]; Arraydata *arraydata[ARRAYREP_NUMBER]; Hashindex **gooditems, **baditems; Include *wanthead[ITEM_NUMBER], *ispagehead, *argshead, *refargshead; choice code2type[SC_NUMBER]; logical succ304; Alias *aliashead[ITEM_NUMBER]; Strpair *searchengines; Dateman dman; Outchoices outopts; Miscoptions miscopts; Strlist *conffilelist; } Options; /*** macros ***/ #undef MAX #define MAX(a, b) (((a) > (b))?(a):(b)) #undef MIN #define MIN(a, b) (((a) < (b))?(a):(b)) /* a whole set of macros to cope with to...() and is...() commands if char is unsigned. */ #define ISALNUM(c) isalnum((unsigned char)(c)) #define ISALPHA(c) isalpha((unsigned char)(c)) #define ISDIGIT(c) isdigit((unsigned char)(c)) #define ISLOWER(c) islower((unsigned char)(c)) #define ISSPACE(c) isspace((unsigned char)(c)) #define ISUPPER(c) isupper((unsigned char)(c)) #define TOLOWER(c) ((char)tolower((unsigned char)(c))) #define TOUPPER(c) ((char)toupper((unsigned char)(c))) #ifdef NEED_STRCMP #define strcmp my_strcmp #endif #ifdef NEED_DIFFTIME #define difftime(t, s) ((double)((t) - (s))) #endif #ifdef NEED_STRTOUL #define strtoul(a, b, c) ((unsigned long)(strtol(a, b, c))) /* This is not quite right because of the different ranges of long and unsigned long, but it's probably OK for our purposes */ #endif #define STREQ(s, t) (strcmp(s, t) == 0) #define MATCHES(s, p) (matchq(s, (void *)p, FALSE, NULL)) #define DAYOFWEEK(d) ((choice)(((d) + 3) % 7)) /* by defns. in dates.c */ #define IS_EMPTY_STRING(s) ((s)[0] == '\0') #define IS_STDIN(s) (STREQ((s), "-") || strcaseeq((s), "stdin")) #define TO_NEXT(x) (x) = (x)->next #ifndef FOPENR #ifdef FOPENR_BINARY #define FOPENR(s) fopen(s, "rb") #else #define FOPENR(s) fopen(s, "r") #endif #endif #ifndef FOPENW #define FOPENW(s) fopen(s, "w") #endif #ifndef FOPENA #define FOPENA(s) fopen(s, "a") #endif #ifndef POPENR #ifdef POPENR_BINARY #define POPENR(s) popen(s, "rb") #else #define POPENR(s) popen(s, "r") #endif #endif #define ENTRY_WANTED(e) ((e) != unwanted_entry) #define ENTRY_BLANK(e) ((e) == blank_entry) #define LEN3(n, c) ((unsigned int)((c == '\0')?(n):((n) + (((n) - 1) / 3)))) /* The length of an n digit number with seps; e.g. 56789 [5] -> 56,789 [6] */ #define DEFAULTSTR(s, n) {s = NULL; \ configstr((void *)(&(s)), NULL, n, NULL, -1);} #define TOO_FULL(n, z) ((n) > (z)) /* defn for hash table too full */ #define TOO_FULL_TREE TOO_FULL #define NEW_SIZE(z) (2 * (z)) /* new size of the hash table */ #define NEW_SIZE_TREE(z) (2 * (z) - 1) /* see ref to IS_REGEXT above; NB can't use >> with negative numbers */ #define IS_REGEXT(type) ((type) / 2) /* for includes */ #define IS_INC(type) ((type) > 0) /* for includes */ /* static char *s = NULL; static size_t len = 0; ENSURE_LEN(s, len, req_len) */ #define ENSURE_LEN(s, l, n) if ((n) > (l)) { \ s = (char *)xrealloc((void *)s, n); \ l = n;} /* These PUT's are used in datesprintf() etc.: quicker than using sprintf() */ #define PUT02d(s, d) {*((s)++) = ((d) / 10) + '0'; \ *((s)++) = ((d) % 10) + '0'; } #define PUT04d(s, d) {*((s)++) = ((d) / 1000) + '0'; \ *((s)++) = ((d) / 100) % 10 + '0'; \ *((s)++) = ((d) / 10) % 10 + '0'; \ *((s)++) = ((d) % 10) + '0'; } #define PUT2d(s, d) {*((s)++) = ((d) < 10)?' ':(((d) / 10) + '0'); \ *((s)++) = ((d) % 10) + '0'; } #define PUTc(s, c) {*((s)++) = (c); } #define PUTs(s, t, n) {int z; size_t l = strlen(t); \ memcpy((void *)s, (void *)t, l); s += l; \ for (z = n; z > 0; z--) *((s)++) = ' '; } /* used in tree.c: see newtreedata() */ #define IS_REUSED(i) ((i)->ispage < 8) /* Some simple command line processing parts implemented as macros */ #define CLSHORTWARN(arg) warn('C', TRUE, "No argument specified after %s command line option (or space wrongly left before argument)", arg) #define CLLONGWARN(arg) warn('C', TRUE, "Command line argument %s too long: ignoring end of it", arg) #define CLSHORTCHECK(command) if (argv[i][2] == '\0') CLSHORTWARN(argv[i]); \ else command #define CLLONGCHECK(command) if (argv[i][2] != '\0') CLLONGWARN(argv[i]); \ command #define CLTOGGLE(f) CLLONGCHECK(f = (argv[i][0] == '+')?TRUE:FALSE) #define CLREPTOGGLE(n) CLTOGGLE(op->outopts.repq[n]) #define CLOUTSTYLE CLTOGGLE #define CLGOTOS CLTOGGLE /* these happen to work because PLAIN == TRUE == ON and HTML == FALSE == OFF */ /* abbreviations for output */ #define PRESTART() if (outstyle == HTML) fputs("
", outf);\
                   else if (outstyle == ASCII) fputc('\n', outf);
#define PREEND() if (outstyle == HTML) fputs("
\n", outf); /* an abbreviation for arrays with size GENREP_NUMBER */ #define G(r) ((r) - FIRST_GENREP) /* magicno as macro not fn. for speed: x is unsigned long to contain answer, s is (char *) to be magicked, b is unsigned long base (no. of hash bins); power of 2 in practice. Formula is (\sum_i 9^i c_i) [mod (ULONG_MAX + 1)] mod b */ #define MAGICNO(x, s, b) {register unsigned char *r; \ for(x = 0, r = (unsigned char *)(s); *r != '\0'; r++) { \ x = (x << 3) + x + (long)(*r); } \ x %= b; } /* for tree magic number, t is end of string, bins are power of 2 plus 1, and formula has 33 in place of 9 */ #define MAGICNOTREE(x, s, t, b) {register unsigned char *r; \ for(x = 0, r = (unsigned char *)(s); \ r < (unsigned char *)(t); r++) { \ x = (x << 5) + x + (long)(*r); } \ x %= (b - 1); x++; } #include "anlghea4.h" /* import function declarations */ #endif /* anlghea3.h not previously included */