mvecstr.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 347 行
C
347 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Functions for "text vector" handling.
*
****************************************************************************/
#include <string.h>
#define _IN_MVECSTR
#include "make.h"
#include "massert.h"
#include "mmemory.h"
#include "mrcmsg.h"
#include "msg.h"
#include "mvecstr.h"
#ifndef max
#define max(a,b) ( ( a ) > ( b ) ? ( a ) : ( b ) )
#endif
#define MIN_TEXT 507 /* minimum length we'll create text */
#ifndef USE_FAR
/* allocate intermediate vectors in regular memory */
# define myMalloc(size) MallocSafe(size)
# define myFree(ptr) FreeSafe(ptr)
#else
/* allocate intermediate vectors in far memory to reduce fragmentation */
# define myMalloc(size) FarMalloc(size)
# define myFree(ptr) FarFree(ptr)
#endif
typedef struct vecEntry FAR *ENTRYPTR;
struct vecEntry {
ENTRYPTR next;
size_t len;
char text[1]; /* variable length buffer */
};
typedef union vecHead *OURPTR;
union vecHead {
OURPTR next;
struct {
ENTRYPTR head;
ENTRYPTR tail;
size_t totlen;
} d;
};
STATIC OURPTR freeVec;
/*
* When StartVec is called, we return a pointer to a union vecHead. The
* initial vecHead contains NULL for head, tail, and 0 for totlen. (The
* next pointer is only used to chain unused vecHeads together - it is not
* used in an active vecHead.)
*
* vecEntrys are allocated as required by the calls to WriteVec and CatVec.
* Each vecEntry contains a character buffer of at least MIN_TEXT characters.
* cpyTxt() fills up the tail vecEntry buffer before allocating a new
* buffer.
*
* If a string larger than MIN_TEXT is written, first the tail buffer is
* filled, and then a new buffer is allocated with enough room to hold the
* remainder of the string. A buffer is never allocated with less than
* MIN_TEXT bytes.
*
* expandVec simply allocates a chunk large enough to contain the complete
* string and copies all the individual chunks into place.
*
* The strings stored in a vecEntry are not null-terminated.
*/
#ifdef USE_SCARCE
STATIC RET_T vecScarce( void )
/****************************/
{
OURPTR cur;
if( freeVec != NULL ) {
while( freeVec != NULL ) {
cur = freeVec;
freeVec = freeVec->next;
FreeSafe( cur );
}
return( RET_SUCCESS );
}
return( RET_ERROR );
}
#endif
extern void VecInit( void )
/*************************/
{
unsigned count;
OURPTR new;
freeVec = NULL;
for( count = 0; count < VECSTR_ALLOC_VECSTR; ++count ) {
new = MallocSafe( sizeof( *new ) );
new->next = freeVec;
freeVec = new;
}
#ifdef USE_SCARCE
IfMemScarce( vecScarce );
#endif
}
extern void VecFini( void )
/*************************/
{
}
extern VECSTR StartVec( void )
/****************************/
{
OURPTR new;
if( freeVec != NULL ) {
new = freeVec;
freeVec = freeVec->next;
} else {
new = MallocSafe( sizeof( *new ) );
}
new->d.head = NULL;
new->d.tail = NULL;
new->d.totlen = 0U;
return( (VECSTR)new );
}
extern void FreeVec( VECSTR vec )
/*******************************/
{
ENTRYPTR walk;
ENTRYPTR cur;
walk = ((OURPTR)vec)->d.head;
while( walk != NULL ) {
cur = walk;
walk = walk->next;
myFree( cur );
}
((OURPTR)vec)->next = freeVec;
freeVec = (OURPTR)vec;
}
STATIC char *expandVec( VECSTR vec )
/**********************************/
{
char *result;
char *d;
ENTRYPTR cur;
assert( vec != NULL );
cur = ((OURPTR)vec)->d.head;
if( cur == NULL ) {
return( CallocSafe( 1 ) );
}
result = MallocSafe( ((OURPTR)vec)->d.totlen + 1 );
d = result;
for( ; cur != NULL; cur = cur->next ) {
_fmemcpy( d, cur->text, cur->len );
d += cur->len;
}
*d = NULLCHAR;
assert( d - result == ((OURPTR)vec)->d.totlen );
return( result );
}
extern char *FinishVec( VECSTR vec )
/**********************************/
{
char *result;
result = expandVec( vec );
FreeVec( vec );
return( result );
}
STATIC void cpyTxt( OURPTR vec, const char FAR *text, size_t len )
/*****************************************************************
* Copy text into vec by filling up the current buffer, and/or
* allocating a new one.
*/
{
ENTRYPTR new;
ENTRYPTR tail;
size_t clen;
char FAR *fptr; /* we use this to help the optimizer */
assert( vec != NULL && text != NULL && *text != NULLCHAR );
clen = vec->d.totlen; /* hold for overflow check */
vec->d.totlen += len;
if( clen > vec->d.totlen ) { /* check for overflow */
PrtMsg( FTL|LOC| MAXIMUM_STRING_LENGTH );
}
tail = vec->d.tail;
if( tail != NULL ) {
fptr = tail->text + tail->len; /* we'll need this value later */
/* we have room in tail for all of text */
if( tail->len + len <= MIN_TEXT ) {
_fmemcpy( fptr, text, len );
tail->len += len;
return;
} else if( tail->len < MIN_TEXT ) { /* partially empty buffer */
clen = MIN_TEXT - tail->len; /* room remaining */
_fmemcpy( fptr, text, clen );
tail->len = MIN_TEXT;
/* setup to make a new entry with remainder of text */
text += clen;
len -= clen;
/**/ assert( len > 0 ); /* the len = 0 case should be handled above */
} /* else we'll have to make a new buffer */
}
/* allocate a new buffer, and copy text into it */
new = myMalloc( sizeof( *new ) + max( len, MIN_TEXT ) );
_fmemcpy( new->text, text, len );
new->len = len;
new->next = NULL;
if( vec->d.head != NULL ) {
assert( tail == vec->d.tail ); /* we set this earlier */
tail->next = new;
} else {
vec->d.head = new;
}
vec->d.tail = new;
}
extern void WriteVec( VECSTR vec, const char *text )
/**************************************************/
{
assert( vec != NULL );
if( text != NULL && *text != NULLCHAR ) {
cpyTxt( (OURPTR) vec, text, strlen( text ) );
}
}
extern void WriteNVec( VECSTR vec, const char *text, size_t len )
/****************************************************************
* write vector with input string length len
*/
{
assert( vec != NULL );
if( text != NULL && *text != NULLCHAR ) {
cpyTxt( (OURPTR) vec, text, len);
}
}
extern void CatVec( VECSTR dest, VECSTR src )
/********************************************
* Append the contents of src onto dest, and do a FreeVec(src)
*/
{
ENTRYPTR walk;
ENTRYPTR cur;
walk = ((OURPTR)src)->d.head;
while( walk != NULL ) {
cur = walk;
walk = walk->next;
cpyTxt( dest, cur->text, cur->len );
myFree( cur );
}
((OURPTR)src)->next = freeVec;
freeVec = (OURPTR)src;
}
// TODO: If these functions work the way I think they do, all calls to
// Cat(N)StrToVec should be just replaced with Write(N)Vec - MN
extern void CatStrToVec( VECSTR dest, const char* str )
/******************************************************
* Concatenate the whole string ended by nullchar to the end of dest
*/
{
WriteVec( dest, str );
}
extern void CatNStrToVec( VECSTR dest, const char* str, size_t length )
/**********************************************************************
* Concatenate a string to the end of 'dest' with length 'length'
*/
{
WriteNVec( dest, str, length );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?