diff --git a/Makefile b/Makefile index 36ec60a..b145fdd 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ dist: $(PACKAGE)-$(VERSION)/include/Makefile \ $(PACKAGE)-$(VERSION)/include/project.conf \ $(PACKAGE)-$(VERSION)/src/c99.c \ + $(PACKAGE)-$(VERSION)/src/code.c \ $(PACKAGE)-$(VERSION)/src/main.c \ $(PACKAGE)-$(VERSION)/src/parser.c \ $(PACKAGE)-$(VERSION)/src/scanner.c \ @@ -33,6 +34,9 @@ dist: $(PACKAGE)-$(VERSION)/src/common.h \ $(PACKAGE)-$(VERSION)/src/tokenset.h \ $(PACKAGE)-$(VERSION)/src/project.conf \ + $(PACKAGE)-$(VERSION)/src/target/graph.c \ + $(PACKAGE)-$(VERSION)/src/target/sparc64.c \ + $(PACKAGE)-$(VERSION)/src/target/project.conf \ $(PACKAGE)-$(VERSION)/Makefile \ $(PACKAGE)-$(VERSION)/config.h \ $(PACKAGE)-$(VERSION)/project.conf diff --git a/src/Makefile b/src/Makefile index c88927c..6039d62 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,3 +1,4 @@ +SUBDIRS = target TARGETS = c99 PREFIX = /usr/local DESTDIR = @@ -12,9 +13,12 @@ MKDIR = mkdir -p INSTALL = install -all: $(TARGETS) +all: subdirs $(TARGETS) -c99_OBJS = c99.o main.o parser.o scanner.o tokenset.o +subdirs: + @for i in $(SUBDIRS); do (cd $$i && $(MAKE)) || exit; done + +c99_OBJS = c99.o code.o main.o parser.o scanner.o tokenset.o c99_CFLAGS = $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) c99: $(c99_OBJS) @@ -23,6 +27,9 @@ c99: $(c99_OBJS) c99.o: c99.c ../include/c99.h common.h $(CC) $(c99_CFLAGS) -c c99.c +code.o: code.c + $(CC) $(c99_CFLAGS) -c code.c + main.o: main.c ../include/c99.h $(CC) $(c99_CFLAGS) -c main.c @@ -36,16 +43,21 @@ tokenset.o: tokenset.c ../include/c99.h common.h tokenset.h $(CC) $(c99_CFLAGS) -c tokenset.c clean: + @for i in $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done $(RM) $(c99_OBJS) -distclean: clean +distclean: + @for i in $(SUBDIRS); do (cd $$i && $(MAKE) distclean) || exit; done + $(RM) $(c99_OBJS) $(RM) $(TARGETS) install: all + @for i in $(SUBDIRS); do (cd $$i && $(MAKE) install) || exit; done $(MKDIR) $(DESTDIR)$(BINDIR) $(INSTALL) -m 0755 c99 $(DESTDIR)$(BINDIR)/c99 uninstall: + @for i in $(SUBDIRS); do (cd $$i && $(MAKE) uninstall) || exit; done $(RM) $(DESTDIR)$(BINDIR)/c99 -.PHONY: all clean distclean install uninstall +.PHONY: all subdirs clean distclean install uninstall diff --git a/src/c99.c b/src/c99.c index 53891af..d17a686 100644 --- a/src/c99.c +++ b/src/c99.c @@ -25,6 +25,11 @@ #include "c99.h" +/* private */ +/* constants */ +#define DEFAULT_OBJECT_FILENAME "a.out" + + /* public */ /* functions */ /* c99_new */ @@ -52,7 +57,7 @@ C99 * c99_new(C99Prefs * prefs, char const * pathname) else c99->outfp = NULL; c99->optlevel = prefs->optlevel; - c99->code = code_new(); + c99->code = code_new(prefs->target); /* abort if there was an error */ if(c99->outfile == NULL || c99->outfp == NULL || c99->code == NULL) { @@ -114,7 +119,7 @@ static char * _new_outfile(int flags, char const * outfile, if(flags & C99PREFS_E && outfile == NULL) outfile = ""; else if(outfile == NULL) - outfile = "a.out"; + outfile = DEFAULT_OBJECT_FILENAME; if((ret = strdup(outfile)) == NULL) { error_set_code(1, "%s", strerror(errno)); @@ -136,7 +141,8 @@ int c99_delete(C99 * c99) free(c99->outfile); if(c99->token != NULL) token_delete(c99->token); - code_delete(c99->code); + if(c99->code != NULL) + code_delete(c99->code); object_delete(c99); return ret; } diff --git a/src/code.c b/src/code.c new file mode 100644 index 0000000..055deb9 --- /dev/null +++ b/src/code.c @@ -0,0 +1,199 @@ +/* $Id$ */ +/* Copyright (c) 2008 Pierre Pronchery */ +/* This file is part of DeforaOS Devel c99 */ +/* c99 is not free software; you can redistribute it and/or modify it under the + * terms of the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 + * Unported as published by the Creative Commons organization. + * + * c99 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the Creative Commons Attribution-NonCommercial- + * ShareAlike 3.0 Unported license for more details. + * + * You should have received a copy of the Creative Commons Attribution- + * NonCommercial-ShareAlike 3.0 along with c99; if not, browse to + * http://creativecommons.org/licenses/by-nc-sa/3.0/ */ +/* TODO: + * - scope */ + + + +#include +#include +#include +#ifdef DEBUG +# include +#endif +#include +#include +#include "target/target.h" +#include "code.h" +#include "../config.h" + +#ifndef PACKAGE +# define PACKAGE "c99" +#endif + +#ifndef PREFIX +# define PREFIX "." +#endif + +#ifndef LIBDIR +# define LIBDIR PREFIX "/lib" +#endif + + +/* private */ +/* types */ +typedef struct _CodeType +{ + char * name; +} CodeType; + +typedef struct _CodeVariable +{ + CodeType * type; + char * name; +} CodeVariable; + + +/* prototypes */ +static int _variable_add(Code * code, char const * name); + +static int _code_add_function(Code * code, char const * name); + + +/* protected */ +/* types */ +struct _Code +{ + CodeContext context; + /* types */ + CodeType * types; + unsigned int types_cnt; + CodeVariable * variables; + unsigned int variables_cnt; + /* target */ + Target * target; +}; + + +/* private */ +/* functions */ +/* code_add_function */ +static int _code_add_function(Code * code, char const * name) +{ + return _variable_add(code, name); +} + + +/* variable_add */ +static int _variable_add(Code * code, char const * name) +{ + CodeVariable * p; + + if((p = realloc(code->variables, sizeof(*p) + * (code->variables_cnt + 1))) == NULL) + return 1; /* FIXME report error */ + code->variables = p; + p = &code->variables[code->variables_cnt]; + p->name = strdup(name); + p->type = NULL; /* FIXME implement */ + if(p->name == NULL) + return 1; /* FIXME report error */ + code->variables_cnt++; + return 0; +} + + +/* public */ +/* functions */ +/* code_new */ +static Target * _new_target(char const * target); + +Code * code_new(char const * target) +{ + Code * code; + + if((code = object_new(sizeof(*code))) == NULL) + return NULL; + code->context = CODE_CONTEXT_UNDEFINED; + code->types = NULL; + code->types_cnt = 0; + code->variables = NULL; + code->variables_cnt = 0; + if((code->target = _new_target(target)) == NULL) + { + code_delete(code); + return NULL; + } + return code; +} + +static Target * _new_target(char const * target) +{ + struct utsname * uts; + + if(target == NULL) + { + if(uname(uts) != 0) + { + error_set_code(1, "%s", strerror(errno)); + return NULL; + } + target = uts->machine; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, target); +#endif + } + return plugin_new(LIBDIR, PACKAGE, "target", target); +} + + +/* code_delete */ +void code_delete(Code * code) +{ + free(code->types); + object_delete(code); +} + + +/* accessors */ +/* code_set_context */ +int code_set_context(Code * code, CodeContext context) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(0x%x)\n", __func__, context); +#endif + code->context = context; + return 0; +} + + +/* code_set_identifier */ +int code_set_identifier(Code * code, char const * name) +{ + switch(code->context) + { + case CODE_CONTEXT_FUNCTION_NAME: + return _code_add_function(code, name); + case CODE_CONTEXT_UNDEFINED: + default: + break; + } + return 1; +} + + +/* useful */ +/* code_is_type */ +int code_is_type(Code * code, char const * name) +{ + unsigned int i; + + /* XXX use a hash table if it gets too slow */ + for(i = 0; i < code->types_cnt; i++) + if(strcmp(code->types[i].name, name) == 0) + return 1; + return 0; +} diff --git a/src/code.h b/src/code.h new file mode 100644 index 0000000..60c54e4 --- /dev/null +++ b/src/code.h @@ -0,0 +1,46 @@ +/* $Id$ */ +/* Copyright (c) 2008 Pierre Pronchery */ +/* This file is part of DeforaOS Devel c99 */ +/* c99 is not free software; you can redistribute it and/or modify it under the + * terms of the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 + * Unported as published by the Creative Commons organization. + * + * c99 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the Creative Commons Attribution-NonCommercial- + * ShareAlike 3.0 Unported license for more details. + * + * You should have received a copy of the Creative Commons Attribution- + * NonCommercial-ShareAlike 3.0 along with c99; if not, browse to + * http://creativecommons.org/licenses/by-nc-sa/3.0/ */ + + + +#ifndef _C99_CODE_H +# define _C99_CODE_H + + +/* Code */ +/* protected */ +typedef struct _Code Code; + +typedef enum _CodeContext +{ + CODE_CONTEXT_UNDEFINED = 0, + CODE_CONTEXT_FUNCTION_NAME +} CodeContext; + + +/* public */ +/* functions */ +Code * code_new(char const * target); +void code_delete(Code * code); + +/* accessors */ +int code_set_context(Code * code, CodeContext context); +int code_set_identifier(Code * code, char const * name); + +/* useful */ +int code_is_type(Code * code, char const * name); + +#endif /* !_C99_CODE_H */ diff --git a/src/common.h b/src/common.h index c38b1c6..495e926 100644 --- a/src/common.h +++ b/src/common.h @@ -21,6 +21,7 @@ # include # include +# include "code.h" /* C99 */ @@ -39,11 +40,12 @@ struct _C99 int in_switch; unsigned int error_cnt; unsigned int warning_cnt; + Code * code; }; /* functions */ /* accessors */ -char const * code_get_string(TokenCode code); +char const * tokencode_get_string(TokenCode code); -#endif /* !C99_C99_H */ +#endif /* !_C99_COMMON_H */ diff --git a/src/main.c b/src/main.c index fae8bbf..3140383 100644 --- a/src/main.c +++ b/src/main.c @@ -72,7 +72,7 @@ int main(int argc, char * argv[]) memset(&prefs, 0, sizeof(prefs)); if(_main_default_paths(&prefs) != 0) return 2; - while((o = getopt(argc, argv, "cD:EgI:L:o:O123sU:")) != -1) + while((o = getopt(argc, argv, "cD:EgI:L:o:O123sU:m:")) != -1) switch(o) { case 'c': @@ -110,6 +110,9 @@ int main(int argc, char * argv[]) case '3': prefs.optlevel = o - '0'; break; + case 'm': + prefs.target = optarg; + break; default: return _usage(); } diff --git a/src/parser.c b/src/parser.c index 8b6bb56..e110ae1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -32,9 +32,7 @@ /* prototypes */ static int _parse_check(C99 * c99, TokenCode code); static int _parse_error(C99 * c99, char const * format, ...); -#ifdef DEBUG static char const * _parse_get_string(C99 * c99); -#endif static int _parse_in_set(C99 * c99, TokenSet set); static int _parse_is_code(C99 * c99, TokenCode code); @@ -120,7 +118,7 @@ static int _parse_check(C99 * c99, TokenCode code) if(!_parse_is_code(c99, code)) { ret = _parse_error(c99, "Expected \"%s\"", - code_get_string(code)); + tokencode_get_string(code)); while(c99_scan(c99) == 0 && c99->token != NULL /* actual token */ && !_parse_is_code(c99, code)); @@ -152,14 +150,12 @@ static int _parse_error(C99 * c99, char const * format, ...) /* parse_get_string */ -#ifdef DEBUG static char const * _parse_get_string(C99 * c99) { if(c99->token == NULL) return "EOF"; return token_get_string(c99->token); } -#endif /* parse_in_set */ @@ -226,6 +222,7 @@ static int _function_definition(C99 * c99) fprintf(stderr, "DEBUG: %s()\n", __func__); #endif ret = _declaration_specifiers(c99); + ret |= code_set_context(c99->code, CODE_CONTEXT_FUNCTION_NAME); ret |= _declarator(c99); if(_parse_in_set(c99, c99set_declaration_list)) ret |= _declaration_list(c99); @@ -252,7 +249,7 @@ static int _declaration_list(C99 * c99) /* declaration */ static int _declaration(C99 * c99) - /* declaration-specifiers [ init-declarator-list ] */ + /* declaration-specifiers [ init-declarator-list ] ";" */ { int ret = 0; @@ -262,6 +259,7 @@ static int _declaration(C99 * c99) ret |= _declaration_specifiers(c99); if(_parse_in_set(c99, c99set_init_declarator)) ret |= _init_declarator_list(c99); + ret |= _parse_check(c99, C99_CODE_OPERATOR_SEMICOLON); return ret; } @@ -540,7 +538,7 @@ static int _function_specifier(C99 * c99) /* "inline" */ { #ifdef DEBUG - fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, + fprintf(stderr, "DEBUG: %s() \"inline\" got \"%s\"\n", __func__, _parse_get_string(c99)); #endif return c99_scan(c99); @@ -656,11 +654,16 @@ static int _direct_declarator(C99 * c99) static int _identifier(C99 * c99) /* identifier-nondigit { (identifier-nondigit | identifier-digit) } */ { + int ret; + char const * str; + + str = _parse_get_string(c99); #ifdef DEBUG - fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, - _parse_get_string(c99)); + fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, str); #endif - return c99_scan(c99); + ret = code_set_identifier(c99->code, str); + ret |= c99_scan(c99); + return ret; } @@ -679,6 +682,7 @@ static int _identifier_list(C99 * c99) ret |= c99_scan(c99); ret |= _identifier(c99); } + ret |= code_set_context(c99->code, CODE_CONTEXT_UNDEFINED); return ret; } diff --git a/src/project.conf b/src/project.conf index 065e408..293495e 100644 --- a/src/project.conf +++ b/src/project.conf @@ -3,11 +3,12 @@ cppflags=-I ../include cflags_force=-W cflags=-Wall -ansi -g ldflags_force=-L $(PREFIX)/lib -Wl,-rpath $(PREFIX)/lib -l cpp +subdirs=target dist=Makefile,common.h,tokenset.h [c99] type=binary -sources=c99.c,main.c,parser.c,scanner.c,tokenset.c +sources=c99.c,code.c,main.c,parser.c,scanner.c,tokenset.c [c99.c] depends=../include/c99.h,common.h diff --git a/src/scanner.c b/src/scanner.c index 931091e..3f044f8 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -51,7 +51,7 @@ static char * _tokens[] = /* protected */ /* functions */ /* accessors */ -char const * code_get_string(TokenCode code) +char const * tokencode_get_string(TokenCode code) { return _tokens[code]; } @@ -96,7 +96,8 @@ int c99_scan(C99 * c99) } c = string[0]; if(isalpha(c)) - token_set_code(c99->token, C99_CODE_IDENTIFIER); + token_set_code(c99->token, code_is_type(c99->code, string) + ? C99_CODE_TYPEDEF_NAME : C99_CODE_IDENTIFIER); else if(isdigit(c)) /* FIXME make a stricter check? */ token_set_code(c99->token, C99_CODE_CONSTANT); return 0;