unifont-6.3.20131215.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
38 main (int argc, char *argv[])
39 {
40
41    unsigned i;                /* loop variable                       */
42    unsigned slen;             /* string length of coverage file line */
43    char inbuf[256];           /* input buffer                        */
44    unsigned thischar;         /* the current character               */
45
46    char *infile="", *outfile="";  /* names of input and output files        */
47    FILE *infp, *outfp;        /* file pointers of input and output files    */
48    FILE *coveragefp;          /* file pointer to coverage.dat file          */
49    int cstart, cend;          /* current coverage start and end code points */
50    char coverstring[MAXBUF];  /* description of current coverage range      */
51    int nglyphs;               /* number of glyphs in this section           */
52    int nextrange();           /* to get next range & name of Unicode glyphs */
53
54    if ((coveragefp = fopen ("coverage.dat", "r")) == NULL) {
55       fprintf (stderr, "\nError: data file \"coverage.dat\" not found.\n\n");
56       exit (0);
57    }
58
59    if (argc > 1) {
60       for (i = 1; i < argc; i++) {
61          if (argv[i][0] == '-') {  /* this is an option argument */
62             switch (argv[i][1]) {
63                case 'i':  /* name of input file */
64                   infile = &argv[i][2];
65                   break;
66                case 'o':  /* name of output file */
67                   outfile = &argv[i][2];
68                   break;
69                default:   /* if unrecognized option, print list and exit */
70                   fprintf (stderr, "\nSyntax:\n\n");
71                   fprintf (stderr, "   %s -p<Unicode_Page> ", argv[0]);
72                   fprintf (stderr, "-i<Input_File> -o<Output_File> -w\n\n");
73                   fprintf (stderr, "\nExample:\n\n");
74                   exit (1);
75             }
76          }
77       }
78    }
79    /*
80       Make sure we can open any I/O files that were specified before
81       doing anything else.
82    */
83    if (strlen (infile) > 0) {
84       if ((infp = fopen (infile, "r")) == NULL) {
85          fprintf (stderr, "Error: can't open %s for input.\n", infile);
86          exit (1);
87       }
88    }
89    else {
90       infp = stdin;
91    }
92    if (strlen (outfile) > 0) {
93       if ((outfp = fopen (outfile, "w")) == NULL) {
94          fprintf (stderr, "Error: can't open %s for output.\n", outfile);
95          exit (1);
96       }
97    }
98    else {
99       outfp = stdout;
100    }
101    slen = nextrange (coveragefp, &cstart, &cend, coverstring);
102    nglyphs = 0;
103    /*
104       Print header row.
105    */
106    fprintf (outfp, "Covered      Range       Script\n");
107    fprintf (outfp, "-------      -----       ------\n\n");
108    /*
109       Read in the glyphs in the file
110    */
111    while (slen != 0 && fgets (inbuf, MAXBUF-1, infp) != NULL) {
112       sscanf (inbuf, "%x", &thischar);
113       while (cend < thischar && slen != 0) {
114          /* print old range total */
115          fprintf (outfp, " %5.1f%%  U+%04X..U+%04X  %s\n",
116                  100.0*nglyphs/(1+cend-cstart), cstart, cend, coverstring);
117          /* start new range total */
118          slen = nextrange (coveragefp, &cstart, &cend, coverstring);
119          /*
120             Count Non-characters as existing for totals counts
121          */
122          nglyphs = 0;
123          if (cstart <= 0xFDD0 && cend >= 0xFDEF && nglyphs == 0)
124             nglyphs += 32;
125          else if (cstart <= 0xFFFE && cend >= 0xFFFF && nglyphs == 0)
126             nglyphs += 2;
127       }
128       /*
129          If we read in a noncharacter, don't count it -- we already
130          counted it once above.
131       */
132       if (thischar < 0xFDD0 || (thischar > 0xFDEF && thischar < 0xFFFE))
133          nglyphs++;
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
145 nextrange (FILE *coveragefp,
146               int *cstart, int *cend,
147               char *coverstring)
148 {
149
150    int i;
151    static char inbuf[MAXBUF];
152    int retval;         /* the return value */
153
154    if (fgets (inbuf, MAXBUF-1, coveragefp) != NULL) {
155       retval = strlen (inbuf);
156       if ((inbuf[0] >= '0' && inbuf[0] <= '9') ||
157           (inbuf[0] >= 'A' && inbuf[0] <= 'F') ||
158           (inbuf[0] >= 'a' && inbuf[0] <= 'f')) {
159          sscanf (inbuf, "%x-%x", cstart, cend);
160          i = 0;
161          while (inbuf[i] != ' ') i++;  /* find first blank */
162          while (inbuf[i] == ' ') i++;  /* find next non-blank */
163          strcpy (coverstring, &inbuf[i]);
164       }
165    }
166    else {
167       retval = 0;
168    }
169
170    return (retval);
171 }