From ab677a0670a45762a9da66ddf8dfee0eeb8a5fa9 Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Thu, 10 Feb 2011 23:50:05 +0000 Subject: [PATCH] Fixed NO_FP support git-svn-id: http://picoc.googlecode.com/svn/trunk@504 21eae674-98b7-11dd-bd71-f92a316d2d60 --- cstdlib/math.c | 2 + cstdlib/stdio.c | 4 + cstdlib/stdlib.c | 8 +- cstdlib/time.c | 4 + expression.c | 4 + include.c | 2 + tests/46_grep.c | 562 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 585 insertions(+), 1 deletion(-) create mode 100644 tests/46_grep.c diff --git a/cstdlib/math.c b/cstdlib/math.c index f7d9c1e..83d5bdb 100644 --- a/cstdlib/math.c +++ b/cstdlib/math.c @@ -2,6 +2,7 @@ #include "../picoc.h" #ifndef BUILTIN_MINI_STDLIB +#ifndef NO_FP static double M_EValue = 2.7182818284590452354; /* e */ static double M_LOG2EValue = 1.4426950408889634074; /* log_2 e */ @@ -182,4 +183,5 @@ void MathSetupFunc(void) VariableDefinePlatformVar(NULL, "M_SQRT1_2", &FPType, (union AnyValue *)&M_SQRT1_2Value, FALSE); } +#endif /* !NO_FP */ #endif /* !BUILTIN_MINI_STDLIB */ diff --git a/cstdlib/stdio.c b/cstdlib/stdio.c index 6b42ca9..bd42661 100644 --- a/cstdlib/stdio.c +++ b/cstdlib/stdio.c @@ -201,9 +201,11 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int S { case 'd': case 'i': ShowType = &IntType; break; /* integer decimal */ case 'o': case 'u': case 'x': case 'X': ShowType = &IntType; break; /* integer base conversions */ +#ifndef NO_FP case 'e': case 'E': ShowType = &FPType; break; /* double, exponent form */ case 'f': case 'F': ShowType = &FPType; break; /* double, fixed-point */ case 'g': case 'G': ShowType = &FPType; break; /* double, flexible format */ +#endif case 'a': case 'A': ShowType = &IntType; break; /* hexadecimal, 0x- format */ case 'c': ShowType = &IntType; break; /* character */ case 's': ShowType = CharPtrType; break; /* string */ @@ -257,6 +259,7 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int S else StdioOutPuts("XXX", &SOStream); } +#ifndef NO_FP else if (ShowType == &FPType) { /* show a floating point number */ @@ -265,6 +268,7 @@ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int S else StdioOutPuts("XXX", &SOStream); } +#endif else if (ShowType == CharPtrType) { if (ThisArg->Typ->Base == TypePointer) diff --git a/cstdlib/stdlib.c b/cstdlib/stdlib.c index ed1e9c9..c280769 100644 --- a/cstdlib/stdlib.c +++ b/cstdlib/stdlib.c @@ -5,10 +5,12 @@ static int ZeroValue = 0; +#ifndef NO_FP void StdlibAtof(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { ReturnValue->Val->FP = atof(Param[0]->Val->Pointer); } +#endif void StdlibAtoi(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { @@ -20,10 +22,12 @@ void StdlibAtol(struct ParseState *Parser, struct Value *ReturnValue, struct Val ReturnValue->Val->Integer = atol(Param[0]->Val->Pointer); } +#ifndef NO_FP void StdlibStrtod(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { ReturnValue->Val->FP = strtod(Param[0]->Val->Pointer, Param[1]->Val->Pointer); } +#endif void StdlibStrtol(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { @@ -130,10 +134,12 @@ typedef struct { \ /* all stdlib.h functions */ struct LibraryFunction StdlibFunctions[] = { +#ifndef NO_FP { StdlibAtof, "float atof(char *);" }, + { StdlibStrtod, "float strtod(char *,char **);" }, +#endif { StdlibAtoi, "int atoi(char *);" }, { StdlibAtol, "int atol(char *);" }, - { StdlibStrtod, "float strtod(char *,char **);" }, { StdlibStrtol, "int strtol(char *,char **,int);" }, { StdlibStrtoul, "int strtoul(char *,char **,int);" }, { StdlibMalloc, "void *malloc(int);" }, diff --git a/cstdlib/time.c b/cstdlib/time.c index 3b765f3..f66e39a 100644 --- a/cstdlib/time.c +++ b/cstdlib/time.c @@ -29,10 +29,12 @@ void StdCtime(struct ParseState *Parser, struct Value *ReturnValue, struct Value ReturnValue->Val->Pointer = ctime(Param[0]->Val->Pointer); } +#ifndef NO_FP void StdDifftime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { ReturnValue->Val->FP = difftime((time_t)Param[0]->Val->Integer, Param[1]->Val->Integer); } +#endif void StdGmtime(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { @@ -88,7 +90,9 @@ struct LibraryFunction StdTimeFunctions[] = { StdAsctime, "char *asctime(struct tm *);" }, { StdClock, "time_t clock();" }, { StdCtime, "char *ctime(int *);" }, +#ifndef NO_FP { StdDifftime, "double difftime(int, int);" }, +#endif { StdGmtime, "struct tm *gmtime(int *);" }, { StdGmtime_r, "struct tm *gmtime_r(int *, struct tm *);" }, { StdLocaltime, "struct tm *localtime(int *);" }, diff --git a/expression.c b/expression.c index 0a3b64a..fa9ed78 100644 --- a/expression.c +++ b/expression.c @@ -1231,7 +1231,11 @@ void ExpressionParseMacroCall(struct ParseState *Parser, struct ExpressionStack if (Parser->Mode == RunModeRun) { /* create a stack frame for this macro */ +#ifndef NO_FP ExpressionStackPushValueByType(Parser, StackTop, &FPType); /* largest return type there is */ +#else + ExpressionStackPushValueByType(Parser, StackTop, VoidPtrType); /* largest return type there is */ +#endif ReturnValue = (*StackTop)->Val; HeapPushStackFrame(); ParamArray = HeapAllocStack(sizeof(struct Value *) * MDef->NumParams); diff --git a/include.c b/include.c index 000850f..49c9dc4 100644 --- a/include.c +++ b/include.c @@ -21,7 +21,9 @@ void IncludeInit() #ifndef BUILTIN_MINI_STDLIB IncludeRegister("ctype.h", NULL, &StdCtypeFunctions[0], NULL); IncludeRegister("errno.h", &StdErrnoSetupFunc, NULL, NULL); +#ifndef NO_FP IncludeRegister("math.h", &MathSetupFunc, &MathFunctions[0], NULL); +#endif IncludeRegister("stdbool.h", &StdboolSetupFunc, NULL, StdboolDefs); IncludeRegister("stdio.h", &StdioSetupFunc, &StdioFunctions[0], StdioDefs); IncludeRegister("stdlib.h", &StdlibSetupFunc, &StdlibFunctions[0], NULL); diff --git a/tests/46_grep.c b/tests/46_grep.c new file mode 100644 index 0000000..b142f98 --- /dev/null +++ b/tests/46_grep.c @@ -0,0 +1,562 @@ +/* + * The information in this document is subject to change + * without notice and should not be construed as a commitment + * by Digital Equipment Corporation or by DECUS. + * + * Neither Digital Equipment Corporation, DECUS, nor the authors + * assume any responsibility for the use or reliability of this + * document or the described software. + * + * Copyright (C) 1980, DECUS + * + * General permission to copy or modify, but not for profit, is + * hereby granted, provided that the above copyright notice is + * included and reference made to the fact that reproduction + * privileges were granted by DECUS. + */ +#include + +/* + * grep + * + * Runs on the Decus compiler or on vms, On vms, define as: + * grep :== "$disk:[account]grep" (native) + * grep :== "$disk:[account]grep grep" (Decus) + * See below for more information. + */ + +#if 0 +char *documentation[] = { +"grep searches a file for a given pattern. Execute by", +" grep [flags] regular_expression file_list\n", +"Flags are single characters preceeded by '-':", +" -c Only a count of matching lines is printed", +" -f Print file name for matching lines switch, see below", +" -n Each line is preceeded by its line number", +" -v Only print non-matching lines\n", +"The file_list is a list of files (wildcards are acceptable on RSX modes).", +"\nThe file name is normally printed if there is a file given.", +"The -f flag reverses this action (print name no file, not if more).\n", +0 }; + +char *patdoc[] = { +"The regular_expression defines the pattern to search for. Upper- and", +"lower-case are always ignored. Blank lines never match. The expression", +"should be quoted to prevent file-name translation.", +"x An ordinary character (not mentioned below) matches that character.", +"'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.", +"'^' A circumflex at the beginning of an expression matches the", +" beginning of a line.", +"'$' A dollar-sign at the end of an expression matches the end of a line.", +"'.' A period matches any character except \"new-line\".", +"':a' A colon matches a class of characters described by the following", +"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,", +"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and", +"': ' other control characters, such as new-line.", +"'*' An expression followed by an asterisk matches zero or more", +" occurrances of that expression: \"fo*\" matches \"f\", \"fo\"", +" \"foo\", etc.", +"'+' An expression followed by a plus sign matches one or more", +" occurrances of that expression: \"fo+\" matches \"fo\", etc.", +"'-' An expression followed by a minus sign optionally matches", +" the expression.", +"'[]' A string enclosed in square brackets matches any character in", +" that string, but no others. If the first character in the", +" string is a circumflex, the expression matches any character", +" except \"new-line\" and the characters in the string. For", +" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"", +" matches \"abc\" but not \"axb\". A range of characters may be", +" specified by two characters separated by \"-\". Note that,", +" [a-z] matches alphabetics, while [z-a] never matches.", +"The concatenation of regular expressions is a regular expression.", +0}; +#endif + +#define LMAX 512 +#define PMAX 256 + +#define CHAR 1 +#define BOL 2 +#define EOL 3 +#define ANY 4 +#define CLASS 5 +#define NCLASS 6 +#define STAR 7 +#define PLUS 8 +#define MINUS 9 +#define ALPHA 10 +#define DIGIT 11 +#define NALPHA 12 +#define PUNCT 13 +#define RANGE 14 +#define ENDPAT 15 + +int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0; + +char *pp, lbuf[LMAX], pbuf[PMAX]; + +char *cclass(); +char *pmatch(); + + +/*** Display a file name *******************************/ +void file(char *s) +{ + printf("File %s:\n", s); +} + +/*** Report unopenable file ****************************/ +void cant(char *s) +{ + fprintf(stderr, "%s: cannot open\n", s); +} + +/*** Give good help ************************************/ +void help(char **hp) +{ + char **dp; + + for (dp = hp; *dp; ++dp) + printf("%s\n", *dp); +} + +/*** Display usage summary *****************************/ +void usage(char *s) +{ + fprintf(stderr, "?GREP-E-%s\n", s); + fprintf(stderr, + "Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n"); + exit(1); +} + +/*** Compile the pattern into global pbuf[] ************/ +void compile(char *source) +{ + char *s; /* Source string pointer */ + char *lp; /* Last pattern pointer */ + int c; /* Current character */ + int o; /* Temp */ + char *spp; /* Save beginning of pattern */ + + s = source; + if (debug) + printf("Pattern = \"%s\"\n", s); + pp = pbuf; + while (c = *s++) { + /* + * STAR, PLUS and MINUS are special. + */ + if (c == '*' || c == '+' || c == '-') { + if (pp == pbuf || + (o=pp[-1]) == BOL || + o == EOL || + o == STAR || + o == PLUS || + o == MINUS) + badpat("Illegal occurrance op.", source, s); + store(ENDPAT); + store(ENDPAT); + spp = pp; /* Save pattern end */ + while (--pp > lp) /* Move pattern down */ + *pp = pp[-1]; /* one byte */ + *pp = (c == '*') ? STAR : + (c == '-') ? MINUS : PLUS; + pp = spp; /* Restore pattern end */ + continue; + } + /* + * All the rest. + */ + lp = pp; /* Remember start */ + switch(c) { + + case '^': + store(BOL); + break; + + case '$': + store(EOL); + break; + + case '.': + store(ANY); + break; + + case '[': + s = cclass(source, s); + break; + + case ':': + if (*s) { + switch(tolower(c = *s++)) { + + case 'a': + case 'A': + store(ALPHA); + break; + + case 'd': + case 'D': + store(DIGIT); + break; + + case 'n': + case 'N': + store(NALPHA); + break; + + case ' ': + store(PUNCT); + break; + + default: + badpat("Unknown : type", source, s); + + } + break; + } + else badpat("No : type", source, s); + + case '\\': + if (*s) + c = *s++; + + default: + store(CHAR); + store(tolower(c)); + } + } + store(ENDPAT); + store(0); /* Terminate string */ + if (debug) { + for (lp = pbuf; lp < pp;) { + if ((c = (*lp++ & 0377)) < ' ') + printf("\\%o ", c); + else printf("%c ", c); + } + printf("\n"); + } +} + +/*** Compile a class (within []) ***********************/ +char *cclass(char *source, char *src) +/* char *source; // Pattern start -- for error msg. */ +/* char *src; // Class start */ +{ + char *s; /* Source pointer */ + char *cp; /* Pattern start */ + int c; /* Current character */ + int o; /* Temp */ + + s = src; + o = CLASS; + if (*s == '^') { + ++s; + o = NCLASS; + } + store(o); + cp = pp; + store(0); /* Byte count */ + while ((c = *s++) && c!=']') { + if (c == '\\') { /* Store quoted char */ + if ((c = *s++) == '\0') /* Gotta get something */ + badpat("Class terminates badly", source, s); + else store(tolower(c)); + } + else if (c == '-' && + (pp - cp) > 1 && *s != ']' && *s != '\0') { + c = pp[-1]; /* Range start */ + pp[-1] = RANGE; /* Range signal */ + store(c); /* Re-store start */ + c = *s++; /* Get end char and*/ + store(tolower(c)); /* Store it */ + } + else { + store(tolower(c)); /* Store normal char */ + } + } + if (c != ']') + badpat("Unterminated class", source, s); + if ((c = (pp - cp)) >= 256) + badpat("Class too large", source, s); + if (c == 0) + badpat("Empty class", source, s); + *cp = c; + return(s); +} + +/*** Store an entry in the pattern buffer **************/ +void store(int op) +{ + if (pp >= &pbuf[PMAX]) + error("Pattern too complex\n"); + *pp++ = op; +} + +/*** Report a bad pattern specification ****************/ +void badpat(char *message, char *source, char *stop) +/* char *message; // Error message */ +/* char *source; // Pattern start */ +/* char *stop; // Pattern end */ +{ + fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source); + fprintf(stderr, "-GREP-E-Stopped at byte %d, '%c'\n", + stop-source, stop[-1]); + error("?GREP-E-Bad pattern\n"); +} + +/*** Scan the file for the pattern in pbuf[] ***********/ +void grep(FILE *fp, char *fn) +/* FILE *fp; // File to process */ +/* char *fn; // File name (for -f option) */ +{ + int lno, count, m; + + lno = 0; + count = 0; + while (fgets(lbuf, LMAX, fp)) { + ++lno; + m = match(); + if ((m && !vflag) || (!m && vflag)) { + ++count; + if (!cflag) { + if (fflag && fn) { + file(fn); + fn = 0; + } + if (nflag) + printf("%d\t", lno); + printf("%s\n", lbuf); + } + } + } + if (cflag) { + if (fflag && fn) + file(fn); + printf("%d\n", count); + } +} + +/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/ +void match() +{ + char *l; /* Line pointer */ + + for (l = lbuf; *l; ++l) { + if (pmatch(l, pbuf)) + return(1); + } + return(0); +} + +/*** Match partial line with pattern *******************/ +char *pmatch(char *line, char *pattern) +/* char *line; // (partial) line to match */ +/* char *pattern; // (partial) pattern to match */ +{ + char *l; /* Current line pointer */ + char *p; /* Current pattern pointer */ + char c; /* Current character */ + char *e; /* End for STAR and PLUS match */ + int op; /* Pattern operation */ + int n; /* Class counter */ + char *are; /* Start of STAR match */ + + l = line; + if (debug > 1) + printf("pmatch(\"%s\")\n", line); + p = pattern; + while ((op = *p++) != ENDPAT) { + if (debug > 1) + printf("byte[%d] = 0%o, '%c', op = 0%o\n", + l-line, *l, *l, op); + switch(op) { + + case CHAR: + if (tolower(*l++) != *p++) + return(0); + break; + + case BOL: + if (l != lbuf) + return(0); + break; + + case EOL: + if (*l != '\0') + return(0); + break; + + case ANY: + if (*l++ == '\0') + return(0); + break; + + case DIGIT: + if ((c = *l++) < '0' || (c > '9')) + return(0); + break; + + case ALPHA: + c = tolower(*l++); + if (c < 'a' || c > 'z') + return(0); + break; + + case NALPHA: + c = tolower(*l++); + if (c >= 'a' && c <= 'z') + break; + else if (c < '0' || c > '9') + return(0); + break; + + case PUNCT: + c = *l++; + if (c == 0 || c > ' ') + return(0); + break; + + case CLASS: + case NCLASS: + c = tolower(*l++); + n = *p++ & 0377; + do { + if (*p == RANGE) { + p += 3; + n -= 2; + if (c >= p[-2] && c <= p[-1]) + break; + } + else if (c == *p++) + break; + } while (--n > 1); + if ((op == CLASS) == (n <= 1)) + return(0); + if (op == CLASS) + p += n - 2; + break; + + case MINUS: + e = pmatch(l, p); /* Look for a match */ + while (*p++ != ENDPAT); /* Skip over pattern */ + if (e) /* Got a match? */ + l = e; /* Yes, update string */ + break; /* Always succeeds */ + + case PLUS: /* One or more ... */ + if ((l = pmatch(l, p)) == 0) + return(0); /* Gotta have a match */ + case STAR: /* Zero or more ... */ + are = l; /* Remember line start */ + while (*l && (e = pmatch(l, p))) + l = e; /* Get longest match */ + while (*p++ != ENDPAT); /* Skip over pattern */ + while (l >= are) { /* Try to match rest */ + if (e = pmatch(l, p)) + return(e); + --l; /* Nope, try earlier */ + } + return(0); /* Nothing else worked */ + + default: + printf("Bad op code %d\n", op); + error("Cannot happen -- match\n"); + } + } + return(l); +} + +/*** Report an error ***********************************/ +void error(char *s) +{ + fprintf(stderr, "%s", s); + exit(1); +} + +/*** Main program - parse arguments & grep *************/ +int main(int argc, char **argv) +{ + char *p; + int c, i; + int gotpattern; + + FILE *f; + + if (argc <= 1) + usage("No arguments"); + if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) { + help(documentation); + help(patdoc); + return; + } + nfile = argc-1; + gotpattern = 0; + for (i=1; i < argc; ++i) { + p = argv[i]; + if (*p == '-') { + ++p; + while (c = *p++) { + switch(tolower(c)) { + + case '?': + help(documentation); + break; + + case 'C': + case 'c': + ++cflag; + break; + + case 'D': + case 'd': + ++debug; + break; + + case 'F': + case 'f': + ++fflag; + break; + + case 'n': + case 'N': + ++nflag; + break; + + case 'v': + case 'V': + ++vflag; + break; + + default: + usage("Unknown flag"); + } + } + argv[i] = 0; + --nfile; + } else if (!gotpattern) { + compile(p); + argv[i] = 0; + ++gotpattern; + --nfile; + } + } + if (!gotpattern) + usage("No pattern"); + if (nfile == 0) + grep(stdin, 0); + else { + fflag = fflag ^ (nfile > 0); + for (i=1; i < argc; ++i) { + if (p = argv[i]) { + if ((f=fopen(p, "r")) == NULL) + cant(p); + else { + grep(f, p); + fclose(f); + } + } + } + } +} +