/* *Decidewhether"foo(..."isafunctiondefinitionordeclaration. * *Atcall,wearelookingatthe'('.Lookaheadtofindthefirst *'{',';'or','thatisnotwithinparenthesesorcomments;then *it'sadefinitionifwefound'{',otherwiseadeclaration. *NotethatthisruleisfooledbyK&R-styleparameterdeclarations, *buttellingthedifferencebetweenthoseandfunctionattributes *seemslikemoretroublethanit'sworth.Thiscodecouldalsobe *fooledbymismatchedparensorapparentcommentstartswithinstring *literals,butthatseemsunlikelyinthecontextit'susedin.
*/ staticint
is_func_definition(char *tp)
{ int paren_depth = 0; int in_comment = false; int in_slash_comment = false; int lastc = 0;
/* We may need to look past the end of the current buffer. */
lookahead_reset(); for (;;) { int c;
/* Fetch next character. */ if (tp < buf_end)
c = *tp++; else {
c = lookahead(); if (c == EOF) break;
} /* Handle comments. */ if (in_comment) { if (lastc == '*' && c == '/')
in_comment = false;
} elseif (lastc == '/' && c == '*' && !in_slash_comment)
in_comment = true; elseif (in_slash_comment) { if (c == '\n')
in_slash_comment = false;
} elseif (lastc == '/' && c == '/')
in_slash_comment = true; /* Count nested parens properly. */ elseif (c == '(')
paren_depth++; elseif (c == ')') {
paren_depth--; /* *Ifwefindunbalancedparens,wemusthavestartedinsidea *declaration.
*/ if (paren_depth < 0) returnfalse;
} elseif (paren_depth == 0) { /* We are outside any parentheses or comments. */ if (c == '{') returntrue; elseif (c == ';' || c == ',') returnfalse;
}
lastc = c;
} /* Hit EOF --- for lack of anything better, assume "not a definition". */ returnfalse;
}
int
lexi(struct parser_state *state)
{ int unary_delim; /* this is set to 1 if the current token
* forces a following operator to be unary */ int code; /* internal code to be returned */ char qchar; /* the delimiter character for a string */
e_token = s_token; /* point to start of place to save token */
unary_delim = false;
state->col_1 = state->last_nl; /* tell world that this token started *incolumn1iffthelastthing
* scanned was a newline */
state->last_nl = false;
while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
state->col_1 = false; /* leading blanks imply token is not in column
* 1 */ if (++buf_ptr >= buf_end)
fill_buffer();
}
while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ if (++buf_ptr >= buf_end)
fill_buffer();
}
state->keyword = 0; if (state->last_token == structure && !state->p_l_follow) { /* if last token was 'struct' and we're not *inparentheses,thenthistoken
* should be treated as a declaration */
state->last_u_d = true; return (decl);
} /* *Operatorafteridentifierisbinaryunlesslasttokenwas'struct'
*/
state->last_u_d = (state->last_token == structure);
p = bsearch(s_token,
specials, sizeof(specials) / sizeof(specials[0]), sizeof(specials[0]),
strcmp_type); if (p == NULL) { /* not a special keyword... */ char *u;
/* ... so maybe a type_t or a typedef */ if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
strcmp(u, "_t") == 0) || (typename_top >= 0 &&
bsearch(s_token, typenames, typename_top + 1, sizeof(typenames[0]), strcmp_type))) {
state->keyword = 4; /* a type name */
state->last_u_d = true; goto found_typename;
}
} else { /* we have a keyword */
state->keyword = p->rwcode;
state->last_u_d = true; switch (p->rwcode) { case7: /* it is a switch */ return (swstmt); case8: /* a case or default */ return (casestmt);
case3: /* a "struct" */ /* FALLTHROUGH */ case4: /* one of the declaration keywords */
found_typename: if (state->p_l_follow) { /* inside parens: cast, param list, offsetof or sizeof */
state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
} if (state->last_token == period || state->last_token == unary_op) {
state->keyword = 0; break;
} if (p != NULL && p->rwcode == 3) return (structure); if (state->p_l_follow) break; return (decl);
case5: /* if, while, for */ return (sp_paren);
case6: /* do, else */ return (sp_nparen);
case10: /* storage class specifier */ return (storage);
case11: /* typedef */ return (type_def);
default: /* all others are treated like any other
* identifier */ return (ident);
} /* end of switch */
} /* end of if (found_it) */ if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
state->in_parameter_declaration == 0 && state->block_init == 0) { if (is_func_definition(buf_ptr)) {
strncpy(state->procname, token, sizeof state->procname - 1); if (state->in_decl)
state->in_parameter_declaration = 1; return (funcname);
}
} /* *Thefollowinghackattemptstoguesswhetherornotthecurrent *tokenisinfactadeclarationkeyword--onethathasbeen *typedefd
*/ elseif (!state->p_l_follow && !state->block_init &&
!state->in_stmt &&
((*buf_ptr == '*' && buf_ptr[1] != '=') ||
isalpha((unsignedchar)*buf_ptr)) &&
(state->last_token == semicolon || state->last_token == lbrace ||
state->last_token == rbrace)) {
state->keyword = 4; /* a type name */
state->last_u_d = true; return decl;
} if (state->last_token == decl) /* if this is a declared variable,
* then following sign is unary */
state->last_u_d = true; /* will make "int a -1" work */ return (ident); /* the ident is not in the list */
} /* end of processing for alphanum character */
/* Scan a non-alphanumeric token */
CHECK_SIZE_TOKEN(3); /* things like "<<=" */
*e_token++ = *buf_ptr; /* if it is only a one-character token, it is
* moved here */
*e_token = '\0'; if (++buf_ptr >= buf_end)
fill_buffer();
switch (*token) { case'\n':
unary_delim = state->last_u_d;
state->last_nl = true; /* remember that we just had a newline */
code = (had_eof ? 0 : newline);
case'\'': /* start of quoted character */ case'"': /* start of string */
qchar = *token; do { /* copy the string */ while (1) { /* move one character or [/<char>]<char> */ if (*buf_ptr == '\n') {
diag2(1, "Unterminated literal"); goto stop_lit;
}
CHECK_SIZE_TOKEN(2);
*e_token = *buf_ptr++; if (buf_ptr >= buf_end)
fill_buffer(); if (*e_token == BACKSLASH) { /* if escape, copy extra char */ if (*buf_ptr == '\n') /* check for escaped newline */
++line_no;
*++e_token = *buf_ptr++;
++e_token; /* we must increment this again because we
* copied two chars */ if (buf_ptr >= buf_end)
fill_buffer();
} else break; /* we copied one character */
} /* end of while (1) */
} while (*e_token++ != qchar);
stop_lit:
code = ident; break;
case ('('): case ('['):
unary_delim = true;
code = lparen; break;
case014: /* a form feed */
unary_delim = state->last_u_d;
state->last_nl = true; /* remember this so we can set 'state->col_1'
* right */
code = form_feed; break;
case (','):
unary_delim = true;
code = comma; break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.