summaryrefslogblamecommitdiff
path: root/misc/pascal/libpoff/pfwstring.c
blob: b1b066e7b79a2c703e0987109df1ed9ea6a46571 (plain) (tree)
























































































































































































































                                                                              
/**********************************************************************
 * pfwstring.c
 * Write string table data a POFF file
 *
 *   Copyright (C) 2008 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 **********************************************************************/

/**********************************************************************
 * Included Files
 **********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "keywords.h"  /* Standard types */
#include "pedefs.h"    /* error code definitions */

#include "perr.h"      /* error() */
#include "pofflib.h"   /* POFF library interface */
#include "pfprivate.h" /* POFF private definitions */

/**********************************************************************
 * Definitions
 **********************************************************************/

/**********************************************************************
 * Global Variables
 **********************************************************************/

/**********************************************************************
 * Private Variables
 **********************************************************************/

/***********************************************************************
 * Private Function Prototypes
 ***********************************************************************/

/***********************************************************************
 * Private Functions
 ***********************************************************************/

/***********************************************************************
 * Public Functions
 ***********************************************************************/

/***********************************************************************/
/* Search the string table for an occurrence of the indicates string.
 * If found, return the offset in the string table to the string; if
 * not found, return -1.
 */

sint32 poffFindString(poffHandle_t handle, const char *string)
{
  poffInfo_t *poffInfo = (poffInfo_t*)handle;
  char       *sptr     = poffInfo->stringTable;
  uint32      offset;

  /* Has the string table been allocated yet? */

  if (!poffInfo->stringTable) return -1;

  /* Handle the NULL string case.  Offset zero is reserved for the NULL
   * string and for the zero-size string.
   */

  if (!string) return 0;

  /* Okay, we will have to search the table */

  for (offset = 0;
       offset < poffInfo->stringTableSection.sh_size;
       offset += (strlen(sptr) + 1))
    {
      /* Get a pointer at this offset into the string table */

      sptr = &poffInfo->stringTable[offset];

      /* Check if the strings match.  If so, return the offset */

      if (strcmp(sptr, string) == 0) return offset;
    }

  /* The string does not exist in the string table */

  return -1;
}

/***********************************************************************/
/***********************************************************************/
/* Add a string to the string table and return the offset to the
 * string storage location in the string table section data.
 */

uint32 poffAddString(poffHandle_t handle, const char *string)
{
  poffInfo_t *poffInfo = (poffInfo_t*)handle;
  sint32 index;
  int len;

  /* Check if we have allocated a string table buffer yet */

  if (!poffInfo->stringTable)
    {
      /* No, allocate it now */

      poffInfo->stringTable = (char*)malloc(INITIAL_STRING_TABLE_SIZE);
      if (!poffInfo->stringTable)
	{
	  fatal(eNOMEMORY);
	}

      /* Index 0 is reserved for the NULL string */

      poffInfo->stringTable[0]             = '\0';
      poffInfo->stringTableSection.sh_size = 1;
      poffInfo->stringTableAlloc           = INITIAL_STRING_TABLE_SIZE;
    }

  /* Check if the string is already defined in the string table.
   * This is very time consuming, but guaratees that we do not keep
   * duplicate strings in the string table.
   */

  index = poffFindString(handle, string);
  if (index < 0)
    {
      /* The string was not found in the string table.  Check for the
       * NULL string.  In this case, return index == 0.  NOTE:  This
       * check is pointless.  If this is any kind of NULL string, then
       * poffFindString will have returned index == 0.
       */

      if ((string == NULL) || ((len = strlen(string)) <= 0))
	{
	  index = 0;
	}
      else
	{
	  /* Increment the length to include the null terminator */

	  len++;

	  /* Check if there is room for the new string */

	  if (poffInfo->stringTableSection.sh_size + len >
	      poffInfo->stringTableAlloc)
	    {
	      uint32 newAlloc =
		poffInfo->stringTableAlloc + STRING_TABLE_INCREMENT;
	      void *tmp;

	      /* Make sure that the new string will fit in the new allocation
	       * size (shouldn't happen)
	       */

	      while (poffInfo->stringTableSection.sh_size + len > newAlloc)
		newAlloc += STRING_TABLE_INCREMENT;

	      /* Reallocate the string buffer */

	      tmp = realloc(poffInfo->stringTable, newAlloc);
	      if (!tmp)
		{
		  fatal(eNOMEMORY);
		}

	      /* And set the new size */

	      poffInfo->stringTableAlloc = newAlloc;
	      poffInfo->stringTable      = (char*)tmp;
	    }

	  /* Copy the string into the string table */

	  index = poffInfo->stringTableSection.sh_size;
	  memcpy(&poffInfo->stringTable[index], string, len);

	  /* Set the new size of the string table */

	  poffInfo->stringTableSection.sh_size += len;
	}
    }
  return index;
}

/***********************************************************************/