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