Changeset View
Changeset View
Standalone View
Standalone View
externals/figlet/chkfont.c
- This file was added.
| #include <stdio.h> | |||||
| #include <string.h> | |||||
| #include <ctype.h> | |||||
| #ifdef __STDC__ | |||||
| #include <stdlib.h> | |||||
| #endif | |||||
| #define DATE "20 Feb 1996" | |||||
| #define VERSION "2.2" | |||||
| /* | |||||
| chkfont | |||||
| By Glenn Chappell <ggc@uiuc.edu> | |||||
| This program checks figlet 2.0/2.1 font files for format errors. | |||||
| It also looks for signs of common problems and gives warnings. | |||||
| chkfont does not modify font files. | |||||
| Usage: chkfont fontfile ... | |||||
| Note: This is very much a spare-time project. It's probably | |||||
| full o' bugs .... | |||||
| */ | |||||
| /* #define CHECKBLANKS */ | |||||
| #define FONTFILESUFFIX ".flf" | |||||
| #define FONTFILEMAGICNUMBER "flf2" | |||||
| char posshardblanks[9] = { '!', '@', '#', '$', '%', '&', '*', 0x7f, 0 }; | |||||
| char *myname,*fontfilename; | |||||
| FILE *fontfile; | |||||
| char hardblank; | |||||
| int charheight,upheight,maxlen=0,old_layout; | |||||
| int spectagcnt; | |||||
| char *fileline; | |||||
| int maxlinelength=0,currline; | |||||
| int ec,wc; | |||||
| int incon_endmarkwarn,endmark_countwarn,nonincrwarn; | |||||
| int bigcodetagwarn,deutschcodetagwarn,asciicodetagwarn; | |||||
| int codetagcnt; | |||||
| int gone; | |||||
| void weregone(really) | |||||
| int really; | |||||
| { | |||||
| if (!really && 2*ec+wc<=40) { | |||||
| return; | |||||
| } | |||||
| if (ec+wc>0) printf("*******************************************************************************\n"); | |||||
| if (!really) { | |||||
| printf("%s: Too many errors/warnings.\n",fontfilename); | |||||
| } | |||||
| printf("%s: Errors: %d, Warnings: %d\n",fontfilename,ec,wc); | |||||
| if (currline>1 && maxlen!=maxlinelength) { | |||||
| printf("%s: maxlen: %d, actual max line length: %d\n", | |||||
| fontfilename,maxlen,maxlinelength); | |||||
| if (codetagcnt>0 && spectagcnt==-1) { | |||||
| printf("%s: Code-tagged characters: %d\n",fontfilename,codetagcnt); | |||||
| } | |||||
| } | |||||
| printf("-------------------------------------------------------------------------------\n"); | |||||
| gone=1; | |||||
| } | |||||
| char *my_alloc(size) | |||||
| int size; | |||||
| { | |||||
| char *ptr; | |||||
| ptr=(char *)malloc(size); | |||||
| if (ptr==NULL) { | |||||
| fprintf(stderr,"%s: Out of memory\n",myname); | |||||
| exit(1); | |||||
| } | |||||
| return(ptr); | |||||
| } | |||||
| int badsuffix(path,suffix) | |||||
| char *path; | |||||
| char *suffix; | |||||
| { | |||||
| char ucsuffix[10]; | |||||
| char *s; | |||||
| strcpy(ucsuffix,suffix); | |||||
| for (s = ucsuffix; *s; s++) { | |||||
| *s = toupper(*s); | |||||
| } | |||||
| if (strlen(path)<strlen(suffix)) return 1; | |||||
| s = path + strlen(path) - strlen(suffix); | |||||
| if (strcmp(s,suffix) == 0) return 0; | |||||
| if (strcmp(s,ucsuffix) == 0) return 0; | |||||
| return 1; | |||||
| } | |||||
| void usageerr() | |||||
| { | |||||
| fprintf(stderr,"chkfont by Glenn Chappell <ggc@uiuc.edu>\n"); | |||||
| fprintf(stderr,"Version: %s, date: %s\n",VERSION,DATE); | |||||
| fprintf(stderr,"Checks figlet 2.0/2.1 font files for format errors.\n"); | |||||
| fprintf(stderr,"(Does not modify font files.)\n"); | |||||
| fprintf(stderr,"Usage: %s fontfile ...\n",myname); | |||||
| exit(1); | |||||
| } | |||||
| void readchar() | |||||
| { | |||||
| int i,expected_width,k,len,newlen,diff,l; | |||||
| char endmark,expected_endmark; | |||||
| int leadblanks,minleadblanks,trailblanks,mintrailblanks; | |||||
| char *ret; | |||||
| expected_width = expected_endmark = 0; /* prevent compiler warning */ | |||||
| for (i=0;i<charheight;i++) { | |||||
| ret = fgets(fileline,maxlen+1000,fontfile); | |||||
| if (ret == NULL) { | |||||
| printf("%s: ERROR (fatal)- Unexpected read error after line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(1); if (gone) return; | |||||
| } | |||||
| if (feof(fontfile)) { | |||||
| printf("%s: ERROR (fatal)- Unexpected end of file after line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(1); if (gone) return; | |||||
| } | |||||
| currline++; | |||||
| len=strlen(fileline)-1; | |||||
| if (len>maxlinelength) { | |||||
| maxlinelength=len; | |||||
| } | |||||
| if (len>maxlen) { | |||||
| printf("%s: ERROR- Line length > maxlen in line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| k=len; | |||||
| endmark=k<0?'\0':(k==0||fileline[k]!='\n')?fileline[k]:fileline[k-1]; | |||||
| for(;k>=0?(fileline[k]=='\n' || fileline[k]==endmark):0;k--) { | |||||
| fileline[k]='\0'; | |||||
| } | |||||
| newlen=strlen(fileline); | |||||
| for (l=0;l<newlen ? fileline[l]==' ' : 0;l++) ; | |||||
| leadblanks = l; | |||||
| for (l=newlen-1;l>=0 ? fileline[l]==' ' : 0;l--) ; | |||||
| trailblanks = newlen-1-l; | |||||
| if (i==0) { | |||||
| expected_endmark = endmark; | |||||
| expected_width = newlen; | |||||
| minleadblanks = leadblanks; | |||||
| mintrailblanks = trailblanks; | |||||
| if (endmark==' ') { | |||||
| printf("%s: Warning- Blank endmark in line %d.\n", | |||||
| fontfilename,currline); | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| } | |||||
| else { | |||||
| if (leadblanks<minleadblanks) minleadblanks = leadblanks; | |||||
| if (trailblanks<mintrailblanks) mintrailblanks = trailblanks; | |||||
| if (endmark!=expected_endmark && !incon_endmarkwarn) { | |||||
| printf("%s: Warning- Inconsistent endmark in line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning will only be printed once.)\n", | |||||
| fontfilename); | |||||
| incon_endmarkwarn = 1; | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (newlen!=expected_width) { | |||||
| printf("%s: ERROR- Inconsistent character width in line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| } | |||||
| diff=len-newlen; | |||||
| if (diff>2) { | |||||
| printf("%s: ERROR- Too many endmarks in line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| else if (charheight>1 && (diff!=(i==charheight-1)+1)) { | |||||
| if (!endmark_countwarn) { | |||||
| printf("%s: Warning- Endchar count convention violated in line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning will only be printed once.)\n", | |||||
| fontfilename); | |||||
| endmark_countwarn = 1; | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| } | |||||
| } | |||||
| #ifdef CHECKBLANKS | |||||
| if (minleadblanks+mintrailblanks>0 && old_layout>=0) { | |||||
| printf("%s: Warning- Leading/trailing blanks in char. ending at line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning only given when old_layout > -1.)\n", | |||||
| fontfilename); | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| #endif /* #ifdef CHECKBLANKS */ | |||||
| } | |||||
| void checkit() | |||||
| { | |||||
| int i,k,cmtcount,numsread,ffrighttoleft,have_layout,layout; | |||||
| char magicnum[5],cha; | |||||
| long oldord,theord; | |||||
| int tmpcnt,len; | |||||
| ec=0;wc=0; | |||||
| incon_endmarkwarn=0; endmark_countwarn=0; nonincrwarn=0; | |||||
| bigcodetagwarn=0; deutschcodetagwarn=0; | |||||
| asciicodetagwarn=0; | |||||
| codetagcnt=0; | |||||
| gone=0; | |||||
| if (!strcmp(fontfilename,"-")) { | |||||
| fontfilename="(stdin)"; | |||||
| fontfile=stdin; | |||||
| } | |||||
| else { | |||||
| fontfile=fopen(fontfilename,"r"); | |||||
| if (fontfile == NULL) { | |||||
| fprintf(stderr,"%s: Could not open file '%s'\n",myname,fontfilename); | |||||
| exit(1); | |||||
| } | |||||
| } | |||||
| if (fontfile!=stdin) { | |||||
| if (badsuffix(fontfilename,FONTFILESUFFIX)) { | |||||
| printf("%s: ERROR- Filename does not end with '%s'.\n", | |||||
| fontfilename,FONTFILESUFFIX); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| } | |||||
| numsread=fscanf(fontfile,"%4s",magicnum); | |||||
| if (numsread == EOF) { | |||||
| printf("%s: ERROR- can't read magic number.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (strcmp(magicnum,FONTFILEMAGICNUMBER)) { | |||||
| printf("%s: ERROR- Incorrect magic number.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| cha=getc(fontfile); | |||||
| if (cha!='a') { | |||||
| printf("%s: Warning- Sub-version character is not 'a'.\n",fontfilename); | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| fileline=(char*)my_alloc(sizeof(char)*(1001)); | |||||
| if (fgets(fileline,1001,fontfile)==NULL) { | |||||
| fileline[0] = '\0'; | |||||
| } | |||||
| if (strlen(fileline)>0 ? fileline[strlen(fileline)-1]!='\n' : 0) { | |||||
| while(k=getc(fontfile),k!='\n'&&k!=EOF) ; /* Advance to end of line */ | |||||
| } | |||||
| numsread=sscanf(fileline,"%c %d %d %d %d %d %d %d %d", | |||||
| &hardblank,&charheight,&upheight,&maxlen,&old_layout,&cmtcount, | |||||
| &ffrighttoleft,&layout,&spectagcnt); | |||||
| free(fileline); | |||||
| fileline = NULL; | |||||
| if (numsread<7) { | |||||
| ffrighttoleft=0; | |||||
| } | |||||
| if (numsread<9) { | |||||
| spectagcnt=-1; | |||||
| } | |||||
| have_layout = (numsread>=8); | |||||
| if (6>numsread) { | |||||
| printf("%s: ERROR (fatal)- First line improperly formatted.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(1); if (gone) return; | |||||
| } | |||||
| if (!strchr(posshardblanks,hardblank)) { | |||||
| printf("%s: Warning- Unusual hardblank.\n",fontfilename); | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (charheight<1) { | |||||
| printf("%s: ERROR (fatal)- charheight not positive.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(1); if (gone) return; | |||||
| } | |||||
| if (upheight>charheight || upheight<1) { | |||||
| printf("%s: ERROR- up_height out of bounds.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (maxlen<1) { | |||||
| printf("%s: ERROR (fatal)- maxlen not positive.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(1); if (gone) return; | |||||
| } | |||||
| if (old_layout<-1) { | |||||
| printf("%s: ERROR- old_layout < -1.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (old_layout>63) { | |||||
| printf("%s: ERROR- old_layout > 63.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (have_layout && layout<0) { | |||||
| printf("%s: ERROR- layout < 0.\n", fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (have_layout &&layout>32767) { | |||||
| printf("%s: ERROR- layout > 32767.\n", fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (have_layout && old_layout == -1 && (layout & 192)) { | |||||
| printf("%s: ERROR- layout %d is inconsistent with old_layout -1.\n", | |||||
| fontfilename,layout); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (have_layout && old_layout == 0 && (layout & 192) != 64 && | |||||
| (layout & 255) != 128) { | |||||
| printf("%s: ERROR- layout %d is inconsistent with old_layout 0.\n", | |||||
| fontfilename,layout); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (have_layout && old_layout > 0 && | |||||
| (!(layout & 128) || old_layout != (layout & 63))) { | |||||
| printf("%s: ERROR- layout %d is inconsistent with old_layout %d.\n", | |||||
| fontfilename,layout,old_layout); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (cmtcount<0) { | |||||
| printf("%s: ERROR- cmt_count is negative.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (ffrighttoleft<0 || ffrighttoleft>1) { | |||||
| printf("%s: ERROR- rtol out of bounds.\n",fontfilename); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| for (i=1;i<=cmtcount;i++) { | |||||
| while(k=getc(fontfile),k!='\n'&&k!=EOF) ; /* Advance to end of line */ | |||||
| } | |||||
| maxlinelength = 0; | |||||
| currline=cmtcount+1; | |||||
| fileline=(char*)my_alloc(sizeof(char)*(maxlen+1001)); | |||||
| for (i=0;i<102;i++) { | |||||
| readchar(); | |||||
| if (gone) return; | |||||
| } | |||||
| oldord=0; | |||||
| while(fgets(fileline,maxlen+1000,fontfile)!=NULL) { | |||||
| currline++; | |||||
| len=strlen(fileline)-1; | |||||
| if (len-100>maxlinelength) { | |||||
| maxlinelength=len-100; | |||||
| } | |||||
| if (len>maxlen+100) { | |||||
| printf("%s: ERROR- Code tag line way too long in line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| tmpcnt=sscanf(fileline,"%li",&theord); | |||||
| if (tmpcnt<1) { | |||||
| printf("%s: Warning- Extra chars after font in line %d.\n", | |||||
| fontfilename,currline); | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| break; | |||||
| } | |||||
| codetagcnt++; | |||||
| if (theord>65535 && !bigcodetagwarn) { | |||||
| printf("%s: Warning- Code tag > 65535 in line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning will only be printed once.)\n", | |||||
| fontfilename); | |||||
| bigcodetagwarn = 1; | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (theord==-1) { | |||||
| printf("%s: ERROR- Code tag -1 (unusable) in line %d.\n", | |||||
| fontfilename,currline); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| break; | |||||
| } | |||||
| if (theord>=-255 && theord<=-249 &&!deutschcodetagwarn) { | |||||
| printf("%s: Warning- Code tag in old Deutsch area in line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning will only be printed once.)\n", | |||||
| fontfilename); | |||||
| deutschcodetagwarn = 1; | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (theord<127 && theord>31 && !asciicodetagwarn) { | |||||
| printf("%s: Warning- Code tag in ASCII range in line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning will only be printed once.)\n", | |||||
| fontfilename); | |||||
| asciicodetagwarn = 1; | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| else if (theord<=oldord && theord>=0 && oldord>=0 && !nonincrwarn) { | |||||
| printf("%s: Warning- Non-increasing code tag in line %d.\n", | |||||
| fontfilename,currline); | |||||
| printf("%s: (Above warning will only be printed once.)\n", | |||||
| fontfilename); | |||||
| nonincrwarn = 1; | |||||
| wc++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| oldord=theord; | |||||
| readchar(); | |||||
| if (gone) return; | |||||
| } | |||||
| if (spectagcnt!=-1 && spectagcnt!=codetagcnt) { | |||||
| printf("%s: ERROR- Inconsistent Codetag_Cnt value %d\n", | |||||
| fontfilename, spectagcnt); | |||||
| ec++; | |||||
| weregone(0); if (gone) return; | |||||
| } | |||||
| if (fontfile!=stdin) fclose(fontfile); | |||||
| weregone(1); if (gone) return; | |||||
| } | |||||
| int main(argc,argv) | |||||
| int argc; | |||||
| char *argv[]; | |||||
| { | |||||
| int arg; | |||||
| if ((myname=strrchr(argv[0],'/'))!=NULL) { | |||||
| myname++; | |||||
| } | |||||
| else { | |||||
| myname = argv[0]; | |||||
| } | |||||
| if (argc<2) { | |||||
| usageerr(); | |||||
| } | |||||
| for (arg=1;arg<argc;arg++) { | |||||
| fontfilename=argv[arg]; | |||||
| fileline=NULL; | |||||
| checkit(); | |||||
| if (fileline!=NULL) free(fileline); | |||||
| } | |||||
| return 0; | |||||
| } | |||||