static int scandec(char *str, int *ind, int *chread, int (*func)(char)) /*;scandec*/ { /* Scandec: scan for an integer followed possibly by a decimal point and * another integer, with digits determined by satisfying func. 1 is returned * if an integer is found, 2 if a there was a decimal point, 0 if no digits * found. * ind is the index into the string str, * chread is the index into the input string line * func is a func indicating valid characters for numbers being scanned */ int stat; stat = scanidorint(str, ind, chread, func, 1); if (line[*chread] == '.') { if (line[*chread + 1] != '.') { if (!stat) { lexerr(lineno, colno + *chread, colno + *chread, "Missing digit before decimal point"); str[(*ind)++] = '0'; } str[(*ind)++] = '.'; (*chread)++; if (!scanidorint(str, ind, chread, func, 1)) { lexerr(lineno, colno + *chread - 1, colno + *chread - 1, "Missing digit after decimal point"); str[(*ind)++] = '0'; } return(2); } } return(stat); }
/* * La procedure "fscanf_Point3f" lit en ascii un point flottant 3D. * Entree : * pp Point flottant 3D a lire. */ void fscanf_Point3f (Point3f *pp) { static const char *err_tbl[] = { "float expected (coordinate ", " of point)" }; int t; /* Lecture de la premiere coordonnee du point. */ if ((t = lex ()) != T_FLOAT && t != T_INT) lexerr ("start",err_tbl[0], "X", err_tbl[1], NULL); pp->x = (t == T_INT) ? (float) myint : myfloat; /* Lecture de la seconde coordonnee du point. */ if ((t= lex ()) != T_FLOAT && t != T_INT) lexerr ("start",err_tbl[0], "Y", err_tbl[1], NULL); pp->y = (t == T_INT) ? (float) myint : myfloat; /* Lecture de la troisieme coordonnee du point. */ if ((t= lex ()) != T_FLOAT && t != T_INT) lexerr ("start",err_tbl[0], "Z", err_tbl[1], NULL); pp->z = (t == T_INT) ? (float) myint : myfloat; }
/* * La procedure "fscanf_Point_list" lit en ascii une liste de points 3D. * Entree : * lp Liste de points a lire. */ void fscanf_Point3f_list (Point3f_list *lp) { static char proc_name[] = "fscanf_Point3f_list"; static char *err_tbl[] = { "float expected (coordinate ", " of point)" }; Point3f *pp; /* point courant */ Point3f *pend; /* borne de "pp" */ /* Lecture du nombre de points de la liste. */ if (lex () != T_INT) lexerr ("start", "integer expected (number of points 3D)", NULL); lp->nbr = (Index) myint; /* FC printf("nbr %d\n",lp->nbr); */ /* Allocation dynamique la liste de points. */ if (lp->nbr == 0) lp->ptr = NULL; else if ((lp->ptr = (Point3f *) malloc (lp->nbr * sizeof (Point3f))) == NULL) { perror (proc_name); exit (1); } /* Lecture des points de la liste un a un. */ pp = lp->ptr; pend = pp + lp->nbr; for (; pp < pend; pp++) { int t; if ((t = lex ()) != T_FLOAT && t != T_INT) lexerr ("start", err_tbl[0], "X", err_tbl[1], NULL); /* FC printf("X %d %f\n",myint, myfloat); */ pp->x = (t == T_INT) ? (float) myint : myfloat; if ((t = lex ()) != T_FLOAT && t != T_INT) lexerr ("start", err_tbl[0], "Y", err_tbl[1], NULL); /* FC printf("Y %d %f\n",myint, myfloat); */ pp->y = (t == T_INT) ? (float) myint : myfloat; if ((t = lex ()) != T_FLOAT && t != T_INT) lexerr ("start", err_tbl[0], "Z", err_tbl[1], NULL); /* FC printf("Z %d %f\n",myint, myfloat); */ pp->z = (t == T_INT) ? (float) myint : myfloat; } }
/* * La procedure "parser" fait l'analyse syntaxique du fichier source. * Entree/Sortie : * bsp Scene surfacique polygonale a lire. */ void parser (Bound_scene *bsp) { int token; while ((token = lex ()) != T_EOF) switch (token) { case '$' : switch (lex ()) { case T_IDENT : /* saute la commande inconnue */ skip_cmd (/* stderr */); unlex (); break; case T_EXIT : return; break; case T_BOUND : if (bsp->bound.nbr == BOUND_NBR) { fprintf (stderr, "mire: too much bound\n"); return; } fscanf_Bound ( &(bsp->bound.ptr[bsp->bound.nbr++])); break; #ifdef used case T_REMOVE : fscanf_Remove (get_remove ()); break; case T_VIEW : fscanf_View_parameters (get_view_parameters ()); set_projection (void); break; #endif /* used */ default : lexerr ("start", "keyword expected", NULL); break; } break; default : lexerr ("start", "symbol '$' expected", NULL); break; } }
static int scanidorint(char *str, int *ind, int *chread, int (*func)(char), int ignore_break) /*;scanidorint*/ { /* Scanidorint: scan for an integer or id, with allowed characters * determined by satisfying function func. 1 returned if found, 0 if not. */ /* ind is the index into the string str, * chread is the index into the input string line * func is a function to be called to determine what chars are to * be included in the integer or identifier */ int hadnum = 0; while (1) { if (line[*chread] == '_') { lexerr(lineno, colno + *chread, colno + *chread, "Break character misplaced"); (*chread)++; continue; } if (!(*func)(line[*chread])) { if (hadnum) lexerr(lineno, colno + *chread - 1, colno + *chread - 1, "Break character misplaced"); break; } str[(*ind)++] = line[(*chread)++]; hadnum = 1; while ((*func)(line[*chread])) str[(*ind)++] = line[(*chread)++]; if (line[*chread] != '_') break; (*chread)++; if (!ignore_break) str[(*ind)++] = '_'; } return(hadnum); }
static void checkbased(char *str, int *ind)/*;checkbased*/ { /* Checkbased: check the validity of a based literal */ int base, err = 0; char *pos; sscanf(str, "%d", &base); pos = strchr(str, '#'); if (base < 2 || base > 16) { lexerr(lineno, colno, colno + pos - str - 1, "Base not in range 2..16"); err = 1; } else while (*++pos != '#') { if (islower(*pos)) *pos = toupper(*pos); if (isdigit(*pos) && *pos - '0' >= base || isalpha(*pos) && *pos - 'A' >= base - 10) { lexerr(lineno, colno + pos - str, colno + pos - str, "Invalid based-number digit"); err = 1; break; } } if (err) { if (strchr(str, '.') == (char *)0) { *ind = 1; *str = '0'; } else { *ind = 3; strcpy(str, "0.0"); } } }
/* * La procedure "fscanf_Remove" lit en ascii les parametres d'elimination * des faces. * Entree : * bp Parametres a lire. */ void fscanf_Remove (Byte *bp) { switch (lex ()) { case T_NONE : *bp = IS_INSIDE; break; case T_ABOVE : *bp |= IS_ABOVE; break; case T_BACK : *bp |= IS_BACK; break; case T_BELOW : *bp |= IS_BELOW; break; case T_FRONT : *bp |= IS_FRONT; break; case T_LEFT : *bp |= IS_LEFT; break; case T_RIGHT : *bp |= IS_RIGHT; break; default : lexerr ("start", "remove: keyword \"none|above|back|below|front|left|right\" expected"); break; } }
char *cpp_catname(char *n1,char *n2) { static char cpp_name[IDMAX + 1]; #ifdef DEBUG assert(n1 && n2); #endif if (strlen(n1) + strlen(n2) >= sizeof(cpp_name)) { #if SCPP lexerr(EM_ident2big); // identifier is too long #else assert(0); #endif cpp_name[0] = 0; } else strcat(strcpy(cpp_name,n1),n2); return cpp_name; }
static void scanexp(char *str, int *ind, int *chread) /*;scanexp*/ { /* Scanexp: scan for an (optional) exponent * ind is the index into the string str, * chread is the index into the input string line */ int oldchread; if (line[*chread] != 'E' && line[*chread] != 'e') return; oldchread = *chread; str[(*ind)++] = 'E'; *chread += 1; if (line[*chread] == '+' || line[*chread] == '-') str[(*ind)++] = line[(*chread)++]; if (!scanidorint(str, ind, chread, isdecimal, 1)) { lexerr(lineno, colno + oldchread, colno + *chread - 1, "Incomplete exponent"); str[(*ind)++] = '0'; } }
static int getline() /*;getline*/ { int ch, ind = 0; if (feof(adafile)) return(EOF); src_index = (src_index + 1) % NUM_LINES; line = data = source_buf[src_index]; lineno++; colno = 1; for (;;) { ch = getc(adafile); if (ch==EOF) break; if (ch <= 13 && ch >= 10) break; if (ind == MAXLINE) { char msg[80]; sprintf(msg, "Line %d exceeds maximum length, truncated to %d characters", lineno, MAXLINE); lexerr(lineno, 1, 1, msg); while ((ch = getc(adafile)) != EOF && !(ch<=13 && ch>=10)); break; } else { data[ind++] = ch; } } data[ind] = '\0'; if (ch == EOF && !ind) return(EOF); #ifdef DEBUG if (trcopt) fprintf(errfile, "%5d: %s\n", lineno, data); if (termopt) printf( "%5d: %s\n", lineno, data); #endif return(0); }
/* * La procedure "fscanf_Bound" lit en ascii une surface. * Entree : * bp Surface a lire. */ void fscanf_Bound (Bound *bp) { /* Lecture du type polygonale de la surface. */ skip_keyword (T_TYPE, "bound: keyword \"type\" expected"); if (lex () != T_INT) lexerr ("start","bound_type: boolean expected (0=FALSE|~0=TRUE)", NULL); bp->is_polygonal = (myint ? 1 : 0); /* Lecture de la liste de points de la surface. */ skip_keyword (T_POINT_LIST, "bound: keyword \"point_list\" expected"); pusherr ("bound_point_list: "); fscanf_Point3f_list (&bp->point); poperr (); /* Lecture de la liste de faces de la surface. */ skip_keyword (T_FACE_LIST, "bound: keyword \"face_list\" expected"); pusherr ("bound_face_list: "); fscanf_Face_list (&bp->face); poperr (); }
MachineResult *get_next_token(ParserData *parser_data, int options) { // remember where we were last by saving source file pointer static FILE *s; // save current line static char l[MAX_LINE_LENGTH_1]; static char *f; static int i = 0; // options for things like NOP static int o = 0; static MachineResult *r; if (o & TOKEN_OPTION_NOP && r != NULL) { o = options; return r; } // grab another line if (s != parser_data->source || f - l > MAX_LINE_LENGTH || *f == 0) { s = parser_data->source; char *line = get_next_line(parser_data->source); strcpy(l, line); f = l; i++; // output line to listing file if (parser_data->listing != NULL) fprintf (parser_data->listing, "%-8d%s\n", i, line); } MachineResult result = machine_omega(f, parser_data->reserved_words, parser_data->symbol_table); // do not increment line counter for eof if (result.token->type == TOKEN_EOF) i--; result.line_no = i; MachineResult *resultPtr = (MachineResult *)malloc(sizeof(MachineResult)); memcpy(resultPtr, &result, sizeof(MachineResult)); // advance our internal pointer f = result.f; if (resultPtr->token->type == TOKEN_WHITESPACE) return get_next_token(parser_data, options); // write token to tokens file if (parser_data->tokens != NULL) { fprintf (parser_data->tokens, "%-10d%-20s%-20s%-6d(%s)\n", i, resultPtr->lexeme, token_type_to_str(resultPtr->token->type), resultPtr->token->attribute, attribute_to_str(resultPtr->token->attribute)); } // handle lexical errors if (resultPtr->token->type == TOKEN_LEXERR) { // output errors to listing file if (!(options & TOKEN_OPTION_SQUASH_ERRS)) lexerr(resultPtr, parser_data); // do not return lexerr tokens return get_next_token(parser_data, options); } // check for a nop if (options & TOKEN_OPTION_NOP) r = resultPtr; o = options; return resultPtr; }
/* * La procedure "fscanf_View_parameters" lit en ascii les parametres * de visualisation. * Entree : * vp Parametres de visualisation a lire. */ void fscanf_View_parameters (View_parameters *vp) { /* Lecture du type de projection lors de la prise de vue. */ skip_keyword (T_TYPE, "view: keyword \"type\" expected"); switch (lex ()) { case T_PARALLEL : vp->type = PARALLEL; break; case T_PERSPECTIVE : vp->type = PERSPECTIVE; break; default : lexerr ("start", "view_type: keyword \"parallel|perspective\" expected"); break; } /* Lecture du centre de projection (oeil) de la prise de vue. */ skip_keyword (T_COP, "view: keyword \"cop\" expected"); pusherr ("view_cop: "); fscanf_Point3f (&vp->cop); poperr (); /* Lecture du point de reference (cible) a la prise de vue. */ skip_keyword (T_VRP, "view: keyword \"vrp\" expected"); pusherr ("view_vrp: "); fscanf_Point3f (&vp->vrp); poperr (); /* Lecture de la direction normale au plan de projection. */ skip_keyword (T_VPN, "view: keyword \"vpn\" expected"); pusherr ("view_vpn: "); fscanf_Vector (&vp->vpn); poperr (); /* Lecture de la direction indiquant le haut de la projection. */ skip_keyword (T_VUP, "view: keyword \"vup\" expected"); pusherr ("view_vup: "); fscanf_Vector (&vp->vup); poperr (); /* Lecture de la fenetre de projection de la prise de vue. */ skip_keyword (T_WINDOW, "view: keyword \"window\" expected"); pusherr ("view_window_umin: "); fscanf_float (&vp->vwd.umin); popuperr ("view_window_umax: "); fscanf_float (&vp->vwd.umax); popuperr ("view_window_vmin: "); fscanf_float (&vp->vwd.vmin); popuperr ("view_window_vmax: "); fscanf_float (&vp->vwd.vmax); poperr (); /* Lecture des profondeurs de decoupage avant et arriere. */ skip_keyword (T_DEPTH, "view: keyword \"depth\" expected"); pusherr ("view_depth_front: "); fscanf_float (&vp->depth.front); popuperr ("view_depth_back: "); fscanf_float (&vp->depth.back); poperr (); }
/* * La procedure "fscanf_Face_list" lit en ascii une liste de faces. * Entree : * lp Liste de faces a lire. */ void fscanf_Face_list (Face_list *lp) { static char proc_name[] = "fscanf_Face_list"; Face *fp; /* face courante */ Face *fend; /* borne de "fp" */ /* Lecture du nombre de faces de la liste */ if (lex () != T_INT) lexerr ("start","integer expected (number of faces)", NULL); lp->nbr = (Index) myint; /* Allocation dynamique de la liste de faces. */ if (lp->nbr == 0) lp->ptr = NULL; else if ((lp->ptr = (Face *) malloc (lp->nbr * sizeof (Face))) == NULL) { perror (proc_name); exit (1); } /* Lecture des faces de la liste une a une. */ fp = lp->ptr; fend = fp + lp->nbr; for (; fp < fend; fp++) { Vertex_list *lp = &fp->vertex; Index *vp; /* sommet courant */ Index *vend; /* borne de "vp" */ /* Lecture du type polygonale de la face. */ if (lex () != T_INT) lexerr ("start", "boolean expected (0=FALSE|~0=TRUE)", NULL); fp->is_polygonal = (myint ? 1 : 0); /* Lecture du nombre de sommets de la face. */ if (lex () != T_INT) lexerr ("start", "integer expected (number of vertices)", NULL); lp->nbr = (Index) myint; /* Allocation dynamique du polygone de la face. */ if (lp->nbr <= DEFAULT_VSIZE) lp->ptr = lp->tbl; else if ((lp->ptr = (Index *) malloc (lp->nbr * sizeof (Index))) == NULL) { perror (proc_name); exit (1); } /* Lecture des sommets de la face un a un. */ vp = lp->ptr; vend = vp + lp->nbr; for (; vp < vend; *vp++ = (Index) myint) if (lex () != T_INT) lexerr ("start", "integer expected (index of points 3D)", NULL); } }
struct prsstack *gettok() /*;gettok*/ { /* Gettok: Scan and return the next token in the adafile, adding the */ /* token to namelist. */ static int nextcanbeprime = 0; /* The next token can be a prime */ static int canbeprime; /* The current token can be a prime */ struct prsstack *tok; /* Token to be returned */ while (1) { while (1) { while (*line == ' ' || *line == '\t') { colno += (*line == '\t') ? (8 - ((colno - 1) % 8)) : 1; line++; } if (!*line || *line == '-' && line[1] == '-') break; canbeprime = nextcanbeprime; nextcanbeprime = 0; if (isalpha(*line)) { /* Scan identifiers */ char id[MAXLINE + 1]; int idind = 0, chread = 0; int tokind, toksym; scanidorint(id, &idind, &chread, isletterordigit, 0); if (id[idind - 1] == '_') idind--; id[idind] = '\0'; convtoupper(id); tokind = namemap(id, idind); toksym = MIN(tokind, ID_SYM); tok = newtoken(toksym, tokind, lineno, colno); nextcanbeprime = toksym == ID_SYM || toksym == RANGE_SYM || toksym == ALL_SYM; colno += chread; line += chread; return(tok); } else if (isdigit(*line) || *line == '.' && isdigit(line[1])) { /* Scan numeric literals */ char num[MAXLINE + 3]; int ind = 0, chread = 0, result; char ch; /* ind is the index into the num string */ /* chread is the index into the line input string */ result = scandec(num, &ind, &chread, isdecimal); ch = line[chread]; if (result == 1 && (ch == '#' || ch == ':')) { /* Scan for the rest of a based literal */ num[ind++] = '#'; chread++; if (!scandec(num, &ind, &chread, ishex)) { lexerr(lineno, colno + chread - 1, colno + chread - 1, "Incomplete based number"); num[ind++] = '0'; } num[ind++] = '#'; if (line[chread] != ch) { if (line[chread] == '#' + ':' - ch) { lexerr(lineno, colno + chread, colno + chread, "Expect #'s or :'s in based number to match"); chread++; } else { char msg[50]; sprintf(msg, "Expect '%c' after last digit", ch); lexerr(lineno, colno + chread - 1, colno + chread - 1, msg); } } else chread++; checkbased(num, &ind); } scanexp(num, &ind, &chread); if (isalpha(line[chread])) lexerr(lineno, colno, colno + chread - 1, "Number should be separated from adjacent identifier"); num[ind] = '\0'; tok = newtoken(NUMBER_SYM, namemap(num, ind), lineno, colno); colno += chread; line += chread; return(tok); } else if (*line == '\'') { int err = 0; if (line[1] != '\0' && line[2] == '\'' && (!canbeprime || line[1] != '(')) { /* Scan a character literal */ char str[4]; int len = 3; strcpy(str, "' '"); if (!isprint(line[1]) && line[1] != ' ') { char msg[80]; sprintf(msg, "Invalid character %s in character literal replaced by space", nonprintingmsg[line[1]]); lexerr(lineno, colno + 1, colno + 1, msg); len = (line[1] == '\t') ? (10 - (colno % 8)) : 2; } else str[1] = line[1]; tok = newtoken(CHAR_SYM, namemap(str, 3), lineno, colno); colno += len; line += 3; return(tok); } else if (!canbeprime) { /* Possibly a single quote delimited string */ int ind; if (line[1] == '\'') ind = 1; else { ind = 3; while (line[ind]) { if (line[ind] == '\'') { if (line[ind + 1] && line[ind + 2] == '\'') { ind = -1; break; } else { if (line[ind + 1] != '\'') break; ind++; } } ind++; } } if (ind > -1 && line[ind]) { err = 1; lexerr(lineno, colno, colno + ind, "Expect double quotes to delimit a character string"); do if (line[ind] == '\'') line[ind] = '"'; while (ind--); } } if (!err) { /* A prime */ int ind = namemap("'", 1); tok = newtoken(ind, ind, lineno, colno); colno++; line++; return(tok); } } else if (*line == '"' || *line == '%') { /* Scan a string literal */ int col = colno; int oldindex = 0, newindex = -1; char bracket = *line; char nxtchr ; char tmpstr[MAXLINE + 1]; int save_col; /* these are maintained to restore line */ char *save_line; /* in case of missing string bracket */ int save_newindex; if ( (strchr(line+1, bracket)) == 0 ) { char bracket_str[2]; *bracket_str = bracket; *(bracket_str + 1) = '\0'; tok = newtoken(ERROR_SYM, namemap(bracket_str, 1), lineno, colno); line++; colno++; return(tok); } while (1) { save_line = line + oldindex + 1; save_col = col + 1; save_newindex = newindex + 1; do { col++; oldindex++; newindex++; nxtchr = line[oldindex] ; tmpstr[newindex] = nxtchr ; } /* test separately for bracket for use of % as delimiter */ while (nxtchr != bracket && IS_STRING_CHAR(nxtchr)); if (line[oldindex] == bracket) { if (line[oldindex + 1] == bracket) { tmpstr[newindex] = bracket ; oldindex++; col++; } else { tmpstr[newindex] = '\0'; tok = newtoken(STRING_SYM, namemap(tmpstr, newindex), lineno, colno+1); colno = col + 1; line += oldindex + 1; return(tok); } } else if (line[oldindex] == '"') { oldindex++; lexerr(lineno, col, col, "% delimited string contains \", being ignored"); } else if (line[oldindex] == '\0') { lexerr(lineno, colno, colno, "Missing string bracket"); /* restore values of line and colno to values prior to * last set of string characters */ line = save_line; colno = save_col; /* insert a closing string bracket */ tmpstr[save_newindex] = bracket; tmpstr[save_newindex + 1] = '\0'; tok = newtoken(STRING_SYM, namemap(tmpstr, save_newindex + 1), lineno, colno); return(tok); } /* else if (isprint(line[oldindex]) || line[oldindex] == ' ') tmpstr[newindex] = line[oldindex]; */ else { char msg[80]; sprintf(msg, "Invalid character %s in string deleted", nonprintingmsg[line[oldindex++]]); lexerr(lineno, col, col, msg); col += (line[oldindex] == '\t') ? 7 - ((col-1)%8) : -1; } } } else if (ISDELIMITER(*line)) /* Scan a delimiter */ { int len = 1, ind; char str[3]; switch (*line) { case '=' : if (line[1] == '>') len = 2; break; case '*' : if (line[1] == '*') len = 2; break; case ':' : case '/' : if (line[1] == '=') len = 2; break; case '>' : if (line[1] == '=' || line[1] == '>') len = 2; break; case '<' : if (line[1] == '=' || line[1] == '<' || line[1] == '>') len = 2; break; case '.' : if (line[1] == '.') len = 2; break; case '!' : *line = '|'; break; case '[' : /* Change to a "(" */ lexerr(lineno, colno, colno, "Bad character \"[\", replaced by \"(\".") ; line[0] = '(' ; break ; case ']' : /* Change to a ")" */ /* Note that this case falls through to the next one */ lexerr(lineno, colno, colno, "Bad character \"]\", replaced by \")\".") ; line[0] = ')' ; case ')' : nextcanbeprime = 1; break; } strncpy(str, line, len); str[len] = '\0'; ind = namemap(str, len); tok = newtoken(ind, ind, lineno, colno); colno += len; line += len; return(tok); } else if (*line == '_') { /* An error- an underline _ */ lexerr(lineno, colno, colno, "Break character misplaced"); colno++; line++; } else { /* An error- an unknown character */ char msg[80]; char ch[2]; *ch = *line; ch[1] = '\0'; sprintf(msg, "Bad character in file ignored: %s", (isprint(*line)) ? ch : nonprintingmsg[*line]); lexerr(lineno, colno, colno, msg); if (isprint(*line)) colno++; line++; } } if (getline() == EOF) return(newtoken(EOFT_SYM, EOFT_SYM, lineno, colno)); } }