home *** CD-ROM | disk | FTP | other *** search
- /* Interface to LUCID Cadillac system for GNU compiler.
- Copyright (C) 1988, 1992 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, 675 Mass Ave, Cambridge, MA 02139, 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
-