Parse an object read from PPS


#include <ppsparse.h>

extern pps_status_t ppsparse( char **ppsdata,
                              const char * const *objnames,
                              const char * const *attrnames,
                              pps_attrib_t *info,
                              int parse_flags );


A pointer to a pointer to the current position in the buffer of PPS data. The function updates this pointer as it parses the options; see the Description below.
A pointer to a NULL-terminated array of object names. If this value is not NULL, ppsparse() looks up any object name it finds and provides its index in the pps_attrib_t structure.
A pointer to a NULL-terminated array of attribute names. If this value is not NULL, ppsparse() looks up any attribute name it finds and provides its index in the pps_attrib_t structure.
A pointer to the data structure pps_attrib_t, which carries detailed about a line of PPS data.
Reserved for future use.




The function ppsparse() parses the next line of a buffer of PPS data. This buffer must be terminated by a null (“\0” in C, or hexadecimal 0x00).

The first time you call this function after reading PPS data, you should set ppsdata to reference the start of the buffer with the data. As it parses each line of data, ppsparse():

When it successfully completes parsing a line, ppsparse() returns the type of line parsed, or end of data; see pps_status_t below.


typedef struct {
    char *obj_name;
    int  obj_index;
    char *attr_name;
    int  attr_index;
    char *encoding;
    char *value;
    int  flags;
    int  options;
    int  option_mask;
    int  quality;
    char *line;
    int  reserved[3];
} pps_attrib_t;

The pps_attrib_t data structure carries parsed PPS object and attribute information. It includes the members described in the table below:

Member Type Description
obj_name char A pointer to the name of the last PPS object encountered. ppsparse() sets this pointer only if it encounters a PPS object name. You should initialize this pointer before calling ppsparse().
obj_index int The index for obj_name in the objnames array. It is set to -1 if the index is not found or objnames is NULL. You should initialize this value before calling ppsparse().
attr_name char A pointer to the name of the attribute from the line PPS data that ppsparse() just parsed. It is set to NULL if no attribute name was found.
attr_index int The index for attrj_name in the attrnames array. It is set to -1 if the index is not found or attrnames is NULL.
encoding char A pointer to a string that indicates the encoding used for the PPS attribute. See Attributes in the chapter PPS Objects and Attributes.
This value is only relevant if the ppsparse() return value is PPS_ATTRIBUTE. See pps_status_t below.
value char A pointer to the value of a PPS attribute.
This value is only relevant if the ppsparse() return value is PPS_ATTRIBUTE. See pps_status_t below.
flags int Flags indicating that parsing has found a PPS special character prefixed to a line, or that the line is incomplete. See pps_attrib_flags_t below.
options int Indicates which non-negated options are prefixed in square brackets to a line. See Object and attribute options in the chapter Options.
option_mask int A mask of the options (both negated and non-negated) prefixed to a line. See pps_options_t below.
quality int Not used.
line char Pointer to the beginning of the line parsed by ppsparse(), for use in case of a parsing error.
reserved[3] int For internal use.


The enumerated values PPS_* defined by pps_attrib_flags_t define the possible states for PPS objects and attributes. These states include:

See also Change notification in the chapter PPS Objects.


The enumerated values PPS_NOPERSIST defined by pps_options_t define values for PPS options:


The enumerated values PPS_* defined by pps_status_t define the possible ppsparse() return values. These values include:


The ppsparse() function returns:

An error occured (errno is set).


The following test application shows how ppsparse() can be used:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// Test data to use if a file name is not provided as a command line argument.
// This data may be read-only in code space, so we copy it.
char *testdata =
    "title::Money money1\n"
    "author:c:Money money2\n"
    "[n]title::Nopersist option\n"
    "[-n]title::Negated option\n"
    "[-xnp]time:c:Unknown options\n"
    "badattr:Improperly formatted\n"
    "title::Money money4\n"
    "Just some garbage\n"
    "[n]+newAttr:abc:New attribute\n" // New attribute (not currently used by pps)
    "+newAttr\n"                      // New attribute, missing encoding etc
    "-deleteAttr::\n"                 // Deleted attribute with encoding etc
    "-deleteAttr\n"                   // Deleted attribute without encoding etc
    "-@unidentified\n"                // Deleted object
    "#@unidentified\n"                // Truncated object
    "[i]flags::flg1,\n"               // Item flag
    "[-i]flags::flg1,\n"              // Negated item flag
    "[7n]quality::qualityAttribute\n" // Attribute with quality setting
    "Incomplete line"

