binutils-gdb/gdb/scm-lang.c
Per Bothner 5b4d668a82 * scm-lang.c: Moved Scheme value printing code to ...
* scm-valprint.c:  ... this new file.
	Also major improvements in support for printing SCM values.
	* scm-lang.h:  New file.
	* scm-tags.h:  New file.
	* Makefile.in:  Note new scm-valprint.{c,o}.
1995-09-30 23:36:40 +00:00

392 lines
7.8 KiB
C

/* Scheme/Guile language support routines for GDB, the GNU debugger.
Copyright 1995 Free Software Foundation, Inc.
This file is part of GDB.
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 "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
#include "value.h"
#include "c-lang.h"
#include "scm-lang.h"
#include "scm-tags.h"
extern struct type ** const (c_builtin_types[]);
extern value_ptr value_allocate_space_in_inferior PARAMS ((int));
extern value_ptr find_function_in_inferior PARAMS ((char*));
static void scm_lreadr ();
struct type *SCM_TYPE = NULL;
static void
scm_read_token (c, weird)
int c;
int weird;
{
while (1)
{
c = *lexptr++;
switch (c)
{
case '[':
case ']':
case '(':
case ')':
case '\"':
case ';':
case ' ': case '\t': case '\r': case '\f':
case '\n':
if (weird)
goto default_case;
case '\0': /* End of line */
eof_case:
--lexptr;
return;
case '\\':
if (!weird)
goto default_case;
else
{
c = *lexptr++;
if (c == '\0')
goto eof_case;
else
goto default_case;
}
case '}':
if (!weird)
goto default_case;
c = *lexptr++;
if (c == '#')
return;
else
{
--lexptr;
c = '}';
goto default_case;
}
default:
default_case:
;
}
}
}
static int
scm_skip_ws ()
{
register int c;
while (1)
switch ((c = *lexptr++))
{
case '\0':
goteof:
return c;
case ';':
lp:
switch ((c = *lexptr++))
{
case '\0':
goto goteof;
default:
goto lp;
case '\n':
break;
}
case ' ': case '\t': case '\r': case '\f': case '\n':
break;
default:
return c;
}
}
static void
scm_lreadparen ()
{
for (;;)
{
int c = scm_skip_ws ();
if (')' == c || ']' == c)
return;
--lexptr;
if (c == '\0')
error ("missing close paren");
scm_lreadr ();
}
}
static void
scm_lreadr ()
{
int c, j;
tryagain:
c = *lexptr++;
switch (c)
{
case '\0':
lexptr--;
return;
case '[':
case '(':
scm_lreadparen ();
return;
case ']':
case ')':
error ("unexpected #\\%c", c);
goto tryagain;
case '\'':
case '`':
scm_lreadr ();
return;
case ',':
c = *lexptr++;
if ('@' != c)
lexptr--;
scm_lreadr ();
return;
case '#':
c = *lexptr++;
switch (c)
{
case '[':
case '(':
scm_lreadparen ();
return;
case 't': case 'T':
case 'f': case 'F':
return;
case 'b': case 'B':
case 'o': case 'O':
case 'd': case 'D':
case 'x': case 'X':
case 'i': case 'I':
case 'e': case 'E':
lexptr--;
c = '#';
goto num;
case '*': /* bitvector */
scm_read_token (c, 0);
return;
case '{':
scm_read_token (c, 1);
return;
case '\\': /* character */
c = *lexptr++;
scm_read_token (c, 0);
return;
case '|':
j = 1; /* here j is the comment nesting depth */
lp:
c = *lexptr++;
lpc:
switch (c)
{
case '\0':
error ("unbalanced comment");
default:
goto lp;
case '|':
if ('#' != (c = *lexptr++))
goto lpc;
if (--j)
goto lp;
break;
case '#':
if ('|' != (c = *lexptr++))
goto lpc;
++j;
goto lp;
}
goto tryagain;
case '.':
default:
callshrp:
scm_lreadr ();
return;
}
case '\"':
while ('\"' != (c = *lexptr++))
{
if (c == '\\')
switch (c = *lexptr++)
{
case '\0':
error ("non-terminated string literal");
case '\n':
continue;
case '0':
case 'f':
case 'n':
case 'r':
case 't':
case 'a':
case 'v':
break;
}
}
return;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
case '-':
case '+':
num:
scm_read_token (c, 0);
return;
case ':':
scm_read_token ('-', 0);
return;
default:
scm_read_token (c, 0);
tok:
return;
}
}
int
scm_parse ()
{
char* start;
struct stoken str;
while (*lexptr == ' ')
lexptr++;
start = lexptr;
scm_lreadr ();
str.length = lexptr - start;
str.ptr = start;
write_exp_elt_opcode (OP_EXPRSTRING);
write_exp_string (str);
write_exp_elt_opcode (OP_EXPRSTRING);
return 0;
}
void
scm_printchar (c, stream)
int c;
GDB_FILE *stream;
{
fprintf_filtered (stream, "#\\%c", c);
}
static void
scm_printstr (stream, string, length, force_ellipses)
GDB_FILE *stream;
char *string;
unsigned int length;
int force_ellipses;
{
fprintf_filtered (stream, "\"%s\"", string);
}
int
is_scmvalue_type (type)
struct type *type;
{
if (TYPE_CODE (type) == TYPE_CODE_INT
&& TYPE_NAME (type) && strcmp (TYPE_NAME (type), "SCM") == 0)
{
SCM_TYPE = type;
return 1;
}
return 0;
}
/* Get the INDEX'th SCM value, assuming SVALUE is the address
of the 0'th one. */
LONGEST
scm_get_field (svalue, index)
LONGEST svalue;
int index;
{
value_ptr val;
char buffer[20];
if (SCM_TYPE == NULL)
error ("internal error - no SCM type");
read_memory (SCM2PTR (svalue) + index * TYPE_LENGTH (SCM_TYPE),
buffer, TYPE_LENGTH (SCM_TYPE));
return unpack_long (SCM_TYPE, buffer);
}
static value_ptr
evaluate_subexp_scm (expect_type, exp, pos, noside)
struct type *expect_type;
register struct expression *exp;
register int *pos;
enum noside noside;
{
enum exp_opcode op = exp->elts[*pos].opcode;
value_ptr func, addr;
int len, pc; char *str;
switch (op)
{
case OP_EXPRSTRING:
pc = (*pos)++;
len = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
if (noside == EVAL_SKIP)
goto nosideret;
str = &exp->elts[ + 2].string;
addr = value_allocate_space_in_inferior (len);
write_memory (value_as_long (addr), str, len);
func = find_function_in_inferior ("scm_evstr");
return call_function_by_hand (func, 1, &addr);
default: ;
}
return evaluate_subexp_standard (expect_type, exp, pos, noside);
nosideret:
return value_from_longest (builtin_type_long, (LONGEST) 1);
}
const struct language_defn scm_language_defn = {
"scheme", /* Language name */
language_scm,
c_builtin_types,
range_check_off,
type_check_off,
scm_parse,
c_error,
evaluate_subexp_scm,
scm_printchar, /* Print a character constant */
scm_printstr, /* Function to print string constant */
NULL, /* Create fundamental type in this language */
c_print_type, /* Print a type using appropriate syntax */
scm_val_print, /* Print a value using appropriate syntax */
scm_value_print, /* Print a top-level value */
{"", "", "", ""}, /* Binary format info */
{"#o%lo", "#o", "o", ""}, /* Octal format info */
{"%ld", "", "d", ""}, /* Decimal format info */
{"#x%lX", "#X", "X", ""}, /* Hex format info */
NULL, /* expression operators for printing */
1, /* c-style arrays */
0, /* String lower bound */
&builtin_type_char, /* Type of string elements */
LANG_MAGIC
};
void
_initialize_scheme_language ()
{
add_language (&scm_language_defn);
}