1 //
2 // GNU gettext message generator for the CUPS PPD Compiler.
3 //
4 // This program is used to generate a dummy source file containing all of
5 // the standard media and sample driver strings. The results are picked up
6 // by GNU gettext and placed in the CUPS message catalog.
7 //
8 // Copyright © 2020-2024 by OpenPrinting.
9 // Copyright 2008-2014 by Apple Inc.
10 //
11 // Licensed under Apache License v2.0. See the file "LICENSE" for more information.
12 //
13 // Usage:
14 //
15 // ./genstrings >sample.c
16 //
17
18 //
19 // Include necessary headers...
20 //
21
22 #include "ppdc-private.h"
23 #include <unistd.h>
24
25
26 //
27 // Local functions...
28 //
29
30 static void add_ui_strings(ppdcDriver *d, ppdcCatalog *catalog);
31 static void write_cstring(const char *s);
32
33
34 //
35 // 'main()' - Main entry for the PPD compiler.
36 //
37
38 int // O - Exit status
main(void)39 main(void)
40 {
41 ppdcSource *src; // PPD source file data
42 ppdcCatalog *catalog; // Catalog to hold all of the UI strings
43
44
45 // Make sure we are in the right place...
46 if (access("../data", 0) || access("sample.drv", 0))
47 {
48 puts("You must run genstrings from the ppdc directory.");
49 return (1);
50 }
51
52 // Load the sample drivers...
53 ppdcSource::add_include("../data");
54
55 src = new ppdcSource("sample.drv");
56 catalog = new ppdcCatalog(NULL);
57
58 catalog->add_message("ISOLatin1");
59 catalog->add_message("English");
60
61 // Add the media size strings...
62 ppdcMediaSize *size; // Current media size
63
64 for (size = (ppdcMediaSize *)src->sizes->first();
65 size;
66 size = (ppdcMediaSize *)src->sizes->next())
67 catalog->add_message(size->text->value);
68
69 // Then collect all of the UI strings from the sample drivers...
70 ppdcDriver *d; // Current driver
71
72 for (d = (ppdcDriver *)src->drivers->first();
73 d;
74 d = (ppdcDriver *)src->drivers->next())
75 add_ui_strings(d, catalog);
76
77 // Finally, write all of the strings...
78 ppdcMessage *message;
79
80 for (message = (ppdcMessage *)catalog->messages->first();
81 message;
82 message = (ppdcMessage *)catalog->messages->next())
83 write_cstring(message->id->value);
84
85 src->release();
86 catalog->release();
87
88 // Return with no errors.
89 return (0);
90 }
91
92
93 //
94 // 'add_ui_strings()' - Add all UI strings from the driver.
95 //
96
97 static void
add_ui_strings(ppdcDriver * d,ppdcCatalog * catalog)98 add_ui_strings(ppdcDriver *d, // I - Driver data
99 ppdcCatalog *catalog) // I - Message catalog
100 {
101 // Add the make/model/language strings...
102 catalog->add_message(d->manufacturer->value);
103 catalog->add_message(d->model_name->value);
104
105 // Add the group/option/choice strings...
106 ppdcGroup *g; // Current group
107 ppdcOption *o; // Current option
108 ppdcChoice *c; // Current choice
109
110 for (g = (ppdcGroup *)d->groups->first();
111 g;
112 g = (ppdcGroup *)d->groups->next())
113 {
114 if (!g->options->count)
115 continue;
116
117 if (_cups_strcasecmp(g->name->value, "General"))
118 catalog->add_message(g->text->value);
119
120 for (o = (ppdcOption *)g->options->first();
121 o;
122 o = (ppdcOption *)g->options->next())
123 {
124 if (!o->choices->count)
125 continue;
126
127 if (o->text->value && strcmp(o->name->value, o->text->value))
128 catalog->add_message(o->text->value);
129 else
130 catalog->add_message(o->name->value);
131
132 for (c = (ppdcChoice *)o->choices->first();
133 c;
134 c = (ppdcChoice *)o->choices->next())
135 if (c->text->value && strcmp(c->name->value, c->text->value))
136 catalog->add_message(c->text->value);
137 else
138 catalog->add_message(c->name->value);
139 }
140 }
141
142 // Add profile and preset strings...
143 ppdcAttr *a; // Current attribute
144 for (a = (ppdcAttr *)d->attrs->first();
145 a;
146 a = (ppdcAttr *)d->attrs->next())
147 {
148 if (a->text->value && a->text->value[0] &&
149 (a->localizable ||
150 !strncmp(a->name->value, "Custom", 6) ||
151 !strncmp(a->name->value, "ParamCustom", 11) ||
152 !strcmp(a->name->value, "APCustomColorMatchingName") ||
153 !strcmp(a->name->value, "APPrinterPreset") ||
154 !strcmp(a->name->value, "cupsICCProfile") ||
155 !strcmp(a->name->value, "cupsIPPReason") ||
156 !strcmp(a->name->value, "cupsMarkerName")))
157 {
158 catalog->add_message(a->text->value);
159
160 if ((a->localizable && a->value->value[0]) ||
161 !strcmp(a->name->value, "cupsIPPReason"))
162 catalog->add_message(a->value->value);
163 }
164 else if (!strncmp(a->name->value, "Custom", 6) ||
165 !strncmp(a->name->value, "ParamCustom", 11))
166 catalog->add_message(a->name->value);
167 }
168 }
169
170
171 //
172 // 'write_cstring()' - Write a translation string as a valid C string to stdout.
173 //
174
175 static void
write_cstring(const char * s)176 write_cstring(const char *s) /* I - String to write */
177 {
178 fputs("_(\"", stdout);
179 if (s)
180 {
181 while (*s)
182 {
183 if (*s == '\\')
184 fputs("\\\\", stdout);
185 else if (*s == '\"')
186 fputs("\\\"", stdout);
187 else if (*s == '\t')
188 fputs("\\t", stdout);
189 else if (*s == '\n')
190 fputs("\\n", stdout);
191 else
192 putchar(*s);
193
194 s ++;
195 }
196 }
197 puts("\");");
198 }
199