1 //
2 // PPD file message catalog program for the CUPS PPD Compiler.
3 //
4 // Copyright © 2020-2024 by OpenPrinting.
5 // Copyright 2007-2015 by Apple Inc.
6 // Copyright 2002-2005 by Easy Software Products.
7 //
8 // Licensed under Apache License v2.0. See the file "LICENSE" for more information.
9 //
10
11 //
12 // Include necessary headers...
13 //
14
15 #include "ppdc-private.h"
16 #include <sys/stat.h>
17 #include <sys/types.h>
18
19
20 //
21 // Local functions...
22 //
23
24 static void add_ui_strings(ppdcDriver *d, ppdcCatalog *catalog);
25 static void usage(void) _CUPS_NORETURN;
26
27
28 //
29 // 'main()' - Main entry for the PPD compiler.
30 //
31
32 int // O - Exit status
main(int argc,char * argv[])33 main(int argc, // I - Number of command-line arguments
34 char *argv[]) // I - Command-line arguments
35 {
36 int i; // Looping var
37 ppdcCatalog *catalog; // Message catalog
38 ppdcSource *src; // PPD source file data
39 ppdcDriver *d; // Current driver
40 char *opt; // Current option
41 int verbose; // Verbosity
42 const char *outfile; // Output file
43 char *value; // Value in option
44
45
46 _cupsSetLocale(argv);
47
48 // Scan the command-line...
49 catalog = new ppdcCatalog("en");
50 src = new ppdcSource();
51 verbose = 0;
52 outfile = 0;
53
54 for (i = 1; i < argc; i ++)
55 if (argv[i][0] == '-')
56 {
57 for (opt = argv[i] + 1; *opt; opt ++)
58 switch (*opt)
59 {
60 case 'D' : // Define variable
61 i ++;
62 if (i >= argc)
63 usage();
64
65 if ((value = strchr(argv[i], '=')) != NULL)
66 {
67 *value++ = '\0';
68
69 src->set_variable(argv[i], value);
70 }
71 else
72 src->set_variable(argv[i], "1");
73 break;
74
75 case 'I' : // Include directory...
76 i ++;
77 if (i >= argc)
78 usage();
79
80 if (verbose > 1)
81 _cupsLangPrintf(stdout,
82 _("ppdc: Adding include directory \"%s\"."),
83 argv[i]);
84
85 ppdcSource::add_include(argv[i]);
86 break;
87
88 case 'o' : // Output file...
89 i ++;
90 if (i >= argc || outfile)
91 usage();
92
93 outfile = argv[i];
94
95 catalog->load_messages(outfile);
96 break;
97
98 case 'v' : // Be verbose...
99 verbose ++;
100 break;
101
102 default : // Unknown
103 usage();
104 }
105 }
106 else
107 {
108 // Open and load the driver info file...
109 if (verbose > 1)
110 _cupsLangPrintf(stdout,
111 _("ppdc: Loading driver information file \"%s\"."),
112 argv[i]);
113
114 src->read_file(argv[i]);
115 }
116
117 // If no drivers have been loaded, display the program usage message.
118 if ((d = (ppdcDriver *)src->drivers->first()) != NULL)
119 {
120 // Add UI strings...
121 while (d != NULL)
122 {
123 if (verbose)
124 _cupsLangPrintf(stderr, _("ppdc: Adding/updating UI text from %s."), argv[i]);
125
126 add_ui_strings(d, catalog);
127
128 d = (ppdcDriver *)src->drivers->next();
129 }
130 }
131 else
132 usage();
133
134 // Delete the printer driver information...
135 src->release();
136
137 // Write the message catalog...
138 if (!outfile)
139 usage();
140 else
141 catalog->save_messages(outfile);
142
143 catalog->release();
144
145 // Return with no errors.
146 return (0);
147 }
148
149
150 //
151 // 'add_ui_strings()' - Add all UI strings from the driver.
152 //
153
154 static void
add_ui_strings(ppdcDriver * d,ppdcCatalog * catalog)155 add_ui_strings(ppdcDriver *d, // I - Driver data
156 ppdcCatalog *catalog) // I - Message catalog
157 {
158 // Add the make/model/language strings...
159 catalog->add_message(d->manufacturer->value);
160 catalog->add_message(d->model_name->value);
161
162 // Add the media size strings...
163 ppdcMediaSize *m; // Current media size
164
165 for (m = (ppdcMediaSize *)d->sizes->first();
166 m;
167 m = (ppdcMediaSize *)d->sizes->next())
168 catalog->add_message(m->text->value);
169
170 // Add the group/option/choice strings...
171 ppdcGroup *g; // Current group
172 ppdcOption *o; // Current option
173 ppdcChoice *c; // Current choice
174
175 for (g = (ppdcGroup *)d->groups->first();
176 g;
177 g = (ppdcGroup *)d->groups->next())
178 {
179 if (!g->options->count)
180 continue;
181
182 if (_cups_strcasecmp(g->name->value, "General"))
183 catalog->add_message(g->text->value);
184
185 for (o = (ppdcOption *)g->options->first();
186 o;
187 o = (ppdcOption *)g->options->next())
188 {
189 if (!o->choices->count)
190 continue;
191
192 if (o->text->value)
193 catalog->add_message(o->text->value);
194 else
195 catalog->add_message(o->name->value);
196
197 for (c = (ppdcChoice *)o->choices->first();
198 c;
199 c = (ppdcChoice *)o->choices->next())
200 if (c->text->value)
201 catalog->add_message(c->text->value);
202 else
203 catalog->add_message(c->name->value);
204 }
205 }
206
207 // Add profile and preset strings...
208 ppdcAttr *a; // Current attribute
209 for (a = (ppdcAttr *)d->attrs->first();
210 a;
211 a = (ppdcAttr *)d->attrs->next())
212 if (a->text->value && a->text->value[0] &&
213 (a->localizable ||
214 !strncmp(a->name->value, "Custom", 6) ||
215 !strncmp(a->name->value, "ParamCustom", 11) ||
216 !strcmp(a->name->value, "APCustomColorMatchingName") ||
217 !strcmp(a->name->value, "APPrinterPreset") ||
218 !strcmp(a->name->value, "cupsICCProfile") ||
219 !strcmp(a->name->value, "cupsIPPReason") ||
220 !strcmp(a->name->value, "cupsMarkerName")))
221 {
222 catalog->add_message(a->text->value);
223
224 if ((a->localizable && a->value->value[0]) ||
225 !strcmp(a->name->value, "cupsIPPReason"))
226 catalog->add_message(a->value->value);
227 }
228 else if (!strncmp(a->name->value, "Custom", 6) ||
229 !strncmp(a->name->value, "ParamCustom", 11))
230 catalog->add_message(a->name->value);
231 }
232
233
234 //
235 // 'usage()' - Show usage and exit.
236 //
237
238 static void
usage(void)239 usage(void)
240 {
241 _cupsLangPuts(stdout, _("Usage: ppdpo [options] -o filename.po filename.drv "
242 "[ ... filenameN.drv ]"));
243 _cupsLangPuts(stdout, _("Options:"));
244 _cupsLangPuts(stdout, _(" -D name=value Set named variable to "
245 "value."));
246 _cupsLangPuts(stdout, _(" -I include-dir Add include directory to "
247 "search path."));
248 _cupsLangPuts(stdout, _(" -v Be verbose."));
249
250 exit(1);
251 }
252