lemon refactor iterate

This commit is contained in:
John Kerl 2016-07-13 21:10:22 -04:00
parent aebe62311c
commit 31308ece2a
3 changed files with 7 additions and 292 deletions

View file

@ -2,7 +2,9 @@ AM_CPPFLAGS= -I${srcdir}
AM_CFLAGS= -std=gnu99
noinst_PROGRAMS= lemon
lemon_SOURCES= lemon.c
lemon_SOURCES= lemon.c \
lemon_option.c \
lemon_option.h
noinst_LTLIBRARIES= libdsl.la
# if we don't want to distribute the generated sources, move them to a nodist_libfoo_la_SOURCES variable

View file

@ -105,8 +105,8 @@ ex2_lexer.c ex2_lexer.h: ex2_lexer.l ./ex_ast.h
flex --prefix=ex2_lexer_ --outfile=ex2_lexer.c --header-file=ex2_lexer.h ex2_lexer.l
# ----------------------------------------------------------------
lemon: lemon.c lempar.c
$(DSLCC) -o lemon lemon.c
lemon: lemon.c lemon_option.c
$(DSLCC) -o lemon lemon.c lemon_option.c
# ----------------------------------------------------------------
clean:

View file

@ -13,6 +13,8 @@
#include <stdlib.h>
#include <unistd.h>
#include "lemon_option.h"
#ifndef __WIN32__
# if defined(_WIN32) || defined(WIN32)
# define __WIN32__
@ -66,20 +68,6 @@ void Configlist_reset(/* void */);
/********* From the file "error.h" ***************************************/
void ErrorMsg(const char *, int,const char *, ...);
/****** From the file "option.h" ******************************************/
struct s_options {
enum { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
char *label;
char *arg;
char *message;
};
int OptInit(/* char**,struct s_options*,FILE* */);
int OptNArgs(/* void */);
char *OptArg(/* int */);
void OptErr(/* int */);
void OptPrint(/* void */);
/******** From the file "parse.h" *****************************************/
int Parse(/* struct lemon *lemp */);
@ -1576,281 +1564,6 @@ char *msort(char *list, char **next, int (*cmp)())
return ep;
}
/************************ From the file "option.c" **************************/
static char **argv;
static struct s_options *op;
static FILE *errstream;
#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
/*
** Print the command line with a carrot pointing to the k-th character
** of the n-th field.
*/
static void errline(int n, int k, FILE *err)
{
int spcnt, i;
spcnt = 0;
if (argv[0]) fprintf(err,"%s",argv[0]);
spcnt = strlen(argv[0]) + 1;
for(i=1; i<n && argv[i]; i++){
fprintf(err," %s",argv[i]);
spcnt += strlen(argv[i]+1);
}
spcnt += k;
for(; argv[i]; i++) fprintf(err," %s",argv[i]);
if (spcnt<20) {
fprintf(err,"\n%*s^-- here\n",spcnt,"");
} else {
fprintf(err,"\n%*shere --^\n",spcnt-7,"");
}
}
/*
** Return the index of the N-th non-switch argument. Return -1
** if N is out of range.
*/
static int argindex(int n)
{
int i;
int dashdash = 0;
if (argv!=0 && *argv!=0) {
for(i=1; argv[i]; i++){
if (dashdash || !ISOPT(argv[i])) {
if (n==0) return i;
n--;
}
if (strcmp(argv[i],"--")==0) dashdash = 1;
}
}
return -1;
}
static char emsg[] = "Command line syntax error: ";
/*
** Process a flag command line argument.
*/
static int handleflags(int i, FILE *err)
{
int v;
int errcnt = 0;
int j;
for(j=0; op[j].label; j++){
if (strncmp(&argv[i][1],op[j].label,strlen(op[j].label))==0) break;
}
v = argv[i][0]=='-' ? 1 : 0;
if (op[j].label==0) {
if (err) {
fprintf(err,"%sundefined option.\n",emsg);
errline(i,1,err);
}
errcnt++;
} else if (op[j].type==OPT_FLAG) {
*((int*)op[j].arg) = v;
} else if (op[j].type==OPT_FFLAG) {
(*(void(*)())(op[j].arg))(v);
} else if (op[j].type==OPT_FSTR) {
(*(void(*)())(op[j].arg))(&argv[i][2]);
} else {
if (err) {
fprintf(err,"%smissing argument on switch.\n",emsg);
errline(i,1,err);
}
errcnt++;
}
return errcnt;
}
/*
** Process a command line switch which has an argument.
*/
static int handleswitch(int i, FILE *err)
{
int lv = 0;
double dv = 0.0;
char *sv = 0, *end;
char *cp;
int j;
int errcnt = 0;
cp = strchr(argv[i],'=');
*cp = 0;
for(j=0; op[j].label; j++){
if (strcmp(argv[i],op[j].label)==0) break;
}
*cp = '=';
if (op[j].label==0) {
if (err) {
fprintf(err,"%sundefined option.\n",emsg);
errline(i,0,err);
}
errcnt++;
} else {
cp++;
switch (op[j].type) {
case OPT_FLAG:
case OPT_FFLAG:
if (err) {
fprintf(err,"%soption requires an argument.\n",emsg);
errline(i,0,err);
}
errcnt++;
break;
case OPT_DBL:
case OPT_FDBL:
dv = strtod(cp,&end);
if (*end) {
if (err) {
fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
}
errcnt++;
}
break;
case OPT_INT:
case OPT_FINT:
lv = strtol(cp,&end,0);
if (*end) {
if (err) {
fprintf(err,"%sillegal character in integer argument.\n",emsg);
errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
}
errcnt++;
}
break;
case OPT_STR:
case OPT_FSTR:
sv = cp;
break;
}
switch (op[j].type) {
case OPT_FLAG:
case OPT_FFLAG:
break;
case OPT_DBL:
*(double*)(op[j].arg) = dv;
break;
case OPT_FDBL:
(*(void(*)())(op[j].arg))(dv);
break;
case OPT_INT:
*(int*)(op[j].arg) = lv;
break;
case OPT_FINT:
(*(void(*)())(op[j].arg))((int)lv);
break;
case OPT_STR:
*(char**)(op[j].arg) = sv;
break;
case OPT_FSTR:
(*(void(*)())(op[j].arg))(sv);
break;
}
}
return errcnt;
}
int OptInit(char **a, struct s_options *o, FILE *err)
{
int errcnt = 0;
argv = a;
op = o;
errstream = err;
if (argv && *argv && op) {
int i;
for(i=1; argv[i]; i++){
if (argv[i][0]=='+' || argv[i][0]=='-') {
errcnt += handleflags(i,err);
} else if (strchr(argv[i],'=')) {
errcnt += handleswitch(i,err);
}
}
}
if (errcnt>0) {
fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
OptPrint();
exit(1);
}
return 0;
}
int OptNArgs() {
int cnt = 0;
int dashdash = 0;
int i;
if (argv!=0 && argv[0]!=0) {
for(i=1; argv[i]; i++){
if (dashdash || !ISOPT(argv[i])) cnt++;
if (strcmp(argv[i],"--")==0) dashdash = 1;
}
}
return cnt;
}
char *OptArg(int n)
{
int i;
i = argindex(n);
return i>=0 ? argv[i] : 0;
}
void OptErr(int n)
{
int i;
i = argindex(n);
if (i>=0) errline(i,0,errstream);
}
void OptPrint(){
int i;
int max, len;
max = 0;
for(i=0; op[i].label; i++){
len = strlen(op[i].label) + 1;
switch (op[i].type) {
case OPT_FLAG:
case OPT_FFLAG:
break;
case OPT_INT:
case OPT_FINT:
len += 9; /* length of "<integer>" */
break;
case OPT_DBL:
case OPT_FDBL:
len += 6; /* length of "<real>" */
break;
case OPT_STR:
case OPT_FSTR:
len += 8; /* length of "<string>" */
break;
}
if (len>max) max = len;
}
for(i=0; op[i].label; i++){
switch (op[i].type) {
case OPT_FLAG:
case OPT_FFLAG:
fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
break;
case OPT_INT:
case OPT_FINT:
fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
(int)(max-strlen(op[i].label)-9),"",op[i].message);
break;
case OPT_DBL:
case OPT_FDBL:
fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
(int)(max-strlen(op[i].label)-6),"",op[i].message);
break;
case OPT_STR:
case OPT_FSTR:
fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
(int)(max-strlen(op[i].label)-8),"",op[i].message);
break;
}
}
}
/*********************** From the file "parse.c" ****************************/
/*
** Input file parser for the LEMON parser generator.