4.3BSD/usr/contrib/courier/compiler/code2.c

Compare this file to the similar file:
Show the results in this format:

#ifndef lint
static char sccsid[] = "@(#)code2.c	4.1 (Berkeley) 7/3/83";
#endif

#include "Courier.h"

/*
 * Generate functions for user and server calls to a procedure.
 */
proc_functions(proc_name, type, value)
	char *proc_name;
	struct object *type, *value;
{
	list p, q;
	int nresults;
	struct object *t, *result_type;
	char *result_name, *func, *ref;

	/*
	 * Make sure there is at most one result returned.
	 */
	nresults = length(type->t_results);
	if (nresults == 1)
		/* could be multiple names with one type */
		nresults = length(car(car(type->t_results)));
	if (nresults > 1) {
		yyerror("Procedures that return multiple results are not supported");
		return;
	}
	if (nresults) {
		result_name = name_of(car(car(car(type->t_results))));
		result_type = (struct object *) cdr(car(type->t_results));
	}

	/*
	 * Server routine.
	 */
	if (nresults) {
		fprintf(sf, "\nextern ");
		print_decl(sf, proc_name, result_type, 1);
		fprintf(sf, "();\n");
	} else
		fprintf(sf, "\nextern void %s();\n", proc_name);
	fprintf(sf,
"\nServer_%s(_buf)\n\
\tregister Unspecified *_buf;\n\
{\n\
\tregister Unspecified *_bp;\n\
\tregister LongCardinal _n;\n",
		proc_name);
	print_level++;
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		t = (struct object *) cdr(car(p));
		for (q = car(car(p)); q != NIL; q = cdr(q))
			print_decl(sf, name_of(car(q)), t, 0);
	}
	if (nresults)
		print_decl(sf, result_name, result_type, 0);
	print_level--;
	fprintf(sf, "\n\t_bp = _buf;\n");
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		t = (struct object *) cdr(car(p));
		ref = refstr(t);
		for (q = car(car(p)); q != NIL; q = cdr(q))
			fprintf(sf, "\t_bp += %s(%s%s, _bp);\n",
				unpack_function(t), ref, name_of(car(q)));
	}
	if (nresults)
		fprintf(sf, "\t%s = %s(", result_name, proc_name);
	else
		fprintf(sf, "\t%s(", proc_name);
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		for (q = car(car(p)); q != NIL; q = cdr(q)) {
			fprintf(sf, "%s", name_of(car(q)));
			if (cdr(q) != NIL)
				fprintf(sf, ", ");
		}
		if (cdr(p) != NIL)
			fprintf(sf, ", ");
	}
	fprintf(sf, ");\n");
	if (nresults) {
		func = pack_function(result_type);
		ref = refstr(result_type);
		fprintf(sf,
"\t_n = %s(%s%s, 0, 0);\n\
\t_bp = Allocate(_n);\n\
\t%s(%s%s, _bp, 1);\n\
\tSendReturnMessage(_n, _bp);\n\
\tDeallocate(_bp);\n",
			func, ref, result_name, func, ref, result_name);
	}
	fprintf(sf, "}\n");

	/*
	 * Remote access routine.
	 */
	if (nresults) {
		fprintf(hf, "\nextern ");
		print_decl(hf, proc_name, result_type, 1);
		fprintf(hf, "();\n");

		fprintf(uf, "\n");
		print_decl(uf, proc_name, result_type, 1);
		fprintf(uf, "(");
	} else {
		fprintf(hf, "\nextern void %s();\n", proc_name);
		fprintf(uf, "\nvoid %s(", proc_name);
	}
	if (explicit) {
		fprintf(uf, "_machine");
		if (type->t_args != NIL)
			fprintf(uf, ", ");
	}
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		for (q = car(car(p)); q != NIL; q = cdr(q)) {
			fprintf(uf, "%s", name_of(car(q)));
			if (cdr(q) != NIL)
				fprintf(uf, ", ");
		}
		if (cdr(p) != NIL)
			fprintf(uf, ", ");
	}
	fprintf(uf, ")\n");
	if (explicit)
		fprintf(uf, "\tString _machine;\n");
	print_level++;
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		t = (struct object *) cdr(car(p));
		for (q = car(car(p)); q != NIL; q = cdr(q))
			print_decl(uf, name_of(car(q)), t, 0);
	}
	fprintf(uf, "{\n");
	if (nresults)
		print_decl(uf, result_name, result_type, 0);
	fprintf(uf,
"\tregister Unspecified *_buf, *_bp;\n\
\tregister LongCardinal _n;\n\
\n\
\t_n = 0;\n");
	print_level--;
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		t = (struct object *) cdr(car(p));
		ref = refstr(t);
		for (q = car(car(p)); q != NIL; q = cdr(q))
			fprintf(uf, "\t_n += %s(%s%s, 0, 0);\n",
				pack_function(t), ref, name_of(car(q)));
	}
	fprintf(uf,
"\t_buf = Allocate(_n);\n\
\t_bp = _buf;\n");
	for (p = type->t_args; p != NIL; p = cdr(p)) {
		t = (struct object *) cdr(car(p));
		ref = refstr(t);
		for (q = car(car(p)); q != NIL; q = cdr(q))
			fprintf(uf, "\t_bp += %s(%s%s, _bp, 1);\n",
				pack_function(t), ref, name_of(car(q)));
	}
	if (explicit)
		fprintf(uf,
"\tSendCallMessage(CourierProgram(\"%s\", _machine), %s, _n, _buf);\n",
			program_name, obj_rep(value));
	else
		fprintf(uf,
"\tSendCallMessage(_%sConnection, %s, _n, _buf);\n",
			program_name, obj_rep(value));
	fprintf(uf, "\tDeallocate(_buf);\n");
	if (nresults) {
		if (explicit)
			fprintf(uf,
"\t_bp = ReceiveReturnMessage(CourierProgram(\"%s\", _machine));\n",
				program_name);
		else
			fprintf(uf,
"\t_bp = ReceiveReturnMessage(_%sConnection);\n",
				program_name);
		fprintf(uf,
"\t%s(%s%s, _bp);\n\
\tDeallocate(_bp);\n\
\treturn (%s);\n",
			unpack_function(result_type), refstr(result_type),
			result_name, result_name);
	}
	fprintf(uf, "}\n");
}

