Added initial code generation helpers
This commit is contained in:
parent
7995b14977
commit
557df7e414
4
Makefile
4
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
|
||||
|
20
src/Makefile
20
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
|
||||
|
12
src/c99.c
12
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;
|
||||
}
|
||||
|
199
src/code.c
Normal file
199
src/code.c
Normal 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
46
src/code.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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();
|
||||
}
|
||||
|
24
src/parser.c
24
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user