You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

372 lines
9.5 KiB

/*******************************************************************
* Description: encode/decode attribute lists
*
* Originated: 03-06-2000
* Original Author: Mike Day - md@soft-hackle.net
*
* Copyright (C) Michael Day, 2000-2001
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*******************************************************************/
%{
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "slp_attr.h"
#include "slp_linkedlist.h"
/* prototypes and globals go here */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#define yymaxdepth slp_attr_maxdepth
#define yyparse slp_attr_parse
#define yylex slp_attr_lex
#define yyerror slp_attr_error
#define yylval slp_attr_lval
#define yychar slp_attr_char
#define yydebug slp_attr_debug
#define yypact slp_attr_pact
#define yyr1 slp_attr_r1
#define yyr2 slp_attr_r2
#define yydef slp_attr_def
#define yychk slp_attr_chk
#define yypgo slp_attr_pgo
#define yyact slp_attr_act
#define yyexca slp_attr_exca
#define yyerrflag slp_attr_errflag
#define yynerrs slp_attr_nerrs
#define yyps slp_attr_ps
#define yypv slp_attr_pv
#define yys slp_attr_s
#define yy_yys slp_attr_yys
#define yystate slp_attr_state
#define yytmp slp_attr_tmp
#define yyv slp_attr_v
#define yy_yyv slp_attr_yyv
#define yyval slp_attr_val
#define yylloc slp_attr_lloc
#define yyreds slp_attr_reds
#define yytoks slp_attr_toks
#define yylhs slp_attr_yylhs
#define yylen slp_attr_yylen
#define yydefred slp_attr_yydefred
#define yydgoto slp_attr_yydgoto
#define yysindex slp_attr_yysindex
#define yyrindex slp_attr_yyrindex
#define yygindex slp_attr_yygindex
#define yytable slp_attr_yytable
#define yycheck slp_attr_yycheck
#define yyname slp_attr_yyname
#define yyrule slp_attr_yyrule
static int bt = TRUE;
static int bf = FALSE;
static SLPAttrList attrHead = {&attrHead, &attrHead, TRUE, NULL, head, {0L}};
static SLPAttrList inProcessAttr = {&inProcessAttr, &inProcessAttr, TRUE, NULL, head, {0L}};
static SLPAttrList inProcessTag = {&inProcessTag, &inProcessTag, TRUE, NULL, head, {0L}};
int slp_attr_parse(void);
void slp_attr_error(char *, ...);
int slp_attr_wrap(void);
int slp_attr_lex(void);
void slp_attr_close_lexer(unsigned int handle);
unsigned int slp_attr_init_lexer(char *s);
%}
/* definitions for ytab.h */
%union
{
int _i;
char *_s;
SLPAttrList *_atl;
}
%token<_i> _TRUE _FALSE _MULTIVAL _INT
%token<_s> _ESCAPED _TAG _STRING
/* typecast the non-terminals */
/* %type <_i> */
%type <_atl> attr_list attr attr_val_list attr_val
%%
attr_list: attr
{
while ( !SLP_IS_HEAD(inProcessAttr.next) )
{
$$ = inProcessAttr.next;
SLP_UNLINK($$);
SLP_INSERT_BEFORE($$, &attrHead);
}
/* all we really want to do here is link each attribute */
/* to the global list head. */
}
| attr_list ',' attr
{
/* both of these non-terminals are really lists */
/* ignore the first non-terminal */
while ( !SLP_IS_HEAD(inProcessAttr.next) )
{
$$ = inProcessAttr.next;
SLP_UNLINK($$);
SLP_INSERT_BEFORE($$, &attrHead);
}
};
attr: _TAG
{
$$ = SLPAllocAttr($1, tag, NULL, 0);
if ( NULL != $$ )
{
SLP_INSERT_BEFORE($$, &inProcessAttr);
}
}
| '(' _TAG ')'
{
$$ = SLPAllocAttr($2, tag, NULL, 0);
if (NULL != $$)
{
SLP_INSERT_BEFORE($$, &inProcessAttr);
}
}
| '(' _TAG '=' attr_val_list ')'
{
$$ = inProcessTag.next;
while (!SLP_IS_HEAD($$))
{
$$->name = strdup($2);
SLP_UNLINK($$);
SLP_INSERT_BEFORE($$, &inProcessAttr);
$$ = inProcessTag.next;
}
};
attr_val_list: attr_val
{
if(NULL != $1)
{
SLP_INSERT($1, &inProcessTag);
}
}
| attr_val_list _MULTIVAL attr_val
{
if (NULL != $3)
{
SLP_INSERT_BEFORE($3, &inProcessTag);
}
};
attr_val: _TRUE
{
$$ = SLPAllocAttr(NULL, boolean, &bt, sizeof(int));
}
| _FALSE
{
$$ = SLPAllocAttr(NULL, boolean, &bf, sizeof(int));
}
| _ESCAPED
{
/* treat it as a string because it is already encoded */
$$ = SLPAllocAttr(NULL, string, $1, strlen($1) + 1);
}
| _STRING
{
$$ = SLPAllocAttr(NULL, string, $1, strlen($1) + 1);
}
| _INT
{
$$ = SLPAllocAttr(NULL, integer, &($1), sizeof(int));
};
%%
SLPAttrList *SLPAllocAttr(char *name, SLPTypes type, void *val, int len)
{
SLPAttrList *attr;
if ( NULL != (attr = (SLPAttrList *)calloc(1, sizeof(SLPAttrList))) )
{
if ( name != NULL )
{
if ( NULL == (attr->name = strdup(name)) )
{
free(attr);
return(NULL);
}
}
attr->type = type;
if ( type == head ) /* listhead */
return(attr);
if ( val != NULL )
{
switch ( type )
{
case string:
if ( NULL != (attr->val.stringVal = strdup((unsigned char *)val)) )
return(attr);
break;
case integer:
attr->val.intVal = *(unsigned int *)val;
break;
case boolean:
attr->val.boolVal = *(int *)val;
break;
case opaque:
#if 0
if ( len > 0 )
{
int encLen;
opq_EncodeOpaque(val, len, (char **)&(attr->val.opaqueVal), &encLen);
if ( NULL != attr->val.opaqueVal )
{
/* first two bytes contain length of attribute */
SLP_SETSHORT(((char *)attr->val.opaqueVal), encLen, 0 );
}
}
#endif
break;
default:
break;
}
}
}
return(attr);
}
SLPAttrList *SLPAllocAttrList(void)
{
SLPAttrList *temp;
if ( NULL != (temp = SLPAllocAttr(NULL, head, NULL, 0)) )
{
temp->next = temp->prev = temp;
temp->isHead = TRUE;
}
return(temp);
}
/* attr MUST be unlinked from its list ! */
void SLPFreeAttr(SLPAttrList *attr)
{
if ( attr->name != NULL )
{
free(attr->name);
}
if ( attr->type == string && attr->val.stringVal != NULL )
{
free(attr->val.stringVal);
}
else if ( attr->type == opaque && attr->val.opaqueVal != NULL )
{
free(attr->val.opaqueVal);
}
free(attr);
}
void SLPFreeAttrList(SLPAttrList *list, int staticFlag)
{
SLPAttrList *temp;
while ( ! (SLP_IS_EMPTY(list)) )
{
temp = list->next;
SLP_UNLINK(temp);
SLPFreeAttr(temp);
}
if ( staticFlag == TRUE )
{
SLPFreeAttr(list);
}
return;
}
void SLPInitInternalAttrList(void)
{
attrHead.next = attrHead.prev = &attrHead;
attrHead.isHead = TRUE;
inProcessAttr.next = inProcessAttr.prev = &inProcessAttr;
inProcessAttr.isHead = TRUE;
inProcessTag.next = inProcessTag.prev = &inProcessTag;
inProcessTag.isHead = TRUE;
return;
}
SLPAttrList *_SLPDecodeAttrString(char *s)
{
unsigned int lexer = 0;
SLPAttrList *temp = NULL;
SLPInitInternalAttrList();
if ( s != NULL )
{
if ( NULL != (temp = SLPAllocAttrList()) )
{
if ((0 != (lexer = slp_attr_init_lexer(s))) && yyparse() )
{
SLPFreeAttrList(temp,0);
while ( !SLP_IS_HEAD(inProcessTag.next) )
{
temp = inProcessTag.next;
SLP_UNLINK(temp);
SLPFreeAttr(temp);
}
while ( !SLP_IS_HEAD(inProcessAttr.next) )
{
temp = inProcessAttr.next;
SLP_UNLINK(temp);
SLPFreeAttr(temp);
}
while ( !SLP_IS_HEAD(attrHead.next) )
{
temp = attrHead.next;
SLP_UNLINK(temp);
SLPFreeAttr(temp);
}
slp_attr_close_lexer(lexer);
return(NULL);
}
if ( !SLP_IS_EMPTY(&attrHead) )
{
SLP_LINK_HEAD(temp, &attrHead);
}
if ( lexer != 0 )
{
slp_attr_close_lexer(lexer);
}
}
}
return(temp);
}