/src/ghostpdl/pcl/pl/pjparse.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* pjparse.c */ |
18 | | /* PJL parser */ |
19 | | #include "stat_.h" |
20 | | #include "memory_.h" |
21 | | #include "stdio_.h" |
22 | | #include "string_.h" |
23 | | #include "scommon.h" |
24 | | #include "gdebug.h" |
25 | | #include "gp.h" |
26 | | #include "gpmisc.h" |
27 | | #include "gxiodev.h" |
28 | | #include "pjparse.h" |
29 | | #include "plfont.h" |
30 | | #include "plver.h" /* PJL_VOLUME_0 PJL_VOLUME_1 */ |
31 | | #include "plmain.h" |
32 | | #include "ctype_.h" /* for toupper() */ |
33 | | #include <stdlib.h> /* for atoi() */ |
34 | | #include "gserrors.h" |
35 | | |
36 | | /* ------ pjl state definitions ------ */ |
37 | | |
38 | | #define PJL_STRING_LENGTH (256) |
39 | 10.1M | #define PJL_PATH_NAME_LENGTH (256) |
40 | 0 | #define MAXPATHLEN 1024 |
41 | | |
42 | | /* definitions for fontsource and font number table entries */ |
43 | | #define pjl_fontsource_body\ |
44 | | char designator[2]; \ |
45 | | PJCONST char *pathname; \ |
46 | | PJCONST char *fontnumber |
47 | | |
48 | | #define PJCONST |
49 | | typedef struct pjl_fontsource |
50 | | { |
51 | | pjl_fontsource_body; |
52 | | } pjl_fontsource_t; |
53 | | #undef PJCONST |
54 | | |
55 | | #define PJCONST const |
56 | | typedef struct pjl_fontsource_default |
57 | | { |
58 | | pjl_fontsource_body; |
59 | | } pjl_fontsource_default_t; |
60 | | #undef PJCONST |
61 | | |
62 | | /* definitions for variable names and values */ |
63 | | #define pjl_envir_var_body\ |
64 | | PJCONST char *var; \ |
65 | | PJCONST char *value |
66 | | |
67 | | #define PJCONST |
68 | | typedef struct pjl_envir_var_s { |
69 | | pjl_envir_var_body; |
70 | | } pjl_envir_var_t; |
71 | | #undef PJCONST |
72 | | |
73 | | #define PJCONST const |
74 | | typedef struct pjl_envir_var_default_s { |
75 | | pjl_envir_var_body; |
76 | | } pjl_envir_var_default_t; |
77 | | #undef PJCONST |
78 | | |
79 | | /* the pjl current environment and the default user environment. Note |
80 | | the default environment should be stored in NVRAM on embedded print |
81 | | systems. */ |
82 | | typedef struct pjl_parser_state_s |
83 | | { |
84 | | char *line; /* buffered command line */ |
85 | | int line_size; |
86 | | int bytes_to_write; /* data processing by fsdownload */ |
87 | | int bytes_to_read; /* data processed by fsupload */ |
88 | | gp_file *fp; /* fsdownload or fsupload file */ |
89 | | int pos; /* current position in line */ |
90 | | pjl_envir_var_t *defaults; /* the default environment (i.e. set default) */ |
91 | | pjl_envir_var_t *envir; /* the pjl environment */ |
92 | | /* these are seperated out from the default and environmnet for no good reason */ |
93 | | pjl_fontsource_t *font_defaults; |
94 | | pjl_fontsource_t *font_envir; |
95 | | char *environment_font_path; /* if there is an operating sytem env |
96 | | var it is used instead of the |
97 | | default pjl fontsource */ |
98 | | /* permenant soft font slots - bit n is the n'th font number. */ |
99 | 0 | #define MAX_PERMANENT_FONTS 256 /* multiple of 8 */ |
100 | | unsigned char permanent_soft_fonts[MAX_PERMANENT_FONTS / 8]; |
101 | | |
102 | | gs_memory_t *mem; |
103 | | } pjl_parser_state_t; |
104 | | |
105 | | /* provide factory defaults for pjl commands. Note these are not pjl |
106 | | defaults but initial values set in the printer when shipped. In an |
107 | | embedded system these would be defined in ROM */ |
108 | | static pjl_envir_var_default_t pjl_factory_defaults[] = { |
109 | | {"formlines", "60"}, |
110 | | {"formlines_set", "off"}, |
111 | | {"widea4", "no"}, |
112 | | {"edgetoedge", "no"}, |
113 | | {"fontsource", "I"}, |
114 | | {"fontnumber", "0"}, |
115 | | {"pitch", "10.00"}, |
116 | | {"ptsize", "12.00"}, |
117 | | /* NB pc8 is used on 6mp, clj4550, clj4600 |
118 | | roman8 is used on most other HP devices */ |
119 | | {"symset", "pc8"}, |
120 | | {"copies", "1"}, |
121 | | {"paper", "letter"}, |
122 | | {"orientation", "portrait"}, |
123 | | {"duplex", "off"}, |
124 | | {"binding", "longedge"}, |
125 | | {"manualfeed", "off"}, |
126 | | {"fontsource", "I"}, |
127 | | {"fontnumber", "0"}, |
128 | | {"personality", "pcl5c"}, |
129 | | {"language", "auto"}, |
130 | | {"disklock", "off"}, |
131 | | {"plotsizeoverride", "off"}, /* override hpgl/2 PS command args */ |
132 | | {"plotsize1", "0"}, /* 1st arg to PS - plotter units */ |
133 | | {"plotsize2", "0"}, /* 2nd arg to PS - plotter units */ |
134 | | {"paperwidth", ""}, |
135 | | {"paperlength", ""}, |
136 | | {"resolution", "0"}, |
137 | | /* {"personality", "rtl"}, */ |
138 | | {"pdfmark", ""}, |
139 | | {"setdistillerparams", ""}, |
140 | | {"", ""} |
141 | | }; |
142 | | |
143 | | /* NB this must be kept synchronized with the table above and we |
144 | | should probably have index definitions for each variable */ |
145 | 216 | #define FDEF_PAPER_INDX 8 |
146 | | |
147 | | /* FONTS I (Internal Fonts) C, C1, C2 (Cartridge Fonts) S (Permanent |
148 | | Soft Fonts) M1, M2, M3, M4 (fonts stored in one of the printer's |
149 | | ROM SIMM slots). Simulate cartridge, permanent soft fonts, and |
150 | | printer ROM SIMMS with sub directories. See table below. Also |
151 | | resources can be set up as lists of resources which is useful for |
152 | | host based systems. Entries are seperated with a semi-colon. Note |
153 | | there is some unnecessary overlap in the factory default and font |
154 | | source table. */ |
155 | | static pjl_fontsource_default_t pjl_fontsource_table[] = { |
156 | | {"I", |
157 | | "%rom%ttfonts/;urwfonts/;pcl/urwfonts/;ghostpdl/pcl/urwfonts/;/windows/fonts/;", ""}, |
158 | | {"C", "CART0/", ""}, |
159 | | {"C1", "CART1/", ""}, |
160 | | {"C2", "CART2/", ""}, |
161 | | {"S", "MEM0/", ""}, |
162 | | {"M1", "MEM1/", ""}, |
163 | | {"M2", "MEM2/", ""}, |
164 | | {"M3", "MEM3/", ""}, |
165 | | {"M4", "MEM4/", ""}, |
166 | | {"", "", ""} |
167 | | }; |
168 | | |
169 | | /* pjl tokens parsed */ |
170 | | typedef enum |
171 | | { |
172 | | DONE, |
173 | | SET, |
174 | | DEFAULT, |
175 | | EQUAL, |
176 | | VARIABLE, |
177 | | SETTING, |
178 | | UNIDENTIFIED, /* NB not used */ |
179 | | LPARM, /* NB not used */ |
180 | | PREFIX, /* @PJL */ |
181 | | INITIALIZE, |
182 | | RESET, |
183 | | INQUIRE, |
184 | | DINQUIRE, |
185 | | ENTER, |
186 | | LANGUAGE, |
187 | | ENTRY, |
188 | | COUNT, |
189 | | OFFSET, |
190 | | FSDOWNLOAD, |
191 | | FSAPPEND, |
192 | | FSDELETE, |
193 | | FSDIRLIST, |
194 | | FSINIT, |
195 | | FSMKDIR, |
196 | | FSQUERY, |
197 | | FSUPLOAD, |
198 | | FORMATBINARY, /* this nonsense is ignored. |
199 | | all data is treated as binary */ |
200 | | NAME, /* used for pathnames */ |
201 | | SIZE, /* size of data */ |
202 | | VOLUME, /* volume indicator for filesystem initialization */ |
203 | | DISKLOCK, |
204 | | GSSET, |
205 | | GSSETSTRING |
206 | | } pjl_token_type_t; |
207 | | |
208 | | /* lookup table to map strings to pjl tokens */ |
209 | | typedef struct pjl_lookup_table_s |
210 | | { |
211 | | char pjl_string[PJL_STRING_LENGTH + 1]; |
212 | | pjl_token_type_t pjl_token; |
213 | | } pjl_lookup_table_t; |
214 | | |
215 | | static const pjl_lookup_table_t pjl_table[] = { |
216 | | {"@PJL", PREFIX}, |
217 | | {"SET", SET}, |
218 | | {"DEFAULT", DEFAULT}, |
219 | | {"INITIALIZE", INITIALIZE}, |
220 | | {"=", EQUAL}, |
221 | | {"DINQUIRE", DINQUIRE}, |
222 | | {"INQUIRE", INQUIRE}, |
223 | | {"ENTER", ENTER}, |
224 | | /* File system related variables */ |
225 | | {"FSDOWNLOAD", FSDOWNLOAD}, |
226 | | {"FSAPPEND", FSAPPEND}, |
227 | | {"FSDELETE", FSDELETE}, |
228 | | {"FSDIRLIST", FSDIRLIST}, |
229 | | {"FSINIT", FSINIT}, |
230 | | {"FSMKDIR", FSMKDIR}, |
231 | | {"FSQUERY", FSQUERY}, |
232 | | {"FSUPLOAD", FSUPLOAD}, |
233 | | {"FORMAT:BINARY", FORMATBINARY}, /* this nonsense is ignored. |
234 | | all data is treated as binary */ |
235 | | {"NAME", NAME}, /* used for pathnames */ |
236 | | {"SIZE", SIZE}, /* size of data */ |
237 | | {"VOLUME", VOLUME}, /* used for volume name */ |
238 | | {"ENTRY", ENTRY}, |
239 | | {"COUNT", COUNT}, |
240 | | {"OFFSET", OFFSET}, |
241 | | {"DISKLOCK", DISKLOCK}, |
242 | | {"GSSET", GSSET}, |
243 | | {"GSSETSTRING", GSSETSTRING}, |
244 | | {"", (pjl_token_type_t) 0 /* don't care */ } |
245 | | }; |
246 | | |
247 | | #include "gdevpxen.h" |
248 | | |
249 | | #define PJLMEDIA(ms, mstr, res, w, h) \ |
250 | | { mstr, w, h }, |
251 | | static const struct |
252 | | { |
253 | | const char *media_name; |
254 | | float width, height; |
255 | | } pjl_media[] = { |
256 | | px_enumerate_media(PJLMEDIA) |
257 | | }; |
258 | | |
259 | | /* ----- private functions and definitions ------------ */ |
260 | | |
261 | | /* forward declaration */ |
262 | | static int pjl_set(pjl_parser_state_t * pst, char *variable, char *value, |
263 | | bool defaults); |
264 | | static int set_pjl_defaults_to_factory(gs_memory_t * mem, pjl_envir_var_t **def); |
265 | | static int set_pjl_defaults(gs_memory_t * mem, pjl_envir_var_t **def, pjl_envir_var_t *from); |
266 | | static int set_pjl_environment_to_factory(gs_memory_t * mem, pjl_envir_var_t **env); |
267 | | static int set_pjl_environment(gs_memory_t * mem, pjl_envir_var_t **env, pjl_envir_var_t *from); |
268 | | static int set_pjl_fontsource_to_factory(gs_memory_t * mem, pjl_fontsource_t **fontenv); |
269 | | static int set_pjl_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontenv, pjl_fontsource_t *from); |
270 | | static int set_pjl_default_fontsource_to_factory(gs_memory_t * mem, pjl_fontsource_t **fontdef); |
271 | | static int set_pjl_default_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontdef, pjl_fontsource_t *from); |
272 | | static int free_pjl_defaults(gs_memory_t * mem, pjl_envir_var_t **def); |
273 | | static int free_pjl_environment(gs_memory_t * mem, pjl_envir_var_t **env); |
274 | | static int free_pjl_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontenv); |
275 | | static int free_pjl_default_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontdef); |
276 | | |
277 | | /* lookup a paper size and return the index in the media return letter |
278 | | if no match. */ |
279 | | |
280 | | /* somewhat awkward, */ |
281 | 216 | #define LETTER_PAPER_INDEX 1 |
282 | | |
283 | | static int |
284 | | pjl_get_media_index(const char *paper) |
285 | 216 | { |
286 | 216 | int i; |
287 | | |
288 | 9.50k | for (i = 0; i < countof(pjl_media); i++) |
289 | 9.28k | if (!pjl_compare(paper, pjl_media[i].media_name)) |
290 | 0 | return i; |
291 | 216 | return LETTER_PAPER_INDEX; |
292 | 216 | } |
293 | | |
294 | | /* calculate the number of lines per page as a function of page |
295 | | length */ |
296 | | static int |
297 | | pjl_calc_formlines_new_page_size(int page_length) |
298 | 216 | { |
299 | | |
300 | | /* note the units are 300 dpi units as pcl traditional |
301 | | documentation dictates. This is not properly documented in the |
302 | | technical reference manual but the formula appears to be: |
303 | | formlines = ((page_length - 300 dots) / 50.0 dots) 50.0 dots |
304 | | corresponds with the default pcl 6 lines per inch and 300 with |
305 | | 1 inch of margin - so the empirical results look plausible. |
306 | | */ |
307 | | |
308 | 216 | double formlines = (page_length - 300.0) / 50.0; |
309 | | |
310 | 216 | return (int)(formlines + 0.5); |
311 | 216 | } |
312 | | |
313 | | /* handle pjl variables which affect the state of other variables - we |
314 | | don't handle all of these yet. NB not complete. */ |
315 | | static void |
316 | | pjl_side_effects(pjl_parser_state_t * pst, char *variable, char *value, |
317 | | bool defaults) |
318 | 6.33k | { |
319 | 6.33k | if (!pjl_compare(variable, "PAPER") || |
320 | 6.11k | !pjl_compare(variable, "ORIENTATION")) { |
321 | | |
322 | 216 | pjl_envir_var_t *table = (defaults ? pst->defaults : pst->envir); |
323 | 216 | int indx = pjl_get_media_index(table[FDEF_PAPER_INDX].value); |
324 | 216 | int page_length = (!pjl_compare(variable, "ORIENTATION") && |
325 | 0 | !pjl_compare(value, "LANDSCAPE") ? |
326 | 0 | (int)(pjl_media[indx].width) : |
327 | 216 | (int)(pjl_media[indx].height)); |
328 | 216 | int formlines = pjl_calc_formlines_new_page_size(page_length); |
329 | 216 | char text[32]; |
330 | | |
331 | 216 | gs_snprintf(text, sizeof(text), "%d", formlines); |
332 | 216 | pjl_set(pst, (char *)"FORMLINES", text, defaults); |
333 | 216 | } |
334 | | /* fill in other side effects here */ |
335 | 6.33k | return; |
336 | 6.33k | } |
337 | | |
338 | | /* set a pjl environment or default variable. */ |
339 | | static int |
340 | | pjl_set(pjl_parser_state_t * pst, char *variable, char *value, bool defaults) |
341 | 6.33k | { |
342 | 6.33k | pjl_envir_var_t *table = (defaults ? pst->defaults : pst->envir); |
343 | 6.33k | int i=0; |
344 | | |
345 | 6.33k | if (defaults) /* default also sets current environment. */ |
346 | 0 | pjl_set(pst, variable, value, false); |
347 | | |
348 | 120k | while (table[i].var) { |
349 | 120k | if (!pjl_compare(table[i].var, variable)) { |
350 | | /* set the value */ |
351 | 6.33k | char *newvalue = (char *)gs_alloc_bytes(pst->mem, strlen(value) + 1, "pjl_set, create new value"); |
352 | 6.33k | if (!newvalue) |
353 | 0 | return 0; |
354 | 6.33k | strcpy(newvalue, value); |
355 | 6.33k | gs_free_object(pst->mem, table[i].value, "pjl_set free old value"); |
356 | 6.33k | table[i].value = newvalue; |
357 | | /* set any side effects of setting the value */ |
358 | 6.33k | pjl_side_effects(pst, variable, value, defaults); |
359 | 6.33k | return 1; |
360 | 6.33k | } |
361 | 114k | i++; |
362 | 114k | } |
363 | | /* didn't find variable */ |
364 | 0 | return 0; |
365 | 6.33k | } |
366 | | |
367 | | /* get next token from the command line buffer */ |
368 | | static pjl_token_type_t |
369 | | pjl_get_token(pjl_parser_state_t * pst, char token[]) |
370 | 119k | { |
371 | 119k | int c; |
372 | 119k | int start_pos; |
373 | | /* skip any whitespace if we need to. */ |
374 | 169k | while ((c = pst->line[pst->pos]) == ' ' || c == '\t') |
375 | 50.2k | pst->pos++; |
376 | | |
377 | | /* special case to allow = with no intevervening spaces between |
378 | | lhs and rhs */ |
379 | 119k | if (c == '=') { |
380 | 16.4k | pst->pos++; |
381 | 16.4k | return EQUAL; |
382 | 16.4k | } |
383 | | |
384 | | /* set the starting position */ |
385 | 103k | start_pos = pst->pos; |
386 | | |
387 | | /* end of line reached; null shouldn't happen but we check anyway */ |
388 | 103k | if (c == '\0' || c == '\n') |
389 | 5.53k | return DONE; |
390 | | |
391 | | /* check for a quoted string. It should not span a line */ |
392 | 97.5k | if (c == '"') { |
393 | 2.02k | pst->pos++; |
394 | 40.2k | while ((c = pst->line[pst->pos]) != '"' && c != '\0' && c != '\n') |
395 | 38.2k | pst->pos++; |
396 | | /* this routine doesn't yet support real error handling - here |
397 | | we should check if c == '"' */ |
398 | 2.02k | if (c == '"') |
399 | 1.84k | pst->pos++; |
400 | 188 | else |
401 | 188 | return DONE; |
402 | 95.5k | } else { |
403 | | /* set the ptr to the next delimeter. */ |
404 | 567k | while ((c = pst->line[pst->pos]) != ' ' && |
405 | 509k | c != '\t' && c != '\r' && c != '\n' && c != '=' && c != '\0') |
406 | 472k | pst->pos++; |
407 | 95.5k | } |
408 | | |
409 | | /* build the token */ |
410 | 97.3k | { |
411 | 97.3k | int slength = pst->pos - start_pos; |
412 | 97.3k | int i; |
413 | | |
414 | | /* we allow = to special case for allowing |
415 | | token doesn't fit or is empty */ |
416 | 97.3k | if (slength == 0) |
417 | 5.58k | return DONE; |
418 | | /* now the string can be safely copied */ |
419 | 91.7k | strncpy(token, &pst->line[start_pos], slength); |
420 | 91.7k | token[slength] = '\0'; |
421 | | |
422 | | /* for known tokens */ |
423 | 1.29M | for (i = 0; pjl_table[i].pjl_string[0]; i++) |
424 | 1.25M | if (!pjl_compare(pjl_table[i].pjl_string, token)) |
425 | 46.6k | return pjl_table[i].pjl_token; |
426 | | |
427 | | /* NB add other cases here */ |
428 | | /* check for variables that we support */ |
429 | 45.1k | i = 0; |
430 | 1.25M | while (pst->envir[i].var) { |
431 | 1.21M | if (!pjl_compare(pst->envir[i].var, token)) |
432 | 6.13k | return VARIABLE; |
433 | 1.20M | i++; |
434 | 1.20M | } |
435 | | |
436 | | /* NB assume this is a setting yuck */ |
437 | 39.0k | return SETTING; |
438 | 45.1k | } |
439 | | /* shouldn't happen */ |
440 | 0 | return DONE; |
441 | 45.1k | } |
442 | | |
443 | | /* check if fonts exist in the current font source path */ |
444 | | static char * |
445 | | pjl_check_font_path(char *path_list, gs_memory_t * mem) |
446 | 251k | { |
447 | | /* lookup a font path and check if any files (presumably fonts are |
448 | | present) */ |
449 | 251k | char path[PJL_PATH_NAME_LENGTH + 1]; |
450 | 251k | char *pathp = path, *tplast = NULL; |
451 | 251k | const char pattern[] = "*"; |
452 | 251k | char path_and_pattern[PJL_PATH_NAME_LENGTH + 1 + 1]; /* pattern + null */ |
453 | 251k | char *dirname; |
454 | 251k | char fontfilename[MAXPATHLEN + 1]; |
455 | | |
456 | | /* Ignore error if the path list is too long, a single path may be |
457 | | okay. */ |
458 | 251k | gs_strlcpy(path, path_list, sizeof(path)); |
459 | | /* for each path search for fonts. If we find them return we only |
460 | | check if the directory resource has files without checking if |
461 | | the files are indeed fonts. */ |
462 | 380k | while ((dirname = gs_strtok(pathp, ";", &tplast)) != NULL) { |
463 | 251k | file_enum *fe; |
464 | | |
465 | 251k | if (gs_strlcpy(path_and_pattern, dirname, sizeof(path_and_pattern)) >= sizeof(path_and_pattern)) |
466 | 0 | continue; |
467 | | |
468 | 251k | if (gs_strlcat(path_and_pattern, pattern, sizeof(path_and_pattern)) >= sizeof(path_and_pattern)) |
469 | 0 | continue; |
470 | | |
471 | 251k | fe = gs_enumerate_files_init(mem, path_and_pattern, |
472 | 251k | strlen(path_and_pattern)); |
473 | 251k | if (fe == NULL |
474 | 251k | || |
475 | 251k | (gs_enumerate_files_next(mem, fe, fontfilename, PJL_PATH_NAME_LENGTH)) |
476 | 251k | == -1) { |
477 | 129k | pathp = NULL; |
478 | 129k | } else { |
479 | | /* wind through the rest of the files. This should close |
480 | | things up as well. All we need to do is clean up but |
481 | | gs_enumerate_files_close() does not close the current |
482 | | directory */ |
483 | 9.85M | while (1) { |
484 | 9.85M | int fstatus = |
485 | 9.85M | (int)gs_enumerate_files_next(mem, fe, fontfilename, |
486 | 9.85M | PJL_PATH_NAME_LENGTH); |
487 | | /* we don't care if the file does not fit (return +1) */ |
488 | 9.85M | if (fstatus == -1) |
489 | 121k | break; |
490 | 9.85M | } |
491 | | /* replace : separated path with real path. The path list |
492 | | is of equal or greater length than dirname, so it can't |
493 | | fail, but we check anyway. */ |
494 | 121k | if (strlen(path_list) < strlen(dirname)) |
495 | 0 | return NULL; |
496 | 121k | else { |
497 | 121k | strcpy(path_list, dirname); |
498 | 121k | return path_list; |
499 | 121k | } |
500 | 121k | } |
501 | 251k | } |
502 | 129k | return NULL; |
503 | 251k | } |
504 | | |
505 | | /* initilize both pjl state and default environment to default font |
506 | | number if font resources are present. Note we depend on the PDL |
507 | | (pcl) to provide information about 'S' permanent soft fonts. For |
508 | | all other resources we check for filenames which should correspond |
509 | | to fonts. */ |
510 | | static void |
511 | | pjl_reset_fontsource_fontnumbers(pjl_parser_state_t * pst) |
512 | 8.09k | { |
513 | 8.09k | char default_font_number[] = {0x30, 0x00}; /* default number if resources are present */ |
514 | 8.09k | gs_memory_t *mem = pst->mem; |
515 | 8.09k | int i; |
516 | 8.09k | char *newvalue; |
517 | | |
518 | 80.9k | for (i = 0; pst->font_defaults[i].designator[0]; i++) { |
519 | 72.8k | if (pjl_check_font_path(pst->font_defaults[i].pathname, mem)) { |
520 | 8.09k | newvalue = (char *)gs_alloc_bytes(mem, strlen(default_font_number) + 1, "pjl_reset_fontsource_fontnumbers, create new value"); |
521 | 8.09k | if (newvalue) { |
522 | 8.09k | gs_free_object(mem, pst->font_defaults[i].fontnumber, "pjl_reset_fontsource_fontnumbers"); |
523 | 8.09k | strcpy(newvalue, default_font_number); |
524 | 8.09k | pst->font_defaults[i].fontnumber = newvalue; |
525 | 8.09k | } |
526 | 8.09k | } |
527 | 72.8k | if (pjl_check_font_path(pst->font_envir[i].pathname, mem)) { |
528 | 8.09k | newvalue = (char *)gs_alloc_bytes(mem, strlen(default_font_number) + 1, "pjl_reset_fontsource_fontnumbers, create new value"); |
529 | 8.09k | if (newvalue) { |
530 | 8.09k | gs_free_object(mem, pst->font_envir[i].fontnumber, "pjl_reset_fontsource_fontnumbers"); |
531 | 8.09k | strcpy(newvalue, default_font_number); |
532 | 8.09k | pst->font_envir[i].fontnumber = newvalue; |
533 | 8.09k | } |
534 | 8.09k | } |
535 | 72.8k | } |
536 | 8.09k | } |
537 | | |
538 | | /* Strips off extra quotes '"' |
539 | | * and changes pjl volume from 0: to makefile specifed PJL_VOLUME_0 directory |
540 | | * and translates '\\' to '/' |
541 | | * result in fnamep, |
542 | | * ie: ""0:\\dir\subdir\file"" --> "PJL_VOLUME_0/dir/subdir/file" |
543 | | */ |
544 | | static void |
545 | | pjl_parsed_filename_to_string(char *fnamep, const char *pathname) |
546 | 0 | { |
547 | 0 | size_t i, size, prefix_size; |
548 | 0 | const char *prefix; |
549 | 0 | char name[MAXPATHLEN]; |
550 | 0 | uint rlen; |
551 | |
|
552 | 0 | *fnamep = 0; /* in case of bad input */ |
553 | 0 | if (pathname == 0 || strlen(pathname) < 4 || |
554 | 0 | pathname[0] != '"' || pathname[strlen(pathname)-1] != '"') |
555 | 0 | return; /* bad input pjl file */ |
556 | | |
557 | 0 | if (pathname[1] == '0' && pathname[2] == ':') { |
558 | 0 | prefix = PJL_VOLUME_0; |
559 | 0 | } else if (pathname[1] == '1' && pathname[2] == ':') { |
560 | 0 | prefix = PJL_VOLUME_1; |
561 | 0 | } else |
562 | 0 | return; /* bad input pjl file */ |
563 | | |
564 | | /* the pathname parsed has whatever quoting mechanism was used |
565 | | * remove quotes, use forward slash, copy rest. |
566 | | */ |
567 | 0 | size = strlen(pathname); |
568 | 0 | if (size - 4 > MAXPATHLEN) |
569 | 0 | return; |
570 | 0 | for (i = 3; i < size - 1; i++) |
571 | 0 | name[i - 3] = (pathname[i] == '\\') ? '/' : pathname[i]; |
572 | 0 | size -= 4; |
573 | | |
574 | | /* copy pjl_volume string in. use strlen+1 to ensure that strncpy() |
575 | | appends '\0', to keep coverity quiet. */ |
576 | 0 | prefix_size = strlen(prefix); |
577 | 0 | strncpy(fnamep, prefix, prefix_size + 1); |
578 | |
|
579 | 0 | if (size == 0) |
580 | 0 | return; |
581 | | |
582 | 0 | if (name[0] != '/') |
583 | 0 | fnamep[prefix_size++] = '/'; |
584 | |
|
585 | 0 | rlen = MAXPATHLEN - prefix_size; |
586 | 0 | if (gp_file_name_reduce(name, size, fnamep + prefix_size, &rlen) == gp_combine_success) |
587 | 0 | fnamep[prefix_size + rlen] = 0; |
588 | 0 | else |
589 | 0 | fnamep[0] = 0; |
590 | 0 | } |
591 | | |
592 | | /* Verify a file write operation is ok. The filesystem must be 0: or |
593 | | 1:, no other pjl files can have pending writes, and the pjl |
594 | | disklock state variable must be false */ |
595 | | static int |
596 | | pjl_verify_file_operation(pjl_parser_state_t * pst, char *fname, const char *access) |
597 | 0 | { |
598 | | /* make sure we are playing in the pjl sandbox */ |
599 | 0 | if (0 != strncmp(PJL_VOLUME_0, fname, strlen(PJL_VOLUME_0)) |
600 | 0 | && 0 != strncmp(PJL_VOLUME_1, fname, strlen(PJL_VOLUME_1))) { |
601 | 0 | dmprintf1(pst->mem, "illegal path name %s\n", fname); |
602 | 0 | return -1; |
603 | 0 | } |
604 | | |
605 | 0 | if (access != NULL && gp_validate_path(pst->mem, fname, access) != 0) { |
606 | 0 | dmprintf1(pst->mem, "illegal path name %s\n", fname); |
607 | 0 | return -1; |
608 | 0 | } |
609 | | |
610 | | /* make sure we are not currently writing to a file. |
611 | | Simultaneously file writing is not supported */ |
612 | 0 | if (pst->bytes_to_write || pst->fp) |
613 | 0 | return -1; |
614 | | |
615 | | /* no operation if disklocak is enabled */ |
616 | 0 | if (!pjl_compare(pjl_get_envvar(pst, "disklock"), "on")) |
617 | 0 | return -1; |
618 | | /* ok */ |
619 | 0 | return 0; |
620 | 0 | } |
621 | | |
622 | | /* debugging procedure to warn about writing to an extant file */ |
623 | | static void |
624 | | pjl_warn_exists(const gs_memory_t * mem, char *fname) |
625 | 0 | { |
626 | 0 | gp_file *fpdownload; |
627 | | |
628 | | /* issue a warning if the file exists */ |
629 | 0 | if ((fpdownload = gp_fopen(mem, fname, gp_fmode_rb)) != NULL) { |
630 | 0 | gp_fclose(fpdownload); |
631 | 0 | dmprintf1(mem, "warning file exists overwriting %s\n", fname); |
632 | 0 | } |
633 | 0 | } |
634 | | |
635 | | /* open a file for writing or appending */ |
636 | | static gp_file * |
637 | | pjl_setup_file_for_writing(pjl_parser_state_t * pst, char *pathname, int size, |
638 | | bool append) |
639 | 0 | { |
640 | 0 | gp_file *fp; |
641 | 0 | char fname[MAXPATHLEN]; |
642 | |
|
643 | 0 | pjl_parsed_filename_to_string(fname, pathname); |
644 | 0 | if (pjl_verify_file_operation(pst, fname, NULL) < 0) |
645 | 0 | return NULL; |
646 | 0 | pjl_warn_exists(pst->mem, fname); |
647 | 0 | { |
648 | 0 | char fmode[4]; |
649 | |
|
650 | 0 | strcpy(fmode, gp_fmode_wb); |
651 | 0 | if (append) |
652 | 0 | strcat(fmode, "+"); |
653 | 0 | if ((fp = gp_fopen(pst->mem, fname, gp_fmode_wb)) == NULL) { |
654 | 0 | dmprintf(pst->mem, "warning file open for writing failed\n"); |
655 | 0 | return NULL; |
656 | 0 | } |
657 | 0 | } |
658 | 0 | return fp; |
659 | 0 | } |
660 | | |
661 | | /* set up the state to download date to a pjl file */ |
662 | | static int |
663 | | pjl_set_fs_download_state(pjl_parser_state_t * pst, char *pathname, int size) |
664 | 0 | { |
665 | | /* somethink is wrong if the state indicates we are already writing to a file */ |
666 | 0 | gp_file *fp = |
667 | 0 | pjl_setup_file_for_writing(pst, pathname, size, false /* append */ ); |
668 | 0 | if (fp == NULL) |
669 | 0 | return -1; |
670 | 0 | pst->fp = fp; |
671 | 0 | pst->bytes_to_write = size; |
672 | 0 | return 0; |
673 | 0 | } |
674 | | |
675 | | /* set up the state to append subsequent data from the input stream to |
676 | | a file */ |
677 | | static int |
678 | | pjl_set_append_state(pjl_parser_state_t * pst, char *pathname, int size) |
679 | 0 | { |
680 | 0 | gp_file *fp = |
681 | 0 | pjl_setup_file_for_writing(pst, pathname, size, true /* append */ ); |
682 | 0 | if (fp == NULL) |
683 | 0 | return -1; |
684 | 0 | pst->fp = fp; |
685 | 0 | pst->bytes_to_write = size; |
686 | 0 | return 0; |
687 | 0 | } |
688 | | |
689 | | /* create a pjl volume, this should create the volume 0: or 1: we |
690 | | simply create a directory with the volume name. */ |
691 | | static int |
692 | | pjl_fsinit(pjl_parser_state_t * pst, char *pathname) |
693 | 0 | { |
694 | 0 | char fname[MAXPATHLEN]; |
695 | |
|
696 | 0 | pjl_parsed_filename_to_string(fname, pathname); |
697 | 0 | if (pjl_verify_file_operation(pst, fname, "c") < 0) |
698 | 0 | return -1; |
699 | | #ifdef GS_NO_FILESYSTEM |
700 | | return -1; |
701 | | #else |
702 | | #ifdef __WIN32__ |
703 | | return _mkdir(fname); |
704 | | #else |
705 | 0 | return mkdir(fname, 0777); |
706 | 0 | #endif |
707 | 0 | #endif |
708 | 0 | } |
709 | | |
710 | | /* make a pjl directory */ |
711 | | static int |
712 | | pjl_fsmkdir(pjl_parser_state_t * pst, char *pathname) |
713 | 0 | { |
714 | 0 | char fname[MAXPATHLEN]; |
715 | |
|
716 | 0 | pjl_parsed_filename_to_string(fname, pathname); |
717 | 0 | if (pjl_verify_file_operation(pst, fname, "c") < 0) |
718 | 0 | return -1; |
719 | | #ifdef GS_NO_FILESYSTEM |
720 | | return -1; |
721 | | #else |
722 | | #ifdef __WIN32__ |
723 | | return _mkdir(fname); |
724 | | #else |
725 | 0 | return mkdir(fname, 0777); |
726 | 0 | #endif |
727 | 0 | #endif |
728 | 0 | } |
729 | | |
730 | | /* query a file in the pjl sandbox */ |
731 | | static int |
732 | | pjl_fsquery(pjl_parser_state_t * pst, char *pathname) |
733 | 0 | { |
734 | | /* not implemented */ |
735 | 0 | return -1; |
736 | 0 | } |
737 | | |
738 | | /* Upload a file from the pjl sandbox */ |
739 | | static int |
740 | | pjl_fsupload(pjl_parser_state_t * pst, char *pathname, int offset, int size) |
741 | 0 | { |
742 | | /* not implemented */ |
743 | 0 | return -1; |
744 | 0 | } |
745 | | |
746 | | /* search pathname for filename return a match in result. result |
747 | | should be a 0 length string upon calling this routine. If a match |
748 | | is found result will hold the matching path and filename. Thie |
749 | | procedure recursively searches the directory tree "pathname" for |
750 | | "filename" */ |
751 | | static int |
752 | | pjl_search_for_file(pjl_parser_state_t * pst, char *pathname, char *filename, |
753 | | char *result) |
754 | 0 | { |
755 | 0 | file_enum *fe; |
756 | 0 | char fontfilename[MAXPATHLEN]; |
757 | 0 | struct stat stbuf; |
758 | | |
759 | | /* should check length */ |
760 | 0 | snprintf(fontfilename, sizeof(fontfilename), "%s/*", pathname); |
761 | 0 | fe = gs_enumerate_files_init(pst->mem, fontfilename, strlen(fontfilename)); |
762 | 0 | if (fe) { |
763 | 0 | do { |
764 | 0 | uint fstatus = |
765 | 0 | gs_enumerate_files_next(pst->mem, fe, fontfilename, |
766 | 0 | PJL_PATH_NAME_LENGTH); |
767 | | /* done */ |
768 | 0 | if (fstatus == ~(uint) 0) |
769 | 0 | return 0; |
770 | 0 | fontfilename[fstatus] = '\0'; |
771 | 0 | if (fontfilename[fstatus - 1] != '.') { /* skip over . and .. */ |
772 | | /* a directory */ |
773 | 0 | if ((stat(fontfilename, &stbuf) >= 0) && stat_is_dir(stbuf)) |
774 | 0 | pjl_search_for_file(pst, fontfilename, filename, result); |
775 | 0 | else /* a file */ |
776 | 0 | if (!strcmp(strrchr(fontfilename, '/') + 1, filename)) |
777 | 0 | strcpy(result, fontfilename); |
778 | 0 | } |
779 | |
|
780 | 0 | } while (1); |
781 | 0 | } |
782 | | /* not implemented */ |
783 | 0 | return -1; |
784 | 0 | } |
785 | | |
786 | | static int |
787 | | pjl_fsdirlist(pjl_parser_state_t * pst, char *pathname, int entry, int count) |
788 | 0 | { |
789 | 0 | file_enum *fe; |
790 | 0 | char fontfilename[MAXPATHLEN + 2]; |
791 | |
|
792 | 0 | pjl_parsed_filename_to_string(fontfilename, pathname); |
793 | 0 | if (pjl_verify_file_operation(pst, fontfilename, NULL) < 0) |
794 | 0 | return -1; |
795 | | |
796 | | /* if this is a directory add * for the directory listing NB fix */ |
797 | 0 | strcat(fontfilename, "/*"); |
798 | 0 | fe = gs_enumerate_files_init(pst->mem, fontfilename, strlen(fontfilename)); |
799 | 0 | if (fe) { |
800 | 0 | do { |
801 | 0 | uint fstatus = |
802 | 0 | gs_enumerate_files_next(pst->mem, fe, fontfilename, |
803 | 0 | PJL_PATH_NAME_LENGTH); |
804 | | /* done */ |
805 | 0 | if (fstatus == ~(uint) 0) |
806 | 0 | return 0; |
807 | 0 | fontfilename[fstatus] = '\0'; |
808 | | /* NB - debugging output only */ |
809 | 0 | dmprintf1(pst->mem, "%s\n", fontfilename); |
810 | 0 | } while (1); |
811 | 0 | } |
812 | | /* should not get here */ |
813 | 0 | return -1; |
814 | 0 | } |
815 | | |
816 | | inline static int |
817 | | pjl_write_remaining_data(pjl_parser_state_t * pst, const byte ** pptr, |
818 | | const byte ** pplimit) |
819 | 0 | { |
820 | 0 | const byte *ptr = *pptr; |
821 | 0 | const byte *plimit = *pplimit; |
822 | 0 | uint avail = plimit - ptr; |
823 | 0 | uint bytes_written = min(avail, pst->bytes_to_write); |
824 | |
|
825 | 0 | if (gp_fwrite(ptr, 1, bytes_written, pst->fp) != bytes_written) { |
826 | | /* try to close the file before failing */ |
827 | 0 | gp_fclose(pst->fp); |
828 | 0 | pst->fp = NULL; |
829 | 0 | return -1; |
830 | 0 | } |
831 | 0 | pst->bytes_to_write -= bytes_written; |
832 | 0 | if (pst->bytes_to_write == 0) { /* done */ |
833 | 0 | gp_fclose(pst->fp); |
834 | 0 | pst->fp = NULL; |
835 | 0 | } |
836 | | /* update stream pointer */ |
837 | 0 | *pptr += bytes_written; |
838 | 0 | return 0; |
839 | 0 | } |
840 | | |
841 | | static int |
842 | | pjl_delete_file(pjl_parser_state_t * pst, char *pathname) |
843 | 0 | { |
844 | 0 | char fname[MAXPATHLEN]; |
845 | |
|
846 | 0 | pjl_parsed_filename_to_string(fname, pathname); |
847 | 0 | if (pjl_verify_file_operation(pst, fname, NULL) < 0) |
848 | 0 | return -1; |
849 | 0 | return gp_unlink(pst->mem, fname); |
850 | 0 | } |
851 | | |
852 | | /* handle pattern foo = setting, e.g. volume = "0:", name = 0:]pcl. |
853 | | the setting will be returned in "token" if successful. Return 0 |
854 | | for success and -1 if we fail */ |
855 | | static int |
856 | | pjl_get_setting(pjl_parser_state_t * pst, pjl_token_type_t tok, char *token) |
857 | 0 | { |
858 | 0 | pjl_token_type_t lhs = pjl_get_token(pst, token); |
859 | |
|
860 | 0 | if (lhs != tok) |
861 | 0 | return -1; |
862 | 0 | if ((tok = pjl_get_token(pst, token)) != EQUAL) |
863 | 0 | return -1; |
864 | 0 | if ((tok = pjl_get_token(pst, token)) != SETTING) |
865 | 0 | return -1; |
866 | 0 | return 0; |
867 | 0 | } |
868 | | |
869 | | static int |
870 | | gs_set(pjl_parser_state_t *pst, const char *variable, const char *token, int string) |
871 | 0 | { |
872 | 0 | int code; |
873 | 0 | int len1 = strlen(variable)+1; |
874 | 0 | int len2 = NULL ? 0 : strlen(token)+1; |
875 | 0 | char *buffer = (char *)gs_alloc_bytes(pst->mem, len1+len2, "gs_set buffer"); |
876 | |
|
877 | 0 | if (buffer == NULL) |
878 | 0 | return -1; |
879 | | |
880 | 0 | strcpy(buffer, variable); |
881 | 0 | if (len2) { |
882 | 0 | strcat(buffer, "="); |
883 | 0 | strcat(buffer, token); |
884 | 0 | } |
885 | |
|
886 | 0 | if (string) |
887 | 0 | code = pl_main_set_string_param(pl_main_get_instance(pst->mem), buffer); |
888 | 0 | else |
889 | 0 | code = pl_main_set_param(pl_main_get_instance(pst->mem), buffer); |
890 | 0 | gs_free_object(pst->mem, buffer, "gs_set buffer"); |
891 | |
|
892 | 0 | return code; |
893 | 0 | } |
894 | | |
895 | | |
896 | | /* parse and set up state for one line of pjl commands */ |
897 | | static int |
898 | | pjl_parse_and_process_line(pjl_parser_state_t * pst) |
899 | 28.8k | { |
900 | 28.8k | pjl_token_type_t tok; |
901 | 28.8k | char *token; |
902 | 28.8k | char pathname[MAXPATHLEN]; |
903 | 28.8k | int bufsize = pst->pos + 1, code; |
904 | | |
905 | 28.8k | token = (char *)gs_alloc_bytes(pst->mem, bufsize, "working buffer for PJL parsing"); |
906 | 28.8k | if (token == 0) |
907 | 0 | return -1; |
908 | | |
909 | 28.8k | memset(token, 0x00, bufsize); |
910 | 28.8k | memset(pathname, 0x00, sizeof(pathname)); |
911 | | |
912 | | /* reset the line position to the beginning of the line */ |
913 | 28.8k | pst->pos = 0; |
914 | | /* all pjl commands start with the pjl prefix @PJL */ |
915 | 28.8k | if ((tok = pjl_get_token(pst, token)) != PREFIX) { |
916 | 132 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
917 | 132 | return -1; |
918 | 132 | } |
919 | | /* NB we should check for required and optional used of whitespace |
920 | | but we don't see PJLTRM 2-6 PJL Command Syntax and Format. */ |
921 | 28.7k | while ((tok = pjl_get_token(pst, token)) != DONE) { |
922 | 28.6k | switch (tok) { |
923 | 14.4k | case SET: |
924 | 14.8k | case DEFAULT: |
925 | 14.8k | { |
926 | 14.8k | bool defaults; |
927 | | |
928 | 17.3k | var:defaults = (tok == DEFAULT); |
929 | | /* NB we skip over lparm and search for the variable */ |
930 | 49.6k | while ((tok = pjl_get_token(pst, token)) != DONE) |
931 | 38.4k | if (tok == VARIABLE) { |
932 | 6.12k | char *variable; |
933 | | |
934 | 6.12k | variable = (char *)gs_alloc_bytes(pst->mem, bufsize, "2nd working buffer for PJL parsing"); |
935 | 6.12k | if (variable == 0) { |
936 | 0 | gs_free_object(pst->mem, token, "2nd working buffer for PJL parsing"); |
937 | 0 | return -1; |
938 | 0 | } |
939 | 6.12k | memset(variable, 0x00, bufsize); |
940 | | |
941 | 6.12k | strcpy(variable, token); |
942 | 6.12k | if (((tok = pjl_get_token(pst, token)) == EQUAL) |
943 | 6.12k | && (tok = pjl_get_token(pst, token)) == SETTING) { |
944 | | /* an unfortunate side effect - we have to |
945 | | identify FORMLINES being set here, for |
946 | | the benefit of PCL, see the |
947 | | documentation to the function |
948 | | pcursor.c:pcl_vmi_default() for |
949 | | details. */ |
950 | 6.11k | if (!pjl_compare(variable, "FORMLINES")) |
951 | 0 | pjl_set(pst, (char *)"FORMLINES_SET", |
952 | 0 | (char *)"on", defaults); |
953 | 6.11k | code = pjl_set(pst, variable, token, |
954 | 6.11k | defaults); |
955 | 6.11k | } else |
956 | 11 | code = -1; /* syntax error */ |
957 | 6.12k | gs_free_object(pst->mem, variable, "2nd working buffer for PJL parsing"); |
958 | 6.12k | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
959 | 6.12k | return code; |
960 | 6.12k | } else |
961 | 32.3k | continue; |
962 | | |
963 | 11.2k | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
964 | 11.2k | return 0; |
965 | 17.3k | } |
966 | 0 | case GSSET: |
967 | 0 | case GSSETSTRING: |
968 | 0 | { |
969 | 0 | bool string; |
970 | |
|
971 | 0 | string = (tok == GSSETSTRING); |
972 | 0 | code = 0; |
973 | 0 | while ((tok = pjl_get_token(pst, token)) != DONE) |
974 | 0 | if (tok == VARIABLE || tok == SETTING) { |
975 | 0 | int len1 = strlen(token)+1; |
976 | 0 | char *variable = (char *)gs_alloc_bytes(pst->mem, len1, |
977 | 0 | "2nd working buffer for PJL parsing"); |
978 | 0 | if (variable == NULL) |
979 | 0 | code = -1; |
980 | 0 | else { |
981 | 0 | strcpy(variable, token); |
982 | 0 | if (((tok = pjl_get_token(pst, token)) == EQUAL) && |
983 | 0 | ((tok = pjl_get_token(pst, token)) == SETTING)) |
984 | 0 | code = gs_set(pst, variable, token, string); |
985 | 0 | else |
986 | 0 | code = gs_set(pst, variable, NULL, string); |
987 | 0 | gs_free_object(pst->mem, variable, "2nd working buffer for PJL parsing"); |
988 | 0 | } |
989 | 0 | break; |
990 | 0 | } |
991 | |
|
992 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
993 | 0 | return code; |
994 | 0 | } |
995 | 0 | case INITIALIZE: |
996 | | /* set the user default environment to the factory default environment */ |
997 | 0 | free_pjl_defaults(pst->mem, &pst->defaults); |
998 | 0 | set_pjl_defaults_to_factory(pst->mem, &pst->defaults); |
999 | 0 | free_pjl_default_fontsource(pst->mem, &pst->font_defaults); |
1000 | 0 | set_pjl_default_fontsource_to_factory(pst->mem, &pst->font_defaults); |
1001 | 0 | pjl_reset_fontsource_fontnumbers(pst); |
1002 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1003 | 0 | return 0; |
1004 | | /* set the current environment to the user default environment */ |
1005 | 0 | case RESET: |
1006 | 0 | free_pjl_defaults(pst->mem, &pst->defaults); |
1007 | 0 | set_pjl_environment_to_factory(pst->mem, &pst->defaults); |
1008 | 0 | free_pjl_fontsource(pst->mem, &pst->font_envir); |
1009 | 0 | set_pjl_fontsource_to_factory(pst->mem, &pst->font_envir); |
1010 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1011 | 0 | return 0; |
1012 | 2.47k | case ENTER: |
1013 | | /* there is no setting for the default language */ |
1014 | 2.47k | tok = SET; |
1015 | 2.47k | goto var; |
1016 | 0 | case FSDOWNLOAD:{ |
1017 | | /* consume and ignore FORMAT:BINARY foolishness. if it is |
1018 | | present or search for the name */ |
1019 | 0 | int size; |
1020 | | |
1021 | | /* ignore format binary stuff */ |
1022 | 0 | if ((tok = pjl_get_token(pst, token)) == FORMATBINARY) { |
1023 | 0 | ; |
1024 | 0 | } |
1025 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1026 | 0 | strlen(token) > MAXPATHLEN - 1) |
1027 | 0 | return -1; |
1028 | 0 | strcpy(pathname, token); |
1029 | 0 | if (pjl_get_setting(pst, SIZE, token) < 0) |
1030 | 0 | return -1; |
1031 | 0 | size = pjl_vartoi(token); |
1032 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1033 | 0 | return pjl_set_fs_download_state(pst, pathname, size); |
1034 | 0 | } |
1035 | 0 | case FSAPPEND:{ |
1036 | 0 | int size; |
1037 | |
|
1038 | 0 | if ((tok = pjl_get_token(pst, token)) == FORMATBINARY) { |
1039 | 0 | ; |
1040 | 0 | } |
1041 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1042 | 0 | strlen(token) > MAXPATHLEN - 1) |
1043 | 0 | return -1; |
1044 | 0 | strcpy(pathname, token); |
1045 | 0 | if (pjl_get_setting(pst, SIZE, token) < 0) |
1046 | 0 | return -1; |
1047 | 0 | size = pjl_vartoi(token); |
1048 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1049 | 0 | return pjl_set_append_state(pst, pathname, size); |
1050 | 0 | } |
1051 | 0 | case FSDELETE: |
1052 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1053 | 0 | strlen(token) > MAXPATHLEN - 1) |
1054 | 0 | return -1; |
1055 | 0 | strcpy(pathname, token); |
1056 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1057 | 0 | return pjl_delete_file(pst, pathname); |
1058 | 0 | case FSDIRLIST:{ |
1059 | 0 | int entry; |
1060 | |
|
1061 | 0 | int count; |
1062 | |
|
1063 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1064 | 0 | strlen(token) > MAXPATHLEN - 1) { |
1065 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1066 | 0 | return -1; |
1067 | 0 | } |
1068 | 0 | strcpy(pathname, token); |
1069 | 0 | if (pjl_get_setting(pst, ENTRY, token) < 0) { |
1070 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1071 | 0 | return -1; |
1072 | 0 | } |
1073 | 0 | entry = pjl_vartoi(token); |
1074 | 0 | if (pjl_get_setting(pst, COUNT, token) < 0) { |
1075 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1076 | 0 | return -1; |
1077 | 0 | } |
1078 | 0 | count = pjl_vartoi(token); |
1079 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1080 | 0 | return pjl_fsdirlist(pst, pathname, entry, count); |
1081 | 0 | } |
1082 | 0 | case FSINIT: |
1083 | 0 | if (pjl_get_setting(pst, VOLUME, token) < 0 || |
1084 | 0 | strlen(token) > MAXPATHLEN - 1) { |
1085 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1086 | 0 | return -1; |
1087 | 0 | } |
1088 | 0 | strcpy(pathname, token); |
1089 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1090 | 0 | return pjl_fsinit(pst, pathname); |
1091 | 0 | case FSMKDIR: |
1092 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1093 | 0 | strlen(token) > MAXPATHLEN - 1) { |
1094 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1095 | 0 | return -1; |
1096 | 0 | } |
1097 | 0 | strcpy(pathname, token); |
1098 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1099 | 0 | return pjl_fsmkdir(pst, pathname); |
1100 | 0 | case FSQUERY: |
1101 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1102 | 0 | strlen(token) > MAXPATHLEN - 1) { |
1103 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1104 | 0 | return -1; |
1105 | 0 | } |
1106 | 0 | strcpy(pathname, token); |
1107 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1108 | 0 | return pjl_fsquery(pst, pathname); |
1109 | 0 | case FSUPLOAD:{ |
1110 | 0 | int size; |
1111 | |
|
1112 | 0 | int offset; |
1113 | |
|
1114 | 0 | if ((tok = pjl_get_token(pst, token)) == FORMATBINARY) { |
1115 | 0 | ; |
1116 | 0 | } |
1117 | 0 | if (pjl_get_setting(pst, NAME, token) < 0 || |
1118 | 0 | strlen(token) > MAXPATHLEN - 1) { |
1119 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1120 | 0 | return -1; |
1121 | 0 | } |
1122 | 0 | strcpy(pathname, token); |
1123 | 0 | if (pjl_get_setting(pst, OFFSET, token) < 0) { |
1124 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1125 | 0 | return -1; |
1126 | 0 | } |
1127 | 0 | offset = pjl_vartoi(token); |
1128 | 0 | if (pjl_get_setting(pst, SIZE, token) < 0) { |
1129 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1130 | 0 | return -1; |
1131 | 0 | } |
1132 | 0 | size = pjl_vartoi(token); |
1133 | 0 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1134 | 0 | return pjl_fsupload(pst, pathname, offset, size); |
1135 | 0 | } |
1136 | 11.2k | default: |
1137 | 11.2k | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1138 | 11.2k | return -1; |
1139 | 28.6k | } |
1140 | 28.6k | } |
1141 | 60 | gs_free_object(pst->mem, token, "working buffer for PJL parsing"); |
1142 | 60 | return 0; |
1143 | 28.7k | } |
1144 | | |
1145 | | /* get a file from 0: or 1: volume */ |
1146 | | static gp_file * |
1147 | | get_fp(pjl_parser_state_t * pst, char *name) |
1148 | 0 | { |
1149 | 0 | char result[MAXPATHLEN]; |
1150 | | |
1151 | | /* 0: */ |
1152 | 0 | result[0] = '\0'; |
1153 | 0 | pjl_search_for_file(pst, (char *)PJL_VOLUME_0, name, result); |
1154 | 0 | if (result[0] == '\0') { |
1155 | | /* try 1: */ |
1156 | 0 | pjl_search_for_file(pst, (char *)PJL_VOLUME_1, name, result); |
1157 | 0 | if (result[0] == '\0') |
1158 | 0 | return 0; |
1159 | 0 | } |
1160 | 0 | return gp_fopen(pst->mem, result, gp_fmode_rb); |
1161 | 0 | } |
1162 | | |
1163 | | /* scan for a named resoource in the pcl sandbox 0: or 1: and return |
1164 | | the size of the object. We do not distinguish between empty and |
1165 | | non-existant files */ |
1166 | | long int |
1167 | | pjl_get_named_resource_size(pjl_parser_state_t * pst, char *name) |
1168 | 0 | { |
1169 | 0 | long int size; |
1170 | 0 | gp_file *fp = get_fp(pst, name); |
1171 | |
|
1172 | 0 | if (fp == NULL) |
1173 | 0 | return 0; |
1174 | 0 | size = gp_fseek(fp, 0L, SEEK_END); |
1175 | 0 | if (size >= 0) |
1176 | 0 | size = gp_ftell(fp); |
1177 | 0 | else |
1178 | 0 | size = 0; |
1179 | 0 | gp_fclose(fp); |
1180 | 0 | return size; |
1181 | 0 | } |
1182 | | |
1183 | | /* get the contents of a file on 0: or 1: and return the result in the |
1184 | | client allocated memory */ |
1185 | | int |
1186 | | pjl_get_named_resource(pjl_parser_state * pst, char *name, byte * data, long int datasize) |
1187 | 0 | { |
1188 | 0 | long int size; |
1189 | 0 | int code = 0; |
1190 | 0 | gp_file *fp = get_fp(pst, name); |
1191 | |
|
1192 | 0 | if (fp == NULL) |
1193 | 0 | return 0; |
1194 | 0 | size = gp_fseek(fp, 0L, SEEK_END); |
1195 | 0 | if (size >= 0) |
1196 | 0 | size = gp_ftell(fp); |
1197 | 0 | gp_rewind(fp); |
1198 | 0 | if (size < 0 || size != datasize || (size != gp_fread(data, 1, size, fp))) { |
1199 | 0 | code = -1; |
1200 | 0 | } |
1201 | 0 | gp_fclose(fp); |
1202 | 0 | return code; |
1203 | 0 | } |
1204 | | |
1205 | | /* set the initial environment to the default environment, this should |
1206 | | be done at the beginning of each job */ |
1207 | | int |
1208 | | pjl_set_init_from_defaults(pjl_parser_state_t * pst) |
1209 | 23.7k | { |
1210 | 23.7k | int code = free_pjl_environment(pst->mem, &pst->envir); |
1211 | 23.7k | if (code < 0) |
1212 | 0 | return code; |
1213 | 23.7k | code = set_pjl_environment(pst->mem, &pst->envir, pst->defaults); |
1214 | 23.7k | if (code < 0) |
1215 | 0 | return code; |
1216 | | |
1217 | 23.7k | code = free_pjl_fontsource(pst->mem, &pst->font_envir); |
1218 | 23.7k | if (code < 0) |
1219 | 0 | return code; |
1220 | 23.7k | return set_pjl_fontsource(pst->mem, &pst->font_envir, pst->font_defaults); |
1221 | 23.7k | } |
1222 | | |
1223 | | void |
1224 | | pjl_set_next_fontsource(pjl_parser_state_t * pst) |
1225 | 0 | { |
1226 | 0 | int current_source; |
1227 | 0 | pjl_envvar_t *current_font_source = pjl_get_envvar(pst, "fontsource"); |
1228 | | |
1229 | | /* find the index of the current resource then work backwards |
1230 | | until we find font resources. We assume the internal source |
1231 | | will have fonts */ |
1232 | 0 | for (current_source = 0; pst->font_envir[current_source].designator[0]; |
1233 | 0 | current_source++) |
1234 | 0 | if (!pjl_compare(pst->font_envir[current_source].designator, |
1235 | 0 | current_font_source)) |
1236 | 0 | break; |
1237 | | |
1238 | | /* next resource is not internal 'I' */ |
1239 | 0 | if (current_source != 0) { |
1240 | 0 | while (current_source > 0) { |
1241 | 0 | current_source--; /* go to next fontsource */ |
1242 | | /* check if it contains fonts, i.e. fontnumber != null */ |
1243 | 0 | if (pst->font_envir[current_source].fontnumber[0]) |
1244 | 0 | break; |
1245 | 0 | } |
1246 | 0 | } |
1247 | | /* set both default and environment font source, the spec is not clear |
1248 | | about this */ |
1249 | 0 | pjl_set(pst, (char *)"fontsource", |
1250 | 0 | pst->font_envir[current_source].designator, true); |
1251 | 0 | pjl_set(pst, (char *)"fontsource", |
1252 | 0 | pst->font_defaults[current_source].designator, false); |
1253 | 0 | } |
1254 | | |
1255 | | /* get a pjl environment variable from the current environment - not |
1256 | | the user default environment */ |
1257 | | pjl_envvar_t * |
1258 | | pjl_get_envvar(pjl_parser_state * pst, const char *pjl_var) |
1259 | 1.19M | { |
1260 | 1.19M | int i=0; |
1261 | 1.19M | pjl_envir_var_t *env = pst->envir; |
1262 | | |
1263 | | /* lookup up the value */ |
1264 | 11.7M | while(env[i].var) { |
1265 | 11.7M | if (!pjl_compare(env[i].var, pjl_var)) { |
1266 | 1.19M | return env[i].value; |
1267 | 1.19M | } |
1268 | 10.5M | i++; |
1269 | 10.5M | } |
1270 | 0 | return NULL; |
1271 | 1.19M | } |
1272 | | |
1273 | | /* get a pjl environment variable from the current environment - not |
1274 | | the user default environment */ |
1275 | | pjl_envvar_t * |
1276 | | pjl_set_envvar(pjl_parser_state * pst, const char *pjl_var, const char *data) |
1277 | 0 | { |
1278 | 0 | int i=0; |
1279 | 0 | pjl_envir_var_t *env = pst->envir; |
1280 | 0 | char *newvalue; |
1281 | | |
1282 | | /* Find the current value */ |
1283 | 0 | while(env[i].var) { |
1284 | 0 | if (!pjl_compare(env[i].var, pjl_var)) { |
1285 | 0 | if (env[i].value) |
1286 | 0 | gs_free_object(pst->mem, env[i].value, "pjl_set_envvar value"); |
1287 | 0 | newvalue = (char *)gs_alloc_bytes(pst->mem, strlen(data) + 1, "pjl_set_envvar, value"); |
1288 | 0 | if (newvalue != NULL) { |
1289 | 0 | strcpy(newvalue, data); |
1290 | 0 | env[i].value = newvalue; |
1291 | 0 | } |
1292 | 0 | } |
1293 | 0 | i++; |
1294 | 0 | } |
1295 | 0 | return NULL; |
1296 | 0 | } |
1297 | | |
1298 | | /* get a pjl environment variable from the current environment - not |
1299 | | the user default environment */ |
1300 | | pjl_envvar_t * |
1301 | | pjl_set_defvar(pjl_parser_state * pst, const char *pjl_var, const char *data) |
1302 | 0 | { |
1303 | 0 | int i=0; |
1304 | 0 | pjl_envir_var_t *env = pst->defaults; |
1305 | 0 | char *newvalue; |
1306 | | |
1307 | | /* Find the current value */ |
1308 | 0 | while(env[i].var) { |
1309 | 0 | if (!pjl_compare(env[i].var, pjl_var)) { |
1310 | 0 | if (env[i].value) |
1311 | 0 | gs_free_object(pst->mem, env[i].value, "pjl_set_defvar value"); |
1312 | 0 | newvalue = (char *)gs_alloc_bytes(pst->mem, strlen(data) + 1, "pjl_set_defvar, value"); |
1313 | 0 | if (newvalue != NULL) { |
1314 | 0 | strcpy(newvalue, data); |
1315 | 0 | env[i].value = newvalue; |
1316 | 0 | } |
1317 | 0 | } |
1318 | 0 | i++; |
1319 | 0 | } |
1320 | 0 | return NULL; |
1321 | 0 | } |
1322 | | /* |
1323 | | * Detect illegal characters when preprocessing each line of PJL. |
1324 | | */ |
1325 | | static inline bool |
1326 | | legal_pjl_char(const byte ch) |
1327 | 978k | { |
1328 | 978k | return (ch >= 32 || isspace(ch)); |
1329 | 978k | } |
1330 | | |
1331 | | /* -- public functions - see pjparse.h for interface documentation -- */ |
1332 | | |
1333 | | /* Process a buffer of PJL commands. */ |
1334 | | int |
1335 | | pjl_process(pjl_parser_state * pst, void *pstate, stream_cursor_read * pr) |
1336 | 6.64k | { |
1337 | 6.64k | const byte *p = pr->ptr; |
1338 | 6.64k | const byte *rlimit = pr->limit; |
1339 | 6.64k | int code = 0; |
1340 | | |
1341 | | /* first check if we are writing data to a file as part of the |
1342 | | file system commands */ |
1343 | | |
1344 | 985k | while (p < rlimit) { |
1345 | 985k | if (pst->bytes_to_write != 0) { |
1346 | 0 | p++; |
1347 | 0 | if (pjl_write_remaining_data(pst, &p, &rlimit) == 0) { |
1348 | 0 | p--; |
1349 | 0 | continue; |
1350 | 0 | } else |
1351 | 0 | return -1; |
1352 | 0 | } |
1353 | | |
1354 | 985k | if (pst->pos == 0) { /* Look ahead for the @PJL prefix or a UEL. */ |
1355 | 35.2k | uint avail = rlimit - p; |
1356 | | |
1357 | 35.2k | if (!memcmp(p + 1, "\033%-12345X", min(avail, 9))) { /* Might be a UEL. */ |
1358 | 2.55k | if (avail < 9) { /* Not enough data to know yet. */ |
1359 | 0 | code = gs_error_NeedInput; |
1360 | 0 | break; |
1361 | 0 | } |
1362 | | /* Skip the UEL and continue. */ |
1363 | 2.55k | p += 9; |
1364 | 2.55k | continue; |
1365 | 32.6k | } else { |
1366 | | /* We allow for a single CRLF at the start of a block of PJL. |
1367 | | * This is in violation of the spec, but allows us to accept |
1368 | | * files like bug 693269. This shouldn't adversely affect any |
1369 | | * real world files. */ |
1370 | 32.6k | if (avail > 0 && p[1] == '\r') |
1371 | 4 | p++, avail--; |
1372 | 32.6k | if (avail > 0 && p[1] == '\n') |
1373 | 6 | p++, avail--; |
1374 | 32.6k | if (!memcmp(p + 1, "@PJL", min(avail, 4))) { /* Might be PJL. */ |
1375 | 28.9k | if (avail < 4) { /* Not enough data to know yet. */ |
1376 | 5 | code = gs_error_NeedInput; |
1377 | 5 | break; |
1378 | 5 | } |
1379 | | /* Definitely a PJL command. */ |
1380 | 28.9k | } else { /* Definitely not PJL. */ |
1381 | 3.76k | code = 1; |
1382 | 3.76k | break; |
1383 | 3.76k | } |
1384 | 32.6k | } |
1385 | 35.2k | } |
1386 | 978k | if (!legal_pjl_char(p[1])) { |
1387 | 2.72k | code = 1; |
1388 | | /* If we haven't read anything yet, then just give up */ |
1389 | 2.72k | if (pst->pos == 0) { |
1390 | 0 | ++p; |
1391 | 0 | break; |
1392 | 0 | } |
1393 | | /* If we have, process what we had collected already before giving up. */ |
1394 | | /* null terminate, parse and set the pjl state */ |
1395 | 2.72k | pst->line[pst->pos] = '\0'; |
1396 | | /* |
1397 | | * NB PJL continues not considering normal errors but we |
1398 | | * ignore memory failure errors here and shouldn't. |
1399 | | */ |
1400 | 2.72k | (void)pjl_parse_and_process_line(pst); |
1401 | 2.72k | pst->pos = 0; |
1402 | 2.72k | break; |
1403 | 2.72k | } |
1404 | 976k | if (p[1] == '\n') { |
1405 | 26.1k | ++p; |
1406 | | /* null terminate, parse and set the pjl state */ |
1407 | 26.1k | pst->line[pst->pos] = '\0'; |
1408 | | /* |
1409 | | * NB PJL continues not considering normal errors but we |
1410 | | * ignore memory failure errors here and shouldn't. |
1411 | | */ |
1412 | 26.1k | (void)pjl_parse_and_process_line(pst); |
1413 | 26.1k | pst->pos = 0; |
1414 | 26.1k | continue; |
1415 | 26.1k | } |
1416 | | |
1417 | | /* Copy the PJL line into the parser's line buffer. */ |
1418 | | /* Always leave room for a terminator. */ |
1419 | 950k | if (pst->pos == pst->line_size) { |
1420 | 90 | char *temp = (char *)gs_alloc_bytes (pst->mem, pst->line_size + 256, "pjl_state increase line buffer"); |
1421 | 90 | if (temp != NULL) { |
1422 | 90 | memcpy(temp, pst->line, pst->line_size); |
1423 | 90 | gs_free_object(pst->mem, pst->line, "pjl_state line buffer"); |
1424 | 90 | pst->line = temp; |
1425 | 90 | pst->line_size += 256; |
1426 | 90 | pst->line[pst->pos] = p[1], pst->pos++; |
1427 | 90 | } |
1428 | 90 | } else |
1429 | 950k | pst->line[pst->pos] = p[1], pst->pos++; |
1430 | 950k | ++p; |
1431 | 950k | } |
1432 | 6.64k | pr->ptr = p; |
1433 | 6.64k | return code; |
1434 | 6.64k | } |
1435 | | |
1436 | | /* Discard the remainder of a job. Return true when we reach a UEL. */ |
1437 | | /* The input buffer must be at least large enough to hold an entire UEL. */ |
1438 | | bool |
1439 | | pjl_skip_to_uel(stream_cursor_read * pr) |
1440 | 0 | { |
1441 | 0 | const byte *p = pr->ptr; |
1442 | 0 | const byte *rlimit = pr->limit; |
1443 | |
|
1444 | 0 | for (; p < rlimit; ++p) |
1445 | 0 | if (p[1] == '\033') { |
1446 | 0 | uint avail = rlimit - p; |
1447 | |
|
1448 | 0 | if (memcmp(p + 1, "\033%-12345X", min(avail, 9))) |
1449 | 0 | continue; |
1450 | 0 | if (avail < 9) |
1451 | 0 | break; |
1452 | 0 | pr->ptr = p + 9; |
1453 | 0 | return true; |
1454 | 0 | } |
1455 | 0 | pr->ptr = p; |
1456 | 0 | return false; |
1457 | 0 | } |
1458 | | |
1459 | | /* PJL symbol set environment variable -> pcl symbol set numbers. |
1460 | | This probably should not be defined here :-( */ |
1461 | | static const struct |
1462 | | { |
1463 | | const char *symname; |
1464 | | const int pcl_code; |
1465 | | } symbol_sets[] = { |
1466 | | {"ROMAN8", 277}, |
1467 | | {"ISOL1", 14}, |
1468 | | {"ISOL2", 78}, |
1469 | | {"ISOL5", 174}, |
1470 | | {"PC8", 341}, |
1471 | | {"PC8DN", 373}, |
1472 | | {"PC850", 405}, |
1473 | | {"PC852", 565}, |
1474 | | {"PC8TK", 308}, |
1475 | | {"WINL1", 309}, |
1476 | | {"WINL2", 293}, |
1477 | | {"WINL5", 180}, |
1478 | | {"DESKTOP", 234}, |
1479 | | {"PSTEXT", 330}, |
1480 | | {"VNINTL", 426}, |
1481 | | {"VNUS", 458}, |
1482 | | {"MSPUBL", 202}, |
1483 | | {"MATH8", 269}, |
1484 | | {"PSMATH", 173}, |
1485 | | {"VNMATH", 205}, |
1486 | | {"PIFONT", 501}, |
1487 | | {"LEGAL", 53}, |
1488 | | {"ISO4", 37}, |
1489 | | {"ISO6", 21}, |
1490 | | {"ISO11", 19}, |
1491 | | {"ISO15", 9}, |
1492 | | {"ISO17", 83}, |
1493 | | {"ISO21", 39}, |
1494 | | {"ISO60", 4}, |
1495 | | {"ISO69", 38}, |
1496 | | {NULL, -1} |
1497 | | }; |
1498 | | |
1499 | | /* map a pjl symbol table name to a pcl symbol table code */ |
1500 | | int |
1501 | | pjl_map_pjl_sym_to_pcl_sym(const char *symname) |
1502 | 99.1k | { |
1503 | 99.1k | int i; |
1504 | | |
1505 | 495k | for (i = 0; symbol_sets[i].symname; i++) |
1506 | 495k | if (!pjl_compare(symname, symbol_sets[i].symname)) |
1507 | 99.1k | return symbol_sets[i].pcl_code; |
1508 | 0 | return -1; |
1509 | 99.1k | } |
1510 | | |
1511 | | /* environment variable to integer */ |
1512 | | int |
1513 | | pjl_vartoi(const pjl_envvar_t * s) |
1514 | 138k | { |
1515 | 138k | return atoi(s); |
1516 | 138k | } |
1517 | | |
1518 | | /* environment variable to float */ |
1519 | | double |
1520 | | pjl_vartof(const pjl_envvar_t * s) |
1521 | 297k | { |
1522 | 297k | return atof(s); |
1523 | 297k | } |
1524 | | |
1525 | | /* convert a pjl font source to a pathname */ |
1526 | | char * |
1527 | | pjl_fontsource_to_path(const pjl_parser_state * pjls, |
1528 | | const pjl_envvar_t * fontsource) |
1529 | 105k | { |
1530 | 105k | int i; |
1531 | | |
1532 | | /* if an environment variable is set we use it, otherwise use the PJL |
1533 | | machinery */ |
1534 | 105k | if (pjls->environment_font_path != NULL) |
1535 | 0 | return pjl_check_font_path(pjls->environment_font_path, pjls->mem); |
1536 | 105k | for (i = 0; pjls->font_envir[i].designator[0]; i++) |
1537 | 105k | if (!pjl_compare(pjls->font_envir[i].designator, fontsource)) |
1538 | 105k | return pjl_check_font_path(pjls->font_envir[i].pathname, |
1539 | 105k | pjls->mem); |
1540 | 0 | return NULL; |
1541 | 105k | } |
1542 | | |
1543 | | static int set_pjl_defaults_to_factory(gs_memory_t * mem, pjl_envir_var_t **def) |
1544 | 8.09k | { |
1545 | 8.09k | return set_pjl_defaults(mem, def, (pjl_envir_var_t *)&pjl_factory_defaults); |
1546 | 8.09k | } |
1547 | | |
1548 | | static int set_pjl_defaults(gs_memory_t * mem, pjl_envir_var_t **def, pjl_envir_var_t *from) |
1549 | 8.09k | { |
1550 | 8.09k | pjl_envir_var_t *pjl_def; |
1551 | 8.09k | char *key, *value, *newkey, *newvalue; |
1552 | 8.09k | int i = 0; |
1553 | 8.09k | int limit = 0; |
1554 | | |
1555 | 234k | while (from[limit].var && from[limit].var[0] != 0x00) |
1556 | 226k | limit++; |
1557 | | |
1558 | 8.09k | pjl_def = (pjl_envir_var_t *) gs_alloc_bytes(mem, |
1559 | 8.09k | sizeof |
1560 | 8.09k | (pjl_envir_var_t) * (limit + 1), |
1561 | 8.09k | "pjl_envir"); |
1562 | 8.09k | if (!pjl_def) |
1563 | 0 | return -1; |
1564 | | |
1565 | 8.09k | memset(pjl_def, 0x00, sizeof(pjl_envir_var_t) * (limit + 1)); |
1566 | 234k | while (i < limit) { |
1567 | 226k | key = from[i].var; |
1568 | 226k | value = from[i].value; |
1569 | | |
1570 | 226k | newkey = (char *)gs_alloc_bytes(mem, strlen(key) + 1, "new_pjl_defaults, key"); |
1571 | 226k | newvalue = (char *)gs_alloc_bytes(mem, strlen(value) + 1, "new_pjl_defaults, value"); |
1572 | 226k | if (!newkey || !newvalue) { |
1573 | 0 | gs_free_object(mem, newkey, "new_pjl_defaults, key"); |
1574 | 0 | free_pjl_defaults(mem, &pjl_def); |
1575 | 0 | return -1; |
1576 | 0 | } |
1577 | 226k | strcpy(newkey, key); |
1578 | 226k | strcpy(newvalue, value); |
1579 | 226k | pjl_def[i].var = newkey; |
1580 | 226k | pjl_def[i].value = newvalue; |
1581 | | |
1582 | 226k | i++; |
1583 | 226k | } |
1584 | 8.09k | *def = pjl_def; |
1585 | 8.09k | return 0; |
1586 | 8.09k | } |
1587 | | |
1588 | | static int set_pjl_environment_to_factory(gs_memory_t * mem, pjl_envir_var_t **env) |
1589 | 8.09k | { |
1590 | 8.09k | return set_pjl_environment(mem, env, (pjl_envir_var_t *)&pjl_factory_defaults); |
1591 | 8.09k | } |
1592 | | |
1593 | | static int set_pjl_environment(gs_memory_t * mem, pjl_envir_var_t **env, pjl_envir_var_t *from) |
1594 | 31.8k | { |
1595 | 31.8k | pjl_envir_var_t *pjl_env; |
1596 | 31.8k | char *key, *value, *newkey, *newvalue; |
1597 | 31.8k | int i = 0; |
1598 | 31.8k | int limit = 0; |
1599 | | |
1600 | 922k | while (from[limit].var && from[limit].var[0] != 0x00) |
1601 | 890k | limit++; |
1602 | | |
1603 | 31.8k | pjl_env = (pjl_envir_var_t *) gs_alloc_bytes(mem, |
1604 | 31.8k | (size_t)sizeof |
1605 | 31.8k | (pjl_envir_var_t) * (limit + 1), |
1606 | 31.8k | "pjl_envir"); |
1607 | 31.8k | if (!pjl_env) |
1608 | 0 | return -1; |
1609 | | |
1610 | 31.8k | memset(pjl_env, 0x00, sizeof(pjl_envir_var_t) * (limit + 1)); |
1611 | 922k | while (i < limit) { |
1612 | 890k | key = from[i].var; |
1613 | 890k | value = from[i].value; |
1614 | 890k | newkey = (char *)gs_alloc_bytes(mem, strlen(key) + 1, "pjl_envir, key"); |
1615 | 890k | newvalue = (char *)gs_alloc_bytes(mem, strlen(value) + 1, "pjl_envir, value"); |
1616 | 890k | if (!newkey || !newvalue) { |
1617 | 0 | gs_free_object(mem, newkey, "pjl_envir, key"); |
1618 | 0 | free_pjl_environment(mem, &pjl_env); |
1619 | 0 | return -1; |
1620 | 0 | } |
1621 | 890k | strcpy(newkey, key); |
1622 | 890k | strcpy(newvalue, value); |
1623 | 890k | pjl_env[i].var = newkey; |
1624 | 890k | pjl_env[i].value = newvalue; |
1625 | | |
1626 | 890k | i++; |
1627 | 890k | } |
1628 | 31.8k | *env = pjl_env; |
1629 | 31.8k | return 0; |
1630 | 31.8k | } |
1631 | | |
1632 | | static int set_pjl_fontsource_to_factory(gs_memory_t * mem, pjl_fontsource_t **fontenv) |
1633 | 8.09k | { |
1634 | 8.09k | return set_pjl_fontsource(mem, fontenv, (pjl_fontsource_t *)pjl_fontsource_table); |
1635 | 8.09k | } |
1636 | | |
1637 | | static int set_pjl_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontenv, pjl_fontsource_t *from) |
1638 | 31.8k | { |
1639 | 31.8k | pjl_fontsource_t *pjl_fontenv; |
1640 | 31.8k | char *key, *value, *newkey, *newvalue; |
1641 | 31.8k | int i = 0; |
1642 | 31.8k | int limit = 0; |
1643 | | |
1644 | 318k | while (from[limit].pathname && from[limit].pathname[0] != 0x00) |
1645 | 286k | limit++; |
1646 | | |
1647 | 31.8k | pjl_fontenv = (pjl_fontsource_t *) gs_alloc_bytes(mem, |
1648 | 31.8k | (size_t)sizeof |
1649 | 31.8k | (pjl_fontsource_t) * (limit + 1), |
1650 | 31.8k | "font_envir"); |
1651 | 31.8k | if (!pjl_fontenv) |
1652 | 0 | return -1; |
1653 | | |
1654 | 31.8k | memset(pjl_fontenv, 0x00, sizeof(pjl_fontsource_t) * (limit + 1)); |
1655 | 318k | while (i < limit) { |
1656 | 286k | key = from[i].pathname; |
1657 | 286k | value = from[i].fontnumber; |
1658 | | |
1659 | 286k | newkey = (char *)gs_alloc_bytes(mem, strlen(key) + 1, "new_font_envir, pathname"); |
1660 | 286k | if (!newkey) { |
1661 | 0 | free_pjl_fontsource(mem, &pjl_fontenv); |
1662 | 0 | return -1; |
1663 | 0 | } |
1664 | 286k | strcpy(newkey, key); |
1665 | 286k | pjl_fontenv[i].pathname = newkey; |
1666 | 286k | if (value) { |
1667 | 286k | newvalue = (char *)gs_alloc_bytes(mem, strlen(value) + 1, "new_font_envir, fontnumber"); |
1668 | 286k | if (!newvalue) { |
1669 | 0 | free_pjl_fontsource(mem, &pjl_fontenv); |
1670 | 0 | return -1; |
1671 | 0 | } |
1672 | 286k | strcpy(newvalue, value); |
1673 | 286k | pjl_fontenv[i].fontnumber = newvalue; |
1674 | 286k | } else { |
1675 | 0 | pjl_fontenv[i].fontnumber = 0x00; |
1676 | 0 | } |
1677 | 286k | memcpy(pjl_fontenv[i].designator, pjl_fontsource_table[i].designator, 2); |
1678 | | |
1679 | 286k | i++; |
1680 | 286k | } |
1681 | 31.8k | *fontenv = pjl_fontenv; |
1682 | 31.8k | return 0; |
1683 | 31.8k | } |
1684 | | |
1685 | | static int set_pjl_default_fontsource_to_factory(gs_memory_t * mem, pjl_fontsource_t **fontdef) |
1686 | 8.09k | { |
1687 | 8.09k | return set_pjl_default_fontsource(mem, fontdef, (pjl_fontsource_t *)&pjl_fontsource_table); |
1688 | 8.09k | } |
1689 | | |
1690 | | static int set_pjl_default_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontdef, pjl_fontsource_t *from) |
1691 | 8.09k | { |
1692 | 8.09k | pjl_fontsource_t *pjl_fontdef; |
1693 | 8.09k | char *key, *value, *newkey, *newvalue; |
1694 | 8.09k | int i = 0; |
1695 | 8.09k | int limit = 0; |
1696 | | |
1697 | 80.9k | while (from[limit].pathname && from[limit].pathname[0] != 0x00) |
1698 | 72.8k | limit++; |
1699 | | |
1700 | 8.09k | pjl_fontdef = (pjl_fontsource_t *) gs_alloc_bytes(mem, |
1701 | 8.09k | (size_t)sizeof |
1702 | 8.09k | (pjl_fontsource_t) * (limit + 1), |
1703 | 8.09k | "new_font_defaults"); |
1704 | 8.09k | if (!pjl_fontdef) |
1705 | 0 | return -1; |
1706 | | |
1707 | 8.09k | memset(pjl_fontdef, 0x00, sizeof(pjl_fontsource_t) * (limit + 1)); |
1708 | 80.9k | while (i < limit) { |
1709 | 72.8k | key = from[i].pathname; |
1710 | 72.8k | value = from[i].fontnumber; |
1711 | | |
1712 | 72.8k | newkey = (char *)gs_alloc_bytes(mem, strlen(key) + 1, "new_font_defaults, pathname"); |
1713 | 72.8k | if (!newkey) { |
1714 | 0 | free_pjl_default_fontsource(mem, &pjl_fontdef); |
1715 | 0 | return -1; |
1716 | 0 | } |
1717 | 72.8k | strcpy(newkey, key); |
1718 | 72.8k | pjl_fontdef[i].pathname = newkey; |
1719 | 72.8k | if (value) { |
1720 | 72.8k | newvalue = (char *)gs_alloc_bytes(mem, strlen(value) + 1, "new_font_defaults, fontnumber"); |
1721 | 72.8k | if (!newvalue) { |
1722 | 0 | free_pjl_default_fontsource(mem, &pjl_fontdef); |
1723 | 0 | return -1; |
1724 | 0 | } |
1725 | 72.8k | strcpy(newvalue, value); |
1726 | 72.8k | pjl_fontdef[i].fontnumber = newvalue; |
1727 | 72.8k | } else { |
1728 | 0 | pjl_fontdef[i].fontnumber = 0x00; |
1729 | 0 | } |
1730 | 72.8k | memcpy(pjl_fontdef[i].designator, pjl_fontsource_table[i].designator, 2); |
1731 | | |
1732 | 72.8k | i++; |
1733 | 72.8k | } |
1734 | 8.09k | *fontdef = pjl_fontdef; |
1735 | 8.09k | return 0; |
1736 | 8.09k | } |
1737 | | |
1738 | | static int free_pjl_defaults(gs_memory_t * mem, pjl_envir_var_t **def) |
1739 | 8.09k | { |
1740 | 8.09k | int i=0; |
1741 | 8.09k | pjl_envir_var_t *pjl_def = *def; |
1742 | | |
1743 | 234k | while (pjl_def[i].var) { |
1744 | 226k | gs_free_object(mem, pjl_def[i].var, "free pjl_defaults key"); |
1745 | 226k | gs_free_object(mem, pjl_def[i].value, "free pjl_defaults value"); |
1746 | 226k | i++; |
1747 | 226k | } |
1748 | 8.09k | gs_free_object(mem, pjl_def, "pjl_defaults"); |
1749 | 8.09k | *def = 0x00; |
1750 | 8.09k | return 0; |
1751 | 8.09k | } |
1752 | | |
1753 | | int free_pjl_environment(gs_memory_t * mem, pjl_envir_var_t **env) |
1754 | 31.8k | { |
1755 | 31.8k | int i=0; |
1756 | 31.8k | pjl_envir_var_t *pjl_env = *env; |
1757 | | |
1758 | 31.8k | if (pjl_env == NULL) |
1759 | 0 | return 0; |
1760 | | |
1761 | 922k | while (pjl_env[i].var) { |
1762 | 890k | gs_free_object(mem, pjl_env[i].var, "free pjl_environment key"); |
1763 | 890k | gs_free_object(mem, pjl_env[i].value, "free pjl_environment value"); |
1764 | 890k | i++; |
1765 | 890k | } |
1766 | 31.8k | gs_free_object(mem, pjl_env, "pjl_environment"); |
1767 | 31.8k | *env = 0x00; |
1768 | 31.8k | return 0; |
1769 | 31.8k | } |
1770 | | |
1771 | | int free_pjl_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontenv) |
1772 | 31.8k | { |
1773 | 31.8k | int i=0; |
1774 | 31.8k | pjl_fontsource_t *pjl_fontenv = *fontenv; |
1775 | | |
1776 | 31.8k | if (pjl_fontenv == NULL) |
1777 | 0 | return 0; |
1778 | | |
1779 | 318k | while (pjl_fontenv[i].pathname) { |
1780 | 286k | gs_free_object(mem, pjl_fontenv[i].pathname, "pjl_font_envir pathname"); |
1781 | 286k | gs_free_object(mem, pjl_fontenv[i].fontnumber, "pjl_font_envir fontnumber"); |
1782 | 286k | i++; |
1783 | 286k | } |
1784 | 31.8k | gs_free_object(mem, pjl_fontenv, "pjl_font_envir"); |
1785 | 31.8k | *fontenv = 0x00; |
1786 | 31.8k | return 0; |
1787 | 31.8k | } |
1788 | | |
1789 | | int free_pjl_default_fontsource(gs_memory_t * mem, pjl_fontsource_t **fontdef) |
1790 | 8.09k | { |
1791 | 8.09k | int i=0; |
1792 | 8.09k | pjl_fontsource_t *pjl_fontdef = *fontdef; |
1793 | | |
1794 | 80.9k | while (pjl_fontdef[i].pathname) { |
1795 | 72.8k | gs_free_object(mem, pjl_fontdef[i].pathname, "pjl_font_defaults pathname"); |
1796 | 72.8k | gs_free_object(mem, pjl_fontdef[i].fontnumber, "pjl_font_defaults fontnumber"); |
1797 | 72.8k | i++; |
1798 | 72.8k | } |
1799 | 8.09k | gs_free_object(mem, pjl_fontdef, "pjl_font_defaults"); |
1800 | 8.09k | *fontdef = 0x00; |
1801 | 8.09k | return 0; |
1802 | 8.09k | } |
1803 | | |
1804 | | /* Create and initialize a new state. */ |
1805 | | pjl_parser_state * |
1806 | | pjl_process_init(gs_memory_t * mem) |
1807 | 8.09k | { |
1808 | 8.09k | pjl_envir_var_t *pjl_env, *pjl_def; |
1809 | 8.09k | pjl_fontsource_t *pjl_fontenv, *pjl_fontdef; |
1810 | | |
1811 | 8.09k | pjl_parser_state_t *pjlstate = (pjl_parser_state *) gs_alloc_bytes(mem, |
1812 | 8.09k | sizeof |
1813 | 8.09k | (pjl_parser_state_t), |
1814 | 8.09k | "pjl_state"); |
1815 | | |
1816 | 8.09k | if (pjlstate == NULL) |
1817 | 0 | return NULL; /* should be fatal so we don't bother piecemeal frees */ |
1818 | | |
1819 | 8.09k | pjlstate->line = (char *)gs_alloc_bytes(mem, 256, "pjl_state line buffer"); |
1820 | 8.09k | if (pjlstate->line == NULL) { |
1821 | 0 | gs_free_object(mem, pjlstate, "pjl_state"); |
1822 | 0 | return NULL; |
1823 | 0 | } |
1824 | 8.09k | pjlstate->line_size = 255; |
1825 | | |
1826 | | /* check for an environment variable */ |
1827 | 8.09k | { |
1828 | 8.09k | int pathlen, code; |
1829 | | |
1830 | | /* The environment variable exists if the function fails to |
1831 | | fit in the null - odd but it works. We allow an |
1832 | | environment variable to override the font default PJL font |
1833 | | path for desktop setups */ |
1834 | 8.09k | pathlen = 0; |
1835 | 8.09k | if ((code = gp_getenv("PCLFONTSOURCE", (char *)0, &pathlen)) < 0) { |
1836 | 0 | char *path = |
1837 | 0 | (char *)gs_alloc_bytes(mem, pathlen + 1, "pjl_font_path"); |
1838 | | /* if the allocation fails we use the pjl fontsource */ |
1839 | 0 | if (path == NULL) |
1840 | 0 | pjlstate->environment_font_path = NULL; |
1841 | 0 | else { |
1842 | 0 | const char * const sepr = gp_file_name_separator(); |
1843 | 0 | const int lsepr = strlen(sepr); |
1844 | 0 | gp_getenv("PCLFONTSOURCE", path, &pathlen); /* can't fail */ |
1845 | | |
1846 | | /* We want to ensure a trailing "/" is present */ |
1847 | 0 | if (gs_file_name_check_separator(path + (pathlen - (lsepr + 1)), lsepr, path + pathlen - 1) != 1) { |
1848 | 0 | strncat(path, gp_file_name_separator(), pathlen + 1); |
1849 | 0 | } |
1850 | 0 | code = gs_add_control_path(mem, gs_permit_file_reading, path); |
1851 | 0 | if (code < 0) { |
1852 | 0 | gs_free_object(mem, path, "pjl_font_path"); |
1853 | 0 | goto fail1; |
1854 | 0 | } |
1855 | 0 | pjlstate->environment_font_path = path; |
1856 | 0 | } |
1857 | 0 | } else /* environmet variable does not exist use pjl fontsource */ |
1858 | 8.09k | pjlstate->environment_font_path = NULL; |
1859 | 8.09k | } |
1860 | | |
1861 | | /* initialize the default and initial pjl environment. We assume |
1862 | | that these are the same layout as the factory defaults. */ |
1863 | 8.09k | if (set_pjl_defaults_to_factory(mem, &pjl_def) < 0) { |
1864 | 0 | goto fail1; |
1865 | 0 | } |
1866 | 8.09k | if (set_pjl_environment_to_factory(mem, &pjl_env) < 0) { |
1867 | 0 | goto fail2; |
1868 | 0 | } |
1869 | 8.09k | if (set_pjl_fontsource_to_factory(mem, &pjl_fontenv) < 0) { |
1870 | 0 | goto fail3; |
1871 | 0 | } |
1872 | 8.09k | if (set_pjl_default_fontsource_to_factory(mem, &pjl_fontdef) < 0) { |
1873 | 0 | goto fail4; |
1874 | 0 | } |
1875 | | |
1876 | | /* initialize the font repository data as well */ |
1877 | 8.09k | pjlstate->defaults = pjl_def; |
1878 | 8.09k | pjlstate->envir = pjl_env; |
1879 | 8.09k | pjlstate->font_envir = pjl_fontenv; |
1880 | 8.09k | pjlstate->font_defaults = pjl_fontdef; |
1881 | | |
1882 | | /* initialize the current position in the line array and bytes pending */ |
1883 | 8.09k | pjlstate->bytes_to_read = 0; |
1884 | 8.09k | pjlstate->bytes_to_write = 0; |
1885 | 8.09k | pjlstate->fp = 0; |
1886 | | /* line pos */ |
1887 | 8.09k | pjlstate->pos = 0; |
1888 | 8.09k | pjlstate->mem = mem; |
1889 | | /* initialize available font sources */ |
1890 | 8.09k | pjl_reset_fontsource_fontnumbers(pjlstate); |
1891 | 8.09k | { |
1892 | 8.09k | int i; |
1893 | | |
1894 | 267k | for (i = 0; i < countof(pjlstate->permanent_soft_fonts); i++) |
1895 | 259k | pjlstate->permanent_soft_fonts[i] = 0; |
1896 | 8.09k | } |
1897 | 8.09k | return (pjl_parser_state *) pjlstate; |
1898 | | |
1899 | 0 | fail4: |
1900 | 0 | free_pjl_fontsource(mem, &pjl_fontenv); |
1901 | 0 | fail3: |
1902 | 0 | free_pjl_environment(mem, &pjl_env); |
1903 | 0 | fail2: |
1904 | 0 | free_pjl_defaults(mem, &pjl_def); |
1905 | 0 | fail1: |
1906 | 0 | gs_free_object(mem, pjlstate->line, "pjl_state line buffer"); |
1907 | 0 | gs_free_object(mem, pjlstate, "pjl_state"); |
1908 | 0 | return NULL; |
1909 | 0 | } |
1910 | | |
1911 | | /* case insensitive comparison of two null terminated strings. */ |
1912 | | int |
1913 | | pjl_compare(const pjl_envvar_t * s1, const char *s2) |
1914 | 15.4M | { |
1915 | 29.8M | for (; toupper(*s1) == toupper(*s2); ++s1, ++s2) |
1916 | 16.1M | if (*s1 == '\0') |
1917 | 1.62M | return (0); |
1918 | 13.7M | return 1; |
1919 | 15.4M | } |
1920 | | |
1921 | | /* free all memory associated with the PJL state */ |
1922 | | void |
1923 | | pjl_process_destroy(pjl_parser_state * pst) |
1924 | 8.09k | { |
1925 | 8.09k | gs_memory_t *mem; |
1926 | | |
1927 | 8.09k | if (pst == NULL) |
1928 | 0 | return; |
1929 | | |
1930 | 8.09k | mem = pst->mem; |
1931 | | |
1932 | 8.09k | free_pjl_defaults(mem, &pst->defaults); |
1933 | 8.09k | free_pjl_environment(mem, &pst->envir); |
1934 | 8.09k | free_pjl_fontsource(mem, &pst->font_envir); |
1935 | 8.09k | free_pjl_default_fontsource(mem, &pst->font_defaults); |
1936 | | |
1937 | 8.09k | if (pst->environment_font_path) |
1938 | 0 | gs_free_object(mem, pst->environment_font_path, "pjl_state"); |
1939 | 8.09k | gs_free_object(mem, pst->line, "pjl_state line buffer"); |
1940 | 8.09k | gs_free_object(mem, pst, "pjl_state"); |
1941 | 8.09k | } |
1942 | | |
1943 | | /* delete a permanent soft font */ |
1944 | | int |
1945 | | pjl_register_permanent_soft_font_deletion(pjl_parser_state * pst, |
1946 | | int font_number) |
1947 | 0 | { |
1948 | 0 | if ((font_number > MAX_PERMANENT_FONTS - 1) || (font_number < 0)) { |
1949 | 0 | dmprintf(pst->mem, |
1950 | 0 | "pjparse.c:pjl_register_permanent_soft_font_deletion() bad font number\n"); |
1951 | 0 | return 0; |
1952 | 0 | } |
1953 | | /* if the font is present. */ |
1954 | 0 | if ((pst->permanent_soft_fonts[font_number >> 3]) & |
1955 | 0 | (128 >> (font_number & 7))) { |
1956 | | /* set the bit to zero to indicate the fontnumber has been deleted */ |
1957 | 0 | pst->permanent_soft_fonts[font_number >> 3] &= |
1958 | 0 | ~(128 >> (font_number & 7)); |
1959 | | /* if the current font source is 'S' and the current font number |
1960 | | is the highest number, and *any* soft font was deleted or if |
1961 | | the last font has been removed, set the stage for changing to |
1962 | | the next priority font source. BLAME HP not me. */ |
1963 | 0 | { |
1964 | 0 | bool is_S = !pjl_compare(pjl_get_envvar(pst, "fontsource"), "S"); |
1965 | 0 | bool empty = true; |
1966 | 0 | int highest_fontnumber = -1; |
1967 | 0 | int current_fontnumber = |
1968 | 0 | pjl_vartoi(pjl_get_envvar(pst, "fontnumber")); |
1969 | 0 | int i; |
1970 | | |
1971 | | /* check for no more fonts and the highest font number. |
1972 | | NB should look at longs not bits in the loop */ |
1973 | 0 | for (i = 0; i < MAX_PERMANENT_FONTS; i++) |
1974 | 0 | if ((pst->permanent_soft_fonts[i >> 3]) & (128 >> (i & 7))) { |
1975 | 0 | empty = false; |
1976 | 0 | highest_fontnumber = i; |
1977 | 0 | } |
1978 | 0 | if (is_S && ((highest_fontnumber == current_fontnumber) || empty)) { |
1979 | 0 | #define SINDEX 4 |
1980 | 0 | pst->font_defaults[SINDEX].fontnumber[0] = '\0'; |
1981 | 0 | pst->font_envir[SINDEX].fontnumber[0] = '\0'; |
1982 | 0 | return 1; |
1983 | 0 | #undef SINDEX |
1984 | 0 | } |
1985 | 0 | } |
1986 | 0 | } |
1987 | 0 | return 0; |
1988 | 0 | } |
1989 | | |
1990 | | /* request that pjl add a soft font and return a pjl font number for |
1991 | | the font. */ |
1992 | | int |
1993 | | pjl_register_permanent_soft_font_addition(pjl_parser_state * pst) |
1994 | 0 | { |
1995 | | /* Find an empty slot in the table. We have no HP documentation |
1996 | | that says how a soft font gets associated with a font number */ |
1997 | 0 | int font_num; |
1998 | 0 | bool slot_found = false; |
1999 | |
|
2000 | 0 | for (font_num = 0; font_num < MAX_PERMANENT_FONTS; font_num++) |
2001 | 0 | if (! |
2002 | 0 | ((pst->permanent_soft_fonts[font_num >> 3]) & |
2003 | 0 | (128 >> (font_num & 7)))) { |
2004 | 0 | slot_found = true; |
2005 | 0 | break; |
2006 | 0 | } |
2007 | | /* yikes, shouldn't happen */ |
2008 | 0 | if (!slot_found) { |
2009 | 0 | dmprintf(pst->mem, |
2010 | 0 | "pjparse.c:pjl_register_permanent_soft_font_addition()\ |
2011 | 0 | font table full recycling font number 0\n"); |
2012 | 0 | font_num = 0; |
2013 | 0 | } |
2014 | | /* set the bit to 1 to indicate the fontnumber has been added */ |
2015 | 0 | pst->permanent_soft_fonts[font_num >> 3] |= (128 >> (font_num & 7)); |
2016 | 0 | return font_num; |
2017 | 0 | } |