/****************************************************************************************/ /* */ /* "expand_const.c" */ /* */ /* This file contains the main routine and the scanner for the constant expander. Its */ /* only task is to replace the constant expressions in file "jrevdct.h" by the their */ /* results. */ /* */ /* First all lines are scanned. If an "/*" occurs they are ignored (very risked) If */ /* they contain a "#COMPUTE" marker the characters between "#COMPUTE" and the next "#" */ /* are grabed and passed to a parser (made by "yacc"). The parser expects a constant */ /* expression and computes it. After that it shifts the result by "CONST_BITS" to the */ /* left. To obtain this value the main routine searches the definition of this variable */ /* in the Java source text. */ /* Furthermore this file contains the "yylex()" routine expected by "yacc". */ /* */ /*--------------------------------------------------------------------------------------*/ /* */ /* This program is free software; you can redistribute it and/or modify it under the */ /* terms of the GNU General Public License as published by the Free Software */ /* Foundation; either version 2 of the License, or (at your option) any later version. */ /* */ /* This program 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 GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License along with this */ /* program; (See "LICENSE.GPL"). If not, write to the Free Software Foundation, Inc., */ /* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* */ /*--------------------------------------------------------------------------------------*/ /* */ /* If the program runs as Java applet it isn't "interactive" in the sense of the GNU */ /* General Public License. So paragraph 2c doesn't apply. */ /* */ /****************************************************************************************/ #include /* "strstr", "strchr" */ #include #include /* "cos" */ #include "y.tab.h" /* made by "yacc" */ double res; /* the result supplied by the parser */ static FILE *infile; int line_nr = 0; int pos; /* character position; used in "yyerror" */ char equation[1024]; /* one equation to be parsed */ static int const_bits = -111; /* The vaule of "CONST_BITS"; "-111.111" means "undefined" */ static char *lex_ptr; /* actual position of the scanner */ #define LENGTH 1024 /* length of some fields */ main(argc, argv) int argc; char *argv[]; { char buffer[LENGTH], *cptr1, *cptr2; char part1[LENGTH], part2[LENGTH]; int t; if (argc != 2) { fprintf(stderr, "Usage %s \n", argv[0]); exit(-1); } if ((infile = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "can't open %s\n", argv[1]); exit(10); } while (fgets(buffer, LENGTH - 1, infile) != NULL) { line_nr++; if (strstr(buffer, "/*")) continue; /* a comment (unclean implementation) */ if (const_bits == -111 && (cptr1 = strstr(buffer, "CONST_BITS_JA")) != NULL) { cptr1 += strlen("CONST_BITS_JA"); if (sscanf(cptr1+1, " %d", &const_bits) != 1) { fprintf(stderr, "line %d: error in CONST_BITS\n", line_nr); exit(10); } } if ((cptr1 = strstr(buffer, "#COMPUTE")) != NULL) { if (const_bits == -111) { fprintf(stderr, "line %d: \"#COMPUTE\" without \"CONST_BITS\"\n", line_nr); exit(10); } if ((cptr2 = strchr(cptr1 + 1, '#')) == NULL) { /* find end of constant expression */ fprintf(stderr, "line %s: \"#COMPUTE\" without \"#\"\n", line_nr); exit(10); } strncpy(part1, buffer, cptr1 - buffer); /* copy all before "#COMPUTE" */ part1[cptr1 - buffer] = '\0'; strncpy(part2, cptr2 + 1, strlen(cptr2)); /* copy all after "#" */ part2[strlen(cptr2)] = '\0'; cptr1+=strlen("#COMPUTE"); /* position after "#COMPUTE" */ strncpy(equation, cptr1, cptr2 - cptr1); /* copy all between "#COMPUTE" and */ equation[cptr2 - cptr1] = '\0'; /* before "#" --> the euqation */ fputs(part1, stdout); /* pass through all before "#COMPUTE" */ lex_ptr = equation; /* initialize scanner */ yyparse(); /* call parser --> compute "res" */ fprintf(stdout, "%d", (int) (res * (1 << const_bits) + 0.5)); /* shift/print result */ fputs(part2, stdout); /* pass through all after "#" */ } else { fputs(buffer, stdout); /* do nothing; pass through */ } } } /* The function "yylex" is a simple scanner usable together with "yacc" */ int yylex() { char buf[1024]; /* in-buffer */ int i; /* a counter */ /* ignore white spaces */ while((*lex_ptr == ' ' || *lex_ptr == '\t') && *lex_ptr != '\0') lex_ptr++; pos = lex_ptr - equation; /* compute "pos" for error message */ if (*lex_ptr == '\0') return 0; /* EOF */ if (*lex_ptr == '.' || (*lex_ptr >= '0' && *lex_ptr <= '9')) { /* a number ??? */ sscanf(lex_ptr, "%lf", &yylval.dwert); /* scan it! */ for(; *lex_ptr == '.' || (*lex_ptr >= '0' && *lex_ptr <= '9'); lex_ptr++); /* new position */ pos = lex_ptr - equation; return(NUMBER); } else if (*lex_ptr >= 'A' && *lex_ptr <= 'Z' || *lex_ptr >= 'a' && *lex_ptr <= 'z') { /* a name ??? */ i = 0; do { /* copy it ! */ buf[i++] = *lex_ptr++; } while (*lex_ptr >= 'A' && *lex_ptr <= 'Z' || *lex_ptr >= 'a' && *lex_ptr <= 'z'); buf[i] = '\0'; pos = lex_ptr - equation; if (strcmp(buf, "pi") == 0) { /* is it "pi" ? */ yylval.dwert = M_PI; return(NUMBER); } yylval.str = (char *) strdup(buf); /* it's apparently a function name */ return(NAME); } else { /* it is a sign */ pos = lex_ptr - equation; return(*lex_ptr++); /* return the ascii number */ } }