/* 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)
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <compilerconn.h>
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern char *input_filename
;
/* Put random information we might want to get back from
/* The connection to the Cadillac kernel. */
/* Input and output file descriptors for Cadillac. */
short fd_input
, fd_output
;
/* #include nesting of current file. */
/* State variables for the connection. */
/* #if level of current file. */
/* Line number that starts current source file. */
/* Name of current file. */
/* Where to stop processing (if process_until is set). */
static cadillac_struct cadillacObj
;
/* Nonzero if in the process of 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 ();
return select (32, &f
, NULL
, NULL
, 0) == 1;
static CObjectType
*tree_to_cadillac_map
;
struct obstack cadillac_obstack
;
/* 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 context_level tem
;
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
);
cadillac_struct
*cp
= &cadillacObj
;
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
;
on_exit (&exit_cadillac
, 0);
gcc_obstack_init (&cadillac_obstack
);
/* Yow! This is the way Cadillac was designed to deal with
cp
->fd_input
= flag_cadillac
;
cp
->fd_output
= flag_cadillac
;
/* Start in "turned-on" state. */
/* 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
);
fatal ("init_cadillac: EOF on connection to kernel, exiting\n");
perror ("Editor to kernel connection");
cadillac_process_requests (conn
)
while (req
= (CCompilerMessage
*) CPeekNextRequest (conn
))
req
= CReadCompilerMessage (conn
);
cadillac_process_request (&cadillacObj
, req
);
cadillac_process_request (cp
, req
)
/* This is not really right. */
cp
->end_position
= ((CCompilerCommand
*)req
)->processuntil
.position
;
cp
->end_filename
= req
->processuntil
.filename
;
switch (req
->header
.data
)
case FinishAnalysisCType
:
case ContinueAnalysisCType
:
fprintf (stderr
, "request type %d not implemented\n", req
->reqType
);
fatal ("unknown request type %d", req
->reqType
);
Connection
*conn
= cadillacObj
.conn
;
/* Let Cadillac know that we start in C++ language scope. */
CWriteHeader (conn
, ForeignLinkageMType
, LinkCPlus
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_printf (msg
, name
)
if (cadillacObj
.messages
)
printf ("[%s,%4d] %s `%s'\n", input_filename
, lineno
, msg
, name
);
cadillac_start_decl (decl
)
Connection
*conn
= cadillacObj
.conn
;
CObjectType object_type
= tree_to_cadillac_map
[TREE_CODE (decl
)];
switch (TREE_CODE (context_stack
->context
))
/* Currently, cadillac only implements top-level forms. */
cadillac_printf ("start class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl
)));
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
);
cadillac_finish_decl (decl
)
Connection
*conn
= cadillacObj
.conn
;
switch (TREE_CODE (context_stack
->context
))
cadillac_printf ("end class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl
)));
CWriteHeader (conn
, EndDefMType
, 0);
cadillac_printf ("end top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
)));
CWriteHeader (conn
, EndDefMType
, 0);
CWriteTopLevel (conn
, StopMType
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_start_function (fndecl
)
Connection
*conn
= cadillacObj
.conn
;
/* nested functions not yet handled. */
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
);
cadillac_finish_function (fndecl
)
Connection
*conn
= cadillacObj
.conn
;
cadillac_printf ("end top-level function", lang_printable_name (fndecl
));
context_stack
= pop_context_level (context_stack
);
/* nested functions not yet implemented. */
CWriteHeader (conn
, EndDefMType
, 0);
CWriteTopLevel (conn
, StopMType
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_finish_anon_union (decl
)
Connection
*conn
= cadillacObj
.conn
;
if (! global_bindings_p ())
cadillac_printf ("finish top-level anon union", "");
CWriteHeader (conn
, EndDefMType
, 0);
CWriteTopLevel (conn
, StopMType
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_start_enum (type
)
Connection
*conn
= cadillacObj
.conn
;
tree name
= TYPE_NAME (type
);
if (TREE_CODE (name
) == TYPE_DECL
)
switch (TREE_CODE (context_stack
->context
))
cadillac_printf ("start top-level enum", IDENTIFIER_POINTER (name
));
CWriteTopLevel (conn
, StartMType
);
CWriteLanguageType (conn
, type
, tree_to_cadillac_map
[ENUMERAL_TYPE
]);
cadillac_finish_enum (type
)
Connection
*conn
= cadillacObj
.conn
;
tree name
= TYPE_NAME (type
);
if (TREE_CODE (name
) == TYPE_DECL
)
switch (TREE_CODE (context_stack
->context
))
CWriteHeader (conn
, EndDefMType
, 0);
CWriteHeader (conn
, EndDefMType
, 0);
cadillac_printf ("finish top-level enum", IDENTIFIER_POINTER (name
));
CWriteTopLevel (conn
, StopMType
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_start_struct (type
)
Connection
*conn
= cadillacObj
.conn
;
tree name
= TYPE_NAME (type
);
if (TREE_CODE (name
) == TYPE_DECL
)
switch (TREE_CODE (context_stack
->context
))
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
)]);
cadillac_finish_struct (type
)
Connection
*conn
= cadillacObj
.conn
;
tree name
= TYPE_NAME (type
);
if (TREE_CODE (name
) == TYPE_DECL
)
context_stack
= pop_context_level (context_stack
);
cadillac_printf ("finish struct", IDENTIFIER_POINTER (name
));
CWriteHeader (conn
, EndDefMType
, 0);
CWriteTopLevel (conn
, StopMType
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_finish_exception (type
)
Connection
*conn
= cadillacObj
.conn
;
fatal ("cadillac_finish_exception");
CWriteHeader (conn
, EndDefMType
, 0);
CWriteTopLevel (conn
, StopMType
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_push_class (type
)
cadillac_push_lang (name
)
Connection
*conn
= cadillacObj
.conn
;
if (name
== lang_name_cplusplus
)
else if (name
== lang_name_c
)
CWriteHeader (conn
, ForeignLinkageMType
, m
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
Connection
*conn
= cadillacObj
.conn
;
CWriteHeader (conn
, ForeignLinkageMType
, LinkPop
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillacObj
.lineno
= lineno
;
cadillacObj
.filename
= input_filename
;
CWriteHeader (conn
, TopLevelFormMType
, m
);
cadillac_note_filepos ();
/* Eventually, this will point somewhere into the digest file. */
CWriteSomething (conn
, &context_id
, sizeof (BITS32
));
CWriteSomething (conn
, &cadillacObj
.iflevel
, sizeof (BITS32
));
int pos
= ftell (finput
);
CWriteSomething (cadillacObj
.conn
, &pos
, sizeof (BITS32
));
cadillac_switch_source (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
);
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
cadillac_switch_source (1);
cadillac_switch_source (0);
CWriteLanguageElem (conn
, p
, 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
);
/* Don't write date_type. */
CWriteVstring0 (conn
, "");
CWriteLanguageDecl (conn
, decl
, object_type
)
struct cadillac_mdep foo
;
CWriteHeader (conn
, LanguageElementMType
, StartDefineMType
);
foo
.object_type
= object_type
;
if (decl_type_context (decl
))
foo
.linkage
= ParentLinkage
;
foo
.access
= PrivateAccess
;
else if (TREE_PROTECTED (decl
))
foo
.access
= ProtectedAccess
;
foo
.access
= PublicAccess
;
foo
.linkage
= GlobalLinkage
;
foo
.linkage
= FileLinkage
;
foo
.access
= PublicAccess
;
foo
.length
= IDENTIFIER_LENGTH (name
);
CWriteLanguageElem (conn
, &foo
, IDENTIFIER_POINTER (name
));
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
CWriteLanguageType (conn
, type
, object_type
)
struct cadillac_mdep foo
;
tree name
= TYPE_NAME (type
);
CWriteHeader (conn
, LanguageElementMType
, StartDefineMType
);
foo
.object_type
= object_type
;
foo
.linkage
= ParentLinkage
;
foo
.access
= PrivateAccess
;
else if (TREE_PROTECTED (type
))
foo
.access
= ProtectedAccess
;
foo
.access
= PublicAccess
;
foo
.access
= PublicAccess
;
if (TREE_CODE (name
) == TYPE_DECL
)
foo
.length
= IDENTIFIER_LENGTH (name
);
CWriteLanguageElem (conn
, &foo
, IDENTIFIER_POINTER (name
));
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
CWriteUseObject (conn
, type
, object_type
, use
)
struct cadillac_mdep foo
;
CWriteHeader (conn
, LanguageElementMType
, use
);
foo
.object_type
= object_type
;
foo
.linkage
= ParentLinkage
;
foo
.access
= PrivateAccess
;
else if (TREE_PROTECTED (type
))
foo
.access
= ProtectedAccess
;
foo
.access
= PublicAccess
;
foo
.access
= PublicAccess
;
switch (TREE_CODE (type
))
foo
.length
= IDENTIFIER_LENGTH (name
);
CWriteLanguageElem (conn
, &foo
, IDENTIFIER_POINTER (name
));
CWriteRequestBuffer (conn
);
cadillac_process_requests (conn
);
/* Here's how we exit under cadillac. */
Connection
*conn
= cadillacObj
.conn
;
CWriteHeader (conn
, FinishedMType
,
errorcount
? 0 : CsObjectWritten
| CsComplete
);
CWriteRequestBuffer (conn
);
while (! readable_p (cadillacObj
.fd_input
))
req
= CReadCompilerMessage (conn
);
cadillac_process_request (&cadillacObj
, req
);
void cadillac_start () {}
void cadillac_start_decl (decl
)
cadillac_finish_decl (decl
)
cadillac_start_function (fndecl
)
cadillac_finish_function (fndecl
)
cadillac_finish_anon_union (decl
)
cadillac_start_enum (type
)
cadillac_finish_enum (type
)
cadillac_start_struct (type
)
cadillac_finish_struct (type
)
cadillac_finish_exception (type
)
cadillac_push_class (type
)
cadillac_push_lang (name
)
cadillac_switch_source ()