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