// // aegis - project change supervisor // Copyright (C) 2001, 2002, 2004-2008, 2012, 2014 Peter Miller // // 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 3 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. If not, see . // #include #include #include #include #include #include #include #include #include #include #include // needs to be after static input::pointer ip; static int error_count; static bool start_of_line; static nstring_accumulator getch_line_buffer; static size_t getch_line_pos; void sccs_lex_open(const nstring &fn) { ip = input_file::open_text(fn); start_of_line = true; } void sccs_lex_close(void) { if (error_count) quit(1); ip.reset(); } static void sccs_lex_error(sub_context_ty *scp, const nstring &s) { assert(scp); change::pointer cp; nstring msg = scp->substitute(cp, s); // re-use substitution context scp->var_set_string("MeSsaGe", msg); scp->var_set_string("File_Name", ip->name()); scp->error_intl(i18n("$filename: $message")); if (++error_count >= 20) { // re-use substitution context scp->var_set_string("File_Name", ip->name()); scp->fatal_intl(i18n("$filename: too many errors")); } } void format_sccs_gram_error(const char *s) { sub_context_ty sc; sccs_lex_error(&sc, s); } static int getch(void) { if (getch_line_pos >= getch_line_buffer.size()) { getch_line_buffer.clear(); getch_line_pos = 0; for (;;) { int c = ip->getch(); if (c < 0) { if (getch_line_buffer.empty()) return -1; break; } getch_line_buffer.push_back(c); if (c == '\n') break; } } start_of_line = !getch_line_pos; int c = getch_line_buffer[getch_line_pos++]; return c; } static void ungetch(int c) { if (c < 0) return; assert(getch_line_pos > 0); --getch_line_pos; assert(c == getch_line_buffer[getch_line_pos]); } #define yylval format_sccs_gram_lval int format_sccs_gram_lex(void) { static nstring_accumulator buffer; for (;;) { int c = getch(); if (c == EOF) return 0; if (start_of_line) { if (c != '\1') { buffer.clear(); for (;;) { if (c == '\n') break; buffer.push_back(c); c = getch(); if (c == EOF) break; } yylval.lv_string = new nstring(buffer.mkstr()); return TEXTLINE; } // // we are looking for a keyword // c = getch(); switch (c) { case 'c': buffer.clear(); c = getch(); if (c != ' ') buffer.push_back(c); for (;;) { c = getch(); if (c == EOF) break; if (c == '\n') { ungetch(c); break; } buffer.push_back(c); } yylval.lv_string = new nstring(buffer.mkstr()); return COMMENT; case 'd': return DELTA_BEGIN; case 'D': return D_KEYWORD; case 'e': return DELTA_END; case 'E': return E_KEYWORD; case 'f': return FLAGS; case 'g': return MR_IGNORE; case 'h': return HEADER; case 'i': return MR_INCLUDE; case 'I': return I_KEYWORD; case 'm': return MR; case 's': return SUMMARY; case 't': return TITLE_BEGIN; case 'T': return TITLE_END; case 'u': return USERS_BEGIN; case 'U': return USERS_END; case 'x': return MR_EXCLUDE; } return JUNK; } // // Throw away white space. // if (isspace((unsigned char)c)) continue; // // "normal" processing // buffer.clear(); for (;;) { buffer.push_back(c); c = getch(); if (c == EOF) break; if (isspace((unsigned char)c)) { ungetch(c); break; } } yylval.lv_string = new nstring(buffer.mkstr()); return STRING; } } // vim: set ts=8 sw=4 et :