1: #ifndef lint 2: static char sccsid[] = "@(#)code2.c 4.1 (Berkeley) 7/3/83"; 3: #endif 4: 5: #include "Courier.h" 6: 7: /* 8: * Generate functions for user and server calls to a procedure. 9: */ 10: proc_functions(proc_name, type, value) 11: char *proc_name; 12: struct object *type, *value; 13: { 14: list p, q; 15: int nresults; 16: struct object *t, *result_type; 17: char *result_name, *func, *ref; 18: 19: /* 20: * Make sure there is at most one result returned. 21: */ 22: nresults = length(type->t_results); 23: if (nresults == 1) 24: /* could be multiple names with one type */ 25: nresults = length(car(car(type->t_results))); 26: if (nresults > 1) { 27: yyerror("Procedures that return multiple results are not supported"); 28: return; 29: } 30: if (nresults) { 31: result_name = name_of(car(car(car(type->t_results)))); 32: result_type = (struct object *) cdr(car(type->t_results)); 33: } 34: 35: /* 36: * Server routine. 37: */ 38: if (nresults) { 39: fprintf(sf, "\nextern "); 40: print_decl(sf, proc_name, result_type, 1); 41: fprintf(sf, "();\n"); 42: } else 43: fprintf(sf, "\nextern void %s();\n", proc_name); 44: fprintf(sf, 45: "\nServer_%s(_buf)\n\ 46: \tregister Unspecified *_buf;\n\ 47: {\n\ 48: \tregister Unspecified *_bp;\n\ 49: \tregister LongCardinal _n;\n", 50: proc_name); 51: print_level++; 52: for (p = type->t_args; p != NIL; p = cdr(p)) { 53: t = (struct object *) cdr(car(p)); 54: for (q = car(car(p)); q != NIL; q = cdr(q)) 55: print_decl(sf, name_of(car(q)), t, 0); 56: } 57: if (nresults) 58: print_decl(sf, result_name, result_type, 0); 59: print_level--; 60: fprintf(sf, "\n\t_bp = _buf;\n"); 61: for (p = type->t_args; p != NIL; p = cdr(p)) { 62: t = (struct object *) cdr(car(p)); 63: ref = refstr(t); 64: for (q = car(car(p)); q != NIL; q = cdr(q)) 65: fprintf(sf, "\t_bp += %s(%s%s, _bp);\n", 66: unpack_function(t), ref, name_of(car(q))); 67: } 68: if (nresults) 69: fprintf(sf, "\t%s = %s(", result_name, proc_name); 70: else 71: fprintf(sf, "\t%s(", proc_name); 72: for (p = type->t_args; p != NIL; p = cdr(p)) { 73: for (q = car(car(p)); q != NIL; q = cdr(q)) { 74: fprintf(sf, "%s", name_of(car(q))); 75: if (cdr(q) != NIL) 76: fprintf(sf, ", "); 77: } 78: if (cdr(p) != NIL) 79: fprintf(sf, ", "); 80: } 81: fprintf(sf, ");\n"); 82: if (nresults) { 83: func = pack_function(result_type); 84: ref = refstr(result_type); 85: fprintf(sf, 86: "\t_n = %s(%s%s, 0, 0);\n\ 87: \t_bp = Allocate(_n);\n\ 88: \t%s(%s%s, _bp, 1);\n\ 89: \tSendReturnMessage(_n, _bp);\n\ 90: \tDeallocate(_bp);\n", 91: func, ref, result_name, func, ref, result_name); 92: } 93: fprintf(sf, "}\n"); 94: 95: /* 96: * Remote access routine. 97: */ 98: if (nresults) { 99: fprintf(hf, "\nextern "); 100: print_decl(hf, proc_name, result_type, 1); 101: fprintf(hf, "();\n"); 102: 103: fprintf(uf, "\n"); 104: print_decl(uf, proc_name, result_type, 1); 105: fprintf(uf, "("); 106: } else { 107: fprintf(hf, "\nextern void %s();\n", proc_name); 108: fprintf(uf, "\nvoid %s(", proc_name); 109: } 110: if (explicit) { 111: fprintf(uf, "_machine"); 112: if (type->t_args != NIL) 113: fprintf(uf, ", "); 114: } 115: for (p = type->t_args; p != NIL; p = cdr(p)) { 116: for (q = car(car(p)); q != NIL; q = cdr(q)) { 117: fprintf(uf, "%s", name_of(car(q))); 118: if (cdr(q) != NIL) 119: fprintf(uf, ", "); 120: } 121: if (cdr(p) != NIL) 122: fprintf(uf, ", "); 123: } 124: fprintf(uf, ")\n"); 125: if (explicit) 126: fprintf(uf, "\tString _machine;\n"); 127: print_level++; 128: for (p = type->t_args; p != NIL; p = cdr(p)) { 129: t = (struct object *) cdr(car(p)); 130: for (q = car(car(p)); q != NIL; q = cdr(q)) 131: print_decl(uf, name_of(car(q)), t, 0); 132: } 133: fprintf(uf, "{\n"); 134: if (nresults) 135: print_decl(uf, result_name, result_type, 0); 136: fprintf(uf, 137: "\tregister Unspecified *_buf, *_bp;\n\ 138: \tregister LongCardinal _n;\n\ 139: \n\ 140: \t_n = 0;\n"); 141: print_level--; 142: for (p = type->t_args; p != NIL; p = cdr(p)) { 143: t = (struct object *) cdr(car(p)); 144: ref = refstr(t); 145: for (q = car(car(p)); q != NIL; q = cdr(q)) 146: fprintf(uf, "\t_n += %s(%s%s, 0, 0);\n", 147: pack_function(t), ref, name_of(car(q))); 148: } 149: fprintf(uf, 150: "\t_buf = Allocate(_n);\n\ 151: \t_bp = _buf;\n"); 152: for (p = type->t_args; p != NIL; p = cdr(p)) { 153: t = (struct object *) cdr(car(p)); 154: ref = refstr(t); 155: for (q = car(car(p)); q != NIL; q = cdr(q)) 156: fprintf(uf, "\t_bp += %s(%s%s, _bp, 1);\n", 157: pack_function(t), ref, name_of(car(q))); 158: } 159: if (explicit) 160: fprintf(uf, 161: "\tSendCallMessage(CourierProgram(\"%s\", _machine), %s, _n, _buf);\n", 162: program_name, obj_rep(value)); 163: else 164: fprintf(uf, 165: "\tSendCallMessage(_%sConnection, %s, _n, _buf);\n", 166: program_name, obj_rep(value)); 167: fprintf(uf, "\tDeallocate(_buf);\n"); 168: if (nresults) { 169: if (explicit) 170: fprintf(uf, 171: "\t_bp = ReceiveReturnMessage(CourierProgram(\"%s\", _machine));\n", 172: program_name); 173: else 174: fprintf(uf, 175: "\t_bp = ReceiveReturnMessage(_%sConnection);\n", 176: program_name); 177: fprintf(uf, 178: "\t%s(%s%s, _bp);\n\ 179: \tDeallocate(_bp);\n\ 180: \treturn (%s);\n", 181: unpack_function(result_type), refstr(result_type), 182: result_name, result_name); 183: } 184: fprintf(uf, "}\n"); 185: } 186: 187: program(prog) 188: struct object *prog; 189: { 190: /* 191: * Program_name should have been set by now, 192: * but a little paranoia never hurt anyone. 193: */ 194: if (! streq(name_of(prog), program_name)) { 195: yyerror("Internal error: conflicting program names %s and %s\n", 196: name_of(prog), program_name); 197: exit(1); 198: } 199: generate_server(); 200: } 201: 202: /* 203: * Generate main loop for server program. 204: */ 205: generate_server() 206: { 207: list p; 208: struct object *t, *proc, *v; 209: 210: fprintf(sf, 211: "\nServer()\n\ 212: {\n\ 213: \tCardinal procedure;\n\ 214: \tregister Unspecified *buf;\n\ 215: \n\ 216: \tServerInit();\n\ 217: \tfor (;;) {\n\ 218: \t\tbuf = ReceiveCallMessage(&procedure);\n\ 219: \t\tswitch (procedure) {\n" 220: ); 221: /* 222: * Find all the procedures declared in the program. 223: */ 224: for (p = Types; p != NIL; p = cdr(p)) { 225: t = (struct object *) cdr(car(p)); 226: if (t->t_constr == C_PROCEDURE) { 227: proc = (struct object *) car(car(p)); 228: v = lookup(Values, proc); 229: fprintf(sf, 230: "\t\tcase %s:\n\ 231: \t\t\tServer_%s(buf);\n\ 232: \t\t\tbreak;\n", 233: obj_rep(v), name_of(proc)); 234: } 235: } 236: fprintf(sf, 237: "\t\tdefault:\n\ 238: \t\t\tNoSuchProcedureValue(\"%s\", procedure);\n\ 239: \t\t\tbreak;\n\ 240: \t\t}\n\ 241: \t\tDeallocate(buf);\n\ 242: \t}\n\ 243: }\n", 244: program_name); 245: } 246: 247: /* 248: * When implicit binding is used, this routine generates functions to 249: * bind the remote Courier program to a machine by setting the global 250: * connection variable for the program, and to remove the binding by 251: * closing the connection. 252: */ 253: generate_binding_functions() 254: { 255: fprintf(uf, 256: "\nint _%sConnection = -1;\n\ 257: \n\ 258: Bind%sToMachine(machine)\n\ 259: \tString machine;\n\ 260: {\n\ 261: \tclose(_%sConnection);\n\ 262: \t_%sConnection = CourierActivate(\"%s\", machine);\n\ 263: }\n\ 264: \n\ 265: Unbind%s()\n\ 266: {\n\ 267: \tclose(_%sConnection);\n\ 268: \t_%sConnection = -1;\n\ 269: }\n", 270: program_name, program_name, program_name, program_name, 271: program_name, program_name, program_name, program_name); 272: }