program(prog)
	struct object *prog;
{
	/*
	 * Program_name should have been set by now,
	 * but a little paranoia never hurt anyone.
	 */
	if (! streq(name_of(prog), program_name)) {
		yyerror("Internal error: conflicting program names %s and %s\n",
			name_of(prog), program_name);
		exit(1);
	}
	generate_server();
}

/*
 * Generate main loop for server program.
 */
generate_server()
{
	list p;
	struct object *t, *proc, *v;

	fprintf(sf,
"\nServer()\n\
{\n\
\tCardinal procedure;\n\
\tregister Unspecified *buf;\n\
\n\
\tServerInit();\n\
\tfor (;;) {\n\
\t\tbuf = ReceiveCallMessage(&procedure);\n\
\t\tswitch (procedure) {\n"
		);
	/*
	 * Find all the procedures declared in the program.
	 */
	for (p = Types; p != NIL; p = cdr(p)) {
		t = (struct object *) cdr(car(p));
		if (t->t_constr == C_PROCEDURE) {
			proc = (struct object *) car(car(p));
			v = lookup(Values, proc);
			fprintf(sf,
"\t\tcase %s:\n\
\t\t\tServer_%s(buf);\n\
\t\t\tbreak;\n",
				obj_rep(v), name_of(proc));
		}
	}
	fprintf(sf,
"\t\tdefault:\n\
\t\t\tNoSuchProcedureValue(\"%s\", procedure);\n\
\t\t\tbreak;\n\
\t\t}\n\
\t\tDeallocate(buf);\n\
\t}\n\
}\n",
		program_name);
}

/*
 * When implicit binding is used, this routine generates functions to
 * bind the remote Courier program to a machine by setting the global
 * connection variable for the program, and to remove the binding by
 * closing the connection.
 */
generate_binding_functions()
{
	fprintf(uf,
"\nint _%sConnection = -1;\n\
\n\
Bind%sToMachine(machine)\n\
\tString machine;\n\
{\n\
\tclose(_%sConnection);\n\
\t_%sConnection = CourierActivate(\"%s\", machine);\n\
}\n\
\n\
Unbind%s()\n\
{\n\
\tclose(_%sConnection);\n\
\t_%sConnection = -1;\n\
}\n",
		program_name, program_name, program_name, program_name,
		program_name, program_name, program_name, program_name);
}