diff options
Diffstat (limited to 'src/pkg/runtime/goc2c.c')
| -rw-r--r-- | src/pkg/runtime/goc2c.c | 723 | 
1 files changed, 0 insertions, 723 deletions
| diff --git a/src/pkg/runtime/goc2c.c b/src/pkg/runtime/goc2c.c deleted file mode 100644 index 826ceff3a..000000000 --- a/src/pkg/runtime/goc2c.c +++ /dev/null @@ -1,723 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* Translate a .goc file into a .c file.  A .goc file is a combination -   of a limited form of Go with C.  */ - -/* -   package PACKAGENAME -   {# line} -   func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] \{ -     C code with proper brace nesting -   \} -*/ - -/* We generate C code which implements the function such that it can -   be called from Go and executes the C code.  */ - -#include <assert.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -/* Whether we're emitting for gcc */ -static int gcc; - -/* File and line number */ -static const char *file; -static unsigned int lineno = 1; - -/* List of names and types.  */ -struct params { -	struct params *next; -	char *name; -	char *type; -}; - -/* index into type_table */ -enum { -	Bool, -	Float, -	Int, -	Uint, -	Uintptr, -	String, -	Slice, -	Eface, -}; - -static struct { -	char *name; -	int size; -} type_table[] = { -	/* variable sized first, for easy replacement */ -	/* order matches enum above */ -	/* default is 32-bit architecture sizes */ -	"bool",		1, -	"float",	4, -	"int",		4, -	"uint",		4, -	"uintptr",	4, -	"String",	8, -	"Slice",	12, -	"Eface",	8, - -	/* fixed size */ -	"float32",	4, -	"float64",	8, -	"byte",		1, -	"int8",		1, -	"uint8",	1, -	"int16",	2, -	"uint16",	2, -	"int32",	4, -	"uint32",	4, -	"int64",	8, -	"uint64",	8, - -	NULL, -}; - -/* Fixed structure alignment (non-gcc only) */ -int structround = 4; - -/* Unexpected EOF.  */ -static void -bad_eof(void) -{ -	fprintf(stderr, "%s:%u: unexpected EOF\n", file, lineno); -	exit(1); -} - -/* Out of memory.  */ -static void -bad_mem(void) -{ -	fprintf(stderr, "%s:%u: out of memory\n", file, lineno); -	exit(1); -} - -/* Allocate memory without fail.  */ -static void * -xmalloc(unsigned int size) -{ -	void *ret = malloc(size); -	if (ret == NULL) -		bad_mem(); -	return ret; -} - -/* Reallocate memory without fail.  */ -static void* -xrealloc(void *buf, unsigned int size) -{ -	void *ret = realloc(buf, size); -	if (ret == NULL) -		bad_mem(); -	return ret; -} - -/* Free a list of parameters.  */ -static void -free_params(struct params *p) -{ -	while (p != NULL) { -		struct params *next; - -		next = p->next; -		free(p->name); -		free(p->type); -		free(p); -		p = next; -	} -} - -/* Read a character, tracking lineno.  */ -static int -getchar_update_lineno(void) -{ -	int c; - -	c = getchar(); -	if (c == '\n') -		++lineno; -	return c; -} - -/* Read a character, giving an error on EOF, tracking lineno.  */ -static int -getchar_no_eof(void) -{ -	int c; - -	c = getchar_update_lineno(); -	if (c == EOF) -		bad_eof(); -	return c; -} - -/* Read a character, skipping comments.  */ -static int -getchar_skipping_comments(void) -{ -	int c; - -	while (1) { -		c = getchar_update_lineno(); -		if (c != '/') -			return c; - -		c = getchar(); -		if (c == '/') { -			do { -				c = getchar_update_lineno(); -			} while (c != EOF && c != '\n'); -			return c; -		} else if (c == '*') { -			while (1) { -				c = getchar_update_lineno(); -				if (c == EOF) -					return EOF; -				if (c == '*') { -					do { -						c = getchar_update_lineno(); -					} while (c == '*'); -					if (c == '/') -						break; -				} -			} -		} else { -			ungetc(c, stdin); -			return '/'; -		} -	} -} - -/* Read and return a token.  Tokens are delimited by whitespace or by -   [(),{}].  The latter are all returned as single characters.  */ -static char * -read_token(void) -{ -	int c; -	char *buf; -	unsigned int alc, off; -	const char* delims = "(),{}"; - -	while (1) { -		c = getchar_skipping_comments(); -		if (c == EOF) -			return NULL; -		if (!isspace(c)) -			break; -	} -	alc = 16; -	buf = xmalloc(alc + 1); -	off = 0; -	if (strchr(delims, c) != NULL) { -		buf[off] = c; -		++off; -	} else { -		while (1) { -			if (off >= alc) { -				alc *= 2; -				buf = xrealloc(buf, alc + 1); -			} -			buf[off] = c; -			++off; -			c = getchar_skipping_comments(); -			if (c == EOF) -				break; -			if (isspace(c) || strchr(delims, c) != NULL) { -				if (c == '\n') -					lineno--; -				ungetc(c, stdin); -				break; -			} -		} -	} -	buf[off] = '\0'; -	return buf; -} - -/* Read a token, giving an error on EOF.  */ -static char * -read_token_no_eof(void) -{ -	char *token = read_token(); -	if (token == NULL) -		bad_eof(); -	return token; -} - -/* Read the package clause, and return the package name.  */ -static char * -read_package(void) -{ -	char *token; - -	token = read_token_no_eof(); -	if (strcmp(token, "package") != 0) { -		fprintf(stderr, -			"%s:%u: expected \"package\", got \"%s\"\n", -			file, lineno, token); -		exit(1); -	} -	return read_token_no_eof(); -} - -/* Read and copy preprocessor lines.  */ -static void -read_preprocessor_lines(void) -{ -	while (1) { -		int c; - -		do { -			c = getchar_skipping_comments(); -		} while (isspace(c)); -		if (c != '#') { -			ungetc(c, stdin); -			break; -		} -		putchar(c); -		do { -			c = getchar_update_lineno(); -			putchar(c); -		} while (c != '\n'); -	} -} - -/* Read a type in Go syntax and return a type in C syntax.  We only -   permit basic types and pointers.  */ -static char * -read_type(void) -{ -	char *p, *op, *q; -	int pointer_count; -	unsigned int len; - -	p = read_token_no_eof(); -	if (*p != '*') -		return p; -	op = p; -	pointer_count = 0; -	while (*p == '*') { -		++pointer_count; -		++p; -	} -	len = strlen(p); -	q = xmalloc(len + pointer_count + 1); -	memcpy(q, p, len); -	while (pointer_count > 0) { -		q[len] = '*'; -		++len; -		--pointer_count; -	} -	q[len] = '\0'; -	free(op); -	return q; -} - -/* Return the size of the given type. */ -static int -type_size(char *p) -{ -	int i; - -	if(p[strlen(p)-1] == '*') -		return type_table[Uintptr].size; - -	for(i=0; type_table[i].name; i++) -		if(strcmp(type_table[i].name, p) == 0) -			return type_table[i].size; -	fprintf(stderr, "%s:%u: unknown type %s\n", file, lineno, p); -	exit(1); -	return 0; -} - -/* Read a list of parameters.  Each parameter is a name and a type. -   The list ends with a ')'.  We have already read the '('.  */ -static struct params * -read_params(int *poffset) -{ -	char *token; -	struct params *ret, **pp, *p; -	int offset, size, rnd; - -	ret = NULL; -	pp = &ret; -	token = read_token_no_eof(); -	offset = 0; -	if (strcmp(token, ")") != 0) { -		while (1) { -			p = xmalloc(sizeof(struct params)); -			p->name = token; -			p->type = read_type(); -			p->next = NULL; -			*pp = p; -			pp = &p->next; - -			size = type_size(p->type); -			rnd = size; -			if(rnd > structround) -				rnd = structround; -			if(offset%rnd) -				offset += rnd - offset%rnd; -			offset += size; - -			token = read_token_no_eof(); -			if (strcmp(token, ",") != 0) -				break; -			token = read_token_no_eof(); -		} -	} -	if (strcmp(token, ")") != 0) { -		fprintf(stderr, "%s:%u: expected '('\n", -			file, lineno); -		exit(1); -	} -	if (poffset != NULL) -		*poffset = offset; -	return ret; -} - -/* Read a function header.  This reads up to and including the initial -   '{' character.  Returns 1 if it read a header, 0 at EOF.  */ -static int -read_func_header(char **name, struct params **params, int *paramwid, struct params **rets) -{ -	int lastline; -	char *token; - -	lastline = -1; -	while (1) { -		token = read_token(); -		if (token == NULL) -			return 0; -		if (strcmp(token, "func") == 0) { -			if(lastline != -1) -				printf("\n"); -			break; -		} -		if (lastline != lineno) { -			if (lastline == lineno-1) -				printf("\n"); -			else -				printf("\n#line %d \"%s\"\n", lineno, file); -			lastline = lineno; -		} -		printf("%s ", token); -	} - -	*name = read_token_no_eof(); - -	token = read_token(); -	if (token == NULL || strcmp(token, "(") != 0) { -		fprintf(stderr, "%s:%u: expected \"(\"\n", -			file, lineno); -		exit(1); -	} -	*params = read_params(paramwid); - -	token = read_token(); -	if (token == NULL || strcmp(token, "(") != 0) -		*rets = NULL; -	else { -		*rets = read_params(NULL); -		token = read_token(); -	} -	if (token == NULL || strcmp(token, "{") != 0) { -		fprintf(stderr, "%s:%u: expected \"{\"\n", -			file, lineno); -		exit(1); -	} -	return 1; -} - -/* Write out parameters.  */ -static void -write_params(struct params *params, int *first) -{ -	struct params *p; - -	for (p = params; p != NULL; p = p->next) { -		if (*first) -			*first = 0; -		else -			printf(", "); -		printf("%s %s", p->type, p->name); -	} -} - -/* Write a 6g function header.  */ -static void -write_6g_func_header(char *package, char *name, struct params *params, -		     int paramwid, struct params *rets) -{ -	int first, n; - -	printf("void\n%s·%s(", package, name); -	first = 1; -	write_params(params, &first); - -	/* insert padding to align output struct */ -	if(rets != NULL && paramwid%structround != 0) { -		n = structround - paramwid%structround; -		if(n & 1) -			printf(", uint8"); -		if(n & 2) -			printf(", uint16"); -		if(n & 4) -			printf(", uint32"); -	} - -	write_params(rets, &first); -	printf(")\n{\n"); -} - -/* Write a 6g function trailer.  */ -static void -write_6g_func_trailer(struct params *rets) -{ -	struct params *p; - -	for (p = rets; p != NULL; p = p->next) -		printf("\tFLUSH(&%s);\n", p->name); -	printf("}\n"); -} - -/* Define the gcc function return type if necessary.  */ -static void -define_gcc_return_type(char *package, char *name, struct params *rets) -{ -	struct params *p; - -	if (rets == NULL || rets->next == NULL) -		return; -	printf("struct %s_%s_ret {\n", package, name); -	for (p = rets; p != NULL; p = p->next) -		printf("  %s %s;\n", p->type, p->name); -	printf("};\n"); -} - -/* Write out the gcc function return type.  */ -static void -write_gcc_return_type(char *package, char *name, struct params *rets) -{ -	if (rets == NULL) -		printf("void"); -	else if (rets->next == NULL) -		printf("%s", rets->type); -	else -		printf("struct %s_%s_ret", package, name); -} - -/* Write out a gcc function header.  */ -static void -write_gcc_func_header(char *package, char *name, struct params *params, -		      struct params *rets) -{ -	int first; -	struct params *p; - -	define_gcc_return_type(package, name, rets); -	write_gcc_return_type(package, name, rets); -	printf(" %s_%s(", package, name); -	first = 1; -	write_params(params, &first); -	printf(") asm (\"%s.%s\");\n", package, name); -	write_gcc_return_type(package, name, rets); -	printf(" %s_%s(", package, name); -	first = 1; -	write_params(params, &first); -	printf(")\n{\n"); -	for (p = rets; p != NULL; p = p->next) -		printf("  %s %s;\n", p->type, p->name); -} - -/* Write out a gcc function trailer.  */ -static void -write_gcc_func_trailer(char *package, char *name, struct params *rets) -{ -	if (rets == NULL) -		; -	else if (rets->next == NULL) -		printf("return %s;\n", rets->name); -	else { -		struct params *p; - -		printf("  {\n    struct %s_%s_ret __ret;\n", package, name); -		for (p = rets; p != NULL; p = p->next) -			printf("    __ret.%s = %s;\n", p->name, p->name); -		printf("    return __ret;\n  }\n"); -	} -	printf("}\n"); -} - -/* Write out a function header.  */ -static void -write_func_header(char *package, char *name, -		  struct params *params, int paramwid, -		  struct params *rets) -{ -	if (gcc) -		write_gcc_func_header(package, name, params, rets); -	else -		write_6g_func_header(package, name, params, paramwid, rets); -	printf("#line %d \"%s\"\n", lineno, file); -} - -/* Write out a function trailer.  */ -static void -write_func_trailer(char *package, char *name, -		   struct params *rets) -{ -	if (gcc) -		write_gcc_func_trailer(package, name, rets); -	else -		write_6g_func_trailer(rets); -} - -/* Read and write the body of the function, ending in an unnested } -   (which is read but not written).  */ -static void -copy_body(void) -{ -	int nesting = 0; -	while (1) { -		int c; - -		c = getchar_no_eof(); -		if (c == '}' && nesting == 0) -			return; -		putchar(c); -		switch (c) { -		default: -			break; -		case '{': -			++nesting; -			break; -		case '}': -			--nesting; -			break; -		case '/': -			c = getchar_update_lineno(); -			putchar(c); -			if (c == '/') { -				do { -					c = getchar_no_eof(); -					putchar(c); -				} while (c != '\n'); -			} else if (c == '*') { -				while (1) { -					c = getchar_no_eof(); -					putchar(c); -					if (c == '*') { -						do { -							c = getchar_no_eof(); -							putchar(c); -						} while (c == '*'); -						if (c == '/') -							break; -					} -				} -			} -			break; -		case '"': -		case '\'': -			{ -				int delim = c; -				do { -					c = getchar_no_eof(); -					putchar(c); -					if (c == '\\') { -						c = getchar_no_eof(); -						putchar(c); -						c = '\0'; -					} -				} while (c != delim); -			} -			break; -		} -	} -} - -/* Process the entire file.  */ -static void -process_file(void) -{ -	char *package, *name; -	struct params *params, *rets; -	int paramwid; - -	package = read_package(); -	read_preprocessor_lines(); -	while (read_func_header(&name, ¶ms, ¶mwid, &rets)) { -		write_func_header(package, name, params, paramwid, rets); -		copy_body(); -		write_func_trailer(package, name, rets); -		free(name); -		free_params(params); -		free_params(rets); -	} -	free(package); -} - -static void -usage(void) -{ -	fprintf(stderr, "Usage: goc2c [--6g | --gc] [file]\n"); -	exit(1); -} - -int -main(int argc, char **argv) -{ -	char *goarch; - -	while(argc > 1 && argv[1][0] == '-') { -		if(strcmp(argv[1], "-") == 0) -			break; -		if(strcmp(argv[1], "--6g") == 0) -			gcc = 0; -		else if(strcmp(argv[1], "--gcc") == 0) -			gcc = 1; -		else -			usage(); -		argc--; -		argv++; -	} - -	if(argc <= 1 || strcmp(argv[1], "-") == 0) { -		file = "<stdin>"; -		process_file(); -		return 0; -	} - -	if(argc > 2) -		usage(); - -	file = argv[1]; -	if(freopen(file, "r", stdin) == 0) { -		fprintf(stderr, "open %s: %s\n", file, strerror(errno)); -		exit(1); -	} - -	if(!gcc) { -		// 6g etc; update size table -		goarch = getenv("GOARCH"); -		if(goarch != NULL && strcmp(goarch, "amd64") == 0) { -			type_table[Uintptr].size = 8; -			type_table[String].size = 16; -			type_table[Slice].size = 8+4+4; -			type_table[Eface].size = 8+8; -			structround = 8; -		} -	} - -	process_file(); -	return 0; -} | 
