def print_fslave_main(p, print_newline, syscall): name = drop_prefix(syscall.name) p("""\ void process_{name}(struct slave_thread *slave_thread) {{ """.format(**locals())) local_vars = [] for datatype, name in (("int", "retval"), ("int", "errnum")): local_vars.append(Variable(datatype, name)) out_arguments = syscall.output_args if len(out_arguments) == 0: cmd_name = make_cmd_name(syscall.name) print_locals(p, local_vars) print_newline() return_func = get_fslave_return_func(syscall) p("""\ \texecute_call(slave_thread, &retval, &errnum); \t{return_func}(slave_thread, {cmd_name}_RETURN, retval, errnum); }} """.format(**locals())) return for a in out_arguments: data = data_of_argument(syscall, a) datatype = a.datatype if data.is_array else drop_pointer(a.datatype) local_vars.append(Variable(datatype, a.name)) print_locals(p, local_vars) print_newline() call_args = ", ".join(["&{name}".format(**vars(a)) for a in out_arguments]) ret_args = make_execute_return_actual_arguments(syscall, out_arguments) p("""\ \texecute_call(slave_thread, &retval, &errnum, {call_args}); \texecute_return(slave_thread, retval, errnum, {ret_args}); }} """.format(**locals()))
def print_execute_return(p, print_newline, syscall): name = syscall.name p("""\ static int execute_return(struct thread *td, struct {name}_args *uap) {{ """.format(**locals())) local_vars = [] for datatype, name in ( ("command_t", "cmd"), ("int", "errnum"), ("int", "errnum_len"), ("int", "error"), ("int", "retval_len"), ("int", "rfd"), ("payload_size_t", "expected_payload_size"), ("payload_size_t", "payload_size"), (syscall.rettype, "retval")): local_vars.append(Variable(datatype, name)) out_arguments = syscall.output_args for a in out_arguments: if a.datatype in ("char *", "void *"): continue data = data_of_argument(syscall, a) st = data.struct if st is not None: local_vars.append(Variable(drop_pointer(a.datatype), a.name)) for _, name in st.expand_all_members(a.name): n = "{name}_len".format(**locals()) local_vars.append(Variable("int", n)) continue assert data_of_argument(syscall, a).is_atom name = a.name local_vars.append(Variable("int", "{name}_len".format(**locals()))) local_vars.append(Variable(drop_pointer(a.datatype), a.name)) print_locals(p, local_vars) print_newline() cmd_name = make_cmd_name(syscall.name) t = concrete_datatype_of_abstract_datatype(syscall.rettype) p("""\ \terror = fmaster_read_command(td, &cmd); \tif (error != 0) \t\treturn (error); \tif (cmd != {cmd_name}_RETURN) {{ \t\tfmaster_log(td, LOG_ERR, \"command mismatched: expected=%d, actual=%d\", {cmd_name}_RETURN, cmd); \t\treturn (EPROTO); \t}} \terror = fmaster_read_payload_size(td, &payload_size); \tif (error != 0) \t\treturn (error); \terror = fmaster_read_{t}(td, &retval, &retval_len); \tif (error != 0) \t\treturn (error); \tif (retval == -1) {{ \t\terror = fmaster_read_int32(td, &errnum, &errnum_len); \t\tif (error != 0) \t\t\treturn (error); \t\tif (retval_len + errnum_len != payload_size) {{ \t\tfmaster_log(td, LOG_ERR, \"payload size mismatched: expected=%d, actual=%d\", payload_size, retval_len + errnum_len); \t\t\treturn (EPROTO); \t\t}} \t\treturn (errnum); \t}} """.format(**locals())) print_newline() p("""\ \trfd = fmaster_rfd_of_thread(td); """) for a in out_arguments: if a.datatype in ("char *", "void *"): p("""\ \terror = fmaster_read_to_userspace(td, rfd, uap->{name}, {size}); \tif (error != 0) \t\treturn (error); """.format(name=a.name, size=data_of_argument(syscall, a).retsize)) continue data = data_of_argument(syscall, a) st = data.struct if st is not None: for datatype, var, name in st.zip_members(a.name): t = concrete_datatype_of_abstract_datatype(datatype) p("""\ \terror = fmaster_read_{t}(td, &{name}, &{var}_len); \tif (error != 0) \t\treturn (error); """.format(**locals())) continue assert data.is_atom t = concrete_datatype_of_abstract_datatype(drop_pointer(a.datatype)) name = a.name p("""\ \terror = fmaster_read_{t}(td, &{name}, &{name}_len); \tif (error != 0) \t\treturn (error); """.format(**locals())) print_newline() expected_payload_size = make_payload_size_expr(syscall, out_arguments, "retsize") p("""\ \texpected_payload_size = retval_len + {expected_payload_size}; \tif (expected_payload_size != payload_size) {{ \t\tfmaster_log(td, LOG_ERR, \"payload size mismatched: expected=%d, actual=%d\", expected_payload_size, payload_size); \t\treturn (EPROTO); \t}} """.format(**locals())) print_newline() for a in syscall.output_args: data = data_of_argument(syscall, a) if data.is_array: continue p("""\ \tif (uap->{name} != NULL) {{ \t\terror = copyout(&{name}, uap->{name}, sizeof({name})); \t\tif (error != 0) \t\t\treturn (error); \t}} """.format(**vars(a))) p("""\ \ttd->td_retval[0] = retval; \treturn (0); }} """.format(**locals()))
def print_fslave_return(p, print_newline, syscall): output_args = syscall.output_args args = ", ".join([make_formal_arguments_of_execute_return(syscall, a) for a in output_args]) p("""\ static void execute_return(struct slave_thread *slave_thread, int retval, int errnum, {args}) {{ """.format(**locals())) local_vars = [Variable(datatype, name, size) for datatype, name, size in ( ("payload_size_t", "payload_size", None), ("char", "retval_buf", bufsize_of_datatype(syscall.rettype)), ("int", "retval_len", None), ("int", "wfd", None))] out_arguments = syscall.output_args for a in out_arguments: datatype = a.datatype if a.datatype in ("char *", "void *"): # in case of an array continue st = data_of_argument(syscall, a).struct append = local_vars.append if st is not None: for datatype, name in st.expand_all_members(a.name): fmt = "{name}_len" append(Variable("int", fmt.format(**locals()))) fmt = "{name}_buf" size = bufsize_of_datatype(datatype) append(Variable("char", fmt.format(**locals()), size)) continue name = a.name size = bufsize_of_datatype(drop_pointer(datatype)) append(Variable("int", "{name}_len".format(**locals()))) append(Variable("char", "{name}_buf".format(**locals()), size)) print_locals(p, local_vars) print_newline() cmd_name = make_cmd_name(syscall.name) return_func = get_fslave_return_func(syscall) p("""\ \tif (retval == -1) {{ \t\t{return_func}(slave_thread, {cmd_name}_RETURN, retval, errnum); \t\treturn; \t}} """.format(**locals())) print_newline() p("""\ \tretval_len = encode_{datatype}(retval, retval_buf, array_sizeof(retval_buf)); """.format(datatype=concrete_datatype_of_abstract_datatype(syscall.rettype))) for a in out_arguments: if a.datatype in ("char *", "void *"): continue st = data_of_argument(syscall, a).struct if st is not None: for datatype, var, name in st.zip_members(a.name, "->"): struct_name = a.name t = concrete_datatype_of_abstract_datatype(datatype) p("""\ \t{var}_len = encode_{t}({name}, {var}_buf, array_sizeof({var}_buf)); """.format(**locals())) continue name = a.name t = drop_pointer(a.datatype) datatype = concrete_datatype_of_abstract_datatype(t) p("""\ \t{name}_len = encode_{datatype}({name}, {name}_buf, sizeof({name}_buf)); """.format(**locals())) payload_size = make_payload_size_expr(syscall, out_arguments, "retsize") p("""\ \tpayload_size = retval_len + {payload_size}; \twfd = slave_thread->fsth_wfd; \twrite_command(wfd, {cmd_name}_RETURN); \twrite_payload_size(wfd, payload_size); \twrite_or_die(wfd, retval_buf, retval_len); """.format(**locals())) for a in out_arguments: if a.datatype in ("char *", "void *"): name = a.name size = data_of_argument(syscall, a).retsize p("""\ \twrite_or_die(wfd, {name}, {size}); """.format(**locals())) continue st = data_of_argument(syscall, a).struct if st is not None: for _, name in st.expand_all_members(a.name): p("""\ \twrite_or_die(wfd, {name}_buf, {name}_len); """.format(**locals())) continue name = a.name p("""\ \twrite_or_die(wfd, {name}_buf, {name}_len); """.format(**locals())) newlined = False for a in out_arguments: data = data_of_argument(syscall, a) if not data.is_array: continue if not newlined: print_newline() newlined = True p("""\ \tfree({name}); """.format(**vars(a))) p("""\ }} """.format(**locals()))
def make_formal_arguments_of_execute_return(syscall, a): data = data_of_argument(syscall, a) dt = a.datatype datatype = drop_pointer(dt) if data.is_atom else dt name = a.name return "{datatype} {name}".format(**locals())