void FuncSet2::triggerFunc()
{
    if(brd == NULL) {
        safePrint(paper, "brd is NULL\n");
        return;
    }

    vector< pair<int,int> > ans;
    safePrint(paper, "Type\tGainSquare\tCostSquares\n");
    int winValue = threatSpaceSearch(brd, turn, ans, paper);
    if(paper == NULL) return;
    paper->print("\n%s %s\n",
                 (turn==BLACK)?"BLACK":"WHITE",
                 (winValue==WIN)?"WIN":"NOWIN");
    paper->print("threat seq = ");
    for(int i=0; i<ans.size(); i++)
        paper->print("(%d,%d) ", ans[i].first, ans[i].second);
    paper->print("\n\n");
    paper->changeColor();
    paper->moveCusorToTheEnd();
}
void FuncSet4::triggerFunc()
{    
    if(brd == NULL) {
        safePrint(paper, "brd is NULL\n");
        return;
    }

    if(root!=NULL) root->~QTreeWidgetItem();
    root = new QTreeWidgetItem();
    pnSearchTree.addTopLevelItem(root);

    pair<int,int> *ans = new pair<int,int>();
    pnsNode *rootNode;
    int winValue = getTruthByPNS(brd, turn, turnTobeProved, true, ans, NULL, &rootNode);
    buildTreeWidgetItem(rootNode, root);
    //printTreePnDn(rootNode, paper);

    if(paper == NULL) return;
    paper->print("winValue = %s\n", (winValue==WIN)?"WIN":"NOWIN");
    paper->print("(x,y) = (%d,%d)\n", ans->first, ans->second);
    paper->changeColor();
    paper->moveCusorToTheEnd();
}
void printWinningTree(pnsNode *node, Paper *paper)
{
    if(paper == NULL) return;
    safePrint(paper, "%d,%d ", node->x, node->y);
    safePrint(paper, "(");

    int flag = 0;
    for(uint i=0; i<node->actualChildren.size();i++)
        if(node->actualChildren[i]->pn==0){
            flag = 1;
            printWinningTree( node->actualChildren[i], paper);
        }
    if(flag == 0){
        if( node->actualChildren.size() == 0 ){
            safePrint(paper, "<< ");
            for(int i=0; i<node->winningSeq.size(); i++)
                safePrint(paper, "%d,%d ", node->winningSeq[i].first, node->winningSeq[i].second);
            safePrint(paper, ">>");
        }else err(false, "printWinningTree(): cant find the next winning step, should be an error in pnSearch");
    }
    safePrint(paper, ")");
}
int
getTruthByPNS(
        BoardData *brd,
        int turn,
        int turnToBeProved,
        bool runTSS,          // if is true => run TSS => need ans
        pair<int,int> *ans,
        Paper *paper,
        pnsNode** rootNode)
{
    if(runTSS) safePrint(paper, "\n######################################\n");
    else safePrint(paper, "\n..............¡õpnSearch(%d,%d)...............\n",turn,turnToBeProved);

    pnsNode *root = new pnsNode(new BoardData(brd), turn);
    if(rootNode!=NULL) *rootNode = root;
    pnsNode *fakeRoot;
    if(turn==turnToBeProved)
        fakeRoot=root;
    else {
        fakeRoot = new pnsNode(new BoardData(brd), turnToBeProved);
        root->parent = fakeRoot;
        fakeRoot->actualChildren.push_back(root);
    }
    // most-proving-node
    pnsNode *mpn = root;
    int cnt=0;
    // (pn==0 || dn==0) means the result has been found
    while( root->pn!=0 && root->dn!=0 ){
        if( runTSS==false ) {
            if(cnt>maxLoopCnt){
                root->pn=PNS_INFINITY;
                root->dn=0;
                break;
            }else cnt++;
        }
        mpn = proofNumberSearch(mpn, turnToBeProved, runTSS, paper);
        //if( mpn==NULL ) mpn = root;

        mpn=root;
#ifdef PRINT_PNSEARCH_DETAIL
        printTreePnDn(root, paper);
        safePrint(paper, "\n");
#endif
    }

    // if tss is included => overall pns => need an answer
    if(runTSS && root->pn==0){
        // find the answer (one step)
        int flag = 0;
        for(uint i=0; i<root->actualChildren.size();i++)
            if(root->actualChildren[i]->pn==0){
                flag = 1;
                //ans = & (make_pair(root->actualChildren[i]->x, root->actualChildren[i]->y) );
                //ans = new pair<int,int>(make_pair(root->actualChildren[i]->x, root->actualChildren[i]->y) );
                //safePrint(paper, " (%d,%d)\n", ans->first, ans->second);
                if(ans==NULL) err(true, "in proofNumberSearch(), ans should not be NULL");
                ans->first = root->actualChildren[i]->x;
                ans->second = root->actualChildren[i]->y;
            }
        if(flag == 0){
            if( root->actualChildren.size() == 0 ){
                //ans = & (make_pair(root->winningSeq[0].first, root->winningSeq[0].second) );
                //ans = new pair<int,int>(make_pair(root->winningSeq[0].first, root->winningSeq[0].second) );
                //safePrint(paper, " (%d,%d)\n", ans->first, ans->second);
                if(ans==NULL) err(true, "in proofNumberSearch(), ans should not be NULL");
                if(root->winningSeq.size()==0) err(true, "getTruthByPNS(): root->winningSeq.Size==0, should be an error in pnSearch");
                ans->first = root->winningSeq[0].first;
                ans->second = root->winningSeq[0].second;
            }else err(false, "getTruthByPNS(): cant find the next winning step, should be an error in pnSearch");
        }
    }
    // print result
    //brd->printBoard();
    safePrint(paper, "turn = %d, pnSearchResult = %s \n", turn, (root->pn==0)? "WIN" : "LOSE");
    if(root->pn == 0) printWinningTree(root, paper); // if WIN, print win seq
    safePrint(paper, "\n");
    if(runTSS) safePrint(paper, "######################################\n");
    else safePrint(paper, "..............¡ôpnSearch...............\n");

    return ( (root->pn==0)? (WIN) : (NOWIN) );
}
pnsNode* proofNumberSearch(pnsNode *node, int rootTurn, bool runTSS, Paper *paper)
{
    if(node==NULL) err(true, "proofNumberSearch() parameter value error: [node] shouldn't be NULL.");

    /***************************************************
     * virtualChildren is empty : node is a leaf (a temp terminal node)
     ***************************************************/
    if(node->virtualChildren.size()==0 && node->actualChildren.size() ==0)
    {
        if(node->pn!=1 || node->dn!=1) err(true, "proofNumberSearch(): terminal pnsNode pn/dn value error");

        // different action varies by "runTSS"
        int winValue = NOWIN;
        if(runTSS){
            // run evaluation function, record the winning seq found by threatSpaceSearch
            winValue = threatSpaceSearch(node->brd, node->turn, node->winningSeq, paper);
            if(g_pnAgain==0 && winValue!=WIN && node->turn == opposite(rootTurn) ){
                pair<int, int> ans;
                g_pnAgain=1;
                int tmpWinValue = getTruthByPNS(node->brd, node->turn, opposite(node->turn), true, &ans);
                g_pnAgain=0;
                if(tmpWinValue==WIN) winValue = LOSE;
            }
        }else {
            // find all (turn)'s threats which are bigger than opn
            Threat *opn = findMaxThreat( node->brd, opposite(node->turn), false );
            vector< Threat* > my = findAllThreat(node->brd, node->turn, true, opn);
#ifdef PRINT_PNSEARCH_DETAIL
            safePrint(paper, ">>>>>>>>>>>>>>>>>>>\n");
            if(opn!=NULL) opn->printThreat(paper);
            if(my.size()!=0) my[0]->printThreat(paper);
            safePrint(paper, ">>>>>>>>>>>>>>>>>>>\n");
#endif
            if(my.size()!=0 && (my[0]->type==Five || my[0]->type==StrF) )winValue=WIN;
            else winValue=NOWIN;
        }

        if( winValue == WIN ){
            // find WIN => this node is a real terminal node
            if(node->turn == rootTurn){
                node->pn = 0;
                node->dn = PNS_INFINITY;
            }else{
                node->pn = PNS_INFINITY;
                node->dn = 0;
            }
#ifdef PNSTEST
            safePrint(paper, "=> WIN,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn);
#endif
            // pn/dn has changed,
            // update parents' pn/dn ( 1 = the original pn/dn value )
            // and return new most-proving-node
            return updatePnDn(node, 1, 1, rootTurn);;
        }else if(winValue == LOSE){
            // means that node->turn is lost
            if(node->turn == rootTurn){
                node->pn = PNS_INFINITY;
                node->dn = 0;
            }else{
                node->pn = 0;
                node->dn = PNS_INFINITY;
            }
            // pn/dn has changed,
            // update parents' pn/dn ( 1 = the original pn/dn value )
            // and return new most-proving-node
#ifdef PNSTEST
            printf("=> LOSE,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn);
#endif
            return updatePnDn(node, 1, 1, rootTurn);
        }else{
            // => this node is not a real terminal node => expand its virtualChildren
            node->virtualChildren = availableMove(node->brd, node->turn);
            /*******************************************************
             * for faster: rootTurn's cut
             * cut children to only squares who form threat
             * ****************************************************/
            /*
            if(node->turn == rootTurn){
                vector< pair<int,int> > threatList=attackMove(node->brd,node->turn);
                if(threatList.size()!=0) node->virtualChildren = threatList;
            }*/
            /*******************************************************/
            if(node->virtualChildren.size()==0){
                // means that node->turn has no move, is lost
                if(node->turn == rootTurn){
                    node->pn = PNS_INFINITY;
                    node->dn = 0;
                }else{
                    node->pn = 0;
                    node->dn = PNS_INFINITY;
                }
                // pn/dn has changed,
                // update parents' pn/dn ( 1 = the original pn/dn value )
                // and return new most-proving-node
#ifdef PNSTEST
                safePrint(paper, "=> LOSE,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn);
#endif
                return updatePnDn(node, 1, 1, rootTurn);
            }else if(node->turn == rootTurn){
                /****** max node ******/
                // pn = min( all child.pn ) = 1 == original node->pn
                // dn = sum( all child.dn )
                node->dn = node->virtualChildren.size();
#ifdef PNSTEST
                safePrint(paper, "=> leaf,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn);
#endif
                // both pn/dn hasn't changed, most-proving-node is still under this tree
                if( node->dn==1 ) return node;
                else {
                    // dn has changed, (pn hasn't)
                    // update parents' dn ( 1 = the original dn value )
                    // and return new most-proving-node
                    return updatePnDn(node, 1, 1, rootTurn);
                }
            }else{
                /****** min node ******/
                // dn = min( all child.dn ) = 1 == original node->dn
                // pn = sum( all child.pn )
                node->pn = node->virtualChildren.size();
#ifdef PNSTEST
                safePrint(paper, "=> leaf,%d,(%d,%d),<%d,%d>\n", opposite(node->turn), node->x, node->y, node->pn, node->dn);
#endif
                // both pn/dn hasn't changed, most-proving-node is still under this tree
                if( node->pn==1 ) return node;
                else {
                    // pn has changed,
                    // update parents' pn ( 1 = the original pn value )
                    // and return new most-proving-node
                    return updatePnDn(node, 1, 1, rootTurn);
                }
            }
        }
    }


    /***************************************************
     * node is an internal node
     ***************************************************/
    pnsNode *successor = NULL;
    if( node->actualChildren.size()!=0 )
        // the actualChildren in the end of actualChildren[] has min pn/dn
        successor = node->actualChildren[ node->actualChildren.size()-1 ];
    if( successor==NULL ||  //actualChildren.size()==0
            // in max node, the child who has min pn is the successor
            ( node->turn==rootTurn && successor->pn!=node->pn ) ||
            // in min node, the child who has min dn is the successor
            ( node->turn==opposite(rootTurn) && successor->dn!=node->dn ) )
    {
        if( node->virtualChildren.size() == 0 )
            err(true, "proofNumberSearch(): can't find any successor at the node");
        successor = new pnsNode(node, node->virtualChildren.back() );
        node->actualChildren.push_back(successor);
        node->virtualChildren.pop_back();
    }

#ifdef PNSTEST
    safePrint(paper, "=> %d,(%d,%d),<%d,%d> ", opposite(node->turn), node->x, node->y, node->pn, node->dn);
#endif
    return proofNumberSearch(successor, rootTurn, runTSS, paper);

}
Example #6
0
size_t parsePdfObj( size_t startPos, uint8_t *buf, size_t endPos, int dataType, struct pdfObject *curObjPtr ) {
  size_t curPos = startPos, bufOffset = 0, sPos;
  uint8_t tmpByte = 0, status = 0, *destBuf;
  int offset = 0, objNum = 0, objRev = 0, count = 0, getNum = 0, i;
  char tmpStr[1024];
  char tmpBuf[4096];
  struct pdfObject *tmpObjPtr;

  /*
   * parse this object
   */

  if ( config->verbose )
    printf( ">> %lu/%lu [%s]\n", startPos, endPos, typeStrings[dataType] );

  /*
   * loop until we are at the end
   */

  while ( curPos < endPos ) {
    if ( dataType EQ PDF_TYPE_NONE ) {
#ifdef DEBUG
      if ( config->debug >= 5 )
	hexDump( curPos, buf+curPos, 64 );
#endif
      if ( buf[curPos] EQ ' ' | buf[curPos] EQ '\r' | buf[curPos] EQ '\n' | buf[curPos] EQ '\t' ) {
	/* white space */
	curPos++;
      } else if ( buf[curPos] EQ '<' ) {
	if ( buf[curPos+1] EQ '<' ) { /* dictionary */
	  curPos+=2;
	  if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	    return FAILED;
	  }
	  curObjPtr->type = PDF_TYPE_DICTIONARY;
	  curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_DICTIONARY, curObjPtr );
	} else { /* hex string */
	  curPos++;
	  if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	    return FAILED;
	  }
	  curObjPtr->type = PDF_TYPE_HEXSTRING; 
	  curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_HEXSTRING, curObjPtr );
	}
      } else if ( buf[curPos] EQ '(' ) { /* string */
	curPos++;
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_STRING; 
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_STRING, curObjPtr );
      } else if ( buf[curPos] EQ '/' ) { /* label */
	curPos++;
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_NAME; 
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NAME, curObjPtr );
      } else if ( buf[curPos] EQ '[' ) {
	/* array */
	curPos++;
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_ARRAY; 
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_ARRAY, curObjPtr );
      } else if ( sscanf( buf+curPos, "%d %d %n%s", &objNum, &objRev, &offset, tmpStr ) EQ 3 ) { /* named object */
	if ( strncmp( tmpStr, "obj", 3 ) EQ 0 ) {
	  printf( "Object: %d %d\n", objNum, objRev );
	  curPos += ( offset + 3 );
	  if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	    return FAILED;
	  }
	  curObjPtr->type = PDF_TYPE_OBJECT;
	  curObjPtr->num = objNum;
	  curObjPtr->gen = objRev;
	  curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_OBJECT, curObjPtr );
	} else if ( tmpStr[0] EQ 'R' ) {
	  printf( "ObjRef: %d %d\n", objNum, objRev );
	  curPos += ( offset + 1 );
	  if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	    return FAILED;
	  }
	  curObjPtr->type = PDF_TYPE_REFERENCE;
	  curObjPtr->num = objNum;
	  curObjPtr->gen = objRev;
	  curObjPtr = curObjPtr->parent;
	  /* once we have loaded all objects, we will link all references to their real objects */
	} else {
	  if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	    return FAILED;
	  }
	  curObjPtr->type = PDF_TYPE_INTNUM;
	  curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_INTNUM, curObjPtr );
	}
      } else if ( isdigit( buf[curPos] ) || ( buf[curPos] EQ '-' ) || ( buf[curPos] EQ '+' ) ) { /* number */
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_INTNUM;
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_INTNUM, curObjPtr );
      } else if ( ( buf[curPos] EQ 't' ) || ( buf[curPos] EQ 'f' ) ) { /* boolean number */
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_BOOL;
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_BOOL, curObjPtr );
      } else if ( buf[curPos] EQ '%' ) { /* comment */
	curPos++;
        /* check if this is EOF */
        if ( strncmp( buf+curPos, "%EOF\n", 5 ) EQ 0 ) {
            curPos += 5;
            printf( "EOF\n" );
            curObjPtr->type = PDF_TYPE_EOF;
            curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_EOF, curObjPtr );

        } else {
            if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
                return FAILED;
            }
            curObjPtr->type = PDF_TYPE_COMMENT;
            curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_COMMENT, curObjPtr );
        }
      } else if ( strncmp( buf+curPos, "stream", 6 ) EQ 0 ) { /* stream */
	curPos += 6;
	if ( buf[curPos] EQ '\r' )
	  curPos++;
	if ( buf[curPos] EQ '\n' )
	  curPos++;
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_STREAM;
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_STREAM, curObjPtr );
      } else if ( strncmp( buf+curPos, "obj", 3 ) EQ 0 ) {
	/* object */
	curPos += 3;
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_OBJECT;
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_OBJECT, curObjPtr );
      } else if ( strncmp( buf+curPos, "xref", 4 ) EQ 0 ) {
          
	/* start of footer */
	curPos += 4;
	if ( ( curObjPtr = insertPdfObject( curObjPtr ) ) EQ NULL ) {
	  return FAILED;
	}
	curObjPtr->type = PDF_TYPE_FOOTER;
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_FOOTER, curObjPtr );
        
      } else if ( strncmp( buf+curPos, "startxref", 9 ) EQ 0 ) {
        curPos += 9;  
        curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr );
      } else if ( strncmp( buf+curPos, "endobj", 6 ) EQ 0 ) {
	return( curPos );

      } else if ( buf[curPos] EQ ']' ) {
	return( curPos );

      } else if ( strncmp( buf+curPos, ">>", 2 ) EQ 0 ) {
	return( curPos );

      } else if ( buf[curPos] EQ '>' ) {
	return( curPos );

      } else {
          if ( isprint( buf[curPos] ) )
              printf( "%c", buf[curPos] );
          else
              printf( "." );
	curPos++;
      }
    } else if ( dataType EQ PDF_TYPE_EOF ) {
        /* all data after EOF is suspect */
	if ( config->write ) {
	  writeStream( curPos, buf+curPos, endPos - curPos );
	} else
	  hexDump( curPos, buf+curPos, endPos - curPos );
        curPos = endPos;
    } else if ( dataType EQ PDF_TYPE_REALNUM ) {
      /* 3.4 = realNum */
      sPos = curPos;
      if ( ( buf[curPos] EQ '-' ) || ( buf[curPos] EQ '+' ) ) {
	tmpStr[curPos-sPos] = buf[curPos];
	curPos++;
      }
      while( isdigit( buf[curPos] ) || buf[curPos] EQ '.' ) {
	tmpStr[curPos-sPos] = buf[curPos];
	curPos++;
      }
      tmpStr[curPos-sPos] = '\0';
      printf( "Real Number: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_INTNUM ) {
      /* 343 = intNum */
      sPos = curPos;

      if ( ( buf[curPos] EQ '-' ) || ( buf[curPos] EQ '+' ) )
	curPos++;

      while( ( isdigit( buf[curPos] ) ) || ( buf[curPos] EQ '.' ) ) {
	if ( buf[curPos] EQ '.' ) {
	  curObjPtr->type = PDF_TYPE_REALNUM;
	  return parsePdfObj( sPos, buf, endPos, PDF_TYPE_REALNUM, curObjPtr );
	}
	curPos++;
      }
      printf( "Integer: %d\n", atoi( buf+sPos ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_BOOL ) {
      /* true | false = bool */

      if ( strncmp( buf+curPos, "true", 4 ) EQ 0 ) {
	/* true */
	printf( "Boolean: true\n" );
	curPos += 4;
      } else if ( strncmp( buf+curPos, "false", 5 ) EQ 0 ) {
	/* false */
	printf( "Boolean: false\n" );
	curPos += 5;
      } else
	curPos++;
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_EOL ) {
      /* \n\r | \n | \n\r\n\r = EOL */
      while( ( buf[curPos] EQ '\n' ) || ( buf[curPos] EQ '\r' ) ) {
	curPos++;
      }
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_COMMENT ) {
      /* % ... EOL = comment */
      sPos = curPos;
      while( ( buf[curPos] != '\r' ) && ( buf[curPos] != '\n' ) ) {
	tmpStr[curPos-sPos] = buf[curPos];
	curPos++;
      }
      tmpStr[curPos-sPos] = '\0';
      printf( "Comment: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_NAME ) {
      /* / ... = name */
      sPos = curPos;
      while( ( buf[curPos] != '\r' ) &&
	     ( buf[curPos] != '\n' ) &&
	     ( buf[curPos] != ' ' ) &&
	     ( buf[curPos] != '[' ) &&
	     ( buf[curPos] != '<' ) &&
	     ( buf[curPos] != '/' ) &&
	     ( buf[curPos] != '(' ) &&
	     ( buf[curPos] != '>' ) &&
	     ( buf[curPos] != ']' ) &&
	     ( buf[curPos] != ')' ) ) {
	/* process label */
	tmpStr[curPos-sPos] = buf[curPos];
	curPos++;
      }
      tmpStr[curPos-sPos] = '\0';
      printf( "Name: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_STRING ) {
      /* ( ... ) = literalString */
      /* XXX add octal notation '\000' */
      /* XXX handle escaped characters */
      while( buf[curPos] EQ ' ' ) {
	curPos++;
      }
      sPos = curPos;
      if ( strncmp( buf+curPos, "254 255", 7 ) EQ 0 ) {
	curObjPtr->type = PDF_TYPE_UTFSTRING;
	return parsePdfObj( curPos, buf, endPos, PDF_TYPE_UTFSTRING, curObjPtr );
      } else if ( ( buf[curPos] EQ 'D' ) && ( buf[curPos+1] EQ ':' ) ) {
	curObjPtr->type = PDF_TYPE_DATESTRING;
	return parsePdfObj( curPos, buf, endPos, PDF_TYPE_DATESTRING, curObjPtr );
      }

      while( buf[curPos] != ')' ) {
	tmpStr[curPos-sPos] = buf[curPos];
	curPos++;
      }
      tmpStr[curPos-sPos] = '\0';
      printf( "String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos + 1 );

    } else if ( dataType EQ PDF_TYPE_UTFSTRING ) {
      /* ( 254 255 ... ) = utf encoded literal string */
      while( sscanf( buf+curPos, "%u%n", (unsigned int *)&tmpByte, &offset ) EQ 1 ) {
	curPos += offset;
	if ( buf[curPos] EQ ' ' ) {
	  curPos++;
	}
      }
      while( buf[curPos] != ')' ) {
	curPos++;
      }
      curPos++;
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_DATESTRING ) {
      sPos = curPos;
      /* (D:YYYYMMDDHHmmSSOHH'mm') = date encoded literal string */
      while( buf[curPos] != ')' ) {
	tmpStr[curPos-sPos] = buf[curPos];
	curPos++;
      }
      curPos++;
      tmpStr[curPos-sPos] = '\0';
      printf( "Date String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_HEXSTRING ) {
      /* < ... > = hexString */
      count = 0;
      sPos = curPos;
      while( buf[curPos] != '>' ) {
	if ( isxdigit( buf[curPos] ) )
	  tmpStr[count++] = buf[curPos];
	curPos++;
      }
      /* append a zero is the string length is odd */
      if ( !( count % 2 ) EQ 0 ) {
	tmpStr[count++] = '0';
      }
      tmpStr[count] = '\0';
      curPos++;
      printf( "HEX String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      for( i = 0, offset = 0; i < count; i += 2 ) {
	tmpStr[offset++] = xtoi( tmpStr+i, 2 );
      }
      hexDump( 0, tmpStr, offset );
      printf( "HEX String: %s\n", safePrint( tmpBuf, sizeof( tmpBuf ), tmpStr ) );
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_UTFHEXSTRING ) {
      /* < fe ff ... > = utf encoded hex string */
      sPos = curPos;


    } else if ( dataType EQ PDF_TYPE_ARRAY ) {
      /* [ ... ] = array NOTE can be an array of any n objects */
      while( buf[curPos] != ']' ) {
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr );
      }
      curPos++;
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_DICTIONARY ) {
      /* << /Kids [ 1 0 R 1 0 R ]  = name tree */
      /*    /Names [ (key1) 1 0 R (key2) 2 0 R ] */
      /*    /Limits [ (firstKey) (lastKey) ] */
      /* << name ... >> = dictionary where key is a name and value can be any object */
      /* XXX organize into name, value pairs */
      while( strncmp( buf+curPos, ">>", 2 ) != 0 ) {
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr );
      }
      curPos += 2;
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );
      
    } else if ( dataType EQ PDF_TYPE_OBJECT ) {
      /* 3 0 obj ... endobj = turns any object into an indirect (referencable) object */
      /*                      3 = objNum, 0 = objRev */
      while ( strncmp( buf+curPos, "endobj", 6 ) != 0 ) {
	curPos = parsePdfObj( curPos, buf, endPos, PDF_TYPE_NONE, curObjPtr );
      }
      curPos += 6;
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[PDF_TYPE_OBJECT] );
      return( curPos );

    } else if ( dataType EQ PDF_TYPE_STREAM ) {
      /* XXX add code to associate the stream dictionary with the stream data */
      /* << ... >>EOLstream\n\r or \r ... \n\r endstream = stream */
      sPos = curPos;

      while( strncmp( buf+curPos, "endstream", 9 ) != 0 ) {
	curPos++;
      }

      printf( "Stream: %lu bytes\n", curPos - sPos );

      /* allocate buffer for decompressed stream */
      if ( ( destBuf = XMALLOC( ( curPos - sPos ) * 4 ) ) EQ NULL ) {
	fprintf( stderr, "ERR - Unable to allocate memory for stream\n" );
	exit( 1 );
      }
      XMEMSET( destBuf, 0, ( curPos-sPos ) * 4 );

      /* decompress the stream */
      z_stream zstrm;
      XMEMSET( &zstrm, 0, sizeof(zstrm) );
      zstrm.avail_in = curPos-sPos;
      zstrm.avail_out = ( curPos-sPos ) * 4;
      zstrm.next_in = buf+sPos;
      zstrm.next_out = destBuf;
      int rsti = inflateInit(&zstrm);
      if (rsti EQ Z_OK) {
	int rst2 = inflate (&zstrm, Z_FINISH);
	if (rst2 >= 0) {
	  if ( config->write ) {
	    writeStream( sPos, destBuf, zstrm.total_out );
	  } else
	    hexDump( 0, destBuf, zstrm.total_out );
	} else {
	  printf( "Stream did not decompress\n" );
	  if ( config->write ) {
	    writeStream( sPos, buf+sPos, curPos-sPos );
	  } else
	    hexDump( sPos, buf+sPos, curPos-sPos );
	}
      }

      XFREE( destBuf );

      curPos += 9;

      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      return( curPos );
      
    } else if ( dataType EQ PDF_TYPE_HEADER ) {
      /* %PDF-1.6EOL%nnnnEOL = file header where each n is > 128 to make file look binary */

    } else if ( dataType EQ PDF_TYPE_FOOTER ) {
      /* xref ... trailer ... startxref ... %%EOF = document footer */
      /* XXX making an asumption, big mistake */
      
      /* 0 271 */
      /* 0000000000 65535 f */
      /* 0000000015 00000 n */
      
      /* found the xref, now look for the trailer, startxref and finally the EOF */
      
      fprintf( stderr, "PDF Footer\n" );
      
      /* XXX need to parse xref table, may be multiple tables in the file */
      
      if ( strncmp( buf+curPos, "trailer", 7 ) EQ 0 ) {
          printf( "trailer\n" );
          curPos += 7;
      } else
          curPos++;
      
      if ( config->verbose )
	printf( "<< %lu/%lu [%s]\n", curPos, endPos, typeStrings[dataType] );
      
      return( curPos );
    }
  }

  return( curPos );
}