cScm Configuration Daemon

cScm – is a tool to convert SCM configuration files into binary format and store its in shared memory for reading by cSvn-ui and cGit-ui CGI scripts

12 Commits   0 Branches   1 Tag

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>

#include <defs.h>

#include <main.h>
#include <error.h>
#include <msglog.h>
#include <xalloc.h>
#include <utf8ing.h>
#include <lex.h>

#include <symtab.h>
#include <parse.h>


SYMBOL *symlist = NULL;

static SYMTAB *symtab  = NULL;

static int constants_counter = 0;
static int sections_counter  = 0;
static int repos_counter     = 0;


static SYMBOL *free_const( SYMBOL *sp )
{
  SYMBOL *next = NULL;

  if( !sp ) return next;

  next = sp->next;

  free( sp->name );

  switch( sp->type )
  {
    case STRING:
      if( sp->u.string ) free( sp->u.string );
      break;
    case PATH:
      if( sp->u.string ) free( sp->u.path );
      break;

    case NUMERICAL:
    default:
      break;
  }

  free( sp );

  return next;
}

static void free_symlist( SYMBOL *sp );

static SYMBOL *free_symbol( SYMBOL *sp )
{
  SYMBOL *next = NULL;

  if( !sp ) return next;

  if( sp->list ) (void)free_symlist( sp->list );

  next = sp->next;

  free( sp->name );

  switch( sp->type )
  {
    case SECTION:
    case STRING:
      if( sp->u.string ) free( sp->u.string );
      break;
    case REPO:
    case PATH:
      if( sp->u.string ) free( sp->u.path );
      break;

    case VARIABLE:
    case NUMERICAL:
    default:
      break;
  }

  free( sp );

  return next;
}

static void free_symlist( SYMBOL *sp )
{
  SYMBOL *next = NULL;

  if( !sp ) return;

  next = free_symbol( sp );
  while( next )
  {
    next = free_symbol( next );
  }
}

/******************************************
  Initialize the stak of symlist pointers:
 */
void init_symtab( void )
{
  SYMTAB *sa = (SYMTAB *)xmalloc( sizeof( SYMTAB ) );

  symtab  = NULL;
  symlist = NULL;

  constants_counter = 0;
  sections_counter  = 0;
  repos_counter     = 0;

  sa->symlist = (SYMBOL **)&symlist;
  sa->next = symtab;
  symtab = sa;
}


/*******************************************
  Push the address of symlist to the stack:
 */
void push_symlist( SYMBOL **head )
{
  if( head )
  {
    SYMTAB  *sa = (SYMTAB *)xmalloc( sizeof( SYMTAB ) );

    sa->symlist = head;
    sa->next = symtab;
    symtab = sa;
  }
}

/********************************************
  Pop the address of symlist from the stack:
 */
void pop_symlist( void )
{
  if( symtab && symtab->next )
  {
    SYMTAB *sa = symtab;
    symtab = symtab->next;
    free( sa );
  }
}

/************************************
  Free the stak of symlist pointers:
 */
void fini_symtab( void )
{
  if( !symtab ) return;

  while( symtab )
  {
    SYMTAB *sa = symtab;
    symtab = symtab->next;
    free( sa );
  }

  constants_counter = 0;
  sections_counter  = 0;
  repos_counter     = 0;

  symtab  = NULL;
  free_symlist( symlist ); /* free main symlist */
  symlist = NULL;
}


/******************************
  Reverse symlist recursively:
 */
void reverse_symlist( SYMBOL **head )
{
  SYMBOL *prev = NULL, *curr = *head, *next;

  while( curr )
  {
    if( curr->list ) reverse_symlist( (SYMBOL **)&(curr->list) );

    next = curr->next;
    curr->next = prev;
    prev = curr;
    curr = next;
  }

  *head = prev;
}

/******************************************************
  Remove temporary constants from symlist recursively:
 */
void remove_consts( SYMBOL **head )
{
  SYMBOL *tmp = NULL;

  while( *head )
  {
    tmp = *head;
    if( !strncmp( tmp->name, "__const.", 8 ) )
    {
      *head = tmp->next;
      (void)free_const( tmp );
    }
    else
    {
      head = &tmp->next;
      if( tmp->list ) remove_consts( (SYMBOL **)&(tmp->list) );
    }
  }
}


