Example #1
0
uint32_t SPIFlash::Write (uint32_t address, uint8_t *buffer, uint32_t len)
{
  uint32_t bytestowrite;
  uint32_t bufferoffset;
  uint32_t results;
  uint32_t byteswritten;

  // There's no point duplicating most error checks here since they will all be
  // done in the underlying call to spiflashWritePage

  // If the data is only on one page we can take a shortcut
  if ((address % W25Q16BV_PAGESIZE) + len <= W25Q16BV_PAGESIZE)
  {
    // Only one page ... write and be done with it
    return WritePage(address, buffer, len);
  }

  // Block spans multiple pages
  byteswritten = 0;
  bufferoffset = 0;
  while(len)
  {
    // Figure out how many bytes need to be written to this page
    bytestowrite = W25Q16BV_PAGESIZE - (address % W25Q16BV_PAGESIZE);
    // Write the current page
    results = WritePage(address, buffer+bufferoffset, bytestowrite);
	byteswritten += results;
    // Abort if we returned an error
    if (!results)
       return byteswritten;  // Something bad happened ... but return what we've written so far
    // Adjust address and len, and buffer offset
    address += bytestowrite;
    len -= bytestowrite;
    bufferoffset+=bytestowrite;
    // If the next page is the last one, write it and exit
    // otherwise stay in the the loop and keep writing
    if (len <= W25Q16BV_PAGESIZE)
    {
      // Write the last frame and then quit
      results = WritePage(address, buffer+bufferoffset, len);
      byteswritten += results;
      // Abort if we returned an error
      if (!results)
        return byteswritten;  // Something bad happened ... but return what we've written so far
      // set len to zero to gracefully exit loop
      len = 0;
    }
  }

  // Return the number of bytes written
  return byteswritten;
}
unsigned char Write_Code_To_Memory_FLASH(unsigned short position, unsigned int new_code)
{
	//check if possition is good
	if (position > PAGE31_END)
		return FAILED;

	if (position >= PAGE31_START)
	{
		BackupPage(memory_backup.v_bkp, (unsigned int *) PAGE31);
		ErasePage(PAGE31,0);
		if (UpdateNewCode(memory_backup.v_bkp, position - PAGE31_START, new_code) == FAILED)
			return FAILED;

		if (WritePage(memory_backup.v_bkp, PAGE31, 1) == FAILED)
			return FAILED;
	}
	else if (position >= PAGE30_START)
	{
		BackupPage(memory_backup.v_bkp, (unsigned int *) PAGE30);
		ErasePage(PAGE30,0);
		if (UpdateNewCode(memory_backup.v_bkp, position - PAGE30_START, new_code) == FAILED)
			return FAILED;

		if (WritePage(memory_backup.v_bkp, PAGE30, 1) == FAILED)
			return FAILED;
	}
	else if (position >= PAGE29_START)
	{
		BackupPage(memory_backup.v_bkp, (unsigned int *) PAGE29);
		ErasePage(PAGE29,0);
		if (UpdateNewCode(memory_backup.v_bkp, position - PAGE29_START, new_code) == FAILED)
			return FAILED;

		if (WritePage(memory_backup.v_bkp, PAGE29, 1) == FAILED)
			return FAILED;
	}
	else if (position >= PAGE28_START)
	{
		BackupPage(memory_backup.v_bkp, (unsigned int *) PAGE28);
		ErasePage(PAGE28,0);
		if (UpdateNewCode(memory_backup.v_bkp, position, new_code) == FAILED)
			return FAILED;

		if (WritePage(memory_backup.v_bkp, PAGE28, 1) == FAILED)
			return FAILED;
	}

	return PASSED;
}
unsigned char WriteConfigurations (void)
{
	unsigned char * p_dos;
	//hago bkp de la pagina??? SI SI NO SE TRABA EL PROGRAMA
	BackupPage(memory_backup.v_bkp, (unsigned int *) PAGE27);

	ErasePage(PAGE27,0);

	//update en memoria
	p_dos = (unsigned char *) &memory_backup.v_bkp[0];

	*p_dos = param_struct.b1t;
	*(p_dos + 1) = param_struct.b1r;
	*(p_dos + 2) = param_struct.b2t;
	*(p_dos + 3) = param_struct.b2r;
	*(p_dos + 4) = param_struct.b3t;
	*(p_dos + 5) = param_struct.b3r;
	*(p_dos + 6) = param_struct.b4t;
	*(p_dos + 7) = param_struct.b4r;


	//faltan los tiempos internos



	if (WritePage(memory_backup.v_bkp, PAGE27, 1) == FAILED)
		return FAILED;

	return PASSED;
}
Example #4
0
void BulkStorage_WriteClose(struct BulkStorage *b)
{
  if ( b == NULL ) {
    return;
  }
  if ( b->dirty != 0 ) {
    WritePage(b);
  }
  if ( b->marked != 0 ) {
    uint32_t image_hash = 0;
    uint32_t page_hash ;
    for ( uint32_t i = 1; i < b->token->number_pages ; i ++ ) {
      ReadPage(b,  i);
      page_hash = CalcCRC(b->data, DATAFLASH_PAGESIZE_NORMAL);
      image_hash ^= page_hash;      
    }
    b->head.hash = image_hash;
    b->head.timestamp = 0;
    b->marked = 0;
    WriteHeader(b->token, &b->head);
  }
  
  b->token = NULL;
  b->loaded_page = 0xFFFF;
  b->dirty = 0;
  b->write = 0;
}
Example #5
0
uint16_t BulkStorage_WriteData(struct BulkStorage *b, uint32_t addr, const uint8_t *buffer, uint16_t size)
{
  if (( b == NULL ) || 
      ( buffer == NULL ) ||
      ( b->write == 0 )) {
    return 0;
  }  
  uint16_t page = CalcPage(addr);
  if ( page != b->loaded_page ) {
    if ( b->dirty != 0 ) {
      WritePage(b);
      b->dirty = 0;
    }
    ReadPage(b, page);
  }
  uint16_t offset = CalcPageAddr(addr);
  uint16_t length = size;
  if (( offset+size) > DATAFLASH_PAGESIZE_NORMAL ) {
    length = DATAFLASH_PAGESIZE_NORMAL - offset;
  }
  if ( memcmp(b->data+offset, buffer, length) != 0 ) {
    b->dirty = 1; /* only mark as dirty if we actually change data... */
    b->marked = 1;  
    memcpy(b->data+offset, buffer, length); 
  }
  return length;
}
Example #6
0
Status WritePersistentMemory(Reference reference, int length, void* buffer)
{
    Status result = OK;
    int pageIndex = reference / FLASH_PAGE_SIZE;
    int pageOffset = pageIndex * FLASH_PAGE_SIZE;
    Reference pageBase = pageOffset;
    int workIndex = reference - pageOffset;
    while ((length > 0) && (result == OK))
    {
        if (pageBase < FLASH_LIMIT)
        {
            int written;
            result = WritePage(pageBase, workIndex, length, buffer, &written);
            pageBase += FLASH_PAGE_SIZE;
            workIndex = 0;
            buffer += written;
            length -= written;
        }
        else
        {
            GenerateAddressStatusText("FlsWrErr", pageBase);
            result = statusText;
        }
    }
    return result;
}
Example #7
0
 void Flush()
 {
   ogg_page page;
   while (const int streamRes = OggApi->ogg_stream_flush(&Stream, &page))
   {
     WritePage(page);
   }
 }
