/* asn1-func2.c - More ASN.1 definitions
* Copyright (C) 2000, 2001 Fabio Fiorina
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2008, 2012 g10 Code GmbH
*
* This file is part of KSBA.
*
* KSBA is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - 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.
*
* or both in parallel, as here.
*
* KSBA 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 copies of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, see .
*/
/*
This file has functions which rely on on the asn1-gentables created
asn1-tables.c - we can't put this into asn1-func.c because this one
is needed by asn1-gentables ;-)
*/
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "ksba.h"
#include "asn1-func.h"
static AsnNode
set_right (AsnNode node, AsnNode right)
{
if (node == NULL)
return node;
node->right = right;
if (right)
right->left = node;
return node;
}
static AsnNode
set_down (AsnNode node, AsnNode down)
{
if (node == NULL)
return node;
node->down = down;
if (down)
down->left = node;
return node;
}
static AsnNode
find_up (AsnNode node)
{
AsnNode p;
if (node == NULL)
return NULL;
p = node;
while ((p->left != NULL) && (p->left->right == p))
p = p->left;
return p->left;
}
/**
* Creates the structures needed to manage the ASN1 definitions. ROOT is
* a vector created by the asn1-gentable tool.
*
* Input Parameter:
*
* Name of the module
*
* Output Parameter:
*
* KsbaAsntree *result : return the pointer to an object to be used
* with other functions.
*
* Return Value:
* 0: structure created correctly.
* GPG_ERR_GENERAL: an error occured while structure creation.
* GPG_ERR_MODULE_NOT_FOUND: No such module NAME
*/
gpg_error_t
ksba_asn_create_tree (const char *mod_name, ksba_asn_tree_t *result)
{
enum { DOWN, UP, RIGHT } move;
const static_asn *root;
const char *strgtbl;
AsnNode pointer;
AsnNode p = NULL;
AsnNode p_last = NULL;
unsigned long k;
int rc;
AsnNode link_next = NULL;
if (!result)
return gpg_error (GPG_ERR_INV_VALUE);
*result = NULL;
if (!mod_name)
return gpg_error (GPG_ERR_INV_VALUE);
root = _ksba_asn_lookup_table (mod_name, &strgtbl);
if (!root)
return gpg_error (GPG_ERR_MODULE_NOT_FOUND);
pointer = NULL;
move = UP;
k = 0;
while (root[k].stringvalue_off || root[k].type || root[k].name_off)
{
p = _ksba_asn_new_node (root[k].type);
p->flags = root[k].flags;
p->flags.help_down = 0;
p->link_next = link_next;
link_next = p;
if (root[k].name_off)
_ksba_asn_set_name (p, strgtbl + root[k].name_off);
if (root[k].stringvalue_off)
{
if (root[k].type == TYPE_TAG)
{
unsigned long val;
val = strtoul (strgtbl+root[k].stringvalue_off, NULL, 10);
_ksba_asn_set_value (p, VALTYPE_ULONG, &val, sizeof(val));
}
else
_ksba_asn_set_value (p, VALTYPE_CSTR,
strgtbl+root[k].stringvalue_off, 0);
}
if (!pointer)
pointer = p;
if (move == DOWN)
set_down (p_last, p);
else if (move == RIGHT)
set_right (p_last, p);
p_last = p;
if (root[k].flags.help_down)
move = DOWN;
else if (root[k].flags.help_right)
move = RIGHT;
else
{
while (1)
{
if (p_last == pointer)
break;
p_last = find_up (p_last);
if (p_last == NULL)
break;
if (p_last->flags.help_right)
{
p_last->flags.help_right = 0;
move = RIGHT;
break;
}
}
}
k++;
}
if (p_last == pointer)
{
ksba_asn_tree_t tree;
_ksba_asn_change_integer_value (pointer);
_ksba_asn_expand_object_id (pointer);
tree = xtrymalloc (sizeof *tree + strlen (mod_name));
if (!tree)
rc = gpg_error (GPG_ERR_ENOMEM);
else
{
tree->parse_tree = pointer;
tree->node_list = p;
strcpy (tree->filename, mod_name);
*result = tree;
rc = 0;
}
}
else
rc = gpg_error (GPG_ERR_GENERAL);
if (rc)
_ksba_asn_delete_structure (pointer);
return rc;
}