GNU Unifont 17.0.05 Pan-Unicode font with complete Unicode Plane 0 coverage and partial coverage of higher planes

unicoverage.c
Go to the documentation of this file.
1/**
2 @file unicoverage.c
3
4 @brief unicoverage - Show the coverage of Unicode plane scripts
5 for a GNU Unifont hex glyph file
6
7 @author Paul Hardy, unifoundry <at> unifoundry.com, 6 January 2008
8
9 @copyright Copyright (C) 2008, 2013 Paul Hardy
10
11 Synopsis: unicoverage [-ifont_file.hex] [-ocoverage_file.txt]
12
13 This program requires the file "coverage.dat" to be present
14 in the directory from which it is run.
15*/
16/*
17 LICENSE:
18
19 This program is free software: you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation, either version 2 of the License, or
22 (at your option) any later version.
23
24 This program is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
28
29 You should have received a copy of the GNU General Public License
30 along with this program. If not, see <http://www.gnu.org/licenses/>.
31*/
32
33/*
34 2016 (Paul Hardy): Modified in Unifont 9.0.01 release to remove non-existent
35 "-p" option and empty example from help printout.
36
37 2018 (Paul Hardy): Modified to cover entire Unicode range, not just Plane 0.
38
39 11 May 2019: [Paul Hardy] changed strcpy function call to strlcpy
40 for better error handling.
41
42 31 May 2019: [Paul Hardy] replaced strlcpy call with strncpy
43 for compilation on more systems.
44
45 4 June 2022: [Paul Hardy] Adjusted column spacing for better alignment
46 of Unicode Plane 1-15 scripts. Added "-n" option to print number of
47 glyphs in each range instead of percent coverage.
48
49 18 September 2022: [Paul Hardy] in nextrange function, initialize retval.
50
51 21 October 2023: [Paul Hardy]
52 Added full function prototype for nextrange function in main function.
53
54 6 September 2025: [Paul Hardy] changed cstart and cend from int to
55 unsigned int to match sscanf parameter declarations.
56*/
57
58#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
61
62
63#define MAXBUF 256 ///< Maximum input line length - 1
64
65
66/**
67 @brief The main function.
68
69 @param[in] argc The count of command line arguments.
70 @param[in] argv Pointer to array of command line arguments.
71 @return This program exits with status 0.
72*/
73 int
74 main (int argc, char *argv[])
75{
76
77 int print_n=0; /* print # of glyphs, not percentage */
78 unsigned i; /* loop variable */
79 unsigned slen; /* string length of coverage file line */
80 char inbuf[256]; /* input buffer */
81 unsigned thischar; /* the current character */
82
83 char *infile="", *outfile=""; /* names of input and output files */
84 FILE *infp, *outfp; /* file pointers of input and output files */
85 FILE *coveragefp; /* file pointer to coverage.dat file */
86 unsigned cstart, cend; /* current coverage start and end code points */
87 char coverstring[MAXBUF]; /* description of current coverage range */
88 int nglyphs; /* number of glyphs in this section */
89
90 /* to get next range & name of Unicode glyphs */
91 int nextrange (FILE *coveragefp, unsigned *cstart, unsigned *cend,
92 char *coverstring);
93
94 void print_subtotal (FILE *outfp, int print_n, int nglyphs,
95 unsigned cstart, unsigned cend, char *coverstring);
96
97 if ((coveragefp = fopen ("coverage.dat", "r")) == NULL) {
98 fprintf (stderr, "\nError: data file \"coverage.dat\" not found.\n\n");
99 exit (0);
100 }
101
102 if (argc > 1) {
103 for (i = 1; i < argc; i++) {
104 if (argv[i][0] == '-') { /* this is an option argument */
105 switch (argv[i][1]) {
106 case 'i': /* name of input file */
107 infile = &argv[i][2];
108 break;
109 case 'n': /* print number of glyphs instead of percentage */
110 print_n = 1;
111 case 'o': /* name of output file */
112 outfile = &argv[i][2];
113 break;
114 default: /* if unrecognized option, print list and exit */
115 fprintf (stderr, "\nSyntax:\n\n");
116 fprintf (stderr, " %s -p<Unicode_Page> ", argv[0]);
117 fprintf (stderr, "-i<Input_File> -o<Output_File> -w\n\n");
118 exit (1);
119 }
120 }
121 }
122 }
123 /*
124 Make sure we can open any I/O files that were specified before
125 doing anything else.
126 */
127 if (strlen (infile) > 0) {
128 if ((infp = fopen (infile, "r")) == NULL) {
129 fprintf (stderr, "Error: can't open %s for input.\n", infile);
130 exit (1);
131 }
132 }
133 else {
134 infp = stdin;
135 }
136 if (strlen (outfile) > 0) {
137 if ((outfp = fopen (outfile, "w")) == NULL) {
138 fprintf (stderr, "Error: can't open %s for output.\n", outfile);
139 exit (1);
140 }
141 }
142 else {
143 outfp = stdout;
144 }
145
146 /*
147 Print header row.
148 */
149 if (print_n) {
150 fprintf (outfp, "# Glyphs Range Script\n");
151 fprintf (outfp, "-------- ----- ------\n");
152 }
153 else {
154 fprintf (outfp, "Covered Range Script\n");
155 fprintf (outfp, "------- ----- ------\n\n");
156 }
157
158 slen = nextrange (coveragefp, &cstart, &cend, coverstring);
159 nglyphs = 0;
160
161 /*
162 Read in the glyphs in the file
163 */
164 while (slen != 0 && fgets (inbuf, MAXBUF-1, infp) != NULL) {
165 sscanf (inbuf, "%x", &thischar);
166
167 /* Read a character beyond end of current script. */
168 while (cend < thischar && slen != 0) {
169 print_subtotal (outfp, print_n, nglyphs, cstart, cend, coverstring);
170
171 /* start new range total */
172 slen = nextrange (coveragefp, &cstart, &cend, coverstring);
173 nglyphs = 0;
174 }
175 nglyphs++;
176 }
177
178 print_subtotal (outfp, print_n, nglyphs, cstart, cend, coverstring);
179
180 exit (0);
181}
182
183/**
184 @brief Get next Unicode range.
185
186 This function reads the next Unicode script range to count its
187 glyph coverage.
188
189 @param[in] coveragefp File pointer to Unicode script range data file.
190 @param[in] cstart Starting code point in current Unicode script range.
191 @param[in] cend Ending code point in current Unicode script range.
192 @param[out] coverstring String containing <cstart>-<cend> substring.
193 @return Length of the last string read, or 0 for end of file.
194*/
195 int
196 nextrange (FILE *coveragefp,
197 unsigned *cstart, unsigned *cend,
198 char *coverstring)
199{
200 int i;
201 static char inbuf[MAXBUF];
202 int retval; /* the return value */
203
204 retval = 0;
205
206 do {
207 if (fgets (inbuf, MAXBUF-1, coveragefp) != NULL) {
208 retval = strlen (inbuf);
209 if ((inbuf[0] >= '0' && inbuf[0] <= '9') ||
210 (inbuf[0] >= 'A' && inbuf[0] <= 'F') ||
211 (inbuf[0] >= 'a' && inbuf[0] <= 'f')) {
212 sscanf (inbuf, "%x-%x", cstart, cend);
213 i = 0;
214 while (inbuf[i] != ' ') i++; /* find first blank */
215 while (inbuf[i] == ' ') i++; /* find next non-blank */
216 strncpy (coverstring, &inbuf[i], MAXBUF);
217 }
218 else retval = 0;
219 }
220 else retval = 0;
221 } while (retval == 0 && !feof (coveragefp));
222
223 return (retval);
224}
225
226
227/**
228 @brief Print the subtotal for one Unicode script range.
229
230 @param[in] outfp Pointer to output file.
231 @param[in] print_n 1 = print number of glyphs, 0 = print percentage.
232 @param[in] nglyphs Number of glyphs in current range.
233 @param[in] cstart Starting code point for current range.
234 @param[in] cend Ending code point for current range.
235 @param[in] coverstring Character string of "<cstart>-<cend>".
236*/
237 void print_subtotal (FILE *outfp, int print_n, int nglyphs,
238 unsigned cstart, unsigned cend, char *coverstring) {
239
240 /* print old range total */
241 if (print_n) { /* Print number of glyphs, not percentage */
242 fprintf (outfp, " %6d ", nglyphs);
243 }
244 else {
245 fprintf (outfp, " %5.1f%%", 100.0*nglyphs/(1+cend-cstart));
246 }
247
248 if (cend < 0x10000)
249 fprintf (outfp, " U+%04X..U+%04X %s",
250 cstart, cend, coverstring);
251 else
252 fprintf (outfp, " U+%05X..U+%05X %s",
253 cstart, cend, coverstring);
254
255 return;
256}
main
int main(int argc, char *argv[])
The main function.
Definition: unicoverage.c:74
print_subtotal
void print_subtotal(FILE *outfp, int print_n, int nglyphs, unsigned cstart, unsigned cend, char *coverstring)
Print the subtotal for one Unicode script range.
Definition: unicoverage.c:237
MAXBUF
#define MAXBUF
Maximum input line length - 1.
Definition: unicoverage.c:63
nextrange
int nextrange(FILE *coveragefp, unsigned *cstart, unsigned *cend, char *coverstring)
Get next Unicode range.
Definition: unicoverage.c:196