unifont-6.3.20131020.tar.gz
[unifont.git] / src / unicoverage.c
1 /*
2    unicoverage - Show the coverage of Unicode Basic Multilingual
3                  Plane scripts for a GNU Unifont hex glyph file
4
5    Synopsis: unicoverage [-ifont_file.hex] [-ocoverage_file.txt]
6
7    This program requires the file "coverage.dat" to be present
8    in the directory from which it is run.
9
10    Author: Paul Hardy, unifoundry <at> unifoundry.com, 6 January 2008
11    
12    Copyright (C) 2008, 2013 Paul Hardy
13
14    LICENSE:
15
16       This program is free software: you can redistribute it and/or modify
17       it under the terms of the GNU General Public License as published by
18       the Free Software Foundation, either version 2 of the License, or
19       (at your option) any later version.
20
21       This program is distributed in the hope that it will be useful,
22       but WITHOUT ANY WARRANTY; without even the implied warranty of
23       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24       GNU General Public License for more details.
25
26       You should have received a copy of the GNU General Public License
27       along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #define MAXBUF 256
35
36
37 int main(int argc, char *argv[]) {
38
39    unsigned i;                /* loop variable                     */
40    unsigned slen;             /* string length of coverage file line */
41    char inbuf[256];           /* input buffer                      */
42    unsigned thischar;         /* the current character             */
43 // unsigned char thischarbyte; /* unsigned char lowest byte of Unicode char */
44
45    char *infile="", *outfile="";  /* names of input and output files   */
46    FILE *infp, *outfp;        /* file pointers of input and output files */
47    FILE *coveragefp;          /* file pointer to coverage.dat file */
48    int cstart, cend;          /* current coverage start and end code points */
49    char coverstring[MAXBUF];  /* description of current coverage range      */
50    int nglyphs;               /* number of glyphs in this section */
51    int nextrange();           /* to get next range & name of Unicode glyphs */
52
53    if ((coveragefp = fopen("coverage.dat", "r")) == NULL) {
54       fprintf(stderr, "\nError: data file \"coverage.dat\" not found.\n\n");
55       exit(0);
56    }
57
58    if (argc > 1) {
59       for (i = 1; i < argc; i++) {
60          if (argv[i][0] == '-') {  /* this is an option argument */
61             switch (argv[i][1]) {
62                case 'i':  /* name of input file */
63                   infile = &argv[i][2];
64                   break;
65                case 'o':  /* name of output file */
66                   outfile = &argv[i][2];
67                   break;
68                default:   /* if unrecognized option, print list and exit */
69                   fprintf(stderr, "\nSyntax:\n\n");
70                   fprintf(stderr, "   %s -p<Unicode_Page> ", argv[0]);
71                   fprintf(stderr, "-i<Input_File> -o<Output_File> -w\n\n");
72                   fprintf(stderr, "\nExample:\n\n");
73                   exit(1);
74             }
75          }
76       }
77    }
78    /*
79       Make sure we can open any I/O files that were specified before
80       doing anything else.
81    */
82    if (strlen(infile) > 0) {
83       if ((infp = fopen(infile, "r")) == NULL) {
84          fprintf(stderr, "Error: can't open %s for input.\n", infile);
85          exit(1);
86       }
87    }
88    else {
89       infp = stdin;
90    }
91    if (strlen(outfile) > 0) {
92       if ((outfp = fopen(outfile, "w")) == NULL) {
93          fprintf(stderr, "Error: can't open %s for output.\n", outfile);
94          exit(1);
95       }
96    }
97    else {
98       outfp = stdout;
99    }
100    slen = nextrange(coveragefp, &cstart, &cend, coverstring);
101    nglyphs = 0;
102    /*
103       Print header row.
104    */
105    fprintf(outfp, "Covered      Range       Script\n");
106    fprintf(outfp, "-------      -----       ------\n\n");
107    /*
108       Read in the glyphs in the file
109    */
110    while (slen != 0 && fgets(inbuf, MAXBUF-1, infp) != NULL) {
111       sscanf(inbuf, "%x", &thischar);
112       while (cend < thischar && slen != 0) {
113          /* print old range total */
114          fprintf(outfp, " %5.1f%%  U+%04X..U+%04X  %s\n",
115                  100.0*nglyphs/(1+cend-cstart), cstart, cend, coverstring);
116          /* start new range total */
117          slen = nextrange(coveragefp, &cstart, &cend, coverstring);
118          /*
119             Count Non-characters as existing for totals counts
120          */
121          nglyphs = 0;
122          if (cstart <= 0xFDD0 && cend >= 0xFDEF && nglyphs == 0)
123             nglyphs += 32;
124          else if (cstart <= 0xFFFE && cend >= 0xFFFF && nglyphs == 0)
125             nglyphs += 2;
126       }
127       /*
128          If we read in a noncharacter, don't count it -- we already
129          counted it once above.
130       */
131       if (thischar < 0xFDD0 || (thischar > 0xFDEF && thischar < 0xFFFE))
132          nglyphs++;
133 //    thischarbyte = (unsigned char)(thischar & 0xff);
134    }
135    /* print last range total */
136    fprintf(outfp, " %5.1f%%  U+%04X..U+%04X  %s\n",
137            100.0*nglyphs/(1+cend-cstart), cstart, cend, coverstring);
138    exit(0);
139 }
140
141 /*
142    nextrange() - get next Unicode range
143 */
144 int nextrange(FILE *coveragefp,
145               int *cstart, int *cend,
146               char *coverstring) {
147
148    int i;
149    static char inbuf[MAXBUF];
150    int retval;         /* the return value */
151
152    if (fgets(inbuf, MAXBUF-1, coveragefp) != NULL) {
153       retval = strlen(inbuf);
154       if ((inbuf[0] >= '0' && inbuf[0] <= '9') ||
155           (inbuf[0] >= 'A' && inbuf[0] <= 'F') ||
156           (inbuf[0] >= 'a' && inbuf[0] <= 'f')) {
157          sscanf(inbuf, "%x-%x", cstart, cend);
158          i = 0;
159          while (inbuf[i] != ' ') i++;  /* find first blank */
160          while (inbuf[i] == ' ') i++;  /* find next non-blank */
161          strcpy(coverstring, &inbuf[i]);
162       }
163    }
164    else {
165       retval = 0;
166    }
167
168    return(retval);
169 }