SYMBOL *assign_value( SYMBOL *dest, SYMBOL *src )
{
  SYMBOL *ret = NULL;

  if( !dest || !src ) return ret;

  if( dest->type == VARIABLE ) /* always not initialized */
  {
    dest->type = src->type;
    dest->u.value = 0;

    switch( src->type )
    {
      case NUMERICAL:
        dest->u.value = src->u.value;
        break;
      case STRING:
        dest->u.string = strdup( (const char *)src->u.string );
        break;
      case PATH:
        dest->u.path = strdup( (const char *)src->u.path );
        break;
      default:
        /* error */
        break;
    }
  }
  else if( dest->type == STRING || dest->type == SECTION )
  {
    switch( src->type )
    {
      case STRING:
        if( src->u.string )
        {
          if( dest->u.string ) free( dest->u.string );
          dest->u.string = strdup( (const char *)src->u.string );
        }
        else
        {
          if( dest->u.string ) free( dest->u.string );
          dest->u.string = NULL;
        }
        break;
      default:
        /* error */
        break;
    }
  }
  else if( dest->type == PATH || dest->type == REPO )
  {
    switch( src->type )
    {
      case PATH:
        if( src->u.path )
        {
          if( dest->u.path ) free( dest->u.path );
          dest->u.path = strdup( (const char *)src->u.path );
        }
        else
        {
          if( dest->u.path ) free( dest->u.path );
          dest->u.path = NULL;
        }
        break;
      default:
        /* error */
        break;
    }
  }
  else if( dest->type == src->type )
  {
    switch( src->type )
    {
      case NUMERICAL:
        dest->u.value = src->u.value;
        break;
      case STRING:
        if( dest->u.string ) free( dest->u.string );
        dest->u.string = strdup( (const char *)src->u.string );
        break;
      case PATH:
        if( dest->u.path ) free( dest->u.path );
        dest->u.path = strdup( (const char *)src->u.path );
        break;
      default:
        /* error */
        break;
    }
  }
  else
  {
    /* error */
  }

  return dest;
}


SYMBOL *install( const char *s, int type, ... )
{
  SYMBOL *sp       = NULL;
  char    name[80] = "__undef";

  if( !symtab ) return sp;

  va_list  argp;

  if( ! type ) return( sp );

  sp = (SYMBOL *)xmalloc( sizeof( SYMBOL ) );

  switch( type )
  {
    case NUMERICAL:
    case STRING:
    case PATH:
      sprintf( (char *)&name[0], "__const.%d", constants_counter++ );
      sp->name = strdup( (const char *)&name[0] );
      break;
    case REPO:
      sprintf( (char *)&name[0], "__repo.%d", repos_counter++ );
      sp->name = strdup( (const char *)&name[0] );
      break;
    case SECTION:
      sprintf( (char *)&name[0], "__section.%d", sections_counter++ );
      sp->name = strdup( (const char *)&name[0] );
      break;
    default:
      if( !s )
        sp->name = strdup( (const char *)&name[0] );
      else
        sp->name = strdup( s );
      break;
  }
  sp->type  = type;

  va_start( argp, type );

  switch( type )
  {
    case SECTION:
    case STRING:
    {
      char *string = (char *)va_arg( argp, char * );
      if( string ) sp->u.string = strdup( (const char *)string );
      break;
    }
    case REPO:
    case PATH:
    {
      char *path = (char *)va_arg( argp, char * );
      if( path ) sp->u.path = strdup( (const char *)path );
      break;
    }

    case VARIABLE:
    case NUMERICAL:
    default:
      sp->u.value = (int)va_arg( argp, int );
      break;
  }

  sp->next  = *(symtab->symlist);  /* alloc in begin of list */
  *(symtab->symlist) = sp;

  return( sp );
}

/***********************************
  Find variable in current symlist:
 */
SYMBOL *lookup( const char *s )
{
  SYMBOL *sp;

  for( sp = *(symtab->symlist); sp != (SYMBOL *)0; sp = sp->next )
  {
    if( strcmp( sp->name, s ) == 0 ) return( sp );
  }

  return( 0 );  /* запись не найдена */
}

/*********************************
  Find section in global symlist:
 */
SYMBOL *lookup_section( const char *s )
{
  SYMBOL *sp;

  for( sp = symlist; sp != (SYMBOL *)0; sp = sp->next )
  {
    if( sp->type == SECTION && sp->u.string && strcmp( sp->u.string, s ) == 0 ) return( sp );
  }

  return( 0 );  /* запись не найдена */
}

/********************************
  Find repo globally in symlist:
 */
#if 0
SYMBOL *lookup_repo_global( const char *s )
{
  SYMBOL *sp;

  for( sp = symlist; sp != (SYMBOL *)0; sp = sp->next )
  {
    /***************************
      lookup in global section:
     */
    if( sp->type == REPO && sp->u.path && strcmp( sp->u.path, s ) == 0 ) return( sp );

    /*************************
      lookup in each section:
     */
    if( sp->type == SECTION && sp->list )
    {
      SYMBOL *rp;
      for( rp = sp->list; rp != (SYMBOL *)0; rp = rp->next )
      {
        if( rp->type == REPO && rp->u.path && strcmp( rp->u.path, s ) == 0 ) return( rp );
      }
    }
  }

  return( 0 );  /* запись не найдена */
}
#endif

/*******************************
  Find repo in current symlist:
 */
SYMBOL *lookup_repo( const char *s )
{
  SYMBOL *sp;

  for( sp = *(symtab->symlist); sp != (SYMBOL *)0; sp = sp->next )
  {
    if( sp->type == REPO && sp->u.path && strcmp( sp->u.path, s ) == 0 ) return( sp );
  }

  return( 0 );  /* запись не найдена */
}