This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Refactor generate_uudmap.c to use a helper function to output init blocks.
[perl5.git] / generate_uudmap.c
1 /* Originally this program just generated uudmap.h
2    However, when we later wanted to generate bitcount.h, it was easier to
3    refactor it and keep the same name, than either alternative - rename it,
4    or duplicate all of the Makefile logic for a second program.  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 /* If it turns out that we need to make this conditional on config.sh derived
9    values, it might be easier just to rip out the use of strerrer().  */
10 #include <string.h>
11 /* If a platform doesn't support errno.h, it's probably so strange that
12    "hello world" won't port easily to it.  */
13 #include <errno.h>
14
15 static void
16 format_char_block(FILE *out, const void *thing, size_t count) {
17   const char *block = (const char *)thing;
18
19   fputs("    ", out);
20   while (count--) {
21     fprintf(out, "%d", *block);
22     block++;
23     if (count) {
24       fputs(", ", out);
25       if (!(count & 15)) {
26         fputs("\n    ", out);
27       }
28     }
29   }
30   fputc('\n', out);
31 }
32
33 static void
34 output_to_file(const char *progname, const char *filename,
35                void (format_function)(FILE *out, const void *thing, size_t count),
36                const void *thing, size_t count) {
37   FILE *const out = fopen(filename, "w");
38
39   if (!out) {
40     fprintf(stderr, "%s: Could not open '%s': %s\n", progname, filename,
41             strerror(errno));
42     exit(1);
43   }
44
45   fputs("{\n", out);
46   format_function(out, thing, count);
47   fputs("}\n", out);
48
49   if (fclose(out)) {
50     fprintf(stderr, "%s: Could not close '%s': %s\n", progname, filename,
51             strerror(errno));
52     exit(1);
53   }
54 }
55
56
57 static const char PL_uuemap[]
58 = "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
59
60 typedef unsigned char U8;
61
62 /* This will ensure it is all zeros.  */
63 static char PL_uudmap[256];
64 static char PL_bitcount[256];
65
66 int main(int argc, char **argv) {
67   size_t i;
68   int bits;
69
70   if (argc < 3 || argv[1][0] == '\0' || argv[2][0] == '\0') {
71     fprintf(stderr, "Usage: %s uudemap.h bitcount.h\n", argv[0]);
72     return 1;
73   }
74
75   for (i = 0; i < sizeof(PL_uuemap) - 1; ++i)
76     PL_uudmap[(U8)PL_uuemap[i]] = (char)i;
77   /*
78    * Because ' ' and '`' map to the same value,
79    * we need to decode them both the same.
80    */
81   PL_uudmap[(U8)' '] = 0;
82
83   output_to_file(argv[0], argv[1], &format_char_block,
84                  (const void *)PL_uudmap, sizeof(PL_uudmap));
85
86   for (bits = 1; bits < 256; bits++) {
87     if (bits & 1)       PL_bitcount[bits]++;
88     if (bits & 2)       PL_bitcount[bits]++;
89     if (bits & 4)       PL_bitcount[bits]++;
90     if (bits & 8)       PL_bitcount[bits]++;
91     if (bits & 16)      PL_bitcount[bits]++;
92     if (bits & 32)      PL_bitcount[bits]++;
93     if (bits & 64)      PL_bitcount[bits]++;
94     if (bits & 128)     PL_bitcount[bits]++;
95   }
96
97   output_to_file(argv[0], argv[2], &format_char_block,
98                  (const void *)PL_bitcount, sizeof(PL_bitcount));
99
100   return 0;
101 }