main(int argc, char *argv[])
    enum {
    static const char *const attrs[] ={
        [ATTR_AUTHOR] = "author",
        [ATTR_TITLE]  = "title",
        [ATTR_TIME]   = "time",
        [LAST_ATTR]   = NULL
    enum {
    static const char *const objs[] = {
        [OBJECT_BOOK] = "@book",
        [OBJECT_FILM] = "@film",
        [OBJECT_SONG] = "@song",
        [LAST_OBJECT] = NULL

    char buffer[1024];
    char  *ppsdata = buffer;
    int fd = -1;
    pps_attrib_t info;
    pps_status_t rc;
    int lineno = 0;

    if ( argc > 1 ) {
        fd = open(argv[1], O_RDONLY);
        if ( fd < 0 ) {
    else {
        strcpy(buffer, testdata);
    memset(&info, 0, sizeof(info));

    while ( ppsdata != NULL ) {
        if ( fd >= 0 ) {
            int n = read(fd, ppsdata, sizeof(buffer) - (ppsdata - buffer) - 1);
            if ( n <= 0 ) {
            ppsdata[n] = '\0';
            ppsdata = buffer;
        while ( (rc = ppsparse(&ppsdata, objs, attrs, &info, 0)) ) {
            printf("%d ---------------------------\n%s  ",++lineno,
                   rc == PPS_ERROR ? "PPS_ERROR" :
                   rc == PPS_END ? "PPS_END" :
                   rc == PPS_OBJECT ? "PPS_OBJECT" :
                   rc == PPS_OBJECT_CREATED ? "PPS_OBJECT_CREATED" :
                   rc == PPS_OBJECT_DELETED ? "PPS_OBJECT_DELETED" :
                   rc == PPS_OBJECT_TRUNCATED ? "PPS_OBJECT_TRUNCATED" :
                   rc == PPS_ATTRIBUTE ? "PPS_ATTRIBUTE" :
                   rc == PPS_ATTRIBUTE_DELETED ? "PPS_ATTRIBUTE_DELETED" : "?");
            if ( info.flags ) {
                printf("flags:%s%s%s%s%s  ",
                       info.flags & PPS_INCOMPLETE ? "inc" : "",
                       info.flags & PPS_CREATED ? "+" : "",
                       info.flags & PPS_DELETED ? "-" : "",
                       info.flags & PPS_TRUNCATED ? "#" : "",
                       info.flags & PPS_PURGED ? "*" : "");
            if ( info.options || info.option_mask ) {
                printf("options:%s%s  mask:%s%s  ",
                       info.options & PPS_NOPERSIST ? "n" : "",
                       info.options & PPS_ITEM ? "i" : "",
                       info.option_mask & PPS_NOPERSIST ? "n" : "",
                       info.option_mask & PPS_ITEM ? "i" : "");
            printf("object:%s (%d)  ",info.obj_name ? info.obj_name : "NULL",
            if ( rc == PPS_ATTRIBUTE || rc == PPS_OBJECT_DELETED ) {
                printf("attr:%s (%d)  ",
                       info.attr_name ? info.attr_name : "NULL", info.attr_index);
                if ( rc == PPS_ATTRIBUTE  ) {
                    printf("quality:%d  encoding:%s  value:%s",info.quality,
                           info.encoding, info.value);

            // now put everything back so we can print out the line.
            if ( info.encoding )
                info.encoding[-1] = ':';
            if ( info.value )
                info.value[-1] = ':';
        if ( fd >= 0 ) {
            // Note: When reading directly from PPS, you don't need to deal
            // with the PPS_INCOMPLETE flag. It is needed only to allow
            // parsing of PPS data where the data is not provided in complete
            // lines.  In this case, the partial line is moved to the beginning
            // of the buffer, more data is read and the parsing is attempted again.
            if ( info.flags & PPS_INCOMPLETE ) {
                memmove(buffer, info.line, ppsdata - info.line);
                ppsdata = buffer + (ppsdata - info.line);
            else {
                ppsdata = buffer;
        else {
            ppsdata = NULL;

    return 0;




Interrupt handler Yes
Signal handler Yes
Thread Yes


During parsing, separators (“:” and “\n”) in the input string may be changed to null characters.

See also:

The rest of the QNX PPS Developer's Guide.