First implementation attempt
This commit is contained in:
parent
7ad15ec40e
commit
7b054a571a
10
Makefile
10
Makefile
|
@ -1,6 +1,6 @@
|
|||
PACKAGE = cpp
|
||||
VERSION = 0.0.0
|
||||
SUBDIRS = src
|
||||
VERSION = 0.0.1
|
||||
SUBDIRS = include src
|
||||
RM = rm -f
|
||||
LN = ln -sf
|
||||
TAR = tar -czvf
|
||||
|
@ -21,12 +21,16 @@ dist:
|
|||
$(RM) -r $(PACKAGE)-$(VERSION)
|
||||
$(LN) . $(PACKAGE)-$(VERSION)
|
||||
@$(TAR) $(PACKAGE)-$(VERSION).tar.gz \
|
||||
$(PACKAGE)-$(VERSION)/src/parser.c \
|
||||
$(PACKAGE)-$(VERSION)/include/cpp.h \
|
||||
$(PACKAGE)-$(VERSION)/include/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/include/project.conf \
|
||||
$(PACKAGE)-$(VERSION)/src/cpp.c \
|
||||
$(PACKAGE)-$(VERSION)/src/main.c \
|
||||
$(PACKAGE)-$(VERSION)/src/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/src/project.conf \
|
||||
$(PACKAGE)-$(VERSION)/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/COPYING \
|
||||
$(PACKAGE)-$(VERSION)/config.h \
|
||||
$(PACKAGE)-$(VERSION)/project.conf
|
||||
$(RM) $(PACKAGE)-$(VERSION)
|
||||
|
||||
|
|
6
config.h
Normal file
6
config.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define PACKAGE "cpp"
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
#ifndef PREFIX
|
||||
# define PREFIX "/usr/local"
|
||||
#endif
|
|
@ -1,5 +1,6 @@
|
|||
package=cpp
|
||||
version=0.0.0
|
||||
version=0.0.1
|
||||
config=h
|
||||
|
||||
subdirs=src
|
||||
dist=Makefile,COPYING
|
||||
subdirs=include,src
|
||||
dist=Makefile,COPYING,config.h
|
||||
|
|
14
src/Makefile
14
src/Makefile
|
@ -3,14 +3,13 @@ PREFIX = /usr/local
|
|||
DESTDIR =
|
||||
LIBDIR = $(PREFIX)/lib
|
||||
CC = cc
|
||||
CPPFLAGS=
|
||||
CPPFLAGS= -I ../include
|
||||
CFLAGSF = -W -Wall
|
||||
CFLAGS = -g
|
||||
AR = ar -rc
|
||||
RANLIB = ranlib
|
||||
LD = ld -shared
|
||||
BINDIR = $(PREFIX)/bin
|
||||
INCLUDEDIR= $(PREFIX)/include
|
||||
RM = rm -f
|
||||
MKDIR = mkdir -p
|
||||
INSTALL = install
|
||||
|
@ -18,7 +17,7 @@ INSTALL = install
|
|||
|
||||
all: $(TARGETS)
|
||||
|
||||
libcpp_OBJS = parser.o cpp.o
|
||||
libcpp_OBJS = cpp.o
|
||||
libcpp_CFLAGS = $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) -fPIC
|
||||
|
||||
libcpp.a: $(libcpp_OBJS)
|
||||
|
@ -32,15 +31,12 @@ cpp_OBJS = main.o
|
|||
cpp_CFLAGS = $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
||||
|
||||
cpp: $(cpp_OBJS)
|
||||
$(CC) -o cpp $(cpp_OBJS) $(LDFLAGSF) $(LDFLAGS) -l cpp -L .
|
||||
$(CC) -o cpp $(cpp_OBJS) $(LDFLAGSF) $(LDFLAGS) -Wl,-rpath,$(LIBDIR) -L $(LIBDIR) -L . -l cpp -l System -l ssl
|
||||
|
||||
parser.o: parser.c parser.h
|
||||
$(CC) $(libcpp_CFLAGS) -c parser.c
|
||||
|
||||
cpp.o: cpp.c parser.h cpp.h
|
||||
cpp.o: cpp.c ../include/cpp.h
|
||||
$(CC) $(libcpp_CFLAGS) -c cpp.c
|
||||
|
||||
main.o: main.c cpp.h
|
||||
main.o: main.c ../include/cpp.h
|
||||
$(CC) $(cpp_CFLAGS) -c main.c
|
||||
|
||||
clean:
|
||||
|
|
538
src/cpp.c
538
src/cpp.c
|
@ -1,5 +1,5 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2007 Pierre Pronchery <khorben@defora.org> */
|
||||
/* Copyright (c) 2008 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Devel cpp */
|
||||
/* cpp is not free software; you can redistribute it and/or modify it under the
|
||||
* terms of the Creative Commons Attribution-NonCommercial-ShareAlike 3.0
|
||||
|
@ -20,31 +20,496 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include "parser.h"
|
||||
#include <errno.h>
|
||||
#include <System.h>
|
||||
#include "cpp.h"
|
||||
|
||||
|
||||
/* CppParser */
|
||||
/* private */
|
||||
/* types */
|
||||
typedef struct _CppOperator
|
||||
{
|
||||
CppCode code;
|
||||
char const * string;
|
||||
} CppOperator;
|
||||
|
||||
typedef struct _CppParser
|
||||
{
|
||||
Parser * parser;
|
||||
const CppOperator * operators;
|
||||
size_t operators_cnt;
|
||||
} CppParser;
|
||||
|
||||
|
||||
/* variables */
|
||||
static const CppOperator _cpp_operators[] =
|
||||
{
|
||||
/* FIXME "&=" */
|
||||
{ CPP_CODE_OPERATOR_DAMPERSAND, "&&" },
|
||||
{ CPP_CODE_OPERATOR_AMPERSAND, "&" },
|
||||
{ CPP_CODE_OPERATOR_COLON, ":" },
|
||||
{ CPP_CODE_OPERATOR_DBAR, "||" },
|
||||
{ CPP_CODE_OPERATOR_BAR, "|" },
|
||||
{ CPP_CODE_OPERATOR_DIVIDE, "/" },
|
||||
{ CPP_CODE_OPERATOR_DOT, "." },
|
||||
{ CPP_CODE_OPERATOR_DEQUALS, "==" },
|
||||
{ CPP_CODE_OPERATOR_EQUALS, "=" },
|
||||
{ CPP_CODE_OPERATOR_DGREATER, ">>" },
|
||||
{ CPP_CODE_OPERATOR_GREATER, ">" },
|
||||
{ CPP_CODE_OPERATOR_INVERSE, "~" },
|
||||
{ CPP_CODE_OPERATOR_LBRACE, "{" },
|
||||
{ CPP_CODE_OPERATOR_LBRACKET, "[" },
|
||||
{ CPP_CODE_OPERATOR_DLESS, "<<" },
|
||||
{ CPP_CODE_OPERATOR_LESS, "<" },
|
||||
{ CPP_CODE_OPERATOR_LPAREN, "(" },
|
||||
/* FIXME "|=" */
|
||||
/* FIXME "->" */
|
||||
/* FIXME "-=" */
|
||||
{ CPP_CODE_OPERATOR_DMINUS, "--" },
|
||||
{ CPP_CODE_OPERATOR_MINUS, "-" },
|
||||
{ CPP_CODE_OPERATOR_MODULO, "%" },
|
||||
{ CPP_CODE_OPERATOR_MULTIPLY, "*" },
|
||||
{ CPP_CODE_OPERATOR_NOT, "!" },
|
||||
/* FIXME "+=" */
|
||||
{ CPP_CODE_OPERATOR_DPLUS, "++" },
|
||||
{ CPP_CODE_OPERATOR_PLUS, "+" },
|
||||
{ CPP_CODE_OPERATOR_RBRACE, "}" },
|
||||
{ CPP_CODE_OPERATOR_RBRACKET, "]" },
|
||||
{ CPP_CODE_OPERATOR_RPAREN, ")" },
|
||||
{ CPP_CODE_OPERATOR_SEMICOLON, ";" },
|
||||
{ CPP_CODE_OPERATOR_XOR, "^" }
|
||||
};
|
||||
static const size_t _cpp_operators_cnt = sizeof(_cpp_operators)
|
||||
/ sizeof(*_cpp_operators);
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static CppParser * _cppparser_new(char const * filename, int filters,
|
||||
const CppOperator * operators, size_t operators_cnt);
|
||||
static void _cppparser_delete(CppParser * cppparser);
|
||||
|
||||
|
||||
|
||||
/* Cpp */
|
||||
/* private */
|
||||
/* types */
|
||||
struct _Cpp
|
||||
{
|
||||
Parser ** parser;
|
||||
size_t parser_cnt;
|
||||
char error[PATH_MAX];
|
||||
CppParser ** parsers;
|
||||
size_t parsers_cnt;
|
||||
int filters;
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
/* useful */
|
||||
static int _cpp_filter_newlines(int * c, void * data);
|
||||
static int _cpp_filter_trigraphs(int * c, void * data);
|
||||
|
||||
/* FIXME the callbacks do not set a token code yet */
|
||||
static int _cpp_callback_whitespace(Parser * parser, Token * token, int c,
|
||||
void * data);
|
||||
/* FIXME handle directives */
|
||||
static int _cpp_callback_comment(Parser * parser, Token * token, int c,
|
||||
void * data);
|
||||
static int _cpp_callback_operator(Parser * parser, Token * token, int c,
|
||||
void * data);
|
||||
static int _cpp_callback_quote(Parser * parser, Token * token, int c,
|
||||
void * data);
|
||||
static int _cpp_callback_word(Parser * parser, Token * token, int c,
|
||||
void * data);
|
||||
static int _cpp_callback_unknown(Parser * parser, Token * token, int c,
|
||||
void * data);
|
||||
|
||||
|
||||
|
||||
/* CppParser */
|
||||
/* private */
|
||||
/* functions */
|
||||
static CppParser * _cppparser_new(char const * filename, int filters,
|
||||
const CppOperator * operators, size_t operators_cnt)
|
||||
{
|
||||
CppParser * cppparser;
|
||||
|
||||
if((cppparser = object_new(sizeof(*cppparser))) == NULL)
|
||||
return NULL;
|
||||
cppparser->operators = operators;
|
||||
cppparser->operators_cnt = operators_cnt;
|
||||
if((cppparser->parser = parser_new(filename)) == NULL)
|
||||
{
|
||||
_cppparser_delete(cppparser);
|
||||
return NULL;
|
||||
}
|
||||
parser_add_filter(cppparser->parser, _cpp_filter_newlines,
|
||||
cppparser->parser);
|
||||
if(filters & CPP_FILTER_TRIGRAPH)
|
||||
parser_add_filter(cppparser->parser, _cpp_filter_trigraphs,
|
||||
cppparser->parser);
|
||||
parser_add_callback(cppparser->parser, _cpp_callback_whitespace, NULL);
|
||||
parser_add_callback(cppparser->parser, _cpp_callback_comment, NULL);
|
||||
parser_add_callback(cppparser->parser, _cpp_callback_operator,
|
||||
cppparser);
|
||||
parser_add_callback(cppparser->parser, _cpp_callback_quote, NULL);
|
||||
parser_add_callback(cppparser->parser, _cpp_callback_word, NULL);
|
||||
parser_add_callback(cppparser->parser, _cpp_callback_unknown, NULL);
|
||||
return cppparser;
|
||||
}
|
||||
|
||||
|
||||
/* cppparser_delete */
|
||||
static void _cppparser_delete(CppParser * cppparser)
|
||||
{
|
||||
parser_delete(cppparser->parser);
|
||||
object_delete(cppparser);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Cpp */
|
||||
/* private */
|
||||
static int _cpp_filter_newlines(int * c, void * data)
|
||||
{
|
||||
Parser * parser = data;
|
||||
/* FIXME obtain from data */
|
||||
static int last;
|
||||
static int last_cnt = 0;
|
||||
|
||||
if(last_cnt)
|
||||
{
|
||||
last_cnt--;
|
||||
*c = last;
|
||||
return 0;
|
||||
}
|
||||
if(*c != '\\')
|
||||
return 0;
|
||||
if((*c = parser_scan(parser)) == '\n')
|
||||
{
|
||||
*c = parser_scan(parser); /* skip the newline */
|
||||
return 0;
|
||||
}
|
||||
last = *c;
|
||||
last_cnt = 1;
|
||||
*c = '\\';
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int _cpp_filter_trigraphs(int * c, void * data)
|
||||
{
|
||||
Parser * parser = data;
|
||||
static int last;
|
||||
static int last_cnt = 0;
|
||||
|
||||
if(last_cnt == 2)
|
||||
{
|
||||
last_cnt--;
|
||||
*c = '?';
|
||||
return 0;
|
||||
}
|
||||
else if(last_cnt == 1)
|
||||
{
|
||||
last_cnt--;
|
||||
*c = last;
|
||||
return 0;
|
||||
}
|
||||
if(*c != '?')
|
||||
return 0;
|
||||
if((last = parser_scan(parser)) != '?')
|
||||
{
|
||||
last_cnt = 1;
|
||||
return 1;
|
||||
}
|
||||
switch((last = parser_scan(parser)))
|
||||
{
|
||||
case '=':
|
||||
*c = '#';
|
||||
break;
|
||||
case '/':
|
||||
*c = '\\';
|
||||
break;
|
||||
case '\'':
|
||||
*c = '^';
|
||||
break;
|
||||
case '(':
|
||||
*c = '[';
|
||||
break;
|
||||
case ')':
|
||||
*c = ']';
|
||||
break;
|
||||
case '!':
|
||||
*c = '|';
|
||||
break;
|
||||
case '<':
|
||||
*c = '{';
|
||||
break;
|
||||
case '>':
|
||||
*c = '}';
|
||||
break;
|
||||
case '-':
|
||||
*c = '~';
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: last=%c\n", last);
|
||||
#endif
|
||||
last_cnt = 2;
|
||||
return 2;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: filtered \"??%c\" into \"%c\"\n", last, *c);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* cpp_callback_whitespace */
|
||||
static int _cpp_callback_whitespace(Parser * parser, Token * token, int c,
|
||||
void * data)
|
||||
{
|
||||
char * str = " ";
|
||||
|
||||
if(!isspace(c))
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: cpp_callback_whitespace()\n");
|
||||
#endif
|
||||
do
|
||||
{
|
||||
if(c == '\n')
|
||||
str = "\n";
|
||||
}
|
||||
while(isspace((c = parser_scan_filter(parser))));
|
||||
token_set_code(token, CPP_CODE_WHITESPACE);
|
||||
token_set_string(token, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* cpp_callback_comment */
|
||||
static int _cpp_callback_comment(Parser * parser, Token * token, int c,
|
||||
void * data)
|
||||
/* FIXME implement properly (and fallback on division) */
|
||||
{
|
||||
if(c != '/')
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: cpp_callback_comment()\n");
|
||||
#endif
|
||||
if((c = parser_scan_filter(parser)) != '*')
|
||||
{
|
||||
token_set_code(token, CPP_CODE_OPERATOR_DIVIDE);
|
||||
token_set_string(token, "/");
|
||||
return 0;
|
||||
}
|
||||
for(c = parser_scan_filter(parser); c != EOF;)
|
||||
{
|
||||
if(c == '*')
|
||||
{
|
||||
if((c = parser_scan_filter(parser)) == '/')
|
||||
break;
|
||||
}
|
||||
else
|
||||
c = parser_scan_filter(parser);
|
||||
}
|
||||
if(c == EOF)
|
||||
return -1;
|
||||
token_set_code(token, CPP_CODE_WHITESPACE);
|
||||
token_set_string(token, "");
|
||||
parser_scan_filter(parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* cpp_callback_operator */
|
||||
static int _cpp_callback_operator(Parser * parser, Token * token, int c,
|
||||
void * data)
|
||||
{
|
||||
CppParser * cp = data;
|
||||
size_t i;
|
||||
const size_t j = sizeof(_cpp_operators) / sizeof(*_cpp_operators);
|
||||
size_t pos;
|
||||
|
||||
for(i = 0; i < cp->operators_cnt; i++)
|
||||
if(cp->operators[i].string[0] == c)
|
||||
break;
|
||||
if(i == cp->operators_cnt) /* nothing found */
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: cpp_callback_operator('%c')\n", c);
|
||||
#endif
|
||||
for(pos = 0; i < j;)
|
||||
{
|
||||
if(cp->operators[i].string[pos] == '\0')
|
||||
break;
|
||||
if(c == cp->operators[i].string[pos])
|
||||
{
|
||||
c = parser_scan_filter(parser);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
if(i == j) /* should not happen */
|
||||
return -1;
|
||||
token_set_code(token, cp->operators[i].code);
|
||||
token_set_string(token, cp->operators[i].string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* cpp_callback_quote */
|
||||
static int _quote_escape(int c);
|
||||
|
||||
static int _cpp_callback_quote(Parser * parser, Token * token, int c,
|
||||
void * data)
|
||||
/* FIXME bug with "" => " */
|
||||
{
|
||||
const int d = c;
|
||||
char * str = NULL;
|
||||
size_t len = 1;
|
||||
char * p;
|
||||
|
||||
if(c == '\'')
|
||||
token_set_code(token, CPP_CODE_SQUOTE);
|
||||
else if(c == '"')
|
||||
token_set_code(token, CPP_CODE_DQUOTE);
|
||||
else
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: cpp_callback_quote('%c')\n", c);
|
||||
#endif
|
||||
while((c = parser_scan_filter(parser)) != EOF && c != d)
|
||||
{
|
||||
if((p = realloc(str, len + 3)) == NULL)
|
||||
break;
|
||||
str = p;
|
||||
if(c == '\\')
|
||||
{
|
||||
if((c = parser_scan_filter(parser)) == EOF)
|
||||
break;
|
||||
else
|
||||
c = _quote_escape(c);
|
||||
}
|
||||
str[len++] = c;
|
||||
}
|
||||
if(str == NULL || c != d) /* an error occured */
|
||||
{
|
||||
free(str);
|
||||
return -1;
|
||||
}
|
||||
str[0] = d;
|
||||
str[len++] = d;
|
||||
str[len] = '\0';
|
||||
token_set_string(token, str);
|
||||
free(str);
|
||||
parser_scan_filter(parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _quote_escape(int c)
|
||||
/* FIXME - handle octal and hexadecimal input
|
||||
* - seems to break further interpretation (eg '\0') */
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '0':
|
||||
return '\0';
|
||||
case 'a':
|
||||
return '\a';
|
||||
case 'b':
|
||||
return '\b';
|
||||
case 'e':
|
||||
return '\e';
|
||||
case 'f':
|
||||
return '\f';
|
||||
case 'n':
|
||||
return '\n';
|
||||
case 'r':
|
||||
return '\r';
|
||||
case 't':
|
||||
return '\t';
|
||||
case 'v':
|
||||
return '\v';
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cpp_callback_word */
|
||||
static int _isword(int c);
|
||||
|
||||
static int _cpp_callback_word(Parser * parser, Token * token, int c,
|
||||
void * data)
|
||||
{
|
||||
char * str = NULL;
|
||||
size_t len = 0;
|
||||
char * p;
|
||||
|
||||
if(!_isword(c))
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: cpp_callback_word('%c')\n", c);
|
||||
#endif
|
||||
do
|
||||
{
|
||||
if((p = realloc(str, len + 2)) == NULL)
|
||||
{
|
||||
error_set_code(1, "%s", strerror(errno));
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
str = p;
|
||||
str[len++] = c;
|
||||
}
|
||||
while(_isword((c = parser_scan_filter(parser))));
|
||||
str[len] = '\0';
|
||||
token_set_code(token, CPP_CODE_WORD);
|
||||
token_set_string(token, str);
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _isword(int c)
|
||||
{
|
||||
return isalnum(c) || c == '_';
|
||||
}
|
||||
|
||||
|
||||
/* cpp_callback_unknown */
|
||||
static int _cpp_callback_unknown(Parser * parser, Token * token, int c,
|
||||
void * data)
|
||||
{
|
||||
static char buf[2] = { '\0', '\0' };
|
||||
|
||||
if(c == EOF)
|
||||
return 1;
|
||||
buf[0] = c;
|
||||
parser_scan(parser);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: cpp_callback_unknown('%c' 0x%x)\n", c, c);
|
||||
#endif
|
||||
token_set_code(token, CPP_CODE_UNKNOWN);
|
||||
token_set_string(token, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* public */
|
||||
/* functions */
|
||||
/* cpp_new */
|
||||
Cpp * cpp_new(void)
|
||||
{
|
||||
Cpp * cpp;
|
||||
|
||||
if((cpp = malloc(sizeof(*cpp))) == NULL)
|
||||
if((cpp = object_new(sizeof(*cpp))) == NULL)
|
||||
return NULL;
|
||||
memset(cpp, sizeof(*cpp), 0);
|
||||
cpp->parsers = NULL;
|
||||
cpp->parsers_cnt = 0;
|
||||
cpp->filters = 0;
|
||||
return cpp;
|
||||
}
|
||||
|
||||
|
@ -54,40 +519,59 @@ void cpp_delete(Cpp * cpp)
|
|||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < cpp->parser_cnt; i++)
|
||||
parser_delete(cpp->parser[i]);
|
||||
free(cpp->parser);
|
||||
free(cpp);
|
||||
for(i = 0; i < cpp->parsers_cnt; i++)
|
||||
parser_delete(cpp->parsers[i]->parser);
|
||||
object_delete(cpp);
|
||||
}
|
||||
|
||||
|
||||
/* accessors */
|
||||
/* cpp_get_error */
|
||||
char const * cpp_get_error(Cpp * cpp)
|
||||
/* cpp_get_filename */
|
||||
char const * cpp_get_filename(Cpp * cpp)
|
||||
{
|
||||
return cpp->error;
|
||||
if(cpp->parsers_cnt > 0)
|
||||
return parser_get_filename(
|
||||
cpp->parsers[cpp->parsers_cnt - 1]->parser);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* cpp_filter_disable */
|
||||
void cpp_filter_disable(Cpp * cpp, CppFilter filter)
|
||||
{
|
||||
cpp->filters -= (cpp->filters & filter);
|
||||
}
|
||||
|
||||
|
||||
/* cpp_filter_enable */
|
||||
void cpp_filter_enable(Cpp * cpp, CppFilter filter)
|
||||
{
|
||||
cpp->filters |= filter;
|
||||
}
|
||||
|
||||
|
||||
/* cpp_parse */
|
||||
int cpp_parse(Cpp * cpp, char const * pathname)
|
||||
{
|
||||
Parser ** p;
|
||||
|
||||
if((p = realloc(cpp->parser, (cpp->parser_cnt + 1)
|
||||
* sizeof(*p))) == NULL)
|
||||
return 1; /* FIXME get error */
|
||||
cpp->parser = p;
|
||||
if((cpp->parser[cpp->parser_cnt] = parser_new(pathname)) == NULL)
|
||||
return 1; /* FIXME get error */
|
||||
cpp->parser_cnt++;
|
||||
if(cpp->parsers_cnt != 0)
|
||||
return error_set_code(1, "%s", "Already parsing");
|
||||
if((cpp->parsers = malloc(sizeof(*cpp->parsers))) == NULL)
|
||||
return error_set_code(1, "%s", strerror(errno));
|
||||
if((cpp->parsers[0] = _cppparser_new(pathname, cpp->filters,
|
||||
_cpp_operators, _cpp_operators_cnt))
|
||||
== NULL)
|
||||
return 1;
|
||||
cpp->parsers_cnt = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* cpp_read */
|
||||
ssize_t cpp_read(Cpp * cpp, char * buf, size_t cnt)
|
||||
/* cpp_scan */
|
||||
int cpp_scan(Cpp * cpp, Token ** token)
|
||||
{
|
||||
/* FIXME implement */
|
||||
return -1;
|
||||
if(cpp->parsers_cnt == 0)
|
||||
return error_set_code(1, "%s", "No file to parse");
|
||||
return parser_get_token(cpp->parsers[cpp->parsers_cnt - 1]->parser,
|
||||
token);
|
||||
}
|
||||
|
|
102
src/main.c
102
src/main.c
|
@ -1,5 +1,5 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2007 Pierre Pronchery <khorben@defora.org> */
|
||||
/* Copyright (c) 2008 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Devel cpp */
|
||||
/* cpp is not free software; you can redistribute it and/or modify it under the
|
||||
* terms of the Creative Commons Attribution-NonCommercial-ShareAlike 3.0
|
||||
|
@ -18,45 +18,99 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "cpp.h"
|
||||
#include "../config.h"
|
||||
|
||||
|
||||
/* cpp */
|
||||
static int _cpp_liberror(char const * message, int ret);
|
||||
/* private */
|
||||
/* types */
|
||||
typedef struct _Prefs
|
||||
{
|
||||
char * output;
|
||||
int flags;
|
||||
} Prefs;
|
||||
#define PREFS_t 0x1
|
||||
|
||||
static int _cpp(char const * filename)
|
||||
|
||||
/* prototypes */
|
||||
static int _cpp(Prefs * prefs, int filec, char * filev[]);
|
||||
static int _cpp_error(void);
|
||||
|
||||
|
||||
/* functions */
|
||||
/* cpp */
|
||||
static int _cpp_do(Prefs * prefs, FILE * fp, char const * filename);
|
||||
|
||||
static int _cpp(Prefs * prefs, int filec, char * filev[])
|
||||
{
|
||||
int ret = 0;
|
||||
FILE * fp;
|
||||
int i;
|
||||
|
||||
if(prefs->output == NULL)
|
||||
fp = stdout;
|
||||
else if((fp = fopen(prefs->output, "w")) == NULL)
|
||||
return error_set_print("cpp", 1, "%s: %s", prefs->output,
|
||||
strerror(errno));
|
||||
for(i = 0; i < filec; i++)
|
||||
ret |= _cpp_do(prefs, fp, filev[i]);
|
||||
if(fclose(fp) != 0)
|
||||
return error_set_print("cpp", 1, "%s: %s", prefs->output,
|
||||
strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _cpp_do(Prefs * prefs, FILE * fp, char const * filename)
|
||||
{
|
||||
int ret;
|
||||
Cpp * cpp;
|
||||
ssize_t len;
|
||||
char buf[BUFSIZ];
|
||||
Token * token;
|
||||
|
||||
if((cpp = cpp_new()) == NULL)
|
||||
return _cpp_liberror("Internal error", 1);
|
||||
if(cpp_parse(cpp, filename) != 0)
|
||||
ret = _cpp_liberror(cpp_get_error(cpp), 1);
|
||||
else
|
||||
return _cpp_error();
|
||||
if(prefs->flags & PREFS_t)
|
||||
cpp_filter_enable(cpp, CPP_FILTER_TRIGRAPH);
|
||||
if((ret = cpp_parse(cpp, filename)) != 0)
|
||||
{
|
||||
while((len = cpp_read(cpp, buf, sizeof(buf))) > 0)
|
||||
fwrite(buf, sizeof(char), len, stdout);
|
||||
if(len < 0)
|
||||
ret = _cpp_liberror(cpp_get_error(cpp), 1);
|
||||
cpp_delete(cpp);
|
||||
return _cpp_error();
|
||||
}
|
||||
while((ret = cpp_scan(cpp, &token)) == 0)
|
||||
{
|
||||
if(token == NULL) /* end of file */
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s (%d)\n", token_get_string(token),
|
||||
token_get_code(token));
|
||||
#else
|
||||
fputs(token_get_string(token), fp);
|
||||
#endif
|
||||
token_delete(token);
|
||||
}
|
||||
if(ret != 0)
|
||||
_cpp_error();
|
||||
cpp_delete(cpp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _cpp_liberror(char const * message, int ret)
|
||||
|
||||
/* cpp_error */
|
||||
static int _cpp_error(void)
|
||||
{
|
||||
fprintf(stderr, "%s%s", "cpp: ", message);
|
||||
return ret;
|
||||
return error_print(PACKAGE);
|
||||
}
|
||||
|
||||
|
||||
/* usage */
|
||||
/* FIXME -E prints metadata? */
|
||||
static int _usage(void)
|
||||
{
|
||||
fputs("Usage: cpp filename\n", stderr);
|
||||
fputs("Usage: " PACKAGE " [-o output][-t] input...\n"
|
||||
" -o Write output to a file\n"
|
||||
" -t Convert trigraphs\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -64,15 +118,23 @@ static int _usage(void)
|
|||
/* main */
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
Prefs prefs;
|
||||
int o;
|
||||
|
||||
while((o = getopt(argc, argv, "")) != -1)
|
||||
memset(&prefs, 0, sizeof(prefs));
|
||||
while((o = getopt(argc, argv, "o:t")) != -1)
|
||||
switch(o)
|
||||
{
|
||||
case 'o':
|
||||
prefs.output = optarg;
|
||||
break;
|
||||
case 't':
|
||||
prefs.flags |= PREFS_t;
|
||||
break;
|
||||
default:
|
||||
return _usage();
|
||||
}
|
||||
if(argc - optind != 1)
|
||||
if(argc - optind < 1)
|
||||
return _usage();
|
||||
return _cpp(argv[optind]) == 0 ? 0 : 2;
|
||||
return _cpp(&prefs, argc - optind, &argv[optind]) == 0 ? 0 : 2;
|
||||
}
|
||||
|
|
71
src/parser.c
71
src/parser.c
|
@ -1,71 +0,0 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2007 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Devel cpp */
|
||||
/* cpp 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.
|
||||
*
|
||||
* cpp 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 cpp; if not, browse to
|
||||
* http://creativecommons.org/licenses/by-nc-sa/3.0/ */
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
/* Parser */
|
||||
/* private */
|
||||
/* types */
|
||||
struct _Parser
|
||||
{
|
||||
char * pathname;
|
||||
FILE * fp;
|
||||
unsigned long line;
|
||||
unsigned long col;
|
||||
};
|
||||
|
||||
|
||||
/* public */
|
||||
/* parser_new */
|
||||
Parser * parser_new(char const * pathname)
|
||||
{
|
||||
Parser * parser;
|
||||
|
||||
if((parser = malloc(sizeof(*parser))) == NULL)
|
||||
return NULL;
|
||||
parser->pathname = strdup(pathname);
|
||||
parser->fp = fopen(pathname, "r");
|
||||
if(parser->pathname == NULL || parser->fp == NULL)
|
||||
{
|
||||
parser_delete(parser);
|
||||
return NULL;
|
||||
}
|
||||
parser->line = 0;
|
||||
parser->col = 0;
|
||||
return parser;
|
||||
}
|
||||
|
||||
|
||||
/* parser_delete */
|
||||
void parser_delete(Parser * parser)
|
||||
{
|
||||
fclose(parser->fp);
|
||||
free(parser->pathname);
|
||||
free(parser);
|
||||
}
|
||||
|
||||
|
||||
/* accessors */
|
||||
char const * parser_get_filename(Parser * parser)
|
||||
{
|
||||
return parser->pathname;
|
||||
}
|
35
src/parser.h
35
src/parser.h
|
@ -1,35 +0,0 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2007 Pierre Pronchery <khorben@defora.org> */
|
||||
/* This file is part of DeforaOS Devel cpp */
|
||||
/* cpp 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.
|
||||
*
|
||||
* cpp 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 cpp; if not, browse to
|
||||
* http://creativecommons.org/licenses/by-nc-sa/3.0/ */
|
||||
|
||||
|
||||
|
||||
#ifndef CPP_PARSER_H
|
||||
# define CPP_PARSER_H
|
||||
|
||||
|
||||
/* cpp */
|
||||
/* types */
|
||||
typedef struct _Parser Parser;
|
||||
|
||||
|
||||
/* functions */
|
||||
Parser * parser_new(char const * pathname);
|
||||
void parser_delete(Parser * parser);
|
||||
|
||||
/* accessors */
|
||||
char const * parser_get_filename(Parser * parser);
|
||||
|
||||
#endif /* !CPP_PARSER_H */
|
|
@ -1,22 +1,21 @@
|
|||
targets=libcpp,cpp
|
||||
cppflags=-I ../include
|
||||
cflags_force=-W -Wall
|
||||
cflags=-g
|
||||
dist=Makefile
|
||||
|
||||
[libcpp]
|
||||
type=library
|
||||
sources=parser.c,cpp.c
|
||||
sources=cpp.c
|
||||
cflags=-fPIC
|
||||
|
||||
[cpp.c]
|
||||
depends=parser.h,cpp.h
|
||||
|
||||
[parser.c]
|
||||
depends=parser.h
|
||||
depends=../include/cpp.h
|
||||
|
||||
[cpp]
|
||||
type=binary
|
||||
sources=main.c
|
||||
ldflags=-l cpp -L .
|
||||
ldflags=-Wl,-rpath,$(LIBDIR) -L $(LIBDIR) -L . -l cpp -l System -l ssl
|
||||
|
||||
[main.c]
|
||||
depends=cpp.h
|
||||
depends=../include/cpp.h
|
||||
|
|
Loading…
Reference in New Issue
Block a user