NetBSD/gnu/usr.bin/gcc/cc1plus/edsel.c
phil 34527405c3 Import gcc-2.7.2. Since it is in the gcc directory instead of the gcc2
directory, this is being done now.  We will live with two trees until
the "formal" switch over by changing src/gnu/usr.bin/Makefile.
1995-12-01 17:58:53 +00:00

929 lines
20 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Interface to LUCID Cadillac system for GNU compiler.
Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC 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, or (at your option)
any later version.
GNU CC 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "tree.h"
#include "flags.h"
#include <stdio.h>
#include "cp-tree.h"
#include "obstack.h"
#ifdef CADILLAC
#include <compilerreq.h>
#include <compilerconn.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/file.h>
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
void init_cadillac ();
extern char *input_filename;
extern int lineno;
/* Put random information we might want to get back from
Cadillac here. */
typedef struct
{
/* The connection to the Cadillac kernel. */
Connection *conn;
/* Input and output file descriptors for Cadillac. */
short fd_input, fd_output;
/* #include nesting of current file. */
short depth;
/* State variables for the connection. */
char messages;
char conversion;
char emission;
char process_until;
/* #if level of current file. */
int iflevel;
/* Line number that starts current source file. */
int lineno;
/* Name of current file. */
char *filename;
/* Where to stop processing (if process_until is set). */
char *end_filename;
int end_position;
} cadillac_struct;
static cadillac_struct cadillacObj;
/* Nonzero if in the process of exiting. */
static int exiting;
void cadillac_note_source ();
static void CWriteLanguageDecl ();
static void CWriteLanguageType ();
static void CWriteTopLevel ();
static void cadillac_note_filepos ();
static void cadillac_process_request (), cadillac_process_requests ();
static void cadillac_switch_source ();
static void exit_cadillac ();
/* Blocking test. */
static int
readable_p (fd)
int fd;
{
fd_set f;
FD_ZERO (&f);
FD_SET (fd, &f);
return select (32, &f, NULL, NULL, 0) == 1;
}
static CObjectType *tree_to_cadillac_map;
struct obstack cadillac_obstack;
#include "stack.h"
struct context_level
{
struct stack_level base;
tree context;
};
/* Stack for maintaining contexts (in case functions or types are nested).
When defining a struct type, the `context' field is the RECORD_TYPE.
When defining a function, the `context' field is the FUNCTION_DECL. */
static struct context_level *context_stack;
static struct context_level *
push_context_level (stack, obstack)
struct stack_level *stack;
struct obstack *obstack;
{
struct context_level tem;
tem.base.prev = stack;
return (struct context_level *)push_stack_level (obstack, &tem, sizeof (tem));
}
/* Discard a level of search allocation. */
static struct context_level *
pop_context_level (stack)
struct context_level *stack;
{
stack = (struct context_level *)pop_stack_level (stack);
return stack;
}
void
init_cadillac ()
{
extern FILE *finput;
extern int errno;
CCompilerMessage* req;
cadillac_struct *cp = &cadillacObj;
int i;
if (! flag_cadillac)
return;
tree_to_cadillac_map = (CObjectType*) xmalloc (sizeof (CObjectType) * LAST_CPLUS_TREE_CODE);
for (i = 0; i < LAST_CPLUS_TREE_CODE; i++)
tree_to_cadillac_map[i] = MiscOType;
tree_to_cadillac_map[RECORD_TYPE] = StructOType;
tree_to_cadillac_map[UNION_TYPE] = UnionOType;
tree_to_cadillac_map[ENUMERAL_TYPE] = EnumTypeOType;
tree_to_cadillac_map[TYPE_DECL] = TypedefOType;
tree_to_cadillac_map[VAR_DECL] = VariableOType;
tree_to_cadillac_map[CONST_DECL] = EnumConstantOType;
tree_to_cadillac_map[FUNCTION_DECL] = FunctionOType;
tree_to_cadillac_map[FIELD_DECL] = FieldOType;
#ifdef sun
on_exit (&exit_cadillac, 0);
#endif
gcc_obstack_init (&cadillac_obstack);
/* Yow! This is the way Cadillac was designed to deal with
Oregon C++ compiler! */
cp->fd_input = flag_cadillac;
cp->fd_output = flag_cadillac;
/* Start in "turned-on" state. */
cp->messages = 1;
cp->conversion = 1;
cp->emission = 1;
/* Establish a connection with Cadillac here. */
cp->conn = NewConnection (cp, cp->fd_input, cp->fd_output);
CWriteHeader (cp->conn, WaitingMType, 0);
CWriteRequestBuffer (cp->conn);
if (!readable_p (cp->fd_input))
;
req = CReadCompilerMessage (cp->conn);
if (!req)
switch (errno)
{
case EWOULDBLOCK:
sleep (5);
return;
case 0:
fatal ("init_cadillac: EOF on connection to kernel, exiting\n");
break;
default:
perror ("Editor to kernel connection");
exit (0);
}
}
static void
cadillac_process_requests (conn)
Connection *conn;
{
CCompilerMessage *req;
while (req = (CCompilerMessage*) CPeekNextRequest (conn))
{
req = CReadCompilerMessage (conn);
cadillac_process_request (&cadillacObj, req);
}
}
static void
cadillac_process_request (cp, req)
cadillac_struct *cp;
CCompilerMessage *req;
{
if (! req)
return;
switch (req->reqType)
{
case ProcessUntilMType:
if (cp->process_until)
my_friendly_abort (23);
cp->process_until = 1;
/* This is not really right. */
cp->end_position = ((CCompilerCommand*)req)->processuntil.position;
#if 0
cp->end_filename = req->processuntil.filename;
#endif
break;
case CommandMType:
switch (req->header.data)
{
case MessagesOnCType:
cp->messages = 1;
break;
case MessagesOffCType:
cp->messages = 0;
break;
case ConversionOnCType:
cp->conversion = 1;
break;
case ConversionOffCType:
cp->conversion = 0;
break;
case EmissionOnCType:
cp->emission = 1;
break;
case EmissionOffCType:
cp->emission = 0;
break;
case FinishAnalysisCType:
return;
case PuntAnalysisCType:
case ContinueAnalysisCType:
case GotoFileposCType:
case OpenSucceededCType:
case OpenFailedCType:
fprintf (stderr, "request type %d not implemented\n", req->reqType);
return;
case DieCType:
if (! exiting)
my_friendly_abort (24);
return;
}
break;
default:
fatal ("unknown request type %d", req->reqType);
}
}
void
cadillac_start ()
{
Connection *conn = cadillacObj.conn;
CCompilerMessage *req;
/* Let Cadillac know that we start in C++ language scope. */
CWriteHeader (conn, ForeignLinkageMType, LinkCPlus);
CWriteLength (conn);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
static void
cadillac_printf (msg, name)
{
if (cadillacObj.messages)
printf ("[%s,%4d] %s `%s'\n", input_filename, lineno, msg, name);
}
void
cadillac_start_decl (decl)
tree decl;
{
Connection *conn = cadillacObj.conn;
CObjectType object_type = tree_to_cadillac_map [TREE_CODE (decl)];
if (context_stack)
switch (TREE_CODE (context_stack->context))
{
case FUNCTION_DECL:
/* Currently, cadillac only implements top-level forms. */
return;
case RECORD_TYPE:
case UNION_TYPE:
cadillac_printf ("start class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl)));
break;
default:
my_friendly_abort (25);
}
else
{
cadillac_printf ("start top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
CWriteTopLevel (conn, StartMType);
}
CWriteLanguageDecl (conn, decl, tree_to_cadillac_map[TREE_CODE (decl)]);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_finish_decl (decl)
tree decl;
{
Connection *conn = cadillacObj.conn;
if (context_stack)
switch (TREE_CODE (context_stack->context))
{
case FUNCTION_DECL:
return;
case RECORD_TYPE:
case UNION_TYPE:
cadillac_printf ("end class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl)));
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
break;
default:
my_friendly_abort (26);
}
else
{
cadillac_printf ("end top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
CWriteTopLevel (conn, StopMType);
}
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_start_function (fndecl)
tree fndecl;
{
Connection *conn = cadillacObj.conn;
if (context_stack)
/* nested functions not yet handled. */
my_friendly_abort (27);
cadillac_printf ("start top-level function", lang_printable_name (fndecl));
context_stack = push_context_level (context_stack, &cadillac_obstack);
context_stack->context = fndecl;
CWriteTopLevel (conn, StartMType);
my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 202);
CWriteLanguageDecl (conn, fndecl,
(TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
? MemberFnOType : FunctionOType));
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_finish_function (fndecl)
tree fndecl;
{
Connection *conn = cadillacObj.conn;
cadillac_printf ("end top-level function", lang_printable_name (fndecl));
context_stack = pop_context_level (context_stack);
if (context_stack)
/* nested functions not yet implemented. */
my_friendly_abort (28);
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
CWriteTopLevel (conn, StopMType);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_finish_anon_union (decl)
tree decl;
{
Connection *conn = cadillacObj.conn;
if (! global_bindings_p ())
return;
cadillac_printf ("finish top-level anon union", "");
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
CWriteTopLevel (conn, StopMType);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_start_enum (type)
tree type;
{
Connection *conn = cadillacObj.conn;
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
if (context_stack)
switch (TREE_CODE (context_stack->context))
{
case FUNCTION_DECL:
return;
case RECORD_TYPE:
case UNION_TYPE:
break;
default:
my_friendly_abort (29);
}
else
{
cadillac_printf ("start top-level enum", IDENTIFIER_POINTER (name));
CWriteTopLevel (conn, StartMType);
}
CWriteLanguageType (conn, type, tree_to_cadillac_map[ENUMERAL_TYPE]);
}
void
cadillac_finish_enum (type)
tree type;
{
Connection *conn = cadillacObj.conn;
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
if (context_stack)
switch (TREE_CODE (context_stack->context))
{
case FUNCTION_DECL:
return;
case RECORD_TYPE:
case UNION_TYPE:
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
break;
default:
my_friendly_abort (30);
}
else
{
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
cadillac_printf ("finish top-level enum", IDENTIFIER_POINTER (name));
CWriteTopLevel (conn, StopMType);
}
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_start_struct (type)
tree type;
{
Connection *conn = cadillacObj.conn;
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
if (context_stack)
switch (TREE_CODE (context_stack->context))
{
case FUNCTION_DECL:
return;
case RECORD_TYPE:
case UNION_TYPE:
return;
default:
my_friendly_abort (31);
}
else
{
cadillac_printf ("start struct", IDENTIFIER_POINTER (name));
CWriteTopLevel (conn, StartMType);
}
context_stack = push_context_level (context_stack, &cadillac_obstack);
context_stack->context = type;
CWriteLanguageType (conn, type,
TYPE_LANG_SPECIFIC (type) && CLASSTYPE_DECLARED_CLASS (type) ? ClassOType : tree_to_cadillac_map[TREE_CODE (type)]);
}
void
cadillac_finish_struct (type)
tree type;
{
Connection *conn = cadillacObj.conn;
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
context_stack = pop_context_level (context_stack);
if (context_stack)
return;
cadillac_printf ("finish struct", IDENTIFIER_POINTER (name));
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
CWriteTopLevel (conn, StopMType);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_finish_exception (type)
tree type;
{
Connection *conn = cadillacObj.conn;
fatal ("cadillac_finish_exception");
CWriteHeader (conn, EndDefMType, 0);
CWriteLength (conn);
CWriteTopLevel (conn, StopMType);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_push_class (type)
tree type;
{
}
void
cadillac_pop_class ()
{
}
void
cadillac_push_lang (name)
tree name;
{
Connection *conn = cadillacObj.conn;
CLinkLanguageType m;
if (name == lang_name_cplusplus)
m = LinkCPlus;
else if (name == lang_name_c)
m = LinkC;
else
my_friendly_abort (32);
CWriteHeader (conn, ForeignLinkageMType, m);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_pop_lang ()
{
Connection *conn = cadillacObj.conn;
CWriteHeader (conn, ForeignLinkageMType, LinkPop);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_finish_stmt ()
{
}
void
cadillac_note_source ()
{
cadillacObj.lineno = lineno;
cadillacObj.filename = input_filename;
}
static void
CWriteTopLevel (conn, m)
Connection *conn;
CMessageSubType m;
{
static context_id = 0;
CWriteHeader (conn, TopLevelFormMType, m);
cadillac_note_filepos ();
/* Eventually, this will point somewhere into the digest file. */
context_id += 1;
CWriteSomething (conn, &context_id, sizeof (BITS32));
CWriteSomething (conn, &cadillacObj.iflevel, sizeof (BITS32));
CWriteLength (conn);
}
static void
cadillac_note_filepos ()
{
extern FILE *finput;
int pos = ftell (finput);
CWriteSomething (cadillacObj.conn, &pos, sizeof (BITS32));
}
void
cadillac_switch_source (startflag)
int startflag;
{
Connection *conn = cadillacObj.conn;
/* Send out the name of the source file being compiled. */
CWriteHeader (conn, SourceFileMType, startflag ? StartMType : StopMType);
CWriteSomething (conn, &cadillacObj.depth, sizeof (BITS16));
CWriteVstring0 (conn, input_filename);
CWriteLength (conn);
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
void
cadillac_push_source ()
{
cadillacObj.depth += 1;
cadillac_switch_source (1);
}
void
cadillac_pop_source ()
{
cadillacObj.depth -= 1;
cadillac_switch_source (0);
}
struct cadillac_mdep
{
short object_type;
char linkage;
char access;
short length;
};
static void
CWriteLanguageElem (conn, p, name)
Connection *conn;
struct cadillac_mdep *p;
char *name;
{
CWriteSomething (conn, &p->object_type, sizeof (BITS16));
CWriteSomething (conn, &p->linkage, sizeof (BITS8));
CWriteSomething (conn, &p->access, sizeof (BITS8));
CWriteSomething (conn, &p->length, sizeof (BITS16));
CWriteVstring0 (conn, name);
#if 0
/* Don't write date_type. */
CWriteVstring0 (conn, "");
#endif
CWriteLength (conn);
}
static void
CWriteLanguageDecl (conn, decl, object_type)
Connection *conn;
tree decl;
CObjectType object_type;
{
struct cadillac_mdep foo;
tree name;
CWriteHeader (conn, LanguageElementMType, StartDefineMType);
foo.object_type = object_type;
if (decl_type_context (decl))
{
foo.linkage = ParentLinkage;
if (TREE_PRIVATE (decl))
foo.access = PrivateAccess;
else if (TREE_PROTECTED (decl))
foo.access = ProtectedAccess;
else
foo.access = PublicAccess;
}
else
{
if (TREE_PUBLIC (decl))
foo.linkage = GlobalLinkage;
else
foo.linkage = FileLinkage;
foo.access = PublicAccess;
}
name = DECL_NAME (decl);
foo.length = IDENTIFIER_LENGTH (name);
CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
static void
CWriteLanguageType (conn, type, object_type)
Connection *conn;
tree type;
CObjectType object_type;
{
struct cadillac_mdep foo;
tree name = TYPE_NAME (type);
CWriteHeader (conn, LanguageElementMType, StartDefineMType);
foo.object_type = object_type;
if (current_class_type)
{
foo.linkage = ParentLinkage;
if (TREE_PRIVATE (type))
foo.access = PrivateAccess;
else if (TREE_PROTECTED (type))
foo.access = ProtectedAccess;
else
foo.access = PublicAccess;
}
else
{
foo.linkage = NoLinkage;
foo.access = PublicAccess;
}
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
foo.length = IDENTIFIER_LENGTH (name);
CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
static void
CWriteUseObject (conn, type, object_type, use)
Connection *conn;
tree type;
CObjectType object_type;
CMessageSubType use;
{
struct cadillac_mdep foo;
tree name = NULL_TREE;
CWriteHeader (conn, LanguageElementMType, use);
foo.object_type = object_type;
if (current_class_type)
{
foo.linkage = ParentLinkage;
if (TREE_PRIVATE (type))
foo.access = PrivateAccess;
else if (TREE_PROTECTED (type))
foo.access = ProtectedAccess;
else
foo.access = PublicAccess;
}
else
{
foo.linkage = NoLinkage;
foo.access = PublicAccess;
}
switch (TREE_CODE (type))
{
case VAR_DECL:
case FIELD_DECL:
case TYPE_DECL:
case CONST_DECL:
case FUNCTION_DECL:
name = DECL_NAME (type);
break;
default:
my_friendly_abort (33);
}
foo.length = IDENTIFIER_LENGTH (name);
CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name));
CWriteRequestBuffer (conn);
cadillac_process_requests (conn);
}
/* Here's how we exit under cadillac. */
static void
exit_cadillac ()
{
extern int errorcount;
Connection *conn = cadillacObj.conn;
if (flag_cadillac)
{
CCompilerMessage *req;
CWriteHeader (conn, FinishedMType,
errorcount ? 0 : CsObjectWritten | CsComplete);
/* Bye, bye! */
CWriteRequestBuffer (conn);
/* Block on read. */
while (! readable_p (cadillacObj.fd_input))
{
if (exiting)
my_friendly_abort (34);
exiting = 1;
}
exiting = 1;
req = CReadCompilerMessage (conn);
cadillac_process_request (&cadillacObj, req);
}
}
#else
/* Stubs. */
void init_cadillac () {}
void cadillac_start () {}
void cadillac_start_decl (decl)
tree decl;
{}
void
cadillac_finish_decl (decl)
tree decl;
{}
void
cadillac_start_function (fndecl)
tree fndecl;
{}
void
cadillac_finish_function (fndecl)
tree fndecl;
{}
void
cadillac_finish_anon_union (decl)
tree decl;
{}
void
cadillac_start_enum (type)
tree type;
{}
void
cadillac_finish_enum (type)
tree type;
{}
void
cadillac_start_struct (type)
tree type;
{}
void
cadillac_finish_struct (type)
tree type;
{}
void
cadillac_finish_exception (type)
tree type;
{}
void
cadillac_push_class (type)
tree type;
{}
void
cadillac_pop_class ()
{}
void
cadillac_push_lang (name)
tree name;
{}
void
cadillac_pop_lang ()
{}
void
cadillac_note_source ()
{}
void
cadillac_finish_stmt ()
{}
void
cadillac_switch_source ()
{}
void
cadillac_push_source ()
{}
void
cadillac_pop_source ()
{}
#endif