Added initial code generation helpers

This commit is contained in:
Pierre Pronchery 2008-04-11 13:05:07 +00:00
parent 7995b14977
commit 557df7e414
10 changed files with 301 additions and 23 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

199
src/code.c Normal file
View File

@ -0,0 +1,199 @@
/* $Id$ */
/* Copyright (c) 2008 Pierre Pronchery <khorben@defora.org> */
/* 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 <System.h>
#include <sys/utsname.h>
#include <stdlib.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#include <string.h>
#include <errno.h>
#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;
}

46
src/code.h Normal file
View File

@ -0,0 +1,46 @@
/* $Id$ */
/* Copyright (c) 2008 Pierre Pronchery <khorben@defora.org> */
/* 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 */

View File

@ -21,6 +21,7 @@
# include <stdio.h>
# include <cpp.h>
# 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 */

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;