home *** CD-ROM | disk | FTP | other *** search
- /*
- Strongtest.c
- Tests StrongHelp manuals for 'dangling' links, etc.
-
- v0.00 Dec '95 Incomplete.
- v1.00 960113 Rewrite becuase I accidentally deleted v0.00
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "kernel.h"
- #include "swis.h"
-
- typedef struct listnode {
- struct listnode* next;
- char* pagename;
- char* path;
- int referenced;
- } node;
-
- char block[1024]; /* general workspace */
- char manual[256]; /* the manual name we're working on */
- node* head; /* global to save passing it around everywhere */
- _kernel_swi_regs r; /* global to save time */
- _kernel_oserror *e; /* ... */
- int dangling = 0; /* dangling link flag/counter */
- int unaccessible = 0; /* unaccessible page flag/counter */
- int fserror = 0; /* filing system error flag/counter */
- int badchars = 0; /* non-ASCII chars flag/counter */
- int throwback = 0; /* throwback flag */
- int verbose = 0; /* verboseness flag :-) */
- int throwbackstarted = 0;
-
-
- /*----------------------------------------------------------------------------
- throwback_start
- => n/a
- <= n/a
- */
- void throwback_start(void)
- {
- e=_kernel_swi(DDEUtils_ThrowbackStart,&r,&r);
- if (e)
- {
- fprintf(stderr,"strongtest: WARNING - %s\n",e->errmess);
- return;
- }
- r.r[0]=0;
- r.r[2]=(int) manual;
- e=_kernel_swi(DDEUtils_ThrowbackSend,&r,&r);
- if (e)
- {
- if (verbose)
- {
- fprintf(stderr,"DEBUG: throwback failed - %s\n",e->errmess);
- }
- return;
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- throwback_error(file, line, m, x)
- => x = flag: 1=>already done an error in this file, 0=>first error ...
- file = ->filename
- line = line
- m = ->error message
- <= n/a
- */
- void throwback_error(char* file, int line, char *m, int x)
- {
- if (throwbackstarted==0)
- {
- throwback_start();
- throwbackstarted=1;
- }
- r.r[0]=1;
- r.r[2]=(int) file;
- r.r[3]=line;
- r.r[4]=1;
- r.r[5]=(int) m;
- e=_kernel_swi(DDEUtils_ThrowbackSend,&r,&r);
- if (e)
- {
- if (verbose)
- {
- fprintf(stderr,"DEBUG: throwback failed - %s\n",e->errmess);
- }
- }
- }
-
-
-
- /*---------------------------------------------------------------------------
- throwback_end
- => n/a
- <= n/a
- */
- void throwback_end(void)
- {
- e=_kernel_swi(DDEUtils_ThrowbackEnd,&r,&r);
- if (e)
- {
- if (verbose)
- {
- fprintf(stderr,"DEBUG: end throwback failed - %s\n",e->errmess);
- }
- }
- }
-
-
-
-
- /*----------------------------------------------------------------------------
- oof(x)
- => x
- <= ->"On" | "Off"
- .
- */
- char* oof(int x)
- {
- return x ? "On" : "Off";
- }
-
-
- /*----------------------------------------------------------------------------
- unpad(s)
- => s = ->string
- <= s modified so that there are no preceding or trailing spaces.
- */
- void unpad(char *s)
- {
- char *c;
-
- c=s+strlen(s);
- while (*--c==' ') /* scan from end for non-space */
- ;
- *++c=0; /* terminate string over first space */
-
- c=s;
- while (*c++==' ')
- ;
- c--;
- if (c==s) { return; }
- while ( (*s++=*c++)!=0 )
- ;
- *s=0;
- }
-
-
-
-
- /*----------------------------------------------------------------------------
- printlist(head)
- => head = ->head node of list
- <= n/a
- debugging function to print out the full contents of the list
- */
- void printlist(node *head)
- {
- if ( !(head->next) )
- {
- printf("---the list is empty\n");
- return;
- }
-
- while (head->next)
- {
- head=head->next;
- printf(" %s - %s\n",head->pagename,head->path);
- }
- }
-
-
- /*----------------------------------------------------------------------------
- lowerise(text)
- => text = ->string
- <= n/a
- Converts the string to lower case.
- */
- void lowerise(char *text)
- {
- while (*text)
- {
- *text=tolower(*text);
- text++;
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- lowcpy(d,s)
- => d = ->destination string
- s = ->source string
- <= n/a (d updated)
- copies s into d, ensuring that d is all lower case.
- */
- void lowcpy(char *d, char *s)
- {
- while (*s)
- {
- *d++=tolower(*s++);
- }
- *d=0;
- }
-
-
-
-
- /*----------------------------------------------------------------------------
- addnode(tail,dir,objname)
- => tail = ->current tail of list
- dir = ->name of directory 'page' is in
- objname = ->leaf name of object
- <= new tail of list
- */
- node* addnode(node *tail, char* dir, char* objname)
- {
- int i;
- node *newnode;
- char *tptr;
- char *pptr;
-
- newnode = malloc(sizeof(node));
- if ( !newnode )
- {
- fprintf(stderr,"strongtest: insufficient memory (case 2)\n");
- exit(4);
- }
- tail->next = newnode;
- newnode->next = 0;
- i=strlen(dir)+strlen(objname)+2;
- tptr = malloc(i*sizeof(char));
- pptr = malloc((strlen(objname)+1)*sizeof(char));
- if (!(tptr && pptr))
- {
- fprintf(stderr,"strongtest: insufficient memory (case 2a)\n");
- exit(4);
- }
- newnode->path = tptr;
- newnode->pagename = pptr;
- strcpy(tptr,dir);
- strcat(tptr,".");
- strcat(tptr,objname);
- strcpy(pptr,objname);
- newnode->referenced=0;
- lowerise(tptr);
- lowerise(pptr);
- return newnode;
- }
-
-
-
- /*----------------------------------------------------------------------------
- buildlist(dir,tail)
- => dir->manual name or subdirectory
- *tail is the node to add the list on to (ie. the tail)
- <= ->new tail of list
- builds the linked list of page information for directory 'name'.
- NB: RECURSIVE
- */
- node *buildlist(char* dir,node *tail)
- {
- char pathname[256];
- int offset;
- int read;
- int *filetype = (int*) (block);
- int *objtype = (int*) (block+16);
- char *objname = (block+20);
-
- offset = 0;
- do
- {
- r.r[0]=10; /* OS_GBPB 10 */
- r.r[1]=(int) dir; /* ->directory name */
- r.r[2]=(int) block; /* ->buffer */
- r.r[3]=1; /* entries to read */
- r.r[4]=offset; /* offset to start from */
- r.r[5]=1024; /* size of buffer */
- r.r[6]=(int) "*"; /* filename to match */
- e=_kernel_swi(OS_GBPB,&r,&r);
- if (e)
- {
- #ifdef DEBUG
- fprintf(stderr,"FS error: %s\n",e->errmess);
- #endif
- fserror++;
- return tail;
- }
- read = r.r[3];
- offset = r.r[4];
-
- if (read>0)
- {
- switch ( *objtype )
- {
- case 1 : switch ( (*filetype) & 0xffffff00 )
- {
- case 0xffffff00 : /* text file */
- case 0xfffffd00 : /* data file */
- tail=addnode(tail,dir,objname);
- break;
- default : ; /* skip anything else */
- }
- break;
- case 2 : strcpy(pathname,dir);
- strcat(pathname,".");
- strcat(pathname,objname);
- tail=buildlist(pathname,tail);
- break;
- default: ; /* Huh? what the hell is *this* doing here?!?! */
- }
- }
- } while (offset!=-1);
-
- return tail;
- }
-
-
- /*----------------------------------------------------------------------------
- testlink(name,dest)
- => name = ->name of link (for messages, etc)
- dest = ->link destination (pagename)
- <= n/a (global dangling updated if necessary, referenced element of
- list node of destination page updated as necessary).
- */
- void testlink(char *name, char *dest, node *page,int line,int *thrown)
- {
- node *scan;
- int succeded = 0;
- char search[256];
-
- lowcpy(search,dest);
- unpad(search);
- if (verbose)
- {
- printf("***testing link <%s=>%s> [%s]\n",name,dest,search);
- }
-
- if (*search=='*') { return; } /* don't test OS commands! */
-
- scan=head->next;
- while (scan && succeded==0)
- {
- if ( strcmp(scan->pagename,search)==0 )
- {
- succeded=1;
- (scan->referenced)++;
- }
- scan=scan->next;
- }
-
- if (succeded==0)
- {
- if (strcmp(name,dest)==0)
- {
- fprintf(stderr,"strongtest: page '%s', line %d - link <%s> fails\n",
- page->pagename,line,name);
- sprintf(search,"link <%s> fails",name);
- if (throwback)
- {
- throwback_error(page->path,line,search,*thrown);
- *thrown=1;
- }
- } else {
- fprintf(stderr,"strongtest: page '%s', line %d - link <%s=>%s> "
- "fails\n",page->pagename,line,name,dest);
- sprintf(search,"link <%s=>%s> fails",name,dest);
- if (throwback)
- {
- throwback_error(page->path,line,search,*thrown);
- *thrown=1;
- }
- }
- dangling++;
- }
- }
-
-
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------
- testpage(ptr)
- => ptr = ->node containg page information
- <= n/a (dangling, fserror, badchars updated)
- tests the page for bad characters & dangling links.
- */
- void testpage(node* ptr)
- {
- int size;
- char *pagetext;
- char linkname[256];
- char linkdest[256];
- char at,prev,next;
- int p;
- int status;
- int lnp;
- int ldp;
- int line;
- int thrown = 0;
-
- if (verbose)
- {
- printf("\n---testing page '%s'\n",ptr->pagename);
- }
- r.r[0]=17;
- r.r[1]=(int) (ptr->path);
- e=_kernel_swi(OS_File,&r,&r); /* get size of page */
- if (e)
- {
- fserror++;
- if (verbose)
- {
- fprintf(stderr,"FS error: %s\n",e->errmess);
- }
- return;
- }
- size=r.r[4];
- pagetext=malloc(size+1); /* allocate memory for page */
- if (!pagetext)
- {
- fprintf(stderr,"strongtest: insufficient memory (case 3)\n");
- exit(4);
- }
- r.r[0]=16;
- r.r[1]=(int) (ptr->path);
- r.r[2]=(int) pagetext;
- r.r[3]=0;
- e=_kernel_swi(OS_File,&r,&r); /* load page */
- if (e)
- {
- fserror++;
- if (verbose)
- {
- fprintf(stderr,"FS error: %s\n",e->errmess);
- }
- return;
- }
- if (verbose)
- {
- printf(" page loaded OK.\n");
- }
- pagetext[size]=0; /* terminate page so we can treat it as a string */
-
- status=0; at='!'; line = 1;
- for (p=0; p<size; p++)
- {
- prev=at;
- at=pagetext[p];
- next=pagetext[p+1];
- if (at=='\n') { line++; }
- if (at<32 && at!='\n' && at!='\t')
- {
- badchars++;
- fprintf(stderr,"strongtest: '%s', line %d - bad character\n",
- ptr->pagename,line);
- if (throwback)
- {
- throwback_error(ptr->path, line, "Bad character", thrown);
- thrown=1;
- }
- }
- switch (status)
- {
- case 0 : if (at=='<' && prev!='\\' && prev!='<' && next!='<'
- && next!='-' && next!='=')
- {
- status=1; lnp=0;
- }
- if (at=='#' && prev=='\n')
- {
- status=3;
- }
- break;
- case 1 : if (at=='=' && prev!='\\')
- {
- if (next=='>')
- {
- linkname[lnp]=0;
- status=2; ldp=0;
- p++;
- }
- } else {
- if (at=='>' && prev!='\\')
- {
- linkname[lnp]=0;
- strcpy(linkdest,linkname);
- testlink(linkname,linkdest,ptr,line,&thrown);
- status=0;
- } else {
- linkname[lnp++]=at;
- if (lnp>255)
- {
- fprintf(stderr,"Can't check page '%s' as it contains"
- " a link name more than 255 chars long.\n",
- ptr->pagename);
- free(pagetext);
- return;
- }
- }
- }
- break;
- case 2 : if (at=='>' && prev!='\\')
- {
- linkdest[ldp]=0;
- testlink(linkname,linkdest,ptr,line,&thrown);
- status=0;
- } else {
- linkdest[ldp++]=at;
- if (ldp>255)
- {
- fprintf(stderr,"Can't check page '%s' as it contains"
- " a link destination more than 255 chars "
- "long.\n", ptr->pagename);
- free(pagetext);
- return;
- }
- }
- break;
- case 3 : if (at=='\n')
- {
- status=0;
- }
- break;
- default: fprintf(stderr,"Page '%s' testing abandonned: "
- "status has escaped!\n", ptr->pagename);
- free(pagetext);
- return;
- }
- }
-
- free(pagetext); /* free the memory we've claimed */
- }
-
-
-
-
-
-
-
-
- /*----------------------------------------------------------------------------
- testmanual(name)
- => name ->manual name to test (full filename)
- <= returns 0 if manual is good, code otherwise:
- bit meaning
- 3 dangling link(s)
- 4 unaccessible pages(s)
- 5 filing system error(s)
- 6 non ASCII chars in page(s)
- */
- int testmanual(char *manual)
- {
- node *tail;
- node *scan;
-
- tail=buildlist(manual,head);
- if (verbose)
- {
- printf("List contents:\n");
- printlist(head);
- printf("\n\n");
- }
-
- throwbackstarted=0;
- scan=head->next;
- while (scan)
- {
- testpage(scan);
- scan=scan->next;
- }
-
- if (throwback && throwbackstarted)
- {
- throwback_end();
- }
-
- if (verbose) { printf("\n-------------------------\n"); }
-
- scan=head->next;
- while (scan)
- {
- if ( (scan->referenced)==0 )
- {
- if (strcmp(scan->pagename,"!root")!=0
- && strcmp(scan->pagename,"!configure")!=0)
- {
- fprintf(stderr,"strongtest: page '%s' is inaccessible\n",
- scan->pagename);
- unaccessible++;
- }
- }
- scan=scan->next;
- }
-
- if (dangling)
- {
- printf("strongtest: found %d dangling link(s)\n",dangling);
- }
- if (unaccessible)
- {
- printf("strongtest: found %d unaccessible pages(s)\n",unaccessible);
- }
- if (fserror)
- {
- printf("strongtest: %d FS errors occurred during testing\n",fserror);
- }
- if (badchars)
- {
- printf("strongtest: %d illegal characters found in manual\n",badchars);
- }
-
- return ( ((dangling!=0)<<3) | ((unaccessible!=0)<<4)
- | ((fserror!=0)<<5) | ((badchars!=0)<<6) );
- }
-
-
-
-
-
-
- /*-----------------------------------------------------------------------------
- main.
- tests args, makes sure that the manual to be tested actually is a manual
- (ie. is an image filetype 3d6). NB: returns an error if StrongHelp isn't
- running - this is because the image wouldn't be accessible.
- => command line args
- <= result of testmanual(<manual>) q.v.
- */
- int main(int argc, char * argv[])
- {
- int goodbad;
- int gotname = 0;
- int i;
-
- if (argc<2 || argc>4)
- {
- fprintf(stderr,"syntax: strongtest [-t] [-v] <manual>\n");
- exit(1);
- }
-
- for (i=1; i<argc; i++)
- {
- switch (*argv[i])
- {
- case '-' : switch (*(argv[i]+1))
- {
- case 't' : case 'T' : throwback=1; break;
- case 'v' : case 'V' : verbose=1; break;
- default: fprintf(stderr,"strongtest: bad switch -%c\n",
- *(argv[i]+1));
- exit(1);
- }
- break;
- default : if (gotname)
- {
- fprintf(stderr,"syntax: strongtest [-t] [-v] <manual>\n");
- exit(1);
- }
- gotname=1;
- strcpy(manual,argv[i]);
- }
- }
-
- if (!gotname)
- {
- fprintf(stderr,"syntax: strongtest [-t] [-v] <manual>\n");
- exit(1);
- }
-
- if (verbose)
- {
- printf("DEBUG: testing '%s', throwback %s\n",
- manual, oof(throwback));
- }
-
- r.r[0]=17;
- r.r[1]=(int) manual;
- _kernel_swi(OS_File,&r,&r); /* read cat. info for 'manual' */
-
- switch (r.r[0]) /* r0 = object type */
- {
- case 0 : fprintf(stderr,"stongtest: '%s' not found\n",manual);
- exit(2);
- break;
- case 1 : fprintf(stderr,"stongtest: '%s' is a file "
- "(is Stronghelp running?)\n",manual);
- exit(2);
- break;
- case 2 : fprintf(stderr,"stongtest: '%s' is a directory\n",manual);
- exit(2);
- break;
- case 3 : if ( (r.r[2] & 0xffffff00)!=0xfff3d600 )
- {
- fprintf(stderr,"strongtest: '%s' is not a manual\n",manual);
- exit(2);
- }
- break;
- default: fprintf(stderr,"strongtest: unrecognised object type"
- " (%d) for '%s'\n",r.r[0],manual);
- exit(2);
- }
-
- head=malloc(sizeof(node));
- if (head==0)
- {
- fprintf(stderr,"strongtest: nowhere near enough memory to run!\n");
- exit(4);
- }
-
- goodbad=testmanual(manual);
- if (goodbad)
- {
- fprintf(stderr,"strongtest: Manual '%s' contains %d error(s)\n",
- manual,dangling+unaccessible+badchars+fserror);
- } else {
- printf("strongtest: Manual '%s' checks out OK.\n",manual);
- }
-
- return goodbad;
- }
-
- /* Phew! */
-