CAPS Universe documentation  1.0.4
All you need to know to be successful
Data Structures | Macros | Functions
libcapsppd-scanner.c File Reference

Scan PPD files for their options. More...

Data Structures

struct  ppd_file
 

Macros

#define BAD_CHAR   -25
 
#define LENGTH_OF_KEYWORD   45
 Length of a PPD 'main keyword'.
 
#define LENGTH_OF_NAME   45
 Length of a PPD 'option keyword'.
 
#define LENGTH_OF_DESCRIPTION   255
 Length of a PPD 'description' or 'translation' string.
 
#define LENGTH_OF_VALUE   4096
 Length of a PPD 'value'.
 

Functions

static bool is_a_line_end (int c)
 
static int skip_new_line (struct ppd_file *ppd_d, int c)
 
static int get_next_char (struct ppd_file *ppd_d)
 
static int print_length_error (struct ppd_file *ppd_d, const char *name, const unsigned char *string)
 
static int print_character_error (struct ppd_file *ppd_d, const char *name, int c)
 
static int mature_end_of_file (struct ppd_file *ppd_d, const char *name, int c)
 
static int mature_end_of_line (struct ppd_file *ppd_d, const char *name, int c)
 
static int append_char_to_string (unsigned char *dst, size_t sz, int c)
 
static int add_to_keyword (struct ppd_file *ppd_d, int c)
 
static int add_to_name (struct ppd_file *ppd_d, int c)
 
static int add_to_description (struct ppd_file *ppd_d, int c)
 
static int add_to_value (struct ppd_file *ppd_d, int c)
 
static void reset_input_strings (struct ppd_file *ppd_d)
 
static int read_comment (struct ppd_file *ppd_d)
 
static int read_keyword (struct ppd_file *ppd_d, int c)
 
static int skip_whitespace (struct ppd_file *ppd_d, int c)
 
static int read_name (struct ppd_file *ppd_d, int c)
 
static int read_description (struct ppd_file *ppd_d)
 
static int read_quoted_string (struct ppd_file *ppd_d, int quote)
 
static int read_value (struct ppd_file *ppd_d)
 
static int read_one_line (struct ppd_file *ppd_d, int c)
 
static int read_ppd_file (struct caps_ppd_options_table *pot, struct ppd_file *ppd_d)
 
static int open_ppd_file_for_read (struct ppd_file *ppd_d, const char *file_name)
 
static void close_ppd_file (struct ppd_file *ppd_d)
 
int caps_ppd_options_table_file_read (struct caps_ppd_options_table *pot, const char *ppd_file_name)
 

Detailed Description

This is a very simple scanner for PPD files. I started with different attempts to scan this kind of files. One attempt was to use FLEX to do the job. But the syntax used in PPD files is such simple and FLEX is a huge beast, so I decided to do it by myself.

Each line in a PPD file conforms to:

 *KEYWORD[ [*]NAME[/DESCRIPTION]]:[ ]VALUE

Refer: Adobe TechNote #5003: PostScript Printer Description File Format Specification Version 4.3

This technote defines our KEYWORD to "main keyword" and our NAME to "option keyword". This technote defines the length of each line is up to 255 chars including the newline char(s)

Some things are still to be discussed:

Todo:

Handle hex characters (e.g. "<[\t :digit:abcdefABCDEF]+>")

"Newlines may occur and should be ignored, except in translation strings, where they are illegal."

Handle "*?" keywords

Macro Definition Documentation

◆ BAD_CHAR

#define BAD_CHAR   -25
Note
The value must be different from EOF

◆ LENGTH_OF_KEYWORD

#define LENGTH_OF_KEYWORD   45

LENGTH_OF_KEYWORD

How long can be a 'keyword'? -> from the spec: 40 chars, CUPS limits it to 34 chars

◆ LENGTH_OF_NAME

#define LENGTH_OF_NAME   45

LENGTH_OF_NAME

How long can be a 'name'? -> from the spec: 40 chars, CUPS limits it to 34 chars

◆ LENGTH_OF_DESCRIPTION

#define LENGTH_OF_DESCRIPTION   255

LENGTH_OF_DESCRIPTION

Todo:
How long can be a 'description'?

◆ LENGTH_OF_VALUE

#define LENGTH_OF_VALUE   4096

LENGTH_OF_VALUE

Todo:
How long can be a 'value'? -> multi line!

Function Documentation

◆ is_a_line_end()

static bool is_a_line_end ( int  c)
static

Check if the character is one of the line end/line feed group

Parameters
[in]cThe character to check
Return values
trueThe character c is newline or carriage return
falseThe character c is something

◆ skip_new_line()

static int skip_new_line ( struct ppd_file ppd_d,
int  c 
)
static

Handle all kind of newline characters

Parameters
[in,out]ppd_dall info about the PPD
[in]ccurrent char from the stream
Returns
Correct char for the current file content

The spec forces us to handle all kind of \n and \r for newline.

  • \n one line
  • \r one line
  • \n\r one line
  • \r\n one line
  • \r\r two lines
  • \n\n two lines
Note
Inside a quoted text the newline replacement is disabled

◆ get_next_char()

static int get_next_char ( struct ppd_file ppd_d)
static

Read the next char from any kind of source

Parameters
[in,out]ppd_dall info about the PPD
Returns
The next 8 bit unsigned character as signed int

◆ print_length_error()

static int print_length_error ( struct ppd_file ppd_d,
const char *  name,
const unsigned char *  string 
)
static

