int displayMessageAndGetString(char *msg, char **last, char *p, int p_size) { int ret = TRUE; displayOneLineMessage(msg); ungetstr(*last); echo(); getnstr(p, p_size - 1); noecho(); if (*p == '\0') { if (*last) strcpy(p, *last); else ret = FALSE; } else { FREE(*last); *last = strdup(p); } return ret; }
int yylex(void) { static enum { Initial = 0, Strings, Comments, Properties, Proplist, Bitmap, Bitlist } state = Initial; static int skiplines = 0; for (;;) { register char *tok; register Keyword *x; switch (state) { default: if (! (tok = getnextoken())) { /* EOF, clean up and terminate */ return 0; } TRACE((2,"state 0: looking at %s\n", tok)); curtok = tok; if (iskwpat(tok)) { if (x = lookup(tok)) { switch (x->tokid) { case COMMENT: state = Comments; TRACE((2,"state 0: tokid %d >> state %d\n", x->tokid, state)); break; case STARTPROPERTIES: state = Properties; TRACE((2,"state 0: return tokid %d >> state %d\n", x->tokid, state)); return x->tokid; case STARTFONT: case STARTCHAR: case FONT: state = Strings; TRACE((2,"state 0: return tokid %d >> state %d\n", x->tokid, state)); return x->tokid; case BITMAP: state = Bitmap; TRACE((2,"state 0: return tokid %d >> state %d\n", x->tokid, state)); return x->tokid; default: TRACE((2,"state 0: return tokid %d >> state %d\n", x->tokid, state)); return x->tokid; } } else { yylval.s = estrdup(tok); TRACE((2,"state 0: return STRING\n")); return STRING; } } else if (isintpat(tok)) { yylval.i = atoi(tok); TRACE((2, "state 0: return INTEGER\n")); return INTEGER; } else if (*tok == '\n') { TRACE((2, "state 0: return '\\n'\n")); return '\n'; } else { fprint(2, "yylex: unkown token %s\n", tok); exits("lexical error"); } break; case Strings: state = 0; if (! (tok = readupto('\n'))) { fprint(2, "yylex: unexpected EOF\n"); exits("lexical error"); } TRACE((2, "state Strings: looking at %s\n", tok)); curtok = tok; yylval.s = estrdup(tok); return STRING; case Bitmap: if (! (tok = getnextoken())) { fprint(2, "yylex: unexpected EOF in Bitmap\n"); return 0; } curtok = tok; TRACE((2, "state Bitmap: looking at %s\n", (*tok == '\n')?"\\n":tok)); if (*tok == '\n') { state = Bitlist; TRACE((2, "state Bitmap: return \\n >> state %d\n", state)); return '\n'; } else { state = 0; yylval.s = estrdup(tok); TRACE((2, "state Bitmap: return STRING >> state %d\n", state)); return STRING; /* let yyparse take care of it */ } case Bitlist: if (! (tok = getnextoken())) { fprint(2, "yylex: unexpected EOF in BITMAP\n"); return 0; } TRACE((2, "state Bitlist: looking at %s\n", (*tok == '\n')?"\\n":tok)); curtok = tok; if (ishexpat(tok)) { yylval.s = estrdup(tok); TRACE((2, "state Bitlist: return HEXBUFF >> state %d\n", state)); return HEXBUFF; } else if (*tok == '\n') { TRACE((2, "state Bitlist: return \\n >> state %d\n", state)); return '\n'; } ungetstr(tok); state = 0; break; case Comments: if (! (tok = readupto('\n'))) { fprint(2, "yylex: unexpected EOF in COMMENT\n"); return 0; } USED(tok); if (peek() == '\n') getch(); state = 0; TRACE((2, "state Comments: token \"%s\" >> state %d\n", tok, state)); break; case Properties: if (! (tok = getnextoken())) { fprint(2, "yylex: unexpected EOF in PROPERTIES\n"); return 0; } TRACE((2, "state Properties: looking at \"%s\"\n", tok)); if (isintpat(tok)) { skiplines = yylval.i = atoi(tok); TRACE((2, "state Properties: return INTEGER >> state %d\n", state)); return INTEGER; } else if (*tok == '\n') { state = Proplist; TRACE((2, "state Properties: return \\n >> state %d\n", state)); return '\n'; } /* probably an error, let yyparse sort it out */ fprint(2, "yylex: unknown token %s in PROPERTIES\n", tok); exits("lexical error"); case Proplist: /* property list keywords can go here */ if (skiplines) { if (! (tok = readupto('\n'))) { fprint(2, "yylex: unexpected EOF in PROPERTIES"); return 0; } yylval.s = estrdup(tok); if (peek() == '\n') getch(); skiplines--; TRACE((2, "state Proplist: return BUFFER >> state %d\n", state)); return BUFFER; } state = 0; TRACE((2, "state Proplist: >> state %d\n", state)); break; } } return 0; /* not reached */ }
/** * We should populate token for some types (const modifiers, etc) * * This function got really complex because of using gettoken() from original * KnR code (which do different things on different tokens). It would be best * to rewrite gettoken() or use correct another one, which * ungetch()/ungetstr() non-DATATYPE/NAME tokens * */ int gettokentype(void) { char c; int modifier = 0; int type = 0; /** check last token correctness (allow modifiers) */ if (check_type(token) == 1) { return tokentype = NAME; } else if (check_type(token) == -1) { modifier = 1; /** save last token value */ strcpy(token_tmp, token); } else if (check_type(token) == 0) { type = 1; /** continue to process more complex type */ strcpy(token_tmp, token); } token[0]='\0'; while ((c = gettoken()) != EOF) { /** check new token first */ if (tokentype == NAME && check_type(token) == 0) { /** concatenate */ if (type == 1 || modifier == 1) { strcat(token_tmp, " "); } else { token_tmp[0] = '\0'; } strcat(token_tmp, token); /** check complex token second */ if (check_type(token_tmp) == 0) { // continue type = 1; } else { /** ungetch last token */ ungetstr(token); token_tmp[strlen(token_tmp)-strlen(token)]='\0'; // strcpy(token, token_tmp); goto out; } } else if (tokentype == NAME && check_type(token) != 0) { ungetstr(token); goto out; /* if (modifier == 1 && type == 0) { // return tokentype = ERR; goto out; } else if (type == 1) { ungetstr(token); // strcpy(token, token_tmp); goto out; } else return tokentype=NAME; */ } else if (tokentype == PARENS || tokentype == BRACKETS) { ungetstr(token); goto out; } else if (tokentype == '(') { ungetch(tokentype); goto out; } else if (tokentype == ERR) { /** ungetch()/ungetstr() depends on ERR case... */ ungetstr(token); goto out; } else { ungetch(c); goto out; } } out: if (type == 1) { strcpy(token, token_tmp); return tokentype = DATATYPE; } else return tokentype = ERR; }
/** parse direct declaration */ void dirdcl(void) { int type; char c; /** assume here: tokentype != ERR before we call gettoken() */ /** "( dcl )" */ if (tokentype == '(') { dcl(); if (tokentype != ')') { printf("error: missing ')'\n"); tokentype = ERR; return; } } /** variable name */ else if (tokentype == NAME) { if (check_type(token) == 1) strcpy(name, token); else { printf("error: name should not be the same as type or type modifier.\n"); tokentype = ERR; return; } } else { printf("error: expected name or ( dcl )\n"); tokentype = ERR; return; } while ((type = gettoken()) == PARENS || type == BRACKETS) { if (type == PARENS) strcat(out, " function returning"); else { strcat(out, " array"); strcat(out, token); strcat(out, " of"); } } if (type == '(' && gettoken() == NAME && check_type(token)==0) { token_tmp[0] = '\0'; strcat(token_tmp, " function ("); strcat(token_tmp, token); while((c = gettoken()) == ',' && gettoken() == NAME && check_type(token)==0) { strcat(token_tmp, ","); strcat(token_tmp, token); } if (c == ')') { strcat(token_tmp, ") returning"); } else { printf("error: something wrong with function`s argument types\n"); ungetstr(token_tmp); return; } strcat(out, token_tmp); /** we should call this to go to next token */ gettoken(); } /** 3. one more check for ERR after gettoken() */ else if (type == ERR) { printf("error[3]: some error symbol inserted\n"); return; } }