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