Example #8
0
 void Save()
 {
   ogg_page page;
   while (const int streamRes = OggApi->ogg_stream_pageout(&Stream, &page))
   {
     WritePage(page);
     if (OggApi->ogg_page_eos(&page))
     {
       break;
     }
   }
 }
//------------------------------------------------------------------------------
void stPlainDiskPageManager::DisposePage(stPage * page){
   stPageID * next;
   
   // Append to free list
   next = (stPageID *)page->GetData();
   *next = header->Available;
   header->Available = page->GetPageID();
   WritePage(page);

   // Update header   
   header->UsedPages--;
   WriteHeaderPage(headerPage);
   
   // Free resources
   ReleasePage(page);
}//end stPlainDiskPageManager::DisposePage
Example #10
0
void PID_NandSave()
{
	int i;
	uint8 data[2048];
	*(uint8*)(data)=PID_ListLength;
	for(i=0;i<PID_ListLength;i++)
	{
		*(fp64*)(data+24*i+8)=Pid_List[i].PROP;
		*(fp64*)(data+24*i+16)=Pid_List[i].Ti;
		*(fp64*)(data+24*i+24)=Pid_List[i].Td;
	}
	EraseBlock(PID_NANDPAGE);
	if(WritePage(PID_NANDPAGE,data)!=1)
	{
		Nand_Error=PID_NANDPAGE;
	}
}
Example #11
0
uint16_t  BulkStorage_ReadData(struct BulkStorage *b, uint32_t addr, uint8_t *buffer, uint16_t size)
{
  if (( b == NULL ) || ( buffer == NULL )) {
    return 0;
  }  
  uint16_t page = CalcPage(addr);
  if ( page != b->loaded_page ) {
    if ( b->dirty != 0 ) {
      WritePage(b);
      b->dirty = 0;
    }
    ReadPage(b, page);
  }
  uint16_t offset = CalcPageAddr(addr);
  uint16_t length = size;
  if (( offset+size) > DATAFLASH_PAGESIZE_NORMAL ) {
    length = DATAFLASH_PAGESIZE_NORMAL - offset;
  }
  memcpy(buffer, b->data+offset, length); 
  return length;
}
Example #12
0
void PF_BufferPool::ForceSinglePage(PF_BufferPage& page)
{
  std::pair<int, PageNum> key = std::pair<int, PageNum> (page.fd, page.pageNum);

  auto res = indexMap.find(key);
  if (res != indexMap.end())
  {
    if (page.pinCount > 0)
    {
      std::cerr << "warning page pinnned" << std::endl;
    }

    if (page.isDirty)
    {
      WritePage(page);

      page.isDirty = false;
    }
  }
  else
    throw PF_Exception(PF_Exception::PAGE_NOT_IN_BUF);
}
Example #13
0
BOOL WriteRawImageToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr)
{
	DWORD dwBlock = 0;
	DWORD dwNumBlocks = 0;
	LPBYTE pbBuffer;
       SectorInfo si;
	//unsigned int sectorchk;
	unsigned int sectorcnt = 0;
	unsigned int areachange = 0;

    OALMSG(OAL_FUNC, (TEXT("+WriteRawImageToBootMedia\r\n")));

    if ( !g_bBootMediaExist ) 
    {
	    OALMSG(OAL_ERROR, (TEXT("ERROR: WriteRawImageToBootMedia: device doesn't exist.\r\n")));
        return(FALSE);
    }
	if(dwLaunchAddr==0x10)
		{
		dwBlock = LOGO_BLOCK;
		//dwImageLength = UPLDR_RAM_IMAGE_SIZE;
		g_ImageType=IMAGE_TYPE_RAWBIN;
		}else{

	if (g_ImageType == IMAGE_TYPE_LOADER)
	{
		dwBlock = EBOOT_BLOCK;
	    if ( !VALID_TOC(g_pTOC) ) 
	    {
		    OALMSG(OAL_WARN, (TEXT("WARN: WriteRawImageToBootMedia: INVALID_TOC\r\n")));
	        if ( !TOC_Init(g_dwTocEntry, g_ImageType, dwImageStart, dwImageLength, dwLaunchAddr) ) 
	        {
			    OALMSG(OAL_ERROR, (TEXT("ERROR: INVALID_TOC\r\n")));
        	    return(FALSE);
        	}
    	}
	}
	else if (g_ImageType == IMAGE_TYPE_STEPLDR)
	{
		dwBlock = STEPLDR_BLOCK;
		dwImageStart += dwLaunchAddr;
		//dwImageLength = 0x2050; //step loader can support 8k bytes.
		//dwImageLength = STEPLDR_RAM_IMAGE_SIZE; //step loader can support 4k bytes only. NO SuperIPL case is 16K....... 3 Block
	}
	else if (g_ImageType == IMAGE_TYPE_DIONB0)
	{
		dwBlock = DIONB0_BLOCK;
		dwImageStart += dwLaunchAddr;
		dwImageLength -= (dwImageLength / (g_FlashInfo.wDataBytesPerSector + 8))*8;
	}
	else if (g_ImageType == IMAGE_TYPE_UPLDR)
	{
		dwBlock = UPLDR_BLOCK;
		dwImageStart += dwLaunchAddr;
		dwImageLength = UPLDR_RAM_IMAGE_SIZE; //step loader can support 4k bytes only. NO SuperIPL case is 16K....... 3 Block
	}
	else if (g_ImageType == IMAGE_TYPE_FLASHBIN)
	{
		dwBlock = FLASHBIN_BLOCK;
//		dwImageStart += dwLaunchAddr;
//		dwImageLength = dwImageLength; //step loader can support 4k bytes only. NO SuperIPL case is 16K....... 3 Block
	}
			}
		if(dwLaunchAddr==0x10)
			pbBuffer=(LPBYTE)dwImageStart;
		else
	pbBuffer = OEMMapMemAddr(dwImageStart, dwImageStart);
	 
    // Compute number of blocks.
    dwNumBlocks = (dwImageLength / (g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock)) + (dwImageLength%(g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock) ? 1: 0);
    OALMSG(TRUE, (TEXT("dwImageLength = 0x%x \r\n"), dwImageLength));
    OALMSG(TRUE, (TEXT("dwNumBlocks = 0x%x \r\n"), dwNumBlocks));

    while (dwNumBlocks--)
    {
        // If the block is marked bad, skip to next block.  Note that the assumption in our error checking
        // is that any truely bad block will be marked either by the factory during production or will be marked
        // during the erase and write verification phases.  If anything other than a bad block fails ECC correction
        // in this routine, it's fatal.

	    OALMSG(TRUE, (TEXT("dwBlock(0x%x) X "), dwBlock));
	    OALMSG(TRUE, (TEXT("g_FlashInfo.wSectorsPerBlock(0x%x)"), g_FlashInfo.wSectorsPerBlock));
	    OALMSG(TRUE, (TEXT(" = 0x%x \r\n"), dwBlock*g_FlashInfo.wSectorsPerBlock));

        if (!FMD_EraseBlock(dwBlock)) 
        {
            OALMSG(TRUE, (TEXT("WriteData: failed to erase block (0x%x).\r\n"), dwBlock));
			++dwBlock;
			++dwNumBlocks;		  // Compensate for fact that we didn't write any blocks.
			continue;
        }

//		FMD_GetBlockStatus(dwBlock);
        if ((FMD_GetBlockStatus(dwBlock) & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))&&dwBlock!=0) {
		    OALMSG(TRUE, (TEXT("FMD_GetBlockStatus Error \r\n")));
            ++dwBlock;
            ++dwNumBlocks;        // Compensate for fact that we didn't write any blocks.
            continue;
        }

		//FMD_ReadSector(dwBlock*g_FlashInfo.wSectorsPerBlock, NULL, &si, 1);
		if (!FMD_ReadSector(dwBlock*g_FlashInfo.wSectorsPerBlock, NULL, &si, 1)) 
		{
		    OALMSG(TRUE, (TEXT("FMD_ReadSector : Failed to get block(0x%x)'s sector info.\r\n"), dwBlock));
            ++dwBlock;
            ++dwNumBlocks;        // Compensate for fact that we didn't write any blocks.
            continue;
		}

		// Stepldr & Eboot image in nand flash
		// block mark as BLOCK_STATUS_RESERVED & BLOCK_STATUS_READONLY & BLOCK_STATUS_BAD
        if ((si.bBadBlock == 0x0) && (si.bOEMReserved !=0xfc )&&dwBlock!=0)
        {
            OALMSG(TRUE, (TEXT("si.bBadBlock failed, si.bOEMReserved %x,si.bBadBlock %x.\r\n"),si.bOEMReserved, si.bBadBlock));
            ++dwBlock;
            ++dwNumBlocks;        // Compensate for fact that we didn't write any blocks.
            continue;
        }
        if (!ReadBlock(dwBlock, NULL, g_pSectorInfoBuf)) 
        {
		    OALMSG(TRUE, (TEXT("WriteData: failed to read block (0x%x).\r\n"), dwBlock));
            return(FALSE);
        }


		if (g_ImageType == IMAGE_TYPE_DIONB0)
		{
			for ( int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector ++ )
			{
				if (!WritePage(dwBlock*g_FlashInfo.wSectorsPerBlock + iSector, pbBuffer, (PSectorInfo)(pbBuffer+g_FlashInfo.wDataBytesPerSector) )) 
				{
					OALMSG(TRUE, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock));
					return(FALSE);
				}
				pbBuffer += (g_FlashInfo.wDataBytesPerSector + 8);
			}

			++dwBlock;
		}
		else if (g_ImageType == IMAGE_TYPE_FLASHBIN)
		{
			for ( int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector ++ )
			{
				//RETAILMSG(1, (TEXT("WriteData: (0x%x)(0x%x,0x%x,0x%x).\r\n"), dwBlock*g_FlashInfo.wSectorsPerBlock + iSector, g_pSectorInfoBuf->dwReserved1, g_pSectorInfoBuf->bOEMReserved, g_pSectorInfoBuf->wReserved2));

				if (!WritePage(dwBlock*g_FlashInfo.wSectorsPerBlock + iSector, pbBuffer, (PSectorInfo)(pbBuffer+g_FlashInfo.wDataBytesPerSector) )) 
				{
					OALMSG(TRUE, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock));
                    #ifdef IROMBOOT
					FMD_EraseBlock(dwBlock);		
							 
					// this block is actually considered to bad block.
					// because it may be erased initial bad block information. 
					si.bOEMReserved = 0xff;
					si.bBadBlock    = BADBLOCKMARK;
					si.dwReserved1  = 0xffffffff;
					si.wReserved2   = 0xffff;

					FMD_WriteSector(BLOCK_TO_SECTOR(dwBlock), NULL, &si, 1);
					pbBuffer -= (g_FlashInfo.wDataBytesPerSector + 8)*iSector;
					iSector = 0;
					break;					
                    
                    #else
					return(FALSE);

                    #endif  // !IROMBOOT
				}
				pbBuffer += (g_FlashInfo.wDataBytesPerSector + 8);
			}

			++dwBlock;
		}
		else
		{
			OALMSG(TRUE, (TEXT(" Write Reserved Area \n")));

			if (!WriteBlock(dwBlock, pbBuffer, g_pSectorInfoBuf)) 
			{
				OALMSG(TRUE, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock));
				return(FALSE);
			}

			++dwBlock;
			OALMSG(TRUE, (TEXT("pbBuffer + %x .\r\n"), SECTOR_SIZE/*SECTORS_PER_PAGE*/*PAGES_PER_BLOCK));
            #ifdef IROMBOOT
			pbBuffer += (SECTOR_SIZE/*SECTORS_PER_PAGE*/*PAGES_PER_BLOCK);

            #else
			pbBuffer += 0x4000;

            #endif  // !IROMBOOT
		}
    }
	
	if (g_ImageType == IMAGE_TYPE_LOADER)
	{
    	g_pTOC->id[0].dwLoadAddress = dwImageStart;
    	g_pTOC->id[0].dwJumpAddress = 0;
    	g_pTOC->id[0].dwTtlSectors  = FILE_TO_SECTOR_SIZE(dwImageLength);
    	g_pTOC->id[0].sgList[0].dwSector = BLOCK_TO_SECTOR(EBOOT_BLOCK);
    	g_pTOC->id[0].sgList[0].dwLength = g_pTOC->id[0].dwTtlSectors;
    }

    OALMSG(OAL_FUNC, (TEXT("_WriteRawImageToBootMedia\r\n")));
	return TRUE;
}
Example #14
0
int				/* O - Exit status */
TextMain(const char *name,	/* I - Name of filter */
         int        argc,	/* I - Number of command-line arguments */
         char       *argv[])	/* I - Command-line arguments */
{
  FILE		*fp;		/* Print file */
  ppd_file_t	*ppd;		/* PPD file */
  int		i,		/* Looping var */
		ch,		/* Current char from file */
		lastch,		/* Previous char from file */
		attr,		/* Current attribute */
		line,		/* Current line */
  		column,		/* Current column */
  		page_column;	/* Current page column */
  int		num_options;	/* Number of print options */
  cups_option_t	*options;	/* Print options */
  const char	*val;		/* Option value */
  char		keyword[64],	/* Keyword string */
		*keyptr;	/* Pointer into string */
  int		keycol;		/* Column where keyword starts */
  int		ccomment;	/* Inside a C-style comment? */
  int		cstring;	/* Inside a C string */


 /*
  * Make sure status messages are not buffered...
  */

  setbuf(stderr, NULL);

 /*
  * Check command-line...
  */

  if (argc < 6 || argc > 7)
  {
    fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
            name);
    return (1);
  }

 /*
  * If we have 7 arguments, print the file named on the command-line.
  * Otherwise, send stdin instead...
  */

  if (argc == 6)
    fp = stdin;
  else
  {
   /*
    * Try to open the print file...
    */

    if ((fp = fopen(argv[6], "rb")) == NULL)
    {
      perror("DEBUG: unable to open print file - ");
      return (1);
    }
  }

 /*
  * Process command-line options and write the prolog...
  */

  options     = NULL;
  num_options = cupsParseOptions(argv[5], 0, &options);

  if ((val = cupsGetOption("prettyprint", num_options, options)) != NULL &&
      strcasecmp(val, "no") && strcasecmp(val, "off") &&
      strcasecmp(val, "false"))
  {
    PageLeft     = 72.0f;
    PageRight    = PageWidth - 36.0f;
    PageBottom   = PageBottom > 36.0f ? PageBottom : 36.0f;
    PageTop      = PageLength - 36.0f;
    CharsPerInch = 12;
    LinesPerInch = 8;

    if ((val = getenv("CONTENT_TYPE")) == NULL)
    {
      PrettyPrint = PRETTY_PLAIN;
      NumKeywords = 0;
      Keywords    = NULL;
    }
    else if (strcasecmp(val, "application/x-cshell") == 0)
    {
      PrettyPrint = PRETTY_SHELL;
      NumKeywords = sizeof(csh_keywords) / sizeof(csh_keywords[0]);
      Keywords    = csh_keywords;
    }
    else if (strcasecmp(val, "application/x-csource") == 0)
    {
      PrettyPrint = PRETTY_CODE;
      NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
      Keywords    = code_keywords;
    }
    else if (strcasecmp(val, "application/x-perl") == 0)
    {
      PrettyPrint = PRETTY_PERL;
      NumKeywords = sizeof(perl_keywords) / sizeof(perl_keywords[0]);
      Keywords    = perl_keywords;
    }
    else if (strcasecmp(val, "application/x-shell") == 0)
    {
      PrettyPrint = PRETTY_SHELL;
      NumKeywords = sizeof(sh_keywords) / sizeof(sh_keywords[0]);
      Keywords    = sh_keywords;
    }
    else
    {
      PrettyPrint = PRETTY_PLAIN;
      NumKeywords = 0;
      Keywords    = NULL;
    }
  }

  ppd = SetCommonOptions(num_options, options, 1);

  if ((val = cupsGetOption("wrap", num_options, options)) == NULL)
    WrapLines = 1;
  else
    WrapLines = !strcasecmp(val, "true") || !strcasecmp(val, "on") ||
                !strcasecmp(val, "yes");

  if ((val = cupsGetOption("columns", num_options, options)) != NULL)
    PageColumns = atoi(val);

  if ((val = cupsGetOption("cpi", num_options, options)) != NULL)
    CharsPerInch = atof(val);

  if ((val = cupsGetOption("lpi", num_options, options)) != NULL)
    LinesPerInch = atof(val);

  if (PrettyPrint)
    PageTop -= 216.0f / LinesPerInch;

  Copies = atoi(argv[4]);

  WriteProlog(argv[3], argv[2], getenv("CLASSIFICATION"),
              cupsGetOption("page-label", num_options, options), ppd);

 /*
  * Read text from the specified source and print it...
  */

  lastch       = 0;
  column       = 0;
  line         = 0;
  page_column  = 0;
  attr         = 0;
  keyptr       = keyword;
  keycol       = 0;
  ccomment     = 0;
  cstring      = 0;

  while ((ch = getutf8(fp)) >= 0)
  {
   /*
    * Control codes:
    *
    *   BS	Backspace (0x08)
    *   HT	Horizontal tab; next 8th column (0x09)
    *   LF	Line feed; forward full line (0x0a)
    *   VT	Vertical tab; reverse full line (0x0b)
    *   FF	Form feed (0x0c)
    *   CR	Carriage return (0x0d)
    *   ESC 7	Reverse full line (0x1b 0x37)
    *   ESC 8	Reverse half line (0x1b 0x38)
    *   ESC 9	Forward half line (0x1b 0x39)
    */

    switch (ch)
    {
      case 0x08 :		/* BS - backspace for boldface & underline */
          if (column > 0)
            column --;

          keyptr = keyword;
	  keycol = column;
          break;

      case 0x09 :		/* HT - tab to next 8th column */
          if (PrettyPrint && keyptr > keyword)
	  {
	    *keyptr = '\0';
	    keyptr  = keyword;

	    if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
	                compare_keywords))
            {
	     /*
	      * Put keywords in boldface...
	      */

	      i = page_column * (ColumnWidth + ColumnGutter);

	      while (keycol < column)
	      {
	        Page[line][keycol + i].attr |= ATTR_BOLD;
		keycol ++;
	      }
	    }
	  }

          column = (column + 8) & ~7;

          if (column >= ColumnWidth && WrapLines)
          {			/* Wrap text to margins */
            line ++;
            column = 0;

            if (line >= SizeLines)
            {
              page_column ++;
              line = 0;

              if (page_column >= PageColumns)
              {
                WritePage();
		page_column = 0;
              }
            }
          }

	  keycol = column;

          attr &= ~ATTR_BOLD;
          break;

      case 0x0d :		/* CR */
