]> git.ipfire.org Git - thirdparty/cups.git/blame - systemv/cupstestdsc.c
Merge changes from CUPS 1.5svn-r8849.
[thirdparty/cups.git] / systemv / cupstestdsc.c
CommitLineData
80ca4592 1/*
b19ccc9e 2 * "$Id: cupstestdsc.c 7720 2008-07-11 22:46:21Z mike $"
80ca4592 3 *
4 * DSC test program for the Common UNIX Printing System (CUPS).
5 *
4d301e69 6 * Copyright 2007-2009 by Apple Inc.
80ca4592 7 * Copyright 2006 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
80ca4592 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 *
89d46774 21 * main() - Main entry for test program.
22 * check() - Check a file for conformance.
23 * usage() - Show program usage.
80ca4592 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
42static int check_file(const char *filename);
43static void usage(void);
44
45
46/*
47 * 'main()' - Main entry for test program.
48 */
49
50int /* O - Exit status */
51main(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
07725fee 59 _cupsSetLocale(argv);
d09495fa 60
80ca4592 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/*
89d46774 96 * 'check()' - Check a file for conformance.
80ca4592 97 */
98
99static int /* O - 0 on success, 1 on failure */
100check_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 */
89d46774 114 int last_page_number; /* Last page number seen */
80ca4592 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? */
80ca4592 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;
89d46774 148 last_page_number = 0;
80ca4592 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;
80ca4592 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,
4d301e69 180 _(" Line %d is longer than 255 characters (%d)\n"
80ca4592 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
80ca4592 195 _cupsLangPuts(stdout,
4d301e69 196 _(" Missing %!PS-Adobe-3.0 on first line\n"
80ca4592 197 " REF: Page 17, 3.1 Conforming Documents\n"));
198 cupsFileClose(fp);
199 return (1);
200 }
201 else
202 version = atof(line + 11);
203 }
204 else if (level > 0)
205 {
206 if (!strncmp(line, "%%BeginDocument:", 16))
207 level ++;
208 else if (!strncmp(line, "%%EndDocument", 13))
209 level --;
210 }
211 else if (saw_trailer)
212 {
213 if (!strncmp(line, "%%Pages:", 8))
214 {
215 if (atoi(line + 8) <= 0)
216 {
217 if (!status)
218 _cupsLangPuts(stdout, _("FAIL\n"));
219
220 status ++;
221 _cupsLangPrintf(stdout,
4d301e69 222 _(" Bad %%%%Pages: on line %d\n"
80ca4592 223 " REF: Page 43, %%%%Pages:\n"),
224 linenum);
225 }
226 else
227 saw_pages = 1;
228 }
229 else if (!strncmp(line, "%%BoundingBox:", 14))
230 {
231 if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2,
232 lbrt + 3) != 4)
233 {
234 if (!status)
235 _cupsLangPuts(stdout, _("FAIL\n"));
236
237 status ++;
4d301e69 238 _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d\n"
80ca4592 239 " REF: Page 39, %%%%BoundingBox:\n"),
240 linenum);
241 }
242 else
243 saw_bounding_box = 1;
244 }
245 }
246 else if (!saw_end_comments)
247 {
248 if (!strncmp(line, "%%EndComments", 13))
249 saw_end_comments = 1;
250 else if (line[0] != '%')
251 saw_end_comments = -1;
252 else if (!strncmp(line, "%%Pages:", 8))
253 {
254 if (strstr(line + 8, "(atend)"))
255 saw_pages = -1;
256 else if (atoi(line + 8) <= 0)
257 {
258 if (!status)
259 _cupsLangPuts(stdout, _("FAIL\n"));
260
261 status ++;
4d301e69 262 _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d\n"
80ca4592 263 " REF: Page 43, %%%%Pages:\n"),
264 linenum);
265 }
266 else
267 saw_pages = 1;
268 }
269 else if (!strncmp(line, "%%BoundingBox:", 14))
270 {
271 if (strstr(line, "(atend)"))
272 saw_bounding_box = -1;
273 else if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2,
274 lbrt + 3) != 4)
275 {
276 if (!status)
277 _cupsLangPuts(stdout, _("FAIL\n"));
278
279 status ++;
4d301e69 280 _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d\n"
80ca4592 281 " REF: Page 39, %%%%BoundingBox:\n"),
282 linenum);
283 }
284 else
285 saw_bounding_box = 1;
286 }
287 }
288 else if (saw_begin_prolog && !saw_end_prolog)
289 {
290 if (!strncmp(line, "%%EndProlog", 11))
291 saw_end_prolog = 1;
292 }
293 else if (saw_begin_setup && !saw_end_setup)
294 {
295 if (!strncmp(line, "%%EndSetup", 10))
296 saw_end_setup = 1;
297 }
298 else if (saw_end_comments)
299 {
300 if (!strncmp(line, "%%Page:", 7))
301 {
89d46774 302 if (sscanf(line + 7, "%255s%d", page_label, &page_number) != 2 ||
303 page_number != (last_page_number + 1) || page_number < 1)
80ca4592 304 {
305 if (!status)
306 _cupsLangPuts(stdout, _("FAIL\n"));
307
308 status ++;
4d301e69 309 _cupsLangPrintf(stdout, _(" Bad %%%%Page: on line %d\n"
80ca4592 310 " REF: Page 53, %%%%Page:\n"),
311 linenum);
312 }
313 else
89d46774 314 {
315 last_page_number = page_number;
316 saw_page = 1;
317 }
80ca4592 318 }
319 else if (!strncmp(line, "%%BeginProlog", 13))
320 saw_begin_prolog = 1;
321 else if (!strncmp(line, "%%BeginSetup", 12))
322 saw_begin_setup = 1;
323 else if (!strncmp(line, "%%BeginDocument:", 16))
324 level ++;
325 else if (!strncmp(line, "%%EndDocument", 13))
326 level --;
327 else if (!strncmp(line, "%%Trailer", 9))
328 saw_trailer = 1;
329 }
330
331 for (i = 0; !binary && i < bytes; i ++)
332 {
333 ch = line[i];
334
335 if ((ch < ' ' || (ch & 0x80)) && ch != '\n' && ch != '\r' && ch != '\t')
336 binary = 1;
337 }
338 }
339
340 if (saw_bounding_box <= 0)
341 {
342 if (!status)
343 _cupsLangPuts(stdout, _("FAIL\n"));
344
345 status ++;
4d301e69 346 _cupsLangPuts(stdout, _(" Missing or bad %%BoundingBox: comment\n"
80ca4592 347 " REF: Page 39, %%BoundingBox:\n"));
348 }
349
350 if (saw_pages <= 0)
351 {
352 if (!status)
353 _cupsLangPuts(stdout, _("FAIL\n"));
354
355 status ++;
4d301e69 356 _cupsLangPuts(stdout, _(" Missing or bad %%Pages: comment\n"
80ca4592 357 " REF: Page 43, %%Pages:\n"));
358 }
359
360 if (!saw_end_comments)
361 {
362 if (!status)
363 _cupsLangPuts(stdout, _("FAIL\n"));
364
365 status ++;
4d301e69 366 _cupsLangPuts(stdout, _(" Missing %%EndComments comment\n"
80ca4592 367 " REF: Page 41, %%EndComments\n"));
368 }
369
370 if (!saw_page)
371 {
372 if (!status)
373 _cupsLangPuts(stdout, _("FAIL\n"));
374
375 status ++;
4d301e69 376 _cupsLangPuts(stdout, _(" Missing or bad %%Page: comments\n"
80ca4592 377 " REF: Page 53, %%Page:\n"));
378 }
379
380 if (level < 0)
381 {
382 if (!status)
383 _cupsLangPuts(stdout, _("FAIL\n"));
384
385 status ++;
4d301e69 386 _cupsLangPuts(stdout, _(" Too many %%EndDocument comments\n"));
80ca4592 387 }
388 else if (level > 0)
389 {
390 if (!status)
391 _cupsLangPuts(stdout, _("FAIL\n"));
392
393 status ++;
4d301e69 394 _cupsLangPuts(stdout, _(" Too many %%BeginDocument comments\n"));
80ca4592 395 }
396
397 if (saw_long_line > 1)
398 _cupsLangPrintf(stderr,
4d301e69 399 _(" Saw %d lines that exceeded 255 characters\n"),
80ca4592 400 saw_long_line);
401
402 if (!status)
403 _cupsLangPuts(stdout, _("PASS\n"));
404
405 if (binary)
4d301e69 406 _cupsLangPuts(stdout, _(" Warning: file contains binary data\n"));
80ca4592 407
408 if (version < 3.0f)
409 _cupsLangPrintf(stdout,
4d301e69 410 _(" Warning: obsolete DSC version %.1f in file\n"),
80ca4592 411 version);
412
413 if (saw_end_comments < 0)
4d301e69 414 _cupsLangPuts(stdout, _(" Warning: no %%EndComments comment in file\n"));
80ca4592 415
416 cupsFileClose(fp);
417
418 return (status);
419}
420
421
422/*
423 * 'usage()' - Show program usage.
424 */
425
426static void
427usage(void)
428{
429 _cupsLangPuts(stdout,
430 _("Usage: cupstestdsc [options] filename.ps [... filename.ps]\n"
431 " cupstestdsc [options] -\n"
432 "\n"
433 "Options:\n"
434 "\n"
435 " -h Show program usage\n"
436 "\n"
437 " Note: this program only validates the DSC comments, "
438 "not the PostScript itself.\n"));
439
440 exit(1);
441}
442
443
444/*
b19ccc9e 445 * End of "$Id: cupstestdsc.c 7720 2008-07-11 22:46:21Z mike $".
80ca4592 446 */