mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
935ced1edd
Summary: Ref T7785. This prepares for (but does not yet use) a pure PHP implementation of Figlet parsing and rendering. Figlet is somewhat complex, but a parser already exists in PEAR. I'll make sure it's suitable and hook it up in the next diff. Test Plan: N/A, code not reachable Reviewers: chad Reviewed By: chad Maniphest Tasks: T9408, T7785 Differential Revision: https://secure.phabricator.com/D14101
476 lines
12 KiB
C
476 lines
12 KiB
C
#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;
|
|
}
|