]> git.ipfire.org Git - thirdparty/cups.git/blob - systemv/cupstestdsc.c
Load cups into easysw/current.
[thirdparty/cups.git] / systemv / cupstestdsc.c
1 /*
2 * "$Id: cupstestdsc.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * DSC test program for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007 by Apple Inc.
7 * Copyright 2006 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * PostScript is a trademark of Adobe Systems, Inc.
16 *
17 * This file is subject to the Apple OS-Developed Software exception.
18 *
19 * Contents:
20 *
21 * main() - Main entry for test program.
22 * check() - Check a file for conformance.
23 * usage() - Show program usage.
24 */
25
26 /*
27 * Include necessary headers...
28 */
29
30 #include <cups/string.h>
31 #include <cups/cups.h>
32 #include <cups/file.h>
33 #include <cups/i18n.h>
34 #include <errno.h>
35 #include <stdlib.h>
36
37
38 /*
39 * Local functions...
40 */
41
42 static int check_file(const char *filename);
43 static void usage(void);
44
45
46 /*
47 * 'main()' - Main entry for test program.
48 */
49
50 int /* O - Exit status */
51 main(int argc, /* I - Number of command-line args */
52 char *argv[]) /* I - Command-line arguments */
53 {
54 int i; /* Looping var */
55 int status; /* Status of tests */
56 int num_files; /* Number of files tested */
57
58
59 _cupsSetLocale(argv);
60
61 /*
62 * Collect command-line arguments...
63 */
64
65 for (i = 1, num_files = 0, status = 0; i < argc; i ++)
66 if (argv[i][0] == '-')
67 {
68 if (argv[i][1])
69 {
70 /*
71 * Currently the only supported option is "-h" (help)...
72 */
73
74 usage();
75 }
76 else
77 {
78 num_files ++;
79 status += check_file("(stdin)");
80 }
81 }
82 else
83 {
84 num_files ++;
85 status += check_file(argv[i]);
86 }
87
88 if (!num_files)
89 usage();
90
91 return (status);
92 }
93
94
95 /*
96 * 'check()' - Check a file for conformance.
97 */
98
99 static int /* O - 0 on success, 1 on failure */
100 check_file(const char *filename) /* I - File to read from */
101 {
102 int i; /* Looping var */
103 cups_file_t *fp; /* File */
104 char line[1024]; /* Line from file */
105 int ch; /* Current character */
106 size_t bytes; /* Length of line */
107 int status; /* Status of test */
108 int linenum; /* Line number */
109 int binary; /* File contains binary data? */
110 float version; /* DSC version */
111 int lbrt[4]; /* Bounding box */
112 char page_label[256]; /* Page label string */
113 int page_number; /* Page number */
114 int last_page_number; /* Last page number seen */
115 int level; /* Embedded document level */
116 int saw_bounding_box, /* %%BoundingBox seen? */
117 saw_pages, /* %%Pages seen? */
118 saw_end_comments, /* %%EndComments seen? */
119 saw_begin_prolog, /* %%BeginProlog seen? */
120 saw_end_prolog, /* %%EndProlog seen? */
121 saw_begin_setup, /* %%BeginSetup seen? */
122 saw_end_setup, /* %%EndSetup seen? */
123 saw_page, /* %%Page seen? */
124 saw_trailer, /* %%Trailer seen? */
125 saw_long_line; /* Saw long lines? */
126
127
128 /*
129 * Open the file...
130 */
131
132 if (!strcmp(filename, "(stdin)"))
133 fp = cupsFileStdin();
134 else
135 fp = cupsFileOpen(filename, "r");
136
137 if (!fp)
138 {
139 perror(filename);
140 return (1);
141 }
142
143 /*
144 * Scan the file...
145 */
146
147 binary = 0;
148 last_page_number = 0;
149 level = 0;
150 linenum = 0;
151 saw_begin_prolog = 0;
152 saw_begin_setup = 0;
153 saw_bounding_box = 0;
154 saw_end_comments = 0;
155 saw_end_prolog = 0;
156 saw_end_setup = 0;
157 saw_long_line = 0;
158 saw_page = 0;
159 saw_pages = 0;
160 saw_trailer = 0;
161 status = 0;
162 version = 0.0f;
163
164 _cupsLangPrintf(stdout, "%s: ", filename);
165 fflush(stdout);
166
167 while ((bytes = cupsFileGetLine(fp, line, sizeof(line))) > 0)
168 {
169 linenum ++;
170
171 if (bytes > 255)
172 {
173 if (!saw_long_line)
174 {
175 if (!status)
176 _cupsLangPuts(stdout, _("FAIL\n"));
177
178 status ++;
179 _cupsLangPrintf(stdout,
180 _(" Line %d is longer than 255 characters (%d)!\n"
181 " REF: Page 25, Line Length\n"),
182 linenum, (int)bytes);
183 }
184
185 saw_long_line ++;
186 }
187
188 if (linenum == 1)
189 {
190 if (strncmp(line, "%!PS-Adobe-", 11))
191 {
192 if (!status)
193 _cupsLangPuts(stdout, _("FAIL\n"));
194
195 status ++;
196 _cupsLangPuts(stdout,
197 _(" Missing %!PS-Adobe-3.0 on first line!\n"
198 " REF: Page 17, 3.1 Conforming Documents\n"));
199 cupsFileClose(fp);
200 return (1);
201 }
202 else
203 version = atof(line + 11);
204 }
205 else if (level > 0)
206 {
207 if (!strncmp(line, "%%BeginDocument:", 16))
208 level ++;
209 else if (!strncmp(line, "%%EndDocument", 13))
210 level --;
211 }
212 else if (saw_trailer)
213 {
214 if (!strncmp(line, "%%Pages:", 8))
215 {
216 if (atoi(line + 8) <= 0)
217 {
218 if (!status)
219 _cupsLangPuts(stdout, _("FAIL\n"));
220
221 status ++;
222 _cupsLangPrintf(stdout,
223 _(" Bad %%%%Pages: on line %d!\n"
224 " REF: Page 43, %%%%Pages:\n"),
225 linenum);
226 }
227 else
228 saw_pages = 1;
229 }
230 else if (!strncmp(line, "%%BoundingBox:", 14))
231 {
232 if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2,
233 lbrt + 3) != 4)
234 {
235 if (!status)
236 _cupsLangPuts(stdout, _("FAIL\n"));
237
238 status ++;
239 _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d!\n"
240 " REF: Page 39, %%%%BoundingBox:\n"),
241 linenum);
242 }
243 else
244 saw_bounding_box = 1;
245 }
246 }
247 else if (!saw_end_comments)
248 {
249 if (!strncmp(line, "%%EndComments", 13))
250 saw_end_comments = 1;
251 else if (line[0] != '%')
252 saw_end_comments = -1;
253 else if (!strncmp(line, "%%Pages:", 8))
254 {
255 if (strstr(line + 8, "(atend)"))
256 saw_pages = -1;
257 else if (atoi(line + 8) <= 0)
258 {
259 if (!status)
260 _cupsLangPuts(stdout, _("FAIL\n"));
261
262 status ++;
263 _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d!\n"
264 " REF: Page 43, %%%%Pages:\n"),
265 linenum);
266 }
267 else
268 saw_pages = 1;
269 }
270 else if (!strncmp(line, "%%BoundingBox:", 14))
271 {
272 if (strstr(line, "(atend)"))
273 saw_bounding_box = -1;
274 else if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2,
275 lbrt + 3) != 4)
276 {
277 if (!status)
278 _cupsLangPuts(stdout, _("FAIL\n"));
279
280 status ++;
281 _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d!\n"
282 " REF: Page 39, %%%%BoundingBox:\n"),
283 linenum);
284 }
285 else
286 saw_bounding_box = 1;
287 }
288 }
289 else if (saw_begin_prolog && !saw_end_prolog)
290 {
291 if (!strncmp(line, "%%EndProlog", 11))
292 saw_end_prolog = 1;
293 }
294 else if (saw_begin_setup && !saw_end_setup)
295 {
296 if (!strncmp(line, "%%EndSetup", 10))
297 saw_end_setup = 1;
298 }
299 else if (saw_end_comments)
300 {
301 if (!strncmp(line, "%%Page:", 7))
302 {
303 if (sscanf(line + 7, "%255s%d", page_label, &page_number) != 2 ||
304 page_number != (last_page_number + 1) || page_number < 1)
305 {
306 if (!status)
307 _cupsLangPuts(stdout, _("FAIL\n"));
308
309 status ++;
310 _cupsLangPrintf(stdout, _(" Bad %%%%Page: on line %d!\n"
311 " REF: Page 53, %%%%Page:\n"),
312 linenum);
313 }
314 else
315 {
316 last_page_number = page_number;
317 saw_page = 1;
318 }
319 }
320 else if (!strncmp(line, "%%BeginProlog", 13))
321 saw_begin_prolog = 1;
322 else if (!strncmp(line, "%%BeginSetup", 12))
323 saw_begin_setup = 1;
324 else if (!strncmp(line, "%%BeginDocument:", 16))
325 level ++;
326 else if (!strncmp(line, "%%EndDocument", 13))
327 level --;
328 else if (!strncmp(line, "%%Trailer", 9))
329 saw_trailer = 1;
330 }
331
332 for (i = 0; !binary && i < bytes; i ++)
333 {
334 ch = line[i];
335
336 if ((ch < ' ' || (ch & 0x80)) && ch != '\n' && ch != '\r' && ch != '\t')
337 binary = 1;
338 }
339 }
340
341 if (saw_bounding_box <= 0)
342 {
343 if (!status)
344 _cupsLangPuts(stdout, _("FAIL\n"));
345
346 status ++;
347 _cupsLangPuts(stdout, _(" Missing or bad %%BoundingBox: comment!\n"
348 " REF: Page 39, %%BoundingBox:\n"));
349 }
350
351 if (saw_pages <= 0)
352 {
353 if (!status)
354 _cupsLangPuts(stdout, _("FAIL\n"));
355
356 status ++;
357 _cupsLangPuts(stdout, _(" Missing or bad %%Pages: comment!\n"
358 " REF: Page 43, %%Pages:\n"));
359 }
360
361 if (!saw_end_comments)
362 {
363 if (!status)
364 _cupsLangPuts(stdout, _("FAIL\n"));
365
366 status ++;
367 _cupsLangPuts(stdout, _(" Missing %%EndComments comment!\n"
368 " REF: Page 41, %%EndComments\n"));
369 }
370
371 if (!saw_page)
372 {
373 if (!status)
374 _cupsLangPuts(stdout, _("FAIL\n"));
375
376 status ++;
377 _cupsLangPuts(stdout, _(" Missing or bad %%Page: comments!\n"
378 " REF: Page 53, %%Page:\n"));
379 }
380
381 if (level < 0)
382 {
383 if (!status)
384 _cupsLangPuts(stdout, _("FAIL\n"));
385
386 status ++;
387 _cupsLangPuts(stdout, _(" Too many %%EndDocument comments!\n"));
388 }
389 else if (level > 0)
390 {
391 if (!status)
392 _cupsLangPuts(stdout, _("FAIL\n"));
393
394 status ++;
395 _cupsLangPuts(stdout, _(" Too many %%BeginDocument comments!\n"));
396 }
397
398 if (saw_long_line > 1)
399 _cupsLangPrintf(stderr,
400 _(" Saw %d lines that exceeded 255 characters!\n"),
401 saw_long_line);
402
403 if (!status)
404 _cupsLangPuts(stdout, _("PASS\n"));
405
406 if (binary)
407 _cupsLangPuts(stdout, _(" Warning: file contains binary data!\n"));
408
409 if (version < 3.0f)
410 _cupsLangPrintf(stdout,
411 _(" Warning: obsolete DSC version %.1f in file!\n"),
412 version);
413
414 if (saw_end_comments < 0)
415 _cupsLangPuts(stdout, _(" Warning: no %%EndComments comment in file!\n"));
416
417 cupsFileClose(fp);
418
419 return (status);
420 }
421
422
423 /*
424 * 'usage()' - Show program usage.
425 */
426
427 static void
428 usage(void)
429 {
430 _cupsLangPuts(stdout,
431 _("Usage: cupstestdsc [options] filename.ps [... filename.ps]\n"
432 " cupstestdsc [options] -\n"
433 "\n"
434 "Options:\n"
435 "\n"
436 " -h Show program usage\n"
437 "\n"
438 " Note: this program only validates the DSC comments, "
439 "not the PostScript itself.\n"));
440
441 exit(1);
442 }
443
444
445 /*
446 * End of "$Id: cupstestdsc.c 6649 2007-07-11 21:46:42Z mike $".
447 */