#!/usr/bin/perl require 'c_types.pl'; $[ = 1; # set array base to 1 $, = ' '; # set output field separator $\ = "\n"; # set output record separator $always_use_temp_storage = 1; sub toupper { local($_) = @_; tr/a-z/A-Z/; return $_; } sub tolower { local($_) = @_; tr/A-Z/a-z/; return $_; } print '/* marshal.c */'; print "/* This is a generated file. Please modify `marshal.pl' */"; print ''; print '#include '; print ''; print '#include '; print '#include '; print ''; print '#include "command.h"'; print '#include '; print ''; $feature_count = 0; while (<>) { chop; # strip record separator if (/^[^#]/) { &output($_); } } sub output { local($line) = @_; @line_fields = split(/\|/, $line, 9999); $retval = $line_fields[1]; $feature = $line_fields[2]; $param_def = $line_fields[4]; $orig = $feature; $feature =~ s/^@//; $space = $feature; $space =~ s/./ /g; $features{++$feature_count} = $orig; return if $orig =~ /^@/; $orig_retval = $retval; if ($retval eq 'retval') { $retval_param = '&retval'; $call_prefix = ''; $call_prefix_space = ''; $prefix = 'retval = '; $prefix_space = ' '; $retval = 'int'; } elsif ($retval !~ /^void$/) { $retval_param = 'NULL'; $prefix = 'retval = '; $prefix_space = ' '; $call_prefix = 'retval = '; $call_prefix_space = ' '; } else { $retval_param = 'NULL'; $call_prefix = ''; $call_prefix_space = ''; $prefix = ''; $prefix_space = ''; } if ($retval =~ /^(array|pointer)\((.*)\)$/) { $retval = ($2 eq 'string') ? 'char **' : "$2 *"; } $need_temp_storage = $always_use_temp_storage; $local_var_init_code = "\t/* variable initialization */\n"; $local_var_init_code .= "\t_LIBGTOP_SEND_len = 0;\n"; $local_var_init_code .= "\t_LIBGTOP_DATA_len = 0;\n"; $local_var_init_code .= "\t_LIBGTOP_SEND_offset = 0;\n"; $local_var_init_code .= "\t_LIBGTOP_SEND_ptr = ". "(char *) _LIBGTOP_SEND_buf;\n"; $marshal_code = "\t/* marshal start */\n"; $marshal_code .= "\tmemset (_LIBGTOP_SEND_buf, 0, _LIBGTOP_SEND_len);\n"; $first_param_name = ''; $size_code = ''; $call_param = ''; $param_decl = ''; $need_temp_len = 0; $nr_params = (@params = split(/:/, $param_def, 9999)); for ($param = 1; $param <= $nr_params; $param++) { $list = $params[$param]; $type = $params[$param]; $type =~ s/\(.*//; $list =~ s/^.*\(//; $list =~ s/\)$//; $count = (@fields = split(/,/, $list, 9999)); for ($field = 1; $field <= $count; $field++) { my $c_type = $typeinfo->{$type}->[1]; if ($first_param_name eq '') { $first_param_name = $fields[$field]; } if ($typeinfo->{$type}->[2]) { $need_temp_storage = 1; } if ($param_decl eq '') { $param_decl = ",\n " . $space . ' '; } else { $param_decl = $param_decl . ', '; } $param_decl = $param_decl . $c_type . ' ' . $fields[$field]; $call_param = $call_param . ', ' . $fields[$field]; $size_code .= "\t_LIBGTOP_SEND_len += "; if ($typeinfo->{$type}->[2]) { $size_code .= sprintf ("sizeof (size_t)"); } else { $size_code .= sprintf ("sizeof (%s)", $c_type); } $size_code .= ";\n"; if (defined $sizeof_funcs->{$type}) { $size_code .= "\t_LIBGTOP_DATA_len += "; $size_code .= $sizeof_funcs->{$type}->($fields[$field]); $size_code .= ";\n"; } $marshal_code .= "\t_LIBGTOP_SEND_ptr = ". "(char *) _LIBGTOP_SEND_buf + _LIBGTOP_SEND_offset;\n"; if (defined $marshal_funcs->{$type}) { $marshal_code .= $marshal_funcs->{$type}->($c_type, $fields[$field], "\t"); } else { $marshal_code .= sprintf ("\tmemcpy (_LIBGTOP_SEND_ptr, %s, %s);\n", '&'.$fields[$field], "sizeof ($c_type)"); } $marshal_code .= "\t_LIBGTOP_SEND_offset += "; if ($typeinfo->{$type}->[2]) { $marshal_code .= sprintf ("sizeof (size_t)"); } else { $marshal_code .= sprintf ("sizeof (%s)", $c_type); } $marshal_code .= ";\n"; } } $local_var_code = ""; $local_var_code .= "\tunsigned _LIBGTOP_SEND_offset, _LIBGTOP_SEND_len;\n"; $local_var_code .= "\tunsigned _LIBGTOP_DATA_len;\n"; if ($need_temp_len) { $local_var_code .= "\tunsigned _LIBGTOP_SEND_temp_len;\n"; } $local_var_code .= "\tvoid *_LIBGTOP_SEND_buf, *_LIBGTOP_DATA_buf;\n"; $local_var_code .= "\tchar *_LIBGTOP_SEND_ptr, *_LIBGTOP_DATA_ptr;\n"; if ($retval !~ /^void$/) { $local_var_code .= sprintf ("\t%s retval = (%s) 0;\n", $retval, $retval); } $total_code = ''; $send_buf_code = "\t/* send buffer */\n"; $send_buf_code .= "\t_LIBGTOP_SEND_buf = "; if ($need_temp_storage) { $send_buf_code .= "g_malloc (_LIBGTOP_SEND_len+1)"; } else { $send_buf_code .= '(void *) &'.$first_param_name; } $send_buf_code .= ";\n\n"; $send_buf_code .= "\t/* data buffer */\n"; $send_buf_code .= "\t_LIBGTOP_DATA_buf = "; if ($need_temp_storage) { $send_buf_code .= "g_malloc (_LIBGTOP_DATA_len+1)"; } else { $send_buf_code .= 'NULL'; } $send_buf_code .= ";\n"; $send_buf_code .= "\t_LIBGTOP_DATA_ptr = _LIBGTOP_DATA_buf;\n"; $call_code = ''; $call_code .= sprintf ("\t%sglibtop_call_i (server, closure, GLIBTOP_CMND_%s,\n", $call_prefix, &toupper($feature)); $call_code .= sprintf ("\t\t\t%s%s, %s,\n", $call_prefix_space, "_LIBGTOP_SEND_len", "_LIBGTOP_SEND_buf"); $call_code .= sprintf ("\t\t\t%s%s, %s,\n", $call_prefix_space, "_LIBGTOP_DATA_len", "_LIBGTOP_DATA_buf"); if ($line_fields[3] eq '') { $call_code .= sprintf ("\t\t\t%s0, NULL,\n", $call_prefix_space); } elsif ($line_fields[3] eq 'array') { $call_code .= sprintf ("\t\t\t%ssizeof (glibtop_array), array,\n", $call_prefix_space); } else { $call_code .= sprintf ("\t\t\t%ssizeof (glibtop_%s), buf,\n", $call_prefix_space, $feature); } $call_code .= sprintf ("\t\t\t%s%s);\n", $call_prefix_space, $retval_param); if ($need_temp_storage) { $send_buf_free_code = "\tg_free (_LIBGTOP_SEND_buf);\n"; $send_buf_free_code .= "\tg_free (_LIBGTOP_DATA_buf);\n"; } else { $send_buf_free_code = ""; } if (!($size_code eq '')) { $size_code = sprintf (qq[\t/* send size */\n%s\n], $size_code); } if ($orig_retval eq 'pointer(string)') { $call_code .= "\n"; $local_var_code .= "\tchar *_LIBGTOP_ARRAY_ptr, **ptrlist;\n"; $local_var_code .= "\toff_t *_LIBGTOP_ARRAY_off_ptr;\n"; $local_var_code .= "\tint i;\n"; $call_code .= "\tptrlist = g_malloc (array->number+1 * sizeof (char *));\n"; $call_code .= "\t_LIBGTOP_ARRAY_off_ptr = (off_t *) retval;\n"; $call_code .= "\t_LIBGTOP_ARRAY_ptr = (char *) retval;\n"; $call_code .= "\t_LIBGTOP_ARRAY_off_ptr++;\n\n"; $call_code .= "\tfor (i = 0; i < array->number; i++)\n"; $call_code .= "\t\tptrlist [i] = g_strdup (_LIBGTOP_ARRAY_ptr + *_LIBGTOP_ARRAY_off_ptr++);\n"; $call_code .= "\tptrlist [array->number] = NULL;\n\n"; $call_code .= "\tg_free (retval);\n"; $call_code .= "\tretval = ptrlist;\n"; } $total_code .= sprintf ("%s%s\n%s\n%s\n%s\n", $size_code, $send_buf_code, $marshal_code, $call_code, $send_buf_free_code); $return_code = ''; if ($retval !~ /^void$/) { $return_code .= "\treturn retval;\n"; } else { $return_code .= "\treturn;\n"; } $total_code .= $return_code; $func_decl = 'static '.$retval."\n"; if ($line_fields[3] eq '') { $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop_server *server, void *closure%s)\n", $feature, $param_decl); } elsif ($line_fields[3] eq 'array') { $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop_server *server, void *closure, glibtop_array *array%s)\n", $feature, $param_decl); } elsif ($line_fields[3] =~ /^array/) { $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop_server *server, void *closure, glibtop_array *array, %s *buf%s)\n", $feature, 'glibtop_'.$feature, $param_decl); } else { $func_decl .= sprintf ("_glibtop_get_%s_c (glibtop_server *server, void *closure, %s *buf%s)\n", $feature, 'glibtop_'.$feature, $param_decl); } $total_code = sprintf ("%s{\n%s\n%s\n%s\n%s}\n", $func_decl, $local_var_code, $local_var_init_code, $total_code); $total_code = sprintf ("#if GLIBTOP_SUID_%s\n\n%s\n#endif /* GLIBTOP_SUID_%s */\n\n", &toupper($feature), $total_code, &toupper($feature)); print $total_code; } $call_vector_code = ''; for ($nr = 1; $nr <= $feature_count; $nr++) { $feature = $features{$nr}; $orig = $feature; $feature =~ s/^@//; if ($orig =~ /^@/) { $call_vector_code .= sprintf (qq[\tNULL,\n]); } else { $call_vector_code .= sprintf (qq[\#if GLIBTOP_SUID_%s\n\t_glibtop_get_%s_c,\n\#else\n\tNULL,\n\#endif\n], &toupper($feature), $feature); } } print 'glibtop_call_vector glibtop_backend_server_call_vector = {'; print $call_vector_code; print '};'; print '';