#ifndef __APPLE__
         /*
	  * All but MacOS/Darwin treat CR as was intended by ANSI
	  * folks, namely to move to column 0/1.  Some programs still
	  * use this to do boldfacing and underlining...
	  */

          column = 0;
          break;
#else
         /*
	  * MacOS/Darwin still need to treat CR as a line ending.
	  */

          {
	    int nextch;
            if ((nextch = getc(fp)) != 0x0a)
	      ungetc(nextch, fp);
	    else
	      ch = nextch;
	  }
#endif /* !__APPLE__ */

      case 0x0a :		/* LF - output current line */
          if (PrettyPrint && keyptr > keyword)
	  {
	    *keyptr = '\0';
	    keyptr  = keyword;

	    if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
	                compare_keywords))
            {
	     /*
	      * Put keywords in boldface...
	      */

	      i = page_column * (ColumnWidth + ColumnGutter);

	      while (keycol < column)
	      {
	        Page[line][keycol + i].attr |= ATTR_BOLD;
		keycol ++;
	      }
	    }
	  }

          line ++;
          column = 0;
	  keycol = 0;

          if (!ccomment && !cstring)
	    attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);

          if (line >= SizeLines)
          {
            page_column ++;
            line = 0;

            if (page_column >= PageColumns)
            {
              WritePage();
	      page_column = 0;
            }
          }
          break;

      case 0x0b :		/* VT - move up 1 line */
          if (line > 0)
	    line --;

          keyptr = keyword;
	  keycol = column;

          if (!ccomment && !cstring)
	    attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
          break;

      case 0x0c :		/* FF - eject current page... */
          if (PrettyPrint && keyptr > keyword)
	  {
	    *keyptr = '\0';
	    keyptr  = keyword;

	    if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
	                compare_keywords))
            {
	     /*
	      * Put keywords in boldface...
	      */

	      i = page_column * (ColumnWidth + ColumnGutter);

	      while (keycol < column)
	      {
	        Page[line][keycol + i].attr |= ATTR_BOLD;
		keycol ++;
	      }
	    }
	  }

          page_column ++;
	  column = 0;
	  keycol = 0;
          line   = 0;

          if (!ccomment && !cstring)
	    attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);

          if (page_column >= PageColumns)
          {
            WritePage();
            page_column = 0;
          }
          break;

      case 0x1b :		/* Escape sequence */
          ch = getutf8(fp);
	  if (ch == '7')
	  {
	   /*
	    * ESC 7	Reverse full line (0x1b 0x37)
	    */

            if (line > 0)
	      line --;
	  }
	  else if (ch == '8')
	  {
           /*
	    *   ESC 8	Reverse half line (0x1b 0x38)
	    */

            if ((attr & ATTR_RAISED) && line > 0)
	    {
	      attr &= ~ATTR_RAISED;
              line --;
	    }
	    else if (attr & ATTR_LOWERED)
	      attr &= ~ATTR_LOWERED;
	    else
	      attr |= ATTR_RAISED;
	  }
	  else if (ch == '9')
	  {
           /*
	    *   ESC 9	Forward half line (0x1b 0x39)
	    */

            if ((attr & ATTR_LOWERED) && line < (SizeLines - 1))
	    {
	      attr &= ~ATTR_LOWERED;
              line ++;
	    }
	    else if (attr & ATTR_RAISED)
	      attr &= ~ATTR_RAISED;
	    else
	      attr |= ATTR_LOWERED;
	  }
	  break;

      default :			/* All others... */
          if (ch < ' ')
            break;		/* Ignore other control chars */

          if (PrettyPrint > PRETTY_PLAIN)
	  {
	   /*
	    * Do highlighting of C/C++ keywords, preprocessor commands,
	    * and comments...
	    */

	    if (ch == ' ' && (attr & ATTR_BOLD))
	    {
	     /*
	      * Stop bolding preprocessor command...
	      */

	      attr &= ~ATTR_BOLD;
	    }
	    else if (!(isalnum(ch & 255) || ch == '_') && keyptr > keyword)
	    {
	     /*
	      * Look for a keyword...
	      */

	      *keyptr = '\0';
	      keyptr  = keyword;

	      if (!(attr & ATTR_ITALIC) &&
	          bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
	                  compare_keywords))
              {
	       /*
	        * Put keywords in boldface...
		*/

	        i = page_column * (ColumnWidth + ColumnGutter);

		while (keycol < column)
		{
	          Page[line][keycol + i].attr |= ATTR_BOLD;
		  keycol ++;
		}
	      }
	    }
	    else if ((isalnum(ch & 255) || ch == '_') && !ccomment && !cstring)
	    {
	     /*
	      * Add characters to the current keyword (if they'll fit).
	      */

              if (keyptr == keyword)
	        keycol = column;

	      if (keyptr < (keyword + sizeof(keyword) - 1))
	        *keyptr++ = ch;
            }
	    else if (ch == '\"' && lastch != '\\' && !ccomment && !cstring)
	    {
	     /*
	      * Start a C string constant...
	      */

	      cstring = -1;
              attr    = ATTR_BLUE;
	    }
            else if (ch == '*' && lastch == '/' && !cstring &&
	             PrettyPrint != PRETTY_SHELL)
	    {
	     /*
	      * Start a C-style comment...
	      */

	      ccomment = 1;
	      attr     = ATTR_ITALIC | ATTR_GREEN;
	    }
	    else if (ch == '/' && lastch == '/' && !cstring &&
	             PrettyPrint == PRETTY_CODE)
	    {
	     /*
	      * Start a C++-style comment...
	      */

	      attr = ATTR_ITALIC | ATTR_GREEN;
	    }
	    else if (ch == '#' && !cstring && PrettyPrint != PRETTY_CODE)
	    {
	     /*
	      * Start a shell-style comment...
	      */

	      attr = ATTR_ITALIC | ATTR_GREEN;
	    }
	    else if (ch == '#' && column == 0 && !ccomment && !cstring &&
	             PrettyPrint == PRETTY_CODE)
	    {
	     /*
	      * Start a preprocessor command...
	      */

	      attr = ATTR_BOLD | ATTR_RED;
	    }
          }

          if (column >= ColumnWidth && WrapLines)
          {			/* Wrap text to margins */
            column = 0;
	    line ++;

            if (line >= SizeLines)
            {
              page_column ++;
              line = 0;

              if (page_column >= PageColumns)
              {
        	WritePage();
        	page_column = 0;
              }
            }
          }

         /*
	  * Add text to the current column & line...
	  */

          if (column < ColumnWidth)
	  {
	    i = column + page_column * (ColumnWidth + ColumnGutter);

            if (PrettyPrint)
              Page[line][i].attr = attr;
	    else if (ch == ' ' && Page[line][i].ch)
	      ch = Page[line][i].ch;
            else if (ch == Page[line][i].ch)
              Page[line][i].attr |= ATTR_BOLD;
            else if (Page[line][i].ch == '_')
              Page[line][i].attr |= ATTR_UNDERLINE;
            else if (ch == '_')
	    {
              Page[line][i].attr |= ATTR_UNDERLINE;

              if (Page[line][i].ch)
	        ch = Page[line][i].ch;
	    }
	    else
              Page[line][i].attr = attr;

            Page[line][i].ch = ch;
	  }

          if (PrettyPrint)
	  {
	    if ((ch == '{' || ch == '}') && !ccomment && !cstring &&
	        column < ColumnWidth)
	    {
	     /*
	      * Highlight curley braces...
	      */

	      Page[line][column].attr |= ATTR_BOLD;
	    }
	    else if ((ch == '/' || ch == '*') && lastch == '/' &&
	             column < ColumnWidth && PrettyPrint != PRETTY_SHELL)
	    {
	     /*
	      * Highlight first comment character...
	      */

	      Page[line][column - 1].attr = attr;
	    }
	    else if (ch == '\"' && lastch != '\\' && !ccomment && cstring > 0)
	    {
	     /*
	      * End a C string constant...
	      */

	      cstring = 0;
	      attr    &= ~ATTR_BLUE;
            }
	    else if (ch == '/' && lastch == '*' && ccomment)
	    {
	     /*
	      * End a C-style comment...
	      */

	      ccomment = 0;
	      attr     &= ~(ATTR_ITALIC | ATTR_GREEN);
	    }

            if (cstring < 0)
	      cstring = 1;
	  }

          column ++;
          break;          
    }

   /*
    * Save this character for the next cycle.
    */

    lastch = ch;
  }

 /*
  * Write any remaining page data...
  */

  if (line > 0 || page_column > 0 || column > 0)
    WritePage();

 /*
  * Write the epilog and return...
  */

  WriteEpilogue();

  if (ppd != NULL)
    ppdClose(ppd);

  return (0);
}