◆ print_character_error()

static int print_character_error ( struct ppd_file ppd_d,
const char *  name,
int  c 
)
static

◆ mature_end_of_file()

static int mature_end_of_file ( struct ppd_file ppd_d,
const char *  name,
int  c 
)
static

◆ mature_end_of_line()

static int mature_end_of_line ( struct ppd_file ppd_d,
const char *  name,
int  c 
)
static

◆ append_char_to_string()

static int append_char_to_string ( unsigned char *  dst,
size_t  sz,
int  c 
)
static

◆ add_to_keyword()

static int add_to_keyword ( struct ppd_file ppd_d,
int  c 
)
static

◆ add_to_name()

static int add_to_name ( struct ppd_file ppd_d,
int  c 
)
static

◆ add_to_description()

static int add_to_description ( struct ppd_file ppd_d,
int  c 
)
static

◆ add_to_value()

static int add_to_value ( struct ppd_file ppd_d,
int  c 
)
static

◆ reset_input_strings()

static void reset_input_strings ( struct ppd_file ppd_d)
static

◆ read_comment()

static int read_comment ( struct ppd_file ppd_d)
static

Read a comment line up to its end (line terminator)

Parameters
[in,out]ppd_dall info about the PPD
Returns
the last char not part of the comment

◆ read_keyword()

static int read_keyword ( struct ppd_file ppd_d,
int  c 
)
static

Read a keyword up to its terminator

Parameters
[in,out]ppd_dall info about the PPD
[in]cThe keyword's start character
Returns
The last character not part of the keyword

Delimiters are:

  • whitespace
  • colon

From the spec:

‍Main keywords can contain any printable ASCII characters within the range of decimal 33 to decimal 126 inclusive, excluding colon and slash.

Delimiters for main keywords are space, tab, colon, or newline. After the initial '*' symbol is recognized, all characters through (but not including) the next space, tab, colon, or newline character are considered part of the main keyword.

◆ skip_whitespace()

static int skip_whitespace ( struct ppd_file ppd_d,
int  c 
)
static

◆ read_name()

static int read_name ( struct ppd_file ppd_d,
int  c 
)
static

Read the 'name' component up to its terminator

Parameters
[in,out]ppd_dall info about the current job
cthe first char from name
Returns
the last char not part of the name

Terminators are:

  • slash
  • colon

From the spec:

‍Option keywords may contain any printable ASCII characters within the range of decimal 33 to decimal 126 inclusive, except for the characters slash and colon, which serve as keyword delimiters. Note that space, tab, and new- line are outside this range.

An option keyword is terminated by a colon or a slash if there is a translation string

◆ read_description()

static int read_description ( struct ppd_file ppd_d)
static

Read a description up to its terminator

Parameters
[in,out]ppd_dall info about the PPD
Returns
The last char not part of the description

Terminators are:

  • colon

From the spec:

‍[...] White space and slashes are allowed in the translation string. A newline encountered before the colon should be considered as an error.

◆ read_quoted_string()

static int read_quoted_string ( struct ppd_file ppd_d,
int  quote 
)
static

Read a quoted value entry

Parameters
[in,out]ppd_dall info about the PPD
[in]quotequote character to define the end of the string
Returns
Last char read or BAD_CHAR in case of a bad value string

Allowed characters for 'value' are

  • 0x20...0x7e printable ASCII characters
  • 0xa0...0xff FIXME??? Not 0x80...0xff???
  • '"' terminates the string
  • EOF is an failure
    Todo:
    Should a '\n' be part of the resulting string or be skipped?

From the spec:

‍Everything between the double quotes is treated as literal; that is, newlines and hexadecimal substrings are allowed and are placed in the output file to be passed on to the interpreter. Note that, unlike other values, a newline does not terminate an InvocationValue and a slash does not mark the beginning of a translation string.

[...] byte codes outside the range of printable 7-bit ASCII [are forbidden] <- InvocationValue

Issue: two types of double quoted values are possible: InvocationValue or QuotedValue Both handle their characters differently.

For QuotedValue the newline is not part of the resulting string. And all characters are allowed.

Todo:
Fix line counting here!

◆ read_value()

static int read_value ( struct ppd_file ppd_d)
static

Read a non-quoted value entry

Parameters
[in,out]ppd_dall info about the PPD
Return values
valueLast char read
BAD_CHARIn case of a bad value string

Allowed characters for value are

  • 0x20...0x7e printable ASCII characters
  • 0xa0...0xff FIXME???

'\n' terminates the string

◆ read_one_line()

static int read_one_line ( struct ppd_file ppd_d,
int  c 
)
static

Read in a whole line of text (e.g. all components from the line)

Parameters
[in,out]ppd_dall info about the PPD
[in]cchar
Return values
valueLast char read
BAD_CHARIn case of a bad value string

◆ read_ppd_file()

static int read_ppd_file ( struct caps_ppd_options_table pot,
struct ppd_file ppd_d 
)
static

Read in a whole PPD file in

Parameters
[in,out]potwhere to add the options read
[in,out]ppd_dall info about the PPD
Return values
0in case of success
BAD_CHARIn case of a bad value string
Todo:
Count the various line terminations only once per line

◆ open_ppd_file_for_read()

static int open_ppd_file_for_read ( struct ppd_file ppd_d,
const char *  file_name 
)
static

◆ close_ppd_file()

static void close_ppd_file ( struct ppd_file ppd_d)
static