diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/check |
Initial commit
Diffstat (limited to 'support/check')
-rw-r--r-- | support/check/check.c | 960 | ||||
-rw-r--r-- | support/check/check.doc | 221 | ||||
l--------- | support/check/check.txt | 1 | ||||
-rw-r--r-- | support/check/readme | 13 |
4 files changed, 1195 insertions, 0 deletions
diff --git a/support/check/check.c b/support/check/check.c new file mode 100644 index 0000000000..9351e376cb --- /dev/null +++ b/support/check/check.c @@ -0,0 +1,960 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +#define maxtag 16 +#define lmax 512 +#define bufsize 256*64 + +#define getch() getchar() + +char lb[lmax] ; + +union mix +{ + struct labelnode *pointer; + int value; +}; +struct labelnode +{ + struct labelnode *next; + union mix labels ; + char text[maxtag]; +}; + +char block[maxtag] ; + +char *infile,*outfile; +int change,verbose,exits,printtext,labels,tags,silent,checking,printchanges; +int tagsout,noline,deutsch,include_input; +FILE *input,*output; +int exitcode; +char *pos; +int line,column,pass,end; +struct labelnode *groups; + +/* *** next *** */ + +char next(void) /* get next text position */ +{ + char c; + int k; + c=*pos++; + if (c=='\n') + { + if (noline&&(lb[0]=='\n')) {} + else if (change&&(pass==2)) fputs(lb,output); + if (fgets(lb,lmax,input)==0) + { + end=1; + return(0); + } + noline=0; + pos=lb; + k=strlen(lb); + if (k==0 || lb[k-1]!='\n') + { + lb[k]='\n'; + lb[k+1]=0; + } + c='\n'; + } + if (printtext) printf("%c",c); + column+=1; + return(c); +} + +/* *** various supporting functions *** */ + +void skip(int l) /* skip l characters */ +{ + int i; + if (l>0) + for (i=0;i<l;i++) next(); +} + +void skipblanks(void) /* skip blanks */ +{ + while (*pos==' ') next(); +} + +void skipalnum(void) /* skip a alphanumerical word */ +{ + while (isalnum(*pos)) next(); +} + +void skipalnumbs(void) /* skip a alphanumerical with \ */ +{ + while (isalnum(*pos) || *pos=='\\') next(); +} + +void printlast(void) /* print last position in text */ +{ + printf("\nLast position checked : Line %d, Column %d (in %s)", + line,column,infile); +} + +void wait(void) +{ + int a; + printf("\nHit return or ESC to exit, please!\n"); + do { + } while((a=getch())==0); + if (a==27) exit(1); +} + +void error(void) /* error exit */ +{ + printlast(); + wait(); + exitcode=1; + if (exits) + exit(exitcode); +} + +int scannumber(void) /* scan text for an integer */ +{ + int sign=0,n=0; + if (*pos=='-') { + sign=1; + next(); + } + if (!(isdigit(*pos))) + { + printf("\nIllegal Number"); + error(); + } + while (isdigit(*pos)) + { + n=n*10+(*pos)-'0'; + next(); + } + if (sign) return(-n); + else return(n); +} + +void putcommand(char *a,int *l) +/* puts a word at pos to a and its length to l */ +{ + char *p; + p=pos; + *l=0; + if (isalpha(*p)) + { + do { + *a++=*p++; + (*l)++; + } while((isalpha(*p))&&(*l<50)); + *a=0; + } + else + { + *a++=*p; + *a=0; + *l=1; + } +} + +void show(char *text) /* print text, if verbose is on */ +{ + if ((verbose)&&(!printtext)) printf("%s",text); +} + +/* *** find and scanfor *** */ + +int find(char *text) /* advance in the file, starting from pos. + if text="", find end of file, else stop at text + if text found, return 1, else 0.*/ +{ + int l; + void advance(void) ; + l=strlen(text); + do + { + if (l>0) + if (strncmp(pos,text,l)==0) { + skip(l); + return(1); + } + advance(); + } while (!end); + return(0); +} + +void scanfor(char *text) /* scan till text appears */ +{ + if(!(find(text))) { + printf("\n%s missing",text); + error(); + } +} + +/* *** subroutines for german syntax *** */ + +void umlaut(char a) +{ + int lbl; + char repl[3]; + if (deutsch&&(pass==2)) + { + pos=pos-1; + repl[0]='\\'; + repl[1]='"'; + repl[2]=a; + lbl=strlen(lb)+1; + if (lbl+3>=lmax) + { + printf("\nLine buffer overflow"); + error(); + exit(exitcode); + } + memmove(pos+2,pos,lbl-(int)(pos-lb)); + memmove(pos,repl,3); + }; +} + +void szet(void) +{ + int lbl; + char repl[5]; + if (deutsch&&(pass==2)) + { + pos=pos-1; + repl[0]='{'; + repl[1]='\\'; + repl[2]='s'; + repl[3]='s'; + repl[4]='}'; + lbl=strlen(lb)+1; + if (lbl+5>=lmax) + { + printf("\nLine buffer overflow"); + error(); + exit(exitcode); + } + memmove(pos+4,pos,lbl-(int)(pos-lb)); + memmove(pos,repl,5); + }; +} + +/* *** label handling commands *** */ + +struct labelnode *findlast(struct labelnode *r) +/* find the last label in a list */ +{ + if (r==0) return(0); + while (r->next!=0) { + r=r->next; + }; + return(r); +} + +struct labelnode *findnode(struct labelnode *r,char *label) +/* scan a list of labels for label */ +{ + if (r==0) return(0); + while (strcmp(label,r->text)!=0) + { + if (r->next==0) return(0); + r=r->next; + } + return(r); +} + +struct labelnode *findlabel(char *group,char *label) +/* find a label in label list, return label */ +{ + struct labelnode *r,*findnode(); + if ((r=findnode(groups,group))==0) return(0); + r=r->labels.pointer; + while (r!=0) + { + if (strcmp(label,r->text)==0) return(r); + r=r->next; + } + return(0); +} + +struct labelnode *newnode(struct labelnode *r,char *label) +/* connects a new label to r */ +{ + struct labelnode *new; + new=(struct labelnode *)malloc(sizeof(struct labelnode)); + if (new==0) + { + printf("\nNo more space for labels"); + error(); + exit(exitcode); + }; + if (r!=0) r->next=new; + new->next=0; + new->labels.pointer=0; + memmove(new->text,label,16); + return(new); +} + +int newvalue(char *group) +/* find the next number in group */ +{ + int count=1; + struct labelnode *r; + if ((r=findnode(groups,group))==0) return(count); + r=r->labels.pointer; + while (r!=0) { + count=r->labels.value; + r=r->next; + } + return(count+1); +} + +void correctlabel(char *group,char *label,char *p1,char *p2) +/* remove p1-p2 from text and add + corresponding number */ +{ + int n,l,lbl,flag; + struct labelnode *r; + char string[12]; + if (strcmp(group,"block")!=0) + { + flag=1; + if ((r=findlabel(group,label))==0) + { + printf("\nLabel %s.%s not defined",group,label); + error(); + n=0; + } + else n=r->labels.value; + } + else + { + flag=0; + noline=1; + } + if (change) + { + if (flag) sprintf(string,"%d",n); + else string[0]=0; + l=strlen(string); + lbl=strlen(lb)+1; + if (lbl+l-(int)(p2-p1)>=lmax) + { + printf("\nLine buffer overflow"); + error(); + exit(exitcode); + } + memmove(p1+l,p2,lbl-(int)(p2-lb)); + memmove(p1,string,l); + if (printchanges&&flag) + printf("\n%s.%s changed to %d",group,label,n); + pos+=l-(int)(p2-p1); + } +} + +void printlabels(void) /* print all used labels */ +{ + struct labelnode *g,*l; + printf("\nUsed Labels and Tags : "); + g=groups; + while (g!=0) + { + l=g->labels.pointer; + while (l!=0) + { + printf("\n%s.%s = %d",g->text,l->text,l->labels.value); + l=l->next; + } + g=g->next; + } +} + +void outlabels(void) /* print all used labels */ +{ + struct labelnode *g,*l; + void outopen(char *) ; + outopen(outfile); + g=groups; + while (g!=0) + { + l=g->labels.pointer; + while (l!=0) + { + fprintf(output,"#;%s.%s=%d\n",g->text,l->text,l->labels.value); + l=l->next; + } + g=g->next; + } + fclose(output); +} + +void addlabel(char *group,char *label,int n) +/* add a label to the label list, value n */ +{ + struct labelnode *r,*new,dummy,*newnode(),*findnode(); + struct labelnode *findlast(),*findlabel(); + if (strcmp(group,"block")==0) + { + /* redefine the default block with label */ + if (strlen(label)<maxtag-2) memmove(block,label,maxtag); + else { + printf("\nBlock %s illegal",label); + error(); + } + } + else + { + /* add the label */ + if(findlabel(group,label)!=0) + { + printf("\nDouble declaration of label %s.%s",group,label); + error(); + }; + if (groups==0) r=groups=newnode(0,group); + else /* there is a group already */ + { + r=findnode(groups,group); /* look up group */ + if (r==0) r=newnode(findlast(groups),group); + } + if (r->labels.pointer==0) /* if new group */ + { + new=newnode(&dummy,label); + r->labels.pointer=dummy.next; + } + else new=newnode(findlast(r->labels.pointer),label); /* append label */ + new->labels.value=n; + } +} + +/* *** tag commands *** */ + +int gettag(char *group,char *label,char **p1,char **p2,int *n,int *val) +/* read a tag or label, and note start and end of labeltext */ +{ + int br; + char *p,*ph; + skipblanks(); + if (*pos=='!' || *pos=='#') + { + *p1=pos; + if (*pos=='!') next(); + *p2=pos; + *label=0; + *group=0; + return(1); + } + if (*pos=='{') { + next(); + br=1; + } else br=0; + p=ph=*p1=pos; + if (*pos=='@') next(); + while (*pos!='}') + { + skipalnumbs(); + if (*pos!='.') break; + ph=pos; + next(); + *p1=pos; + } + skipalnum(); + *p2=pos; + if (((*p2-*p1)>maxtag-1)||((ph-p)>maxtag-2)) return(0); + if (ph!=p) { + memmove(group,p,(int)(ph-p)); + *(group+(int)(ph-p))=0; + } + else memmove(group,block,maxtag-1); + memmove(label,*p1,(int)(*p2-*p1)); + *(label+(int)(*p2-*p1))=0; + if (*val&&(*pos=='=')) { + next(); + *n=scannumber(); + *val=1; + *p2=pos; + } + else *val=0; + if (*pos=='_') { + next(); + *p2=pos; + } + if (br) + if (*pos!='}') return(0); + else next(); + return(1); +} + +/* *** subroutines to process special syntax features *** */ + +void brackets(void) /* process {...} */ +{ + int l,c; + l=line; + c=column; + show("{ "); + if(!(find("}"))) + { + printf("\n{ unbalanced in line %d, column %d",l,c); + error(); + } + else show("} "); +} + +void informula(void) /* process $...$ */ +{ + int l,c; + show("+$ "); + l=line; + c=column; + if (!(find("$"))) + { + printf("\nUnmatched $ in line %d, column %d",l,c); + error(); + }; + if (*pos=='$') + { + printf("\n$$ not allowed here"); + error(); + } + else show("-$ "); +} + +void formula(void) /* process $$...$$ */ +{ + int l,c; + show("+$$ "); + l=line; + c=column; + if (!(find("$")) || *pos++!='$') + { + printf("\nUnmatched $$ in line %d, column %c",l,c); + error(); + }; + if (*pos=='$') + { + printf("$$$ is illegal"); + error(); + } + else show("-$$ "); +} + +void comment(void) /* pass a coment %... */ +{ + while (*pos!='\n') { + next(); + }; +} + +void label(void) /* process a label, i.e note the label #=... or change #: to + a number, depending on pass, collect #; and cancel */ +{ + char group[maxtag],label[maxtag],a,*p,*p1,*p2; + int n,val; + p=pos; + a=*pos; + next(); + if ((a=='=')||(a==':')||(a==';')) + { + if (a==':') val=0; + else val=1; /* =value allowed? */ + if(!(gettag(group,label,&p1,&p2,&n,&val))) + { + printf("\nIllegal Label"); + error(); + exit(exitcode); + }; + if (pass==1) + if ((a=='=')||(a==';')) + { + if (!val) n=newvalue(group); /* n was not found in =n */ + + addlabel(group,label,n); + } + if (pass==2) + { + if (strcmp(group,"block")==0) addlabel(group,label,0); + if (a==';') { + correctlabel("block",label,p-1,pos); + noline=1; + } + else correctlabel(group,label,p-1,pos); + } + } +} + +/* *** command processing functions *** */ + +void tag(void) /* process \tag {...} or \tag ... */ +{ + char label[maxtag],group[maxtag],*p1,*p2; + int n,val=1; + if (tags) + { + *group='@'; + if (!(gettag(group+1,label,&p1,&p2,&n,&val))) + { + printf("\nIllegal Tag"); + error(); + exit(exitcode); + }; + if ((pass==1)&&(*p1!='!')&&(*p1!='#')) + { + if (!val) n=newvalue(group); /* =n not found */ + addlabel(group,label,n); + } + else if (pass==2) + if ((*p1!='!')&&(*p1!='#')) + correctlabel(group,label,p1,p2); + else correctlabel("block",label,p1,p2); + } +} + +void thetag(void) +{ + char label[maxtag],group[maxtag],*p1,*p2; + int n,val=0; + if (tags) + { + *group='@'; + if (!(gettag(group+1,label,&p1,&p2,&n,&val))) + { + printf("\nIllegal Tag"); + error(); + exit(exitcode); + }; + if (pass==2) + if ((*p1!='!') && (*p1!='#')) + correctlabel(group,label,p1,p2); + else correctlabel("block",label,p1,p2); + } +} + +void inopen(char *filename); +void doinput (void) +{ + FILE *oldfile; + char name[512],*n,*oldinfile; + int c,oldline; + oldfile=input; + oldinfile=infile; + oldline=line; + next(); + n=name; + while (*pos!=' ' && *pos!='}' && *pos!='\n') + { + *n++=next(); + } + *n++=0; + inopen(name); + line=0; + infile=name; + find(""); + fclose(input); + input=oldfile; + pos=lb; + noline=1; + *pos='\n'; + infile=oldinfile; + line=oldline; + end=0; +} + +void command(void) /* process a command \... */ +{ + char com[50]; + int l; + putcommand(com,&l); + skip(l); + if (strcmp(com,"tag")==0) tag(); + else if (strcmp(com,"thetag")==0) thetag(); + else if (strcmp(com,"input")==0 && include_input) doinput(); +} + +/* *** subroutines to process the file *** */ + +void advance(void) /* advance pos one character or command */ +{ + char c; + c=next(); + if (checking) + switch(c) + { + case '\n': + { + line+=1; + column=1; + if (verbose) printf(" %d ",line); + break; + } + case '{': + { + brackets(); + break; + } + case '}': + { + printf("\nUnmatched }"); + error(); + break; + } + case '$': + { + if (*pos=='$') + { + next(); + if (*pos=='$') + { + printf("$$$ is illegal"); + error(); + } + else formula(); + } + else informula(); + break; + } + case '\\': + { + command(); + break; + } + case '%': + { + comment(); + break; + } + case '#': + { + if (labels) label(); + break; + } + case '': + case '': + { + umlaut('o'); + break; + } + case '': + case '': + { + umlaut('a'); + break; + } + case '': + case '': + { + umlaut('u'); + break; + } + case '': + case '': + { + umlaut('O'); + break; + } + + case '': + case '': + { + umlaut('A'); + break; + } + case '': + case '': + { + umlaut('U'); + break; + } + case '': + case '': + case '': + { + szet(); + break; + } + default: + { + }; + } + else + switch(c) + { + case '#': + { + if (labels) label(); + break; + } + case '\n' : + { + column=1; + line+=1; + if (verbose) printf("%d ",line); + break; + } + default: + { + }; + } +} + +/* *** main subroutines *** */ + +void getparams(int n,char *a[]) /* read parameters from command line */ +{ + char *i; + if ((n<3)||(*a[1]!='-')) + { + printf("\nUsage -vpltsne file1.tex file2.tex"); + printf("\nv=verbose, p=print, l=labels, t=tags"); + printf("\ns=silent, n=no checking e=don't exit on error"); + printf("\no=output tags and labels, d=deutsch, i=include input"); + wait(); + exit(1); + } + verbose=printtext=labels=tags=silent=deutsch=include_input=0; + exits=checking=1; + for (i=a[1]+1;*i!=0;i++) + switch(toupper(*i)) + { + case 'V': + { + verbose=1; + break; + } + case 'P': + { + printtext=1; + verbose=0; + break; + } + case 'L': + { + labels=1; + break; + } + case 'T': + { + tags=1; + break; + } + case 'S': + { + silent=1; + break; + } + case 'N': + { + checking=0; + break; + } + case 'E': + { + exits=0; + break; + } + case 'O': + { + tagsout=1; + break; + } + case 'D': + { + deutsch=1; + break; + } + case 'I': + { + include_input=1; + break; + } + default: + { + } + } + infile=a[2]; + if (n<4) change=0; + else { + outfile=a[3]; + change=1; + }; + if (tagsout) change=0 ; +} + +void inopen(char *filename) +{ + char name[512]; + if ((input=fopen(filename,"r"))==0) + { + strcpy(name,filename); + strcat(name,".tex"); + if ((input=fopen(name,"r"))==0) + { + printf("\nUnable to open %s",filename); + wait(); + exit(1); + } + }; + setvbuf(input,0,_IOFBF,bufsize); + lb[0]='\n'; + pos=lb; + noline=1; +} + +void outopen(char *filename) +{ + if ((output=fopen(filename,"w"))==0) + { + printf("\nUnable to open %s",filename); + wait(); + exit(1); + }; + setvbuf(output,0,_IOFBF,bufsize); +} + +void checkfile(void) /* check the syntax of the file at filestart */ +{ + printf("\nPass 1 : \n"); /* line swap on */ + line=0; + column=1; + groups=0; + block[0]=0; + pass=1; + end=0; + inopen(infile); + if (labels||tags) find(""); + if ((labels||tags)&&(!silent)) printlabels(); + if (tagsout) outlabels() ; + else + { + pass=2; + line=0; + column=1; + printtext=0; + printchanges=verbose; + verbose=0; + end=0; + block[0]=0; + rewind(input); + lb[0]='\n'; + pos=lb; + noline=1; + if (change) outopen(outfile); + printf("\nPass 2 : \n"); + find(""); + if (change) fclose(output) ; + } + printlast(); + fclose(input) ; + printf("\n\n"); +} + +main(int argc,char *argv[]) /* main function to read in, process and write file */ +{ + printf( + "\n ***** Checker, Copyright by R. Grothmann, Version %s ***** \n", + __DATE__); + getparams(argc,argv); + if (change) printf("\nModifying %s to %s.",infile,outfile); + else printf("\nChecking %s.",infile); + checkfile(); + return(exitcode); +} + diff --git a/support/check/check.doc b/support/check/check.doc new file mode 100644 index 0000000000..83d8b30dd9 --- /dev/null +++ b/support/check/check.doc @@ -0,0 +1,221 @@ + +*********************************************************************** +* * +* CHECKER * +* by R. Grothmann * +* * +*********************************************************************** + + Documentation + ============= + + + Introduction + ------------ + + Checker is a program designed for testing TeX files. Besides checking + the syntax, it features labels and automatic tag numbering. Just start + checker by entering + + check -options infile outfile + + On the Atari ST you have to click on check.ttp and enter the options + and files into the ttp box, appearing on the screen. "options" is a + sequence of the letters (capital or not) l,t,s,v,p,n or o. "infile" + and "outfile" (optional) are standard filenames. An example is + + check -lt work.txt work.tex + + The program will read in the file work.txt, check it and produce an + output to the file work.tex, thereby changing labels and tags to their + values. If you omit the outfile, the program will produce no output. + + + Labels + ------ + + Labels belong to a group and have a name and a value, which is an + integer (positive or negative). They are defined in a program by + + #=group.name + + or + + #={group.name} + + The name is any alphanumeric string (consisting of lowercase or upper- + case letters or digits), not exceeding 15 characters. The group may + consist of several alphanumeric strings, seperated by "." and not ex- + ceeding 14 characters. An example is + + #=1.1.a + + or + + #={1.1.a} + + where "1.1" is the group and "a" is the name. The Value of the label + can be assigned to it by the sequence + + #=group.name=value + + or + + #={group.name=value} + + Remember that "value" has to be an integer. For example + + #=refs.miller=10 + + If you do not assign a value to the label, it gets the value of the + previous label in the group plus 1. If there is no previous label, the + value will be 1. On the output, the whole definition of the label is + replaced by the value of the label. And so are all references of the + label. References are of the following form + + #:group.name + + or + + #:{group.name} + + Of course, you cannot assign a value to a reference. If a label is + immediately followed by an underbar "_", then this underbar disappears + from the output, for instance + + #:test.a_a + + will be replaced by "1a", if "test.a" has the value 1. The label feature + is only active, if the option "l" was given on the command line. Other- + wise the program will just read over any #. + + + Default Group + ------------- + + If a label is defined or referred to without a group (omitting both + the group and the "."), then it is assumed to be a label in the default + group. You can set the default group by + + #=block.group + + This is not a label definition. There is never a group named "block". + Instead, the default group is set to "group". As an example, let + + #=block.refs + #=a + + be a sequence from your file. Then the reference + + #:a + + is a reference to the label "refs.a", unless you have redefined the + default group. If you did so, you may refer to that label by + + #:refs.a + + + Tags + ---- + + Tags are a part of TeX's syntax. Checker assumes tags to be defined as + + \tag group.name + + or + + \tag {group.name} + + "group" and "name" obey the same syntax rules as in the definition of + labels above. They are referred to by + + \thetag{group.name} + + As with labels, you may assign a value to a tag. An example is + + \tag 1.a=0 + + On the output, only the name of the tag is replaced by the value of the + tag. Thus the above tag would change to + + \tag 1.0 + + Of course, all references (\thetag ...) are corrected too. As with + labels, the program checks for double definition of a tag. Tags may + be proteced by + + \tag !something + + or + + \thetag !something + + The the program will not change "something". Only the "!" will be left + out. What was said about default groups, holds for tags too. The tag + feature is active, if the option "t" is given in the command line. The + "_" works in the same way, as it does with labels. + + + Syntax checking + --------------- + + Unless the option "n" was given, the program checks the syntax in your + file for correct usage of "$". "$$", "{" and "}". The program is clever + enough to know that "\{" is different from "{". The first error will + abort the program and will be reported. Comments "%" are omitted. An + error does not abort the program if the option "e" was given int the + command line. + + + Output of Labels and Tags + ------------------------- + + Only labels and tags are written to the output file, if the option "o" + was given in the command line. This is done in such a way that the + output file can be read into a TeX file. All labels are written as + + #;group.name=value + + The tags look like + + #;@group.name=value + + The sequence "#;" starts a blind label. Such a label is defined, as + if "@;" was replaced by "@=". But on the output, it will not show up. + The same is true for tags. So you can just use the old label definitions + in a new TeX file. This may be used in a continuation of a previous + TeX text. If a blind label or tag occupies a complete line, then this + line will not go to output. Otherwise the rest of the line will be + in the output. + + + Other Options + ------------- + + You have control over the screen output of the program. Least printing + is produced with the option "s" (silent). The option "v" lists all the + syntax elements the program finds (verbose). The option "p" prints out + the complete text (print). + + + Internals + --------- + + Checker is a C program, which uses two passes. Pass 1 checks the syntax + and collects all labels and tags. Pass 2 corrects labels and tags and + produces the outfile. An existing outfile will be truncated without + backup. Reading and Writing is done via a buffer. The preformance is + best, when the files are on RAM disk or harddisk. + +************************************************************************ + + If you have troubles with the program, contact + + R. Grothmann + Ostenstr. 18 + 8078 Eichstaett + W-Germany + + EMail: rene.grothmann@ku-eichstaett.de + +************************************************************************* diff --git a/support/check/check.txt b/support/check/check.txt new file mode 120000 index 0000000000..8095cb5e7f --- /dev/null +++ b/support/check/check.txt @@ -0,0 +1 @@ +check.doc
\ No newline at end of file diff --git a/support/check/readme b/support/check/readme new file mode 100644 index 0000000000..552ec2ab25 --- /dev/null +++ b/support/check/readme @@ -0,0 +1,13 @@ +Overview +-------- + +check.c is the source of a TeX file filter. It provides syntax checking +as well as automatic labelling, and additionally german language support. + + +Hints for compiling check.c +--------------------------- + +check.c can be compiled with any ANSI-C C-compiler. On UNIX systems use + cc -o check check.c -lm +to produce an executable check. Read check.doc for usage hints. |