github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/dist/goc2c.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "a.h"
     6  
     7  /*
     8   * Translate a .goc file into a .c file.  A .goc file is a combination
     9   * of a limited form of Go with C.
    10   */
    11  
    12  /*
    13  	package PACKAGENAME
    14  	{# line}
    15  	func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{
    16  	  C code with proper brace nesting
    17  	\}
    18  */
    19  
    20  /*
    21   * We generate C code which implements the function such that it can
    22   * be called from Go and executes the C code.
    23   */
    24  
    25  static char *input;
    26  static Buf *output;
    27  #define EOF -1
    28  
    29  enum
    30  {
    31  	use64bitint = 1,
    32  };
    33  
    34  static int
    35  xgetchar(void)
    36  {
    37  	int c;
    38  	
    39  	c = *input;
    40  	if(c == 0)
    41  		return EOF;
    42  	input++;
    43  	return c;
    44  }
    45  
    46  static void
    47  xungetc(void)
    48  {
    49  	input--;
    50  }
    51  
    52  static void
    53  xputchar(char c)
    54  {
    55  	bwrite(output, &c, 1);
    56  }
    57  
    58  static int
    59  xisspace(int c)
    60  {
    61  	return c == ' ' || c == '\t' || c == '\r' || c == '\n';
    62  }
    63  
    64  /* Whether we're emitting for gcc */
    65  static int gcc;
    66  
    67  /* File and line number */
    68  static const char *file;
    69  static unsigned int lineno;
    70  
    71  /* List of names and types.  */
    72  struct params {
    73  	struct params *next;
    74  	char *name;
    75  	char *type;
    76  };
    77  
    78  /* index into type_table */
    79  enum {
    80  	Bool,
    81  	Float,
    82  	Int,
    83  	Uint,
    84  	Uintptr,
    85  	String,
    86  	Slice,
    87  	Eface,
    88  	Complex128,
    89  	Float32,
    90  	Float64,
    91  };
    92  
    93  static struct {
    94  	char *name;
    95  	int size;
    96  	int rnd; // alignment
    97  } type_table[] = {
    98  	/* 
    99  	 * variable sized first, for easy replacement.
   100  	 * order matches enum above.
   101  	 * default is 32-bit architecture sizes.
   102  	 * spelling as in package runtime, so intgo/uintgo not int/uint.
   103  	 */
   104  	{"bool",	1},
   105  	{"float",	4},
   106  	{"intgo",		4},
   107  	{"uintgo",	4},
   108  	{"uintptr",	4},
   109  	{"String",	8},
   110  	{"Slice",	12},
   111  	{"Eface",	8},
   112  	{"Complex128", 16},
   113  
   114  	/* fixed size */
   115  	{"float32",	4},
   116  	{"float64",	8},
   117  	{"byte",	1},
   118  	{"int8",	1},
   119  	{"uint8",	1},
   120  	{"int16",	2},
   121  	{"uint16",	2},
   122  	{"int32",	4},
   123  	{"rune",	4},
   124  	{"uint32",	4},
   125  	{"int64",	8},
   126  	{"uint64",	8},
   127  
   128  	{nil, 0},
   129  };
   130  
   131  /* Fixed structure alignment (non-gcc only) */
   132  int structround = 4;
   133  
   134  /* Unexpected EOF.  */
   135  static void
   136  bad_eof(void)
   137  {
   138  	fatal("%s:%d: unexpected EOF\n", file, lineno);
   139  }
   140  
   141  /* Free a list of parameters.  */
   142  static void
   143  free_params(struct params *p)
   144  {
   145  	while (p != nil) {
   146  		struct params *next;
   147  
   148  		next = p->next;
   149  		xfree(p->name);
   150  		xfree(p->type);
   151  		xfree(p);
   152  		p = next;
   153  	}
   154  }
   155  
   156  /* Read a character, tracking lineno.  */
   157  static int
   158  getchar_update_lineno(void)
   159  {
   160  	int c;
   161  
   162  	c = xgetchar();
   163  	if (c == '\n')
   164  		++lineno;
   165  	return c;
   166  }
   167  
   168  /* Read a character, giving an error on EOF, tracking lineno.  */
   169  static int
   170  getchar_no_eof(void)
   171  {
   172  	int c;
   173  
   174  	c = getchar_update_lineno();
   175  	if (c == EOF)
   176  		bad_eof();
   177  	return c;
   178  }
   179  
   180  /* Read a character, skipping comments.  */
   181  static int
   182  getchar_skipping_comments(void)
   183  {
   184  	int c;
   185  
   186  	while (1) {
   187  		c = getchar_update_lineno();
   188  		if (c != '/')
   189  			return c;
   190  
   191  		c = xgetchar();
   192  		if (c == '/') {
   193  			do {
   194  				c = getchar_update_lineno();
   195  			} while (c != EOF && c != '\n');
   196  			return c;
   197  		} else if (c == '*') {
   198  			while (1) {
   199  				c = getchar_update_lineno();
   200  				if (c == EOF)
   201  					return EOF;
   202  				if (c == '*') {
   203  					do {
   204  						c = getchar_update_lineno();
   205  					} while (c == '*');
   206  					if (c == '/')
   207  						break;
   208  				}
   209  			}
   210  		} else {
   211  			xungetc();
   212  			return '/';
   213  		}
   214  	}
   215  }
   216  
   217  /*
   218   * Read and return a token.  Tokens are string or character literals
   219   * or else delimited by whitespace or by [(),{}].
   220   * The latter are all returned as single characters.
   221   */
   222  static char *
   223  read_token(void)
   224  {
   225  	int c, q;
   226  	char *buf;
   227  	unsigned int alc, off;
   228  	char* delims = "(),{}";
   229  
   230  	while (1) {
   231  		c = getchar_skipping_comments();
   232  		if (c == EOF)
   233  			return nil;
   234  		if (!xisspace(c))
   235  			break;
   236  	}
   237  	alc = 16;
   238  	buf = xmalloc(alc + 1);
   239  	off = 0;
   240  	if(c == '"' || c == '\'') {
   241  		q = c;
   242  		buf[off] = c;
   243  		++off;
   244  		while (1) {
   245  			if (off+2 >= alc) { // room for c and maybe next char
   246  				alc *= 2;
   247  				buf = xrealloc(buf, alc + 1);
   248  			}
   249  			c = getchar_no_eof();
   250  			buf[off] = c;
   251  			++off;
   252  			if(c == q)
   253  				break;
   254  			if(c == '\\') {
   255  				buf[off] = getchar_no_eof();
   256  				++off;
   257  			}
   258  		}
   259  	} else if (xstrrchr(delims, c) != nil) {
   260  		buf[off] = c;
   261  		++off;
   262  	} else {
   263  		while (1) {
   264  			if (off >= alc) {
   265  				alc *= 2;
   266  				buf = xrealloc(buf, alc + 1);
   267  			}
   268  			buf[off] = c;
   269  			++off;
   270  			c = getchar_skipping_comments();
   271  			if (c == EOF)
   272  				break;
   273  			if (xisspace(c) || xstrrchr(delims, c) != nil) {
   274  				if (c == '\n')
   275  					lineno--;
   276  				xungetc();
   277  				break;
   278  			}
   279  		}
   280  	}
   281  	buf[off] = '\0';
   282  	return buf;
   283  }
   284  
   285  /* Read a token, giving an error on EOF.  */
   286  static char *
   287  read_token_no_eof(void)
   288  {
   289  	char *token = read_token();
   290  	if (token == nil)
   291  		bad_eof();
   292  	return token;
   293  }
   294  
   295  /* Read the package clause, and return the package name.  */
   296  static char *
   297  read_package(void)
   298  {
   299  	char *token;
   300  
   301  	token = read_token_no_eof();
   302  	if (token == nil)
   303  		fatal("%s:%d: no token\n", file, lineno);
   304  	if (!streq(token, "package")) {
   305  		fatal("%s:%d: expected \"package\", got \"%s\"\n",
   306  			file, lineno, token);
   307  	}
   308  	return read_token_no_eof();
   309  }
   310  
   311  /* Read and copy preprocessor lines.  */
   312  static void
   313  read_preprocessor_lines(void)
   314  {
   315  	int first;
   316  	
   317  	first = 1;
   318  	while (1) {
   319  		int c;
   320  
   321  		do {
   322  			c = getchar_skipping_comments();
   323  		} while (xisspace(c));
   324  		if (c != '#') {
   325  			xungetc();
   326  			break;
   327  		}
   328  		if(first) {
   329  			first = 0;
   330  			xputchar('\n');
   331  		}
   332  		xputchar(c);
   333  		do {
   334  			c = getchar_update_lineno();
   335  			xputchar(c);
   336  		} while (c != '\n');
   337  	}
   338  }
   339  
   340  /*
   341   * Read a type in Go syntax and return a type in C syntax.  We only
   342   * permit basic types and pointers.
   343   */
   344  static char *
   345  read_type(void)
   346  {
   347  	char *p, *op, *q;
   348  	int pointer_count;
   349  	unsigned int len;
   350  
   351  	p = read_token_no_eof();
   352  	if (*p != '*' && !streq(p, "int") && !streq(p, "uint"))
   353  		return p;
   354  	op = p;
   355  	pointer_count = 0;
   356  	while (*p == '*') {
   357  		++pointer_count;
   358  		++p;
   359  	}
   360  	len = xstrlen(p);
   361  	q = xmalloc(len + 2 + pointer_count + 1);
   362  	xmemmove(q, p, len);
   363  
   364  	// Turn int/uint into intgo/uintgo.
   365  	if((len == 3 && xmemcmp(q, "int", 3) == 0) || (len == 4 && xmemcmp(q, "uint", 4) == 0)) {
   366  		q[len++] = 'g';
   367  		q[len++] = 'o';
   368  	}
   369  
   370  	while (pointer_count-- > 0)
   371  		q[len++] = '*';
   372  	
   373  	q[len] = '\0';
   374  	xfree(op);
   375  	return q;
   376  }
   377  
   378  /* Return the size of the given type. */
   379  static int
   380  type_size(char *p, int *rnd)
   381  {
   382  	int i;
   383  
   384  	if(p[xstrlen(p)-1] == '*') {
   385  		*rnd = type_table[Uintptr].rnd;
   386  		return type_table[Uintptr].size;
   387  	}
   388  
   389  	if(streq(p, "Iface"))
   390  		p = "Eface";
   391  
   392  	for(i=0; type_table[i].name; i++)
   393  		if(streq(type_table[i].name, p)) {
   394  			*rnd = type_table[i].rnd;
   395  			return type_table[i].size;
   396  		}
   397  	fatal("%s:%d: unknown type %s\n", file, lineno, p);
   398  	return 0;
   399  }
   400  
   401  /*
   402   * Read a list of parameters.  Each parameter is a name and a type.
   403   * The list ends with a ')'.  We have already read the '('.
   404   */
   405  static struct params *
   406  read_params(int *poffset)
   407  {
   408  	char *token;
   409  	struct params *ret, **pp, *p;
   410  	int offset, size, rnd;
   411  
   412  	ret = nil;
   413  	pp = &ret;
   414  	token = read_token_no_eof();
   415  	offset = 0;
   416  	if (!streq(token, ")")) {
   417  		while (1) {
   418  			p = xmalloc(sizeof(struct params));
   419  			p->name = token;
   420  			p->next = nil;
   421  			*pp = p;
   422  			pp = &p->next;
   423  
   424  			if(streq(token, "...")) {
   425  				p->type = xstrdup("");
   426  			} else {
   427  				p->type = read_type();
   428  				rnd = 0;
   429  				size = type_size(p->type, &rnd);
   430  				if(rnd > structround)
   431  					rnd = structround;
   432  				if(offset%rnd)
   433  					offset += rnd - offset%rnd;
   434  				offset += size;
   435  			}
   436  
   437  			token = read_token_no_eof();
   438  			if (!streq(token, ","))
   439  				break;
   440  			token = read_token_no_eof();
   441  		}
   442  	}
   443  	if (!streq(token, ")")) {
   444  		fatal("%s:%d: expected '('\n",
   445  			file, lineno);
   446  	}
   447  	if (poffset != nil)
   448  		*poffset = offset;
   449  	return ret;
   450  }
   451  
   452  /*
   453   * Read a function header.  This reads up to and including the initial
   454   * '{' character.  Returns 1 if it read a header, 0 at EOF.
   455   */
   456  static int
   457  read_func_header(char **name, struct params **params, int *paramwid, struct params **rets)
   458  {
   459  	int lastline;
   460  	char *token;
   461  
   462  	lastline = -1;
   463  	while (1) {
   464  		read_preprocessor_lines();
   465  		token = read_token();
   466  		if (token == nil)
   467  			return 0;
   468  		if (streq(token, "func")) {
   469  			if(lastline != -1)
   470  				bwritef(output, "\n");
   471  			break;
   472  		}
   473  		if (lastline != lineno) {
   474  			if (lastline == lineno-1)
   475  				bwritef(output, "\n");
   476  			else
   477  				bwritef(output, "\n#line %d \"%s\"\n", lineno, file);
   478  			lastline = lineno;
   479  		}
   480  		bwritef(output, "%s ", token);
   481  	}
   482  
   483  	*name = read_token_no_eof();
   484  
   485  	token = read_token();
   486  	if (token == nil || !streq(token, "(")) {
   487  		fatal("%s:%d: expected \"(\"\n",
   488  			file, lineno);
   489  	}
   490  	*params = read_params(paramwid);
   491  
   492  	token = read_token();
   493  	if (token == nil || !streq(token, "("))
   494  		*rets = nil;
   495  	else {
   496  		*rets = read_params(nil);
   497  		token = read_token();
   498  	}
   499  	if (token == nil || !streq(token, "{")) {
   500  		fatal("%s:%d: expected \"{\"\n",
   501  			file, lineno);
   502  	}
   503  	return 1;
   504  }
   505  
   506  /* Write out parameters.  */
   507  static void
   508  write_params(struct params *params, int *first)
   509  {
   510  	struct params *p;
   511  
   512  	for (p = params; p != nil; p = p->next) {
   513  		if (*first)
   514  			*first = 0;
   515  		else
   516  			bwritef(output, ", ");
   517  		bwritef(output, "%s %s", p->type, p->name);
   518  	}
   519  }
   520  
   521  /* Write a 6g function header.  */
   522  static void
   523  write_6g_func_header(char *package, char *name, struct params *params,
   524  		     int paramwid, struct params *rets)
   525  {
   526  	int first, n;
   527  	struct params *p;
   528  
   529  	bwritef(output, "void\n");
   530  	if(!contains(name, "·"))
   531  		bwritef(output, "%s·", package);
   532  	bwritef(output, "%s(", name);
   533  
   534  	first = 1;
   535  	write_params(params, &first);
   536  
   537  	/* insert padding to align output struct */
   538  	if(rets != nil && paramwid%structround != 0) {
   539  		n = structround - paramwid%structround;
   540  		if(n & 1)
   541  			bwritef(output, ", uint8");
   542  		if(n & 2)
   543  			bwritef(output, ", uint16");
   544  		if(n & 4)
   545  			bwritef(output, ", uint32");
   546  	}
   547  
   548  	write_params(rets, &first);
   549  	bwritef(output, ")\n{\n");
   550  	
   551  	for (p = rets; p != nil; p = p->next) {
   552  		if(streq(p->name, "..."))
   553  			continue;
   554  		if(streq(p->type, "Slice"))
   555  			bwritef(output, "\t%s.array = 0;\n\t%s.len = 0;\n\t%s.cap = 0;\n", p->name, p->name, p->name);
   556  		else if(streq(p->type, "String"))
   557  			bwritef(output, "\t%s.str = 0;\n\t%s.len = 0;\n", p->name, p->name);
   558  		else if(streq(p->type, "Eface"))
   559  			bwritef(output, "\t%s.type = 0;\n\t%s.data = 0;\n", p->name, p->name);
   560  		else if(streq(p->type, "Iface"))
   561  			bwritef(output, "\t%s.tab = 0;\n\t%s.data = 0;\n", p->name, p->name);
   562  		else if(streq(p->type, "Complex128"))
   563  			bwritef(output, "\t%s.real = 0;\n\t%s.imag = 0;\n", p->name, p->name);
   564  		else
   565  			bwritef(output, "\t%s = 0;\n", p->name);
   566  		bwritef(output, "\tFLUSH(&%s);\n", p->name);
   567  	}
   568  }
   569  
   570  /* Write a 6g function trailer.  */
   571  static void
   572  write_6g_func_trailer(struct params *rets)
   573  {
   574  	struct params *p;
   575  
   576  	for (p = rets; p != nil; p = p->next)
   577  		if(!streq(p->name, "..."))
   578  			bwritef(output, "\tFLUSH(&%s);\n", p->name);
   579  	bwritef(output, "}\n");
   580  }
   581  
   582  /* Define the gcc function return type if necessary.  */
   583  static void
   584  define_gcc_return_type(char *package, char *name, struct params *rets)
   585  {
   586  	struct params *p;
   587  
   588  	if (rets == nil || rets->next == nil)
   589  		return;
   590  	bwritef(output, "struct %s_%s_ret {\n", package, name);
   591  	for (p = rets; p != nil; p = p->next)
   592  		bwritef(output, "  %s %s;\n", p->type, p->name);
   593  	bwritef(output, "};\n");
   594  }
   595  
   596  /* Write out the gcc function return type.  */
   597  static void
   598  write_gcc_return_type(char *package, char *name, struct params *rets)
   599  {
   600  	if (rets == nil)
   601  		bwritef(output, "void");
   602  	else if (rets->next == nil)
   603  		bwritef(output, "%s", rets->type);
   604  	else
   605  		bwritef(output, "struct %s_%s_ret", package, name);
   606  }
   607  
   608  /* Write out a gcc function header.  */
   609  static void
   610  write_gcc_func_header(char *package, char *name, struct params *params,
   611  		      struct params *rets)
   612  {
   613  	int first;
   614  	struct params *p;
   615  
   616  	define_gcc_return_type(package, name, rets);
   617  	write_gcc_return_type(package, name, rets);
   618  	bwritef(output, " %s_%s(", package, name);
   619  	first = 1;
   620  	write_params(params, &first);
   621  	bwritef(output, ") asm (\"%s.%s\");\n", package, name);
   622  	write_gcc_return_type(package, name, rets);
   623  	bwritef(output, " %s_%s(", package, name);
   624  	first = 1;
   625  	write_params(params, &first);
   626  	bwritef(output, ")\n{\n");
   627  	for (p = rets; p != nil; p = p->next)
   628  		bwritef(output, "  %s %s;\n", p->type, p->name);
   629  }
   630  
   631  /* Write out a gcc function trailer.  */
   632  static void
   633  write_gcc_func_trailer(char *package, char *name, struct params *rets)
   634  {
   635  	if (rets == nil) {
   636  		// nothing to do
   637  	}
   638  	else if (rets->next == nil)
   639  		bwritef(output, "return %s;\n", rets->name);
   640  	else {
   641  		struct params *p;
   642  
   643  		bwritef(output, "  {\n    struct %s_%s_ret __ret;\n", package, name);
   644  		for (p = rets; p != nil; p = p->next)
   645  			bwritef(output, "    __ret.%s = %s;\n", p->name, p->name);
   646  		bwritef(output, "    return __ret;\n  }\n");
   647  	}
   648  	bwritef(output, "}\n");
   649  }
   650  
   651  /* Write out a function header.  */
   652  static void
   653  write_func_header(char *package, char *name,
   654  		  struct params *params, int paramwid,
   655  		  struct params *rets)
   656  {
   657  	if (gcc)
   658  		write_gcc_func_header(package, name, params, rets);
   659  	else
   660  		write_6g_func_header(package, name, params, paramwid, rets);
   661  	bwritef(output, "#line %d \"%s\"\n", lineno, file);
   662  }
   663  
   664  /* Write out a function trailer.  */
   665  static void
   666  write_func_trailer(char *package, char *name,
   667  		   struct params *rets)
   668  {
   669  	if (gcc)
   670  		write_gcc_func_trailer(package, name, rets);
   671  	else
   672  		write_6g_func_trailer(rets);
   673  }
   674  
   675  /*
   676   * Read and write the body of the function, ending in an unnested }
   677   * (which is read but not written).
   678   */
   679  static void
   680  copy_body(void)
   681  {
   682  	int nesting = 0;
   683  	while (1) {
   684  		int c;
   685  
   686  		c = getchar_no_eof();
   687  		if (c == '}' && nesting == 0)
   688  			return;
   689  		xputchar(c);
   690  		switch (c) {
   691  		default:
   692  			break;
   693  		case '{':
   694  			++nesting;
   695  			break;
   696  		case '}':
   697  			--nesting;
   698  			break;
   699  		case '/':
   700  			c = getchar_update_lineno();
   701  			xputchar(c);
   702  			if (c == '/') {
   703  				do {
   704  					c = getchar_no_eof();
   705  					xputchar(c);
   706  				} while (c != '\n');
   707  			} else if (c == '*') {
   708  				while (1) {
   709  					c = getchar_no_eof();
   710  					xputchar(c);
   711  					if (c == '*') {
   712  						do {
   713  							c = getchar_no_eof();
   714  							xputchar(c);
   715  						} while (c == '*');
   716  						if (c == '/')
   717  							break;
   718  					}
   719  				}
   720  			}
   721  			break;
   722  		case '"':
   723  		case '\'':
   724  			{
   725  				int delim = c;
   726  				do {
   727  					c = getchar_no_eof();
   728  					xputchar(c);
   729  					if (c == '\\') {
   730  						c = getchar_no_eof();
   731  						xputchar(c);
   732  						c = '\0';
   733  					}
   734  				} while (c != delim);
   735  			}
   736  			break;
   737  		}
   738  	}
   739  }
   740  
   741  /* Process the entire file.  */
   742  static void
   743  process_file(void)
   744  {
   745  	char *package, *name, *p, *n;
   746  	struct params *params, *rets;
   747  	int paramwid;
   748  
   749  	package = read_package();
   750  	read_preprocessor_lines();
   751  	while (read_func_header(&name, &params, &paramwid, &rets)) {
   752  		// name may have a package override already
   753  		n = xstrstr(name, "·");
   754  		if(n != nil) {
   755  			p = xmalloc(n - name + 1);
   756  			xmemmove(p, name, n - name);
   757  			p[n - name] = 0;
   758  			n += xstrlen("·");
   759  		} else {
   760  			p = package;
   761  			n = name;
   762  		}
   763  		write_func_header(p, n, params, paramwid, rets);
   764  		copy_body();
   765  		write_func_trailer(p, n, rets);
   766  		xfree(name);
   767  		if(p != package) xfree(p);
   768  		free_params(params);
   769  		free_params(rets);
   770  	}
   771  	xfree(package);
   772  }
   773  
   774  void
   775  goc2c(char *goc, char *c)
   776  {
   777  	int i;
   778  	Buf in, out;
   779  	
   780  	binit(&in);
   781  	binit(&out);
   782  	
   783  	file = goc;
   784  	readfile(&in, goc);
   785  
   786  	// TODO: set gcc=1 when using gcc
   787  
   788  	if(!gcc) {
   789  		if(streq(goarch, "amd64")) {
   790  			type_table[Uintptr].size = 8;
   791  			if(use64bitint) {
   792  				type_table[Int].size = 8;
   793  			} else {
   794  				type_table[Int].size = 4;
   795  			}
   796  			structround = 8;
   797  		} else if(streq(goarch, "amd64p32")) {
   798  			type_table[Uintptr].size = 4;
   799  			type_table[Int].size = 4;
   800  			structround = 8;
   801  		} else {
   802  			// NOTE: These are set in the initializer,
   803  			// but they might have been changed by a
   804  			// previous invocation of goc2c, so we have
   805  			// to restore them.
   806  			type_table[Uintptr].size = 4;
   807  			type_table[Int].size = 4;
   808  			structround = 4;
   809  		}
   810  
   811  		type_table[Uint].size = type_table[Int].size;
   812  		type_table[Slice].size = type_table[Uintptr].size+2*type_table[Int].size;
   813  		type_table[Eface].size = 2*type_table[Uintptr].size;
   814  		type_table[String].size = 2*type_table[Uintptr].size;
   815  
   816  		for(i=0; i<nelem(type_table); i++)
   817  			type_table[i].rnd = type_table[i].size;
   818  
   819  		type_table[String].rnd = type_table[Uintptr].rnd;
   820  		type_table[Slice].rnd = type_table[Uintptr].rnd;
   821  		type_table[Eface].rnd = type_table[Uintptr].rnd;
   822  		type_table[Complex128].rnd = type_table[Float64].rnd;
   823  	}
   824  
   825  	bprintf(&out, "// auto generated by go tool dist\n// goos=%s goarch=%s\n\n", goos, goarch);
   826  	input = bstr(&in);
   827  	output = &out;
   828  
   829  	lineno = 1;
   830  	process_file();
   831  	
   832  	writefile(&out, c, 0);
   833  }