#include "config.h"
#include "libdwarfdefs.h"
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include "pro_incl.h"
#include "dwarf.h"
#include "libdwarf.h"
#include "pro_opaque.h"
#include "dwarfstring.h"
static int
translatetosigned(char *s,Dwarf_Signed *v, UNUSEDARG int *err)
{
unsigned char *cp = (unsigned char *)s;
unsigned char *digits = (unsigned char *)s;
int signmult = 1;
Dwarf_Signed l = 0;
if (*cp == '0' &&
(*(cp+1) == 'x'|| (*(cp+1) == 'X'))) {
digits += 2;
cp = digits;
for( ; *cp; cp++) {
l = l << 4;
switch (*cp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
l += (*cp - '0');
break;
case 'a':
case 'A':
l += 10;
break;
case 'b':
case 'B':
l += 11;
break;
case 'c':
case 'C':
l += 12;
break;
case 'd':
case 'D':
l += 13;
break;
case 'e':
case 'E':
l += 14;
break;
case 'f':
case 'F':
l += 15;
break;
default:
#ifdef TESTING
printf("ERROR in hex string \"%s\" "
"bad character 0x%x, line %d %s\n",
s,*cp,__LINE__,__FILE__);
#endif
*err = DW_DLE_HEX_STRING_ERROR;
return DW_DLV_ERROR;
}
}
*v = l;
return DW_DLV_OK;
} else if (*cp == '-') {
signmult = -1;
digits ++;
}
cp = digits;
for( ; *cp; cp++) {
l = l * 10;
switch (*cp) {
case '9':
case '8':
case '7':
case '6':
case '5':
case '4':
case '3':
case '2':
case '1':
case '0':
l += (*cp - '0');
break;
default:
#ifdef TESTING
printf("ERROR in decimal string \"%s\", "
"bad character 0x%x, line %d %s\n",
s,*cp,__LINE__,__FILE__);
#endif
*err = DW_DLE_DECIMAL_STRING_ERROR;
return DW_DLV_ERROR;
}
}
*v = signmult * l;
return DW_DLV_OK;
}
static int
update_named_field(Dwarf_P_Debug dbg, dwarfstring *cmsname,dwarfstring *cmsvalue,
int *err)
{
char *name = dwarfstring_string(cmsname);
char *value = dwarfstring_string(cmsvalue);
Dwarf_Signed v = 0;
int res;
res = translatetosigned(value,&v,err);
if (res != DW_DLV_OK) {
return res;
}
if ( dwarfstring_strlen(cmsvalue) == 0) {
return DW_DLV_NO_ENTRY;
}
if (!strcmp(name,"default_is_stmt")) {
dbg->de_line_inits.pi_default_is_stmt = (unsigned)v;
} else if (!strcmp(name,"minimum_instruction_length")) {
dbg->de_line_inits.pi_minimum_instruction_length = (unsigned)v;
} else if (!strcmp(name,"maximum_operations_per_instruction")) {
dbg->de_line_inits.pi_maximum_operations_per_instruction = (unsigned)v;
} else if (!strcmp(name,"opcode_base")) {
dbg->de_line_inits.pi_opcode_base = (unsigned)v;
} else if (!strcmp(name,"line_base")) {
dbg->de_line_inits.pi_line_base = (int)v;
} else if (!strcmp(name,"line_range")) {
dbg->de_line_inits.pi_line_range = (int)v;
} else if (!strcmp(name,"linetable_version")) {
dbg->de_line_inits.pi_linetable_version = (unsigned)v;
dbg->de_output_version = (unsigned)v;
} else if (!strcmp(name,"segment_selector_size")) {
dbg->de_line_inits.pi_segment_selector_size = (unsigned)v;
} else if (!strcmp(name,"segment_size")) {
dbg->de_line_inits.pi_segment_size = (unsigned)v;
} else if (!strcmp(name,"address_size")) {
dbg->de_line_inits.pi_address_size = (unsigned)v;
dbg->de_pointer_size = (unsigned)v;
} else {
#ifdef TESTING
printf("ERROR due to unknown string \"%s\", line %d %s\n",
name,__LINE__,__FILE__);
#endif
*err = DW_DLE_PRO_INIT_EXTRAS_UNKNOWN;
return DW_DLV_ERROR;
}
return DW_DLV_OK;
}
static int
update_named_value(Dwarf_P_Debug dbg, dwarfstring*cms,
int *err)
{
char * str = dwarfstring_string(cms);
char *cp = str;
char * value_start = 0;
dwarfstring cmsname;
dwarfstring cmsvalue;
unsigned slen = 0;
int res = 0;
dwarfstring_constructor(&cmsname);
dwarfstring_constructor(&cmsvalue);
for ( ; *cp && *cp != '=' && *cp != ' '; cp++) { }
if (! *cp) {
dwarfstring_destructor(&cmsname);
dwarfstring_destructor(&cmsvalue);
return DW_DLV_NO_ENTRY;
}
if (*cp == ' ') {
dwarfstring_destructor(&cmsname);
dwarfstring_destructor(&cmsvalue);
#ifdef TESTING
printf("ERROR due to trailing spaces before = in \"%s\", line %d %s\n",
cp,__LINE__,__FILE__);
#endif
*err = DW_DLE_PRO_INIT_EXTRAS_ERR;
return DW_DLV_ERROR;
}
slen = cp - str;
dwarfstring_append_length(&cmsname,str,slen);
cp++;
value_start = cp;
for ( ; *cp && *cp != ' '; cp++) { }
slen = cp - value_start;
if (slen) {
dwarfstring_append_length(&cmsvalue,value_start,slen);
} else {
dwarfstring_destructor(&cmsname);
dwarfstring_destructor(&cmsvalue);
return DW_DLV_NO_ENTRY;
}
res = update_named_field(dbg,&cmsname,&cmsvalue,err);
dwarfstring_destructor(&cmsname);
dwarfstring_destructor(&cmsvalue);
return res;
}
static int
find_next_comma(const char *base,const char **nextcomma)
{
const char *cp = base;
for( ; *cp ; ++cp) {
if (*cp == ',') {
*nextcomma = cp;
return DW_DLV_OK;
}
}
*nextcomma = cp;
return DW_DLV_OK;
}
int
_dwarf_log_extra_flagstrings(Dwarf_P_Debug dbg,
const char *extra,
int *err)
{
int res = 0;
const char *nextcharloc = 0;
const char *nextcomma = 0;
dwarfstring cms;
dwarfstring input;
if (!extra || !*extra) {
return DW_DLV_NO_ENTRY;
}
dwarfstring_constructor(&cms);
dwarfstring_constructor(&input);
dwarfstring_append(&input,(char *)extra);
dwarfstring_append(&input,(char *)",");
nextcharloc = dwarfstring_string(&input);
while (1) {
dwarfstring_reset(&cms);
find_next_comma(nextcharloc,&nextcomma);
{
unsigned len = nextcomma - nextcharloc;
if (len > 0) {
dwarfstring_append_length(&cms,(char *)nextcharloc,
len);
res = update_named_value(dbg,&cms,err);
if (res == DW_DLV_ERROR) {
dwarfstring_destructor(&cms);
dwarfstring_destructor(&input);
return res;
}
} else {
}
if (!(nextcomma[1])) {
dwarfstring_destructor(&cms);
dwarfstring_destructor(&input);
return DW_DLV_OK;
}
nextcharloc = nextcomma+1;
}
}
dwarfstring_destructor(&input);
dwarfstring_destructor(&cms);
return DW_DLV_OK;
}